2 #ifndef GEODESIC_ALGORITHM_EXACT_20071231 3 #define GEODESIC_ALGORITHM_EXACT_20071231 5 #include "geodesic_memory.h" 6 #include "geodesic_algorithm_base.h" 7 #include "geodesic_algorithm_exact_elements.h" 14 class GeodesicAlgorithmExact :
public GeodesicAlgorithmBase
17 GeodesicAlgorithmExact(geodesic::Mesh* mesh):
18 GeodesicAlgorithmBase(mesh),
19 m_memory_allocator(mesh->edges().size(), mesh->edges().size()),
20 m_edge_interval_lists(mesh->edges().size())
24 for(
unsigned i=0; i<m_edge_interval_lists.size(); ++i)
26 m_edge_interval_lists[i].initialize(&mesh->edges()[i]);
30 ~GeodesicAlgorithmExact(){};
32 void propagate(std::vector<SurfacePoint>& sources,
33 double max_propagation_distance = GEODESIC_INF,
34 std::vector<SurfacePoint>* stop_points = NULL);
36 void trace_back(SurfacePoint& destination,
37 std::vector<SurfacePoint>& path);
39 unsigned best_source(SurfacePoint& point,
40 double& best_source_distance);
42 void print_statistics();
45 typedef std::set<interval_pointer, Interval> IntervalQueue;
47 void update_list_and_queue(list_pointer list,
48 IntervalWithStop* candidates,
49 unsigned num_candidates);
51 unsigned compute_propagated_parameters(
double pseudo_x,
62 IntervalWithStop* candidates);
64 void construct_propagated_intervals(
bool invert,
67 IntervalWithStop* candidates,
68 unsigned& num_candidates,
69 interval_pointer source_interval);
71 double compute_positive_intersection(
double start,
77 unsigned intersect_intervals(interval_pointer zero,
78 IntervalWithStop* one);
80 interval_pointer best_first_interval(SurfacePoint& point,
81 double& best_total_distance,
82 double& best_interval_position,
83 unsigned& best_source_index);
85 bool check_stop_conditions(
unsigned& index);
89 m_memory_allocator.clear();
91 for(
unsigned i=0; i<m_edge_interval_lists.size(); ++i)
93 m_edge_interval_lists[i].clear();
95 m_propagation_distance_stopped = GEODESIC_INF;
98 list_pointer interval_list(edge_pointer e)
100 return &m_edge_interval_lists[e->id()];
103 void set_sources(std::vector<SurfacePoint>& sources)
105 m_sources.initialize(sources);
108 void initialize_propagation_data();
110 void list_edges_visible_from_source(MeshElementBase* p,
111 std::vector<edge_pointer>& storage);
113 long visible_from_source(SurfacePoint& point);
115 void best_point_on_the_edge_set(SurfacePoint& point,
116 std::vector<edge_pointer>
const& storage,
117 interval_pointer& best_interval,
118 double& best_total_distance,
119 double& best_interval_position);
121 void possible_traceback_edges(SurfacePoint& point,
122 std::vector<edge_pointer>& storage);
124 bool erase_from_queue(interval_pointer p);
126 IntervalQueue m_queue;
128 MemoryAllocator<Interval> m_memory_allocator;
129 std::vector<IntervalList> m_edge_interval_lists;
131 enum MapType {OLD, NEW};
134 interval_pointer i_new[5];
136 unsigned m_queue_max_size;
137 unsigned m_iterations;
139 SortedSources m_sources;
142 inline void GeodesicAlgorithmExact::best_point_on_the_edge_set(SurfacePoint& point,
143 std::vector<edge_pointer>
const& storage,
144 interval_pointer& best_interval,
145 double& best_total_distance,
146 double& best_interval_position)
148 best_total_distance = 1e100;
149 for(
unsigned i=0; i<storage.size(); ++i)
151 edge_pointer e = storage[i];
152 list_pointer list = interval_list(e);
156 interval_pointer interval;
158 list->find_closest_point(&point,
163 if(distance < best_total_distance)
165 best_interval = interval;
166 best_total_distance = distance;
167 best_interval_position = offset;
172 inline void GeodesicAlgorithmExact::possible_traceback_edges(SurfacePoint& point,
173 std::vector<edge_pointer>& storage)
177 if(point.type() == VERTEX)
179 vertex_pointer v =
static_cast<vertex_pointer
>(point.base_element());
180 for(
unsigned i=0; i<v->adjacent_faces().size(); ++i)
182 face_pointer f = v->adjacent_faces()[i];
183 storage.push_back(f->opposite_edge(v));
186 else if(point.type() == EDGE)
188 edge_pointer e =
static_cast<edge_pointer
>(point.base_element());
189 for(
unsigned i=0; i<e->adjacent_faces().size(); ++i)
191 face_pointer f = e->adjacent_faces()[i];
193 storage.push_back(f->next_edge(e,e->v0()));
194 storage.push_back(f->next_edge(e,e->v1()));
199 face_pointer f =
static_cast<face_pointer
>(point.base_element());
200 storage.push_back(f->adjacent_edges()[0]);
201 storage.push_back(f->adjacent_edges()[1]);
202 storage.push_back(f->adjacent_edges()[2]);
207 inline long GeodesicAlgorithmExact::visible_from_source(SurfacePoint& point)
209 FEASSERT(point.type() != UNDEFINED_POINT);
211 if(point.type() == EDGE)
213 edge_pointer e =
static_cast<edge_pointer
>(point.base_element());
214 list_pointer list = interval_list(e);
215 double position = std::min(point.distance(e->v0()), e->length());
216 interval_pointer interval = list->covering_interval(position);
218 if(interval && interval->visible_from_source())
220 return (
long)interval->source_index();
227 else if(point.type() == FACE)
231 else if(point.type() == VERTEX)
233 vertex_pointer v =
static_cast<vertex_pointer
>(point.base_element());
234 for(
unsigned i=0; i<v->adjacent_edges().size(); ++i)
236 edge_pointer e = v->adjacent_edges()[i];
237 list_pointer list = interval_list(e);
239 double position = e->v0()->id() == v->id() ? 0.0 : e->length();
240 interval_pointer interval = list->covering_interval(position);
241 if(interval && interval->visible_from_source())
243 return (
long)interval->source_index();
254 inline double GeodesicAlgorithmExact::compute_positive_intersection(
double start,
260 FEASSERT(pseudo_y < 0);
262 double denominator = sin_alpha*(pseudo_x - start) - cos_alpha*pseudo_y;
268 double numerator = -pseudo_y*start;
270 if(numerator < 1e-30)
275 if(denominator < 1e-30)
280 return numerator/denominator;
283 inline void GeodesicAlgorithmExact::list_edges_visible_from_source(MeshElementBase* p,
284 std::vector<edge_pointer>& storage)
286 FEASSERT(p->type() != UNDEFINED_POINT);
288 if(p->type() == FACE)
290 face_pointer f =
static_cast<face_pointer
>(p);
291 for(
unsigned i=0; i<3; ++i)
293 storage.push_back(f->adjacent_edges()[i]);
296 else if(p->type() == EDGE)
298 edge_pointer e =
static_cast<edge_pointer
>(p);
299 storage.push_back(e);
303 vertex_pointer v =
static_cast<vertex_pointer
>(p);
304 for(
unsigned i=0; i<v->adjacent_edges().size(); ++i)
306 storage.push_back(v->adjacent_edges()[i]);
312 inline bool GeodesicAlgorithmExact::erase_from_queue(interval_pointer p)
314 if(p->min() < GEODESIC_INF/10.0)
316 FEASSERT(m_queue.count(p)<=1);
318 IntervalQueue::iterator it = m_queue.find(p);
320 if(it != m_queue.end())
330 inline unsigned GeodesicAlgorithmExact::intersect_intervals(interval_pointer zero,
331 IntervalWithStop* one)
333 FEASSERT(zero->edge()->id() == one->edge()->id());
334 FEASSERT(zero->stop() > one->start() && zero->start() < one->stop());
335 FEASSERT(one->min() < GEODESIC_INF/10.0);
337 double const local_epsilon = SMALLEST_INTERVAL_RATIO*one->edge()->length();
340 if(zero->min() > GEODESIC_INF/10.0)
342 start[0] = zero->start();
343 if(zero->start() < one->start() - local_epsilon)
346 start[1] = one->start();
356 if(zero->stop() > one->stop() + local_epsilon)
359 start[N++] = one->stop();
362 start[N+1] = zero->stop();
366 double const local_small_epsilon = 1e-8*one->edge()->length();
368 double D = zero->d() - one->d();
369 double x0 = zero->pseudo_x();
370 double x1 = one->pseudo_x();
371 double R0 = x0*x0 + zero->pseudo_y()*zero->pseudo_y();
372 double R1 = x1*x1 + one->pseudo_y()*one->pseudo_y();
377 if(std::abs(D)<local_epsilon)
379 double denom = x1 - x0;
380 if(std::abs(denom)>local_small_epsilon)
382 inter[0] = (R1 - R0)/(2.*denom);
389 double Q = 0.5*(R1-R0-D2);
393 double B = Q*X + D2*x0;
394 double C = Q*Q - D2*R0;
396 if (std::abs(A)<local_small_epsilon)
398 if(std::abs(B)>local_small_epsilon)
406 double det = B*B-A*C;
407 if(det>local_small_epsilon*local_small_epsilon)
412 inter[0] = (-B - det)/A;
413 inter[1] = (-B + det)/A;
417 inter[0] = (-B + det)/A;
418 inter[1] = (-B - det)/A;
421 if(inter[1] - inter[0] > local_small_epsilon)
438 double left = std::max(zero->start(), one->start());
439 double right = std::min(zero->stop(), one->stop());
441 double good_start[4];
442 good_start[0] = left;
445 for(
char i=0; i<Ninter; ++i)
448 if(x > left + local_epsilon && x < right - local_epsilon)
450 good_start[Ngood_start++] = x;
453 good_start[Ngood_start++] = right;
456 for(
char i=0; i<Ngood_start-1; ++i)
458 double mid = (good_start[i] + good_start[i+1])*0.5;
459 mid_map[i] = zero->signal(mid) <= one->signal(mid) ? OLD : NEW;
464 if(zero->start() < left - local_epsilon)
466 if(mid_map[0] == OLD)
468 good_start[0] = zero->start();
473 start[N++] = zero->start();
477 for(
long i=0;i<Ngood_start-1;++i)
479 MapType current_map = mid_map[i];
480 if(N==0 || map[N-1] != current_map)
482 map[N] = current_map;
483 start[N++] = good_start[i];
487 if(zero->stop() > one->stop() + local_epsilon)
489 if(N==0 || map[N-1] == NEW)
492 start[N++] = one->stop();
496 start[0] = zero->start();
502 inline void GeodesicAlgorithmExact::initialize_propagation_data()
506 IntervalWithStop candidate;
507 std::vector<edge_pointer> edges_visible_from_source;
508 for(
unsigned i=0; i<m_sources.size(); ++i)
510 SurfacePoint* source = &m_sources[i];
512 edges_visible_from_source.clear();
513 list_edges_visible_from_source(source->base_element(),
514 edges_visible_from_source);
516 for(
unsigned j=0; j<edges_visible_from_source.size(); ++j)
518 edge_pointer e = edges_visible_from_source[j];
519 candidate.initialize(e, source, i);
520 candidate.stop() = e->length();
521 candidate.compute_min_distance(candidate.stop());
522 candidate.direction() = Interval::FROM_SOURCE;
524 update_list_and_queue(interval_list(e), &candidate, 1);
529 inline void GeodesicAlgorithmExact::propagate(std::vector<SurfacePoint>& sources,
530 double max_propagation_distance,
531 std::vector<SurfacePoint>* stop_points)
533 set_stop_conditions(stop_points, max_propagation_distance);
534 set_sources(sources);
535 initialize_propagation_data();
537 clock_t start = clock();
539 unsigned satisfied_index = 0;
542 m_queue_max_size = 0;
544 IntervalWithStop candidates[2];
546 while(!m_queue.empty())
548 m_queue_max_size = std::max(
unsigned(m_queue.size()), m_queue_max_size);
550 unsigned const check_period = 10;
551 if(++m_iterations % check_period == 0)
553 if (check_stop_conditions(satisfied_index))
559 interval_pointer min_interval = *m_queue.begin();
560 m_queue.erase(m_queue.begin());
561 edge_pointer edge = min_interval->edge();
562 list_pointer list = interval_list(edge);
564 FEASSERT(min_interval->d() < GEODESIC_INF);
566 bool const first_interval = min_interval->start() == 0.0;
568 bool const last_interval = min_interval->next() == NULL;
570 bool const turn_left = edge->v0()->saddle_or_boundary();
571 bool const turn_right = edge->v1()->saddle_or_boundary();
573 for(
unsigned i=0; i<edge->adjacent_faces().size(); ++i)
575 if(!edge->is_boundary())
577 if((i == 0 && min_interval->direction() == Interval::FROM_FACE_0) ||
578 (i == 1 && min_interval->direction() == Interval::FROM_FACE_1))
584 face_pointer face = edge->adjacent_faces()[i];
585 edge_pointer next_edge = face->next_edge(edge,edge->v0());
587 unsigned num_propagated = compute_propagated_parameters(min_interval->pseudo_x(),
588 min_interval->pseudo_y(),
590 min_interval->start(),
591 min_interval->stop(),
592 face->vertex_angle(edge->v0()),
599 bool propagate_to_right =
true;
603 if(candidates[num_propagated-1].stop() != next_edge->length())
605 propagate_to_right =
false;
608 bool const invert = next_edge->v0()->id() != edge->v0()->id();
610 construct_propagated_intervals(invert,
617 update_list_and_queue(interval_list(next_edge),
622 if(propagate_to_right)
625 double length = edge->length();
626 next_edge = face->next_edge(edge,edge->v1());
628 num_propagated = compute_propagated_parameters(length - min_interval->pseudo_x(),
629 min_interval->pseudo_y(),
631 length - min_interval->stop(),
632 length - min_interval->start(),
633 face->vertex_angle(edge->v1()),
643 bool const invert = next_edge->v0()->id() != edge->v1()->id();
645 construct_propagated_intervals(invert,
652 update_list_and_queue(interval_list(next_edge),
660 m_propagation_distance_stopped = m_queue.empty() ? GEODESIC_INF : (*m_queue.begin())->min();
661 clock_t stop = clock();
662 m_time_consumed = (
static_cast<double>(stop)-static_cast<double>(start))/CLOCKS_PER_SEC;
679 inline bool GeodesicAlgorithmExact::check_stop_conditions(
unsigned& index)
681 double queue_distance = (*m_queue.begin())->min();
682 if(queue_distance < stop_distance())
687 while(index < m_stop_vertices.size())
689 vertex_pointer v = m_stop_vertices[index].first;
690 edge_pointer edge = v->adjacent_edges()[0];
692 double distance = edge->v0()->id() == v->id() ?
693 interval_list(edge)->signal(0.0) :
694 interval_list(edge)->signal(edge->length());
696 if(queue_distance < distance + m_stop_vertices[index].second)
707 inline void GeodesicAlgorithmExact::update_list_and_queue(list_pointer list,
708 IntervalWithStop* candidates,
709 unsigned num_candidates)
711 FEASSERT(num_candidates <= 2);
713 edge_pointer edge = list->edge();
714 double const local_epsilon = SMALLEST_INTERVAL_RATIO * edge->length();
716 if(list->first() == NULL)
718 interval_pointer* p = &list->first();
719 IntervalWithStop* first;
720 IntervalWithStop* second;
722 if(num_candidates == 1)
726 first->compute_min_distance(first->stop());
730 if(candidates->start() <= (candidates+1)->start())
733 second = candidates+1;
737 first = candidates+1;
740 FEASSERT(first->stop() == second->start());
742 first->compute_min_distance(first->stop());
743 second->compute_min_distance(second->stop());
746 if(first->start() > 0.0)
748 *p = m_memory_allocator.allocate();
749 (*p)->initialize(edge);
753 *p = m_memory_allocator.allocate();
754 memcpy(*p,first,
sizeof(Interval));
757 if(num_candidates == 2)
760 *p = m_memory_allocator.allocate();
761 memcpy(*p,second,
sizeof(Interval));
765 if(second->stop() < edge->length())
768 *p = m_memory_allocator.allocate();
769 (*p)->initialize(edge);
770 (*p)->start() = second->stop();
781 for(
unsigned i=0; i<num_candidates; ++i)
783 IntervalWithStop* q = &candidates[i];
785 interval_pointer previous = NULL;
787 interval_pointer p = list->first();
788 FEASSERT(p->start() == 0.0);
790 while(p != NULL && p->stop() - local_epsilon < q->start())
795 while(p != NULL && p->start() < q->stop() - local_epsilon)
797 unsigned const N = intersect_intervals(p, q);
805 previous->next() = p;
806 previous->compute_min_distance(p->start());
807 m_queue.insert(previous);
816 previous->next() = p->next();
818 m_memory_allocator.deallocate(p);
820 p = previous->next();
825 interval_pointer next = p->next();
828 memcpy(previous,q,
sizeof(Interval));
830 previous->start() = start[0];
831 previous->next() = next;
841 propagate_flag = erase_from_queue(p);
843 for(
unsigned j=1; j<N; ++j)
845 i_new[j] = m_memory_allocator.allocate();
852 previous->next() = p;
853 previous->compute_min_distance(previous->stop());
854 m_queue.insert(previous);
858 p->next() = i_new[1];
859 p->start() = start[0];
864 previous->next() = i_new[1];
865 m_memory_allocator.deallocate(p);
871 memcpy(p,q,
sizeof(Interval));
873 p->next() = i_new[1];
874 p->start() = start[0];
879 for(
unsigned j=1; j<N; ++j)
881 interval_pointer current_interval = i_new[j];
885 memcpy(current_interval,&swap,
sizeof(Interval));
889 memcpy(current_interval,q,
sizeof(Interval));
894 current_interval->next() = swap.next();
898 current_interval->next() = i_new[j+1];
901 current_interval->start() = start[j];
904 for(
unsigned j=0; j<N; ++j)
906 if(j==N-1 && map[j]==NEW)
912 interval_pointer current_interval = i_new[j];
914 current_interval->compute_min_distance(current_interval->stop());
916 if(map[j]==NEW || (map[j]==OLD && propagate_flag))
918 m_queue.insert(current_interval);
928 previous->compute_min_distance(previous->stop());
929 m_queue.insert(previous);
935 inline unsigned GeodesicAlgorithmExact::compute_propagated_parameters(
double pseudo_x,
946 IntervalWithStop* candidates)
948 FEASSERT(pseudo_y<=0.0);
949 FEASSERT(d<GEODESIC_INF/10.0);
950 FEASSERT(begin<=end);
951 FEASSERT(first_interval ? (begin == 0.0) :
true);
953 IntervalWithStop* p = candidates;
955 if(std::abs(pseudo_y) <= 1e-30)
957 if(first_interval && pseudo_x <= 0.0)
961 p->d() = d - pseudo_x;
966 else if(last_interval && pseudo_x >= end)
970 p->d() = d + pseudo_x-end;
971 p->pseudo_x() = end*cos(alpha);
972 p->pseudo_y() = -end*sin(alpha);
975 else if(pseudo_x >= begin && pseudo_x <= end)
980 p->pseudo_x() = pseudo_x*cos(alpha);
981 p->pseudo_y() = -pseudo_x*sin(alpha);
990 double sin_alpha = sin(alpha);
991 double cos_alpha = cos(alpha);
995 double L1 = compute_positive_intersection(begin,
1001 if(L1 < 0 || L1 >= L)
1003 if(first_interval && turn_left)
1007 p->d() = d + sqrt(pseudo_x*pseudo_x + pseudo_y*pseudo_y);
1008 p->pseudo_y() = 0.0;
1009 p->pseudo_x() = 0.0;
1018 double L2 = compute_positive_intersection(end,
1024 if(L2 < 0 || L2 >= L)
1029 p->pseudo_x() = cos_alpha*pseudo_x + sin_alpha*pseudo_y;
1030 p->pseudo_y() = -sin_alpha*pseudo_x + cos_alpha*pseudo_y;
1038 p->pseudo_x() = cos_alpha*pseudo_x + sin_alpha*pseudo_y;
1039 p->pseudo_y() = -sin_alpha*pseudo_x + cos_alpha*pseudo_y;
1040 FEASSERT(p->pseudo_y() <= 0.0);
1042 if(!(last_interval && turn_right))
1052 double dx = pseudo_x - end;
1053 p->d() = d + sqrt(dx*dx + pseudo_y*pseudo_y);
1054 p->pseudo_x() = end*cos_alpha;
1055 p->pseudo_y() = -end*sin_alpha;
1061 inline void GeodesicAlgorithmExact::construct_propagated_intervals(
bool invert,
1064 IntervalWithStop* candidates,
1065 unsigned& num_candidates,
1066 interval_pointer source_interval)
1068 double edge_length = edge->length();
1069 double local_epsilon = SMALLEST_INTERVAL_RATIO * edge_length;
1072 if(num_candidates == 2)
1074 double start = std::min(candidates->start(), (candidates+1)->start());
1075 double stop = std::max(candidates->stop(), (candidates+1)->stop());
1076 if(candidates->stop()-candidates->start() < local_epsilon)
1078 *candidates = *(candidates+1);
1080 candidates->start() = start;
1081 candidates->stop() = stop;
1083 else if ((candidates+1)->stop() - (candidates+1)->start() < local_epsilon)
1086 candidates->start() = start;
1087 candidates->stop() = stop;
1091 IntervalWithStop* first;
1092 IntervalWithStop* second;
1093 if(num_candidates == 1)
1096 second = candidates;
1100 if(candidates->start() <= (candidates+1)->start())
1103 second = candidates+1;
1107 first = candidates+1;
1108 second = candidates;
1110 FEASSERT(first->stop() == second->start());
1113 if(first->start() < local_epsilon)
1115 first->start() = 0.0;
1117 if(edge_length - second->stop() < local_epsilon)
1119 second->stop() = edge_length;
1123 Interval::DirectionType direction = edge->adjacent_faces()[0]->id() == face->id() ?
1124 Interval::FROM_FACE_0 :
1125 Interval::FROM_FACE_1;
1129 for(
unsigned i=0; i<num_candidates; ++i)
1131 IntervalWithStop* p = candidates + i;
1133 p->next() = (i == num_candidates - 1) ? NULL : candidates + i + 1;
1135 p->direction() = direction;
1136 p->source_index() = source_interval->source_index();
1140 FEASSERT(p->start() < p->stop());
1145 for(
unsigned i=0; i<num_candidates; ++i)
1147 IntervalWithStop* p = candidates + i;
1149 p->next() = (i == 0) ? NULL : candidates + i - 1;
1151 p->direction() = direction;
1152 p->source_index() = source_interval->source_index();
1154 double length = edge_length;
1155 p->pseudo_x() = length - p->pseudo_x();
1157 double start = length - p->stop();
1158 p->stop() = length - p->start();
1163 FEASSERT(p->start() < p->stop());
1164 FEASSERT(p->start() >= 0.0);
1165 FEASSERT(p->stop() <= edge->length());
1171 inline unsigned GeodesicAlgorithmExact::best_source(SurfacePoint& point,
1172 double& best_source_distance)
1174 double best_interval_position;
1175 unsigned best_source_index;
1177 best_first_interval(point,
1178 best_source_distance,
1179 best_interval_position,
1182 return best_source_index;
1185 inline interval_pointer GeodesicAlgorithmExact::best_first_interval(SurfacePoint& point,
1186 double& best_total_distance,
1187 double& best_interval_position,
1188 unsigned& best_source_index)
1190 FEASSERT(point.type() != UNDEFINED_POINT);
1192 interval_pointer best_interval = NULL;
1193 best_total_distance = GEODESIC_INF;
1195 if(point.type() == EDGE)
1197 edge_pointer e =
static_cast<edge_pointer
>(point.base_element());
1198 list_pointer list = interval_list(e);
1200 best_interval_position = point.distance(e->v0());
1201 best_interval = list->covering_interval(best_interval_position);
1205 best_total_distance = best_interval->signal(best_interval_position);
1206 best_source_index = best_interval->source_index();
1209 else if(point.type() == FACE)
1211 face_pointer f =
static_cast<face_pointer
>(point.base_element());
1212 for(
unsigned i=0; i<3; ++i)
1214 edge_pointer e = f->adjacent_edges()[i];
1215 list_pointer list = interval_list(e);
1219 interval_pointer interval;
1221 list->find_closest_point(&point,
1226 if(interval && distance < best_total_distance)
1228 best_interval = interval;
1229 best_total_distance = distance;
1230 best_interval_position = offset;
1231 best_source_index = interval->source_index();
1236 SortedSources::sorted_iterator_pair local_sources = m_sources.sources(f);
1237 for(SortedSources::sorted_iterator it=local_sources.first; it != local_sources.second; ++it)
1239 SurfacePointWithIndex* source = *it;
1240 double distance = point.distance(source);
1241 if(distance < best_total_distance)
1243 best_interval = NULL;
1244 best_total_distance = distance;
1245 best_interval_position = 0.0;
1246 best_source_index = source->index();
1250 else if(point.type() == VERTEX)
1252 vertex_pointer v =
static_cast<vertex_pointer
>(point.base_element());
1253 for(
unsigned i=0; i<v->adjacent_edges().size(); ++i)
1255 edge_pointer e = v->adjacent_edges()[i];
1256 list_pointer list = interval_list(e);
1258 double position = e->v0()->id() == v->id() ? 0.0 : e->length();
1259 interval_pointer interval = list->covering_interval(position);
1262 double distance = interval->signal(position);
1264 if(distance < best_total_distance)
1266 best_interval = interval;
1267 best_total_distance = distance;
1268 best_interval_position = position;
1269 best_source_index = interval->source_index();
1275 if(best_total_distance > m_propagation_distance_stopped)
1277 best_total_distance = GEODESIC_INF;
1282 return best_interval;
1286 inline void GeodesicAlgorithmExact::trace_back(SurfacePoint& destination,
1287 std::vector<SurfacePoint>& path)
1290 double best_total_distance;
1291 double best_interval_position;
1292 unsigned source_index = std::numeric_limits<unsigned>::max();
1293 interval_pointer best_interval = best_first_interval(destination,
1294 best_total_distance,
1295 best_interval_position,
1298 if(best_total_distance >= GEODESIC_INF/2.0)
1303 path.push_back(destination);
1307 std::vector<edge_pointer> possible_edges;
1308 possible_edges.reserve(10);
1310 while(visible_from_source(path.back()) < 0)
1312 SurfacePoint& q = path.back();
1314 possible_traceback_edges(q, possible_edges);
1316 interval_pointer interval;
1317 double total_distance;
1320 best_point_on_the_edge_set(q,
1327 FEASSERT(total_distance<GEODESIC_INF);
1328 source_index = interval->source_index();
1330 edge_pointer e = interval->edge();
1331 double local_epsilon = SMALLEST_INTERVAL_RATIO*e->length();
1332 if(position < local_epsilon)
1334 path.push_back(SurfacePoint(e->v0()));
1336 else if(position > e->length()-local_epsilon)
1338 path.push_back(SurfacePoint(e->v1()));
1342 double normalized_position = position/e->length();
1343 path.push_back(SurfacePoint(e, normalized_position));
1348 SurfacePoint& source =
static_cast<SurfacePoint&
>(m_sources[source_index]);
1349 if(path.back().distance(&source) > 0)
1351 path.push_back(source);
1355 inline void GeodesicAlgorithmExact::print_statistics()
1357 GeodesicAlgorithmBase::print_statistics();
1359 unsigned interval_counter = 0;
1360 for(
unsigned i=0; i<m_edge_interval_lists.size(); ++i)
1362 interval_counter += m_edge_interval_lists[i].number_of_intervals();
1364 double intervals_per_edge = (double)interval_counter/(
double)m_edge_interval_lists.size();
1366 double memory = m_edge_interval_lists.size()*
sizeof(IntervalList) +
1367 interval_counter*
sizeof(Interval);
1369 std::cout <<
"uses about " << memory/1e6 <<
"Mb of memory" <<std::endl;
1370 std::cout << interval_counter <<
" total intervals, or " 1371 << intervals_per_edge <<
" intervals per edge" 1373 std::cout <<
"maximum interval queue size is " << m_queue_max_size << std::endl;
1374 std::cout <<
"number of interval propagations is " << m_iterations << std::endl;
1379 #endif //GEODESIC_ALGORITHM_EXACT_20071231 Matrix< 4, 4, T > & invert(Matrix< 4, 4, T > &a_inverted, const Matrix< 4, 4, T > &a_matrix)
4x4 full matrix inversion
Definition: Matrix.h:1033
Definition: geodesic_cpp_03_02_2008/geodesic_algorithm_base.h:11