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" 15 class GeodesicAlgorithmExact :
public GeodesicAlgorithmBase
18 GeodesicAlgorithmExact(geodesic::Mesh* mesh):
19 GeodesicAlgorithmBase(mesh),
20 m_memory_allocator(mesh->edges().size(), mesh->edges().size()),
21 m_edge_interval_lists(mesh->edges().size())
25 for(
unsigned i=0; i<m_edge_interval_lists.size(); ++i)
27 m_edge_interval_lists[i].initialize(&mesh->edges()[i]);
31 ~GeodesicAlgorithmExact(){};
33 void propagate(std::vector<SurfacePoint>& sources,
34 double max_propagation_distance = GEODESIC_INF,
35 std::vector<SurfacePoint>* stop_points = NULL);
37 void trace_back(SurfacePoint& destination,
38 std::vector<SurfacePoint>& path);
40 unsigned best_source(SurfacePoint& point,
41 double& best_source_distance);
43 void print_statistics();
46 typedef std::set<interval_pointer, Interval> IntervalQueue;
48 void update_list_and_queue(list_pointer list,
49 IntervalWithStop* candidates,
50 unsigned num_candidates);
52 unsigned compute_propagated_parameters(
double pseudo_x,
63 IntervalWithStop* candidates);
65 void construct_propagated_intervals(
bool invert,
68 IntervalWithStop* candidates,
69 unsigned& num_candidates,
70 interval_pointer source_interval);
72 double compute_positive_intersection(
double start,
78 unsigned intersect_intervals(interval_pointer zero,
79 IntervalWithStop* one);
81 interval_pointer best_first_interval(SurfacePoint& point,
82 double& best_total_distance,
83 double& best_interval_position,
84 unsigned& best_source_index);
86 bool check_stop_conditions(
unsigned& index);
90 m_memory_allocator.clear();
92 for(
unsigned i=0; i<m_edge_interval_lists.size(); ++i)
94 m_edge_interval_lists[i].clear();
96 m_propagation_distance_stopped = GEODESIC_INF;
99 list_pointer interval_list(edge_pointer e)
101 return &m_edge_interval_lists[e->id()];
104 void set_sources(std::vector<SurfacePoint>& sources)
106 m_sources.initialize(sources);
109 void initialize_propagation_data();
111 void list_edges_visible_from_source(MeshElementBase* p,
112 std::vector<edge_pointer>& storage);
114 long visible_from_source(SurfacePoint& point);
116 void best_point_on_the_edge_set(SurfacePoint& point,
117 std::vector<edge_pointer>
const& storage,
118 interval_pointer& best_interval,
119 double& best_total_distance,
120 double& best_interval_position);
122 void possible_traceback_edges(SurfacePoint& point,
123 std::vector<edge_pointer>& storage);
125 bool erase_from_queue(interval_pointer p);
127 IntervalQueue m_queue;
129 MemoryAllocator<Interval> m_memory_allocator;
130 std::vector<IntervalList> m_edge_interval_lists;
132 enum MapType {OLD, NEW};
135 interval_pointer i_new[5];
137 unsigned m_queue_max_size;
138 unsigned m_iterations;
140 SortedSources m_sources;
143 inline void GeodesicAlgorithmExact::best_point_on_the_edge_set(SurfacePoint& point,
144 std::vector<edge_pointer>
const& storage,
145 interval_pointer& best_interval,
146 double& best_total_distance,
147 double& best_interval_position)
149 best_total_distance = 1e100;
150 for(
unsigned i=0; i<storage.size(); ++i)
152 edge_pointer e = storage[i];
153 list_pointer list = interval_list(e);
157 interval_pointer interval;
159 list->find_closest_point(&point,
164 if(distance < best_total_distance)
166 best_interval = interval;
167 best_total_distance = distance;
168 best_interval_position = offset;
173 inline void GeodesicAlgorithmExact::possible_traceback_edges(SurfacePoint& point,
174 std::vector<edge_pointer>& storage)
178 if(point.type() == VERTEX)
180 vertex_pointer v =
static_cast<vertex_pointer
>(point.base_element());
181 for(
unsigned i=0; i<v->adjacent_faces().size(); ++i)
183 face_pointer f = v->adjacent_faces()[i];
184 storage.push_back(f->opposite_edge(v));
187 else if(point.type() == EDGE)
189 edge_pointer e =
static_cast<edge_pointer
>(point.base_element());
190 for(
unsigned i=0; i<e->adjacent_faces().size(); ++i)
192 face_pointer f = e->adjacent_faces()[i];
194 storage.push_back(f->next_edge(e,e->v0()));
195 storage.push_back(f->next_edge(e,e->v1()));
200 face_pointer f =
static_cast<face_pointer
>(point.base_element());
201 storage.push_back(f->adjacent_edges()[0]);
202 storage.push_back(f->adjacent_edges()[1]);
203 storage.push_back(f->adjacent_edges()[2]);
208 inline long GeodesicAlgorithmExact::visible_from_source(SurfacePoint& point)
210 assert(point.type() != UNDEFINED_POINT);
212 if(point.type() == EDGE)
214 edge_pointer e =
static_cast<edge_pointer
>(point.base_element());
215 list_pointer list = interval_list(e);
216 double position = std::min(point.distance(e->v0()), e->length());
217 interval_pointer interval = list->covering_interval(position);
219 if(interval && interval->visible_from_source())
221 return (
long)interval->source_index();
228 else if(point.type() == FACE)
232 else if(point.type() == VERTEX)
234 vertex_pointer v =
static_cast<vertex_pointer
>(point.base_element());
235 for(
unsigned i=0; i<v->adjacent_edges().size(); ++i)
237 edge_pointer e = v->adjacent_edges()[i];
238 list_pointer list = interval_list(e);
240 double position = e->v0()->id() == v->id() ? 0.0 : e->length();
241 interval_pointer interval = list->covering_interval(position);
242 if(interval && interval->visible_from_source())
244 return (
long)interval->source_index();
255 inline double GeodesicAlgorithmExact::compute_positive_intersection(
double start,
261 assert(pseudo_y < 0);
263 double denominator = sin_alpha*(pseudo_x - start) - cos_alpha*pseudo_y;
269 double numerator = -pseudo_y*start;
271 if(numerator < 1e-30)
276 if(denominator < 1e-30)
281 return numerator/denominator;
284 inline void GeodesicAlgorithmExact::list_edges_visible_from_source(MeshElementBase* p,
285 std::vector<edge_pointer>& storage)
287 assert(p->type() != UNDEFINED_POINT);
289 if(p->type() == FACE)
291 face_pointer f =
static_cast<face_pointer
>(p);
292 for(
unsigned i=0; i<3; ++i)
294 storage.push_back(f->adjacent_edges()[i]);
297 else if(p->type() == EDGE)
299 edge_pointer e =
static_cast<edge_pointer
>(p);
300 storage.push_back(e);
304 vertex_pointer v =
static_cast<vertex_pointer
>(p);
305 for(
unsigned i=0; i<v->adjacent_edges().size(); ++i)
307 storage.push_back(v->adjacent_edges()[i]);
313 inline bool GeodesicAlgorithmExact::erase_from_queue(interval_pointer p)
315 if(p->min() < GEODESIC_INF/10.0)
317 assert(m_queue.count(p)<=1);
319 IntervalQueue::iterator it = m_queue.find(p);
321 if(it != m_queue.end())
331 inline unsigned GeodesicAlgorithmExact::intersect_intervals(interval_pointer zero,
332 IntervalWithStop* one)
334 assert(zero->edge()->id() == one->edge()->id());
335 assert(zero->stop() > one->start() && zero->start() < one->stop());
336 assert(one->min() < GEODESIC_INF/10.0);
338 double const local_epsilon = SMALLEST_INTERVAL_RATIO*one->edge()->length();
341 if(zero->min() > GEODESIC_INF/10.0)
343 start[0] = zero->start();
344 if(zero->start() < one->start() - local_epsilon)
347 start[1] = one->start();
357 if(zero->stop() > one->stop() + local_epsilon)
360 start[N++] = one->stop();
363 start[N+1] = zero->stop();
367 double const local_small_epsilon = 1e-8*one->edge()->length();
369 double D = zero->d() - one->d();
370 double x0 = zero->pseudo_x();
371 double x1 = one->pseudo_x();
372 double R0 = x0*x0 + zero->pseudo_y()*zero->pseudo_y();
373 double R1 = x1*x1 + one->pseudo_y()*one->pseudo_y();
378 if(std::abs(D)<local_epsilon)
380 double denom = x1 - x0;
381 if(std::abs(denom)>local_small_epsilon)
383 inter[0] = (R1 - R0)/(2.*denom);
390 double Q = 0.5*(R1-R0-D2);
394 double B = Q*X + D2*x0;
395 double C = Q*Q - D2*R0;
397 if (std::abs(A)<local_small_epsilon)
399 if(std::abs(B)>local_small_epsilon)
407 double det = B*B-A*C;
408 if(det>local_small_epsilon*local_small_epsilon)
413 inter[0] = (-B - det)/A;
414 inter[1] = (-B + det)/A;
418 inter[0] = (-B + det)/A;
419 inter[1] = (-B - det)/A;
422 if(inter[1] - inter[0] > local_small_epsilon)
439 double left = std::max(zero->start(), one->start());
440 double right = std::min(zero->stop(), one->stop());
442 double good_start[4];
443 good_start[0] = left;
446 for(
char i=0; i<Ninter; ++i)
449 if(x > left + local_epsilon && x < right - local_epsilon)
451 good_start[Ngood_start++] = x;
454 good_start[Ngood_start++] = right;
457 for(
char i=0; i<Ngood_start-1; ++i)
459 double mid = (good_start[i] + good_start[i+1])*0.5;
460 mid_map[i] = zero->signal(mid) <= one->signal(mid) ? OLD : NEW;
465 if(zero->start() < left - local_epsilon)
467 if(mid_map[0] == OLD)
469 good_start[0] = zero->start();
474 start[N++] = zero->start();
478 for(
long i=0;i<Ngood_start-1;++i)
480 MapType current_map = mid_map[i];
481 if(N==0 || map[N-1] != current_map)
483 map[N] = current_map;
484 start[N++] = good_start[i];
488 if(zero->stop() > one->stop() + local_epsilon)
490 if(N==0 || map[N-1] == NEW)
493 start[N++] = one->stop();
497 start[0] = zero->start();
503 inline void GeodesicAlgorithmExact::initialize_propagation_data()
507 IntervalWithStop candidate;
508 std::vector<edge_pointer> edges_visible_from_source;
509 for(
unsigned i=0; i<m_sources.size(); ++i)
511 SurfacePoint* source = &m_sources[i];
513 edges_visible_from_source.clear();
514 list_edges_visible_from_source(source->base_element(),
515 edges_visible_from_source);
517 for(
unsigned j=0; j<edges_visible_from_source.size(); ++j)
519 edge_pointer e = edges_visible_from_source[j];
520 candidate.initialize(e, source, i);
521 candidate.stop() = e->length();
522 candidate.compute_min_distance(candidate.stop());
523 candidate.direction() = Interval::FROM_SOURCE;
525 update_list_and_queue(interval_list(e), &candidate, 1);
530 inline void GeodesicAlgorithmExact::propagate(std::vector<SurfacePoint>& sources,
531 double max_propagation_distance,
532 std::vector<SurfacePoint>* stop_points)
534 set_stop_conditions(stop_points, max_propagation_distance);
535 set_sources(sources);
536 initialize_propagation_data();
538 clock_t start = clock();
540 unsigned satisfied_index = 0;
543 m_queue_max_size = 0;
545 IntervalWithStop candidates[2];
547 while(!m_queue.empty())
549 m_queue_max_size = std::max(m_queue.size(), m_queue_max_size);
551 unsigned const check_period = 10;
552 if(++m_iterations % check_period == 0)
554 if (check_stop_conditions(satisfied_index))
560 interval_pointer min_interval = *m_queue.begin();
561 m_queue.erase(m_queue.begin());
562 edge_pointer edge = min_interval->edge();
563 list_pointer list = interval_list(edge);
565 assert(min_interval->d() < GEODESIC_INF);
567 bool const first_interval = min_interval->start() == 0.0;
569 bool const last_interval = min_interval->next() == NULL;
571 bool const turn_left = edge->v0()->saddle_or_boundary();
572 bool const turn_right = edge->v1()->saddle_or_boundary();
574 for(
unsigned i=0; i<edge->adjacent_faces().size(); ++i)
576 if(!edge->is_boundary())
578 if((i == 0 && min_interval->direction() == Interval::FROM_FACE_0) ||
579 (i == 1 && min_interval->direction() == Interval::FROM_FACE_1))
585 face_pointer face = edge->adjacent_faces()[i];
586 edge_pointer next_edge = face->next_edge(edge,edge->v0());
588 unsigned num_propagated = compute_propagated_parameters(min_interval->pseudo_x(),
589 min_interval->pseudo_y(),
591 min_interval->start(),
592 min_interval->stop(),
593 face->vertex_angle(edge->v0()),
600 bool propagate_to_right =
true;
604 if(candidates[num_propagated-1].stop() != next_edge->length())
606 propagate_to_right =
false;
609 bool const invert = next_edge->v0()->id() != edge->v0()->id();
611 construct_propagated_intervals(invert,
618 update_list_and_queue(interval_list(next_edge),
623 if(propagate_to_right)
626 double length = edge->length();
627 next_edge = face->next_edge(edge,edge->v1());
629 num_propagated = compute_propagated_parameters(length - min_interval->pseudo_x(),
630 min_interval->pseudo_y(),
632 length - min_interval->stop(),
633 length - min_interval->start(),
634 face->vertex_angle(edge->v1()),
644 bool const invert = next_edge->v0()->id() != edge->v1()->id();
646 construct_propagated_intervals(invert,
653 update_list_and_queue(interval_list(next_edge),
661 m_propagation_distance_stopped = m_queue.empty() ? GEODESIC_INF : (*m_queue.begin())->min();
662 clock_t stop = clock();
663 m_time_consumed = (
static_cast<double>(stop)-static_cast<double>(start))/CLOCKS_PER_SEC;
680 inline bool GeodesicAlgorithmExact::check_stop_conditions(
unsigned& index)
682 double queue_distance = (*m_queue.begin())->min();
683 if(queue_distance < stop_distance())
688 while(index < m_stop_vertices.size())
690 vertex_pointer v = m_stop_vertices[index].first;
691 edge_pointer edge = v->adjacent_edges()[0];
693 double distance = edge->v0()->id() == v->id() ?
694 interval_list(edge)->signal(0.0) :
695 interval_list(edge)->signal(edge->length());
697 if(queue_distance < distance + m_stop_vertices[index].second)
708 inline void GeodesicAlgorithmExact::update_list_and_queue(list_pointer list,
709 IntervalWithStop* candidates,
710 unsigned num_candidates)
712 assert(num_candidates <= 2);
714 edge_pointer edge = list->edge();
715 double const local_epsilon = SMALLEST_INTERVAL_RATIO * edge->length();
717 if(list->first() == NULL)
719 interval_pointer* p = &list->first();
720 IntervalWithStop* first;
721 IntervalWithStop* second;
723 if(num_candidates == 1)
727 first->compute_min_distance(first->stop());
731 if(candidates->start() <= (candidates+1)->start())
734 second = candidates+1;
738 first = candidates+1;
741 assert(first->stop() == second->start());
743 first->compute_min_distance(first->stop());
744 second->compute_min_distance(second->stop());
747 if(first->start() > 0.0)
749 *p = m_memory_allocator.allocate();
750 (*p)->initialize(edge);
754 *p = m_memory_allocator.allocate();
755 memcpy(*p,first,
sizeof(Interval));
758 if(num_candidates == 2)
761 *p = m_memory_allocator.allocate();
762 memcpy(*p,second,
sizeof(Interval));
766 if(second->stop() < edge->length())
769 *p = m_memory_allocator.allocate();
770 (*p)->initialize(edge);
771 (*p)->start() = second->stop();
782 for(
unsigned i=0; i<num_candidates; ++i)
784 IntervalWithStop* q = &candidates[i];
786 interval_pointer previous = NULL;
788 interval_pointer p = list->first();
789 assert(p->start() == 0.0);
791 while(p != NULL && p->stop() - local_epsilon < q->start())
796 while(p != NULL && p->start() < q->stop() - local_epsilon)
798 unsigned const N = intersect_intervals(p, q);
806 previous->next() = p;
807 previous->compute_min_distance(p->start());
808 m_queue.insert(previous);
817 previous->next() = p->next();
819 m_memory_allocator.deallocate(p);
821 p = previous->next();
826 interval_pointer next = p->next();
829 memcpy(previous,q,
sizeof(Interval));
831 previous->start() = start[0];
832 previous->next() = next;
842 propagate_flag = erase_from_queue(p);
844 for(
unsigned j=1; j<N; ++j)
846 i_new[j] = m_memory_allocator.allocate();
853 previous->next() = p;
854 previous->compute_min_distance(previous->stop());
855 m_queue.insert(previous);
859 p->next() = i_new[1];
860 p->start() = start[0];
865 previous->next() = i_new[1];
866 m_memory_allocator.deallocate(p);
872 memcpy(p,q,
sizeof(Interval));
874 p->next() = i_new[1];
875 p->start() = start[0];
880 for(
unsigned j=1; j<N; ++j)
882 interval_pointer current_interval = i_new[j];
886 memcpy(current_interval,&swap,
sizeof(Interval));
890 memcpy(current_interval,q,
sizeof(Interval));
895 current_interval->next() = swap.next();
899 current_interval->next() = i_new[j+1];
902 current_interval->start() = start[j];
905 for(
unsigned j=0; j<N; ++j)
907 if(j==N-1 && map[j]==NEW)
913 interval_pointer current_interval = i_new[j];
915 current_interval->compute_min_distance(current_interval->stop());
917 if(map[j]==NEW || (map[j]==OLD && propagate_flag))
919 m_queue.insert(current_interval);
929 previous->compute_min_distance(previous->stop());
930 m_queue.insert(previous);
936 inline unsigned GeodesicAlgorithmExact::compute_propagated_parameters(
double pseudo_x,
947 IntervalWithStop* candidates)
949 assert(pseudo_y<=0.0);
950 assert(d<GEODESIC_INF/10.0);
952 assert(first_interval ? (begin == 0.0) :
true);
954 IntervalWithStop* p = candidates;
956 if(std::abs(pseudo_y) <= 1e-30)
958 if(first_interval && pseudo_x <= 0.0)
962 p->d() = d - pseudo_x;
967 else if(last_interval && pseudo_x >= end)
971 p->d() = d + pseudo_x-end;
972 p->pseudo_x() = end*cos(alpha);
973 p->pseudo_y() = -end*sin(alpha);
976 else if(pseudo_x >= begin && pseudo_x <= end)
981 p->pseudo_x() = pseudo_x*cos(alpha);
982 p->pseudo_y() = -pseudo_x*sin(alpha);
991 double sin_alpha = sin(alpha);
992 double cos_alpha = cos(alpha);
996 double L1 = compute_positive_intersection(begin,
1002 if(L1 < 0 || L1 >= L)
1004 if(first_interval && turn_left)
1008 p->d() = d + sqrt(pseudo_x*pseudo_x + pseudo_y*pseudo_y);
1009 p->pseudo_y() = 0.0;
1010 p->pseudo_x() = 0.0;
1019 double L2 = compute_positive_intersection(end,
1025 if(L2 < 0 || L2 >= L)
1030 p->pseudo_x() = cos_alpha*pseudo_x + sin_alpha*pseudo_y;
1031 p->pseudo_y() = -sin_alpha*pseudo_x + cos_alpha*pseudo_y;
1039 p->pseudo_x() = cos_alpha*pseudo_x + sin_alpha*pseudo_y;
1040 p->pseudo_y() = -sin_alpha*pseudo_x + cos_alpha*pseudo_y;
1041 assert(p->pseudo_y() <= 0.0);
1043 if(!(last_interval && turn_right))
1053 double dx = pseudo_x - end;
1054 p->d() = d + sqrt(dx*dx + pseudo_y*pseudo_y);
1055 p->pseudo_x() = end*cos_alpha;
1056 p->pseudo_y() = -end*sin_alpha;
1062 inline void GeodesicAlgorithmExact::construct_propagated_intervals(
bool invert,
1065 IntervalWithStop* candidates,
1066 unsigned& num_candidates,
1067 interval_pointer source_interval)
1069 double edge_length = edge->length();
1070 double local_epsilon = SMALLEST_INTERVAL_RATIO * edge_length;
1073 if(num_candidates == 2)
1075 double start = std::min(candidates->start(), (candidates+1)->start());
1076 double stop = std::max(candidates->stop(), (candidates+1)->stop());
1077 if(candidates->stop()-candidates->start() < local_epsilon)
1079 *candidates = *(candidates+1);
1081 candidates->start() = start;
1082 candidates->stop() = stop;
1084 else if ((candidates+1)->stop() - (candidates+1)->start() < local_epsilon)
1087 candidates->start() = start;
1088 candidates->stop() = stop;
1092 IntervalWithStop* first;
1093 IntervalWithStop* second;
1094 if(num_candidates == 1)
1097 second = candidates;
1101 if(candidates->start() <= (candidates+1)->start())
1104 second = candidates+1;
1108 first = candidates+1;
1109 second = candidates;
1111 assert(first->stop() == second->start());
1114 if(first->start() < local_epsilon)
1116 first->start() = 0.0;
1118 if(edge_length - second->stop() < local_epsilon)
1120 second->stop() = edge_length;
1124 Interval::DirectionType direction = edge->adjacent_faces()[0]->id() == face->id() ?
1125 Interval::FROM_FACE_0 :
1126 Interval::FROM_FACE_1;
1130 for(
unsigned i=0; i<num_candidates; ++i)
1132 IntervalWithStop* p = candidates + i;
1134 p->next() = (i == num_candidates - 1) ? NULL : candidates + i + 1;
1136 p->direction() = direction;
1137 p->source_index() = source_interval->source_index();
1141 assert(p->start() < p->stop());
1146 for(
unsigned i=0; i<num_candidates; ++i)
1148 IntervalWithStop* p = candidates + i;
1150 p->next() = (i == 0) ? NULL : candidates + i - 1;
1152 p->direction() = direction;
1153 p->source_index() = source_interval->source_index();
1155 double length = edge_length;
1156 p->pseudo_x() = length - p->pseudo_x();
1158 double start = length - p->stop();
1159 p->stop() = length - p->start();
1164 assert(p->start() < p->stop());
1165 assert(p->start() >= 0.0);
1166 assert(p->stop() <= edge->length());
1172 inline unsigned GeodesicAlgorithmExact::best_source(SurfacePoint& point,
1173 double& best_source_distance)
1175 double best_interval_position;
1176 unsigned best_source_index;
1178 best_first_interval(point,
1179 best_source_distance,
1180 best_interval_position,
1183 return best_source_index;
1186 inline interval_pointer GeodesicAlgorithmExact::best_first_interval(SurfacePoint& point,
1187 double& best_total_distance,
1188 double& best_interval_position,
1189 unsigned& best_source_index)
1191 assert(point.type() != UNDEFINED_POINT);
1193 interval_pointer best_interval = NULL;
1194 best_total_distance = GEODESIC_INF;
1196 if(point.type() == EDGE)
1198 edge_pointer e =
static_cast<edge_pointer
>(point.base_element());
1199 list_pointer list = interval_list(e);
1201 best_interval_position = point.distance(e->v0());
1202 best_interval = list->covering_interval(best_interval_position);
1206 best_total_distance = best_interval->signal(best_interval_position);
1207 best_source_index = best_interval->source_index();
1210 else if(point.type() == FACE)
1212 face_pointer f =
static_cast<face_pointer
>(point.base_element());
1213 for(
unsigned i=0; i<3; ++i)
1215 edge_pointer e = f->adjacent_edges()[i];
1216 list_pointer list = interval_list(e);
1220 interval_pointer interval;
1222 list->find_closest_point(&point,
1227 if(interval && distance < best_total_distance)
1229 best_interval = interval;
1230 best_total_distance = distance;
1231 best_interval_position = offset;
1232 best_source_index = interval->source_index();
1237 SortedSources::sorted_iterator_pair local_sources = m_sources.sources(f);
1238 for(SortedSources::sorted_iterator it=local_sources.first; it != local_sources.second; ++it)
1240 SurfacePointWithIndex* source = *it;
1241 double distance = point.distance(source);
1242 if(distance < best_total_distance)
1244 best_interval = NULL;
1245 best_total_distance = distance;
1246 best_interval_position = 0.0;
1247 best_source_index = source->index();
1251 else if(point.type() == VERTEX)
1253 vertex_pointer v =
static_cast<vertex_pointer
>(point.base_element());
1254 for(
unsigned i=0; i<v->adjacent_edges().size(); ++i)
1256 edge_pointer e = v->adjacent_edges()[i];
1257 list_pointer list = interval_list(e);
1259 double position = e->v0()->id() == v->id() ? 0.0 : e->length();
1260 interval_pointer interval = list->covering_interval(position);
1263 double distance = interval->signal(position);
1265 if(distance < best_total_distance)
1267 best_interval = interval;
1268 best_total_distance = distance;
1269 best_interval_position = position;
1270 best_source_index = interval->source_index();
1276 if(best_total_distance > m_propagation_distance_stopped)
1278 best_total_distance = GEODESIC_INF;
1283 return best_interval;
1287 inline void GeodesicAlgorithmExact::trace_back(SurfacePoint& destination,
1288 std::vector<SurfacePoint>& path)
1291 double best_total_distance;
1292 double best_interval_position;
1293 unsigned source_index = std::numeric_limits<unsigned>::max();
1294 interval_pointer best_interval = best_first_interval(destination,
1295 best_total_distance,
1296 best_interval_position,
1299 if(best_total_distance >= GEODESIC_INF/2.0)
1304 path.push_back(destination);
1308 std::vector<edge_pointer> possible_edges;
1309 possible_edges.reserve(10);
1311 while(visible_from_source(path.back()) < 0)
1313 SurfacePoint& q = path.back();
1315 possible_traceback_edges(q, possible_edges);
1317 interval_pointer interval;
1318 double total_distance;
1321 best_point_on_the_edge_set(q,
1328 assert(total_distance<GEODESIC_INF);
1329 source_index = interval->source_index();
1331 edge_pointer e = interval->edge();
1332 double local_epsilon = SMALLEST_INTERVAL_RATIO*e->length();
1333 if(position < local_epsilon)
1335 path.push_back(SurfacePoint(e->v0()));
1337 else if(position > e->length()-local_epsilon)
1339 path.push_back(SurfacePoint(e->v1()));
1343 double normalized_position = position/e->length();
1344 path.push_back(SurfacePoint(e, normalized_position));
1349 SurfacePoint& source =
static_cast<SurfacePoint&
>(m_sources[source_index]);
1350 if(path.back().distance(&source) > 0)
1352 path.push_back(source);
1356 inline void GeodesicAlgorithmExact::print_statistics()
1358 GeodesicAlgorithmBase::print_statistics();
1360 unsigned interval_counter = 0;
1361 for(
unsigned i=0; i<m_edge_interval_lists.size(); ++i)
1363 interval_counter += m_edge_interval_lists[i].number_of_intervals();
1365 double intervals_per_edge = (double)interval_counter/(
double)m_edge_interval_lists.size();
1367 double memory = m_edge_interval_lists.size()*
sizeof(IntervalList) +
1368 interval_counter*
sizeof(Interval);
1370 std::cout <<
"uses about " << memory/1e6 <<
"Mb of memory" <<std::endl;
1371 std::cout << interval_counter <<
" total intervals, or " 1372 << intervals_per_edge <<
" intervals per edge" 1374 std::cout <<
"maximum interval queue size is " << m_queue_max_size << std::endl;
1375 std::cout <<
"number of interval propagations is " << m_iterations << std::endl;
1380 #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