Fréchet View  1.6.0
A Tool for Exploring Fréchet Distance Algorithms
poly_path.cpp
Go to the documentation of this file.
1 
2 #include <poly_path.h>
5 #include <spirolator.h>
6 
7 using namespace frechet;
8 using namespace poly;
9 using namespace reach;
10 
12  : FSPath(fs)
13 {
14  wrapTop=false;
15 }
16 
18  const Graph::ptr G,
19  double aneps)
20 {
21  if (!std::isnan(aneps))
22  fs->calculateFreeSpace(aneps);
23 
24  Q_ASSERT(G);
25  gmodel = G->graphModel();
26 
27  FSPath::clear();
28  drillDown(G); // calculate fix points
29 
30  calculatePath();
31  gmodel.reset();
32 }
33 
34 
36 {
37  Q_ASSERT(G->graphModel()==gmodel);
38 
39  // find start/end interval
40  int p = G->foundDiagonalElement();
41  Interval start_ival = mapInterval(HORIZONTAL,p);
42  Q_ASSERT(start_ival);
43  // don't pick start point at interval border; pick middle instead
44  double start = (start_ival.lower()+start_ival.upper())/2;
45  start = fmod(start,fs->n-1);
46 
47  fix.clear();
48  addFixPoint(Point(start,0.0));
49  // end point is mapped to Q(0), again
50 
51  // G consists of three merged parts A B A'
52  Graph::ptr A = G->origin.A;
53  Graph::ptr B = G->origin.B;
54 
55  B->synchFromGpu();
56 
57  // find the connecting points A-B-A'
59  Q_ASSERT(k.first <= k.second);
60 
61  addFixPoint(A->hmask().upper,k.first);
62 
63  drillDown(B, k.first, k.second);
64 
65  addFixPoint(B->hmask().upper,k.second);
66  // End Point
67  if (fix.size()>1 && fix.last().x()==start)
68  fix.last().ry() = fs->m-1; // replace last point
69  else
70  addFixPoint(Point(start,fs->m-1));
71 
72  Q_ASSERT(is_consistent(fix));
73 }
74 
75 
76 void PolygonFSPath::drillDown(Graph::ptr M, int k1, int k2)
77 {
78  if (M->origin.operation==Graph::Origin::MERGE2)
79  {
80  Graph::ptr A = M->origin.A;
81  Graph::ptr B = M->origin.B;
82 
83  A->synchFromGpu();
84  B->synchFromGpu();
85 
86  Q_ASSERT(Graph::is_adjacent_to(*A,*B));
87 
88  int k = findConnectingPoint(A,k1, B,k2);
89  Q_ASSERT(k >= k1 && k <= k2);
90 
91  drillDown(A, k1, k);
92 
93  addFixPoint(A->hmask().upper,k);
94 
95  drillDown(B, k, k2);
96  }
97 }
98 
100  Graph::ptr A, int ia,
101  Graph::ptr B, int ib) const
102 {
103  Q_ASSERT(A->graphModel()==gmodel);
104  Q_ASSERT(B->graphModel()==gmodel);
105 
106  Interval ival1 = mapInterval(VERTICAL,ia);
107  Interval ival2 = mapInterval(VERTICAL,ib);
108  Q_ASSERT(ival1.lower() < ival2.upper());
109 
110  IndexRange r = A->find_next_range(VERTICAL,ia, VERTICAL,0);
111  for( ; ! r.empty(); r = A->find_next_range(VERTICAL,ia, VERTICAL,r.upper))
112  {
113  Spirolator k (r.lower,r.upper);
114  for ( ; k; ++k) {
115  if (B->contains_edge(VERTICAL, k, VERTICAL, ib)) {
116  Interval ival3 = mapInterval(VERTICAL, k);
117  // avoid picking too narrow bounds. While perfectly legal,
118  // it will cause headaches when painting the homeomorphism.
119  if (ival3.lower() == ival3.upper())
120  continue;
121 // if (ival3.upper() >= ival1.lower() && ival3.lower() <= ival2.upper()) {
122  Q_ASSERT(A->contains_edge(VERTICAL, ia, VERTICAL, k));
123  Q_ASSERT(B->contains_edge(VERTICAL, k, VERTICAL, ib));
124  return k;
125 // }
126  }
127  }
128  }
129  Q_ASSERT(false);
130  return -1;
131 }
132 
133 void PolygonFSPath::addFixPoint(int pi, int qi) {
134  // map to curve offset
135  int p = mapPoint(HORIZONTAL,pi);
136  p = p % (fs->n-1);
137 
138  Interval q = mapInterval(VERTICAL,qi);
139  double y,y1,y2;
140  if (fix.isEmpty())
141  addFixPoint(Point(p,q.lower()));
142  else if (q.lower() > fix.last().y()) {
143  // avoid picking too narrow bounds. While perfectly legal,
144  // it will cause headaches when painting the homeomorphism.
145  double y = (q.lower()+q.upper())/2;
146  addFixPoint(Point(p,y));
147  }
148  else {
149  y1 = std::max(q.lower(),fix.last().y());
150  Q_ASSERT(q.upper() > y1);
151  y = (y1+q.upper())/2;
152  Q_ASSERT(q.contains(y));
153  addFixPoint(Point(p,y));
154  }
155 }
156 
158 {
159  if (!fix.empty() && p==fix.last())
160  return; // skip duplicates
161  if (fix.empty()) {
162  fix.push_back(p);
163  return;
164  }
165  // the homeomprphism must be bijective !!
166  QPointF last = fix.last();
167  Q_ASSERT(p.x() != last.x()); // greater modulo n
168  Q_ASSERT(p.y() > last.y());
169  fix.push_back(p);
170 }
171 
176 {
177  const std::vector<Interval>& reverse = gmodel->reverseMap(o);
178  return reverse[p % reverse.size()];
179 }
183 double PolygonFSPath::mapPoint(Orientation o, int p) const
184 {
186 }
187 
189 {
190  GraphModel::ptr model = A->graphModel();
191 
192  Q_ASSERT(Graph::is_adjacent_to(*A,*B));
193  Q_ASSERT(Graph::is_adjacent_to(*B,*A));
194 
195  Q_ASSERT(A->origin.operation==Graph::Origin::RG);
196  //Q_ASSERT(B->origin.operation!=Graph::Origin::RG);
197 
198  IndexRange r1 = A->find_next_range(HORIZONTAL,i, VERTICAL,0);
199  for( ; ! r1.empty(); r1 = A->find_next_range(HORIZONTAL,i, VERTICAL,r1.upper))
200  {
201  Spirolator k1 (r1.lower,r1.upper);
202  for ( ; k1; ++k1) {
203  // k.first must map to an interval > 0
204  Interval ival1 = mapInterval(VERTICAL, k1);
205  if (ival1.upper() <= 0.0) continue;
206 
207  Q_ASSERT(A->contains_edge(HORIZONTAL, i, VERTICAL, k1));
208 
209  IndexRange r2 = B->find_next_range(VERTICAL, k1, VERTICAL, k1);
210  for (; !r2.empty(); r2 = B->find_next_range(VERTICAL, k1, VERTICAL, r2.upper))
211  {
212  Spirolator k2(r2.lower,r2.upper);
213  for ( ; k2; ++k2)
214  if (A->contains_edge(VERTICAL, k2, HORIZONTAL, i)) {
215  // intervals must be strictly monotonous
216  Interval ival2 = mapInterval(VERTICAL, k2);
217  if (ival2.lower() >= fs->m - 1) continue;
218  if (ival2.upper() <= ival1.lower()) continue;
219  return IndexPair(k1,k2);
220  }
221  }
222  }
223  }
224 /* naive implementation
225  for(k.first=0; k.first < v1; ++k.first)
226  for(k.second=0; k.second < v1; ++k.second)
227  if (A->contains_edge(HORIZONTAL,i, VERTICAL,k.first)
228  && B->contains_edge(VERTICAL,k.first, VERTICAL,k.second)
229  && A->contains_edge(VERTICAL,k.second,HORIZONTAL,i))
230  return k;
231 */
232  Q_ASSERT(false);
233  return IndexPair(-1,-1);
234 }
235 
237 {
238  Curve result;
239  // map points from P to Q
240  double pa = mapFromQToP(qa);
241  double pb = mapFromQToP(qb);
242 
243  // create a shortest path tree searcher
244  PolygonShortestPaths shortestPaths(tri);
245  return shortestPaths.find1ShortestPath(pa,pb);
246 }
247 
249 {
250  Curve result;
251  // map points from P to Q
252  double qa = mapFromPToQ(pa);
253  double qb = mapFromPToQ(pb);
254 
255  // create a shortest path tree searcher
256  PolygonShortestPaths shortestPaths(tri);
257  return shortestPaths.find1ShortestPath(qa,qb);
258 }
259 
260 
261 
262 
264 {
265 // for(int i=0; i < fix.size(); ++i)
266 // std::cout << "["<<fix[i].x()<<","<<fix[i].y()<<"]" << std::endl;
267 // std::cout << std::endl;
268  // consistency check. fix must not contain duplicates
269  for(int i=0; i < fix.size(); ++i) {
270  Q_ASSERT(fix.indexOf(fix[i])==i);
271  }
272 
273  // must be strictly monotonous (modulo n)
274  int wrapped=0;
275  for(int i=1; i < fix.size(); ++i)
276  {
277  Q_ASSERT(fix[i].y() > fix[i-1].y());
278  if (fix[i].x() < fix[i-1].x()) wrapped++;
279  Q_ASSERT(fix[i].x() > fix[i-1].x() || (wrapped==1));
280  }
281  return true;
282 }
bool wrapTop
free-space wraps at top, Q is closed
Definition: fs_path.h:50
double mapPoint(Orientation o, int p) const
map a node of a reachability graph to a point in the free-space interval.
Definition: poly_path.cpp:183
global definitions for all algorithms.
IndexPair findSolutionConnectingPoints(Graph::ptr A, int i, Graph::ptr B) const
given the solution of the simple polygon algorithm, drill down to the original graphs and find the fi...
Definition: poly_path.cpp:188
boost::shared_ptr< GraphModel > ptr
smart pointer to a GraphModel object
Definition: graph_model.h:307
double mapFromQToP(int q) const
Definition: fs_path.cpp:817
GraphModel::ptr gmodel
model for mapping free-space intervals to reachability graph nodes
Definition: poly_path.h:28
Curve findShortestPathP(int qa, int qb, Triangulation &tri)
given a diagonal in Q, compute the mapped shortest-path in P.
Definition: poly_path.cpp:236
double upper() const
Definition: interval.h:96
int upper
upper index (exclusive)
Definition: graph_model.h:23
int lower
lower index (inclusive)
Definition: graph_model.h:21
Curve find1ShortestPath(double p1, double p2)
compute the shortest path between two points on the boundary of the polygon
void drillDown(Graph::ptr res)
Drill down, starting from the solution Graph, replacing diagonals step by step. Until finally we have...
Definition: poly_path.cpp:35
QPointF Point
a point in the plane; with double floating point precision. This type is heavily used throughout all ...
Definition: types.h:14
std::pair< int, int > IndexPair
Definition: poly_path.h:100
QPolygonF Curve
a polygonal curve in the plane; with double floating point precision. This type is heavily used throu...
Definition: types.h:20
an integer iterator that goes in "spirals", like this:
Definition: spirolator.h:16
a range of node indices in a Reachability Graph
Definition: graph_model.h:17
Orientation
Segment Orientation.
Definition: boundary.h:31
double lower() const
Definition: interval.h:92
boost::shared_ptr< Graph > ptr
Definition: graph_boost.h:59
void addFixPoint(int pi, int qi)
add a fix point to the feasible path
Definition: poly_path.cpp:133
Curve fix
fix points
Definition: fs_path.h:56
Interval mapInterval(Orientation o, int p) const
map a node of a reachability graph to the associated free-space interval
Definition: poly_path.cpp:175
static bool is_consistent(Curve fix)
for debugging only; test the consistency of a feasible path. It must be monotone in both x- and y-coo...
Definition: poly_path.cpp:263
int findConnectingPoint(Graph::ptr A, int ia, Graph::ptr B, int ib) const
given two reachability graphs, drill down to the original graphs and find the fixed points of the fea...
Definition: poly_path.cpp:99
void calculatePath()
calculate the feasible path
Definition: fs_path.cpp:674
compute Shortest-Paths-Tree on a polygon
PolygonFSPath(FreeSpace::ptr fs)
constructor with free-space
Definition: poly_path.cpp:11
bool contains(double x) const
containment test (assumes closed interval, bounds inclusive)
Definition: interval.h:206
Wrapper for CGAL::Triangulation_Data_Structure https://doc.cgal.org/latest/TDS_2/index....
an interval of two double values.
Definition: interval.h:31
static double pickIntervalPoint(const Interval &j, int m=INT_MAX)
pick a point from a free-space interval. Helper function for creating feasible paths.
Definition: algorithm.cpp:572
Curve findShortestPathQ(int pa, int pb, Triangulation &tri)
given a diagonal in P, compute the mapped shortest-path in Q
Definition: poly_path.cpp:248
FreeSpace::ptr fs
underlying free-space
Definition: fs_path.h:48
static bool is_adjacent_to(const Graph &A, const Graph &B)
Definition: graph_m4ri.cpp:775
boost::shared_ptr< FreeSpace > ptr
smart pointer to FreeSpace object
Definition: freespace.h:92
Calculates a feasible path in the Free-Space given a start point (0,0) and an end point (n-1,...
Definition: fs_path.h:44
virtual void clear()
Definition: fs_path.cpp:222
double mapFromPToQ(int p) const
Definition: fs_path.cpp:811
double max(double a, double b)
maximum function with checks for NAN
Definition: numeric.h:233
void update(const Graph::ptr result, double epsilon)
compute a feasible path from the results of the simple polygon algorithm
Definition: poly_path.cpp:17