Loading [MathJax]/extensions/tex2jax.js
Free Electron
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
geodesic_cpp_mod/geodesic_algorithm_subdivision.h
1 //Copyright (C) 2008 Danil Kirsanov, MIT License
2 #ifndef GEODESIC_ALGORITHM_SUBDIVISION_122806
3 #define GEODESIC_ALGORITHM_SUBDIVISION_122806
4 
5 #include "geodesic_algorithm_graph_base.h"
6 #include "geodesic_mesh_elements.h"
7 #include <vector>
8 #include <set>
9 
10 namespace geodesic{
11 
12 class SubdivisionNode: public SurfacePoint
13 {
14  typedef SubdivisionNode* node_pointer;
15 public:
16  SubdivisionNode(){};
17 
18  template <class Pointer>
19  SubdivisionNode(Pointer p):
20  SurfacePoint(p),
21  m_previous(NULL),
22  m_distance(0.0)
23  {};
24 
25  template <class Pointer, class Parameter>
26  SubdivisionNode(Pointer p, Parameter param):
27  SurfacePoint(p, param),
28  m_previous(NULL),
29  m_distance(0.0)
30  {};
31 
32  ~SubdivisionNode(){};
33 
34  double& distance_from_source(){return m_distance;};
35  node_pointer& previous(){return m_previous;};
36  unsigned& source_index(){return m_source_index;};
37 
38  void clear()
39  {
40  m_distance = GEODESIC_INF;
41  m_previous = NULL;
42  }
43 
44  bool operator()(node_pointer const s1, node_pointer const s2) const
45  {
46  if(s1 == s2)
47  {
48  return false;
49  }
50  if(s1->distance_from_source() != s2->distance_from_source())
51  {
52  return s1->distance_from_source() < s2->distance_from_source();
53  }
54 /* if(s1->type() != s2->type())
55  {
56  return s1->type() < s2->type();
57  }
58  if(s1->base_element()->id() != s2->base_element()->id())
59  {
60  return s1->base_element()->id() < s2->base_element()->id();
61  } */
62  if(s1->x() != s2->x()) //two nodes cannot be located in the same space
63  {
64  return s1->x() < s2->x();
65  }
66  if(s1->y() != s2->y())
67  {
68  return s1->y() < s2->y();
69  }
70  if(s1->z() != s2->z())
71  {
72  return s1->z() < s2->z();
73  }
74 
75  FEASSERT(0);
76  return true;
77  };
78 
79  SurfacePoint& surface_point(){return static_cast<SurfacePoint&>(*this);};
80 
81 private:
82  double m_distance; //distance to the closest source
83  unsigned m_source_index; //closest source index
84  node_pointer m_previous; //previous node in the geodesic path
85 };
86 
87 class GeodesicAlgorithmSubdivision: public GeodesicAlgorithmGraphBase<SubdivisionNode>
88 {
89  typedef SubdivisionNode Node;
90 public:
91  GeodesicAlgorithmSubdivision(geodesic::Mesh* mesh = NULL,
92  unsigned subdivision_level = 0):
93  GeodesicAlgorithmGraphBase<Node>(mesh)
94  {
95  m_type = SUBDIVISION;
96 
97  m_nodes.reserve(mesh->vertices().size());
98  for(unsigned i=0; i<mesh->vertices().size(); ++i)
99  {
100  vertex_pointer v = &mesh->vertices()[i];
101  m_nodes.push_back(Node(v)); //!!
102  }
103 
104  set_subdivision_level(subdivision_level);
105  };
106 
107  ~GeodesicAlgorithmSubdivision(){};
108 
109  unsigned subdivision_level(){return m_subdivision_level;};
110 
111  void set_subdivision_level(unsigned subdivision_level)
112  {
113  m_subdivision_level = subdivision_level;
114 
115  m_nodes.resize(m_mesh->vertices().size());
116  m_nodes.reserve(m_mesh->vertices().size() +
117  m_mesh->edges().size()*subdivision_level);
118 
119  for(unsigned i=0; i<m_mesh->edges().size(); ++i)
120  {
121  edge_pointer e = &m_mesh->edges()[i];
122  for(unsigned i=0; i<subdivision_level; ++i)
123  {
124  double offset = (double)(i+1)/(double)(subdivision_level+1);
125  m_nodes.push_back(Node(e, offset));
126  }
127  }
128  };
129 
130 protected:
131  void list_nodes_visible_from_source(MeshElementBase* p,
132  std::vector<node_pointer>& storage); //list all nodes that belong to this mesh element
133 
134  void list_nodes_visible_from_node(node_pointer node, //list all nodes that belong to this mesh element
135  std::vector<node_pointer>& storage,
136  std::vector<double>& distances,
137  double threshold_distance); //list only the nodes whose current distance is larger than the threshold
138 
139  unsigned node_indexx(edge_pointer e)
140  {
141  return e->id()*m_subdivision_level + m_mesh->vertices().size();
142  };
143 
144 private:
145  void list_nodes(MeshElementBase* p, //list nodes that belong to this mesh element
146  std::vector<node_pointer>& storage,
147  double threshold_distance = -1.0); //list only the nodes whose current distance is larger than the threshold
148 
149  unsigned m_subdivision_level; //when level is equal to 1, this algorithm corresponds to the Dijkstra algorithm
150 };
151 
152 inline void GeodesicAlgorithmSubdivision::list_nodes(MeshElementBase* p,
153  std::vector<node_pointer>& storage,
154  double threshold_distance)
155 {
156  FEASSERT(p->type() != UNDEFINED_POINT);
157 
158  if(p->type() == VERTEX)
159  {
160  vertex_pointer v = static_cast<vertex_pointer>(p);
161  node_pointer node = &m_nodes[node_index(v)];
162  if(node->distance_from_source() > threshold_distance)
163  {
164  storage.push_back(node);
165  }
166  }
167  else if(p->type() == EDGE)
168  {
169  edge_pointer e = static_cast<edge_pointer>(p);
170  unsigned node_index = node_indexx(e);
171  for(unsigned i=0; i<m_subdivision_level; ++i)
172  {
173  node_pointer node = &m_nodes[node_index++];
174  if(node->distance_from_source() > threshold_distance)
175  {
176  storage.push_back(node);
177  }
178  }
179  }
180  //FACE has no nodes
181 }
182 
183 void GeodesicAlgorithmSubdivision::list_nodes_visible_from_source(MeshElementBase* p,
184  std::vector<node_pointer>& storage)
185 {
186  FEASSERT(p->type() != UNDEFINED_POINT);
187 
188  if(p->type() == FACE)
189  {
190  face_pointer f = static_cast<face_pointer>(p);
191  for(unsigned i=0; i<3; ++i)
192  {
193  list_nodes(f->adjacent_vertices()[i],storage);
194  list_nodes(f->adjacent_edges()[i],storage);
195  }
196  }
197  else if(p->type() == EDGE)
198  {
199  list_nodes(p,storage);
200  list_nodes(p->adjacent_vertices()[0],storage);
201  list_nodes(p->adjacent_vertices()[1],storage);
202  }
203  else //VERTEX
204  {
205  list_nodes(p,storage);
206  }
207 }
208 
209 void GeodesicAlgorithmSubdivision::list_nodes_visible_from_node(node_pointer node, //list all nodes that belong to this mesh element
210  std::vector<node_pointer>& storage,
211  std::vector<double>& distances,
212  double threshold_distance)
213 {
214  MeshElementBase* p = node->base_element();
215  FEASSERT(p->type() != UNDEFINED_POINT);
216  FEASSERT(storage.size() == distances.size());
217 
218  if(p->type() == VERTEX)
219  {
220  vertex_pointer v = static_cast<vertex_pointer>(p);
221 
222  for(unsigned i=0; i<v->adjacent_edges().size(); ++i)
223  {
224  edge_pointer e = v->adjacent_edges()[i];
225  vertex_pointer v_opposite = e->opposite_vertex(v);
226  list_nodes(e, storage, threshold_distance);
227  list_nodes(v_opposite, storage, threshold_distance);
228  }
229  for(unsigned i=0; i<v->adjacent_faces().size(); ++i)
230  {
231  face_pointer f = v->adjacent_faces()[i];
232  edge_pointer e = f->opposite_edge(v);
233  list_nodes(e, storage, threshold_distance);
234  }
235  }
236  else if(p->type() == EDGE)
237  {
238  edge_pointer e = static_cast<edge_pointer>(p);
239 
240  vertex_pointer v0 = e->adjacent_vertices()[0];
241  vertex_pointer v1 = e->adjacent_vertices()[1];
242  list_nodes(v0, storage, threshold_distance);
243  list_nodes(v1, storage, threshold_distance);
244 
245  for(unsigned i=0; i<e->adjacent_faces().size(); ++i)
246  {
247  face_pointer f = e->adjacent_faces()[i];
248 
249  list_nodes(f->next_edge(e,v0), storage, threshold_distance);
250  list_nodes(f->next_edge(e,v1), storage, threshold_distance);
251  list_nodes(f->opposite_vertex(e), storage, threshold_distance);
252  }
253  }
254  else
255  {
256  FEASSERT(0);
257  }
258 
259  unsigned index = distances.size();
260  distances.resize(storage.size());
261  for(; index<storage.size(); ++index)
262  {
263  distances[index] = node->distance(&storage[index]->surface_point());
264  }
265 }
266 
267 } //geodesic
268 
269 #endif //GEODESIC_ALGORITHM_SUBDIVISION_122806
Definition: geodesic_cpp_03_02_2008/geodesic_algorithm_base.h:11