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"
6// for template implementation:
7#include "MRBitSet.h"
8
9namespace MR
10{
11
14class PolylineTopology
15{
16public:
20 template<typename T, typename F1, typename F2>
21 void buildFromContours( const std::vector<std::vector<T>> & contours, F1 && reservePoints, F2 && addPoint );
22
25 MRMESH_API void buildOpenLines( const std::vector<VertId> & comp2firstVert );
26
28 template<typename T, typename F>
29 [[nodiscard]] std::vector<std::vector<T>> convertToContours( F&& getPoint, std::vector<std::vector<VertId>>* vertMap = nullptr ) const;
30
32 [[nodiscard]] MRMESH_API EdgeId makeEdge();
33
42 MRMESH_API EdgeId makeEdge( VertId a, VertId b, EdgeId e = {} );
43
46 MRMESH_API int makeEdges( const Edges & edges );
47
49 [[nodiscard]] MRMESH_API bool isLoneEdge( EdgeId a ) const;
50
52 [[nodiscard]] MRMESH_API UndirectedEdgeId lastNotLoneUndirectedEdge() const;
53
55 [[nodiscard]] EdgeId lastNotLoneEdge() const { auto ue = lastNotLoneUndirectedEdge(); return ue ? EdgeId( ue ) + 1 : EdgeId(); }
56
58 [[nodiscard]] size_t edgeSize() const { return edges_.size(); }
59
61 [[nodiscard]] size_t edgeCapacity() const { return edges_.capacity(); }
62
64 [[nodiscard]] size_t undirectedEdgeSize() const { return edges_.size() >> 1; }
65
67 [[nodiscard]] size_t undirectedEdgeCapacity() const { return edges_.capacity() >> 1; }
68
70 [[nodiscard]] MRMESH_API size_t computeNotLoneUndirectedEdges() const;
71
73 void edgeReserve( size_t newCapacity ) { edges_.reserve( newCapacity ); }
74
76 [[nodiscard]] bool hasEdge( EdgeId e ) const { assert( e.valid() ); return e < (int)edgeSize() && !isLoneEdge( e ); }
77
79 MRMESH_API void deleteEdge( UndirectedEdgeId ue );
80
82 MRMESH_API void deleteEdges( const UndirectedEdgeBitSet & es );
83
85 [[nodiscard]] MRMESH_API size_t heapBytes() const;
86
91 MRMESH_API void splice( EdgeId a, EdgeId b );
92
94 [[nodiscard]] EdgeId next( EdgeId he ) const { assert(he.valid()); return edges_[he].next; }
95
97 [[nodiscard]] VertId org( EdgeId he ) const { assert(he.valid()); return edges_[he].org; }
98
100 [[nodiscard]] VertId dest( EdgeId he ) const { assert(he.valid()); return edges_[he.sym()].org; }
101
104 MRMESH_API void setOrg( EdgeId a, VertId v );
105
107 [[nodiscard]] const Vector<EdgeId, VertId> & edgePerVertex() const { return edgePerVertex_; }
108
110 [[nodiscard]] MRMESH_API Vector<VertId, EdgeId> getOrgs() const;
111
113 [[nodiscard]] EdgeId edgeWithOrg( VertId a ) const { assert( a.valid() ); return a < int(edgePerVertex_.size()) && edgePerVertex_[a].valid() ? edgePerVertex_[a] : EdgeId(); }
114
116 [[nodiscard]] bool hasVert( VertId a ) const { return validVerts_.test( a ); }
117
119 [[nodiscard]] MRMESH_API int getVertDegree( VertId a ) const;
120
122 [[nodiscard]] int numValidVerts() const { return numValidVerts_; }
123
125 [[nodiscard]] MRMESH_API VertId lastValidVert() const;
126
128 [[nodiscard]] VertId addVertId() { edgePerVertex_.push_back( {} ); validVerts_.push_back( false ); return VertId( (int)edgePerVertex_.size() - 1 ); }
129
131 MRMESH_API void vertResize( size_t newSize );
132
134 MRMESH_API void vertResizeWithReserve( size_t newSize );
135
137 void vertReserve( size_t newCapacity ) { edgePerVertex_.reserve( newCapacity ); validVerts_.reserve( newCapacity ); }
138
140 [[nodiscard]] size_t vertSize() const { return edgePerVertex_.size(); }
141
143 [[nodiscard]] size_t vertCapacity() const { return edgePerVertex_.capacity(); }
144
146 [[nodiscard]] const VertBitSet & getValidVerts() const { return validVerts_; }
147
149 [[nodiscard]] const VertBitSet & getVertIds( const VertBitSet * region ) const { return region ? *region : validVerts_; }
150
152 [[nodiscard]] MRMESH_API EdgeId findEdge( VertId o, VertId d ) const;
153
155 [[nodiscard]] MRMESH_API VertBitSet getPathVertices( const EdgePath & path ) const;
156
161 MRMESH_API EdgeId splitEdge( EdgeId e );
162
166 MRMESH_API EdgeId makePolyline( const VertId * vs, size_t num );
167
170 MRMESH_API void addPart( const PolylineTopology & from,
171 VertMap * outVmap = nullptr, WholeEdgeMap * outEmap = nullptr );
172
174 MRMESH_API void addPartByMask( const PolylineTopology& from, const UndirectedEdgeBitSet& mask,
175 VertMap* outVmap = nullptr, EdgeMap* outEmap = nullptr );
176
179 MRMESH_API void pack( VertMap * outVmap = nullptr, WholeEdgeMap * outEmap = nullptr );
180
182 MRMESH_API void write( std::ostream & s ) const;
183
185 MRMESH_API bool read( std::istream & s );
186
188 [[nodiscard]] bool operator ==( const PolylineTopology & b ) const { return edges_ == b.edges_; }
189 [[nodiscard]] bool operator !=( const PolylineTopology & b ) const { return edges_ != b.edges_; }
190
192 [[nodiscard]] MRMESH_API bool isConsistentlyOriented() const;
193
195 MRMESH_API void flip();
196
198 MRMESH_API bool checkValidity() const;
199
202
204 [[nodiscard]] MRMESH_API bool isClosed() const;
205
206private:
208 void setOrg_( EdgeId a, VertId v );
209
211 struct HalfEdgeRecord
212 {
213 EdgeId next;
214 VertId org;
215
216 bool operator ==( const HalfEdgeRecord& b ) const
217 {
218 return next == b.next && org == b.org;
219 }
220 HalfEdgeRecord() noexcept = default;
221 explicit HalfEdgeRecord( NoInit ) noexcept : next( noInit ), org( noInit ) {}
222 };
223
225 Vector<HalfEdgeRecord, EdgeId> edges_;
226
228 Vector<EdgeId, VertId> edgePerVertex_;
229 VertBitSet validVerts_;
230 int numValidVerts_ = 0;
231};
232
233template<typename T, typename F1, typename F2>
234void PolylineTopology::buildFromContours( const std::vector<std::vector<T>> & contours, F1 && reservePoints, F2 && addPoint )
235{
236 *this = {};
237 size_t size = 0;
238 std::vector<bool> closed;
239 closed.reserve( contours.size() );
240 int numClosed = 0;
241 for ( const auto& c : contours )
242 {
243 const auto csize = c.size();
244 if ( csize > 2 )
245 {
246 closed.push_back( c.front() == c.back() );
247 }
248 else
249 {
250 closed.push_back( false );
251 }
252 if ( csize < 2 )
253 continue; // ignore contours with 0 or 1 points because of no edges in them
254 size += c.size();
255 if ( closed.back() )
256 ++numClosed;
257 }
258
259 reservePoints( size - numClosed );
260 vertResize( size - numClosed );
261
262 for ( int i = 0; i < contours.size(); ++i )
263 {
264 const auto& c = contours[i];
265 if ( c.size() < 2 )
266 continue; // ignore contours with 0 or 1 points because of no edges in them
267 const auto e0 = makeEdge();
268 const auto v0 = addPoint( c[0] );
269 setOrg( e0, v0 );
270 auto e = e0;
271 for ( int j = 1; j + 1 < c.size(); ++j )
272 {
273 const auto ej = makeEdge();
274 splice( ej, e.sym() );
275 const auto vj = addPoint( c[j] );
276 setOrg( ej, vj );
277 e = ej;
278 }
279 if ( closed[i] )
280 {
281 splice( e0, e.sym() );
282 }
283 else
284 {
285 const auto vx = addPoint( c.back() );
286 setOrg( e.sym(), vx );
287 }
288 }
289 assert( isConsistentlyOriented() );
290 assert( edgePerVertex_.size() == size - numClosed );
291}
292
293template<typename T, typename F>
294std::vector<std::vector<T>> PolylineTopology::convertToContours( F&& getPoint, std::vector<std::vector<VertId>>* vertMap ) const
295{
296 std::vector<std::vector<T>> res;
297
298 UndirectedEdgeBitSet linesUsed;
299 linesUsed.autoResizeSet( UndirectedEdgeId{ undirectedEdgeSize() } );
300 linesUsed.flip();
301 for ( EdgeId e0 : linesUsed )
302 {
303 if ( isLoneEdge( e0 ) )
304 continue;
305
306 EdgeId curLine = e0;
307 while ( curLine != next( curLine ) )
308 {
309 curLine = next( curLine ).sym();
310 if ( curLine == e0 )
311 break;
312 }
313
314 linesUsed.set( curLine.undirected(), false );
315
316 EdgeId e = curLine;
317 std::vector<T> cont;
318 std::vector<VertId> map;
319 auto orgV = org( e );
320 cont.push_back( getPoint( orgV ) );
321 if ( vertMap )
322 map.push_back( orgV );
323 for ( ;; )
324 {
325 e = e.sym();
326 cont.push_back( getPoint( org( e ) ) );
327 e = next( e );
328 if ( !linesUsed.test_set( e.undirected(), false ) )
329 break;
330 }
331 res.push_back( std::move( cont ) );
332 if ( vertMap )
333 vertMap->push_back( std::move( map ) );
334 }
335
336 return res;
337}
338
340struct PolylineMaker
341{
342 PolylineTopology & topology;
343 PolylineMaker( PolylineTopology & t ) : topology( t ) {}
344
347 EdgeId start( VertId v )
348 {
349 assert( !e0_ && !eLast_ );
350 e0_ = eLast_ = topology.makeEdge();
351 topology.setOrg( e0_, v );
352 return e0_;
353 }
356 EdgeId proceed( VertId v )
357 {
358 assert( eLast_ );
359 const auto ej = topology.makeEdge();
360 topology.splice( ej, eLast_.sym() );
361 topology.setOrg( ej, v );
362 return eLast_ = ej;
363 }
365 void close()
366 {
367 assert( e0_ && eLast_ );
368 topology.splice( e0_, eLast_.sym() );
369 e0_ = eLast_ = {};
370 }
372 void finishOpen( VertId v )
373 {
374 assert( eLast_ );
375 topology.setOrg( eLast_.sym(), v );
376 e0_ = eLast_ = {};
377 }
378
379private:
380 EdgeId e0_, eLast_;
381};
382
383} // namespace MR
#define MRMESH_API
Definition MRMeshFwd.h:80
Edges
Definition MRObjectMeshHolder.h:16
unsafe void close()
unsafe PolylineMaker(MR.Const_PolylineMaker _other)
unsafe MR.EdgeId start(MR.VertId v)
unsafe void finishOpen(MR.VertId v)
unsafe MR.EdgeId proceed(MR.VertId v)
unsafe void pack(MR.VertMap? outVmap=null, MR.WholeEdgeMap? outEmap=null)
unsafe MR.EdgeId splitEdge(MR.EdgeId e)
unsafe void vertReserve(ulong newCapacity)
unsafe int makeEdges(MR.Const_Edges edges)
unsafe void setOrg(MR.EdgeId a, MR.VertId v)
unsafe bool read(MR.Std.Istream s)
unsafe void flip()
unsafe void vertResizeWithReserve(ulong newSize)
unsafe void computeValidsFromEdges()
unsafe void buildOpenLines(MR.Std.Const_Vector_MRVertId comp2firstVert)
unsafe MR.EdgeId makePolyline(MR.VertId? vs, ulong num)
unsafe void deleteEdge(MR.UndirectedEdgeId ue)
unsafe MR.VertId addVertId()
unsafe void addPart(MR.Const_PolylineTopology from, MR.VertMap? outVmap=null, MR.WholeEdgeMap? outEmap=null)
unsafe void vertResize(ulong newSize)
unsafe void splice(MR.EdgeId a, MR.EdgeId b)
unsafe void deleteEdges(MR.Const_UndirectedEdgeBitSet es)
unsafe void edgeReserve(ulong newCapacity)
unsafe MR.EdgeId makeEdge()
unsafe void addPartByMask(MR.Const_PolylineTopology from, MR.Const_UndirectedEdgeBitSet mask, MR.VertMap? outVmap=null, MR.EdgeMap? outEmap=null)
unsafe void reserve(ulong numBits)
Definition MRCameraOrientationPlugin.h:8
ImVec2 size(const ViewportRectangle &rect)
Definition MRViewport.h:29
readonly unsafe MR.EdgeId sym()