MeshLib C++ Docs
Loading...
Searching...
No Matches
MREdgePathsBuilder.h
Go to the documentation of this file.
1#pragma once
2
3#include "MREdgePaths.h"
4#include "MRBitSet.h"
5#include "MRMesh.h"
6#include "MRRingIterator.h"
7#include "MRphmap.h"
8#include "MRMacros.h"
9#include <queue>
10
11namespace MR
12{
13
16
18struct VertPathInfo
19{
20 // edge from this vertex to its predecessor in the forest
21 EdgeId back;
22 // best summed metric to reach this vertex
23 float metric = FLT_MAX;
24
25 bool isStart() const { return !back.valid(); }
26};
27
28// ParallelHashMap here was significantly slower (especially in debug version of tunnel detection),
29// probably because of more allocations
30using VertPathInfoMap = HashMap<VertId, VertPathInfo>;
31
33template<class MetricToPenalty>
35{
36public:
37 EdgePathsBuilderT( const MeshTopology & topology, const EdgeMetric & metric );
38
39 explicit EdgePathsBuilderT( const MeshTopology & topology );
40
42 void reset( const EdgeMetric & metric );
43
46 bool addStart( VertId startVert, float startMetric );
47
50 {
52
55
58 float penalty = FLT_MAX;
59
61 float metric = FLT_MAX;
62 };
63
66 ReachedVert reachNext();
67
70 bool addOrgRingSteps( const ReachedVert & rv );
71
73 ReachedVert growOneEdge();
74
75public:
77 bool done() const { return nextSteps_.empty(); }
78
80 float doneDistance() const { return nextSteps_.empty() ? FLT_MAX : nextSteps_.top().penalty; }
81
83 const VertPathInfoMap & vertPathInfoMap() const { return vertPathInfoMap_; }
84
86 const VertPathInfo * getVertInfo( VertId v ) const;
87
89 EdgePath getPathBack( VertId backpathStart ) const;
90
93 VertId trackPathBack( VertId backpathStart, EdgePath* res = nullptr ) const;
94
95protected:
97
98private:
99 const MeshTopology & topology_;
100 EdgeMetric metric_;
101 VertPathInfoMap vertPathInfoMap_;
102
103 struct CandidateVert
104 {
105 VertId v;
107 float penalty = FLT_MAX;
108
110 friend bool operator <( const CandidateVert & a, const CandidateVert & b )
111 {
112 return a.penalty > b.penalty;
113 }
114 };
115 std::priority_queue<CandidateVert> nextSteps_;
116
120 bool addNextStep_( const VertPathInfo & c );
121};
122
124struct TrivialMetricToPenalty
125{
126 float operator()( float metric, VertId ) const { return metric; }
127};
128
129using EdgePathsBuilder = EdgePathsBuilderT<TrivialMetricToPenalty>;
130
131template<class MetricToPenalty>
132EdgePathsBuilderT<MetricToPenalty>::EdgePathsBuilderT( const MeshTopology & topology, const EdgeMetric & metric )
133 : topology_( topology )
134 , metric_( metric )
135{
136}
137
138template<class MetricToPenalty>
140 : topology_( topology )
141{
142}
143
144template<class MetricToPenalty>
145void EdgePathsBuilderT<MetricToPenalty>::reset( const EdgeMetric & metric )
146{
147 metric_ = metric;
148 vertPathInfoMap_.clear();
149 while ( !nextSteps_.empty() )
150 nextSteps_.pop();
151}
152
153template<class MetricToPenalty>
154bool EdgePathsBuilderT<MetricToPenalty>::addStart( VertId startVert, float startMetric )
155{
156 auto & vi = vertPathInfoMap_[startVert];
157 if ( vi.metric > startMetric )
158 {
159 vi = { EdgeId{}, startMetric };
160 nextSteps_.push( CandidateVert{ startVert, metricToPenalty_( startMetric, startVert ) } );
161 return true;
162 }
163 return false;
164}
165
166template<class MetricToPenalty>
168{
169 auto it = vertPathInfoMap_.find( v );
170 return ( it != vertPathInfoMap_.end() ) ? &it->second : nullptr;
171}
172
173template<class MetricToPenalty>
175{
176 EdgePath res;
177 trackPathBack( v, &res );
178 return res;
179}
180
181template<class MetricToPenalty>
183{
184 for (;;)
185 {
186 auto it = vertPathInfoMap_.find( v );
187 if ( it == vertPathInfoMap_.end() )
188 {
189 assert( false );
190 break;
191 }
192 auto & vi = it->second;
193 if ( vi.isStart() )
194 break;
195 if ( res )
196 res->push_back( vi.back );
197 v = topology_.dest( vi.back );
198 }
199 return v;
200}
201
202template<class MetricToPenalty>
204{
205 if ( !( c.metric < FLT_MAX ) )
206 return false; // maximal or infinity metric means that this path shall be skipped
207 const auto vert = topology_.org( c.back );
208 auto & vi = vertPathInfoMap_[vert];
209 if ( vi.metric > c.metric )
210 {
211 vi = c;
212 nextSteps_.push( CandidateVert{ vert, metricToPenalty_( c.metric, vert ) } );
213 return true;
214 }
215 return false;
216}
217
218template<class MetricToPenalty>
220{
221 bool aNextStepAdded = false;
222 if ( !rv.v )
223 {
224 assert( !rv.backward );
225 return aNextStepAdded;
226 }
227 const float orgMetric = rv.metric;
228 const EdgeId back = rv.backward ? rv.backward : topology_.edgeWithOrg( rv.v );
229 for ( EdgeId e : orgRing( topology_, back ) )
230 {
231 VertPathInfo c;
232 c.back = e.sym();
233 c.metric = orgMetric + metric_( e );
234 aNextStepAdded = addNextStep_( c ) || aNextStepAdded;
235 }
236 return aNextStepAdded;
237}
238
239template<class MetricToPenalty>
241{
242 while ( !nextSteps_.empty() )
243 {
244 const auto c = nextSteps_.top();
245 nextSteps_.pop();
246 auto & vi = vertPathInfoMap_[c.v];
247 if ( metricToPenalty_( vi.metric, c.v ) < c.penalty )
248 {
249 // shorter path to the vertex was found
250 continue;
251 }
252 assert( metricToPenalty_( vi.metric, c.v ) == c.penalty );
253 return { .v = c.v, .backward = vi.back, .penalty = c.penalty, .metric = vi.metric };
254 }
255 return {};
256}
257
258template<class MetricToPenalty>
260{
261 auto res = reachNext();
262 addOrgRingSteps( res );
263 return res;
264}
265
269{
270 const VertCoords * points = nullptr;
271 Vector3f target;
272 float operator()( float metric, VertId v ) const
273 {
274 return metric + ( (*points)[v] - target ).length();
275 }
276};
277
280class EdgePathsAStarBuilder: public EdgePathsBuilderT<MetricToAStarPenalty>
281{
282public:
283 EdgePathsAStarBuilder( const Mesh & mesh, VertId target, VertId start ) :
284 EdgePathsBuilderT( mesh.topology, edgeLengthMetric( mesh ) )
285 {
286 metricToPenalty_.points = &mesh.points;
287 metricToPenalty_.target = mesh.points[target];
288 addStart( start, 0 );
289 }
290 EdgePathsAStarBuilder( const Mesh & mesh, const MeshTriPoint & target, const MeshTriPoint & start ) :
291 EdgePathsBuilderT( mesh.topology, edgeLengthMetric( mesh ) )
292 {
293 metricToPenalty_.points = &mesh.points;
294 metricToPenalty_.target = mesh.triPoint( target );
295 const auto startPt = mesh.triPoint( start );
296 mesh.topology.forEachVertex( start, [&]( VertId v )
297 {
298 addStart( v, ( mesh.points[v] - startPt ).length() );
299 } );
300 }
301};
302
304
305} // namespace MR
#define MR_NO_UNIQUE_ADDRESS
Definition MRMacros.h:42
length
Definition MRObjectDimensionsEnum.h:14
unsafe EdgePathsAStarBuilder(MR._ByValue_EdgePathsAStarBuilder _other)
unsafe bool addStart(MR.VertId startVert, float startMetric)
the class is responsible for finding smallest metric edge paths on a mesh
Definition MREdgePathsBuilder.h:35
ReachedVert growOneEdge()
the same as reachNext() + addOrgRingSteps()
Definition MREdgePathsBuilder.h:259
bool done() const
returns true if further edge forest growth is impossible
Definition MREdgePathsBuilder.h:77
bool addStart(VertId startVert, float startMetric)
Definition MREdgePathsBuilder.h:154
ReachedVert reachNext()
Definition MREdgePathsBuilder.h:240
EdgePathsBuilderT(const MeshTopology &topology)
Definition MREdgePathsBuilder.h:139
float doneDistance() const
returns path length till the next candidate vertex or maximum float value if all vertices have been r...
Definition MREdgePathsBuilder.h:80
bool addOrgRingSteps(const ReachedVert &rv)
Definition MREdgePathsBuilder.h:219
void reset(const EdgeMetric &metric)
clears everything without freeing memory, and sets new metric
Definition MREdgePathsBuilder.h:145
MR_NO_UNIQUE_ADDRESS MetricToPenalty metricToPenalty_
Definition MREdgePathsBuilder.h:96
VertId trackPathBack(VertId backpathStart, EdgePath *res=nullptr) const
Definition MREdgePathsBuilder.h:182
EdgePathsBuilderT(const MeshTopology &topology, const EdgeMetric &metric)
Definition MREdgePathsBuilder.h:132
EdgePath getPathBack(VertId backpathStart) const
returns the path in the forest from given vertex to one of start vertices
Definition MREdgePathsBuilder.h:174
const VertPathInfoMap & vertPathInfoMap() const
gives read access to the map from vertex to path to it
Definition MREdgePathsBuilder.h:83
const VertPathInfo * getVertInfo(VertId v) const
returns one element from the map (or nullptr if the element is missing)
Definition MREdgePathsBuilder.h:167
Definition MRMesh/MRMeshTopology.h:19
Definition MREdgePathsBuilder.h:269
Definition MREdgePathsBuilder.h:19
MRMESH_API EdgeMetric edgeLengthMetric(const Mesh &mesh)
Definition MRCameraOrientationPlugin.h:8
IteratorRange< OrgRingIterator > orgRing(const MeshTopology &topology, EdgeId edge)
Definition MRRingIterator.h:70
information about just reached vertex (with final metric value)
Definition MREdgePathsBuilder.h:50
float penalty
Definition MREdgePathsBuilder.h:58
EdgeId backward
edge from this vertex to its predecessor in the forest (if this vertex is not start)
Definition MREdgePathsBuilder.h:54
float metric
summed metric to reach this vertex
Definition MREdgePathsBuilder.h:61
VertId v
Definition MREdgePathsBuilder.h:51