Loading [MathJax]/extensions/tex2jax.js
Free Electron
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
geodesic_cpp_mod/geodesic_algorithm_exact_elements.h
1 //Copyright (C) 2008 Danil Kirsanov, MIT License
2 #ifndef GEODESIC_ALGORITHM_EXACT_ELEMENTS_20071231
3 #define GEODESIC_ALGORITHM_EXACT_ELEMENTS_20071231
4 
5 #include "geodesic_memory.h"
6 #include "geodesic_mesh_elements.h"
7 #include <vector>
8 #include <cmath>
9 #include <algorithm>
10 
11 namespace geodesic{
12 
13 class Interval;
14 class IntervalList;
15 typedef Interval* interval_pointer;
16 typedef IntervalList* list_pointer;
17 
18 class Interval //interval of the edge
19 {
20 public:
21 
22  Interval(){};
23  ~Interval(){};
24 
25  enum DirectionType
26  {
27  FROM_FACE_0,
28  FROM_FACE_1,
29  FROM_SOURCE,
30  UNDEFINED_DIRECTION
31  };
32 
33  double signal(double x) //geodesic distance function at point x
34  {
35  FEASSERT(x>=0.0 && x <= m_edge->length());
36 
37  if(m_d == GEODESIC_INF)
38  {
39  return GEODESIC_INF;
40  }
41  else
42  {
43  double dx = x - m_pseudo_x;
44  if(m_pseudo_y == 0.0)
45  {
46  return m_d + std::abs(dx);
47  }
48  else
49  {
50  return m_d + sqrt(dx*dx + m_pseudo_y*m_pseudo_y);
51  }
52  }
53  }
54 
55  double max_distance(double end)
56  {
57  if(m_d == GEODESIC_INF)
58  {
59  return GEODESIC_INF;
60  }
61  else
62  {
63  double a = std::abs(m_start - m_pseudo_x);
64  double b = std::abs(end - m_pseudo_x);
65 
66  return a > b ? m_d + sqrt(a*a + m_pseudo_y*m_pseudo_y):
67  m_d + sqrt(b*b + m_pseudo_y*m_pseudo_y);
68  }
69  }
70 
71  void compute_min_distance(double stop) //compute min, given c,d theta, start, end.
72  {
73  FEASSERT(stop > m_start);
74 
75  if(m_d == GEODESIC_INF)
76  {
77  m_min = GEODESIC_INF;
78  }
79  else if(m_start > m_pseudo_x)
80  {
81  m_min = signal(m_start);
82  }
83  else if(stop < m_pseudo_x)
84  {
85  m_min = signal(stop);
86  }
87  else
88  {
89  FEASSERT(m_pseudo_y<=0);
90  m_min = m_d - m_pseudo_y;
91  }
92  }
93  //compare two intervals in the queue
94  bool operator()(interval_pointer const x, interval_pointer const y) const
95  {
96  if(x->min() != y->min())
97  {
98  return x->min() < y->min();
99  }
100  else if(x->start() != y->start())
101  {
102  return x->start() < y->start();
103  }
104  else
105  {
106  return x->edge()->id() < y->edge()->id();
107  }
108  }
109 
110  double stop() //return the endpoint of the interval
111  {
112  return m_next ? m_next->start() : m_edge->length();
113  }
114 
115  double hypotenuse(double a, double b)
116  {
117  return sqrt(a*a + b*b);
118  }
119 
120  void find_closest_point(double const x,
121  double const y,
122  double& offset,
123  double& distance); //find the point on the interval that is closest to the point (alpha, s)
124 
125  double& start(){return m_start;};
126  double& d(){return m_d;};
127  double& pseudo_x(){return m_pseudo_x;};
128  double& pseudo_y(){return m_pseudo_y;};
129  double& min(){return m_min;};
130  interval_pointer& next(){return m_next;};
131  edge_pointer& edge(){return m_edge;};
132  DirectionType& direction(){return m_direction;};
133  bool visible_from_source(){return m_direction == FROM_SOURCE;};
134  unsigned& source_index(){return m_source_index;};
135 
136  void initialize(edge_pointer edge,
137  SurfacePoint* point = NULL,
138  unsigned source_index = 0);
139 
140 protected:
141  double m_start; //initial point of the interval on the edge
142  double m_d; //distance from the source to the pseudo-source
143  double m_pseudo_x; //coordinates of the pseudo-source in the local coordinate system
144  double m_pseudo_y; //y-coordinate should be always negative
145  double m_min; //minimum distance on the interval
146 
147  interval_pointer m_next; //pointer to the next interval in the list
148  edge_pointer m_edge; //edge that the interval belongs to
149  unsigned m_source_index; //the source it belongs to
150  DirectionType m_direction; //where the interval is coming from
151 };
152 
153 struct IntervalWithStop : public Interval
154 {
155 public:
156  double& stop(){return m_stop;};
157 protected:
158  double m_stop;
159 };
160 
161 class IntervalList //list of the of intervals of the given edge
162 {
163 public:
164  IntervalList(){m_first = NULL;};
165  ~IntervalList(){};
166 
167  void clear()
168  {
169  m_first = NULL;
170  };
171 
172  void initialize(edge_pointer e)
173  {
174  m_edge = e;
175  m_first = NULL;
176  };
177 
178  interval_pointer covering_interval(double offset) //returns the interval that covers the offset
179  {
180  FEASSERT(offset >= 0.0 && offset <= m_edge->length());
181 
182  interval_pointer p = m_first;
183  while(p && p->stop() < offset)
184  {
185  p = p->next();
186  }
187 
188  return p;// && p->start() <= offset ? p : NULL;
189  };
190 
191  void find_closest_point(SurfacePoint* point,
192  double& offset,
193  double& distance,
194  interval_pointer& interval)
195  {
196  interval_pointer p = m_first;
197  distance = GEODESIC_INF;
198  interval = NULL;
199 
200  double x,y;
201  m_edge->local_coordinates(point, x, y);
202 
203  while(p)
204  {
205  if(p->min()<GEODESIC_INF)
206  {
207  double o, d;
208  p->find_closest_point(x, y, o, d);
209  if(d < distance)
210  {
211  distance = d;
212  offset = o;
213  interval = p;
214  }
215  }
216  p = p->next();
217  }
218  };
219 
220  unsigned number_of_intervals()
221  {
222  interval_pointer p = m_first;
223  unsigned count = 0;
224  while(p)
225  {
226  ++count;
227  p = p->next();
228  }
229  return count;
230  }
231 
232  interval_pointer last()
233  {
234  interval_pointer p = m_first;
235  if(p)
236  {
237  while(p->next())
238  {
239  p = p->next();
240  }
241  }
242  return p;
243  }
244 
245  double signal(double x)
246  {
247  interval_pointer interval = covering_interval(x);
248 
249  return interval ? interval->signal(x) : GEODESIC_INF;
250  }
251 
252  interval_pointer& first(){return m_first;};
253  edge_pointer& edge(){return m_edge;};
254 private:
255  interval_pointer m_first; //pointer to the first member of the list
256  edge_pointer m_edge; //edge that owns this list
257 };
258 
259 class SurfacePointWithIndex : public SurfacePoint
260 {
261 public:
262  unsigned index(){return m_index;};
263 
264  void initialize(SurfacePoint& p, unsigned index)
265  {
266  SurfacePoint::initialize(p);
267  m_index = index;
268  }
269 
270  bool operator()(SurfacePointWithIndex* x, SurfacePointWithIndex* y) const //used for sorting
271  {
272  FEASSERT(x->type() != UNDEFINED_POINT && y->type() !=UNDEFINED_POINT);
273 
274  if(x->type() != y->type())
275  {
276  return x->type() < y->type();
277  }
278  else
279  {
280  return x->base_element()->id() < y->base_element()->id();
281  }
282  }
283 
284 private:
285  unsigned m_index;
286 };
287 
288 class SortedSources : public std::vector<SurfacePointWithIndex>
289 {
290 private:
291  typedef std::vector<SurfacePointWithIndex*> sorted_vector_type;
292 public:
293  typedef sorted_vector_type::iterator sorted_iterator;
294  typedef std::pair<sorted_iterator, sorted_iterator> sorted_iterator_pair;
295 
296  sorted_iterator_pair sources(base_pointer mesh_element)
297  {
298  m_search_dummy.base_element() = mesh_element;
299 
300  return equal_range(m_sorted.begin(),
301  m_sorted.end(),
302  &m_search_dummy,
303  m_compare_less);
304  }
305 
306  void initialize(std::vector<SurfacePoint>& sources) //we initialize the sources by copie
307  {
308  resize(sources.size());
309  m_sorted.resize(sources.size());
310  for(unsigned i=0; i<sources.size(); ++i)
311  {
312  SurfacePointWithIndex& p = *(begin() + i);
313 
314  p.initialize(sources[i],i);
315  m_sorted[i] = &p;
316  }
317 
318  std::sort(m_sorted.begin(), m_sorted.end(), m_compare_less);
319  };
320 
321  SurfacePointWithIndex& operator[](unsigned i)
322  {
323  FEASSERT(i < size());
324  return *(begin() + i);
325  }
326 
327 private:
328  sorted_vector_type m_sorted;
329  SurfacePointWithIndex m_search_dummy; //used as a search template
330  SurfacePointWithIndex m_compare_less; //used as a compare functor
331 };
332 
333 
334 inline void Interval::find_closest_point(double const rs,
335  double const hs,
336  double& r,
337  double& d_out) //find the point on the interval that is closest to the point (alpha, s)
338  {
339  if(m_d == GEODESIC_INF)
340  {
341  r = GEODESIC_INF;
342  d_out = GEODESIC_INF;
343  return;
344  }
345 
346  double hc = -m_pseudo_y;
347  double rc = m_pseudo_x;
348  double end = stop();
349 
350  double local_epsilon = SMALLEST_INTERVAL_RATIO*m_edge->length();
351  if(std::abs(hs+hc) < local_epsilon)
352  {
353  if(rs<=m_start)
354  {
355  r = m_start;
356  d_out = signal(m_start) + std::abs(rs - m_start);
357  }
358  else if(rs>=end)
359  {
360  r = end;
361  d_out = signal(end) + fabs(end - rs);
362  }
363  else
364  {
365  r = rs;
366  d_out = signal(rs);
367  }
368  }
369  else
370  {
371  double ri = (rs*hc + hs*rc)/(hs+hc);
372 
373  if(ri<m_start)
374  {
375  r = m_start;
376  d_out = signal(m_start) + hypotenuse(m_start - rs, hs);
377  }
378  else if(ri>end)
379  {
380  r = end;
381  d_out = signal(end) + hypotenuse(end - rs, hs);
382  }
383  else
384  {
385  r = ri;
386  d_out = m_d + hypotenuse(rc - rs, hc + hs);
387  }
388  }
389  }
390 
391 
392 inline void Interval::initialize(edge_pointer edge,
393  SurfacePoint* source,
394  unsigned source_index)
395 {
396  m_next = NULL;
397  //m_geodesic_previous = NULL;
398  m_direction = UNDEFINED_DIRECTION;
399  m_edge = edge;
400  m_source_index = source_index;
401 
402  m_start = 0.0;
403  //m_stop = edge->length();
404  if(!source)
405  {
406  m_d = GEODESIC_INF;
407  m_min = GEODESIC_INF;
408  return;
409  }
410  m_d = 0;
411 
412  if(source->base_element()->type() == VERTEX)
413  {
414  if(source->base_element()->id() == edge->v0()->id())
415  {
416  m_pseudo_x = 0.0;
417  m_pseudo_y = 0.0;
418  m_min = 0.0;
419  return;
420  }
421  else if(source->base_element()->id() == edge->v1()->id())
422  {
423  m_pseudo_x = stop();
424  m_pseudo_y = 0.0;
425  m_min = 0.0;
426  return;
427  }
428  }
429 
430  edge->local_coordinates(source, m_pseudo_x, m_pseudo_y);
431  m_pseudo_y = -m_pseudo_y;
432 
433  compute_min_distance(stop());
434 }
435 
436 } //geodesic
437 
438 #endif //GEODESIC_ALGORITHM_EXACT_ELEMENTS_20071231
Definition: geodesic_cpp_03_02_2008/geodesic_algorithm_base.h:11