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
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
31
33template<class MetricToPenalty>
35{
36public:
37 EdgePathsBuilderT( const MeshTopology & topology, const EdgeMetric & metric );
38
41 bool addStart( VertId startVert, float startMetric );
42
45 {
46 VertId v;
47
49 EdgeId backward;
50
53 float penalty = FLT_MAX;
54
56 float metric = FLT_MAX;
57 };
58
61 ReachedVert reachNext();
62
65 bool addOrgRingSteps( const ReachedVert & rv );
66
68 ReachedVert growOneEdge();
69
70public:
72 bool done() const { return nextSteps_.empty(); }
73
75 float doneDistance() const { return nextSteps_.empty() ? FLT_MAX : nextSteps_.top().penalty; }
76
78 const VertPathInfoMap & vertPathInfoMap() const { return vertPathInfoMap_; }
79
81 const VertPathInfo * getVertInfo( VertId v ) const;
82
84 EdgePath getPathBack( VertId backpathStart ) const;
85
86protected:
88
89private:
90 const MeshTopology & topology_;
91 EdgeMetric metric_;
92 VertPathInfoMap vertPathInfoMap_;
93
94 struct CandidateVert
95 {
96 VertId v;
98 float penalty = FLT_MAX;
99
101 friend bool operator <( const CandidateVert & a, const CandidateVert & b )
102 {
103 return a.penalty > b.penalty;
104 }
105 };
106 std::priority_queue<CandidateVert> nextSteps_;
107
111 bool addNextStep_( const VertPathInfo & c );
112};
113
116{
117 float operator()( float metric, VertId ) const { return metric; }
118};
119
121
122template<class MetricToPenalty>
124 : topology_( topology )
125 , metric_( metric )
126{
127}
128
129template<class MetricToPenalty>
130bool EdgePathsBuilderT<MetricToPenalty>::addStart( VertId startVert, float startMetric )
131{
132 auto & vi = vertPathInfoMap_[startVert];
133 if ( vi.metric > startMetric )
134 {
135 vi = { EdgeId{}, startMetric };
136 nextSteps_.push( CandidateVert{ startVert, metricToPenalty_( startMetric, startVert ) } );
137 return true;
138 }
139 return false;
140}
141
142template<class MetricToPenalty>
144{
145 auto it = vertPathInfoMap_.find( v );
146 return ( it != vertPathInfoMap_.end() ) ? &it->second : nullptr;
147}
148
149template<class MetricToPenalty>
151{
152 EdgePath res;
153 for (;;)
154 {
155 auto it = vertPathInfoMap_.find( v );
156 if ( it == vertPathInfoMap_.end() )
157 {
158 assert( false );
159 break;
160 }
161 auto & vi = it->second;
162 if ( vi.isStart() )
163 break;
164 res.push_back( vi.back );
165 v = topology_.dest( vi.back );
166 }
167 return res;
168}
169
170template<class MetricToPenalty>
172{
173 if ( !( c.metric < FLT_MAX ) )
174 return false; // maximal or infinity metric means that this path shall be skipped
175 const auto vert = topology_.org( c.back );
176 auto & vi = vertPathInfoMap_[vert];
177 if ( vi.metric > c.metric )
178 {
179 vi = c;
180 nextSteps_.push( CandidateVert{ vert, metricToPenalty_( c.metric, vert ) } );
181 return true;
182 }
183 return false;
184}
185
186template<class MetricToPenalty>
188{
189 bool aNextStepAdded = false;
190 if ( !rv.v )
191 {
192 assert( !rv.backward );
193 return aNextStepAdded;
194 }
195 const float orgMetric = rv.metric;
196 const EdgeId back = rv.backward ? rv.backward : topology_.edgeWithOrg( rv.v );
197 for ( EdgeId e : orgRing( topology_, back ) )
198 {
199 VertPathInfo c;
200 c.back = e.sym();
201 c.metric = orgMetric + metric_( e );
202 aNextStepAdded = addNextStep_( c ) || aNextStepAdded;
203 }
204 return aNextStepAdded;
205}
206
207template<class MetricToPenalty>
209{
210 while ( !nextSteps_.empty() )
211 {
212 const auto c = nextSteps_.top();
213 nextSteps_.pop();
214 auto & vi = vertPathInfoMap_[c.v];
215 if ( metricToPenalty_( vi.metric, c.v ) < c.penalty )
216 {
217 // shorter path to the vertex was found
218 continue;
219 }
220 assert( metricToPenalty_( vi.metric, c.v ) == c.penalty );
221 return { .v = c.v, .backward = vi.back, .penalty = c.penalty, .metric = vi.metric };
222 }
223 return {};
224}
225
226template<class MetricToPenalty>
228{
229 auto res = reachNext();
230 addOrgRingSteps( res );
231 return res;
232}
233
237{
238 const VertCoords * points = nullptr;
239 Vector3f target;
240 float operator()( float metric, VertId v ) const
241 {
242 return metric + ( (*points)[v] - target ).length();
243 }
244};
245
248class EdgePathsAStarBuilder: public EdgePathsBuilderT<MetricToAStarPenalty>
249{
250public:
251 EdgePathsAStarBuilder( const Mesh & mesh, VertId target, VertId start ) :
252 EdgePathsBuilderT( mesh.topology, edgeLengthMetric( mesh ) )
253 {
255 metricToPenalty_.target = mesh.points[target];
256 addStart( start, 0 );
257 }
258 EdgePathsAStarBuilder( const Mesh & mesh, const MeshTriPoint & target, const MeshTriPoint & start ) :
259 EdgePathsBuilderT( mesh.topology, edgeLengthMetric( mesh ) )
260 {
262 metricToPenalty_.target = mesh.triPoint( target );
263 const auto startPt = mesh.triPoint( start );
264 mesh.topology.forEachVertex( start, [&]( VertId v )
265 {
266 addStart( v, ( mesh.points[v] - startPt ).length() );
267 } );
268 }
269};
270
272
273} // namespace MR
#define MR_NO_UNIQUE_ADDRESS
Definition MRMacros.h:37
length
Definition MRObjectDimensionsEnum.h:14
Definition MREdgePathsBuilder.h:249
EdgePathsAStarBuilder(const Mesh &mesh, VertId target, VertId start)
Definition MREdgePathsBuilder.h:251
EdgePathsAStarBuilder(const Mesh &mesh, const MeshTriPoint &target, const MeshTriPoint &start)
Definition MREdgePathsBuilder.h:258
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:227
bool done() const
returns true if further edge forest growth is impossible
Definition MREdgePathsBuilder.h:72
bool addStart(VertId startVert, float startMetric)
Definition MREdgePathsBuilder.h:130
ReachedVert reachNext()
Definition MREdgePathsBuilder.h:208
float doneDistance() const
returns path length till the next candidate vertex or maximum float value if all vertices have been r...
Definition MREdgePathsBuilder.h:75
bool addOrgRingSteps(const ReachedVert &rv)
Definition MREdgePathsBuilder.h:187
MR_NO_UNIQUE_ADDRESS MetricToPenalty metricToPenalty_
Definition MREdgePathsBuilder.h:87
EdgePathsBuilderT(const MeshTopology &topology, const EdgeMetric &metric)
Definition MREdgePathsBuilder.h:123
EdgePath getPathBack(VertId backpathStart) const
returns the path in the forest from given vertex to one of start vertices
Definition MREdgePathsBuilder.h:150
const VertPathInfoMap & vertPathInfoMap() const
gives read access to the map from vertex to path to it
Definition MREdgePathsBuilder.h:78
const VertPathInfo * getVertInfo(VertId v) const
returns one element from the map (or nullptr if the element is missing)
Definition MREdgePathsBuilder.h:143
Definition MRMesh/MRMeshTopology.h:18
void forEachVertex(const MeshTriPoint &p, T &&callback) const
Definition MRMesh/MRMeshTopology.h:571
MRMESH_API EdgeMetric edgeLengthMetric(const Mesh &mesh)
std::function< float(EdgeId)> EdgeMetric
Definition MRMesh/MRMeshFwd.h:460
HashMap< VertId, VertPathInfo > VertPathInfoMap
Definition MREdgePathsBuilder.h:30
std::vector< EdgeId > EdgePath
Definition MRMesh/MRMeshFwd.h:120
IteratorRange< OrgRingIterator > orgRing(const MeshTopology &topology, EdgeId edge)
Definition MRRingIterator.h:70
phmap::flat_hash_map< K, V, Hash, Eq > HashMap
Definition MRMesh/MRMeshFwd.h:482
information about just reached vertex (with final metric value)
Definition MREdgePathsBuilder.h:45
float penalty
Definition MREdgePathsBuilder.h:53
EdgeId backward
edge from this vertex to its predecessor in the forest (if this vertex is not start)
Definition MREdgePathsBuilder.h:49
float metric
summed metric to reach this vertex
Definition MREdgePathsBuilder.h:56
VertId v
Definition MREdgePathsBuilder.h:46
Definition MRMesh/MRMeshTriPoint.h:23
Definition MRMesh/MRMesh.h:23
MRMESH_API Vector3f triPoint(const MeshTriPoint &p) const
computes coordinates of point given as face and barycentric representation
MeshTopology topology
Definition MRMesh/MRMesh.h:24
VertCoords points
Definition MRMesh/MRMesh.h:25
Definition MREdgePathsBuilder.h:237
Vector3f target
Definition MREdgePathsBuilder.h:239
float operator()(float metric, VertId v) const
Definition MREdgePathsBuilder.h:240
const VertCoords * points
Definition MREdgePathsBuilder.h:238
the vertices in the queue are ordered by their metric from a start location
Definition MREdgePathsBuilder.h:116
float operator()(float metric, VertId) const
Definition MREdgePathsBuilder.h:117
information associated with each vertex by the paths builder
Definition MREdgePathsBuilder.h:19
float metric
Definition MREdgePathsBuilder.h:23
EdgeId back
Definition MREdgePathsBuilder.h:21
bool isStart() const
Definition MREdgePathsBuilder.h:25