diff --git a/CI/Windows.bat b/CI/Windows.bat index 278ac033..78722eed 100644 --- a/CI/Windows.bat +++ b/CI/Windows.bat @@ -38,13 +38,13 @@ IF "%BUILD_PLATFORM%" == "VS2013" ( set GENERATOR=Visual Studio 12%ARCH_VS% set VS_PATH="C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\devenv.com" IF "%ARCHITECTURE%" == "x64" ( - set QT_INSTALL_PATH=E:\Qt\Qt5.3.1-vs2013-%STRING_ARCH%\5.3\msvc2013_64_opengl - set QT_BASE_CONFIG=-DQT5_INSTALL_PATH=E:\Qt\Qt5.3.1-vs2013-%STRING_ARCH%\5.3\msvc2013_64_opengl + set QT_INSTALL_PATH=E:\Qt\Qt5.7.0\5.7\msvc2013_64 + set QT_BASE_CONFIG=-DQT5_INSTALL_PATH=E:\Qt\Qt5.7.0\5.7\msvc2013_64 ) IF "%ARCHITECTURE%" == "x32" ( - set QT_INSTALL_PATH=E:\Qt\Qt5.3.1-vs2013-%STRING_ARCH%\5.3\msvc2013_opengl - set QT_BASE_CONFIG=-DQT5_INSTALL_PATH=E:\Qt\Qt5.3.1-vs2013-%STRING_ARCH%\5.3\msvc2013_opengl + set QT_INSTALL_PATH=E:\Qt\Qt5.7.0\5.7\msvc2013 + set QT_BASE_CONFIG=-DQT5_INSTALL_PATH=E:\Qt\Qt5.7.0\5.7\msvc2013 ) ) @@ -98,6 +98,7 @@ IF "%APPS%" == "ON" ( ECHO "=============================================================" ECHO "=============================================================" ECHO "Building with :" +whoami ECHO "ARCHITECTURE : %ARCHITECTURE%" ECHO "BUILD_PLATFORM : %BUILD_PLATFORM%" ECHO "GTESTVERSION : %GTESTVERSION%" diff --git a/CMakeLists.txt b/CMakeLists.txt index dda2f40a..1c3690e6 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required (VERSION 2.6) +cmake_minimum_required(VERSION 3.1.0 FATAL_ERROR) # Set and enforce C++-11 flags diff --git a/Doc/changelog.docu b/Doc/changelog.docu index 1abf1df0..c38bd385 100644 --- a/Doc/changelog.docu +++ b/Doc/changelog.docu @@ -9,9 +9,25 @@ 7.2 (?/?/?) +Core + + IO + +Tools + + +Build System + diff --git a/Doc/tools.docu b/Doc/tools.docu index 5da44bcd..7ae8c68a 100644 --- a/Doc/tools.docu +++ b/Doc/tools.docu @@ -6,6 +6,7 @@ \li \subpage subdivider_docu \li \subpage vdpm_docu \li \subpage smoother_docu +\li \subpage smarttagger_docu \li Miscellaneous OpenMesh::StripifierT diff --git a/cmake/ACGOutput.cmake b/cmake/ACGOutput.cmake index de488cf8..d06e298c 100644 --- a/cmake/ACGOutput.cmake +++ b/cmake/ACGOutput.cmake @@ -30,11 +30,13 @@ function (acg_print_configure_header _id _name) acg_color_message ("${_escape}[40;37m* Package : ${_escape}[32m${_project} ${_escape}[37m *${_escape}[0m") acg_color_message ("${_escape}[40;37m* Version : ${_escape}[32m${_version} ${_escape}[37m *${_escape}[0m") - # Just artistic. remove 2 spaces for release to make it look nicer ;-) - if (${CMAKE_BUILD_TYPE} MATCHES "Debug") - acg_color_message ("${_escape}[40;37m* Type : ${_escape}[32m${CMAKE_BUILD_TYPE} ${_escape}[37m *${_escape}[0m") - else() - acg_color_message ("${_escape}[40;37m* Type : ${_escape}[32m${CMAKE_BUILD_TYPE} ${_escape}[37m *${_escape}[0m") + if ( NOT WIN32 ) + # Just artistic. remove 2 spaces for release to make it look nicer ;-) + if (${CMAKE_BUILD_TYPE} MATCHES "Debug") + acg_color_message ("${_escape}[40;37m* Type : ${_escape}[32m${CMAKE_BUILD_TYPE} ${_escape}[37m *${_escape}[0m") + else() + acg_color_message ("${_escape}[40;37m* Type : ${_escape}[32m${CMAKE_BUILD_TYPE} ${_escape}[37m *${_escape}[0m") + endif() endif() acg_color_message ("${_escape}[40;37m************************************************************${_escape}[0m") diff --git a/src/OpenMesh/Core/IO/IOInstances.hh b/src/OpenMesh/Core/IO/IOInstances.hh index 744b9a81..96793a67 100644 --- a/src/OpenMesh/Core/IO/IOInstances.hh +++ b/src/OpenMesh/Core/IO/IOInstances.hh @@ -82,6 +82,7 @@ #include #include #include +#include //=== NAMESPACES ============================================================== @@ -104,6 +105,7 @@ static BaseWriter* OFFWriterInstance = &OFFWriter(); static BaseWriter* STLWriterInstance = &STLWriter(); static BaseWriter* OMWriterInstance = &OMWriter(); static BaseWriter* PLYWriterInstance = &PLYWriter(); +static BaseWriter* VTKWriterInstance = &VTKWriter(); //============================================================================= diff --git a/src/OpenMesh/Core/IO/reader/PLYReader.cc b/src/OpenMesh/Core/IO/reader/PLYReader.cc index 87078882..37e605a7 100644 --- a/src/OpenMesh/Core/IO/reader/PLYReader.cc +++ b/src/OpenMesh/Core/IO/reader/PLYReader.cc @@ -1201,185 +1201,187 @@ bool _PLYReader_::can_u_read(std::istream& _is) const { _is >> keyword; while (keyword != "end_header") { - if (keyword == "comment") { - std::getline(_is, line); - } else if (keyword == "element") { - _is >> elementName; - _is >> elementCount; + if (keyword == "comment") { + std::getline(_is, line); + } else if (keyword == "element") { + _is >> elementName; + _is >> elementCount; - ElementInfo element; - element.name_ = elementName; - element.count_ = elementCount; + ElementInfo element; + element.name_ = elementName; + element.count_ = elementCount; - if (elementName == "vertex") { - vertexCount_ = elementCount; - element.element_ = VERTEX; - } else if (elementName == "face") { - faceCount_ = elementCount; - element.element_ = FACE; - } else { - omerr() << "PLY header unsupported element type: " << elementName << std::endl; - element.element_ = UNKNOWN; - } + if (elementName == "vertex") { + vertexCount_ = elementCount; + element.element_ = VERTEX; + } else if (elementName == "face") { + faceCount_ = elementCount; + element.element_ = FACE; + } else { + omerr() << "PLY header unsupported element type: " << elementName << std::endl; + element.element_ = UNKNOWN; + } - elements_.push_back(element); - } else if (keyword == "property") { - std::string tmp1; - std::string tmp2; + elements_.push_back(element); + } else if (keyword == "property") { + std::string tmp1; + std::string tmp2; - // Read first keyword, as it might be a list - _is >> tmp1; + // Read first keyword, as it might be a list + _is >> tmp1; - if (tmp1 == "list") { - _is >> listIndexType; - _is >> listEntryType; - _is >> propertyName; + if (tmp1 == "list") { + _is >> listIndexType; + _is >> listEntryType; + _is >> propertyName; - ValueType indexType = Unsupported; - ValueType entryType = Unsupported; + ValueType indexType = Unsupported; + ValueType entryType = Unsupported; - if (listIndexType == "uint8") { - indexType = ValueTypeUINT8; - } else if (listIndexType == "uchar") { - indexType = ValueTypeUCHAR; - } else if (listIndexType == "int") { - indexType = ValueTypeINT; - } else { - omerr() << "Unsupported Index type for property list: " << listIndexType << std::endl; - continue; - } + if (listIndexType == "uint8") { + indexType = ValueTypeUINT8; + } else if (listIndexType == "uint16") { + indexType = ValueTypeUINT16; + } else if (listIndexType == "uchar") { + indexType = ValueTypeUCHAR; + } else if (listIndexType == "int") { + indexType = ValueTypeINT; + } else { + omerr() << "Unsupported Index type for property list: " << listIndexType << std::endl; + return false; + } - entryType = get_property_type(listEntryType, listEntryType); + entryType = get_property_type(listEntryType, listEntryType); - if (entryType == Unsupported) { - omerr() << "Unsupported Entry type for property list: " << listEntryType << std::endl; - } + if (entryType == Unsupported) { + omerr() << "Unsupported Entry type for property list: " << listEntryType << std::endl; + } - PropertyInfo property(CUSTOM_PROP, entryType, propertyName); - property.listIndexType = indexType; + PropertyInfo property(CUSTOM_PROP, entryType, propertyName); + property.listIndexType = indexType; - if (elementName == "face") - { - // special case for vertex indices - if (propertyName == "vertex_index" || propertyName == "vertex_indices") - { - property.property = VERTEX_INDICES; - - if (!elements_.back().properties_.empty()) - { - omerr() << "Custom face Properties defined, before 'vertex_indices' property was defined. They will be skipped" << std::endl; - elements_.back().properties_.clear(); - } - } else { - options_ += Options::Custom; - } + if (elementName == "face") + { + // special case for vertex indices + if (propertyName == "vertex_index" || propertyName == "vertex_indices") + { + property.property = VERTEX_INDICES; - } - else - omerr() << "property " << propertyName << " belongs to unsupported element " << elementName << std::endl; - - elements_.back().properties_.push_back(property); - - } else { - // as this is not a list property, read second value of property - _is >> tmp2; - - - // Extract name and type of property - // As the order seems to be different in some files, autodetect it. - ValueType valueType = get_property_type(tmp1, tmp2); - propertyName = get_property_name(tmp1, tmp2); - - PropertyInfo entry; - - //special treatment for some vertex properties. - if (elementName == "vertex") { - if (propertyName == "x") { - entry = PropertyInfo(XCOORD, valueType); - vertexDimension_++; - } else if (propertyName == "y") { - entry = PropertyInfo(YCOORD, valueType); - vertexDimension_++; - } else if (propertyName == "z") { - entry = PropertyInfo(ZCOORD, valueType); - vertexDimension_++; - } else if (propertyName == "nx") { - entry = PropertyInfo(XNORM, valueType); - options_ += Options::VertexNormal; - } else if (propertyName == "ny") { - entry = PropertyInfo(YNORM, valueType); - options_ += Options::VertexNormal; - } else if (propertyName == "nz") { - entry = PropertyInfo(ZNORM, valueType); - options_ += Options::VertexNormal; - } else if (propertyName == "u" || propertyName == "s") { - entry = PropertyInfo(TEXX, valueType); - options_ += Options::VertexTexCoord; - } else if (propertyName == "v" || propertyName == "t") { - entry = PropertyInfo(TEXY, valueType); - options_ += Options::VertexTexCoord; - } else if (propertyName == "red") { - entry = PropertyInfo(COLORRED, valueType); - options_ += Options::VertexColor; - if (valueType == ValueTypeFLOAT || valueType == ValueTypeFLOAT32) - options_ += Options::ColorFloat; - } else if (propertyName == "green") { - entry = PropertyInfo(COLORGREEN, valueType); - options_ += Options::VertexColor; - if (valueType == ValueTypeFLOAT || valueType == ValueTypeFLOAT32) - options_ += Options::ColorFloat; - } else if (propertyName == "blue") { - entry = PropertyInfo(COLORBLUE, valueType); - options_ += Options::VertexColor; - if (valueType == ValueTypeFLOAT || valueType == ValueTypeFLOAT32) - options_ += Options::ColorFloat; - } else if (propertyName == "diffuse_red") { - entry = PropertyInfo(COLORRED, valueType); - options_ += Options::VertexColor; - if (valueType == ValueTypeFLOAT || valueType == ValueTypeFLOAT32) - options_ += Options::ColorFloat; - } else if (propertyName == "diffuse_green") { - entry = PropertyInfo(COLORGREEN, valueType); - options_ += Options::VertexColor; - if (valueType == ValueTypeFLOAT || valueType == ValueTypeFLOAT32) - options_ += Options::ColorFloat; - } else if (propertyName == "diffuse_blue") { - entry = PropertyInfo(COLORBLUE, valueType); - options_ += Options::VertexColor; - if (valueType == ValueTypeFLOAT || valueType == ValueTypeFLOAT32) - options_ += Options::ColorFloat; - } else if (propertyName == "alpha") { - entry = PropertyInfo(COLORALPHA, valueType); - options_ += Options::VertexColor; - options_ += Options::ColorAlpha; - if (valueType == ValueTypeFLOAT || valueType == ValueTypeFLOAT32) - options_ += Options::ColorFloat; - } - } - - //not a special property, load as custom - if (entry.value == Unsupported){ - Property prop = CUSTOM_PROP; - options_ += Options::Custom; - entry = PropertyInfo(prop, valueType, propertyName); - } - - if (entry.property != UNSUPPORTED) + if (!elements_.back().properties_.empty()) { - elements_.back().properties_.push_back(entry); + omerr() << "Custom face Properties defined, before 'vertex_indices' property was defined. They will be skipped" << std::endl; + elements_.back().properties_.clear(); } + } else { + options_ += Options::Custom; } + } + else + omerr() << "property " << propertyName << " belongs to unsupported element " << elementName << std::endl; + + elements_.back().properties_.push_back(property); + } else { - omlog() << "Unsupported keyword : " << keyword << std::endl; + // as this is not a list property, read second value of property + _is >> tmp2; + + + // Extract name and type of property + // As the order seems to be different in some files, autodetect it. + ValueType valueType = get_property_type(tmp1, tmp2); + propertyName = get_property_name(tmp1, tmp2); + + PropertyInfo entry; + + //special treatment for some vertex properties. + if (elementName == "vertex") { + if (propertyName == "x") { + entry = PropertyInfo(XCOORD, valueType); + vertexDimension_++; + } else if (propertyName == "y") { + entry = PropertyInfo(YCOORD, valueType); + vertexDimension_++; + } else if (propertyName == "z") { + entry = PropertyInfo(ZCOORD, valueType); + vertexDimension_++; + } else if (propertyName == "nx") { + entry = PropertyInfo(XNORM, valueType); + options_ += Options::VertexNormal; + } else if (propertyName == "ny") { + entry = PropertyInfo(YNORM, valueType); + options_ += Options::VertexNormal; + } else if (propertyName == "nz") { + entry = PropertyInfo(ZNORM, valueType); + options_ += Options::VertexNormal; + } else if (propertyName == "u" || propertyName == "s") { + entry = PropertyInfo(TEXX, valueType); + options_ += Options::VertexTexCoord; + } else if (propertyName == "v" || propertyName == "t") { + entry = PropertyInfo(TEXY, valueType); + options_ += Options::VertexTexCoord; + } else if (propertyName == "red") { + entry = PropertyInfo(COLORRED, valueType); + options_ += Options::VertexColor; + if (valueType == ValueTypeFLOAT || valueType == ValueTypeFLOAT32) + options_ += Options::ColorFloat; + } else if (propertyName == "green") { + entry = PropertyInfo(COLORGREEN, valueType); + options_ += Options::VertexColor; + if (valueType == ValueTypeFLOAT || valueType == ValueTypeFLOAT32) + options_ += Options::ColorFloat; + } else if (propertyName == "blue") { + entry = PropertyInfo(COLORBLUE, valueType); + options_ += Options::VertexColor; + if (valueType == ValueTypeFLOAT || valueType == ValueTypeFLOAT32) + options_ += Options::ColorFloat; + } else if (propertyName == "diffuse_red") { + entry = PropertyInfo(COLORRED, valueType); + options_ += Options::VertexColor; + if (valueType == ValueTypeFLOAT || valueType == ValueTypeFLOAT32) + options_ += Options::ColorFloat; + } else if (propertyName == "diffuse_green") { + entry = PropertyInfo(COLORGREEN, valueType); + options_ += Options::VertexColor; + if (valueType == ValueTypeFLOAT || valueType == ValueTypeFLOAT32) + options_ += Options::ColorFloat; + } else if (propertyName == "diffuse_blue") { + entry = PropertyInfo(COLORBLUE, valueType); + options_ += Options::VertexColor; + if (valueType == ValueTypeFLOAT || valueType == ValueTypeFLOAT32) + options_ += Options::ColorFloat; + } else if (propertyName == "alpha") { + entry = PropertyInfo(COLORALPHA, valueType); + options_ += Options::VertexColor; + options_ += Options::ColorAlpha; + if (valueType == ValueTypeFLOAT || valueType == ValueTypeFLOAT32) + options_ += Options::ColorFloat; + } + } + + //not a special property, load as custom + if (entry.value == Unsupported){ + Property prop = CUSTOM_PROP; + options_ += Options::Custom; + entry = PropertyInfo(prop, valueType, propertyName); + } + + if (entry.property != UNSUPPORTED) + { + elements_.back().properties_.push_back(entry); + } } - streamPos = _is.tellg(); - _is >> keyword; - if (_is.bad()) { - omerr() << "Error while reading PLY file header" << std::endl; - return false; - } + } else { + omlog() << "Unsupported keyword : " << keyword << std::endl; + } + + streamPos = _is.tellg(); + _is >> keyword; + if (_is.bad()) { + omerr() << "Error while reading PLY file header" << std::endl; + return false; + } } // As the binary data is directy after the end_header keyword diff --git a/src/OpenMesh/Core/Mesh/CirculatorsT.hh b/src/OpenMesh/Core/Mesh/CirculatorsT.hh index 06560599..f3a0c6e2 100644 --- a/src/OpenMesh/Core/Mesh/CirculatorsT.hh +++ b/src/OpenMesh/Core/Mesh/CirculatorsT.hh @@ -470,7 +470,7 @@ class GenericCirculatorT_DEPRECATED : protected GenericCirculatorBaseT { To be save, you can use the CW/CCW circulator definitions, which behave\ the same as the original ones, without the previously mentioned issues." - DEPRECATED( DECREMENT_DEPRECATED_WARNINGS_TEXT ) + OM_DEPRECATED( DECREMENT_DEPRECATED_WARNINGS_TEXT ) #endif // NO_DECREMENT_DEPRECATED_WARNINGS GenericCirculatorT_DEPRECATED& operator--() { assert(this->mesh_); @@ -488,7 +488,7 @@ class GenericCirculatorT_DEPRECATED : protected GenericCirculatorBaseT { /// Post-decrement #ifndef NO_DECREMENT_DEPRECATED_WARNINGS - DEPRECATED( DECREMENT_DEPRECATED_WARNINGS_TEXT ) + OM_DEPRECATED( DECREMENT_DEPRECATED_WARNINGS_TEXT ) #undef DECREMENT_DEPRECATED_WARNINGS_TEXT #endif //NO_DECREMENT_DEPRECATED_WARNINGS GenericCirculatorT_DEPRECATED operator--(int) { @@ -542,7 +542,7 @@ class GenericCirculatorT_DEPRECATED : protected GenericCirculatorBaseT { return GenericCirculator_ValueHandleFns::is_valid(this->heh_,this->start_, this->lap_counter_); } - DEPRECATED("current_halfedge_handle() is an implementation detail and should not be accessed from outside the iterator class.") + OM_DEPRECATED("current_halfedge_handle() is an implementation detail and should not be accessed from outside the iterator class.") /** * \deprecated * current_halfedge_handle() is an implementation detail and should not @@ -552,7 +552,7 @@ class GenericCirculatorT_DEPRECATED : protected GenericCirculatorBaseT { return this->heh_; } - DEPRECATED("Do not use this error prone implicit cast. Compare to end-iterator or use is_valid(), instead.") + OM_DEPRECATED("Do not use this error prone implicit cast. Compare to end-iterator or use is_valid(), instead.") /** * \deprecated * Do not use this error prone implicit cast. Compare to the @@ -567,7 +567,7 @@ class GenericCirculatorT_DEPRECATED : protected GenericCirculatorBaseT { * \deprecated * This function clutters your code. Use dereferencing operators -> and * instead. */ - DEPRECATED("This function clutters your code. Use dereferencing operators -> and * instead.") + OM_DEPRECATED("This function clutters your code. Use dereferencing operators -> and * instead.") value_type handle() const { return **this; } @@ -578,7 +578,7 @@ class GenericCirculatorT_DEPRECATED : protected GenericCirculatorBaseT { * Implicit casts of iterators are unsafe. Use dereferencing operators * -> and * instead. */ - DEPRECATED("Implicit casts of iterators are unsafe. Use dereferencing operators -> and * instead.") + OM_DEPRECATED("Implicit casts of iterators are unsafe. Use dereferencing operators -> and * instead.") operator value_type() const { return **this; } diff --git a/src/OpenMesh/Core/Mesh/IteratorsT.hh b/src/OpenMesh/Core/Mesh/IteratorsT.hh index 6d2c92bc..284004c9 100644 --- a/src/OpenMesh/Core/Mesh/IteratorsT.hh +++ b/src/OpenMesh/Core/Mesh/IteratorsT.hh @@ -126,7 +126,7 @@ class GenericIteratorT { * \deprecated * This function clutters your code. Use dereferencing operators -> and * instead. */ - DEPRECATED("This function clutters your code. Use dereferencing operators -> and * instead.") + OM_DEPRECATED("This function clutters your code. Use dereferencing operators -> and * instead.") value_handle handle() const { return hnd_; } @@ -137,7 +137,7 @@ class GenericIteratorT { * Implicit casts of iterators are unsafe. Use dereferencing operators * -> and * instead. */ - DEPRECATED("Implicit casts of iterators are unsafe. Use dereferencing operators -> and * instead.") + OM_DEPRECATED("Implicit casts of iterators are unsafe. Use dereferencing operators -> and * instead.") operator value_handle() const { return hnd_; } diff --git a/src/OpenMesh/Core/Mesh/TriConnectivity.hh b/src/OpenMesh/Core/Mesh/TriConnectivity.hh index 197420dd..baab7c60 100644 --- a/src/OpenMesh/Core/Mesh/TriConnectivity.hh +++ b/src/OpenMesh/Core/Mesh/TriConnectivity.hh @@ -162,27 +162,63 @@ public: * * \note The properties of the new edges, halfedges, and faces will be undefined! * - * @param _eh Edge handle that should be splitted + * @param _eh Edge handle that should be split * @param _vh Vertex handle that will be inserted at the edge */ void split(EdgeHandle _eh, VertexHandle _vh); + /** \brief Edge split (= 2-to-4 split) + * + * + * The function will introduce two new faces ( non-boundary case) or + * one additional face (if edge is boundary) + * + * \note The properties of the new edges, halfedges, and faces will be undefined! + * + * \note This is an override to prevent a direct call to PolyConnectivity split_edge, + * which would introduce a singular vertex with valence 2 which is not allowed + * on TriMeshes + * + * @param _eh Edge handle that should be split + * @param _vh Vertex handle that will be inserted at the edge + */ + inline void split_edge(EdgeHandle _eh, VertexHandle _vh) { TriConnectivity::split(_eh, _vh); } + /** \brief Edge split (= 2-to-4 split) * * The function will introduce two new faces ( non-boundary case) or * one additional face (if edge is boundary) * - * \note The properties of the new edges will be adjusted to the properties of the original edge - * \note The properties of the new faces and halfedges will be undefined + * \note The properties of the new edges and faces will be adjusted to the + * properties of the original edge and face + * \note The properties of the new halfedges will be undefined * - * @param _eh Edge handle that should be splitted + * @param _eh Edge handle that should be split * @param _vh Vertex handle that will be inserted at the edge */ void split_copy(EdgeHandle _eh, VertexHandle _vh); + /** \brief Edge split (= 2-to-4 split) + * + * The function will introduce two new faces ( non-boundary case) or + * one additional face (if edge is boundary) + * + * \note The properties of the new edges and faces will be adjusted to the + * properties of the original edge and face + * \note The properties of the new halfedges will be undefined + * + * \note This is an override to prevent a direct call to PolyConnectivity split_edge_copy, + * which would introduce a singular vertex with valence 2 which is not allowed + * on TriMeshes + * + * @param _eh Edge handle that should be split + * @param _vh Vertex handle that will be inserted at the edge + */ + inline void split_edge_copy(EdgeHandle _eh, VertexHandle _vh) { TriConnectivity::split_copy(_eh, _vh); } + /** \brief Face split (= 1-to-3) split, calls corresponding PolyMeshT function). * - * @param _fh Face handle that should be splitted + * @param _fh Face handle that should be split * @param _vh Vertex handle that will be inserted at the face */ inline void split(FaceHandle _fh, VertexHandle _vh) @@ -190,7 +226,7 @@ public: /** \brief Face split (= 1-to-3) split, calls corresponding PolyMeshT function). * - * @param _fh Face handle that should be splitted + * @param _fh Face handle that should be split * @param _vh Vertex handle that will be inserted at the face */ inline void split_copy(FaceHandle _fh, VertexHandle _vh) diff --git a/src/OpenMesh/Core/System/config.h b/src/OpenMesh/Core/System/config.h index 9d7520c1..bb5a7893 100644 --- a/src/OpenMesh/Core/System/config.h +++ b/src/OpenMesh/Core/System/config.h @@ -83,17 +83,17 @@ #endif #if defined(_MSC_VER) -# define DEPRECATED(msg) __declspec(deprecated(msg)) +# define OM_DEPRECATED(msg) __declspec(deprecated(msg)) #elif defined(__GNUC__) # if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) >= 40500 /* Test for GCC >= 4.5.0 */ -# define DEPRECATED(msg) __attribute__ ((deprecated(msg))) +# define OM_DEPRECATED(msg) __attribute__ ((deprecated(msg))) # else -# define DEPRECATED(msg) __attribute__ ((deprecated)) +# define OM_DEPRECATED(msg) __attribute__ ((deprecated)) # endif #elif defined(__clang__) -# define DEPRECATED(msg) __attribute__ ((deprecated(msg))) +# define OM_DEPRECATED(msg) __attribute__ ((deprecated(msg))) #else -# define DEPRECATED(msg) +# define OM_DEPRECATED(msg) #endif typedef unsigned int uint; diff --git a/src/OpenMesh/Tools/SmartTagger/SmartTaggerT.cc b/src/OpenMesh/Tools/SmartTagger/SmartTaggerT.cc new file mode 100644 index 00000000..b75e4cef --- /dev/null +++ b/src/OpenMesh/Tools/SmartTagger/SmartTaggerT.cc @@ -0,0 +1,212 @@ +/* ========================================================================= * + * * + * OpenMesh * + * Copyright (c) 2001-2015, RWTH-Aachen University * + * Department of Computer Graphics and Multimedia * + * All rights reserved. * + * www.openmesh.org * + * * + *---------------------------------------------------------------------------* + * This file is part of OpenMesh. * + *---------------------------------------------------------------------------* + * * + * Redistribution and use in source and binary forms, with or without * + * modification, are permitted provided that the following conditions * + * are met: * + * * + * 1. Redistributions of source code must retain the above copyright notice, * + * this list of conditions and the following disclaimer. * + * * + * 2. Redistributions in binary form must reproduce the above copyright * + * notice, this list of conditions and the following disclaimer in the * + * documentation and/or other materials provided with the distribution. * + * * + * 3. Neither the name of the copyright holder nor the names of its * + * contributors may be used to endorse or promote products derived from * + * this software without specific prior written permission. * + * * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER * + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * + * * + * ========================================================================= */ + +/*===========================================================================*\ + * * + * $Revision$ * + * $Date$ * + * * +\*===========================================================================*/ + +#define OPENMESH_SMARTTAGGERT_C + +//== INCLUDES ================================================================= + +#include "SmartTaggerT.hh" + +#include +#include + +//== NAMESPACES =============================================================== + +namespace OpenMesh { + +//== IMPLEMENTATION ========================================================== + +template +SmartTaggerT:: +SmartTaggerT(Mesh& _mesh, unsigned int _tag_range) + : mesh_(_mesh), + current_base_(0), + tag_range_(_tag_range) +{ + // add new property + mesh_.add_property(ep_tag_); + + // reset all tags once + all_tags_to_zero(); +} + + +//----------------------------------------------------------------------------- + + +template +SmartTaggerT:: +~SmartTaggerT() +{ + mesh_.remove_property(ep_tag_); +} + + +//----------------------------------------------------------------------------- + + +template +void +SmartTaggerT:: +untag_all() +{ + unsigned int max_uint = std::numeric_limits::max(); + + if( current_base_ < max_uint - 2*tag_range_) + current_base_ += tag_range_; + else + { + //overflow -> reset all tags +#ifdef STV_DEBUG_CHECKS + std::cerr << "Tagging Overflow occured...\n"; +#endif + current_base_ = 0; + all_tags_to_zero(); + } +} + + +//----------------------------------------------------------------------------- + + +template +void +SmartTaggerT:: +untag_all( const unsigned int _new_tag_range) +{ + set_tag_range(_new_tag_range); +} + + +//----------------------------------------------------------------------------- + +template +void +SmartTaggerT:: +set_tag ( const EHandle _eh, unsigned int _tag) +{ +#ifdef STV_DEBUG_CHECKS + if( _tag > tag_range_) + std::cerr << "ERROR in set_tag tag range!!!\n"; +#endif + + mesh_.property(ep_tag_, _eh) = current_base_ + _tag; +} + + +//----------------------------------------------------------------------------- + + +template +unsigned int +SmartTaggerT:: +get_tag ( const EHandle _eh) const +{ + unsigned int t = mesh_.property(ep_tag_, _eh); + +#ifdef STV_DEBUG_CHECKS + if( t > current_base_ + tag_range_) + std::cerr << "ERROR in get_tag tag range!!!\n"; +#endif + + if( t<= current_base_) return 0; + else return t-current_base_; +} + + +//----------------------------------------------------------------------------- + + +template +bool +SmartTaggerT:: +is_tagged( const EHandle _eh) const +{ + return bool(get_tag(_eh)); +} + + +//----------------------------------------------------------------------------- + + +template +void +SmartTaggerT:: +set_tag_range( const unsigned int _tag_range) +{ + if( _tag_range <= tag_range_) + { + untag_all(); + tag_range_ = _tag_range; + } + else + { + tag_range_ = _tag_range; + untag_all(); + } +} + + +//----------------------------------------------------------------------------- + + +template +void +SmartTaggerT:: +all_tags_to_zero() +{ + // iterate over property vector + for(unsigned int i=0; i +#include + + +//== DEFINES ================================================================== + +#define STV_DEBUG_CHECKS + +//== NAMESPACES =============================================================== + +namespace OpenMesh { + +//== FORWARD DECLARATIONS ===================================================== + +// Smarttagging for vertices +template< class Mesh> class SmartTaggerVT; +// Smarttagging for edges +template< class Mesh> class SmartTaggerET; +// Smarttagging for faces +template< class Mesh> class SmartTaggerFT; +// Smarttagging for halfedges +template< class Mesh> class SmartTaggerHT; + + +//== CLASS DEFINITION ========================================================= + + +/** \page smarttagger_docu Smart Tagger + +The smart tagger can be used to tag vertices/halfedges/edges/faces on the mesh. It provides +an O(1) reset function to untag all primitives at once. + +Usage: + +\code +SmartTaggerVT< MeshType > tagger(mesh); + +// Reset tagged flag on all vertices +tagger.untag_all(); + +// Check if something is tagged +bool tag = tagger.is_tagged(vh); + +// Set tagged: +tagger.set_tag(vh); +\endcode + +For details see OpenMesh::SmartTaggerT + +*/ + + +/** \brief Smart Tagger + * + * A tagger class to be used on OpenMesh. It provides an O(1) reset function for the property. + * - Smarttagging for vertices: SmartTaggerVT; + * - Smarttagging for edges: SmartTaggerET; + * - Smarttagging for faces: SmartTaggerFT; + * - Smarttagging for halfedges: SmartTaggerHT; + * + * Usage: + * + * \code + * SmartTaggerVT< MeshType >* tagger = new SmartTaggerVT< MeshType > (mesh_); + * + * // Reset tagged flag on all vertices + * tagger.untag_all(); + * + * // Check if something is tagged + * bool tag = tagger.is_tagged(vh); + * + * // Set tagged: + * tagger.set_tag(vh); + * \endcode + */ +template +class SmartTaggerT +{ +public: + + /// Constructor + SmartTaggerT(Mesh& _mesh, unsigned int _tag_range = 1); + + /// Destructor + ~SmartTaggerT(); + + /** \brief untag all elements + * + */ + inline void untag_all(); + + /** \brief untag all elements and set new tag_range + * + * @param _new_tag_range New tag range of the tagger + */ + inline void untag_all( const unsigned int _new_tag_range); + + /** \brief set tag to a value in [0..tag_range] + * + * @param _eh Edge handle for the tag + * @param _tag Tag value + */ + inline void set_tag ( const EHandle _eh, unsigned int _tag = 1); + + /** \brief get tag value in range [0..tag_range] + * + * @param _eh Edge handle for the tag + * @return Current tag value at that edge + */ + inline unsigned int get_tag ( const EHandle _eh) const; + + /** \brief overloaded member for boolean tags + * + * @param _eh Edge handle for the tag + * @return Current tag value at that edge + */ + inline bool is_tagged( const EHandle _eh) const; + + /** \brief set new tag range and untag_all + * + * Set new tag range and reset tagger + * + * @param _tag_range New tag range of the tagger + */ + inline void set_tag_range( const unsigned int _tag_range); + +protected: + + inline void all_tags_to_zero(); + +protected: + + // Reference to Mesh + Mesh& mesh_; + + // property which holds the current tags + EPHandle ep_tag_; + + // current tags range is [current_base_+1...current_base_+tag_range_] + unsigned int current_base_; + + // number of different tagvalues available + unsigned int tag_range_; +}; + + +//== SPECIALIZATION =========================================================== + +// define standard Tagger +template< class Mesh> +class SmartTaggerVT + : public SmartTaggerT< Mesh, typename Mesh::VertexHandle, OpenMesh::VPropHandleT > +{ +public: + typedef SmartTaggerT< Mesh, typename Mesh::VertexHandle, OpenMesh::VPropHandleT > BaseType; + SmartTaggerVT(Mesh& _mesh, unsigned int _tag_range = 1) : BaseType(_mesh, _tag_range) {} +}; + +template< class Mesh> +class SmartTaggerET + : public SmartTaggerT< Mesh, typename Mesh::EdgeHandle, OpenMesh::EPropHandleT > +{ +public: + typedef SmartTaggerT< Mesh, typename Mesh::EdgeHandle, OpenMesh::EPropHandleT > BaseType; + SmartTaggerET(Mesh& _mesh, unsigned int _tag_range = 1) : BaseType(_mesh, _tag_range) {} +}; + +template< class Mesh> +class SmartTaggerFT + : public SmartTaggerT< Mesh, typename Mesh::FaceHandle, OpenMesh::FPropHandleT > +{ +public: + typedef SmartTaggerT< Mesh, typename Mesh::FaceHandle, OpenMesh::FPropHandleT > BaseType; + SmartTaggerFT(Mesh& _mesh, unsigned int _tag_range = 1): BaseType(_mesh, _tag_range) {} +}; + +template< class Mesh> +class SmartTaggerHT + : public SmartTaggerT< Mesh, typename Mesh::HalfedgeHandle, OpenMesh::HPropHandleT > +{ +public: + typedef SmartTaggerT< Mesh, typename Mesh::HalfedgeHandle, OpenMesh::HPropHandleT > BaseType; + SmartTaggerHT(Mesh& _mesh, unsigned int _tag_range = 1): BaseType(_mesh, _tag_range){} +}; + + +//============================================================================= +} // namespace OpenMesh +//============================================================================= +#if defined(OM_INCLUDE_TEMPLATES) && !defined(OPENMESH_SMARTTAGGERT_C) +#define OPENMESH_SMARTTAGGERT_TEMPLATES +#include "SmartTaggerT.cc" +#endif + diff --git a/src/Unittests/unittests_read_write_PLY.cc b/src/Unittests/unittests_read_write_PLY.cc index e92a678e..82370bb3 100644 --- a/src/Unittests/unittests_read_write_PLY.cc +++ b/src/Unittests/unittests_read_write_PLY.cc @@ -728,4 +728,58 @@ TEST_F(OpenMeshReadWritePLY, LoadSimpleBinaryPLYWithExtraElements) { EXPECT_EQ(12u, mesh_.n_faces()) << "The number of loaded faces is not correct!"; } + +/* +* Ignore a file that does not contain vertices and faces +*/ +TEST_F(OpenMeshReadWritePLY, IgnoreNonMeshPlyFile) { + + mesh_.clear(); + + std::stringstream data; + data << "ply" << "\n"; + data << "format binary_little_endian 1.0" << "\n"; + data << "comment Image data" << "\n"; + data << "element image 0" << "\n"; + data << "property list uint16 uint16 row" << "\n"; + data << "end_header" << "\n"; + + OpenMesh::IO::Options options = OpenMesh::IO::Options::Binary; + + bool ok = OpenMesh::IO::read_mesh(mesh_, data, ".ply", options); + + EXPECT_TRUE(ok) << "This empty file should be readable without an error!"; + + EXPECT_EQ(0u, mesh_.n_vertices()) << "The number of loaded vertices is not correct!"; + EXPECT_EQ(0u, mesh_.n_edges()) << "The number of loaded edges is not correct!"; + EXPECT_EQ(0u, mesh_.n_faces()) << "The number of loaded faces is not correct!"; +} + + +/* +* Ignore a file that does not contain vertices and faces +*/ +TEST_F(OpenMeshReadWritePLY, FailOnUnknownPropertyTypeForLists) { + + mesh_.clear(); + + std::stringstream data; + data << "ply" << "\n"; + data << "format binary_little_endian 1.0" << "\n"; + data << "comment Image data" << "\n"; + data << "element image 0" << "\n"; + data << "property list blibb blubb row" << "\n"; + data << "end_header" << "\n"; + + OpenMesh::IO::Options options = OpenMesh::IO::Options::Binary; + + bool ok = OpenMesh::IO::read_mesh(mesh_, data, ".ply", options); + + EXPECT_FALSE(ok) << "This file should fail to read!"; + + EXPECT_EQ(0u, mesh_.n_vertices()) << "The number of loaded vertices is not correct!"; + EXPECT_EQ(0u, mesh_.n_edges()) << "The number of loaded edges is not correct!"; + EXPECT_EQ(0u, mesh_.n_faces()) << "The number of loaded faces is not correct!"; +} + } diff --git a/src/Unittests/unittests_smarttagger.cc b/src/Unittests/unittests_smarttagger.cc new file mode 100644 index 00000000..112fbf74 --- /dev/null +++ b/src/Unittests/unittests_smarttagger.cc @@ -0,0 +1,252 @@ +#include +#include +#include +#include + +namespace { + +class OpenMeshSmartTagger : public OpenMeshBase { + + protected: + + // This function is called before each test is run + virtual void SetUp() { + + // Do some initial stuff with the member data here... + } + + // This function is called after all tests are through + virtual void TearDown() { + + // Do some final stuff with the member data here... + } + + // Member already defined in OpenMeshBase + //Mesh mesh_; +}; + +/* + * ==================================================================== + * Define tests below + * ==================================================================== + */ + +/* Checks SmartTagger on vertices + */ +TEST_F(OpenMeshSmartTagger, SmartTaggerVertices) { + + mesh_.clear(); + + // Add some vertices + Mesh::VertexHandle vhandle[7]; + + vhandle[0] = mesh_.add_vertex(Mesh::Point(0, 1, 0)); + vhandle[1] = mesh_.add_vertex(Mesh::Point(1, 0, 0)); + vhandle[2] = mesh_.add_vertex(Mesh::Point(2, 1, 0)); + vhandle[3] = mesh_.add_vertex(Mesh::Point(0,-1, 0)); + vhandle[4] = mesh_.add_vertex(Mesh::Point(2,-1, 0)); + vhandle[5] = mesh_.add_vertex(Mesh::Point(3, 0, 0)); + + + // Add two faces + std::vector face_vhandles; + + face_vhandles.push_back(vhandle[0]); + face_vhandles.push_back(vhandle[1]); + face_vhandles.push_back(vhandle[2]); + mesh_.add_face(face_vhandles); + + face_vhandles.clear(); + + face_vhandles.push_back(vhandle[1]); + face_vhandles.push_back(vhandle[3]); + face_vhandles.push_back(vhandle[4]); + mesh_.add_face(face_vhandles); + + face_vhandles.clear(); + + face_vhandles.push_back(vhandle[0]); + face_vhandles.push_back(vhandle[3]); + face_vhandles.push_back(vhandle[1]); + mesh_.add_face(face_vhandles); + + face_vhandles.clear(); + + face_vhandles.push_back(vhandle[2]); + face_vhandles.push_back(vhandle[1]); + face_vhandles.push_back(vhandle[4]); + mesh_.add_face(face_vhandles); + + face_vhandles.clear(); + + face_vhandles.push_back(vhandle[5]); + face_vhandles.push_back(vhandle[2]); + face_vhandles.push_back(vhandle[4]); + mesh_.add_face(face_vhandles); + + /* Test setup: + 0 ==== 2 + |\ /|\ + | \ / | \ + | 1 | 5 + | / \ | / + |/ \|/ + 3 ==== 4 + + */ + + + OpenMesh::SmartTaggerVT< Mesh > tagger(mesh_); + + + EXPECT_FALSE( tagger.is_tagged(vhandle[0] ) ) << "Vertex should be untagged after init!"; + EXPECT_FALSE( tagger.is_tagged(vhandle[1] ) ) << "Vertex should be untagged after init!"; + EXPECT_FALSE( tagger.is_tagged(vhandle[2] ) ) << "Vertex should be untagged after init!"; + EXPECT_FALSE( tagger.is_tagged(vhandle[3] ) ) << "Vertex should be untagged after init!"; + EXPECT_FALSE( tagger.is_tagged(vhandle[4] ) ) << "Vertex should be untagged after init!"; + EXPECT_FALSE( tagger.is_tagged(vhandle[5] ) ) << "Vertex should be untagged after init!"; + + // Reset tagged flag on all vertices + tagger.untag_all(); + + EXPECT_FALSE( tagger.is_tagged(vhandle[0] ) ) << "Vertex should be untagged after first untag_all!"; + EXPECT_FALSE( tagger.is_tagged(vhandle[1] ) ) << "Vertex should be untagged after first untag_all!"; + EXPECT_FALSE( tagger.is_tagged(vhandle[2] ) ) << "Vertex should be untagged after first untag_all!"; + EXPECT_FALSE( tagger.is_tagged(vhandle[3] ) ) << "Vertex should be untagged after first untag_all!"; + EXPECT_FALSE( tagger.is_tagged(vhandle[4] ) ) << "Vertex should be untagged after first untag_all!"; + EXPECT_FALSE( tagger.is_tagged(vhandle[5] ) ) << "Vertex should be untagged after first untag_all!"; + + + // Set tagged: + tagger.set_tag(vhandle[2]); + tagger.set_tag(vhandle[4]); + + EXPECT_FALSE( tagger.is_tagged(vhandle[0] ) ) << "Vertex should be untagged!"; + EXPECT_FALSE( tagger.is_tagged(vhandle[1] ) ) << "Vertex should be untagged!"; + EXPECT_TRUE( tagger.is_tagged(vhandle[2] ) ) << "Vertex should be tagged!"; + EXPECT_FALSE( tagger.is_tagged(vhandle[3] ) ) << "Vertex should be untagged!"; + EXPECT_TRUE( tagger.is_tagged(vhandle[4] ) ) << "Vertex should be tagged!"; + EXPECT_FALSE( tagger.is_tagged(vhandle[5] ) ) << "Vertex should be untagged!"; + + // Reset tagged flag on all vertices + tagger.untag_all(); + + EXPECT_FALSE( tagger.is_tagged(vhandle[0] ) ) << "Vertex should be untagged after second untag_all!"; + EXPECT_FALSE( tagger.is_tagged(vhandle[1] ) ) << "Vertex should be untagged after second untag_all!"; + EXPECT_FALSE( tagger.is_tagged(vhandle[2] ) ) << "Vertex should be untagged after second untag_all!"; + EXPECT_FALSE( tagger.is_tagged(vhandle[3] ) ) << "Vertex should be untagged after second untag_all!"; + EXPECT_FALSE( tagger.is_tagged(vhandle[4] ) ) << "Vertex should be untagged after second untag_all!"; + EXPECT_FALSE( tagger.is_tagged(vhandle[5] ) ) << "Vertex should be untagged after second untag_all!"; + +} + +/* Checks SmartTagger on vertices + */ +TEST_F(OpenMeshSmartTagger, SmartTaggerFaces) { + + mesh_.clear(); + + // Add some vertices + Mesh::VertexHandle vhandle[7]; + + vhandle[0] = mesh_.add_vertex(Mesh::Point(0, 1, 0)); + vhandle[1] = mesh_.add_vertex(Mesh::Point(1, 0, 0)); + vhandle[2] = mesh_.add_vertex(Mesh::Point(2, 1, 0)); + vhandle[3] = mesh_.add_vertex(Mesh::Point(0,-1, 0)); + vhandle[4] = mesh_.add_vertex(Mesh::Point(2,-1, 0)); + vhandle[5] = mesh_.add_vertex(Mesh::Point(3, 0, 0)); + + + // Add two faces + std::vector face_vhandles; + + face_vhandles.push_back(vhandle[0]); + face_vhandles.push_back(vhandle[1]); + face_vhandles.push_back(vhandle[2]); + Mesh::FaceHandle fh1 = mesh_.add_face(face_vhandles); + + face_vhandles.clear(); + + face_vhandles.push_back(vhandle[1]); + face_vhandles.push_back(vhandle[3]); + face_vhandles.push_back(vhandle[4]); + Mesh::FaceHandle fh2 = mesh_.add_face(face_vhandles); + + face_vhandles.clear(); + + face_vhandles.push_back(vhandle[0]); + face_vhandles.push_back(vhandle[3]); + face_vhandles.push_back(vhandle[1]); + Mesh::FaceHandle fh3 = mesh_.add_face(face_vhandles); + + face_vhandles.clear(); + + face_vhandles.push_back(vhandle[2]); + face_vhandles.push_back(vhandle[1]); + face_vhandles.push_back(vhandle[4]); + Mesh::FaceHandle fh4 = mesh_.add_face(face_vhandles); + + face_vhandles.clear(); + + face_vhandles.push_back(vhandle[5]); + face_vhandles.push_back(vhandle[2]); + face_vhandles.push_back(vhandle[4]); + Mesh::FaceHandle fh5 = mesh_.add_face(face_vhandles); + + /* Test setup: + 0 ==== 2 + |\ /|\ + | \ / | \ + | 1 | 5 + | / \ | / + |/ \|/ + 3 ==== 4 + + */ + + + OpenMesh::SmartTaggerFT< Mesh > tagger(mesh_); + + + EXPECT_FALSE( tagger.is_tagged( fh1 ) ) << "Face should be untagged after init!"; + EXPECT_FALSE( tagger.is_tagged( fh2 ) ) << "Face should be untagged after init!"; + EXPECT_FALSE( tagger.is_tagged( fh3 ) ) << "Face should be untagged after init!"; + EXPECT_FALSE( tagger.is_tagged( fh4 ) ) << "Face should be untagged after init!"; + EXPECT_FALSE( tagger.is_tagged( fh5 ) ) << "Face should be untagged after init!"; + + + // Reset tagged flag on all vertices + tagger.untag_all(); + + EXPECT_FALSE( tagger.is_tagged( fh1 ) ) << "Face should be untagged after first untag_all!"; + EXPECT_FALSE( tagger.is_tagged( fh2 ) ) << "Face should be untagged after first untag_all!"; + EXPECT_FALSE( tagger.is_tagged( fh3 ) ) << "Face should be untagged after first untag_all!"; + EXPECT_FALSE( tagger.is_tagged( fh4 ) ) << "Face should be untagged after first untag_all!"; + EXPECT_FALSE( tagger.is_tagged( fh5 ) ) << "Face should be untagged after first untag_all!"; + + + + // Set tagged: + tagger.set_tag(fh3); + tagger.set_tag(fh5); + + + EXPECT_FALSE( tagger.is_tagged(fh1 ) ) << "Face should be untagged!"; + EXPECT_FALSE( tagger.is_tagged(fh2 ) ) << "Face should be untagged!"; + EXPECT_TRUE( tagger.is_tagged(fh3 ) ) << "Face should be tagged!"; + EXPECT_FALSE( tagger.is_tagged(fh4 ) ) << "Face should be tagged!"; + EXPECT_TRUE( tagger.is_tagged(fh5 ) ) << "Face should be tagged!"; + + + // Reset tagged flag on all vertices + tagger.untag_all(); + + EXPECT_FALSE( tagger.is_tagged( fh1 ) ) << "Face should be untagged after second untag_all!"; + EXPECT_FALSE( tagger.is_tagged( fh2 ) ) << "Face should be untagged after second untag_all!"; + EXPECT_FALSE( tagger.is_tagged( fh3 ) ) << "Face should be untagged after second untag_all!"; + EXPECT_FALSE( tagger.is_tagged( fh4 ) ) << "Face should be untagged after second untag_all!"; + EXPECT_FALSE( tagger.is_tagged( fh5 ) ) << "Face should be untagged after second untag_all!"; + +} + +}