#ifndef UPDATABLE_DELAUNAY_TRIANGULATION_2_H #define UPDATABLE_DELAUNAY_TRIANGULATION_2_H #ifdef NDEBUG #define CGAL_UD_DEBUG(x) #else #define CGAL_UD_DEBUG(x) std::cout << x #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include CGAL_BEGIN_NAMESPACE /* Open questions: - storage of certs - priority queue for deletions Where to go next: - optimize priority queue--insert is 20% - Delaunay::set is 14%, this seems a bit slow - storing certs in edge is 10% - delete certificate is 5% - static certificates: how to do it for wide intervals and just check at each successive event to make sure that they can be advanced. This requires being able to create certificates from the Traits which is an easy change to Delaunay but still a change. */ template struct Updatable_Delaunay_triangulation_2 { typedef typename IndirectKernel::Point_2 Point_key; typedef typename Kinetic::Suggested_exact_simulation_traits_base SimTraits_base; typedef Update_cert_tuple Cert_tuple; typedef CGAL::Interval_nt_advanced INT; typedef CGAL::Gmpq NT; typedef CGAL::POLYNOMIAL::Polynomial Function; typedef CGAL::POLYNOMIAL::Sturm_root_stack_traits Root_stack_traits; typedef CGAL::POLYNOMIAL::Sturm_root_stack Root_stack; typedef CGAL::POLYNOMIAL::Kernel Function_kernel; typedef typename CGAL::Kinetic::Handle_degeneracy_function_kernel KK_function_kernel; typedef typename CGAL::Kinetic::Cartesian_kinetic_kernel Kinetic_kernel; typedef IndirectKernel Indirect_kernel; typedef Updatable_delaunay_triangulation_table_2 Update_information; typedef typename Indirect_kernel::Geometric_point_2 Static_point_2; typedef typename Indirect_kernel::Swapable_container Points; typedef typename Kinetic_kernel::Point_2 Kinetic_point_2; typedef typename Kinetic_kernel::Motion_function Kinetic_coordinate; typedef typename Indirect_kernel::Current_coordinates IK_current_coordinates; typedef typename Kinetic_kernel::Certificate Exact_certificate; typedef typename Function_kernel::Root Exact_time; struct Refiner { struct CS: public CGAL::Kinetic::Ref_counted { CS(const Exact_certificate &c): cert_(c){} Exact_certificate cert_; }; // enum State {INTERVAL, EXACT, INVALID}; Refiner(Cert_tuple t, const INT *certf, typename Update_information::Handle tbl): tuple_(t), ui_(tbl){ /*CGAL::Protect_FPU_rounding prot; ui_->certificate_function(t[0], t[1], t[2], t[3], certf_); CGAL_UD_DEBUG("Certificate func is " << certf_[0] << " + " << certf_[1] << "*t + " << certf_[2] << "*t^2 +" << certf_[2] << "*t^3 + " << certf_[3] << "*t^4" << std::endl);*/ certf_[0]=certf[0]; certf_[1]=certf[1]; certf_[2]=certf[2]; certf_[3]=certf[3]; certf_[4]=certf[4]; } Refiner() { } bool is_invalid() const { return tuple_.is_invalid(); } typedef Exact_time Exact_root; /*This operator-() const { return *this; }*/ bool refine(std::pair &iv) const { CGAL_precondition(ui_ != typename Update_information::Handle()); if (iv.first == iv.second) return false; if (has_exact_root()) return false; double dd= iv.second-iv.first; if (dd > .000001) { CGAL::Protect_FPU_rounding prot; std::pair oiv=iv; typename Update_information::Certificate_evaluator se(certf_); ui_->isolate_failure(se, iv.first, iv.second, false, 0, 20, iv); #ifndef NDEBUG if ( oiv ==iv) { std::cout << "Can't subdivide more in " << iv.first << " " << iv.second << std::endl; } #endif return oiv != iv; } else { // compute exact; CGAL_assertion(!has_exact_root()); //++comparison_certificates_; ensure_exact_root(iv); iv= CGAL::to_interval(exact_root()); return true; } } const Exact_root& exact_root() const { /*if (ui_ == typename Update_information::Handle()) { CGAL_assertion(0); static Exact_root er; return er; } else {*/ return cert_->cert_.failure_time(); //} } const Exact_root& exact_root(std::pair &iv) const { /*if (ui_ == typename Update_information::Handle()) { CGAL_assertion(0); static Exact_root er; return er; } else {*/ ensure_exact_root(iv); return exact_root(); //} } void write(std::ostream &out) const { if (tuple_ == Cert_tuple()) { } else{ out << tuple_; if (has_exact_root()) { out << " " << exact_root(); } } } const Cert_tuple tuple() const { return tuple_; } bool equal_description(const Refiner &o) const { if (tuple_ == Cert_tuple()) return false; return tuple_== o.tuple_; } bool has_exact_root() const { return cert_!= typename CS::Handle() ; } CGAL::Sign sign_at(INT t) const { return Update_information::sign_at(certf_, t); } void ensure_exact_root(std::pair &iv) const { if (!has_exact_root()) { if (ui_ != typename Update_information::Handle()) { ++comparison_certificates_; CGAL_UD_DEBUG("Generating exact with interval " << iv.first << " " << iv.second << std::endl); cert_= new CS(ui_->compute_exact_failure_time(tuple_, iv.first)); CGAL_assertion(check_.failure_time() == exact_root()); iv= CGAL::to_interval(exact_root()); } else { double cs[2]; cs[0]=iv.first; cs[1]=-1.0; typename Exact_certificate::Function f(cs, cs+2); // hack cert_= new CS(Exact_certificate(f, KK_function_kernel(), -1, 2)); CGAL_UD_DEBUG(f << ": " << exact_root() << std::endl); CGAL_assertion(exact_root() == Exact_time(iv.first)); #ifndef NDEBUG check_= cert_->cert_; #endif } } } void ensure_exact_root(const Exact_time &et) const { if (!has_exact_root()) { CGAL_UD_DEBUG("Generating exact with root " << et << std::endl); ++comparison_certificates_; CGAL_precondition(ui_ != typename Update_information::Handle()); //if (ui_ != ) { cert_= new CS(ui_->compute_exact_failure_time(tuple_, et)); CGAL_assertion(check_.failure_time() == exact_root()); } } const Exact_certificate& exact_certificate() const { return cert_->cert_; } std::pair interval_from_exact() const { CGAL_precondition(has_exact_root()); if (exact_root() >= Exact_time(1)) { return std::make_pair(1.0, -1.0); } else { std::pair ip= CGAL::to_interval(exact_root()); return ip; } } void set_exact_certificate(const Exact_certificate& ec) { CGAL_precondition(!has_exact_root()); cert_= new CS(ec); CGAL_postcondition(exact_root() == check_.failure_time()); } Cert_tuple tuple_; typename Update_information::Handle ui_; mutable typename CS::Handle cert_; INT certf_[5]; #ifndef NDEBUG mutable Exact_certificate check_; #endif }; struct Simulation_traits { typedef SimTraits_base P; struct Sillyness { typedef Kinetic_kernel KK; //typedef Active_points_2_table APT; }; typedef typename Sillyness::KK Kinetic_kernel; typedef Update_information Active_points_2_table; Active_points_2_table* active_points_2_table_handle() { return ap_.get(); } const Active_points_2_table* active_points_2_table_handle() const { return ap_.get(); } typedef CGAL::Simple_cartesian Static_kernel; typedef typename Kinetic::Cartesian_instantaneous_kernel Instantaneous_kernel; Instantaneous_kernel instantaneous_kernel_object() const { return Instantaneous_kernel(ap_, Static_kernel()); } typedef typename Kinetic::Interval_simulator_traits Simulator_traits; typedef typename Kinetic::Two_list_pointer_event_queue Queue; typedef typename Kinetic::Default_simulator Simulator; typename Simulator::Handle simulator_handle() { return sim_; } typename Simulator::Handle simulator_handle() const { return sim_; } typedef typename Simulator::Time Time; Simulation_traits(Indirect_kernel ik, double lb, double ub): sim_(new Simulator(lb, ub)){ ap_=new Active_points_2_table(ik, kinetic_kernel_object()); } Simulation_traits(){} Kinetic_kernel kinetic_kernel_object() const { return Kinetic_kernel(); } protected: typename Active_points_2_table::Handle ap_; typename Simulator::Handle sim_; }; typedef typename Simulation_traits::Simulator::Event_key Event_key; typedef CGAL::Delaunay_triangulation_2, CGAL::Kinetic::Delaunay_triangulation_face_base_2 > > Triangulation; typedef CGAL::Kinetic::internal::Triangulation_data_structure_helper_2 TDS_helper; typedef typename Triangulation::Edge Edge; typedef typename Simulation_traits::Kinetic_kernel::Motion_function::NT ENT; typedef Kinetic::Delaunay_triangulation_default_traits_2 Default_traits; struct Traits: public Default_traits { typedef Default_traits P; typedef typename Simulation_traits::Simulator::Time Time; struct Certificate_data{}; typedef std::pair Certificate_pair; typedef typename Default_traits::Triangulation Triangulation; typedef typename Default_traits::Point_2 Point_2; typedef typename Default_traits::Simulator Simulator; bool is_exact() const { return true; } Cert_typle tuple(Point_key ks[4]) const { return Cert_typle(ks); } /*Cert_tuple tuple(typename Default_traits::Edge e) const { Point_key ks[4]; ks[0]= TDS_helper::origin(e)->point(); ks[1]= TDS_helper::third_vertex(e)->point(); ks[2]= TDS_helper::destination(e)->point(); ks[3]= TDS_helper::mirror_vertex(e)->point(); if (ks[1] == Point_key() || ks[3]==Point_key() || ks[0] == Point_key() || ks[2]== Point_key()) return Cert_tuple(); else return Cert_tuple(ks); }*/ void point_changed(Point_key k){ ui()->point_changed(k); } const Time ¤t_time() const { return P::simulator_handle()->current_time(); } Certificate_pair null_pair() const { return std::make_pair(Time(2.0), Certificate_data()); } Certificate_pair return_pair(Time rt) const { return Certificate_pair(rt, Certificate_data()); } double rational_current_time() const { return CGAL::to_interval(current_time()).first; } Traits(Simulation_traits st): P(st){} //soc_(tr.kinetic_kernel_object().positive_side_of_oriented_circle_2_object()){} Update_information* ui() { return P::active_points_2_table_handle().get(); } bool hull_certificate_failure_time(typename Default_traits::Edge, Point_key [3], Time, Certificate_data) { return false; } bool internal_certificate_failure_time(typename Default_traits::Edge e, Point_key pks[4], Time &rett, Certificate_data) { Cert_tuple ct= tuple(pks); double end_time= ui()->next_activation(); //ui()->set_next_activation(1.0); #ifndef NDEBUG Exact_time check_failure_time; Exact_certificate check_cert; { Exact_time ect; if (P::simulator_handle()->current_time().refiner().is_invalid()) { ect= Exact_time(CGAL::to_interval(P::simulator_handle()->current_time()).first); } else { ect= P::simulator_handle()->current_time().refiner().check_.failure_time(); } check_cert= ui()->soc_(ui()->exact_point(ct[0]), ui()->exact_point(ct[1]), ui()->exact_point(ct[2]), ui()->exact_point(ct[3]), ect, 1); check_failure_time= check_cert.failure_time(); if (check_failure_time > end_time) check_failure_time= 2; } #endif //std::pair ctp= Cert_tuple::make(ks); CGAL_UD_DEBUG("Computing failure time for " << ct << std::endl); CGAL_UD_DEBUG("Exact failure time is " << check_failure_time<< std::endl); double bt = ui()->start_time(); if (bt <0) { bt= CGAL::to_interval(current_time()).first; } if (!ui()->can_fail(ct, bt, end_time)) { CGAL_postcondition(check_failure_time > 1); return null_pair(); } INT cf[5]; std::pair ft; typename Update_information::Isolate_result isc; #ifndef NDEBUG if (ui()->is_active(ct[0]) || ui()->is_active(ct[1]) || ui()->is_active(ct[2]) || ui()->is_active(ct[3])){ #else { #endif CGAL::Protect_FPU_rounding prot; ui()->certificate_function(ct[0], ct[1], ct[2], ct[3], cf); //typename Update_information::Certificate_evaluator se(cf); isc= ui()->isolate_failure(cf, bt, end_time, true, ft); #ifndef NDEBUG } else { isc = Update_information::NO_FAILURE; } #else } #endif if (isc == Update_information::NO_FAILURE) { CGAL_UD_DEBUG("Not isolated" << std::endl); CGAL_assertion(check_failure_time >=1); return null_pair(); } rett= Time(ft.first, ft.second, Refiner(ct, cf, ui())); #ifndef NDEBUG rett.refiner().check_= check_cert; #endif /* Check if the curren time is exact, if so check if I am positive at it*/ if (isc == Update_information::CERTAIN_FAILURE) { if (ft.first <= CGAL::to_interval(current_time()).second) { // interval overlaps current //std::pair cti= CGAL::to_interval(P::simulator_handle()->current_time()); //P::simulator_handle()->current_time().refiner().ensure_exact_root(cti); const Exact_time &ect= P::simulator_handle()->current_time().exact_root(); if (Exact_time(ft.first) <= ect) { rett.refiner().ensure_exact_root(ect); CGAL_UD_DEBUG("Exact" << rett.refiner().exact_root() << std::endl); rett.set_interval(CGAL::to_interval(rett.refiner().exact_root())); } } CGAL_UD_DEBUG("Returning isolated " << rett << std::endl); return true; } else { //if (!has_exact_failure_time(ct)) { ++uncertain_exact_computations_; // } CGAL_UD_DEBUG("Not isolated " << std::endl); //std::pair cti=CGAL::to_interval(P::simulator_handle()->current_time()); //P::simulator_handle()->current_time().refiner().ensure_exact_root(cti); const Exact_time &ect= P::simulator_handle()->current_time().exact_root(); rett.refiner().ensure_exact_root(ect); CGAL_UD_DEBUG("Exact" << rett.refiner().exact_root() << std::endl); if (rett.refiner().exact_root() >= 1) { CGAL_assertion(check_failure_time >=1); CGAL_UD_DEBUG("Phantom root " << std::endl); CGAL_postcondition(check_failure_time > 1); return false; } else { rett.set_interval(CGAL::to_interval(rett.refiner().exact_root())); CGAL_UD_DEBUG("Returning exact " << rett << std::endl); return true; } } } bool certificate_failure_time(typename Default_traits::Edge, Certificate_data , Time &rett, Certificate_data) { bool end_time_is_not_correct; const Time &curt= P::simulator_handle()->current_time(); Cert_tuple ct= curt.refiner().tuple().opposite(); #ifndef NDEBUG Cert_tuple check_ct= tuple(e); #endif CGAL_assertion(ct == check_ct); double end_time= ui()->next_activation(); ui()->set_next_activation(1.0); #ifndef NDEBUG Exact_time check_failure_time; Exact_certificate check_cert; { check_cert= curt.refiner().check_; check_cert.pop_failure_time(); check_failure_time= check_cert.failure_time(); if (check_failure_time > end_time) check_failure_time= 2; CGAL_UD_DEBUG("Exact time is " << check_cert.failure_time() << std::endl); } #endif //std::pair ctp= Cert_tuple::make(ks); /*if (!can_fail(ct, end_time)) { CGAL_postcondition(check_failure_time > 1); return null_pair(); }*/ CGAL_UD_DEBUG("Advancing certificate for " << ct << std::endl); // this depends on being the last event of the batch whose time is computed const Time& net= P::simulator_handle()->next_event_time(); double lb= CGAL::to_interval(net).first; bool pos_start=false; if (lb == ui()->start_time()) { pos_start=true; } else { // done twiceish CGAL::Protect_FPU_rounding prot; CGAL::Sign sn= curt.refiner().sign_at(INT(lb,lb)); //ui()->sign_at(ct[0],ct[1],ct[2],ct[3], INT(lb, lb)); if (sn != CGAL::POSITIVE) { lb= CGAL::to_interval(curt).first; } else { pos_start=true; } } INT cf[5]; std::pair ft; typename Update_information::Isolate_result isc; { CGAL::Protect_FPU_rounding prot; ui()->certificate_function(ct[0], ct[1], ct[2], ct[3], cf); //typename Update_information::Certificate_evaluator se(cf); isc = ui()->isolate_failure(cf, lb, end_time, pos_start, ft); } if (isc == Update_information::NO_FAILURE) { CGAL_UD_DEBUG("No root there." << std::endl); CGAL_postcondition(check_failure_time > 1); return false; } rett=Time(ft.first, ft.second, Refiner(ct, cf, ui())); #ifndef NDEBUG rett.refiner().check_= check_cert; #endif if (isc == Update_information::CERTAIN_FAILURE && ft.first <= CGAL::to_interval(curt).second || isc == Update_information::POSSIBLE_FAILURE || curt.refiner().has_exact_root()) { if (isc == Update_information::POSSIBLE_FAILURE) { ++uncertain_exact_computations_; } curt.exact_root(); Exact_certificate ec= curt.refiner().exact_certificate(); ec.pop_failure_time(); if (ec.failure_time() > 1) { ++unfailing_kinetic_certificates_; CGAL_UD_DEBUG("Phantom root " << std::endl); CGAL_postcondition(check_failure_time > 1); return false; } ++certificate_advances_; ft= CGAL::to_interval(curt.refiner().exact_root()); rett.set_interval(ft); rett.refiner().set_exact_certificate(ec); return true; } else { CGAL_UD_DEBUG("Returning " << rett << std::endl); return true; } } CGAL::Comparison_result compare_concurrent(Event_key a, Edge, Event_key b, Edge) const { return CGAL::compare(a,b); } }; struct Visitor: public CGAL::Kinetic::Delaunay_triangulation_visitor_base_2 { Visitor(Simulation_traits tr): tr_(tr) { } Update_information* ui() { return tr_.active_points_2_table_handle(); } const Update_information* ui() const { return tr_.active_points_2_table_handle(); } bool test_and_add(Edge e, std::vector &active) const { ++static_certificates_; if (!compute_ok(e, ui()->fk_)) { add(e.first->vertex(0)->point(), active); add(e.first->vertex(1)->point(), active); add(e.first->vertex(2)->point(), active); add(TDS_helper::mirror_vertex(e)->point(), active); return true; } else return false; } bool test_and_add_one(Edge e, std::vector &active) const { ++ui()->static_certificates_; if (!compute_ok(e, ui()->fk_)) { //add(e.first->vertex(0)->point(), active); //add(e.first->vertex(1)->point(), active); //add(e.first->vertex(2)->point(), active); add(TDS_helper::mirror_vertex(e)->point(), active); return true; } else return false; } template void initialize_events(const TDS &triangulation, Indirect_kernel fk) { stat_num_edges_=triangulation.tds().number_of_edges(); ui()->set_final_kernel(fk); std::vector active; for (typename TDS::Finite_edges_iterator it= triangulation.finite_edges_begin(); it != triangulation.finite_edges_end(); ++it){ if (test_and_add(*it, active)) { ++stat_bad_edges_; } } Interpolate_event ev(tr_, ui(), ui()->ik_.current_coordinates_object(), ui()->fk_.current_coordinates_object(), active.begin(), active.end()); if (!ev.empty()) { INT iat= CGAL::to_interval(ev.time()); tr_.simulator_handle()->new_event(ev.time(), ev); /*for (unsigned int i=0; i< active.size(); ++i){ ui_->activate(active[i],iat); }*/ } } void after_flip(Edge e) { //++num_events_; // schedule a bulk set event for next rational time std::vector active; //test_and_add(e, active); //CGAL_precondition(ui_->is_active(e.first->vertex((e.second+1)%3)->point())); //CGAL_precondition(ui_->is_active(e.first->vertex((e.second+2)%3)->point())); //CGAL_precondition(ui_->is_active(e.first->vertex(e.second)->point())); add(e.first->vertex(0)->point(), active); add(e.first->vertex(1)->point(), active); add(e.first->vertex(2)->point(), active); Edge em= TDS_helper::mirror_edge(e); //CGAL_precondition(ui_->is_active(em.first->vertex(em.second)->point())); add(em.first->vertex(em.second)->point(), active); //test_and_add_one(Edge(e.first, (e.second+1)%3), active); //test_and_add_one(Edge(e.first, (e.second+2)%3), active); //test_and_add_one(Edge(em.first, (em.second+1)%3), active); //test_and_add_one(Edge(em.first, (em.second+2)%3), active); if (!active.empty()) { Interpolate_event ev(tr_, ui(), ui()->ik_.current_coordinates_object(), ui()->fk_.current_coordinates_object(), active.begin(), active.end()); if (!ev.empty()){ tr_.simulator_handle()->new_event(ev.time(), ev); //active_.set(active.begin(), active.end()); ++num_interpolations_; /*for (unsigned int i=0; i< active.size(); ++i){ ui_->activate(active[i], true); }*/ ui()->set_next_activation(CGAL::to_interval(ev.time()).second); } } bool ok=true; double skip_to= CGAL::to_interval(tr_.simulator_handle()->next_event_time()).first; { CGAL::Protect_FPU_rounding prot; CGAL::Sign sn = tr_.simulator_handle()->current_time().refiner().sign_at(INT(skip_to)); /*= ui()->sign_at(e.first->vertex(0)->point(), e.first->vertex(1)->point(), e.first->vertex(2)->point(), em.first->vertex(em.second)->point(), INT(skip_to));*/ if (sn == CGAL::POSITIVE) { for (int i=0; i< 3; ++i) { if (i != e.second) { CGAL::Sign sn= ui()->sign_at(e.first->vertex(0)->point(), e.first->vertex(1)->point(), e.first->vertex(2)->point(), e.first->mirror_vertex(i)->point(), INT(skip_to)); if (sn != CGAL::POSITIVE) { ok=false; break; } } if (i != em.second) { CGAL::Sign sn= ui()->sign_at(em.first->vertex(0)->point(), em.first->vertex(1)->point(), em.first->vertex(2)->point(), em.first->mirror_vertex(i)->point(), INT(skip_to)); if (sn != CGAL::POSITIVE) { ok=false; break; } } } } } if (ok) { CGAL_UD_DEBUG("Skipping to " << skip_to << " from " << tr_.simulator_handle()->current_time() << std::endl); ui()->set_start_time(skip_to); } else { ui()->set_start_time(-1); } } bool is_active(Point_key k) const { return ui()->is_active(k); } void add( Point_key k, std::vector &active) const { if (!is_active(k)) { active.push_back(k); } } void reset() { ui()->reset(); } Static_point_2 initial(Point_key pk) const { return ui()->ik_.current_coordinates_object()(pk); } Static_point_2 final(Point_key pk) const { return ui()->fk_.current_coordinates_object()(pk); } void stats_clear() { ui()->clear_stats(); } void stats_write(std::ostream &out) { ui()->write_stats(out); } Simulation_traits tr_; }; static Kinetic_point_2 interpolate_t1(NT time, Static_point_2 ip, Static_point_2 fp) { typedef typename Simulation_traits::Kinetic_kernel::Motion_function MF; typedef typename MF::NT NT; MF mf[2]; for (unsigned int i=0; i< 2; ++i){ NT c[2]; c[1]=(NT(ip[i])-NT(fp[i]))/NT(time-1); c[0]=NT(fp[i])-c[1]; mf[i]=MF(c, c+2); } return Kinetic_point_2(mf[0], mf[1]); } static Kinetic_point_2 interpolate_12(Static_point_2 ip, Static_point_2 fp) { typedef typename Simulation_traits::Kinetic_kernel::Motion_function MF; MF mf[2]; for (unsigned int i=0; i< 2; ++i){ NT c[2]; c[1]=(fp[i]-ip[i]); c[0]=2*ip[i]-fp[i]; mf[i]=MF(c, c+2); } return Kinetic_point_2(mf[0], mf[1]); } struct Interpolate_event: public CGAL::Kinetic::Free_event_base { //typedef typename Simulation_traits::Active_points_2_table Table; //typedef typename Simulation_traits::Active_points_2_table::Key Table_key; //typedef typename std::pair MP; template Interpolate_event(Simulation_traits tr, typename Update_information::Handle ui, IK_current_coordinates ic, IK_current_coordinates fc, It b, It e): ui_(ui) { // make sure it is clear of the event to not prompt building of exact /*if (tr.simulator_handle()->current_time() == typename Simulation_traits::Simulator::NT(0)) { time_=0; } else {*/ time_= CGAL::to_interval(tr.simulator_handle()->current_time()).second; //} std::sort(b,e); It ne= std::unique(b,e); for (It c=b; c!= ne; ++c){ if (ic(*c) != fc(*c)) { motions_.push_back(*c); } else { CGAL_UD_DEBUG("Point " << *c << " doesn't move." << std::endl); } } if (!empty()) { CGAL_UD_DEBUG("Will Interpolate at " << time()); } } typename Simulation_traits::Simulator::Time time() const { return time_; } std::ostream & write(std::ostream&out) const { out << "Update "; for (unsigned int i=0; i< motions_.size(); ++i){ out << motions_[i] << " "; } return out; } bool empty() const { return motions_.empty(); } void process() { INT it= CGAL::to_interval(time_); ui_->set_is_editing(Update_information::LOGGED); CGAL::Protect_FPU_rounding prot; for (unsigned int i=0; i< motions_.size(); ++i) { /*out << "Setting motion of " << motions_[i].first << " to " << motions_[i].second << " which is currently " << motions_[i].second.x()(time_) << " " << motions_[i].second.y()(time_) << " with a current position of " << tr_.active_points_2_table_handle()->at(motions_[i].first) << std::endl;*/ ui_->activate(time_, motions_[i]); } ui_->set_is_editing(Update_information::NOT); } typename Update_information::Handle ui_; typename std::vector motions_; double time_; }; typedef CGAL::Kinetic::Delaunay_triangulation_2 KDel; struct Final_event: public CGAL::Kinetic::Free_event_base { typedef typename Simulation_traits::Active_points_2_table::Key Table_key; Final_event(Simulation_traits tr, typename KDel::Handle kdel): tr_(tr), kdel_(kdel){ } std::ostream & write(std::ostream&out) const { out << "Final event "; return out; } void process() { kdel_->write_stats(std::cout); kdel_->visitor().stats_write(std::cout); tr_.simulator_handle()->set_interval(1,2); tr_.active_points_2_table_handle()->set_is_editing(Update_information::LOGGED); for (typename Simulation_traits::Active_points_2_table::Key_iterator it = tr_.active_points_2_table_handle()->keys_begin(); it != tr_.active_points_2_table_handle()->keys_end(); ++it) { if (!kdel_->visitor().is_active(*it)) { tr_.active_points_2_table_handle()->set(*it, interpolate_12(initial(*it), final(*it))); } else { Kinetic_point_2 np(ENT(final(*it).x()), ENT(final(*it).y())); tr_.active_points_2_table_handle()->set(*it,np); } } tr_.active_points_2_table_handle()->set_is_editing(Update_information::NOT); } Static_point_2 initial(Point_key pk) const { return tr_.active_points_2_table_handle()->initial(pk); } Static_point_2 final(Point_key pk) const { return tr_.active_points_2_table_handle()->final(pk); } Simulation_traits tr_; typename KDel::Handle kdel_; }; template Updatable_Delaunay_triangulation_2(It b, It e) { typename Indirect_kernel::Key_range rg= ik_.new_point_2s(b,e); tr_= Simulation_traits(ik_, 0,0); Triangulation tr(ik_); tr.insert(rg.first, rg.second); Traits traits(tr_); /*traits.active_points_2_table_handle()->set_is_editing(Update_information::UNLOGGED); for (It c=b; c!= e; ++c){ traits.active_points_2_table_handle()->insert(Kinetic_point_2(Kinetic_coordinate(c->x()), Kinetic_coordinate(c->y()))); } traits.active_points_2_table_handle()->set_is_editing(Update_information::NOT);*/ kdel_= new KDel(traits, tr, Visitor(tr_)); kdel_->clear_stats(); kdel_->visitor().stats_clear(); } const Triangulation &triangulation() const { return kdel_->triangulation(0); } Triangulation &triangulation() { return kdel_->triangulation(0); } void update_coordinates_demo(const Points &pts) { typedef CGAL::Kinetic::Qt_widget_2 Qt_gui; typedef CGAL::Kinetic::Qt_moving_points_2 Qt_mps; typedef CGAL::Kinetic::Qt_triangulation_2 Qt_triangulation; audit(); kdel_->visitor().stats_clear(); kdel_->clear_stats(); Indirect_kernel fk=set_up_update(pts); char *argv[1]={"UpdateDel"}; typename Qt_gui::Handle qtsim= new Qt_gui(1, argv, tr_.simulator_handle()); typename Qt_mps::Handle qtmps= new Qt_mps(qtsim, tr_); //qtmps->set_point_size(10); typename Qt_triangulation::Handle qtdel = new Qt_triangulation(kdel_, tr_.instantaneous_kernel_object(), qtsim); tr_.simulator_handle()->new_final_event(Final_event(tr_, kdel_)); std::cout << "Green edges just flipped, grey edges will not flip until" << " their certificate changes and black edges will flip." << std::endl; qtsim->begin_event_loop(); ik_.swap(fk); audit(); } Indirect_kernel set_up_update(const Points &pts) { kdel_->visitor().reset(); kdel_->set_has_certificates(false); tr_.simulator_handle()->set_interval(0,1); /* tr_.active_points_2_table_handle()->set_is_editing(Update_information::UNLOGGED); typename Indirect_kernel::Current_coordinates cc= ik_.current_coordinates_object(); for (typename Simulation_traits::Active_points_2_table::Key_iterator kit= tr_.active_points_2_table_handle()->keys_begin(); kit != tr_.active_points_2_table_handle()->keys_end(); ++kit) { tr_.active_points_2_table_handle()->set(*kit, Kinetic_point_2(Kinetic_coordinate(cc(*kit).x()), Kinetic_coordinate(cc(*kit).y()))); } tr_.active_points_2_table_handle()->set_is_editing(Update_information::NOT);*/ Indirect_kernel fk; fk.new_point_2s(pts.begin(), pts.end()); kdel_->set_has_certificates(true, true); kdel_->visitor().initialize_events(kdel_->triangulation(), fk); return fk; } void update_coordinates(const Points &pts) { Indirect_kernel fk=set_up_update(pts); tr_.simulator_handle()->set_current_time(1); ik_.swap(fk); } void write_statistics(std::ostream &out) const { kdel_->write_stats(out); kdel_->visitor().stats_write(out); } void audit() const { typename Indirect_kernel::Current_coordinates cc = ik_.current_coordinates_object(); for (typename KDel::Triangulation::Edge_iterator it = kdel_->triangulation().edges_begin(); it != kdel_->triangulation().edges_end(); ++it){ if (!compute_ok(*it, ik_)) { std::cout << "Problem with edge " << it->first->vertex((it->second+1)%3)->point() << " " << it->first->vertex((it->second+2)%3)->point() << " " << cc(it->first->vertex((it->second+1)%3)->point()) << ": " << cc(it->first->vertex((it->second+2)%3)->point()) << std::endl; } } } static void read(std::string name, Points &points) { std::ifstream in(name.c_str()); if (!in) { std::cerr << "Error opening file " << name << std::endl; exit(1); } while (true) { char ln[10000]; in.getline(ln, 10000); if (!in) { break; } Static_point_2 p; std::istringstream iss(ln); iss >> p; if (!iss) { CGAL::Simple_cartesian::Point_2 dpt; std::istringstream iss2(ln); iss2 >> dpt; if (!iss2) { std::cerr << "Error processing line " << ln << std::endl; } else { points.push_back(Static_point_2(dpt.x(), dpt.y())); } } else { points.push_back(p); } }; } /*static bool is_hull_edge(const Edge &e) { return ! TDS_helper::mirror_vertex(e)->point().is_valid() || ! TDS_helper::third_vertex(e)->point().is_valid() || ! TDS_helper::origin(e)->point().is_valid() || ! TDS_helper::destination(e)->point().is_valid(); }*/ static bool compute_ok(const Edge &e, Indirect_kernel sk) { //typename Indirect_kernel::Current_coordinates //cc= sk.current_coordinates_object(); Point_key ks[4]; ks[0]= TDS_helper::origin(e)->point(); ks[1]= TDS_helper::third_vertex(e)->point(); ks[2]= TDS_helper::destination(e)->point(); ks[3]= TDS_helper::mirror_vertex(e)->point(); for (unsigned int i=0; i< 4; ++i){ if (ks[i]==Point_key()) { return true; } } typename Indirect_kernel::Side_of_oriented_circle_2 soc = sk.side_of_oriented_circle_2_object(); CGAL::Oriented_side s=soc(ks[0], ks[1], ks[2], ks[3]); if (s== CGAL::ON_ORIENTED_BOUNDARY) { CGAL_UD_DEBUG("Degeneracy with edge " << ks[0] << " " << ks[2] << std::endl); } return s!= CGAL::ON_NEGATIVE_SIDE; } static int run(int argc, char *argv[], int n, int d, int seed, std::string ifile, std::string ffile) { //typedef CGAL::Kinetic::Inexact_simulation_traits_2 Traits; CGAL_KINETIC_SET_LOG_LEVEL(CGAL::Kinetic::LOG_SOME); if (ifile.empty() || ffile.empty()) { std::cerr << "Need an initial and final coordinate files." << std::endl; } Points ipoints, fpoints; read(ifile, ipoints); read(ffile, fpoints); CGAL_assertion(ipoints.size() == fpoints.size()); Updatable_Delaunay_triangulation_2 udt2(ipoints.begin(), ipoints.end()); udt2.update_coordinates_demo(fpoints); udt2.update_coordinates_demo(ipoints); return 0; } Indirect_kernel ik_; Simulation_traits tr_; typename KDel::Handle kdel_; }; CGAL_END_NAMESPACE #endif #undef CGAL_UD_DEBUG