2 #ifndef GEODESIC_ALGORITHM_EXACT_20071231 3 #define GEODESIC_ALGORITHM_EXACT_20071231 24 m_memory_allocator(mesh->edges().size(), mesh->edges().size()),
25 m_edge_interval_lists(mesh->edges().size())
29 for(
unsigned i=0; i<m_edge_interval_lists.size(); ++i)
31 m_edge_interval_lists[i].initialize(&mesh->
edges()[i]);
37 void propagate(std::vector<SurfacePoint>& sources,
39 std::vector<SurfacePoint>* stop_points = NULL);
42 std::vector<SurfacePoint>& path);
46 std::vector<SurfacePoint>& path,std::vector<unsigned>& indexVertex);
49 double& best_source_distance);
54 typedef std::set<interval_pointer, Interval> IntervalQueue;
58 unsigned num_candidates);
60 unsigned compute_propagated_parameters(
double pseudo_x,
73 void construct_propagated_intervals(
bool invert,
77 unsigned& num_candidates,
80 double compute_positive_intersection(
double start,
90 double& best_total_distance,
91 double& best_interval_position,
92 unsigned& best_source_index);
94 bool check_stop_conditions(
unsigned& index);
98 m_memory_allocator.clear();
100 for(
unsigned i=0; i<m_edge_interval_lists.size(); ++i)
102 m_edge_interval_lists[i].clear();
109 return &m_edge_interval_lists[e->
id()];
112 void set_sources(std::vector<SurfacePoint>& sources)
117 void initialize_propagation_data();
120 std::vector<edge_pointer>& storage);
125 std::vector<edge_pointer>
const& storage,
127 double& best_total_distance,
128 double& best_interval_position);
131 std::vector<edge_pointer>& storage);
135 IntervalQueue m_queue;
138 std::vector<IntervalList> m_edge_interval_lists;
140 enum MapType {OLD, NEW};
145 size_t m_queue_max_size;
146 unsigned m_iterations;
151 inline void GeodesicAlgorithmExact::best_point_on_the_edge_set(
SurfacePoint& point,
152 std::vector<edge_pointer>
const& storage,
154 double& best_total_distance,
155 double& best_interval_position)
157 best_total_distance = 1e100;
158 for(
unsigned i=0; i<storage.size(); ++i)
164 double distance = 0.0;
172 if(distance < best_total_distance)
174 best_interval = interval;
175 best_total_distance = distance;
176 best_interval_position = offset;
181 inline void GeodesicAlgorithmExact::possible_traceback_edges(
SurfacePoint& point,
182 std::vector<edge_pointer>& storage)
216 inline long GeodesicAlgorithmExact::visible_from_source(
SurfacePoint& point)
227 if(interval && interval->visible_from_source())
248 double position = e->
v0()->
id() == v->
id() ? 0.0 : e->
length();
263 inline double GeodesicAlgorithmExact::compute_positive_intersection(
double start,
269 assert(pseudo_y < 0);
271 double denominator = sin_alpha*(pseudo_x - start) - cos_alpha*pseudo_y;
277 double numerator = -pseudo_y*start;
279 if(numerator < 1e-30)
284 if(denominator < 1e-30)
289 return numerator/denominator;
292 inline void GeodesicAlgorithmExact::list_edges_visible_from_source(
MeshElementBase* p,
293 std::vector<edge_pointer>& storage)
300 for(
unsigned i=0; i<3; ++i)
308 storage.push_back(e);
325 assert(m_queue.count(p)<=1);
327 IntervalQueue::iterator it = m_queue.find(p);
329 if(it != m_queue.end())
339 inline unsigned GeodesicAlgorithmExact::intersect_intervals(
interval_pointer zero,
351 start[0] = zero->
start();
352 if(zero->
start() < one->
start() - local_epsilon)
355 start[1] = one->
start();
365 if(zero->
stop() > one->
stop() + local_epsilon)
368 start[N++] = one->
stop();
371 start[N+1] = zero->
stop();
375 double const local_small_epsilon = 1e-8*one->
edge()->
length();
377 double D = zero->
d() - one->
d();
386 if(std::abs(D)<local_epsilon)
388 double denom = x1 - x0;
389 if(std::abs(denom)>local_small_epsilon)
391 inter[0] = (R1 - R0)/(2.*denom);
398 double Q = 0.5*(R1-R0-D2);
402 double B = Q*X + D2*x0;
403 double C = Q*Q - D2*R0;
405 if (std::abs(A)<local_small_epsilon)
407 if(std::abs(B)>local_small_epsilon)
415 double det = B*B-A*C;
416 if(det>local_small_epsilon*local_small_epsilon)
421 inter[0] = (-B - det)/A;
422 inter[1] = (-B + det)/A;
426 inter[0] = (-B + det)/A;
427 inter[1] = (-B - det)/A;
430 if(inter[1] - inter[0] > local_small_epsilon)
450 double good_start[4];
451 good_start[0] = left;
452 unsigned char Ngood_start=1;
454 for(
unsigned char i=0; i<Ninter; ++i)
457 if(x > left + local_epsilon && x < right - local_epsilon)
459 good_start[Ngood_start++] = x;
462 good_start[Ngood_start++] = right;
465 for(
unsigned char i=0; i<Ngood_start-1; ++i)
467 double mid = (good_start[i] + good_start[i+1])*0.5;
468 mid_map[i] = zero->
signal(mid) <= one->
signal(mid) ? OLD : NEW;
473 if(zero->
start() < left - local_epsilon)
475 if(mid_map[0] == OLD)
477 good_start[0] = zero->
start();
482 start[N++] = zero->
start();
486 for(
long i=0;i<Ngood_start-1;++i)
488 MapType current_map = mid_map[i];
489 if(N==0 || map[N-1] != current_map)
491 map[N] = current_map;
492 start[N++] = good_start[i];
496 if(zero->
stop() > one->
stop() + local_epsilon)
498 if(N==0 || map[N-1] == NEW)
501 start[N++] = one->
stop();
505 start[0] = zero->
start();
511 inline void GeodesicAlgorithmExact::initialize_propagation_data()
516 std::vector<edge_pointer> edges_visible_from_source;
517 for(
unsigned i=0; i<m_sources.size(); ++i)
521 edges_visible_from_source.clear();
523 edges_visible_from_source);
525 for(
unsigned j=0; j<edges_visible_from_source.size(); ++j)
533 update_list_and_queue(interval_list(e), &candidate, 1);
539 double max_propagation_distance,
540 std::vector<SurfacePoint>* stop_points)
543 set_sources(sources);
544 initialize_propagation_data();
546 clock_t start = clock();
548 unsigned satisfied_index = 0;
551 m_queue_max_size = 0;
555 while(!m_queue.empty())
557 m_queue_max_size =
std::max(m_queue.size(), m_queue_max_size);
559 unsigned const check_period = 10;
560 if(++m_iterations % check_period == 0)
562 if (check_stop_conditions(satisfied_index))
569 m_queue.erase(m_queue.begin());
575 bool const first_interval = min_interval->
start() == 0.0;
577 bool const last_interval = min_interval->
next() == NULL;
596 unsigned num_propagated = compute_propagated_parameters(min_interval->
pseudo_x(),
599 min_interval->
start(),
600 min_interval->
stop(),
608 bool propagate_to_right =
true;
612 if(candidates[num_propagated-1].stop() != next_edge->
length())
614 propagate_to_right =
false;
617 bool const invert = next_edge->
v0()->
id() != edge->
v0()->
id();
619 construct_propagated_intervals(invert,
626 update_list_and_queue(interval_list(next_edge),
631 if(propagate_to_right)
637 num_propagated = compute_propagated_parameters(length - min_interval->
pseudo_x(),
640 length - min_interval->
stop(),
641 length - min_interval->
start(),
652 bool const invert = next_edge->
v0()->
id() != edge->
v1()->
id();
654 construct_propagated_intervals(invert,
661 update_list_and_queue(interval_list(next_edge),
670 clock_t stop = clock();
671 m_time_consumed = (
static_cast<double>(stop)-static_cast<double>(start))/CLOCKS_PER_SEC;
688 inline bool GeodesicAlgorithmExact::check_stop_conditions(
unsigned& index)
690 double queue_distance = (*m_queue.begin())->
min();
701 double distance = edge->
v0()->
id() == v->
id() ?
702 interval_list(edge)->
signal(0.0) :
716 inline void GeodesicAlgorithmExact::update_list_and_queue(
list_pointer list,
718 unsigned num_candidates)
720 assert(num_candidates <= 2);
725 if(list->
first() == NULL)
731 if(num_candidates == 1)
739 if(candidates->
start() <= (candidates+1)->start())
742 second = candidates+1;
746 first = candidates+1;
749 assert(first->
stop() == second->
start());
755 if(first->
start() > 0.0)
757 *p = m_memory_allocator.allocate();
758 (*p)->initialize(edge);
762 *p = m_memory_allocator.allocate();
766 if(num_candidates == 2)
769 *p = m_memory_allocator.allocate();
777 *p = m_memory_allocator.allocate();
778 (*p)->initialize(edge);
779 (*p)->start() = second->
stop();
790 for(
unsigned i=0; i<num_candidates; ++i)
797 assert(p->
start() == 0.0);
799 while(p != NULL && p->
stop() - local_epsilon < q->
start())
804 while(p != NULL && p->
start() < q->
stop() - local_epsilon)
806 unsigned const N = intersect_intervals(p, q);
814 previous->
next() = p;
816 m_queue.insert(previous);
827 m_memory_allocator.deallocate(p);
829 p = previous->
next();
837 memcpy(previous,q,
sizeof(
Interval));
839 previous->
start() = start[0];
840 previous->
next() = next;
850 propagate_flag = erase_from_queue(p);
852 for(
unsigned j=1; j<N; ++j)
854 i_new[j] = m_memory_allocator.allocate();
861 previous->
next() = p;
863 m_queue.insert(previous);
867 p->
next() = i_new[1];
868 p->
start() = start[0];
873 previous->
next() = i_new[1];
874 m_memory_allocator.deallocate(p);
882 p->
next() = i_new[1];
883 p->
start() = start[0];
888 for(
unsigned j=1; j<N; ++j)
894 memcpy(current_interval,&swap,
sizeof(
Interval));
898 memcpy(current_interval,q,
sizeof(
Interval));
903 current_interval->
next() = swap.
next();
907 current_interval->
next() = i_new[j+1];
910 current_interval->
start() = start[j];
913 for(
unsigned j=0; j<N; ++j)
915 if(j==N-1 && map[j]==NEW)
925 if(map[j]==NEW || (map[j]==OLD && propagate_flag))
927 m_queue.insert(current_interval);
938 m_queue.insert(previous);
944 inline unsigned GeodesicAlgorithmExact::compute_propagated_parameters(
double pseudo_x,
957 assert(pseudo_y<=0.0);
960 assert(first_interval ? (begin == 0.0) :
true);
964 if(std::abs(pseudo_y) <= 1e-30)
966 if(first_interval && pseudo_x <= 0.0)
970 p->
d() = d - pseudo_x;
975 else if(last_interval && pseudo_x >= end)
979 p->
d() = d + pseudo_x-end;
984 else if(pseudo_x >= begin && pseudo_x <= end)
989 p->
pseudo_x() = pseudo_x*cos(alpha);
990 p->
pseudo_y() = -pseudo_x*sin(alpha);
999 double sin_alpha = sin(alpha);
1000 double cos_alpha = cos(alpha);
1004 double L1 = compute_positive_intersection(begin,
1010 if(L1 < 0 || L1 >= L)
1012 if(first_interval && turn_left)
1016 p->
d() = d + sqrt(pseudo_x*pseudo_x + pseudo_y*pseudo_y);
1027 double L2 = compute_positive_intersection(end,
1033 if(L2 < 0 || L2 >= L)
1038 p->
pseudo_x() = cos_alpha*pseudo_x + sin_alpha*pseudo_y;
1039 p->
pseudo_y() = -sin_alpha*pseudo_x + cos_alpha*pseudo_y;
1047 p->
pseudo_x() = cos_alpha*pseudo_x + sin_alpha*pseudo_y;
1048 p->
pseudo_y() = -sin_alpha*pseudo_x + cos_alpha*pseudo_y;
1051 if(!(last_interval && turn_right))
1061 double dx = pseudo_x - end;
1062 p->
d() = d + sqrt(dx*dx + pseudo_y*pseudo_y);
1070 inline void GeodesicAlgorithmExact::construct_propagated_intervals(
bool invert,
1074 unsigned& num_candidates,
1077 double edge_length = edge->
length();
1081 if(num_candidates == 2)
1083 double start =
std::min(candidates->
start(), (candidates+1)->start());
1084 double stop =
std::max(candidates->
stop(), (candidates+1)->stop());
1085 if(candidates->
stop()-candidates->
start() < local_epsilon)
1087 *candidates = *(candidates+1);
1089 candidates->
start() = start;
1090 candidates->
stop() = stop;
1092 else if ((candidates+1)->stop() - (candidates+1)->start() < local_epsilon)
1095 candidates->
start() = start;
1096 candidates->
stop() = stop;
1102 if(num_candidates == 1)
1105 second = candidates;
1109 if(candidates->
start() <= (candidates+1)->start())
1112 second = candidates+1;
1116 first = candidates+1;
1117 second = candidates;
1119 assert(first->
stop() == second->
start());
1122 if(first->
start() < local_epsilon)
1124 first->
start() = 0.0;
1126 if(edge_length - second->
stop() < local_epsilon)
1128 second->
stop() = edge_length;
1138 for(
unsigned i=0; i<num_candidates; ++i)
1142 p->
next() = (i == num_candidates - 1) ? NULL : candidates + i + 1;
1154 for(
unsigned i=0; i<num_candidates; ++i)
1158 p->
next() = (i == 0) ? NULL : candidates + i - 1;
1163 double length = edge_length;
1166 double start = length - p->
stop();
1173 assert(p->
start() >= 0.0);
1181 double& best_source_distance)
1183 double best_interval_position;
1184 unsigned best_source_index;
1186 best_first_interval(point,
1187 best_source_distance,
1188 best_interval_position,
1191 return best_source_index;
1195 double& best_total_distance,
1196 double& best_interval_position,
1197 unsigned& best_source_index)
1209 best_interval_position = point.
distance(e->
v0());
1214 best_total_distance = best_interval->
signal(best_interval_position);
1215 best_source_index = best_interval->source_index();
1221 for(
unsigned i=0; i<3; ++i)
1226 double offset = 0.0;
1227 double distance = 0.0;
1235 if(interval && distance < best_total_distance)
1237 best_interval = interval;
1238 best_total_distance = distance;
1239 best_interval_position = offset;
1249 double distance = point.
distance(source);
1250 if(distance < best_total_distance)
1252 best_interval = NULL;
1253 best_total_distance = distance;
1254 best_interval_position = 0.0;
1255 best_source_index = source->
index();
1267 double position = e->
v0()->
id() == v->
id() ? 0.0 : e->
length();
1271 double distance = interval->
signal(position);
1273 if(distance < best_total_distance)
1275 best_interval = interval;
1276 best_total_distance = distance;
1277 best_interval_position = position;
1291 return best_interval;
1296 std::vector<SurfacePoint>& path,std::vector<unsigned>& )
1302 std::vector<SurfacePoint>& path)
1305 double best_total_distance;
1306 double best_interval_position;
1309 best_total_distance,
1310 best_interval_position,
1318 path.push_back(destination);
1322 std::vector<edge_pointer> possible_edges;
1323 possible_edges.reserve(10);
1325 while(visible_from_source(path.back()) < 0)
1329 possible_traceback_edges(q, possible_edges);
1332 double total_distance;
1333 double position = 0.0;
1335 best_point_on_the_edge_set(q,
1347 if(position < local_epsilon)
1351 else if(position > e->
length()-local_epsilon)
1357 double normalized_position = position/e->
length();
1364 if(path.back().distance(&source) > 0)
1366 path.push_back(source);
1374 unsigned interval_counter = 0;
1375 for(
unsigned i=0; i<m_edge_interval_lists.size(); ++i)
1377 interval_counter += m_edge_interval_lists[i].number_of_intervals();
1379 double intervals_per_edge = (double)interval_counter/(
double)m_edge_interval_lists.size();
1381 double memory = m_edge_interval_lists.size()*
sizeof(
IntervalList) +
1384 std::cout <<
"uses about " << memory/1e6 <<
"Mb of memory" <<std::endl;
1385 std::cout << interval_counter <<
" total intervals, or " 1386 << intervals_per_edge <<
" intervals per edge" 1388 std::cout <<
"maximum interval queue size is " << m_queue_max_size << std::endl;
1389 std::cout <<
"number of interval propagations is " << m_iterations << std::endl;
1394 #endif //GEODESIC_ALGORITHM_EXACT_20071231
unsigned best_source(SurfacePoint &point, double &best_source_distance)
float min(float x, float y)
DirectionType & direction()
float max(float x, float y)
~GeodesicAlgorithmExact()
double m_propagation_distance_stopped
GeodesicAlgorithmExact(geodesic::Mesh *mesh)
bool & saddle_or_boundary()
edge_pointer_vector & adjacent_edges()
std::pair< sorted_iterator, sorted_iterator > sorted_iterator_pair
bool visible_from_source()
void set_stop_conditions(std::vector< SurfacePoint > *stop_points, double stop_distance)
interval_pointer & next()
std::vector< stop_vertex_with_distace_type > m_stop_vertices
std::vector< Edge > & edges()
void initialize(edge_pointer edge, SurfacePoint *point=NULL, unsigned source_index=0)
void propagate(std::vector< SurfacePoint > &sources, double max_propagation_distance=GEODESIC_INF, std::vector< SurfacePoint > *stop_points=NULL)
sorted_vector_type::iterator sorted_iterator
void compute_min_distance(double stop)
double vertex_angle(vertex_pointer v)
virtual void print_statistics()
double length(std::vector< SurfacePoint > &path)
interval_pointer covering_interval(double offset)
unsigned & source_index()
edge_pointer opposite_edge(vertex_pointer v)
void trace_back(SurfacePoint &destination, std::vector< SurfacePoint > &path)
double const GEODESIC_INF
base_pointer & base_element()
void initialize(std::vector< SurfacePoint > &sources)
face_pointer_vector & adjacent_faces()
double distance(double *v)
sorted_iterator_pair sources(base_pointer mesh_element)
void swap(scoped_ptr< T > &x, scoped_ptr< T > &y)
interval_pointer & first()
double const SMALLEST_INTERVAL_RATIO
edge_pointer next_edge(edge_pointer e, vertex_pointer v)
void find_closest_point(SurfacePoint *point, double &offset, double &distance, interval_pointer &interval)
void trace_back_with_index(SurfacePoint &destination, std::vector< SurfacePoint > &path, std::vector< unsigned > &indexVertex)