MeshLib
 
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 <queue>
9
10namespace MR
11{
12
15
18{
19 // edge from this vertex to its predecessor in the forest
21 // best summed metric to reach this vertex
22 float metric = FLT_MAX;
23
24 bool isStart() const { return !back.valid(); }
25};
26
27// ParallelHashMap here was significantly slower (especially in debug version of tunnel detection),
28// probably because of more allocations
30
32template<class MetricToPenalty>
34{
35public:
36 EdgePathsBuilderT( const MeshTopology & topology, const EdgeMetric & metric );
37 // compares proposed metric with best value known for startVert;
38 // if proposed metric is smaller then adds it in the queue and returns true
39 bool addStart( VertId startVert, float startMetric );
40
41 // information about just reached vertex (with final metric value)
43 {
45 // edge from this vertex to its predecessor in the forest (if this vertex is not start)
47 // the penalty to reach this vertex
48 float penalty = FLT_MAX;
49 // summed metric to reach this vertex
50 float metric = FLT_MAX;
51 };
52
53 // include one more vertex in the final forest, returning vertex-info for the newly reached vertex;
54 // returns invalid VertId in v-field if no more vertices left
55 ReachedVert reachNext();
56 // adds steps for all origin ring edges of the reached vertex;
57 // returns true if at least one step was added
58 bool addOrgRingSteps( const ReachedVert & rv );
59 // the same as reachNext() + addOrgRingSteps()
60 ReachedVert growOneEdge();
61
62public:
63 // returns true if further edge forest growth is impossible
64 bool done() const { return nextSteps_.empty(); }
65 // returns path length till the next candidate vertex or maximum float value if all vertices have been reached
66 float doneDistance() const { return nextSteps_.empty() ? FLT_MAX : nextSteps_.top().penalty; }
67 // gives read access to the map from vertex to path to it
68 const VertPathInfoMap & vertPathInfoMap() const { return vertPathInfoMap_; }
69 // returns one element from the map (or nullptr if the element is missing)
70 const VertPathInfo * getVertInfo( VertId v ) const;
71
72 // returns the path in the forest from given vertex to one of start vertices
73 EdgePath getPathBack( VertId backpathStart ) const;
74
75protected:
76 [[no_unique_address]] MetricToPenalty metricToPenalty_;
77
78private:
79 const MeshTopology & topology_;
80 EdgeMetric metric_;
81 VertPathInfoMap vertPathInfoMap_;
82
83 struct CandidateVert
84 {
85 VertId v;
86 // best penalty to reach this vertex
87 float penalty = FLT_MAX;
88
89 // smaller penalty to be the first
90 friend bool operator <( const CandidateVert & a, const CandidateVert & b )
91 {
92 return a.penalty > b.penalty;
93 }
94 };
95 std::priority_queue<CandidateVert> nextSteps_;
96
97 // compares proposed step with the value known for org( c.back );
98 // if proposed step is smaller then adds it in the queue and returns true;
99 // otherwise if the known metric to org( c.back ) is already not greater than returns false
100 bool addNextStep_( const VertPathInfo & c );
101};
102
105{
106 float operator()( float metric, VertId ) const { return metric; }
107};
108
110
111template<class MetricToPenalty>
113 : topology_( topology )
114 , metric_( metric )
115{
116}
117
118template<class MetricToPenalty>
119bool EdgePathsBuilderT<MetricToPenalty>::addStart( VertId startVert, float startMetric )
120{
121 auto & vi = vertPathInfoMap_[startVert];
122 if ( vi.metric > startMetric )
123 {
124 vi = { EdgeId{}, startMetric };
125 nextSteps_.push( CandidateVert{ startVert, metricToPenalty_( startMetric, startVert ) } );
126 return true;
127 }
128 return false;
129}
130
131template<class MetricToPenalty>
133{
134 auto it = vertPathInfoMap_.find( v );
135 return ( it != vertPathInfoMap_.end() ) ? &it->second : nullptr;
136}
137
138template<class MetricToPenalty>
140{
141 EdgePath res;
142 for (;;)
143 {
144 auto it = vertPathInfoMap_.find( v );
145 if ( it == vertPathInfoMap_.end() )
146 {
147 assert( false );
148 break;
149 }
150 auto & vi = it->second;
151 if ( vi.isStart() )
152 break;
153 res.push_back( vi.back );
154 v = topology_.dest( vi.back );
155 }
156 return res;
157}
158
159template<class MetricToPenalty>
161{
162 if ( !( c.metric < FLT_MAX ) )
163 return false; // maximal or infinity metric means that this path shall be skipped
164 const auto vert = topology_.org( c.back );
165 auto & vi = vertPathInfoMap_[vert];
166 if ( vi.metric > c.metric )
167 {
168 vi = c;
169 nextSteps_.push( CandidateVert{ vert, metricToPenalty_( c.metric, vert ) } );
170 return true;
171 }
172 return false;
173}
174
175template<class MetricToPenalty>
177{
178 bool aNextStepAdded = false;
179 if ( !rv.v )
180 {
181 assert( !rv.backward );
182 return aNextStepAdded;
183 }
184 const float orgMetric = rv.metric;
185 const EdgeId back = rv.backward ? rv.backward : topology_.edgeWithOrg( rv.v );
186 for ( EdgeId e : orgRing( topology_, back ) )
187 {
188 VertPathInfo c;
189 c.back = e.sym();
190 c.metric = orgMetric + metric_( e );
191 aNextStepAdded = addNextStep_( c ) || aNextStepAdded;
192 }
193 return aNextStepAdded;
194}
195
196template<class MetricToPenalty>
198{
199 while ( !nextSteps_.empty() )
200 {
201 const auto c = nextSteps_.top();
202 nextSteps_.pop();
203 auto & vi = vertPathInfoMap_[c.v];
204 if ( metricToPenalty_( vi.metric, c.v ) < c.penalty )
205 {
206 // shorter path to the vertex was found
207 continue;
208 }
209 assert( metricToPenalty_( vi.metric, c.v ) == c.penalty );
210 return { .v = c.v, .backward = vi.back, .penalty = c.penalty, .metric = vi.metric };
211 }
212 return {};
213}
214
215template<class MetricToPenalty>
217{
218 auto res = reachNext();
219 addOrgRingSteps( res );
220 return res;
221}
222
226{
227 const VertCoords * points = nullptr;
229 float operator()( float metric, VertId v ) const
230 {
231 return metric + ( (*points)[v] - target ).length();
232 }
233};
234
237class EdgePathsAStarBuilder: public EdgePathsBuilderT<MetricToAStarPenalty>
238{
239public:
240 EdgePathsAStarBuilder( const Mesh & mesh, VertId target, VertId start ) :
241 EdgePathsBuilderT( mesh.topology, edgeLengthMetric( mesh ) )
242 {
244 metricToPenalty_.target = mesh.points[target];
245 addStart( start, 0 );
246 }
247 EdgePathsAStarBuilder( const Mesh & mesh, const MeshTriPoint & target, const MeshTriPoint & start ) :
248 EdgePathsBuilderT( mesh.topology, edgeLengthMetric( mesh ) )
249 {
251 metricToPenalty_.target = mesh.triPoint( target );
252 const auto startPt = mesh.triPoint( start );
253 mesh.topology.forEachVertex( start, [&]( VertId v )
254 {
255 addStart( v, ( mesh.points[v] - startPt ).length() );
256 } );
257 }
258};
259
261
262} // namespace MR
List< Vector3f^> VertCoords
Definition MRDotNet/MRMeshFwd.h:95
int VertId
Definition MRDotNet/MRMeshFwd.h:51
int EdgeId
Definition MRDotNet/MRMeshFwd.h:52
length
Definition MRObjectDimensionsEnum.h:14
Definition MREdgePathsBuilder.h:238
EdgePathsAStarBuilder(const Mesh &mesh, VertId target, VertId start)
Definition MREdgePathsBuilder.h:240
EdgePathsAStarBuilder(const Mesh &mesh, const MeshTriPoint &target, const MeshTriPoint &start)
Definition MREdgePathsBuilder.h:247
the class is responsible for finding smallest metric edge paths on a mesh
Definition MREdgePathsBuilder.h:34
ReachedVert growOneEdge()
Definition MREdgePathsBuilder.h:216
bool done() const
Definition MREdgePathsBuilder.h:64
bool addStart(VertId startVert, float startMetric)
Definition MREdgePathsBuilder.h:119
ReachedVert reachNext()
Definition MREdgePathsBuilder.h:197
float doneDistance() const
Definition MREdgePathsBuilder.h:66
bool addOrgRingSteps(const ReachedVert &rv)
Definition MREdgePathsBuilder.h:176
MetricToPenalty metricToPenalty_
Definition MREdgePathsBuilder.h:76
EdgePathsBuilderT(const MeshTopology &topology, const EdgeMetric &metric)
Definition MREdgePathsBuilder.h:112
EdgePath getPathBack(VertId backpathStart) const
Definition MREdgePathsBuilder.h:139
const VertPathInfoMap & vertPathInfoMap() const
Definition MREdgePathsBuilder.h:68
const VertPathInfo * getVertInfo(VertId v) const
Definition MREdgePathsBuilder.h:132
Definition MRMesh/MRMeshTopology.h:18
void forEachVertex(const MeshTriPoint &p, T &&callback) const
Definition MRMesh/MRMeshTopology.h:560
represents a 3-dimentional float-typed vector
Definition MRDotNet/MRVector3.h:8
MRMESH_API EdgeMetric edgeLengthMetric(const Mesh &mesh)
Definition MRCameraOrientationPlugin.h:7
std::function< float(EdgeId)> EdgeMetric
Definition MRMesh/MRMeshFwd.h:428
HashMap< VertId, VertPathInfo > VertPathInfoMap
Definition MREdgePathsBuilder.h:29
std::vector< EdgeId > EdgePath
Definition MRMesh/MRMeshFwd.h:98
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:450
Definition MREdgePathsBuilder.h:43
float penalty
Definition MREdgePathsBuilder.h:48
EdgeId backward
Definition MREdgePathsBuilder.h:46
float metric
Definition MREdgePathsBuilder.h:50
VertId v
Definition MREdgePathsBuilder.h:44
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:226
Vector3f target
Definition MREdgePathsBuilder.h:228
float operator()(float metric, VertId v) const
Definition MREdgePathsBuilder.h:229
const VertCoords * points
Definition MREdgePathsBuilder.h:227
the vertices in the queue are ordered by their metric from a start location
Definition MREdgePathsBuilder.h:105
float operator()(float metric, VertId) const
Definition MREdgePathsBuilder.h:106
information associated with each vertex by the paths builder
Definition MREdgePathsBuilder.h:18
float metric
Definition MREdgePathsBuilder.h:22
EdgeId back
Definition MREdgePathsBuilder.h:20
bool isStart() const
Definition MREdgePathsBuilder.h:24