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