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" 14 typedef DijkstraNode1* node_pointer;
19 double& distance_from_source(){
return m_distance;};
20 node_pointer& previous(){
return m_previous;};
21 unsigned& source_index(){
return m_source_index;};
22 vertex_pointer& vertex(){
return m_vertex;};
26 m_distance = GEODESIC_INF;
30 bool operator()(node_pointer
const s1, node_pointer
const s2)
const 32 return s1->distance_from_source() != s2->distance_from_source() ?
33 s1->distance_from_source() < s2->distance_from_source() :
34 s1->vertex()->id() < s2->vertex()->id();
39 unsigned m_source_index;
40 node_pointer m_previous;
41 vertex_pointer m_vertex;
44 class GeodesicAlgorithmDijkstraAlternative:
public GeodesicAlgorithmBase
47 typedef DijkstraNode1 Node;
48 typedef Node* node_pointer;
50 GeodesicAlgorithmDijkstraAlternative(geodesic::Mesh* mesh = NULL):
51 GeodesicAlgorithmBase(mesh),
52 m_nodes(mesh->vertices().size())
55 for(
unsigned i=0; i<m_nodes.size(); ++i)
57 m_nodes[i].vertex() = &m_mesh->vertices()[i];
61 ~GeodesicAlgorithmDijkstraAlternative(){};
63 virtual void propagate(std::vector<SurfacePoint>& sources,
64 double max_propagation_distance = GEODESIC_INF,
65 std::vector<SurfacePoint>* stop_points = NULL);
67 virtual void trace_back(SurfacePoint& destination,
68 std::vector<SurfacePoint>& path);
70 virtual unsigned best_source(SurfacePoint& point,
71 double& best_source_distance);
74 void set_sources(std::vector<SurfacePoint>& sources)
79 bool check_stop_conditions(
unsigned& index);
81 std::vector<Node> m_nodes;
83 std::vector<SurfacePoint> m_sources;
85 typedef std::set<node_pointer, Node> queue_type;
89 inline unsigned GeodesicAlgorithmDijkstraAlternative::best_source(SurfacePoint& point,
90 double& best_source_distance)
92 if(point.type() == VERTEX)
94 vertex_pointer v = (vertex_pointer)point.base_element();
95 node_pointer node = &m_nodes[v->id()];
96 best_source_distance = node->distance_from_source();
97 return node->source_index();
101 std::vector<vertex_pointer> possible_vertices;
102 m_mesh->closest_vertices(&point, &possible_vertices);
104 best_source_distance = GEODESIC_INF;
105 vertex_pointer min_vertex = NULL;
106 for(
unsigned i=0; i<possible_vertices.size(); ++i)
108 vertex_pointer v = possible_vertices[i];
110 double distance_from_source = m_nodes[v->id()].distance_from_source();
111 double distance_from_dest = v->distance(&point);
112 if(distance_from_source + distance_from_dest < best_source_distance)
114 best_source_distance = distance_from_source + distance_from_dest;
118 FEASSERT(min_vertex);
119 node_pointer node = &m_nodes[min_vertex->id()];
120 return node->source_index();
124 inline void GeodesicAlgorithmDijkstraAlternative::trace_back(SurfacePoint& destination,
125 std::vector<SurfacePoint>& path)
128 path.push_back(destination);
130 if(destination.type() != VERTEX)
132 std::vector<vertex_pointer> possible_vertices;
133 m_mesh->closest_vertices(&destination, &possible_vertices);
135 double min_distance = GEODESIC_INF;
136 vertex_pointer min_vertex = NULL;
137 for(
unsigned i=0; i<possible_vertices.size(); ++i)
139 vertex_pointer v = possible_vertices[i];
141 double distance_from_source = m_nodes[v->id()].distance_from_source();
142 double distance_from_dest = v->distance(&destination);
143 if(distance_from_source + distance_from_dest < min_distance)
145 min_distance = distance_from_source + distance_from_dest;
149 FEASSERT(min_vertex);
150 path.push_back(SurfacePoint(min_vertex));
153 node_pointer node = &m_nodes[path.back().base_element()->id()];
154 while(node->previous())
156 node = node->previous();
157 path.push_back(SurfacePoint(node->vertex()));
160 SurfacePoint& source = m_sources[node->source_index()];
161 if(source.type() != VERTEX ||
162 source.base_element()->id() != node->vertex()->id())
164 path.push_back(source);
168 inline void GeodesicAlgorithmDijkstraAlternative::propagate(std::vector<SurfacePoint>& sources,
169 double max_propagation_distance,
170 std::vector<SurfacePoint>* stop_points)
172 set_stop_conditions(stop_points, max_propagation_distance);
173 set_sources(sources);
176 for(
unsigned i=0; i<m_nodes.size(); ++i)
181 clock_t start = clock();
183 std::vector<vertex_pointer> visible_vertices;
184 for(
unsigned i=0; i<m_sources.size(); ++i)
186 SurfacePoint* s = &m_sources[i];
187 m_mesh->closest_vertices(s, &visible_vertices);
188 for(
unsigned j=0; j<visible_vertices.size(); ++j)
190 vertex_pointer v = visible_vertices[j];
191 double distance = s->distance(v);
193 node_pointer node = &m_nodes[v->id()];
194 if(distance < node->distance_from_source())
196 node->distance_from_source() = distance;
197 node->source_index() = i;
198 node->previous() = NULL;
201 visible_vertices.clear();
204 for(
unsigned i=0; i<m_nodes.size(); ++i)
206 if(m_nodes[i].distance_from_source() < GEODESIC_INF)
208 m_queue.insert(&m_nodes[i]);
212 unsigned counter = 0;
213 unsigned satisfied_index = 0;
215 while(!m_queue.empty())
217 if(counter++ % 10 == 0)
219 if (check_stop_conditions(satisfied_index))
226 node_pointer min_node = *m_queue.begin();
227 m_queue.erase(m_queue.begin());
229 vertex_pointer v = min_node->vertex();
231 for(
unsigned i=0; i<v->adjacent_edges().size(); ++i)
233 edge_pointer e = v->adjacent_edges()[i];
234 vertex_pointer next_v = e->opposite_vertex(v);
235 node_pointer next_node = &m_nodes[next_v->id()];
237 if(next_node->distance_from_source() > min_node->distance_from_source() + e->length())
239 if(next_node->distance_from_source() < GEODESIC_INF)
241 queue_type::iterator iter = m_queue.find(next_node);
242 FEASSERT(iter != m_queue.end());
245 next_node->distance_from_source() = min_node->distance_from_source() + e->length();
246 next_node->source_index() = min_node->source_index();
247 next_node->previous() = min_node;
248 m_queue.insert(next_node);
254 clock_t finish = clock();
255 m_time_consumed = (
static_cast<double>(finish)-static_cast<double>(start))/CLOCKS_PER_SEC;
258 inline bool GeodesicAlgorithmDijkstraAlternative::check_stop_conditions(
unsigned& index)
260 double queue_min_distance = (*m_queue.begin())->distance_from_source();
262 if(queue_min_distance < m_max_propagation_distance)
267 while(index < m_stop_vertices.size())
269 vertex_pointer v = m_stop_vertices[index].first;
270 Node& node = m_nodes[v->id()];
271 if(queue_min_distance < node.distance_from_source() + m_stop_vertices[index].second)
282 #endif //GEODESIC_ALGORITHM_DIJKSTRA_ALTERNATIVE_010506 Definition: geodesic_cpp_03_02_2008/geodesic_algorithm_base.h:11