Fréchet View  1.6.0
A Tool for Exploring Fréchet Distance Algorithms
graph_model.cpp
Go to the documentation of this file.
1 
2 #include <graph_model.h>
3 #include <iostream>
5 
6 using namespace frechet;
7 using namespace reach;
8 using namespace data;
9 
11 : IndexRange(HORIZONTAL, 0,0)
12 {}
13 
14 IndexRange::IndexRange(Orientation anori, int l, int u)
15 : ori(anori), lower(l),upper(u)
16 { }
17 
18 bool IndexRange::empty() const { return upper <= lower; }
20 
21 int IndexRange::len() const {
22  Q_ASSERT(upper>=lower);
23  return upper-lower;
24 }
25 
26 bool IndexRange::contains(int i) const {
27  return i>=lower && i < upper;
28 }
29 
30 bool IndexRange::contains(const IndexRange& that) const
31 {
32  Q_ASSERT(ori==that.ori);
33  return (that.lower >= this->lower) && (that.upper <= this->upper);
34 }
35 
37 {
38  Q_ASSERT(ori==b.ori);
39  return IndexRange(ori,
40  std::max(lower,b.lower),
41  std::min(upper,b.upper));
42 }
43 
45 {
46  Q_ASSERT(ori==b.ori);
49  return *this;
50 }
51 
52 bool IndexRange::intersects(const IndexRange& b) const
53 {
54  return (ori==b.ori)
55  && (upper > b.lower)
56  && (lower < b.upper);
57 }
58 
60 {
61  Q_ASSERT(this->ori==b.ori);
62  Q_ASSERT(this->upper==b.lower || b.upper==this->lower);
63  return IndexRange(ori,
64  std::min(lower,b.lower),
65  std::max(upper,b.upper));
66 }
67 
68 bool IndexRange::operator==(const IndexRange& that) const
69 {
70  return ori==that.ori
71  && lower==that.lower
72  && upper==that.upper;
73 }
74 
75 bool IndexRange::operator!=(const IndexRange& that) const
76 {
77  return ! operator==(that);
78 }
79 
81 {
82  return IndexRange(ori,lower+offset,upper+offset);
83 }
84 
86 {
87  return IndexRange(ori,lower-offset,upper-offset);
88 }
89 
91  Q_ASSERT(this->ori==b.ori);
92  Q_ASSERT(this->upper==b.lower || b.upper==this->lower);
95  return *this;
96 }
97 
99 {
100  lower -= offset;
101  upper -= offset;
102  return *this;
103 }
104 
106  return (Bias)((uint8_t)a | (uint8_t)b);
107 }
108 
110  a = (a|b);
111  return a;
112 }
113 
114 GraphModelAxis::GraphModelAxis() : map(),_max_index(0),_dim(0) { }
115 
116 void GraphModelAxis::insert1(double x, Bias bias)
117 {
118  Map::iterator i = map.find(x);
119  if (i==map.end()) {
120  map.insert(std::make_pair(x,BoundsIndex(-1,bias)));
121  }
122  else {
123  i->second.bias |= bias;
124  }
125 }
126 
136 void GraphModelAxis::insert2(double x, Bias bias)
137 {
138  insert1(x,bias);
139  insert1(x+_dim,bias);
140 }
141 
143 {
144  map.erase(x);
145 }
146 
147 const BoundsIndex& GraphModelAxis::lookup(double x) const
148 {
149  //Q_ASSERT(x >= 0.0 && x <= _dim);
150  Map::const_iterator i = map.find(x);
151  Q_ASSERT(i != map.end());
152  return i->second;
153 }
154 
156 {
157  Map::const_iterator i = map.lower_bound(x); // *i >= x
158  if (i==map.end())
159  return nullptr;
160  Q_ASSERT(i != map.end());
161  Q_ASSERT(i->first >= x);
162  if (i->first==x)
163  return &i->second;
164  --i;
165  if (i==map.end())
166  return nullptr;
167  Q_ASSERT(i->first < x);
168  return &i->second;
169 }
170 
172 {
173  Map::const_iterator i = map.upper_bound(x); // *i > x
174  if (i==map.end())
175  return nullptr;
176  Q_ASSERT(i != map.end());
177  Q_ASSERT(i->first > x);
178  return &i->second;
179 }
180 
181 void GraphModelAxis::indexify(int start) {
182  _max_index = start;
183  for(Map::iterator i=map.begin(); i != map.end(); ++i)
184  {
185  i->second.index = _max_index++;
186  if (i->second.bias==LOWER_UPPER) _max_index++;
187  // Single-Value Intervals [x,x] need to be indexed separately.
188  // Reserve an index for them.
189  }
190 }
191 
192 void GraphModelAxis::createReverseMap(std::vector<Interval>& result) const
193 {
194  if (map.empty()) return;
195 
196  Map::const_iterator i=map.begin();
197  Map::const_iterator j=i;
198  ++j;
199 
200  result.reserve(map.size());
201  for( ; j != map.end(); ++i,++j)
202  {
203  Q_ASSERT(i->second.index==result.size());
204  if (i->second.bias==LOWER_UPPER)
205  result.push_back(Interval(i->first,i->first));
206  if (j != map.end())
207  result.push_back(Interval(i->first,j->first));
208  }
209  Q_ASSERT(i != map.end());
210  if (i->second.bias==LOWER_UPPER)
211  result.push_back(Interval(i->first,i->first));
212 
213  result.push_back(Interval(result.back().upper(),_dim));
214 }
215 
216 
218  switch(ori) {
219  case HORIZONTAL: //Q_ASSERT((axis[HORIZONTAL]._dim % 2) == 0);
220  return axis[HORIZONTAL]._dim;
221  case VERTICAL: return axis[VERTICAL]._dim;
222  }
223  Q_ASSERT(false); // don't come here
224  return -1;
225 }
226 
228  switch(ori) {
229  case HORIZONTAL: return 2*axis[HORIZONTAL]._dim;
230  case VERTICAL: return axis[VERTICAL]._dim;
231  }
232  Q_ASSERT(false); // don't come here
233  return -1;
234 }
235 
236 
238 {
239  switch(ori) {
240  case HORIZONTAL: return axis[HORIZONTAL]._max_index;
241  case VERTICAL: return axis[VERTICAL]._max_index;
242  }
243  Q_ASSERT(false); // don't come here
244  return -1;
245 }
246 
248 {
249  return count2(HORIZONTAL) + count2(VERTICAL);
250 }
251 /*
252 BoundsIndex GraphModel::lookup(Orientation ori, double x) const
253 {
254  Q_ASSERT(x >= 0.0);
255  Q_ASSERT(x <= dim2(ori));
256  return axis[ori].lookup(x);
257 }
258 */
260  Orientation ori,
261  const Interval& ival,
262  bool upperBoundInclusive) const
263 {
264  // Lookup lower and upper bounds
265  BoundsIndex low = axis[ori].lookup(ival.lower());
266  if (ival.lower()==ival.upper()) {
267  // Single-point interval; it must be present in the map
268  Q_ASSERT(low.bias==LOWER_UPPER);
269  if (upperBoundInclusive)
270  return IndexRange(ori, low.index,low.index+1);
271  else
272  return IndexRange(ori, low.index,low.index);
273  }
274  // else
275  //Q_ASSERT(ival.upper() <= 2*axis[ori]._dim);
276 
277  if (ori==HORIZONTAL && ival.upper() == 2*axis[ori]._dim) {
278  return IndexRange(ori, low.index, count2(ori));
279  }
280  else {
281  BoundsIndex upp = axis[ori].lookup(ival.upper());
282  if ((upp.bias==LOWER_UPPER) && upperBoundInclusive)
283  return IndexRange(ori, low.index,upp.index+1);
284  else
285  return IndexRange(ori, low.index,upp.index);
286  }
287 }
288 
289 IndexRange
291  Orientation ori,
292  const Interval &ival) const
293 {
294  const BoundsIndex* low = axis[ori].lookupLowerEqual(ival.lower());
295  const BoundsIndex* upp = axis[ori].lookupLarger(ival.upper());
296 
297  if (upp && upp->bias==LOWER_UPPER)
298  return IndexRange(ori, low ? low->index:0, upp->index+1);
299  else if (upp)
300  return IndexRange(ori, low ? low->index:0, upp->index);
301  else
302  return IndexRange(ori, low ? low->index:0, count2(ori));
303 }
304 
306 {
307  Q_ASSERT(b);
308  return map(b->ori, *b, true);
309 }
310 
312 {
313  return map_lower(p->ori, p->lower());
314 }
315 
317 {
318  return map_upper(p->ori, p->upper(), true);
319 }
320 
321 int GraphModel::map_lower(Orientation ori, double x) const
322 {
323  BoundsIndex low = axis[ori].lookup(x);
324  return low.index;
325 }
326 
327 int GraphModel::map_upper(Orientation ori, double x, bool inclusive) const
328 {
329  if (ori==HORIZONTAL && x==2*axis[ori]._dim)
330  return count2(HORIZONTAL);
331 
332  BoundsIndex upp = axis[ori].lookup(x);
333  if (inclusive && upp.bias==LOWER_UPPER)
334  return upp.index+1;
335  else
336  return upp.index;
337 }
338 
340 {
341  //int h1 = graphModel()->count1(HORIZONTAL);
342  Q_ASSERT(ma.ori==HORIZONTAL && mb.ori==HORIZONTAL);
343  //Q_ASSERT((ma.upper==mb.lower) || (ma.upper==mb.lower+h1));
344 
345  if (ma.upper==mb.lower)
346  return ma + mb;
347  else {
348  IndexRange mb2 = this->shiftedHorizontally(mb);
349  return ma + mb2;
350  }
351 }
352 
354 {
355  initHorizontal(fs);
356  initVertical(fs);
357 
358  // GraphModel represents a DOUBLE Free-Space
359  // The Horizontal axis is be duplicated (@see lookup).
360 
362  axis[VERTICAL].indexify(0);
363 
364  //hcount1 = map_lower(HORIZONTAL,dim1(HORIZONTAL));
365 
366  // Q_ASSERT(count2(HORIZONTAL)%2==0);
367 // Q_ASSERT(map_lower(HORIZONTAL,dim1(HORIZONTAL))==count1(HORIZONTAL));
368 
371 }
372 
373 bool GraphModel::empty() const {
374  return count2(HORIZONTAL)==0 || count2(VERTICAL)==0;
375 }
376 
378 {
380  ax._dim = fs->m-1;
381  for(int i=0; i < fs->n; ++i)
382  {
383  const Interval& L = fs->cell(i,0).L;
384  bool inside = (L.lower()==0.0);
385  if (inside) {
386  ax.insert1(0.0, LOWER);
387  }
388 
389  for(int j=0; j < fs->m-1; ++j)
390  {
391  const Interval& L = fs->cell(i,j).L;
392  const Interval& L2 = fs->cell(i,j+1).L;
393 
394  if (inside) {
395  // integer boundaries
396  ax.insert1((double)j,LOWER_UPPER);
397  }
398 
399  if (!L) {
400  inside=false;
401  }
402  else if (L.lower() > 0.0) {
403  ax.insert1(L.lower() + (double)j,
404  (L.lower()==L.upper()) ? LOWER_UPPER:LOWER);
405  inside = (L.upper() >= 1.0) && (L2.lower()==0.0);
406  if (!inside) ax.insert1(L.upper() + (double)j,UPPER);
407  }
408  else if (inside) {
409  Q_ASSERT(L.lower()==0.0);
410  inside = (L.upper() >= 1.0) && (L2.lower()==0.0);
411  if (!inside) ax.insert1(L.upper() + (double)j,UPPER);
412  }
413  }
414 
415  if (inside) {
416  ax.insert1((double)(fs->m-1),UPPER);
417  }
418  }
419 }
420 
422 {
424  ax._dim = fs->n-1;
425  for(int j=0; j < fs->m; ++j)
426  {
427  const Interval& B = fs->cell(0,j).B;
428  bool inside = (B.lower()==0.0);
429  if (inside) {
430  ax.insert2(0.0, LOWER);
431  }
432 
433  for(int i=0; i < fs->n-1; ++i)
434  {
435  const Interval& B = fs->cell(i,j).B;
436 
437  if (true) {
438  // integer boundaries
439  ax.insert2((double)i,LOWER_UPPER);
440  }
441 
442  if (!B) {
443  inside=false;
444  }
445  else if (B.lower() > 0.0) {
446  ax.insert2(B.lower() + (double)i,
447  (B.lower()==B.upper()) ? LOWER_UPPER:LOWER);
448  inside = (B.upper() >= 1.0) && (i+1 < fs->n) && (fs->cell(i+1,j).B.lower()==0.0);
449  if (!inside) ax.insert2(B.upper() + (double)i,UPPER);
450  }
451  else if (inside) {
452  Q_ASSERT(B.lower()==0.0);
453  inside = (B.upper() >= 1.0) && (i+1 < fs->n) && (fs->cell(i+1,j).B.lower()==0.0);
454  if (!inside) ax.insert2(B.upper() + (double)i,UPPER);
455  }
456  }
457  ax.remove((double)2*ax._dim);
458  //ax.insert2((double)(fs->n-1),LOWER_UPPER);
459  }
460 }
461 
void createReverseMap(std::vector< Interval > &result) const
create a reverse mapping; mapping graph nodes to free-space intervals
void insert1(double x, Bias bias)
insert one value, with an optional bias. Initially will be mapped to an invalid Graph node....
Bias
bias of a GraphModel boundary (how shall we explain this?)
Definition: graph_model.h:150
bool contains(int i) const
containment test
Definition: graph_model.cpp:26
IndexRange mapClosest(Orientation ori, const Interval &ival) const
map a free-space interval to the closest graph nodes
GraphModelAxis axis[2]
horizontal and vertical mapping
Definition: graph_model.h:301
Bias operator|(Bias a, Bias b)
union operator
int _max_index
maximum node index
Definition: graph_model.h:214
void remove(double x)
remove a value
Bias bias
bias: inclusive to lower / upper interval
Definition: graph_model.h:179
boundary is inclusive to adjacent upper interval
Definition: graph_model.h:153
global definitions for all algorithms.
const BoundsIndex * lookupLarger(double x) const
look up a node that is larger than value
const Orientation ori
horizontal or vertical
Definition: boundary.h:318
int map_lower(Pointer p) const
map the lower bound of a reachability structure interval
GraphModelAxis()
empty constructor
IndexRange operator+(const IndexRange &b) const
union operator
Definition: graph_model.cpp:59
IndexRange operator &(const IndexRange &b) const
intersection operator
Definition: graph_model.cpp:36
void clear()
clear range
Definition: graph_model.cpp:19
int dim2(Orientation ori) const
IndexRange & operator-=(int offset)
shift operator
Definition: graph_model.cpp:98
boundary interval in the reachability structure. Represents an interval on the boundary of the FreeSp...
Definition: boundary.h:285
bool intersects(const IndexRange &b) const
intersection test
Definition: graph_model.cpp:52
IndexRange()
empty constructor
Definition: graph_model.cpp:10
double upper() const
Definition: interval.h:96
int upper
upper index (exclusive)
Definition: graph_model.h:23
int index
index of node in reachability graph
Definition: graph_model.h:177
int lower
lower index (inclusive)
Definition: graph_model.h:21
int dim1(Orientation ori) const
mapping within a GraphModel
Definition: graph_model.h:175
IndexRange operator-(int offset) const
shift operator
Definition: graph_model.cpp:85
a range of node indices in a Reachability Graph
Definition: graph_model.h:17
Orientation
Segment Orientation.
Definition: boundary.h:31
void insert2(double x, Bias bias)
insert a value plus value shifted by free-space width (so that we can model a double-free-space diagr...
IndexRange map(Orientation ori, const Interval &, bool upperBoundInclusive) const
map a free-space interval to a range of graph nodes
double lower() const
Definition: interval.h:92
double min(double a, double b)
minimum function with checks for NAN
Definition: numeric.h:222
IndexRange & operator+=(const IndexRange &b)
union operator
Definition: graph_model.cpp:90
boundary is inclusive to adjacent lower interval
Definition: graph_model.h:152
const BoundsIndex & lookup(double x) const
look up a value and map it to a graph node
Bias & operator|=(Bias &a, Bias b)
union operator
bool operator!=(const IndexRange &that) const
comparison operator
Definition: graph_model.cpp:75
IndexRange mergedHMask(const IndexRange &m1, const IndexRange &m2) const
merged two node ranges representing the horizontal masks of reachability graph (see frechet::reach::G...
IndexRange & operator&=(const IndexRange &b)
intersection operator
Definition: graph_model.cpp:44
void init(Structure &prototype)
void indexify(int start)
assign graph node indexes to all values (intervals)
manages a mapping between free-space intervals (continous, floating point) to reachability graph node...
Definition: graph_model.h:207
Orientation ori
horizontal or vertical part of the reachability structure?
Definition: graph_model.h:19
std::vector< Interval > reversed[2]
reverse mapping from nodes to intervals (horizontal and vertical)
Definition: graph_model.h:303
const BoundsIndex * lookupLowerEqual(double x) const
look up a node that is lower or equal to value
void initHorizontal(const FreeSpace::ptr fs)
set up the mappings for horizontal intervals
IndexRange shiftedHorizontally(const IndexRange &r) const
map a node range to its counterpart in the duplicated part of a double-free-space
Definition: graph_model.h:355
int _dim
width or height of the free-space diagram
Definition: graph_model.h:216
an interval of two double values.
Definition: interval.h:31
boost::shared_ptr< FreeSpace > ptr
smart pointer to FreeSpace object
Definition: freespace.h:92
int map_upper(Pointer p) const
map the upper bound of a reachability structure interval
void initVertical(const FreeSpace::ptr fs)
set up the mappings for vertical intervals
bool operator==(const IndexRange &that) const
comparison operator
Definition: graph_model.cpp:68
double max(double a, double b)
maximum function with checks for NAN
Definition: numeric.h:233