MeshLib C++ Docs
Loading...
Searching...
No Matches
MRPolylineTopology.h
Go to the documentation of this file.
1#pragma once
2
3#include "MRMeshFwd.h"
4#include "MRVector.h"
5#include "MRId.h"
7#include "MRBitSet.h"
8
9namespace MR
10{
13
14
18{
19public:
23 template<typename T, typename F1, typename F2>
24 void buildFromContours( const std::vector<std::vector<T>> & contours, F1 && reservePoints, F2 && addPoint );
25
28 MRMESH_API void buildOpenLines( const std::vector<VertId> & comp2firstVert );
29
31 template<typename T, typename F>
32 [[nodiscard]] std::vector<std::vector<T>> convertToContours( F&& getPoint, std::vector<std::vector<VertId>>* vertMap = nullptr ) const;
33
35 [[nodiscard]] MRMESH_API EdgeId makeEdge();
36
45 MRMESH_API EdgeId makeEdge( VertId a, VertId b, EdgeId e = {} );
46
49 MRMESH_API int makeEdges( const Edges & edges );
50
52 [[nodiscard]] MRMESH_API bool isLoneEdge( EdgeId a ) const;
53
55 [[nodiscard]] MRMESH_API UndirectedEdgeId lastNotLoneUndirectedEdge() const;
56
58 [[nodiscard]] EdgeId lastNotLoneEdge() const { auto ue = lastNotLoneUndirectedEdge(); return ue ? EdgeId( ue ) + 1 : EdgeId(); }
59
61 [[nodiscard]] size_t edgeSize() const { return edges_.size(); }
62
64 [[nodiscard]] size_t edgeCapacity() const { return edges_.capacity(); }
65
67 [[nodiscard]] size_t undirectedEdgeSize() const { return edges_.size() >> 1; }
68
70 [[nodiscard]] size_t undirectedEdgeCapacity() const { return edges_.capacity() >> 1; }
71
73 [[nodiscard]] MRMESH_API size_t computeNotLoneUndirectedEdges() const;
74
76 void edgeReserve( size_t newCapacity ) { edges_.reserve( newCapacity ); }
77
79 [[nodiscard]] bool hasEdge( EdgeId e ) const { assert( e.valid() ); return e < (int)edgeSize() && !isLoneEdge( e ); }
80
82 MRMESH_API void deleteEdge( UndirectedEdgeId ue );
83
85 MRMESH_API void deleteEdges( const UndirectedEdgeBitSet & es );
86
88 [[nodiscard]] MRMESH_API size_t heapBytes() const;
89
94 MRMESH_API void splice( EdgeId a, EdgeId b );
95
97 [[nodiscard]] EdgeId next( EdgeId he ) const { assert(he.valid()); return edges_[he].next; }
98
100 [[nodiscard]] VertId org( EdgeId he ) const { assert(he.valid()); return edges_[he].org; }
101
103 [[nodiscard]] VertId dest( EdgeId he ) const { assert(he.valid()); return edges_[he.sym()].org; }
104
107 MRMESH_API void setOrg( EdgeId a, VertId v );
108
110 [[nodiscard]] const Vector<EdgeId, VertId> & edgePerVertex() const { return edgePerVertex_; }
111
114
116 [[nodiscard]] EdgeId edgeWithOrg( VertId a ) const { assert( a.valid() ); return a < int(edgePerVertex_.size()) && edgePerVertex_[a].valid() ? edgePerVertex_[a] : EdgeId(); }
117
119 [[nodiscard]] bool hasVert( VertId a ) const { return validVerts_.test( a ); }
120
122 [[nodiscard]] MRMESH_API int getVertDegree( VertId a ) const;
123
125 [[nodiscard]] int numValidVerts() const { return numValidVerts_; }
126
128 [[nodiscard]] MRMESH_API VertId lastValidVert() const;
129
131 [[nodiscard]] VertId addVertId() { edgePerVertex_.push_back( {} ); validVerts_.push_back( false ); return VertId( (int)edgePerVertex_.size() - 1 ); }
132
134 MRMESH_API void vertResize( size_t newSize );
135
137 MRMESH_API void vertResizeWithReserve( size_t newSize );
138
140 void vertReserve( size_t newCapacity ) { edgePerVertex_.reserve( newCapacity ); validVerts_.reserve( newCapacity ); }
141
143 [[nodiscard]] size_t vertSize() const { return edgePerVertex_.size(); }
144
146 [[nodiscard]] size_t vertCapacity() const { return edgePerVertex_.capacity(); }
147
149 [[nodiscard]] const VertBitSet & getValidVerts() const { return validVerts_; }
150
152 [[nodiscard]] const VertBitSet & getVertIds( const VertBitSet * region ) const { return region ? *region : validVerts_; }
153
155 [[nodiscard]] MRMESH_API EdgeId findEdge( VertId o, VertId d ) const;
156
158 [[nodiscard]] MRMESH_API VertBitSet getPathVertices( const EdgePath & path ) const;
159
164 MRMESH_API EdgeId splitEdge( EdgeId e );
165
169 MRMESH_API EdgeId makePolyline( const VertId * vs, size_t num );
170
174 VertMap * outVmap = nullptr, WholeEdgeMap * outEmap = nullptr );
175
177 MRMESH_API void addPartByMask( const PolylineTopology& from, const UndirectedEdgeBitSet& mask,
178 VertMap* outVmap = nullptr, EdgeMap* outEmap = nullptr );
179
182 MRMESH_API void pack( VertMap * outVmap = nullptr, WholeEdgeMap * outEmap = nullptr );
183
185 MRMESH_API void write( std::ostream & s ) const;
186
188 MRMESH_API bool read( std::istream & s );
189
191 [[nodiscard]] bool operator ==( const PolylineTopology & b ) const { return edges_ == b.edges_; }
192 [[nodiscard]] bool operator !=( const PolylineTopology & b ) const { return edges_ != b.edges_; }
193
195 [[nodiscard]] MRMESH_API bool isConsistentlyOriented() const;
196
199
202
205
207 [[nodiscard]] MRMESH_API bool isClosed() const;
208
209private:
211 void setOrg_( EdgeId a, VertId v );
212
214 struct HalfEdgeRecord
215 {
216 EdgeId next;
217 VertId org;
218
219 bool operator ==( const HalfEdgeRecord& b ) const
220 {
221 return next == b.next && org == b.org;
222 }
223 HalfEdgeRecord() noexcept = default;
224 explicit HalfEdgeRecord( NoInit ) noexcept : next( noInit ), org( noInit ) {}
225 };
226
229
231 Vector<EdgeId, VertId> edgePerVertex_;
232 VertBitSet validVerts_;
233 int numValidVerts_ = 0;
234};
235
236template<typename T, typename F1, typename F2>
237void PolylineTopology::buildFromContours( const std::vector<std::vector<T>> & contours, F1 && reservePoints, F2 && addPoint )
238{
239 *this = {};
240 size_t size = 0;
241 std::vector<bool> closed;
242 closed.reserve( contours.size() );
243 int numClosed = 0;
244 for ( const auto& c : contours )
245 {
246 const auto csize = c.size();
247 if ( csize > 2 )
248 {
249 closed.push_back( c.front() == c.back() );
250 }
251 else
252 {
253 closed.push_back( false );
254 }
255 if ( csize < 2 )
256 continue;
257 size += c.size();
258 if ( closed.back() )
259 ++numClosed;
260 }
261
262 reservePoints( size - numClosed );
263 vertResize( size - numClosed );
264
265 for ( int i = 0; i < contours.size(); ++i )
266 {
267 const auto& c = contours[i];
268 if ( c.size() < 2 )
269 continue;
270 const auto e0 = makeEdge();
271 const auto v0 = addPoint( c[0] );
272 setOrg( e0, v0 );
273 auto e = e0;
274 for ( int j = 1; j + 1 < c.size(); ++j )
275 {
276 const auto ej = makeEdge();
277 splice( ej, e.sym() );
278 const auto vj = addPoint( c[j] );
279 setOrg( ej, vj );
280 e = ej;
281 }
282 if ( closed[i] )
283 {
284 splice( e0, e.sym() );
285 }
286 else
287 {
288 const auto vx = addPoint( c.back() );
289 setOrg( e.sym(), vx );
290 }
291 }
292 assert( isConsistentlyOriented() );
293 assert( edgePerVertex_.size() == size - numClosed );
294}
295
296template<typename T, typename F>
297std::vector<std::vector<T>> PolylineTopology::convertToContours( F&& getPoint, std::vector<std::vector<VertId>>* vertMap ) const
298{
299 std::vector<std::vector<T>> res;
300
301 UndirectedEdgeBitSet linesUsed;
302 linesUsed.autoResizeSet( UndirectedEdgeId{ undirectedEdgeSize() } );
303 linesUsed.flip();
304 for ( EdgeId e0 : linesUsed )
305 {
306 if ( isLoneEdge( e0 ) )
307 continue;
308
309 EdgeId curLine = e0;
310 while ( curLine != next( curLine ) )
311 {
312 curLine = next( curLine ).sym();
313 if ( curLine == e0 )
314 break;
315 }
316
317 linesUsed.set( curLine.undirected(), false );
318
319 EdgeId e = curLine;
320 std::vector<T> cont;
321 std::vector<VertId> map;
322 auto orgV = org( e );
323 cont.push_back( getPoint( orgV ) );
324 if ( vertMap )
325 map.push_back( orgV );
326 for ( ;; )
327 {
328 e = e.sym();
329 cont.push_back( getPoint( org( e ) ) );
330 e = next( e );
331 if ( !linesUsed.test_set( e.undirected(), false ) )
332 break;
333 }
334 res.push_back( std::move( cont ) );
335 if ( vertMap )
336 vertMap->push_back( std::move( map ) );
337 }
338
339 return res;
340}
341
344{
347
350 EdgeId start( VertId v )
351 {
352 assert( !e0_ && !eLast_ );
353 e0_ = eLast_ = topology.makeEdge();
354 topology.setOrg( e0_, v );
355 return e0_;
356 }
357
359 EdgeId proceed( VertId v )
360 {
361 assert( eLast_ );
362 const auto ej = topology.makeEdge();
363 topology.splice( ej, eLast_.sym() );
364 topology.setOrg( ej, v );
365 return eLast_ = ej;
366 }
367
368 void close()
369 {
370 assert( e0_ && eLast_ );
371 topology.splice( e0_, eLast_.sym() );
372 e0_ = eLast_ = {};
373 }
374
375 void finishOpen( VertId v )
376 {
377 assert( eLast_ );
378 topology.setOrg( eLast_.sym(), v );
379 e0_ = eLast_ = {};
380 }
381
382private:
383 EdgeId e0_, eLast_;
384};
385
386}
#define MRMESH_API
Definition MRMeshFwd.h:80
Definition MRPolylineTopology.h:18
std::vector<T>-like container that requires specific indexing type,
Definition MRVector.h:23
EdgeId makeEdge()
creates an edge not associated with any vertex
size_t undirectedEdgeSize() const
returns the number of undirected edges (pairs of half-edges) including lone ones
Definition MRPolylineTopology.h:67
void deleteEdges(const UndirectedEdgeBitSet &es)
calls deleteEdge for every set bit
EdgeId findEdge(VertId o, VertId d) const
finds and returns edge from o to d in the mesh; returns invalid edge otherwise
EdgeId makePolyline(const VertId *vs, size_t num)
bool checkValidity() const
verifies that all internal data structures are valid
void pack(VertMap *outVmap=nullptr, WholeEdgeMap *outEmap=nullptr)
Vector< VertId, EdgeId > getOrgs() const
for all edges this vector contains its origin
void vertReserve(size_t newCapacity)
sets the capacity of vertices vector
Definition MRPolylineTopology.h:140
Edges
Definition MRObjectMeshHolder.h:19
bool hasVert(VertId a) const
returns true if given vertex is present in the mesh
Definition MRPolylineTopology.h:119
EdgeId edgeWithOrg(VertId a) const
returns valid edge if given vertex is present in the mesh
Definition MRPolylineTopology.h:116
EdgeId next(EdgeId he) const
next (counter clock wise) half-edge in the origin ring
Definition MRPolylineTopology.h:97
ImVec2 size(const ViewportRectangle &rect)
Definition MRViewport.h:32
EdgeId lastNotLoneEdge() const
returns last not lone edge id, or invalid id if no such edge exists
Definition MRPolylineTopology.h:58
bool isLoneEdge(EdgeId a) const
checks whether the edge is disconnected from all other edges and disassociated from all vertices (as ...
void addPartByMask(const PolylineTopology &from, const UndirectedEdgeBitSet &mask, VertMap *outVmap=nullptr, EdgeMap *outEmap=nullptr)
appends polyline topology (from) in addition to the current topology: creates new edges,...
VertId org
vertex at the origin of the edge
Definition MRPolylineTopology.h:217
const VertBitSet & getValidVerts() const
returns cached set of all valid vertices
Definition MRPolylineTopology.h:149
VertId lastValidVert() const
returns last valid vertex id, or invalid id if no single valid vertex exists
UndirectedEdgeId lastNotLoneUndirectedEdge() const
returns last not lone undirected edge id, or invalid id if no such edge exists
void buildOpenLines(const std::vector< VertId > &comp2firstVert)
EdgeId start(VertId v)
Definition MRPolylineTopology.h:350
void finishOpen(VertId v)
finishes the polyline adding final vertex in it
Definition MRPolylineTopology.h:375
void setOrg(EdgeId a, VertId v)
size_t heapBytes() const
returns the amount of memory this object occupies on heap
void flip()
changes the orientation of all edges: every edge e is replaced with e.sym()
int getVertDegree(VertId a) const
returns 0 if given vertex does not exist, 1 if it has one incident edge, and 2 if it has two incident...
void close()
closes the polyline
Definition MRPolylineTopology.h:368
void vertResizeWithReserve(size_t newSize)
explicitly increases the size of vertices vector, doubling the current capacity if it was not enough
size_t vertCapacity() const
returns the number of allocated vert records
Definition MRPolylineTopology.h:146
size_t edgeSize() const
returns the number of half-edge records including lone ones
Definition MRPolylineTopology.h:61
void computeValidsFromEdges()
computes numValidVerts_ and validVerts_ from edgePerVertex_
void splice(EdgeId a, EdgeId b)
size_t computeNotLoneUndirectedEdges() const
computes the number of not-lone (valid) undirected edges
PolylineTopology & topology
Definition MRPolylineTopology.h:345
const Vector< EdgeId, VertId > & edgePerVertex() const
for all valid vertices this vector contains an edge with the origin there
Definition MRPolylineTopology.h:110
VertId org(EdgeId he) const
returns origin vertex of half-edge
Definition MRPolylineTopology.h:100
void vertResize(size_t newSize)
explicitly increases the size of vertices vector
int makeEdges(const Edges &edges)
PolylineMaker(PolylineTopology &t)
Definition MRPolylineTopology.h:346
VertBitSet getPathVertices(const EdgePath &path) const
returns all vertices incident to path edges
const VertBitSet & getVertIds(const VertBitSet *region) const
if region pointer is not null then converts it in reference, otherwise returns all valid vertices in ...
Definition MRPolylineTopology.h:152
size_t vertSize() const
returns the number of vertex records including invalid ones
Definition MRPolylineTopology.h:143
bool isConsistentlyOriented() const
returns true if for each edge e: e == e.next() || e.odd() == next( e ).sym().odd()
void addPart(const PolylineTopology &from, VertMap *outVmap=nullptr, WholeEdgeMap *outEmap=nullptr)
std::vector< EdgeId > EdgePath
Definition MRMeshFwd.h:147
void edgeReserve(size_t newCapacity)
sets the capacity of half-edges vector
Definition MRPolylineTopology.h:76
constexpr NoInit noInit
Definition MRMeshFwd.h:98
void buildFromContours(const std::vector< std::vector< T > > &contours, F1 &&reservePoints, F2 &&addPoint)
Definition MRPolylineTopology.h:237
int numValidVerts() const
returns the number of valid vertices
Definition MRPolylineTopology.h:125
EdgeId next
next counter clock wise half-edge in the origin ring
Definition MRPolylineTopology.h:216
EdgeId proceed(VertId v)
Definition MRPolylineTopology.h:359
VertId dest(EdgeId he) const
returns destination vertex of half-edge
Definition MRPolylineTopology.h:103
VertId addVertId()
creates new vert-id not associated with any edge yet
Definition MRPolylineTopology.h:131
size_t edgeCapacity() const
returns the number of allocated edge records
Definition MRPolylineTopology.h:64
EdgeId makeEdge(VertId a, VertId b, EdgeId e={})
bool read(std::istream &s)
loads this from binary stream
void write(std::ostream &s) const
saves this in binary stream
bool operator==(const HalfEdgeRecord &b) const
Definition MRPolylineTopology.h:219
bool isClosed() const
returns true if the polyline does not have any holes
EdgeId splitEdge(EdgeId e)
std::vector< std::vector< T > > convertToContours(F &&getPoint, std::vector< std::vector< VertId > > *vertMap=nullptr) const
converts this topology into contours of given type using the functor returning point by its Id
Definition MRPolylineTopology.h:297
bool hasEdge(EdgeId e) const
returns true if given edge is within valid range and not-lone
Definition MRPolylineTopology.h:79
void deleteEdge(UndirectedEdgeId ue)
given edge becomes lone after the call, so it is un-spliced from connected edges, and if it was not c...
bool operator!=(const PolylineTopology &b) const
Definition MRPolylineTopology.h:192
bool operator==(const PolylineTopology &b) const
comparison via edges (all other members are considered as not important caches)
Definition MRPolylineTopology.h:191
size_t undirectedEdgeCapacity() const
returns the number of allocated undirected edges (pairs of half-edges)
Definition MRPolylineTopology.h:70
only for bindings generation
Definition MRCameraOrientationPlugin.h:8
Definition MRMeshFwd.h:97