cgal/Kinetic_data_structures/include/CGAL/Updatable_Delaunay_triangul...

1431 lines
39 KiB
C++

#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 <CGAL/Kinetic/basic.h>
#include <CGAL/Kinetic/Interval_simulator_traits.h>
#include <CGAL/Kinetic/Simulation_traits.h>
#include <CGAL/Kinetic/Free_event_base.h>
#include <CGAL/Kinetic/Delaunay_triangulation_2.h>
#include <CGAL/Kinetic/Delaunay_triangulation_vertex_base_2.h>
#include <CGAL/Kinetic/Delaunay_triangulation_recent_edges_visitor_2.h>
#include <CGAL/Kinetic/Delaunay_triangulation_visitor_base_2.h>
#include <CGAL/Updatable_Delaunay_triangulation_table_2.h>
#include <CGAL/Indirect_point_2_kernel.h>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Kinetic/IO/Qt_moving_points_2.h>
#include <CGAL/Kinetic/IO/Qt_triangulation_2.h>
#include <CGAL/Kinetic/IO/Qt_widget_2.h>
#include <vector>
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 <class IndirectKernel>
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<Point_key> Cert_tuple;
typedef CGAL::Interval_nt_advanced INT;
typedef CGAL::Gmpq NT;
typedef CGAL::POLYNOMIAL::Polynomial<NT> Function;
typedef CGAL::POLYNOMIAL::Sturm_root_stack_traits<Function> Root_stack_traits;
typedef CGAL::POLYNOMIAL::Sturm_root_stack<Root_stack_traits> Root_stack;
typedef CGAL::POLYNOMIAL::Kernel<Function, Root_stack> Function_kernel;
typedef typename CGAL::Kinetic::Handle_degeneracy_function_kernel<Function_kernel, true> KK_function_kernel;
typedef typename CGAL::Kinetic::Cartesian_kinetic_kernel<KK_function_kernel> Kinetic_kernel;
typedef IndirectKernel Indirect_kernel;
typedef Updatable_delaunay_triangulation_table_2<Indirect_kernel, Kinetic_kernel> 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> {
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<double,double> &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<true> prot;
INT niv=ui_->Newton_refine(certf_, certpf_, INT(iv));
bool ret= (niv.inf() != iv.first || niv.sup() != iv.second);
iv= std::pair<double,double>(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<double,double> 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<double,double> iv) const {
if (!has_exact_root()) {
compute_exact_root(iv);
return true;
} else return false;
}
void compute_exact_root(std::pair<double,double> 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<double,double> 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<double,double> 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<NT> Static_kernel;
typedef typename Kinetic::Cartesian_instantaneous_kernel<Active_points_2_table, Static_kernel> Instantaneous_kernel;
Instantaneous_kernel instantaneous_kernel_object() const {
return Instantaneous_kernel(ap_, Static_kernel());
}
typedef typename Kinetic::Interval_simulator_traits<Refiner> Simulator_traits;
typedef typename Kinetic::Two_list_pointer_event_queue<Simulator_traits, false, 2> Queue;
typedef typename Kinetic::Default_simulator<Simulator_traits, Queue > 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<IndirectKernel,
CGAL::Triangulation_data_structure_2<
CGAL::Kinetic::Delaunay_triangulation_vertex_base_2<IndirectKernel>,
CGAL::Kinetic::Delaunay_triangulation_face_base_2<Simulation_traits> > > Triangulation;
typedef CGAL::Kinetic::internal::Triangulation_data_structure_helper_2<typename Triangulation::Triangulation_data_structure> TDS_helper;
typedef typename Triangulation::Edge Edge;
typedef typename Simulation_traits::Kinetic_kernel::Motion_function::NT ENT;
typedef Kinetic::Delaunay_triangulation_default_traits_2<Simulation_traits, Triangulation> Default_traits;
struct Traits: public Default_traits {
typedef Default_traits P;
typedef typename Simulation_traits::Simulator::Time Time;
struct Certificate_data{};
typedef std::pair<Time, Certificate_data> 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 &current_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<true> 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<true> 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<true> 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<true> 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<true> 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<Point_key> &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<Point_key> &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 <class TDS>
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<Point_key> 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<Point_key> 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<true> 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<Point_key> &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<Simulation_traits, Visitor, Triangulation, Traits> 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, 2> mf;
for (unsigned int i=0; i< 2; ++i){
Protected_array<NT,2> 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, 2> mf;
for (unsigned int i=0; i< 2; ++i){
Protected_array<NT,2> 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 <class It>
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<double>::max());
} else {
time_=0;
}
//}
std::sort(b,e);
It ne= std::unique(b,e);
ui_->set_next_activation(time_);
{
CGAL::Protect_FPU_rounding<true> 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<true> 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<Point_key> 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 <class It>
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<typename Simulation_traits::Simulator> Qt_gui;
typedef CGAL::Kinetic::Qt_moving_points_2<Simulation_traits, Qt_gui> Qt_mps;
typedef CGAL::Kinetic::Qt_triangulation_2<KDel, typename Simulation_traits::Instantaneous_kernel, Qt_gui> 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<double>::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