Loading [MathJax]/extensions/tex2jax.js
Free Electron
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
geodesic_cpp_03_02_2008/geodesic_algorithm_graph_base.h
1 #ifndef GEODESIC_ALGORITHM_GRAPH_BASE_010907
2 #define GEODESIC_ALGORITHM_GRAPH_BASE_010907
3 
4 #include "geodesic_algorithm_base.h"
5 #include "geodesic_mesh_elements.h"
6 #include <vector>
7 #include <set>
8 #include <assert.h>
9 
10 namespace geodesic{
11 
12 template<class Node>
13 class GeodesicAlgorithmGraphBase: public GeodesicAlgorithmBase
14 {
15 public:
16  typedef Node* node_pointer;
17 
18  GeodesicAlgorithmGraphBase(geodesic::Mesh* mesh):
19  GeodesicAlgorithmBase(mesh)
20  {};
21 
22  ~GeodesicAlgorithmGraphBase(){};
23 
24  void propagate(std::vector<SurfacePoint>& sources,
25  double max_propagation_distance = GEODESIC_INF, //propagation algorithm stops after reaching the certain distance from the source
26  std::vector<SurfacePoint>* stop_points = NULL); //or after ensuring that all the stop_points are covered
27 
28  void trace_back(SurfacePoint& destination, //trace back piecewise-linear path
29  std::vector<SurfacePoint>& path);
30 
31  unsigned best_source(SurfacePoint& point, //quickly find what source this point belongs to and what is the distance to this source
32  double& best_source_distance);
33 
34  void print_statistics()
35  {
36  GeodesicAlgorithmBase::print_statistics();
37 
38  double memory = m_nodes.size()*sizeof(Node);
39  std::cout << "uses about " << memory/1e6 << "Mb of memory" <<std::endl;
40  }
41 
42 protected:
43  unsigned node_index(vertex_pointer v) //gives index of the node that corresponds to this vertex
44  {
45  return v->id();
46  };
47 
48  void set_sources(std::vector<SurfacePoint>& sources)
49  {
50  m_sources = sources;
51  }
52 
53  node_pointer best_first_node(SurfacePoint& point, double& best_total_distance)
54  {
55  node_pointer best_node = NULL;
56  if(point.type() == VERTEX)
57  {
58  vertex_pointer v = (vertex_pointer)point.base_element();
59  best_node = &m_nodes[node_index(v)];
60  best_total_distance = best_node->distance_from_source();
61  }
62  else
63  {
64  std::vector<node_pointer> possible_nodes;
65  list_nodes_visible_from_source(point.base_element(), possible_nodes);
66 
67  best_total_distance = GEODESIC_INF;
68  for(unsigned i=0; i<possible_nodes.size(); ++i)
69  {
70  node_pointer node = possible_nodes[i];
71 
72  double distance_from_dest = node->distance(&point);
73  if(node->distance_from_source() + distance_from_dest < best_total_distance)
74  {
75  best_total_distance = node->distance_from_source() + distance_from_dest;
76  best_node = node;
77  }
78  }
79  }
80 
81  //assert(best_node);
82  //assert(best_total_distance<GEODESIC_INF);
83  if(best_total_distance > m_propagation_distance_stopped) //result is unreliable
84  {
85  best_total_distance = GEODESIC_INF;
86  return NULL;
87  }
88  else
89  {
90  return best_node;
91  }
92  }; //quickly find what node will be the next one in geodesic path
93 
94  bool check_stop_conditions(unsigned& index); //check when propagation should stop
95 
96  virtual void list_nodes_visible_from_source(MeshElementBase* p,
97  std::vector<node_pointer>& storage) = 0; //list all nodes that belong to this mesh element
98 
99  virtual void list_nodes_visible_from_node(node_pointer node, //list all nodes that belong to this mesh element
100  std::vector<node_pointer>& storage,
101  std::vector<double>& distances,
102  double threshold_distance) = 0; //list only the nodes whose current distance is larger than the threshold
103 
104  std::vector<Node> m_nodes; //nodes of the graph
105 
106  typedef std::set<node_pointer, Node> queue_type;
107  queue_type m_queue;
108 
109  std::vector<SurfacePoint> m_sources; //for simplicity, we keep sources as they are
110 };
111 
112 template<class Node>
113 void GeodesicAlgorithmGraphBase<Node>::propagate(std::vector<SurfacePoint>& sources,
114  double max_propagation_distance, //propagation algorithm stops after reaching the certain distance from the source
115  std::vector<SurfacePoint>* stop_points) //or after ensuring that all the stop_points are covered
116 {
117  set_stop_conditions(stop_points, max_propagation_distance);
118  set_sources(sources);
119 
120  m_queue.clear();
121  m_propagation_distance_stopped = GEODESIC_INF;
122  for(unsigned i=0; i<m_nodes.size(); ++i)
123  {
124  m_nodes[i].clear();
125  }
126 
127  clock_t start = clock();
128 
129  std::vector<node_pointer> visible_nodes; //initialize vertices directly visible from sources
130  for(unsigned i=0; i<m_sources.size(); ++i)
131  {
132  SurfacePoint* source = &m_sources[i];
133  list_nodes_visible_from_source(source->base_element(),
134  visible_nodes);
135 
136  for(unsigned j=0; j<visible_nodes.size(); ++j)
137  {
138  node_pointer node = visible_nodes[j];
139  double distance = node->distance(source);
140  if(distance < node->distance_from_source())
141  {
142  node->distance_from_source() = distance;
143  node->source_index() = i;
144  node->previous() = NULL;
145  }
146  }
147  visible_nodes.clear();
148  }
149 
150  for(unsigned i=0; i<m_nodes.size(); ++i) //initialize the queue
151  {
152  if(m_nodes[i].distance_from_source() < GEODESIC_INF)
153  {
154  m_queue.insert(&m_nodes[i]);
155  }
156  }
157 
158  unsigned counter = 0;
159  unsigned satisfied_index = 0;
160 
161  std::vector<double> distances_between_nodes;
162  while(!m_queue.empty()) //main cycle
163  {
164  if(counter++ % 10 == 0) //check if we covered all required vertices
165  {
166  if (check_stop_conditions(satisfied_index))
167  {
168  break;
169  }
170  }
171 
172  node_pointer min_node = *m_queue.begin();
173  m_queue.erase(m_queue.begin());
174  assert(min_node->distance_from_source() < GEODESIC_INF);
175 
176  visible_nodes.clear();
177  distances_between_nodes.clear();
178  list_nodes_visible_from_node(min_node,
179  visible_nodes,
180  distances_between_nodes,
181  min_node->distance_from_source());
182 
183  for(unsigned i=0; i<visible_nodes.size(); ++i) //update all the adgecent vertices
184  {
185  node_pointer next_node = visible_nodes[i];
186 
187  if(next_node->distance_from_source() > min_node->distance_from_source() +
188  distances_between_nodes[i])
189  {
190  if(next_node->distance_from_source() < GEODESIC_INF) //remove it from the queue
191  {
192  typename queue_type::iterator iter = m_queue.find(next_node);
193  assert(iter != m_queue.end());
194  m_queue.erase(iter);
195  }
196  next_node->distance_from_source() = min_node->distance_from_source() +
197  distances_between_nodes[i];
198  next_node->source_index() = min_node->source_index();
199  next_node->previous() = min_node;
200  m_queue.insert(next_node);
201  }
202  }
203  }
204 
205  m_propagation_distance_stopped = m_queue.empty() ? GEODESIC_INF : (*m_queue.begin())->distance_from_source();
206  clock_t finish = clock();
207  m_time_consumed = (static_cast<double>(finish)-static_cast<double>(start))/CLOCKS_PER_SEC;
208  //std::cout << std::endl;
209 }
210 
211 template<class Node>
212 inline bool GeodesicAlgorithmGraphBase<Node>::check_stop_conditions(unsigned& index)
213 {
214  double queue_min_distance = (*m_queue.begin())->distance_from_source();
215 
216  if(queue_min_distance < m_max_propagation_distance)
217  {
218  return false;
219  }
220 
221  while(index < m_stop_vertices.size())
222  {
223  vertex_pointer v = m_stop_vertices[index].first;
224  Node& node = m_nodes[node_index(v)];
225  if(queue_min_distance < node.distance_from_source() + m_stop_vertices[index].second)
226  {
227  return false;
228  }
229  ++index;
230  }
231  return true;
232 }
233 
234 template<class Node>
235 inline void GeodesicAlgorithmGraphBase<Node>::trace_back(SurfacePoint& destination, //trace back piecewise-linear path
236  std::vector<SurfacePoint>& path)
237 {
238  path.clear();
239 
240  double total_path_length;
241  node_pointer node = best_first_node(destination, total_path_length);
242 
243  if(total_path_length>GEODESIC_INF/2.0) //unable to find the path
244  {
245  return;
246  }
247 
248  path.push_back(destination);
249 
250  if(node->distance(&destination) > 1e-50)
251  {
252  path.push_back(node->surface_point());
253  }
254 
255  while(node->previous()) //follow the path
256  {
257  node = node->previous();
258  path.push_back(node->surface_point());
259  }
260 
261  SurfacePoint& source = m_sources[node->source_index()]; //add source to the path if it is not already there
262  if(node->distance(&source) > 1e-50)
263  {
264  path.push_back(source);
265  }
266 }
267 
268 
269 template<class Node>
270 inline unsigned GeodesicAlgorithmGraphBase<Node>::best_source(SurfacePoint& point, //quickly find what source this point belongs to and what is the distance to this source
271  double& best_source_distance)
272 {
273  node_pointer node = best_first_node(point, best_source_distance);
274  return node ? node->source_index() : 0;
275 };
276 
277 } //geodesic
278 
279 #endif //GEODESIC_ALGORITHM_GRAPH_BASE_010907
Definition: geodesic_cpp_03_02_2008/geodesic_algorithm_base.h:11