#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 #define NEWTON /* 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, typename Update_information::Certificate_function_const_pointer certf, typename Update_information::Certificate_derivitive_const_pointer certpf, typename Update_information::Handle tbl): tuple_(t), ui_(tbl), certf_(certf) , certpf_(certpf) { } 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; INT niv=ui_->Newton_refine(certf_, certpf_, INT(iv)); bool ret= (niv.inf() != iv.first || niv.sup() != iv.second); iv= std::pair(niv.inf(), niv.sup()); return ret; } else { // compute exact; CGAL_assertion(!has_exact_root()); //++comparison_certificates_; compute_exact_root(iv); iv= CGAL::to_interval(exact_root()); return true; } } const Exact_root& exact_root() const { return cert_->cert_.failure_time(); } /*const Exact_root& exact_root(std::pair iv) const { compute_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); } bool ensure_exact_root(std::pair iv) const { if (!has_exact_root()) { compute_exact_root(iv); return true; } else return false; } void compute_exact_root(std::pair iv) const { CGAL_precondition(!has_exact_root()); if (ui_ != typename Update_information::Handle()) { ++stat_exact_certificate_functions_; ++stat_exact_certificate_functions_from_compare_; 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_UD_DEBUG("Got " << cert_->cert_.failure_time() << std::endl); CGAL_assertion(check_.failure_time() == cert_->cert_.failure_time()); //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 advance_exact_root(const Exact_time &et) const { CGAL_precondition(has_exact_root()); ++stat_exact_certificate_functions_; while (CGAL::compare(exact_root(), et) == CGAL::SMALLER) { CGAL_UD_DEBUG("Advancing exact root " << cert_->cert_ << std::endl); cert_->cert_.pop_failure_time(); } } 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()); } typename Update_information::Certificate_function_const_pointer certificate_function() const { return certf_; } typename Update_information::Certificate_derivitive_const_pointer certificate_derivitive() const { return certpf_; } Cert_tuple tuple_; typename Update_information::Handle ui_; mutable typename CS::Handle cert_; typename Update_information::Certificate_function certf_; typename Update_information::Certificate_derivitive certpf_; #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_tuple tuple(Point_key ks[4]) const { return Cert_tuple(ks); } #ifndef NDEBUG 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); } #endif 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) { ++stat_certificate_computations_; Cert_tuple ct= tuple(pks); //bool check_if_point_is_activated; double end_time= 1; //i()->next_activation(); //ui()->set_next_activation(1.0); CGAL_UD_DEBUG("Current time is " << P::simulator_handle()->current_time() << std::endl); #ifndef MOVE_ALL bool found=false; for (unsigned int i=0; i< 4; ++i) { if (ui()->is_activating(ct[i])) { found=true; break; } } if (found) { CGAL_UD_DEBUG("Shortening end time to " << ui()->next_activation() << std::endl); end_time= ui()->next_activation(); } #endif #ifndef NDEBUG Exact_time check_failure_time; Exact_certificate check_cert; { Exact_time ect; if (current_time().refiner().is_invalid()) { ect= Exact_time(CGAL::to_interval(current_time()).first); } else { ect= current_time().refiner().check_.failure_time(); } check_cert= ui()->in_circle_object()(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; } //CGAL_UD_DEBUG("Computing failure time for " << ct << std::endl); CGAL_UD_DEBUG("True failure time is " << check_failure_time<< std::endl); //CGAL_UD_DEBUG("Exact cert is " << check_cert << std::endl); #endif double bt;// = ui()->start_time(); //if (bt <0) { bt= CGAL::to_interval(current_time()).first; //} #ifdef MOVE_ALL if (!ui()->can_fail(ct, bt)) { CGAL_postcondition(check_failure_time > 1); return false; } #else if (!ui()->can_fail(ct, bt, end_time)) { CGAL_postcondition(check_failure_time > 1); return false; } #endif typename Update_information::Certificate_function cf; typename Update_information::Certificate_derivitive cfp; INT ft; typename Update_information::Isolate_result isc; #ifndef NDEBUG #ifndef MOVE_ALL if (!(ui()->is_active(ct[0]) || ui()->is_active(ct[1]) || ui()->is_active(ct[2]) || ui()->is_active(ct[3]))) { isc= Update_information::NO_FAILURE; } else #endif #endif { CGAL::Protect_FPU_rounding prot; ++stat_interval_certificate_functions_; ui()->certificate_function(ct[0], ct[1], ct[2], ct[3], cf); cfp= cf.prime(); { bt= ui()->derivitive_filter(cf, cfp, bt, end_time); if (bt>= end_time) { CGAL_UD_DEBUG("No root with deriv." << std::endl); return false; } } //typename Update_information::Certificate_evaluator se(cf); typename Update_information::Certificate_acceleration cfpp= cfp.prime(); isc= ui()->Newton_isolate(cf, cfp, cfpp, bt, end_time, ft); CGAL_UD_DEBUG("Newton isolate got " << isc << " with interval " << ft << std::endl); if (isc == Update_information::CERTAIN_FAILURE) { ft= ui()->Newton_refine(cf,cfp, ft); CGAL_UD_DEBUG("After refinement got " << ft << std::endl); } else if (isc == Update_information::POSSIBLE_FAILURE) { if (!current_time().is_point()) current_time().refine(); //current_time().refine(); CGAL_UD_DEBUG("Refining current time to " << current_time() << std::endl); bt= CGAL::to_interval(current_time()).first; isc= ui()->Newton_isolate(cf, cfp, cfpp, bt, end_time, ft); CGAL_UD_DEBUG("Newton isolate got " << isc << " with interval " << ft << std::endl); if (isc == Update_information::CERTAIN_FAILURE) { ft= ui()->Newton_refine(cf,cfp, ft); CGAL_UD_DEBUG("After refinement got " << ft << std::endl); } } } if (isc == Update_information::NO_FAILURE) { CGAL_UD_DEBUG("No root" << std::endl << std::endl); CGAL_assertion(check_failure_time >=1); return false; } rett= Time(ft.inf(), ft.sup(), Refiner(ct, cf,cfp, 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 && CGAL::compare(rett, current_time()) == CGAL::LARGER) { #ifndef NDEBUG CGAL_UD_DEBUG("BEGIN NARROW" << std::endl); CGAL::Protect_FPU_rounding prot; double owid; INT nft= ui()->Newton_refine(cf,cfp, ft); do { owid= nft.sup()- nft.inf(); nft= ui()->Newton_refine(cf,cfp, nft); } while (owid > 1.01 * (nft.sup() -nft.inf())); stat_total_interval_width_+= owid; stat_number_of_intervals_+= 1; CGAL_UD_DEBUG("END NARROW" << std::endl); #endif CGAL_UD_DEBUG("Returning isolated " << rett << std::endl); CGAL_assertion(Exact_time(CGAL::to_interval(rett).first) <= check_failure_time); CGAL_assertion(Exact_time(CGAL::to_interval(rett).second) >= check_failure_time); return true; } else { CGAL_UD_DEBUG("Possible root " << std::endl); rett.refiner().compute_exact_root(CGAL::to_interval(ft)); CGAL_UD_DEBUG(std::cout << "Have to generate exact certificate" << std::endl); CGAL_UD_DEBUG("Exact root is" << rett.refiner().exact_root() << std::endl); CGAL_UD_DEBUG("Exact cert is " << rett.refiner().exact_certificate() << std::endl); if (rett.exact_root() <= 1) { const Exact_time &ect= current_time().exact_root(); rett.refiner().advance_exact_root(ect); if (rett.exact_root() <= 1) { rett.set_interval(CGAL::to_interval(rett.refiner().exact_root())); CGAL_postcondition(CGAL::compare(rett.exact_root(), check_failure_time) == 0); CGAL_UD_DEBUG("Returning exact " << rett << std::endl); return true; } else { CGAL_assertion(check_failure_time >=1); CGAL_UD_DEBUG("Very phantom root " << std::endl); CGAL_postcondition(check_failure_time > 1); ++stat_unfailing_exact_certificate_functions_; return false; } } else { CGAL_assertion(check_failure_time >=1); CGAL_UD_DEBUG("Phantom root " << std::endl); CGAL_postcondition(check_failure_time > 1); ++stat_unfailing_exact_certificate_functions_; return false; } #if 0 CGAL_UD_DEBUG("Initial points are " << std:: endl); typename Indirect_kernel::Current_coordinates ic= ui()->initial_coordinates_object(); typename Indirect_kernel::Current_coordinates fc= ui()->final_coordinates_object(); { CGAL::Protect_FPU_rounding prot; CGAL_UD_DEBUG(ic(ct[0]) << ": " << ic(ct[1]) << ": " << ic(ct[2]) << ": " << ic(ct[3]) << std::endl); CGAL_UD_DEBUG("Final points are " << std:: endl); CGAL_UD_DEBUG(fc(ct[0]) << ": " << fc(ct[1]) << ": " << fc(ct[2]) << ": " << fc(ct[3]) << std::endl); CGAL_UD_DEBUG("Initial incircle is " << ui()->eval_incircle(INT(ic(ct[0])[0]), INT(ic(ct[0])[1]), INT(ic(ct[1])[0]), INT(ic(ct[1])[1]), INT(ic(ct[2])[0]), INT(ic(ct[2])[1]), INT(ic(ct[3])[0]), INT(ic(ct[3])[1])) << std::endl); CGAL_UD_DEBUG("Final incircle is " << ui()->eval_incircle(INT(fc(ct[0])[0]), INT(fc(ct[0])[1]), INT(fc(ct[1])[0]), INT(fc(ct[1])[1]), INT(fc(ct[2])[0]), INT(fc(ct[2])[1]), INT(fc(ct[3])[0]), INT(fc(ct[3])[1])) << std::endl); } #endif } } bool certificate_failure_time( #ifndef NDEBUG typename Default_traits::Edge e, #else typename Default_traits::Edge, #endif Certificate_data , Time &rett, Certificate_data) { ++stat_certificate_advances_; const Time &curt= current_time(); Cert_tuple ct= curt.refiner().tuple().opposite(); CGAL_UD_DEBUG("Current time is " << current_time() << std::endl); #ifndef NDEBUG Cert_tuple check_ct= tuple(e); #endif CGAL_assertion(ct == check_ct); double end_time= 1; //ui()->next_activation(); #ifndef MOVE_ALL ui()->set_next_activation(1.0); #endif #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; //GAL_UD_DEBUG("Exact time is " << check_cert.failure_time() << std::endl); CGAL_UD_DEBUG("True failure time is " << check_cert.failure_time() << std::endl); } #endif // 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; CGAL_UD_DEBUG("Advancing certificate for " << ct << " to " << lb << std::endl); #ifndef MOVE_ALL bool found=false; for (unsigned int i=0; i< 4; ++i) { if (ui()->is_activating(ct[i])) { found=true; break; } } if (found) { CGAL_UD_DEBUG("Shortening end time to " << ui()->next_activation() << std::endl); end_time= ui()->next_activation(); if (end_time <= lb) { CGAL_UD_DEBUG("And the interval is empty " << std::endl); return false; } } #endif typename Update_information::Certificate_function cf(curt.refiner().certificate_function(), true); bool wrap_this_into_newton; // done twiceish CGAL::Protect_FPU_rounding prot; ++stat_point_predicate_evaluations_; //CGAL::Sign sn= curt.refiner().sign_at(INT(lb,lb)); { INT lbv= cf(lb); //ui()->sign_at(ct[0],ct[1],ct[2],ct[3], INT(lb, lb)); if (lbv.inf()<=0) { CGAL_UD_DEBUG("Not positive at " << lb << std::endl); lb= CGAL::to_interval(curt).first; } } { ++stat_interval_predicate_evaluations_; //CGAL::Sign sn= curt.refiner().sign_at(INT(lb,lb)); INT lbv= cf(INT(lb, end_time)); if (lbv.inf()>0) { CGAL_UD_DEBUG("No root in interval." << std::endl); CGAL_postcondition(check_failure_time > 1); return false; } } typename Update_information::Certificate_derivitive cfp(curt.refiner().certificate_derivitive(), true); { lb= ui()->derivitive_filter(cf, cfp, lb, end_time); if (lb>= end_time) { CGAL_UD_DEBUG("No root with deriv." << std::endl); return false; } } INT 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); typename Update_information::Certificate_acceleration cfpp(cfp.prime()); isc= ui()->Newton_isolate(cf, cfp, cfpp, lb, end_time, ft); if (isc == Update_information::CERTAIN_FAILURE) { ft= ui()->Newton_refine(cf, cfp, ft); } CGAL_UD_DEBUG("Newton isolate got " << isc << " with interval " << ft << std::endl); } 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.inf(), ft.sup(), Refiner(ct, cf, cfp, ui())); #ifndef NDEBUG rett.refiner().check_= check_cert; #endif if (isc == Update_information::CERTAIN_FAILURE && ft.inf() <= CGAL::to_interval(curt).second || isc == Update_information::POSSIBLE_FAILURE || curt.refiner().has_exact_root()) { curt.exact_root(); CGAL_UD_DEBUG("Have to generate exact certificate" << std::endl); Exact_certificate ec= curt.refiner().exact_certificate(); CGAL_UD_DEBUG("Curt is now " << curt << std::endl); CGAL_UD_DEBUG("Root was " << ec.failure_time() << std::endl); ec.pop_failure_time(); CGAL_UD_DEBUG("Root is " << ec.failure_time() << std::endl); CGAL_UD_DEBUG("Exact cert is " << ec << std::endl); ++stat_exact_certificate_functions_from_advance_; if (ec.failure_time() > 1) { CGAL_UD_DEBUG("Phantom root " << std::endl); CGAL_postcondition(check_failure_time > 1); return false; } ft= CGAL::to_interval(curt.refiner().exact_root()); rett.set_interval(CGAL::to_interval(ft)); rett.refiner().set_exact_certificate(ec); return true; } else { CGAL_assertion(Exact_time(CGAL::to_interval(rett).first) <= check_failure_time); CGAL_assertion(Exact_time(CGAL::to_interval(rett).second) >= check_failure_time); 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(); } #ifndef MOVE_ALL bool test_and_add(Edge e, std::vector &active) const { ++stat_point_predicate_evaluations_; if (!compute_ok(e, ui()->final_kernel_object())) { 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 { ++stat_point_predicate_evaluations_; if (!compute_ok(e, ui()->final_kernel_object())) { //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; } #endif template void initialize_events(const TDS &triangulation, Indirect_kernel fk) { stat_number_of_edges_=triangulation.tds().number_of_edges(); ui()->set_final_kernel(fk); #ifndef MOVE_ALL 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_number_of_bad_edges_; } } Interpolate_event ev(tr_, ui(), ui()->initial_coordinates_object(), ui()->final_coordinates_object(), active.begin(), active.end()); ++stat_number_of_interpolations_; if (!ev.empty()) { INT iat= CGAL::to_interval(ev.time()); tr_.simulator_handle()->new_event(ev.time(), ev); } #endif } 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())); Edge em= TDS_helper::mirror_edge(e); #ifndef MOVE_ALL add(e.first->vertex(0)->point(), active); add(e.first->vertex(1)->point(), active); add(e.first->vertex(2)->point(), active); //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()->initial_coordinates_object(), ui()->final_coordinates_object(), active.begin(), active.end()); if (!ev.empty()){ ++stat_number_of_interpolations_; 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); } } #endif /* 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)); 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); } */ } #ifndef MOVE_ALL 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); } } #endif 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_; }; typedef CGAL::Kinetic::Delaunay_triangulation_2 KDel; #ifndef MOVE_ALL 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; Protected_array mf; for (unsigned int i=0; i< 2; ++i){ Protected_array c; 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; Protected_array mf; for (unsigned int i=0; i< 2; ++i){ Protected_array c; c[1]=(fp[i]-ip[i]); c[0]=2*ip[i]-fp[i]; mf[i]=MF(c.begin(), c.end()); } return Kinetic_point_2(mf[0], mf[1]); } struct Interpolate_event: public CGAL::Kinetic::Free_event_base { 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) { if (CGAL::to_interval(tr.simulator_handle()->current_time()).second != 0) { time_= nextafter(CGAL::to_interval(tr.simulator_handle()->current_time()).second, std::numeric_limits::max()); } else { time_=0; } //} std::sort(b,e); It ne= std::unique(b,e); ui_->set_next_activation(time_); { CGAL::Protect_FPU_rounding prot; for (It c=b; c!= ne; ++c){ if (ic(*c) != fc(*c)) { motions_.push_back(*c); ui_->preactivate(*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() { ui_->set_next_activation(-1); 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) { ui_->activate(time_, motions_[i]); } ui_->set_is_editing(Update_information::NOT); } typename Update_information::Handle ui_; typename std::vector motions_; double time_; }; 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_; }; #endif 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_); kdel_= new KDel(traits, tr, Visitor(tr_)); kdel_->clear_stats(); kdel_->visitor().stats_clear(); kdel_->set_neighbors_initialized(true); #ifndef MOVE_ALL kdel_->set_has_certificates(true, true, true); #endif } 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); #ifndef MOVE_ALL tr_.simulator_handle()->new_final_event(Final_event(tr_, kdel_)); #endif 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(); kdel_->visitor().stats_write(std::cout); ik_.swap(fk); audit(); } Indirect_kernel set_up_update(const Points &pts) { kdel_->visitor().reset(); kdel_->set_has_certificates(false, true); tr_.simulator_handle()->set_interval(0,1); Indirect_kernel fk; fk.new_point_2s(pts.begin(), pts.end()); kdel_->visitor().initialize_events(kdel_->triangulation(), fk); #ifdef MOVE_ALL kdel_->set_has_certificates(true, false, true); #else kdel_->set_has_certificates(true, true, true); #endif 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 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 , char *[], int , int , int , 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