2 #ifndef GEODESIC_ALGORITHM_DIJKSTRA_ALTERNATIVE_010506 3 #define GEODESIC_ALGORITHM_DIJKSTRA_ALTERNATIVE_010506 5 #include "geodesic_algorithm_base.h" 6 #include "geodesic_mesh_elements.h" 15 typedef DijkstraNode1* node_pointer;
20 double& distance_from_source(){
return m_distance;};
21 node_pointer& previous(){
return m_previous;};
22 unsigned& source_index(){
return m_source_index;};
23 vertex_pointer& vertex(){
return m_vertex;};
27 m_distance = GEODESIC_INF;
31 bool operator()(node_pointer
const s1, node_pointer
const s2)
const 33 return s1->distance_from_source() != s2->distance_from_source() ?
34 s1->distance_from_source() < s2->distance_from_source() :
35 s1->vertex()->id() < s2->vertex()->id();
40 unsigned m_source_index;
41 node_pointer m_previous;
42 vertex_pointer m_vertex;
45 class GeodesicAlgorithmDijkstraAlternative:
public GeodesicAlgorithmBase
48 typedef DijkstraNode1 Node;
49 typedef Node* node_pointer;
51 GeodesicAlgorithmDijkstraAlternative(geodesic::Mesh* mesh = NULL):
52 GeodesicAlgorithmBase(mesh),
53 m_nodes(mesh->vertices().size())
56 for(
unsigned i=0; i<m_nodes.size(); ++i)
58 m_nodes[i].vertex() = &m_mesh->vertices()[i];
62 ~GeodesicAlgorithmDijkstraAlternative(){};
64 virtual void propagate(std::vector<SurfacePoint>& sources,
65 double max_propagation_distance = GEODESIC_INF,
66 std::vector<SurfacePoint>* stop_points = NULL);
68 virtual void trace_back(SurfacePoint& destination,
69 std::vector<SurfacePoint>& path);
71 virtual unsigned best_source(SurfacePoint& point,
72 double& best_source_distance);
75 void set_sources(std::vector<SurfacePoint>& sources)
80 bool check_stop_conditions(
unsigned& index);
82 std::vector<Node> m_nodes;
84 std::vector<SurfacePoint> m_sources;
86 typedef std::set<node_pointer, Node> queue_type;
90 inline unsigned GeodesicAlgorithmDijkstraAlternative::best_source(SurfacePoint& point,
91 double& best_source_distance)
93 if(point.type() == VERTEX)
95 vertex_pointer v = (vertex_pointer)point.base_element();
96 node_pointer node = &m_nodes[v->id()];
97 best_source_distance = node->distance_from_source();
98 return node->source_index();
102 std::vector<vertex_pointer> possible_vertices;
103 m_mesh->closest_vertices(&point, &possible_vertices);
105 best_source_distance = GEODESIC_INF;
106 vertex_pointer min_vertex = NULL;
107 for(
unsigned i=0; i<possible_vertices.size(); ++i)
109 vertex_pointer v = possible_vertices[i];
111 double distance_from_source = m_nodes[v->id()].distance_from_source();
112 double distance_from_dest = v->distance(&point);
113 if(distance_from_source + distance_from_dest < best_source_distance)
115 best_source_distance = distance_from_source + distance_from_dest;
120 node_pointer node = &m_nodes[min_vertex->id()];
121 return node->source_index();
125 inline void GeodesicAlgorithmDijkstraAlternative::trace_back(SurfacePoint& destination,
126 std::vector<SurfacePoint>& path)
129 path.push_back(destination);
131 if(destination.type() != VERTEX)
133 std::vector<vertex_pointer> possible_vertices;
134 m_mesh->closest_vertices(&destination, &possible_vertices);
136 double min_distance = GEODESIC_INF;
137 vertex_pointer min_vertex = NULL;
138 for(
unsigned i=0; i<possible_vertices.size(); ++i)
140 vertex_pointer v = possible_vertices[i];
142 double distance_from_source = m_nodes[v->id()].distance_from_source();
143 double distance_from_dest = v->distance(&destination);
144 if(distance_from_source + distance_from_dest < min_distance)
146 min_distance = distance_from_source + distance_from_dest;
151 path.push_back(SurfacePoint(min_vertex));
154 node_pointer node = &m_nodes[path.back().base_element()->id()];
155 while(node->previous())
157 node = node->previous();
158 path.push_back(SurfacePoint(node->vertex()));
161 SurfacePoint& source = m_sources[node->source_index()];
162 if(source.type() != VERTEX ||
163 source.base_element()->id() != node->vertex()->id())
165 path.push_back(source);
169 inline void GeodesicAlgorithmDijkstraAlternative::propagate(std::vector<SurfacePoint>& sources,
170 double max_propagation_distance,
171 std::vector<SurfacePoint>* stop_points)
173 set_stop_conditions(stop_points, max_propagation_distance);
174 set_sources(sources);
177 for(
unsigned i=0; i<m_nodes.size(); ++i)
182 clock_t start = clock();
184 std::vector<vertex_pointer> visible_vertices;
185 for(
unsigned i=0; i<m_sources.size(); ++i)
187 SurfacePoint* s = &m_sources[i];
188 m_mesh->closest_vertices(s, &visible_vertices);
189 for(
unsigned j=0; j<visible_vertices.size(); ++j)
191 vertex_pointer v = visible_vertices[j];
192 double distance = s->distance(v);
194 node_pointer node = &m_nodes[v->id()];
195 if(distance < node->distance_from_source())
197 node->distance_from_source() = distance;
198 node->source_index() = i;
199 node->previous() = NULL;
202 visible_vertices.clear();
205 for(
unsigned i=0; i<m_nodes.size(); ++i)
207 if(m_nodes[i].distance_from_source() < GEODESIC_INF)
209 m_queue.insert(&m_nodes[i]);
213 unsigned counter = 0;
214 unsigned satisfied_index = 0;
216 while(!m_queue.empty())
218 if(counter++ % 10 == 0)
220 if (check_stop_conditions(satisfied_index))
227 node_pointer min_node = *m_queue.begin();
228 m_queue.erase(m_queue.begin());
230 vertex_pointer v = min_node->vertex();
232 for(
unsigned i=0; i<v->adjacent_edges().size(); ++i)
234 edge_pointer e = v->adjacent_edges()[i];
235 vertex_pointer next_v = e->opposite_vertex(v);
236 node_pointer next_node = &m_nodes[next_v->id()];
238 if(next_node->distance_from_source() > min_node->distance_from_source() + e->length())
240 if(next_node->distance_from_source() < GEODESIC_INF)
242 queue_type::iterator iter = m_queue.find(next_node);
243 assert(iter != m_queue.end());
246 next_node->distance_from_source() = min_node->distance_from_source() + e->length();
247 next_node->source_index() = min_node->source_index();
248 next_node->previous() = min_node;
249 m_queue.insert(next_node);
255 clock_t finish = clock();
256 m_time_consumed = (
static_cast<double>(finish)-static_cast<double>(start))/CLOCKS_PER_SEC;
259 inline bool GeodesicAlgorithmDijkstraAlternative::check_stop_conditions(
unsigned& index)
261 double queue_min_distance = (*m_queue.begin())->distance_from_source();
263 if(queue_min_distance < m_max_propagation_distance)
268 while(index < m_stop_vertices.size())
270 vertex_pointer v = m_stop_vertices[index].first;
271 Node& node = m_nodes[v->id()];
272 if(queue_min_distance < node.distance_from_source() + m_stop_vertices[index].second)
283 #endif //GEODESIC_ALGORITHM_DIJKSTRA_ALTERNATIVE_010506 Definition: geodesic_cpp_03_02_2008/geodesic_algorithm_base.h:11