3#include <Core/Containers/VectorArray.hpp>
4#include <Core/Geometry/OpenMesh.hpp>
5#include <Core/Geometry/StandardAttribNames.hpp>
6#include <Core/Geometry/TriangleMesh.hpp>
7#include <Core/RaCore.hpp>
9#include <Core/Utils/Index.hpp>
10#include <Core/Utils/Log.hpp>
11#include <Core/Utils/StdOptional.hpp>
13#include <OpenMesh/Core/Mesh/PolyMesh_ArrayKernelT.hh>
14#include <OpenMesh/Core/Mesh/Traits.hh>
15#include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>
16#include <OpenMesh/Core/Utils/Property.hh>
17#include <OpenMesh/Core/Utils/PropertyManager.hh>
20#include <Eigen/Geometry>
24#include <unordered_map>
35 using Point = Ra::Core::Vector3;
36 using Normal = Ra::Core::Vector3;
38 VertexAttributes( OpenMesh::Attributes::Status | OpenMesh::Attributes::Normal );
39 FaceAttributes( OpenMesh::Attributes::Status | OpenMesh::Attributes::Normal );
40 EdgeAttributes( OpenMesh::Attributes::Status );
42 HalfedgeAttributes( OpenMesh::Attributes::Status | OpenMesh::Attributes::Normal );
55class RA_CORE_API
TopologicalMesh :
public OpenMesh::PolyMesh_ArrayKernelT<TopologicalMeshTraits>
58 using base = OpenMesh::PolyMesh_ArrayKernelT<TopologicalMeshTraits>;
59 using base::PolyMesh_ArrayKernelT;
60 using Vector3 = Ra::Core::Vector3;
61 using Index = Ra::Core::Utils::Index;
63 class WedgeCollection;
67 using WedgeIndex = Ra::Core::Utils::Index;
68 using WedgeAttribIndex = Ra::Core::Utils::Index;
79 template <
typename MeshIndex>
105 template <
typename MeshIndex,
typename NonManifoldFaceCommand>
108 NonManifoldFaceCommand command );
123 template <
typename NonManifoldFaceCommand>
127 NonManifoldFaceCommand command );
133 template <
typename NonManifoldFaceCommand>
136 NonManifoldFaceCommand command );
141 TriangleMesh toTriangleMesh();
148 PolyMesh toPolyMesh();
150 LineMesh toLineMesh();
158 void updateTriangleMeshNormals( AttribArrayGeometry::NormalAttribHandle::Container& normals );
163 void updatePositions(
const AttribArrayGeometry::PointAttribHandle::Container& vertices );
165 using base::halfedge_handle;
171 inline HalfedgeHandle halfedge_handle( VertexHandle vh, FaceHandle fh )
const;
176 using base::set_normal;
184 inline void propagate_normal_to_wedges( VertexHandle vh );
190 inline const OpenMesh::HPropHandleT<Index>& getInputTriangleMeshIndexPropHandle()
const;
197 inline const OpenMesh::HPropHandleT<Index>& getOutputTriangleMeshIndexPropHandle()
const;
205 void updateWedgeNormals();
210 void copyPointsPositionToWedges();
227 bool splitEdge( TopologicalMesh::EdgeHandle eh, Scalar f );
238 void collapse( HalfedgeHandle he,
bool keepFromVertex =
false );
239 [[deprecated(
"use collapse() instead." )]]
void
240 collapseWedge( TopologicalMesh::HalfedgeHandle he,
bool keepFromVertex =
false );
252 inline WedgeIndex getWedgeIndex( OpenMesh::HalfedgeHandle heh )
const;
258 inline const WedgeData& getWedgeData(
const WedgeIndex& idx )
const;
259 template <
typename T>
260 [[deprecated(
"use getWedgeAttrib() instead." )]]
const T&
261 getWedgeData(
const WedgeIndex& idx,
const std::string& name )
const;
262 template <
typename T>
263 const T& getWedgeAttrib(
const WedgeIndex& idx,
const std::string& name )
const;
268 inline unsigned int getWedgeRefCount(
const WedgeIndex& idx )
const;
275 inline void setWedgeData( WedgeIndex widx,
const WedgeData& wd );
283 template <
typename T>
284 [[deprecated(
"use setWedgeAttrib() instead." )]]
inline bool
285 setWedgeData(
const WedgeIndex& idx,
const std::string& name,
const T& value );
287 template <
typename T>
288 inline bool setWedgeAttrib(
const WedgeIndex& idx,
const std::string& name,
const T& value );
295 return m_wedges.newWedgeData( to_vertex_handle( he ), point( to_vertex_handle( he ) ) );
303 inline WedgeIndex replaceWedge( OpenMesh::HalfedgeHandle he,
const WedgeData& wd );
305 template <
typename T>
306 inline WedgeAttribIndex addWedgeAttrib(
const std::string& name, T value = {} ) {
307 return m_wedges.addAttrib<T>( name, value );
314 inline void replaceWedgeIndex( OpenMesh::HalfedgeHandle he,
const WedgeIndex& widx );
320 inline void mergeEqualWedges();
326 inline void mergeEqualWedges( OpenMesh::VertexHandle vh );
329 void garbage_collection();
330 inline void clean() {
341 inline bool isFeatureVertex(
const VertexHandle& vh )
const;
346 inline bool isFeatureEdge(
const EdgeHandle& eh )
const;
348 inline const OpenMesh::HPropHandleT<WedgeIndex>& getWedgeIndexPph()
const;
350 void delete_face( FaceHandle _fh,
bool _delete_isolated_vertices =
true );
356 bool isManifold( VertexHandle vh )
const;
360 bool checkIntegrity()
const;
375 inline bool operator==(
const WedgeData& lhs )
const;
376 inline bool operator!=(
const WedgeData& lhs )
const;
377 inline bool operator<(
const WedgeData& lhs )
const;
379 template <
typename T>
381 template <
typename T>
387 VertexHandle m_vertexHandle;
388 Vector3 m_position {};
396 template <
typename T>
397 static int compareVector(
const T& a,
const T& b );
402 void collapse_edge( HalfedgeHandle,
bool );
403 void collapse_loop( HalfedgeHandle );
410 class RA_CORE_API Wedge
414 explicit Wedge(
const WedgeData& wd ) : m_wedgeData { wd }, m_refCount { 1 } {};
415 const WedgeData& getWedgeData()
const {
return m_wedgeData; }
416 void setWedgeData(
const WedgeData& wedgeData ) { m_wedgeData = wedgeData; }
417 void setWedgeData( WedgeData&& wedgeData ) { m_wedgeData =
std::move( wedgeData ); }
418 void incrementRefCount() { ++m_refCount; }
419 void decrementRefCount() {
420 if ( m_refCount ) --m_refCount;
423 bool operator==(
const Wedge& lhs )
const {
return m_wedgeData == lhs.m_wedgeData; }
425 bool isDeleted()
const {
return m_refCount == 0; }
426 unsigned int getRefCount()
const {
return m_refCount; }
428 friend WedgeCollection;
429 friend TopologicalMesh;
432 WedgeData& getWedgeData() {
return m_wedgeData; }
434 WedgeData m_wedgeData {};
435 unsigned int m_refCount { 0 };
445 class RA_CORE_API WedgeCollection
455 WedgeIndex
add(
const WedgeData& wd );
463 inline void del(
const WedgeIndex& idx );
464 WedgeIndex newReference(
const WedgeIndex& idx );
472 inline const Wedge& getWedge(
const WedgeIndex& idx )
const;
474 inline const WedgeData& getWedgeData(
const WedgeIndex& idx )
const;
475 template <
typename T>
476 inline const T& getWedgeData(
const WedgeIndex& idx,
const std::string& name )
const;
477 template <
typename T>
478 inline T& getWedgeData(
const WedgeIndex& idx,
int attribIndex );
479 template <
typename T>
480 inline const T& getWedgeAttrib(
const WedgeIndex& idx,
const std::string& name )
const;
481 template <
typename T>
482 inline T& getWedgeAttrib(
const WedgeIndex& idx,
int attribIndex );
484 unsigned int getWedgeRefCount(
const WedgeIndex& idx )
const;
487 inline void setWedgeData(
const WedgeIndex& idx,
const WedgeData& wd );
493 template <
typename T>
495 setWedgeAttrib( TopologicalMesh::WedgeData& wd,
const std::string& name,
const T& value );
496 template <
typename T>
498 setWedgeAttrib(
const WedgeIndex& idx,
const std::string& name,
const T& value );
499 template <
typename T>
500 inline void setWedgeAttrib(
const TopologicalMesh::WedgeIndex& idx,
501 const int& attribIndex,
504 template <
typename T>
505 inline WedgeAttribIndex getWedgeAttribIndex(
const std::string& name );
507 inline bool setWedgePosition(
const WedgeIndex& idx,
const Vector3& value );
511 template <
typename T>
517 template <
typename T>
518 WedgeAttribIndex addAttribName(
const std::string& name );
521 template <
typename T>
522 WedgeAttribIndex addAttrib(
const std::string& name,
const T& value = {} );
532 inline size_t size()
const {
return m_data.size(); }
535 inline void garbageCollection();
540 inline WedgeData newWedgeData()
const;
541 inline WedgeData newWedgeData( TopologicalMesh::VertexHandle vh,
542 TopologicalMesh::Point p )
const;
558 template <
typename T>
560 AlignedStdVector<Wedge> m_data;
564 class InitWedgeAttribsFromMultiIndexedGeometry
567 InitWedgeAttribsFromMultiIndexedGeometry(
568 TopologicalMesh* topo,
570 m_topo( topo ), m_triMesh( triMesh ) {}
571 void operator()( AttribBase* attr )
const;
574 TopologicalMesh* m_topo;
580 struct DefaultNonManifoldFaceCommand {
582 DefaultNonManifoldFaceCommand(
const std::string& details = {} ) : m_details { details } {}
587 LOG( logWARNING ) <<
"Invalid face handle returned : face not added " + m_details;
590 inline void postProcess( TopologicalMesh& ) {}
597 WedgeData interpolateWedgeAttributes(
const WedgeData&,
const WedgeData&, Scalar alpha );
600 template <
typename T>
604 VectorArray<T>* to );
609 const std::vector<AttribHandle<Scalar>>& wprop_float,
610 const std::vector<AttribHandle<Vector2>>& wprop_vec2,
611 const std::vector<AttribHandle<Vector3>>& wprop_vec3,
612 const std::vector<AttribHandle<Vector4>>& wprop_vec4,
613 TopologicalMesh::WedgeData* wd );
615 template <
typename T>
616 using HandleAndValueVector =
618 Eigen::aligned_allocator<std::pair<AttribHandle<T>, T>>>;
620 void split_copy( EdgeHandle _eh, VertexHandle _vh );
621 void split( EdgeHandle _eh, VertexHandle _vh );
623 OpenMesh::HPropHandleT<WedgeIndex> m_wedgeIndexPph;
624 WedgeCollection m_wedges;
627 OpenMesh::HPropHandleT<Index> m_inputTriangleMeshIndexPph;
628 OpenMesh::HPropHandleT<Index> m_outputTriangleMeshIndexPph;
630 int m_normalsIndex { -1 };
634 friend class TMOperations;
638void printWedgesInfo(
const TopologicalMesh& );
644inline bool TopologicalMesh::WedgeData::operator==(
const TopologicalMesh::WedgeData& lhs )
const {
649 m_position == lhs.m_position && m_floatAttrib == lhs.m_floatAttrib &&
650 m_vector2Attrib == lhs.m_vector2Attrib && m_vector3Attrib == lhs.m_vector3Attrib &&
651 m_vector4Attrib == lhs.m_vector4Attrib;
654bool TopologicalMesh::WedgeData::operator!=(
const TopologicalMesh::WedgeData& lhs )
const {
655 return !( *
this == lhs );
658inline bool TopologicalMesh::WedgeData::operator<(
const TopologicalMesh::WedgeData& lhs )
const {
660 CORE_ASSERT( ( m_floatAttrib.size() == lhs.m_floatAttrib.size() ) &&
661 ( m_vector2Attrib.size() == lhs.m_vector2Attrib.size() ) &&
662 ( m_vector3Attrib.size() == lhs.m_vector3Attrib.size() ) &&
663 ( m_vector4Attrib.size() == lhs.m_vector4Attrib.size() ),
664 "Could only compare wedge with same number of attributes" );
667 int comp = compareVector( m_position, lhs.m_position );
668 if ( comp == 2 )
return true;
669 if ( comp == 3 )
return false;
671 for (
size_t i = 0; i < m_floatAttrib.size(); i++ ) {
672 if ( m_floatAttrib[i] < lhs.m_floatAttrib[i] )
674 else if ( m_floatAttrib[i] > lhs.m_floatAttrib[i] )
678 for (
size_t i = 0; i < m_vector2Attrib.size(); i++ ) {
679 int comp = compareVector( m_vector2Attrib[i], lhs.m_vector2Attrib[i] );
680 if ( comp == 2 )
return true;
681 if ( comp == 3 )
return false;
683 for (
size_t i = 0; i < m_vector3Attrib.size(); i++ ) {
684 int comp = compareVector( m_vector3Attrib[i], lhs.m_vector3Attrib[i] );
685 if ( comp == 2 )
return true;
686 if ( comp == 3 )
return false;
688 for (
size_t i = 0; i < m_vector4Attrib.size(); i++ ) {
689 int comp = compareVector( m_vector4Attrib[i], lhs.m_vector4Attrib[i] );
690 if ( comp == 2 )
return true;
691 if ( comp == 3 )
return false;
696#define GET_ATTRIB_ARRAY_HELPER( TYPE, NAME ) \
698 inline VectorArray<TYPE>& TopologicalMesh::WedgeData::getAttribArray<TYPE>() { \
699 return m_##NAME##Attrib; \
702 inline const VectorArray<TYPE>& TopologicalMesh::WedgeData::getAttribArray<TYPE>() const { \
703 return m_##NAME##Attrib; \
706GET_ATTRIB_ARRAY_HELPER( Scalar,
float )
707GET_ATTRIB_ARRAY_HELPER( Vector2, vector2 )
708GET_ATTRIB_ARRAY_HELPER( Vector3, vector3 )
709GET_ATTRIB_ARRAY_HELPER( Vector4, vector4 )
710#undef GET_ATTRIB_ARRAY_HELPER
713inline VectorArray<T>& TopologicalMesh::WedgeData::getAttribArray() {
714 static_assert(
sizeof( T ) == -1,
"this type is not supported" );
719int TopologicalMesh::WedgeData::compareVector(
const T& a,
const T& b ) {
720 for (
int i = 0; i < T::RowsAtCompileTime; i++ ) {
721 if ( a[i] < b[i] )
return 2;
722 if ( a[i] > b[i] )
return 3;
738inline void TopologicalMesh::WedgeCollection::del(
const TopologicalMesh::WedgeIndex& idx ) {
739 if ( idx.isValid() ) m_data[idx].decrementRefCount();
742inline TopologicalMesh::WedgeIndex
743TopologicalMesh::WedgeCollection::newReference(
const TopologicalMesh::WedgeIndex& idx ) {
744 if ( idx.isValid() ) m_data[idx].incrementRefCount();
748inline const TopologicalMesh::Wedge&
749TopologicalMesh::WedgeCollection::getWedge(
const TopologicalMesh::WedgeIndex& idx )
const {
753inline const TopologicalMesh::WedgeData&
754TopologicalMesh::WedgeCollection::getWedgeData(
const WedgeIndex& idx )
const {
755 CORE_ASSERT( idx.isValid() && !m_data[idx].isDeleted(),
756 "access to invalid or deleted wedge is prohibited" );
758 return m_data[idx].getWedgeData();
763TopologicalMesh::WedgeCollection::getWedgeData(
const TopologicalMesh::WedgeIndex& idx,
765 return getWedgeAttrib<T>( idx, name );
770TopologicalMesh::WedgeCollection::getWedgeAttrib(
const TopologicalMesh::WedgeIndex& idx,
772 if ( idx.isValid() ) {
773 auto nameArray = getNameArray<T>();
774 auto itr =
std::find( nameArray.begin(), nameArray.end(), name );
775 if ( itr != nameArray.end() ) {
777 return m_data[idx].getWedgeData().getAttribArray<T>()[attrIndex];
780 LOG( logERROR ) <<
"Warning, set wedge: no wedge attrib named " << name <<
" of type "
781 <<
typeid( T ).name();
789inline T& TopologicalMesh::WedgeCollection::getWedgeData(
const TopologicalMesh::WedgeIndex& idx,
791 return getWedgeAttrib<T>( idx, attribIndex );
795inline T& TopologicalMesh::WedgeCollection::getWedgeAttrib(
const TopologicalMesh::WedgeIndex& idx,
797 return m_data[idx].getWedgeData().getAttribArray<T>()[attribIndex];
801TopologicalMesh::WedgeCollection::getWedgeRefCount(
const WedgeIndex& idx )
const {
802 CORE_ASSERT( idx.isValid(),
"access to invalid or deleted wedge is prohibited" );
803 return m_data[idx].getRefCount();
806inline void TopologicalMesh::WedgeCollection::setWedgeData(
const TopologicalMesh::WedgeIndex& idx,
807 const TopologicalMesh::WedgeData& wd ) {
808 if ( !( wd.m_floatAttrib.size() == m_floatAttribNames.size() &&
809 wd.m_vector2Attrib.size() == m_vector2AttribNames.size() &&
810 wd.m_vector3Attrib.size() == m_vector3AttribNames.size() &&
811 wd.m_vector4Attrib.size() == m_vector4AttribNames.size() ) ) {
812 LOG( logWARNING ) <<
"Warning, topological mesh set wedge: number of attribs inconsistency";
814 if ( idx.isValid() ) m_data[idx].setWedgeData( wd );
818inline bool TopologicalMesh::WedgeCollection::setWedgeAttrib( TopologicalMesh::WedgeData& wd,
821 auto nameArray = getNameArray<T>();
822 auto itr =
std::find( nameArray.begin(), nameArray.end(), name );
823 if ( itr != nameArray.end() ) {
825 wd.getAttribArray<T>()[attrIndex] = value;
829 LOG( logERROR ) <<
"Warning, set wedge: no wedge attrib named " << name <<
" of type "
830 <<
typeid( T ).name();
837TopologicalMesh::WedgeCollection::setWedgeAttrib(
const TopologicalMesh::WedgeIndex& idx,
840 if ( idx.isValid() ) {
841 auto nameArray = getNameArray<T>();
842 auto itr =
std::find( nameArray.begin(), nameArray.end(), name );
843 if ( itr != nameArray.end() ) {
845 m_data[idx].getWedgeData().getAttribArray<T>()[attrIndex] = value;
849 LOG( logERROR ) <<
"Warning, set wedge: no wedge attrib named " << name <<
" of type "
850 <<
typeid( T ).name();
858TopologicalMesh::WedgeCollection::setWedgeAttrib(
const TopologicalMesh::WedgeIndex& idx,
859 const int& attrIndex,
861 m_data[idx].getWedgeData().getAttribArray<T>()[attrIndex] = value;
865inline TopologicalMesh::WedgeAttribIndex
866TopologicalMesh::WedgeCollection::getWedgeAttribIndex(
const std::string& name ) {
867 auto nameArray = getNameArray<T>();
868 auto itr =
std::find( nameArray.begin(), nameArray.end(), name );
869 if ( itr != nameArray.end() ) {
return std::distance( nameArray.begin(), itr ); }
874TopologicalMesh::WedgeCollection::setWedgePosition(
const TopologicalMesh::WedgeIndex& idx,
875 const Vector3& value ) {
876 if ( idx.isValid() ) {
877 m_data[idx].getWedgeData().m_position = value;
883#define GET_NAME_ARRAY_HELPER( TYPE, NAME ) \
885 inline const std::vector<std::string>& TopologicalMesh::WedgeCollection::getNameArray<TYPE>() \
887 return m_##NAME##AttribNames; \
890 inline std::vector<std::string>& TopologicalMesh::WedgeCollection::getNameArray<TYPE>() { \
891 return m_##NAME##AttribNames; \
894GET_NAME_ARRAY_HELPER( Scalar,
float )
895GET_NAME_ARRAY_HELPER( Vector2, vector2 )
896GET_NAME_ARRAY_HELPER( Vector3, vector3 )
897GET_NAME_ARRAY_HELPER( Vector4, vector4 )
899#undef GET_NAME_ARRAY_HELPER
905 LOG( logWARNING ) <<
"Warning, mesh attribute " <<
typeid( T ).name()
906 <<
" is not supported (only float, vec2, vec3 nor vec4 are supported)";
907 static_assert(
sizeof( T ) == -1,
"this type is not supported" );
908 return m_floatAttribNames;
914 LOG( logWARNING ) <<
"Warning, mesh attribute " <<
typeid( T ).name()
915 <<
" is not supported (only float, vec2, vec3 nor vec4 are supported)";
916 static_assert(
sizeof( T ) == -1,
"this type is not supported" );
917 return m_floatAttribNames;
920TopologicalMesh::WedgeAttribIndex
921TopologicalMesh::WedgeCollection::addAttribName(
const std::string& name ) {
922 if ( name != getAttribName( MeshAttrib::VERTEX_POSITION ) ) {
923 getNameArray<T>().push_back( name );
925 return getNameArray<T>().
size() - 1;
929TopologicalMesh::WedgeAttribIndex
930TopologicalMesh::WedgeCollection::addAttrib(
const std::string& name,
const T& value ) {
932 auto index = addAttribName<T>( name );
933 for (
auto& w : m_data ) {
934 CORE_ASSERT( index = w.getWedgeData().getAttribArray<T>().size(),
935 "inconsistent wedge attrib" );
936 w.getWedgeData().getAttribArray<T>().push_back( value );
941inline void TopologicalMesh::WedgeCollection::garbageCollection() {
944 [](
const Wedge& w ) { return w.isDeleted(); } ),
948inline void TopologicalMesh::WedgeCollection::clean() {
950 m_floatAttribNames.clear();
951 m_vector2AttribNames.clear();
952 m_vector3AttribNames.clear();
953 m_vector4AttribNames.clear();
954 m_wedgeFloatAttribHandles.clear();
955 m_wedgeVector2AttribHandles.clear();
956 m_wedgeVector3AttribHandles.clear();
957 m_wedgeVector4AttribHandles.clear();
962 for (
size_t i = 0; i < names.
size(); ++i ) {
967inline TopologicalMesh::WedgeData TopologicalMesh::WedgeCollection::newWedgeData()
const {
969 init<Scalar>( ret.getAttribArray<Scalar>(), m_floatAttribNames );
970 init<Vector2>( ret.getAttribArray<Vector2>(), m_vector2AttribNames );
971 init<Vector3>( ret.getAttribArray<Vector3>(), m_vector3AttribNames );
972 init<Vector4>( ret.getAttribArray<Vector4>(), m_vector4AttribNames );
976inline TopologicalMesh::WedgeData
977TopologicalMesh::WedgeCollection::newWedgeData( TopologicalMesh::VertexHandle vh,
978 TopologicalMesh::Point p )
const {
980 ret.m_vertexHandle = vh;
989TopologicalMesh::InitWedgeAttribsFromMultiIndexedGeometry::operator()( AttribBase* attr )
const {
990 if ( attr->getSize() != m_triMesh.vertices().size() ) {
991 LOG( logWARNING ) <<
"[TopologicalMesh] Skip badly sized attribute " << attr->getName();
993 else if ( attr->getName() != getAttribName( MeshAttrib::VERTEX_POSITION ) ) {
994 if ( attr->isFloat() ) {
995 m_topo->m_wedges.m_wedgeFloatAttribHandles.push_back(
996 m_triMesh.template getAttribHandle<Scalar>( attr->getName() ) );
997 m_topo->m_wedges.addAttribName<Scalar>( attr->getName() );
999 else if ( attr->isVector2() ) {
1000 m_topo->m_wedges.m_wedgeVector2AttribHandles.push_back(
1001 m_triMesh.template getAttribHandle<Vector2>( attr->getName() ) );
1002 m_topo->m_wedges.addAttribName<Vector2>( attr->getName() );
1004 else if ( attr->isVector3() ) {
1005 m_topo->m_wedges.m_wedgeVector3AttribHandles.push_back(
1006 m_triMesh.template getAttribHandle<Vector3>( attr->getName() ) );
1007 m_topo->m_wedges.addAttribName<Vector3>( attr->getName() );
1009 else if ( attr->isVector4() ) {
1010 m_topo->m_wedges.m_wedgeVector4AttribHandles.push_back(
1011 m_triMesh.template getAttribHandle<Vector4>( attr->getName() ) );
1012 m_topo->m_wedges.addAttribName<Vector4>( attr->getName() );
1016 <<
"Warning, mesh attribute " << attr->getName()
1017 <<
" type is not supported (only float, vec2, vec3 nor vec4 are supported)";
1026 std::size_t operator()(
const Vector3& lvalue )
const {
1030 return ( hx ^ ( hy << 1 ) ) ^ hz;
1034template <
typename MeshIndex>
1036 TopologicalMesh( mesh, DefaultNonManifoldFaceCommand(
"[default ctor]" ) ) {}
1038template <
typename MeshIndex,
typename NonManifoldFaceCommand>
1040 NonManifoldFaceCommand command ) :
1042 initWithWedge( mesh, mesh.getLayerKey(), command );
1048 TopologicalMesh( mesh, layerKey, DefaultNonManifoldFaceCommand(
"[default ctor]" ) ) {}
1050template <
typename NonManifoldFaceCommand>
1054 NonManifoldFaceCommand command ) :
1056 initWithWedge( mesh, layerKey, command );
1059inline void TopologicalMesh::initWithWedge(
1062 initWithWedge( mesh,
1064 DefaultNonManifoldFaceCommand(
"[initWithWedges (MultiIndexedGeometry)]" ) );
1067template <
typename NonManifoldFaceCommand>
1068void TopologicalMesh::initWithWedge(
1071 NonManifoldFaceCommand command ) {
1073 const auto& abstractLayer = mesh.
getLayer( layerKey );
1075 if ( !abstractLayer.hasSemantic( TriangleIndexLayer::staticSemanticName ) &&
1076 !abstractLayer.hasSemantic( QuadIndexLayer::staticSemanticName ) &&
1077 !abstractLayer.hasSemantic( PolyIndexLayer::staticSemanticName ) ) {
1078 LOG( logWARNING ) <<
"TopologicalMesh: mesh does not contains faces. Aborting conversion";
1084 LOG( logDEBUG ) <<
"TopologicalMesh: load mesh with " << abstractLayer.getSize()
1085 <<
" faces and " << mesh.
vertices().size() <<
" vertices.";
1088 VertexMap vertexHandles;
1093 for (
size_t i = 0; i < mesh.
vertices().size(); ++i ) {
1098 wd.m_position = mesh.
vertices()[i];
1099 copyMeshToWedgeData( mesh,
1101 m_wedges.m_wedgeFloatAttribHandles,
1102 m_wedges.m_wedgeVector2AttribHandles,
1103 m_wedges.m_wedgeVector3AttribHandles,
1104 m_wedges.m_wedgeVector4AttribHandles,
1110 m_wedges.m_data.push_back( w );
1113 LOG( logDEBUG ) <<
"TopologicalMesh: have " << m_wedges.size() <<
" wedges ";
1115 const bool hasNormals = !mesh.
normals().empty();
1116 if ( !hasNormals ) {
1117 release_face_normals();
1118 release_vertex_normals();
1119 release_halfedge_normals();
1122 command.initialize( mesh );
1124 auto processFaces = [&mesh, &vertexHandles,
this, hasNormals, &command](
const auto& faces ) {
1125 size_t num_triangles = faces.size();
1126 for (
unsigned int i = 0; i < num_triangles; i++ ) {
1127 const auto& face = faces[i];
1128 const size_t num_vert = face.size();
1133 for (
size_t j = 0; j < num_vert; ++j ) {
1134 unsigned int inMeshVertexIndex = face[j];
1135 const Vector3& p = mesh.
vertices()[inMeshVertexIndex];
1137 typename VertexMap::iterator vtr = vertexHandles.find( p );
1138 TopologicalMesh::VertexHandle vh;
1139 if ( vtr == vertexHandles.end() ) {
1140 vh = add_vertex( p );
1141 vertexHandles.insert( vtr,
typename VertexMap::value_type( p, vh ) );
1143 else { vh = vtr->second; }
1145 face_vhandles[j] = vh;
1146 if ( hasNormals ) face_normals[j] = mesh.
normals()[inMeshVertexIndex];
1147 face_wedges[j] = WedgeIndex { inMeshVertexIndex };
1148 m_wedges.m_data[inMeshVertexIndex].getWedgeData().m_vertexHandle = vh;
1156 auto begin = face_vhandles.
begin();
1157 if ( face_vhandles.
size() > 2 ) {
1158 auto end = face_vhandles.
end() - 1;
1159 auto wedgeEnd = face_wedges.
end() - 1;
1160 auto normalEnd = face_normals.
end() - 1;
1162 while ( begin != end && *begin == *end ) {
1167 face_vhandles.
erase( end + 1, face_vhandles.
end() );
1168 face_wedges.
erase( wedgeEnd + 1, face_wedges.
end() );
1169 face_normals.
erase( normalEnd + 1, face_normals.
end() );
1180 auto first = face_vhandles.
begin();
1181 auto wedgeFirst = face_wedges.
begin();
1182 auto normalFirst = face_normals.
begin();
1183 auto last = face_vhandles.
end();
1185 if ( first != last ) {
1186 auto result = first;
1187 auto wedgeResult = wedgeFirst;
1188 auto normalResult = normalFirst;
1189 while ( ++first != last ) {
1190 if ( !( *result == *first ) ) {
1194 if ( result != first ) {
1196 *wedgeResult =
std::move( *wedgeFirst );
1197 *normalResult =
std::move( *normalFirst );
1201 face_vhandles.
erase( result + 1, face_vhandles.
end() );
1202 face_wedges.
erase( wedgeResult + 1, face_wedges.
end() );
1203 face_normals.
erase( normalResult + 1, face_normals.
end() );
1210 TopologicalMesh::FaceHandle fh;
1212 if ( face_vhandles.
size() > 2 ) fh = add_face( face_vhandles );
1216 if ( fh.is_valid() ) {
1217 for (
size_t vindex = 0; vindex < face_vhandles.
size(); vindex++ ) {
1218 TopologicalMesh::HalfedgeHandle heh =
1220 if ( hasNormals ) set_normal( heh, face_normals[vindex] );
1221 property( m_wedgeIndexPph, heh ) = m_wedges.newReference( face_wedges[vindex] );
1224 else { command.process( face_vhandles ); }
1225 face_vhandles.
clear();
1226 face_normals.
clear();
1230 if ( abstractLayer.hasSemantic( TriangleIndexLayer::staticSemanticName ) ) {
1231 const auto& faces =
static_cast<const TriangleIndexLayer&
>( abstractLayer ).collection();
1232 LOG( logDEBUG ) <<
"TopologicalMesh: process " << faces.size() <<
" triangular faces ";
1233 processFaces( faces );
1235 else if ( abstractLayer.hasSemantic( PolyIndexLayer::staticSemanticName ) ) {
1236 const auto& faces =
static_cast<const PolyIndexLayer&
>( abstractLayer ).collection();
1237 LOG( logDEBUG ) <<
"TopologicalMesh: process " << faces.size() <<
" polygonal faces ";
1238 processFaces( faces );
1241 command.postProcess( *
this );
1244 m_wedges.getWedgeAttribIndex<Normal>( getAttribName( MeshAttrib::VERTEX_NORMAL ) );
1246 m_vertexFaceWedgesWithSameNormals.
clear();
1247 m_vertexFaceWedgesWithSameNormals.
resize( n_vertices() );
1249 for (
auto itr = vertices_begin(), stop = vertices_end(); itr != stop; ++itr ) {
1253 normalSharedByWedges;
1257 for ( ConstVertexIHalfedgeIter vh_it = cvih_iter( vh ); vh_it.is_valid(); ++vh_it ) {
1258 const auto& widx = property( m_wedgeIndexPph, *vh_it );
1259 if ( widx.isValid() && !m_wedges.getWedge( widx ).isDeleted() ) {
1260 auto oldNormal = m_wedges.getWedgeData<Normal>( widx, m_normalsIndex );
1261 normalSharedByWedges[oldNormal].first.insert( face_handle( *vh_it ) );
1262 normalSharedByWedges[oldNormal].second.insert( widx );
1266 for (
const auto& pair : normalSharedByWedges ) {
1267 for (
const auto& fh : pair.second.first ) {
1268 auto& v = m_vertexFaceWedgesWithSameNormals[vh.idx()][fh.idx()];
1269 v.
insert( v.end(), pair.second.second.begin(), pair.second.second.end() );
1274 LOG( logDEBUG ) <<
"TopologicalMesh: load end with " << m_wedges.size() <<
" wedges ";
1277template <
typename T>
1279 unsigned int vindex,
1282 for (
auto handle : attrHandleVec ) {
1283 auto& attr = mesh.template getAttrib<T>( handle );
1289 unsigned int vindex,
1295 copyAttribToWedgeData( mesh, vindex, wprop_float, &wd->m_floatAttrib );
1296 copyAttribToWedgeData( mesh, vindex, wprop_vec2, &wd->m_vector2Attrib );
1297 copyAttribToWedgeData( mesh, vindex, wprop_vec3, &wd->m_vector3Attrib );
1298 copyAttribToWedgeData( mesh, vindex, wprop_vec4, &wd->m_vector4Attrib );
1302 if ( !has_halfedge_normals() ) {
1303 LOG( logERROR ) <<
"TopologicalMesh has no normals, nothing set";
1306 for ( VertexIHalfedgeIter vih_it = vih_iter( vh ); vih_it.is_valid(); ++vih_it ) {
1307 auto wd =
getWedgeData( property( getWedgeIndexPph(), *vih_it ) );
1309 m_wedges.setWedgeAttrib( wd, getAttribName( MeshAttrib::VERTEX_NORMAL ), normal( vh ) );
1316 FaceHandle fh )
const {
1317 for ( ConstVertexIHalfedgeIter vih_it = cvih_iter( vh ); vih_it.is_valid(); ++vih_it ) {
1318 if ( face_handle( *vih_it ) == fh ) {
return *vih_it; }
1320 CORE_ASSERT(
false,
"vh is not a vertex of face fh" );
1321 return HalfedgeHandle();
1324inline const OpenMesh::HPropHandleT<TopologicalMesh::Index>&
1326 return m_inputTriangleMeshIndexPph;
1329inline const OpenMesh::HPropHandleT<TopologicalMesh::Index>&
1331 return m_outputTriangleMeshIndexPph;
1338 for ( ConstVertexIHalfedgeIter vh_it = cvih_iter( vh ); vh_it.is_valid(); ++vh_it ) {
1339 auto widx = property( m_wedgeIndexPph, *vh_it );
1340 if ( widx.isValid() && !m_wedges.getWedge( widx ).isDeleted() ) ret.
insert( widx );
1345inline TopologicalMesh::WedgeIndex
1347 return property( getWedgeIndexPph(), heh );
1351 return m_wedges.getWedgeRefCount( idx );
1354template <
typename T>
1358 return setWedgeAttrib( idx, name, value );
1361template <
typename T>
1362inline bool TopologicalMesh::setWedgeAttrib(
const TopologicalMesh::WedgeIndex& idx,
1365 return m_wedges.setWedgeAttrib( idx, name, value );
1370 m_wedges.setWedgeData( widx, wedge );
1375 return m_wedges.getWedgeData( idx );
1378template <
typename T>
1381 return getWedgeAttrib<T>( idx, name );
1384template <
typename T>
1385inline const T& TopologicalMesh::getWedgeAttrib(
const TopologicalMesh::WedgeIndex& idx,
1387 return m_wedges.getWedgeData<T>( idx, name );
1392 m_wedges.del( property( getWedgeIndexPph(), he ) );
1393 auto index = m_wedges.add( wd );
1394 property( getWedgeIndexPph(), he ) = index;
1399 const WedgeIndex& widx ) {
1400 m_wedges.del( property( getWedgeIndexPph(), he ) );
1401 property( getWedgeIndexPph(), he ) = m_wedges.newReference( widx );
1405 for (
auto itr = vertices_begin(), stop = vertices_end(); itr != stop; ++itr ) {
1411 for (
auto itr = vih_iter( vh ); itr.is_valid(); ++itr ) {
1413 if ( !is_boundary( *itr ) )
1419 return m_wedges.m_vector4AttribNames;
1422 return m_wedges.m_vector3AttribNames;
1425 return m_wedges.m_vector2AttribNames;
1428 return m_wedges.m_floatAttribNames;
1439 return property( m_wedgeIndexPph, heh0 ) !=
1440 property( m_wedgeIndexPph,
1441 prev_halfedge_handle( opposite_halfedge_handle( heh0 ) ) ) ||
1442 property( m_wedgeIndexPph, heh1 ) !=
1443 property( m_wedgeIndexPph,
1444 prev_halfedge_handle( opposite_halfedge_handle( heh1 ) ) );
1447inline const OpenMesh::HPropHandleT<TopologicalMesh::WedgeIndex>&
1448TopologicalMesh::getWedgeIndexPph()
const {
1449 return m_wedgeIndexPph;
const NormalAttribHandle::Container & normals() const
Access the vertices normals.
const PointAttribHandle::Container & vertices() const
Access the vertices positions.
Utils::AttribManager & vertexAttribs()
A single layer MultiIndexedGeometry.
AbstractGeometry with per-vertex attributes and layers of indices. Each layer represents a different ...
const GeometryIndexLayerBase & getLayer(const LayerKeyType &layerKey) const
Read-only access to a layer.
WedgeIndex getWedgeIndex(OpenMesh::HalfedgeHandle heh) const
void replaceWedgeIndex(OpenMesh::HalfedgeHandle he, const WedgeIndex &widx)
WedgeIndex replaceWedge(OpenMesh::HalfedgeHandle he, const WedgeData &wd)
bool isFeatureEdge(const EdgeHandle &eh) const
void propagate_normal_to_wedges(VertexHandle vh)
bool isFeatureVertex(const VertexHandle &vh) const
true if more than one wedge arount vertex vh, false if only one wedge
void setWedgeData(WedgeIndex widx, const WedgeData &wd)
std::set< WedgeIndex > getVertexWedges(OpenMesh::VertexHandle vh) const
WedgeData newWedgeData() const
const OpenMesh::HPropHandleT< Index > & getInputTriangleMeshIndexPropHandle() const
unsigned int getWedgeRefCount(const WedgeIndex &idx) const
const OpenMesh::HPropHandleT< Index > & getOutputTriangleMeshIndexPropHandle() const
const WedgeData & getWedgeData(const WedgeIndex &idx) const
WedgeData newWedgeData(HalfedgeHandle he) const
HalfedgeHandle halfedge_handle(VertexHandle vh, FaceHandle fh) const
An attrib handle basically store an Index and a name.
void for_each_attrib(const F &func) const
This class implements ContainerIntrospectionInterface for AlignedStdVector.
Quaternion add(const Quaternion &q1, const Quaternion &q2)
Returns the sum of two quaternions.
This namespace contains everything "low level", related to data, datastuctures, and computation.
@ Geometry
"Geometry" render objects are those loaded using Radium::IO and generated by GeometrySystem
hepler function to manage enum as underlying types in VariableSet
Index layer for polygonal mesh.
Index layer for triangle mesh.