3#include "MRPch/MRBindingMacros.h"
25 [[nodiscard]]
MRMESH_API bool isLoneEdge( EdgeId a )
const;
28 [[nodiscard]]
MRMESH_API UndirectedEdgeId lastNotLoneUndirectedEdge()
const;
31 [[nodiscard]] EdgeId lastNotLoneEdge()
const {
auto ue = lastNotLoneUndirectedEdge();
return ue ? EdgeId( ue ) + 1 : EdgeId(); }
34 MRMESH_API void excludeLoneEdges( UndirectedEdgeBitSet & edges )
const;
37 [[nodiscard]]
size_t edgeSize()
const {
return edges_.size(); }
40 [[nodiscard]]
size_t edgeCapacity()
const {
return edges_.capacity(); }
43 [[nodiscard]]
size_t undirectedEdgeSize()
const {
return edges_.size() >> 1; }
46 [[nodiscard]]
size_t undirectedEdgeCapacity()
const {
return edges_.capacity() >> 1; }
49 [[nodiscard]]
MRMESH_API size_t computeNotLoneUndirectedEdges()
const;
52 [[nodiscard]]
MRMESH_API UndirectedEdgeBitSet findNotLoneUndirectedEdges()
const;
55 void edgeReserve(
size_t newCapacity ) { edges_.reserve( newCapacity ); }
58 [[nodiscard]]
bool hasEdge( EdgeId e )
const { assert( e.valid() );
return e < (int)edgeSize() && !isLoneEdge( e ); }
61 [[nodiscard]]
MRMESH_API size_t heapBytes()
const;
80 MRMESH_API EdgeId
collapseEdge( EdgeId e,
const std::function<
void( EdgeId del, EdgeId rem )> & onEdgeDel );
84 [[nodiscard]] EdgeId next( EdgeId he )
const { assert(he.valid());
return edges_[he].next; }
87 [[nodiscard]] EdgeId prev( EdgeId he )
const { assert(he.valid());
return edges_[he].prev; }
90 [[nodiscard]] VertId org( EdgeId he )
const { assert(he.valid());
return edges_[he].org; }
93 [[nodiscard]] VertId dest( EdgeId he )
const { assert(he.valid());
return edges_[he.sym()].org; }
96 [[nodiscard]] FaceId left( EdgeId he )
const { assert(he.valid());
return edges_[he].left; }
99 [[nodiscard]] FaceId right( EdgeId he )
const { assert(he.valid());
return edges_[he.sym()].left; }
112 [[nodiscard]]
MRMESH_API bool fromSameOriginRing( EdgeId a, EdgeId b )
const;
115 [[nodiscard]]
MRMESH_API bool fromSameLeftRing( EdgeId a, EdgeId b )
const;
119 [[nodiscard]]
MRMESH_API int getOrgDegree( EdgeId a )
const;
122 [[nodiscard]]
int getVertDegree( VertId v )
const {
return getOrgDegree( edgeWithOrg( v ) ); }
125 [[nodiscard]]
MRMESH_API int getLeftDegree( EdgeId a )
const;
128 [[nodiscard]]
int getFaceDegree( FaceId f )
const {
return getLeftDegree( edgeWithLeft( f ) ); }
131 [[nodiscard]]
MRMESH_API bool isLeftTri( EdgeId a )
const;
135 void getTriVerts( FaceId f, VertId & v0, VertId & v1, VertId & v2 )
const { getLeftTriVerts( edgeWithLeft( f ), v0, v1, v2 ); }
136 MR_BIND_IGNORE
void getTriVerts( FaceId f, VertId (&v)[3] )
const { getLeftTriVerts( edgeWithLeft( f ), v ); }
137 void getTriVerts( FaceId f, ThreeVertIds & v )
const { getLeftTriVerts( edgeWithLeft( f ), v ); }
138 [[nodiscard]]
ThreeVertIds getTriVerts( FaceId f )
const {
return getLeftTriVerts( edgeWithLeft( f ) ); }
141 [[nodiscard]]
bool isTriVert( FaceId f, VertId v )
const {
auto vs = getTriVerts( f );
return v == vs[0] || v == vs[1] || v == vs[2]; }
144 [[nodiscard]]
MRMESH_API std::vector<ThreeVertIds> getAllTriVerts()
const;
148 [[nodiscard]]
MRMESH_API Triangulation getTriangulation()
const;
152 MRMESH_API void getLeftTriVerts( EdgeId a, VertId & v0, VertId & v1, VertId & v2 )
const;
153 MR_BIND_IGNORE
void getLeftTriVerts( EdgeId a, VertId (&v)[3] )
const { getLeftTriVerts( a, v[0], v[1], v[2] ); }
154 void getLeftTriVerts( EdgeId a, ThreeVertIds & v )
const { getLeftTriVerts( a, v[0], v[1], v[2] ); }
155 [[nodiscard]]
ThreeVertIds getLeftTriVerts( EdgeId a )
const {
ThreeVertIds v; getLeftTriVerts( a, v[0], v[1], v[2] );
return v; }
161 template <
typename T>
162 void forEachVertex(
const MeshTriPoint & p, T && callback )
const;
167 MRMESH_API void getLeftTriEdges( EdgeId e0, EdgeId & e1, EdgeId & e2 )
const;
171 void getTriEdges( FaceId f, EdgeId & e0, EdgeId & e1, EdgeId & e2 )
const { getLeftTriEdges( e0 = edgeWithLeft( f ), e1, e2 ); }
172 MR_BIND_IGNORE
void getTriEdges( FaceId f, EdgeId (&e)[3] )
const { getLeftTriEdges( e[0] = edgeWithLeft( f ), e[1], e[2] ); }
175 [[nodiscard]]
MRMESH_API bool isLeftQuad( EdgeId a )
const;
178 [[nodiscard]]
const Vector<EdgeId, VertId> & edgePerVertex()
const {
return edgePerVertex_; }
181 [[nodiscard]] EdgeId edgeWithOrg( VertId a )
const { assert( a.valid() );
return a < int(edgePerVertex_.size()) ? edgePerVertex_[a] : EdgeId(); }
184 [[nodiscard]]
bool hasVert( VertId a )
const { assert( updateValids_ );
return validVerts_.test( a ); }
187 [[nodiscard]]
int numValidVerts()
const { assert( updateValids_ );
return numValidVerts_; }
190 [[nodiscard]]
MRMESH_API VertId lastValidVert()
const;
193 [[nodiscard]] VertId
addVertId() { edgePerVertex_.emplace_back();
if ( updateValids_ ) { validVerts_.push_back(
false ); }
return edgePerVertex_.backId(); }
202 void vertReserve(
size_t newCapacity ) { edgePerVertex_.reserve( newCapacity );
if ( updateValids_ ) { validVerts_.
reserve( newCapacity ); } }
205 [[nodiscard]]
size_t vertSize()
const {
return edgePerVertex_.size(); }
208 [[nodiscard]]
size_t vertCapacity()
const {
return edgePerVertex_.capacity(); }
211 [[nodiscard]]
const VertBitSet & getValidVerts()
const { assert( updateValids_ );
return validVerts_; }
214 void flip( VertBitSet & vs )
const { vs = getValidVerts() - vs; }
217 [[nodiscard]]
const VertBitSet & getVertIds(
const VertBitSet * region )
const
219 assert( region || updateValids_ );
220 assert( !updateValids_ || !region || region->is_subset_of( validVerts_ ) );
221 return region ? *region : validVerts_;
226 [[nodiscard]]
const Vector<EdgeId, FaceId> & edgePerFace()
const {
return edgePerFace_; }
229 [[nodiscard]] EdgeId edgeWithLeft( FaceId a )
const { assert( a.valid() );
return a < int(edgePerFace_.size()) ? edgePerFace_[a] : EdgeId(); }
232 [[nodiscard]]
bool hasFace( FaceId a )
const { assert( updateValids_ );
return validFaces_.test( a ); }
235 [[nodiscard]]
MRMESH_API EdgeId sharedEdge( FaceId l, FaceId r )
const;
238 [[nodiscard]]
MRMESH_API EdgeId sharedVertInOrg( EdgeId a, EdgeId b )
const;
241 [[nodiscard]]
MRMESH_API EdgeId sharedVertInOrg( FaceId l, FaceId r )
const;
244 [[nodiscard]]
MRMESH_API FaceId sharedFace( EdgeId a, EdgeId b )
const;
247 [[nodiscard]]
int numValidFaces()
const { assert( updateValids_ );
return numValidFaces_; }
250 [[nodiscard]]
MRMESH_API FaceId lastValidFace()
const;
253 [[nodiscard]] FaceId
addFaceId() { edgePerFace_.emplace_back();
if ( updateValids_ ) { validFaces_.push_back(
false ); }
return edgePerFace_.backId(); }
259 MRMESH_API void deleteFaces(
const FaceBitSet & fs,
const UndirectedEdgeBitSet * keepEdges =
nullptr );
268 void faceReserve(
size_t newCapacity ) { edgePerFace_.reserve( newCapacity );
if ( updateValids_ ) { validFaces_.
reserve( newCapacity ); } }
271 [[nodiscard]]
size_t faceSize()
const {
return edgePerFace_.size(); }
274 [[nodiscard]]
size_t faceCapacity()
const {
return edgePerFace_.capacity(); }
277 [[nodiscard]]
const FaceBitSet & getValidFaces()
const { assert( updateValids_ );
return validFaces_; }
280 void flip( FaceBitSet & fs )
const { fs = getValidFaces() - fs; }
283 [[nodiscard]]
const FaceBitSet & getFaceIds(
const FaceBitSet * region )
const
285 assert( region || updateValids_ );
286 assert( !updateValids_ || !region || region->is_subset_of( validFaces_ ) );
287 return region ? *region : validFaces_;
292 [[nodiscard]]
MRMESH_API EdgeId bdEdgeSameLeft( EdgeId e,
const FaceBitSet * region =
nullptr )
const;
296 [[nodiscard]]
bool isLeftBdFace( EdgeId e,
const FaceBitSet * region =
nullptr )
const {
return contains( region, left( e ) ) && bdEdgeSameLeft( e, region ).
valid(); }
300 [[nodiscard]] EdgeId bdEdgeWithLeft( FaceId f,
const FaceBitSet * region =
nullptr )
const {
return bdEdgeSameLeft( edgeWithLeft( f ), region ); }
303 [[nodiscard]]
bool isBdFace( FaceId f,
const FaceBitSet * region =
nullptr )
const {
return isLeftBdFace( edgeWithLeft( f ), region ); }
306 [[nodiscard]]
MRMESH_API FaceBitSet findBdFaces(
const FaceBitSet * region =
nullptr )
const;
310 [[nodiscard]]
bool isLeftInRegion( EdgeId e,
const FaceBitSet * region =
nullptr )
const {
return contains( region, left( e ) ); }
313 [[nodiscard]]
bool isInnerEdge( EdgeId e,
const FaceBitSet * region =
nullptr )
const {
return isLeftInRegion( e, region ) && isLeftInRegion( e.sym(), region ); }
320 [[nodiscard]]
MRMESH_API bool isBdEdge( EdgeId e,
const FaceBitSet * region =
nullptr )
const;
323 [[nodiscard]]
MRMESH_API EdgeBitSet findLeftBdEdges(
const FaceBitSet * region =
nullptr,
const EdgeBitSet * test =
nullptr )
const;
327 [[nodiscard]]
MRMESH_API EdgeId bdEdgeSameOrigin( EdgeId e,
const FaceBitSet * region =
nullptr )
const;
330 [[nodiscard]]
bool isBdVertexInOrg( EdgeId e,
const FaceBitSet * region =
nullptr )
const {
return bdEdgeSameOrigin( e, region ).
valid(); }
334 [[nodiscard]] EdgeId bdEdgeWithOrigin( VertId v,
const FaceBitSet * region =
nullptr )
const {
return bdEdgeSameOrigin( edgeWithOrg( v ), region ); }
337 [[nodiscard]]
bool isBdVertex( VertId v,
const FaceBitSet * region =
nullptr )
const {
return isBdVertexInOrg( edgeWithOrg( v ), region ); }
340 [[nodiscard]]
MRMESH_API VertBitSet findBdVerts(
const FaceBitSet * region =
nullptr,
const VertBitSet * test =
nullptr )
const;
343 [[nodiscard]]
MRMESH_API bool isInnerOrBdVertex( VertId v,
const FaceBitSet * region =
nullptr )
const;
346 [[nodiscard]]
bool isLeftBdEdge( EdgeId e,
const FaceBitSet * region =
nullptr )
const {
return region ? ( isLeftInRegion( e, region ) && !isLeftInRegion( e.sym(), region ) ) : !right( e ); }
349 [[nodiscard]]
bool isInnerOrBdEdge( EdgeId e,
const FaceBitSet * region =
nullptr )
const {
return isLeftInRegion( e, region ) || isLeftInRegion( e.sym(), region ); }
352 [[nodiscard]]
MRMESH_API EdgeId nextLeftBd( EdgeId e,
const FaceBitSet * region =
nullptr )
const;
355 [[nodiscard]]
MRMESH_API EdgeId prevLeftBd( EdgeId e,
const FaceBitSet * region =
nullptr )
const;
359 [[nodiscard]]
MRMESH_API EdgeId findEdge( VertId o, VertId d )
const;
362 [[nodiscard]]
MRMESH_API bool isClosed(
const FaceBitSet * region =
nullptr )
const;
366 [[nodiscard]]
MRMESH_API std::vector<EdgeId> findHoleRepresentiveEdges(
const FaceBitSet * region =
nullptr )
const;
370 [[nodiscard]]
MRMESH_API int findNumHoles( EdgeBitSet * holeRepresentativeEdges =
nullptr )
const;
377 [[nodiscard]]
MRMESH_API std::vector<EdgeLoop> getLeftRings(
const std::vector<EdgeId> & es )
const;
380 [[nodiscard]] [[deprecated(
"Use findLeftBdEdges")]]
MRMESH_API MR_BIND_IGNORE EdgeBitSet findBoundaryEdges()
const;
384 [[nodiscard]] [[deprecated(
"Use findBdFaces")]]
MRMESH_API MR_BIND_IGNORE FaceBitSet findBoundaryFaces(
const FaceBitSet * region =
nullptr )
const;
388 [[nodiscard]] [[deprecated(
"Use findBdVerts")]]
MRMESH_API MR_BIND_IGNORE VertBitSet findBoundaryVerts(
const VertBitSet * region =
nullptr )
const;
392 [[nodiscard]]
MRMESH_API VertBitSet getPathVertices(
const EdgePath & path )
const;
395 [[nodiscard]]
MRMESH_API FaceBitSet getPathLeftFaces(
const EdgePath & path )
const;
398 [[nodiscard]]
MRMESH_API FaceBitSet getPathRightFaces(
const EdgePath & path )
const;
408 void flipEdgesIn( EdgeId e0, T && flipNeeded );
413 void flipEdgesIn( VertId v, T && flipNeeded ) { flipEdgesIn( edgeWithOrg( v ), std::forward<T>( flipNeeded ) ); }
418 void flipEdgesOut( EdgeId e0, T && flipNeeded );
423 void flipEdgesOut( VertId v, T && flipNeeded ) { flipEdgesOut( edgeWithOrg( v ), std::forward<T>( flipNeeded ) ); }
433 MRMESH_API EdgeId
splitEdge( EdgeId e, FaceBitSet * region =
nullptr, FaceHashMap * new2Old =
nullptr );
438 MRMESH_API VertId
splitFace( FaceId f, FaceBitSet * region =
nullptr, FaceHashMap * new2Old =
nullptr );
452 FaceMap * outFmap =
nullptr, VertMap * outVmap =
nullptr, WholeEdgeMap * outEmap =
nullptr,
453 bool rearrangeTriangles =
false );
458 MR_BIND_IGNORE
void addPartByMask(
const MeshTopology & from,
const FaceBitSet & fromFaces,
const PartMapping & map = {} )
466 const std::vector<EdgePath> & thisContours = {},
const std::vector<EdgePath> & fromContours = {},
467 const PartMapping & map = {} );
471 const std::vector<EdgePath> & thisContours = {},
const std::vector<EdgePath> & fromContours = {},
481 MRMESH_API void pack( FaceMap * outFmap =
nullptr, VertMap * outVmap =
nullptr, WholeEdgeMap * outEmap =
nullptr,
bool rearrangeTriangles =
false );
494 MRMESH_API void write( std::ostream & s )
const;
498 MRMESH_API Expected<void>
read( std::istream& s, ProgressCallback callback = {} );
512 const FaceMap & fmap,
const VertMap & vmap );
524 [[nodiscard]]
bool updatingValids()
const {
return updateValids_; }
535 MRMESH_API bool checkValidity( ProgressCallback cb = {},
bool allVerts = true )
const;
538 friend class MeshTopologyDiff;
546 void setOrg_( EdgeId a, VertId v );
552 void setLeft_( EdgeId a, FaceId f );
558 struct alignas( 16 ) HalfEdgeRecord
565 bool operator ==(
const HalfEdgeRecord& b )
const
567 return next == b.next && prev == b.prev && org == b.org && left == b.left;
569 HalfEdgeRecord() noexcept = default;
570 explicit HalfEdgeRecord( NoInit ) noexcept : next( noInit ), prev( noInit ), org( noInit ), left( noInit ) {}
572 static_assert(
sizeof( HalfEdgeRecord ) == 16 );
575 template<
typename FM,
typename VM,
typename WEM>
576 void translateNoFlip_( HalfEdgeRecord & r,
const FM & fmap,
const VM & vmap,
const WEM & emap )
const;
577 template<
typename FM,
typename VM,
typename WEM>
578 void translate_( HalfEdgeRecord & r, HalfEdgeRecord & rsym,
579 const FM & fmap,
const VM & vmap,
const WEM & emap,
bool flipOrientation )
const;
582 Vector<HalfEdgeRecord, EdgeId> edges_;
585 Vector<EdgeId, VertId> edgePerVertex_;
586 VertBitSet validVerts_;
589 Vector<EdgeId, FaceId> edgePerFace_;
590 FaceBitSet validFaces_;
592 int numValidVerts_ = 0;
593 int numValidFaces_ = 0;
595 bool updateValids_ =
true;
599void MeshTopology::forEachVertex(
const MeshTriPoint & p, T && callback )
const
601 if (
auto v = p.inVertex( *
this ) )
606 if (
auto e = p.onEdge( *
this ) )
608 callback( org( e.e ) );
609 callback( dest( e.e ) );
614 getLeftTriVerts( p.e, v );
615 for (
int i = 0; i < 3; ++i )
620void MeshTopology::flipEdgesIn(
const EdgeId e0, T && flipNeeded )
625 auto testEdge = prev( e.sym() );
626 if ( left( testEdge ) && right( testEdge ) && flipNeeded( testEdge ) )
638void MeshTopology::flipEdgesOut( EdgeId e0, T && flipNeeded )
643 if ( left( e ) && right( e ) && flipNeeded( e ) )
659template<
typename T,
typename I>
665 const auto& mData = map.
b.
data();
666 const auto sz = std::min( oldVector.
size(), map.
b.
size() );
667 for ( I i = I(0); i < sz; ++i)
671 newVector[newV] = oldVector[i];
#define MRMESH_API
Definition MRMeshFwd.h:80
auto size() const
Definition MRBuffer.h:66
auto data()
Definition MRBuffer.h:97
unsafe void reserve(ulong numBits)
unsafe void deleteFace(MR.FaceId f, MR.Const_UndirectedEdgeBitSet? keepEdges=null)
unsafe void splice(MR.EdgeId a, MR.EdgeId b)
unsafe MR.FaceId addFaceId()
unsafe void setLeft(MR.EdgeId a, MR.FaceId f)
unsafe void vertResizeWithReserve(ulong newSize)
unsafe void packMinMem(MR.Const_PackMapping map)
unsafe void flipEdge(MR.EdgeId e)
unsafe void rotateTriangles()
unsafe void vertResize(ulong newSize)
unsafe void resizeBeforeParallelAdd(ulong edgeSize, ulong vertSize, ulong faceSize)
unsafe void faceResizeWithReserve(ulong newSize)
unsafe void edgeReserve(ulong newCapacity)
unsafe bool buildGridMesh(MR.Const_GridSettings settings, MR.Std._ByValue_Function_BoolFuncFromFloat? cb=null)
unsafe MR.EdgeId collapseEdge(MR.EdgeId e, MR.Std.Const_Function_VoidFuncFromMREdgeIdMREdgeId onEdgeDel)
unsafe void addPartByMask(MR.Const_MeshTopology from, MR.Const_FaceBitSet? fromFaces, MR.Const_PartMapping? map=null)
unsafe void shrinkToFit()
unsafe void deleteFaces(MR.Const_FaceBitSet fs, MR.Const_UndirectedEdgeBitSet? keepEdges=null)
unsafe bool computeValidsFromEdges(MR.Std._ByValue_Function_BoolFuncFromFloat? cb=null)
unsafe void flipOrientation(MR.Const_UndirectedEdgeBitSet? fullComponents=null)
unsafe MR.VertId addVertId()
unsafe void preferEdges(MR.Const_UndirectedEdgeBitSet stableEdges)
unsafe void read(MR.Std.Istream s, MR.Std._ByValue_Function_BoolFuncFromFloat? callback=null)
unsafe void vertReserve(ulong newCapacity)
unsafe MR.EdgeId splitEdge(MR.EdgeId e, MR.FaceBitSet? region=null, MR.Phmap.FlatHashMap_MRFaceId_MRFaceId? new2Old=null)
unsafe void faceReserve(ulong newCapacity)
unsafe void addPackedPart(MR.Const_MeshTopology from, MR.EdgeId toEdgeId, MR.Const_FaceMap fmap, MR.Const_VertMap vmap)
unsafe void addPart(MR.Const_MeshTopology from, MR.Const_PartMapping? map=null, bool? rearrangeTriangles=null)
unsafe void stopUpdatingValids()
unsafe void setOrg(MR.EdgeId a, MR.VertId v)
unsafe MR.VertId splitFace(MR.FaceId f, MR.FaceBitSet? region=null, MR.Phmap.FlatHashMap_MRFaceId_MRFaceId? new2Old=null)
unsafe void faceResize(ulong newSize)
unsafe MR.EdgeId makeEdge()
unsafe void pack(MR.FaceMap? outFmap=null, MR.VertMap? outVmap=null, MR.WholeEdgeMap? outEmap=null, bool? rearrangeTriangles=null)
std::vector<T>-like container that requires specific indexing type,
Definition MRVector.h:19
std::size_t size() const
Definition MRVector.h:51
void resize(size_t newSize) MR_REQUIRES_IF_SUPPORTED(sizeof(T)>0 &&std
Definition MRVector.h:53
unsafe void reserve(ulong numBits)
bool contains(const TypedBitSet< I > *bitset, I id)
Definition MRMesh/MRBitSet.h:326
Definition MRCameraOrientationPlugin.h:8
Vector< T, I > rearrangeVectorByMap(const Vector< T, I > &oldVector, const BMap< I, I > &map)
Definition MRMesh/MRMeshTopology.h:660
flat map: I -> T
Definition MRBuffer.h:143
Buffer< T, I > b
Definition MRBuffer.h:144
size_t tsize
target size, all values inside b must be less than this value
Definition MRBuffer.h:145
readonly unsafe bool valid()