mirror of https://github.com/CGAL/cgal
1558 lines
44 KiB
C++
1558 lines
44 KiB
C++
#ifndef UPDATABLE_DELAUNAY_TRIANGULATION_2_H
|
|
#define UPDATABLE_DELAUNAY_TRIANGULATION_2_H
|
|
#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/Kinetic/Active_objects_update_vector.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>
|
|
#include <boost/dynamic_bitset.hpp>
|
|
|
|
#ifdef NDEBUG
|
|
#define CGAL_UD_DEBUG(x)
|
|
#else
|
|
#define CGAL_UD_DEBUG(x) std::cout << x
|
|
#endif
|
|
|
|
CGAL_BEGIN_NAMESPACE
|
|
|
|
template <class Point_key>
|
|
struct Update_cert_tuple {
|
|
Update_cert_tuple(){}
|
|
Update_cert_tuple(Point_key k[4]) {
|
|
std::copy(k, k+4, k_);
|
|
int swaps=0;
|
|
for (unsigned int i=0; i< 3; ++i){
|
|
for (unsigned int j=i+1; j< 4; ++j) {
|
|
if (k_[i] > k_[j]) {
|
|
std::swap(k_[i], k_[j]);
|
|
++swaps;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (swaps%2 ==1) {
|
|
std::swap(k_[2], k_[3]);
|
|
}
|
|
}
|
|
|
|
/*static std::pair<Cert_tuple, bool> make(Point_key k[4]) {
|
|
Cert_tuple r(k);
|
|
int swaps=0;
|
|
for (unsigned int i=0; i< 3; ++i){
|
|
for (unsigned int j=i+1; j< 4; ++j) {
|
|
if (r.k_[i] > r.k_[j]) {
|
|
std::swap(r.k_[i], r.k_[j]);
|
|
++swaps;
|
|
}
|
|
}
|
|
}
|
|
return std::make_pair(r, swaps%2==0);
|
|
}*/
|
|
|
|
Update_cert_tuple canonicalize() const {
|
|
Update_cert_tuple ret= *this;
|
|
if (ret.k_[2] > ret.k_[3]) {
|
|
std::swap(ret.k_[2], ret.k_[3]);
|
|
}
|
|
return ret;
|
|
}
|
|
Update_cert_tuple opposite() const {
|
|
Update_cert_tuple ret= *this;
|
|
std::swap(ret.k_[2], ret.k_[3]);
|
|
return ret;
|
|
}
|
|
|
|
bool operator<(const Update_cert_tuple o) const {
|
|
for (unsigned int i=0; i< 4; ++i){
|
|
if (k_[i] < o.k_[i]) return true;
|
|
else if (k_[i] > o.k_[i]) return false;
|
|
}
|
|
return false;
|
|
}
|
|
bool operator==(const Update_cert_tuple o) const {
|
|
for (unsigned int i=0; i< 4; ++i){
|
|
if (k_[i] != o.k_[i]) return false;
|
|
}
|
|
return true;
|
|
}
|
|
Point_key operator[](int i) const {
|
|
return k_[i];
|
|
}
|
|
void write(std::ostream&out) const {
|
|
out << k_[0] << " " << k_[1] << " " << k_[2] << " " << k_[3];
|
|
}
|
|
Point_key k_[4];
|
|
};
|
|
|
|
template <class K>
|
|
std::ostream &operator<<(std::ostream &out,
|
|
const Update_cert_tuple<K> &ct) {
|
|
out << ct[0] << " " << ct[1] << " " << ct[2] << " " << ct[3];
|
|
return out;
|
|
}
|
|
|
|
/*
|
|
Where to go next:
|
|
|
|
- compute interval bound on root and see if that is good enough (use
|
|
compare_concurrent if they overlap). Currently I make sure that
|
|
the event actually occurs as this is easier than trying to handle
|
|
events disappearing. There are some difficulties with new events
|
|
that occur close to the current event. I think if I keep a last
|
|
event around and use its inexact or exact rep to prune any new
|
|
events I look at then I am fine. How to get the rep of the current
|
|
time in the traits is a bit tricky.
|
|
|
|
- there should be a way of making sure I have a correct root since
|
|
if there are roots close together and nothing happened in between
|
|
I can take the last (mod 2). So can I mantain the set of
|
|
everything before and everything after? Or do I need a whole
|
|
graph? I know I can disambiguate everything that came before. So
|
|
for a tuple/interval pair either I never computed the exact root,
|
|
in which case I can take the last one with the right sign (can I
|
|
still determine the right sign?) or I computed it, in which case I
|
|
could store it.
|
|
|
|
- each tuple can only be in the queue once. If it is there and has
|
|
no exact current root then we can take the first root in the
|
|
interval to be the root. Otherwise, it has an exact root.
|
|
|
|
- for advancing, if I don't have an exact root, look for a disjoint
|
|
interval (since I know none of the later roots overlap). Otherwise
|
|
find the next root after the current exact root.
|
|
|
|
- cached Certificate means that
|
|
|
|
|
|
- maintain a list of certificates which are valid at the next event
|
|
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;
|
|
|
|
|
|
|
|
|
|
struct Simulation_traits {
|
|
typedef SimTraits_base P;
|
|
typedef typename Kinetic::Active_objects_update_vector<P::Kinetic_kernel::Point_2, Point_key> 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 typename Kinetic::Cartesian_instantaneous_kernel<Active_points_2_table, P::Static_kernel> Instantaneous_kernel;
|
|
Instantaneous_kernel instantaneous_kernel_object() const {
|
|
return Instantaneous_kernel(ap_, typename P::Static_kernel());
|
|
}
|
|
typedef typename Kinetic::Interval_simulator_traits<Cert_tuple> Simulator_traits;
|
|
typedef typename Kinetic::Two_list_pointer_event_queue<Simulator_traits, 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(const Time &lb,
|
|
const Time &ub): ap_(new Active_points_2_table()),
|
|
sim_(new Simulator(lb, ub)){}
|
|
|
|
typedef typename P::Function_kernel Function_kernel;
|
|
Function_kernel function_kernel_object() {
|
|
return Function_kernel();
|
|
}
|
|
|
|
typedef typename P::Kinetic_kernel Kinetic_kernel;
|
|
Kinetic_kernel kinetic_kernel_object() const {
|
|
return Kinetic_kernel();
|
|
}
|
|
|
|
typedef typename P::Static_kernel Static_kernel;
|
|
Static_kernel static_kernel_object() const {
|
|
return Static_kernel();
|
|
}
|
|
|
|
typedef typename P::NT NT;
|
|
|
|
protected:
|
|
typename Active_points_2_table::Handle ap_;
|
|
typename Simulator::Handle sim_;
|
|
};
|
|
|
|
|
|
|
|
|
|
typedef typename Simulation_traits::Simulator::Event_key Event_key;
|
|
|
|
|
|
|
|
|
|
|
|
// typedef typename Simulation_traits::Kinetic_kernel::Point_2 Kinetic_point_2;
|
|
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 IndirectKernel Indirect_kernel;
|
|
|
|
typedef typename Triangulation::Edge Edge;
|
|
|
|
typedef typename Indirect_kernel::Geometric_point_2 Static_point_2;
|
|
|
|
|
|
typedef typename Indirect_kernel::Swapable_container Points;
|
|
typedef typename Simulation_traits::Kinetic_kernel::Point_2 Kinetic_point_2;
|
|
typedef typename Simulation_traits::Kinetic_kernel::Motion_function Kinetic_coordinate;
|
|
|
|
typedef typename Indirect_kernel::Current_coordinates IK_current_coordinates;
|
|
|
|
typedef typename Simulation_traits::Simulator::NT NT;
|
|
typedef typename Simulation_traits::Kinetic_kernel::Motion_function::NT ENT;
|
|
typedef CGAL::Interval_nt_advanced INT;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct Update_information: public Kinetic::Ref_counted<Update_information> {
|
|
struct Coef_data {
|
|
Coef_data(INT x_0, INT x_1, INT y_0, INT y_1){
|
|
c_[0][0]=x_0;
|
|
c_[0][1]=x_1;
|
|
c_[1][0]=y_0;
|
|
c_[1][1]=y_1;
|
|
}
|
|
Coef_data(){}
|
|
const INT* operator[](int i) const {
|
|
return c_[i];
|
|
}
|
|
INT c_[2][2];
|
|
};
|
|
|
|
typedef boost::dynamic_bitset<> Active;
|
|
Update_information(Indirect_kernel ik,
|
|
typename Simulation_traits::Active_points_2_table::Handle aot):aot_(aot),
|
|
ik_(ik),
|
|
active_(ik_.number_of_point_2s(), false),
|
|
coef_cache_(ik_.number_of_point_2s()),
|
|
failure_time_(ik_.number_of_point_2s(), 1){
|
|
clear_stats();
|
|
}
|
|
|
|
void clear_stats() {
|
|
static_certificates_=0;
|
|
//unsigned int num_events_=0;
|
|
bad_edges_=0;
|
|
num_interpolations_=0;
|
|
constant_filtered_=0;
|
|
interval_filtered_=0;
|
|
interval2_filtered_=0;
|
|
interval3_filtered_=0;
|
|
kinetic_certificates_=0;
|
|
unfailing_kinetic_certificates_=0;
|
|
certificate_advances_=0;
|
|
uncertain_exact_computations_=0;
|
|
exact_current_time_certificates_=0;
|
|
comparison_certificates_=0;
|
|
}
|
|
|
|
|
|
INT interval(Point_key a, int i) const {
|
|
if (!is_active(a)) return CGAL::to_interval(initial(a)[i]);
|
|
INT ii= CGAL::to_interval(initial(a)[i]);
|
|
INT fi= CGAL::to_interval(final(a)[i]);
|
|
return INT(std::min(fi.inf(), ii.inf()),
|
|
std::max(fi.sup(), ii.sup()));
|
|
}
|
|
|
|
|
|
// need start time for each point
|
|
INT cur_interval(Point_key a, INT ct, int i) const {
|
|
if (is_active(a)) {
|
|
|
|
//INT c[2];
|
|
// (st-1)fi-ii+fi
|
|
// stfi -ii
|
|
|
|
//CGAL_precondition(ct.inf() >= 0);
|
|
//CGAL_precondition(ct.sup() <= 1);
|
|
|
|
return coef_cache_[a.to_index()][i][0] + ct*coef_cache_[a.to_index()][i][1];
|
|
} else {
|
|
return CGAL::to_interval(initial(a)[i]);
|
|
}
|
|
}
|
|
|
|
|
|
void write_stats(std::ostream &out) {
|
|
out << "The triangululation had " << bad_edges_ << " bad edges" << std::endl;
|
|
out << "Points were interpolated on " << num_interpolations_ << " occasions" << std::endl;
|
|
out << "There were " << static_certificates_
|
|
<< " static computations for "
|
|
<< num_edges_
|
|
<< " edges" << std::endl;
|
|
|
|
out << "Constant filtered removed " << constant_filtered_
|
|
<< " computations and interval removed "
|
|
<< interval_filtered_ << " computations"
|
|
<< " and the second round of interval filtering remove " << interval2_filtered_
|
|
<< " and the third " << interval3_filtered_
|
|
<< std::endl;
|
|
out << "There remained " << kinetic_certificates_ << " certificates that were "
|
|
<< "computed which were advanced " << certificate_advances_
|
|
<< " times and " << unfailing_kinetic_certificates_
|
|
<< " of which could have been filtered" << std::endl;
|
|
out << "Of these " << uncertain_exact_computations_ << " were caused "
|
|
<< " by inability to determine if the root was there and "
|
|
<< exact_current_time_certificates_
|
|
<< " were caused to make the current time exact "
|
|
<< " and " << comparison_certificates_
|
|
<< " were caused in order to compare." << std::endl;
|
|
}
|
|
|
|
|
|
bool is_active(Point_key k) const {
|
|
return active_[k.to_index()];
|
|
}
|
|
|
|
|
|
void activate(Point_key k, Kinetic_point_2 kp, INT t) {
|
|
CGAL_precondition(t.inf() == t.sup());
|
|
//CGAL_precondition(active_[k.to_index()]==false);
|
|
if (!active_[k.to_index()]) {
|
|
active_[k.to_index()]=true;
|
|
//start_time_[k.to_index()]= t.inf();
|
|
INT stm1=(t-1);
|
|
|
|
INT xii= CGAL::to_interval(initial(k)[0]);
|
|
INT xfi= CGAL::to_interval(final(k)[0]);
|
|
INT xc0= (t*xfi - xii)/stm1;
|
|
INT xc1=(xii-xfi)/stm1;
|
|
|
|
INT yii= CGAL::to_interval(initial(k)[1]);
|
|
INT yfi= CGAL::to_interval(final(k)[1]);
|
|
INT yc0= (t*yfi - yii)/stm1;
|
|
INT yc1=(yii-yfi)/stm1;
|
|
coef_cache_[k.to_index()]= Coef_data(xc0, xc1, yc0, yc1);
|
|
aot_->set(k, kp);
|
|
}
|
|
}
|
|
|
|
void set_is_editing(bool tf) {
|
|
aot_->set_is_editing(tf);
|
|
}
|
|
|
|
void set_final_kernel(Indirect_kernel &fk){
|
|
fk_=fk;
|
|
}
|
|
|
|
void active_clear() {
|
|
active_.reset();
|
|
}
|
|
|
|
Static_point_2 initial(Point_key pk) const {
|
|
return ik_.current_coordinates_object()(pk);
|
|
}
|
|
Static_point_2 final(Point_key pk) const {
|
|
return fk_.current_coordinates_object()(pk);
|
|
}
|
|
|
|
/*INT start_time(Point_key k) const {
|
|
return CGAL::to_interval(start_time_[k.to_index()]);
|
|
}*/
|
|
|
|
/*double failure_time(Point_key k) const {
|
|
return start_time_[k.to_index()];
|
|
}*/
|
|
|
|
|
|
template <class CNT>
|
|
CNT incircle(CNT ax, CNT ay, CNT bx, CNT by,
|
|
CNT cx, CNT cy, CNT dx, CNT dy,
|
|
bool stat=false) {
|
|
if (stat) ++static_certificates_;
|
|
CNT qpx = bx - ax;
|
|
CNT qpy = by - ay;
|
|
CNT rpx = cx - ax;
|
|
CNT rpy = cy - ay;
|
|
CNT tpx = dx - ax;
|
|
CNT tpy = dy - ay;
|
|
CNT det=CGAL::det2x2_by_formula(qpx*tpy - qpy*tpx, tpx*(dx - bx) + tpy*(dy - by),
|
|
qpx*rpy - qpy*rpx, rpx*(cx - bx) + rpy*(cy - by));
|
|
return det;
|
|
}
|
|
|
|
typename Simulation_traits::Active_points_2_table::Handle aot_;
|
|
Indirect_kernel ik_, fk_;
|
|
Active active_;
|
|
std::vector<Coef_data > coef_cache_;
|
|
std::vector<double> failure_time_;
|
|
|
|
mutable unsigned int kinetic_certificates_;
|
|
mutable unsigned int unfailing_kinetic_certificates_;
|
|
mutable unsigned int certificate_advances_;
|
|
mutable unsigned int static_certificates_;
|
|
//unsigned int num_events_=0;
|
|
mutable unsigned int bad_edges_;
|
|
mutable unsigned int num_edges_;
|
|
mutable unsigned int num_interpolations_;
|
|
mutable unsigned int constant_filtered_;
|
|
mutable unsigned int interval_filtered_;
|
|
mutable unsigned int interval2_filtered_;
|
|
mutable unsigned int interval3_filtered_;
|
|
mutable unsigned int uncertain_exact_computations_;
|
|
mutable unsigned int exact_current_time_certificates_;
|
|
mutable unsigned int comparison_certificates_;
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 typename Simulation_traits::Kinetic_kernel::Positive_side_of_oriented_circle_2::result_type Exact_certificate;
|
|
typedef typename Simulation_traits::Function_kernel::Root Exact_time;
|
|
|
|
struct Cache_data {
|
|
Cache_data(){}
|
|
Cache_data(Exact_certificate cert): cert_(cert){}
|
|
|
|
const Exact_time& failure_time() const {
|
|
return cert_.failure_time();
|
|
}
|
|
|
|
void pop_failure_time() {
|
|
//()) {
|
|
cert_.pop_failure_time();
|
|
//}
|
|
}
|
|
|
|
Exact_certificate cert_;
|
|
};
|
|
|
|
typedef std::map<Cert_tuple,Cache_data> Cache;
|
|
|
|
|
|
Traits(Simulation_traits tr,
|
|
typename Update_information::Handle ui): P(tr), ui_(ui),
|
|
soc_(tr.kinetic_kernel_object().positive_side_of_oriented_circle_2_object()){}
|
|
|
|
typedef std::pair<Time, Certificate_data> Certificate_pair;
|
|
|
|
Certificate_pair null_pair() const {
|
|
return std::make_pair(Time(2), Certificate_data());
|
|
}
|
|
|
|
Cert_tuple tuple(typename P::Edge e) const {
|
|
typename P::Point_key ks[4];
|
|
P::edge_points(e, ks);
|
|
return Cert_tuple(ks);
|
|
}
|
|
|
|
|
|
bool has_exact_failure_time(Cert_tuple ct) const {
|
|
return cache_.find(ct) != cache_.end();
|
|
}
|
|
|
|
Certificate_pair return_pair(Time rt) const {
|
|
return Certificate_pair(rt, Certificate_data());
|
|
}
|
|
|
|
void point_changed(Point_key k){
|
|
std::vector<typename Cache::iterator> tk;
|
|
for (typename Cache::iterator it = cache_.begin(); it != cache_.end(); ++it) {
|
|
for (unsigned int i=0; i< 4; ++i){
|
|
if (it->first[i]==k) {
|
|
tk.push_back(it);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
for (unsigned int i=0; i< tk.size(); ++i) {
|
|
CGAL_UD_DEBUG("Erasing " << tk[i]->first << std::endl);
|
|
cache_.erase(tk[i]);
|
|
}
|
|
}
|
|
|
|
const Time ¤t_time() const {
|
|
return P::simulator_handle()->current_time();
|
|
}
|
|
|
|
Certificate_pair certificate_failure_time(typename P::Edge e) {
|
|
if (is_hull_edge(e)) return null_pair();
|
|
|
|
Cert_tuple ct= tuple(e);
|
|
#ifndef NDEBUG
|
|
Exact_time actual_failure_time;
|
|
{
|
|
Cert_tuple cct= tuple(e);
|
|
if (check_.find(cct) != check_.end()) {
|
|
check_.erase(cct);
|
|
}
|
|
if (check_.find(cct.opposite()) != check_.end()) {
|
|
check_.erase(cct.opposite());
|
|
}
|
|
Exact_time ect;
|
|
if (current_time().data() == Cert_tuple()) {
|
|
ect= Exact_time(CGAL::to_interval(current_time()).first);
|
|
} else {
|
|
CGAL_assertion(check_.find(current_time().data()) != check_.end());
|
|
ect= check_[current_time().data()].failure_time();
|
|
}
|
|
Exact_certificate ecert=compute_exact_certificate(cct, ect);
|
|
actual_failure_time= ecert.failure_time();
|
|
check_[cct]= ecert;
|
|
|
|
}
|
|
#endif
|
|
|
|
//std::pair<Cert_tuple, bool> ctp= Cert_tuple::make(ks);
|
|
|
|
if (!can_fail(ct)) {
|
|
CGAL_postcondition(actual_failure_time > 1);
|
|
return null_pair();
|
|
}
|
|
|
|
CGAL_UD_DEBUG("Computing failure time for " << ct << std::endl);
|
|
CGAL_UD_DEBUG("Exact failure time is " << actual_failure_time<< std::endl);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Time ft;
|
|
bool isc= isolate_failure(ct,
|
|
CGAL::to_interval(current_time()).first,
|
|
ft);
|
|
if (ft== Time()) {
|
|
CGAL_UD_DEBUG("Not isolated" << std::endl);
|
|
CGAL_postcondition(actual_failure_time > 1);
|
|
return null_pair();
|
|
}
|
|
if (isc) {
|
|
if (CGAL::compare(ft, current_time()) == CGAL::EQUAL) {
|
|
// interval overlaps current
|
|
Exact_time ect= exact_current_time();
|
|
|
|
if (Exact_time(CGAL::to_interval(ft).first) <= ect) {
|
|
compute_exact_failure_time(ct, ect);
|
|
CGAL_UD_DEBUG("Exact" << exact_failure_time(ct) << std::endl);
|
|
ft= interval_from_exact_failure_time(ct);
|
|
}
|
|
}
|
|
CGAL_UD_DEBUG("Returning isolated " << ft << std::endl);
|
|
CGAL_postcondition(actual_failure_time >= CGAL::to_interval(ft).first);
|
|
CGAL_postcondition(actual_failure_time <= CGAL::to_interval(ft).second);
|
|
return return_pair(ft);
|
|
} else {
|
|
//if (!has_exact_failure_time(ct)) {
|
|
++ui_->uncertain_exact_computations_;
|
|
// }
|
|
Exact_time ect= exact_current_time();
|
|
compute_exact_failure_time(ct, ect);
|
|
ft= interval_from_exact_failure_time(ct);
|
|
CGAL_UD_DEBUG("Not isolated " << exact_failure_time(ct) << std::endl);
|
|
if (ft == Time()) {
|
|
CGAL_UD_DEBUG("Phantom root " << ft << std::endl);
|
|
CGAL_postcondition(actual_failure_time > 1);
|
|
return null_pair();
|
|
} else {
|
|
CGAL_UD_DEBUG("Returning exact " << ft << "("
|
|
<< exact_failure_time(ct) << ")" << std::endl);
|
|
CGAL_postcondition(actual_failure_time >= CGAL::to_interval(ft).first);
|
|
CGAL_postcondition(actual_failure_time <= CGAL::to_interval(ft).second);
|
|
return return_pair(ft);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
Certificate_pair certificate_failure_time(typename P::Edge e,
|
|
Certificate_data ) {
|
|
Cert_tuple ct= tuple(e);
|
|
|
|
#ifndef NDEBUG
|
|
Exact_time actual_failure_time;
|
|
{
|
|
CGAL_precondition(check_.find(ct.opposite()) != check_.end());
|
|
Exact_certificate ec= check_[ct.opposite()];
|
|
check_.erase(ct.opposite());
|
|
ec.pop_failure_time();
|
|
check_[ct]= ec;
|
|
actual_failure_time= ec.failure_time();
|
|
CGAL_UD_DEBUG("Exact time is " << ec.failure_time() << std::endl);
|
|
}
|
|
#endif
|
|
//std::pair<Cert_tuple, bool> ctp= Cert_tuple::make(ks);
|
|
|
|
if (!can_fail(ct)) {
|
|
CGAL_assertion(0);
|
|
//std::cout << "Can't fail." << std::endl;
|
|
CGAL_postcondition(actual_failure_time > 1);
|
|
return null_pair();
|
|
}
|
|
|
|
CGAL_UD_DEBUG("Advancing failure time for " << ct << std::endl);
|
|
CGAL_UD_DEBUG("Exact time is " << actual_failure_time << std::endl);
|
|
|
|
Time ft;
|
|
// this depends on being the last event of the batch whose time is computed
|
|
Time net= P::simulator_handle()->next_event_time();
|
|
|
|
bool isc= isolate_failure(ct, CGAL::to_interval(net).first, ft);
|
|
|
|
if (ft == Time()) {
|
|
CGAL_UD_DEBUG("Can't isolate." << std::endl);
|
|
CGAL_postcondition(actual_failure_time > 1);
|
|
return null_pair();
|
|
}
|
|
if (isc) {
|
|
if (CGAL::compare(ft, current_time()) == CGAL::EQUAL) {
|
|
//ensure_exact_failure_time(ct, current_time());
|
|
// this works because if there is no exact failure, we can take the first in the interval
|
|
ensure_exact_failure_time(ct, current_time());
|
|
advance_exact_failure_time(ct);
|
|
if (exact_failure_time(ct) > 1) {
|
|
++ui_->unfailing_kinetic_certificates_;
|
|
}
|
|
ft= interval_from_exact_failure_time(ct);
|
|
CGAL_UD_DEBUG("Separated from current " << exact_failure_time(ct)
|
|
<< std::endl);
|
|
}
|
|
CGAL_UD_DEBUG("Returning isolated " << ft << std::endl);
|
|
CGAL_postcondition(actual_failure_time >= CGAL::to_interval(ft).first);
|
|
CGAL_postcondition(actual_failure_time <= CGAL::to_interval(ft).second);
|
|
return return_pair(ft);
|
|
} else {
|
|
//ensure_exact_failure_time(ct, current_time());
|
|
//if (!has_exact_failure_time(ct)) {
|
|
++ui_->uncertain_exact_computations_;
|
|
//}
|
|
ensure_exact_failure_time(ct, current_time());
|
|
advance_exact_failure_time(ct);
|
|
if (cache_[ct].failure_time() > 1) {
|
|
++ui_->unfailing_kinetic_certificates_;
|
|
}
|
|
ft= interval_from_exact_failure_time(ct);
|
|
|
|
if (ft == Time()) {
|
|
CGAL_UD_DEBUG("Phantom root " << ft << std::endl);
|
|
CGAL_postcondition(actual_failure_time > 1);
|
|
return null_pair();
|
|
} else {
|
|
CGAL_UD_DEBUG("Returning exact " << ft << "("
|
|
<< exact_failure_time(ct) << ")" << std::endl);
|
|
CGAL_postcondition(actual_failure_time >= CGAL::to_interval(ft).first);
|
|
CGAL_postcondition(actual_failure_time <= CGAL::to_interval(ft).second);
|
|
return return_pair(ft);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ensure_exact_failure_time(Cert_tuple ct, Time rt) const {
|
|
compute_exact_failure_time(ct, Exact_time(CGAL::to_interval(rt).first));
|
|
}
|
|
|
|
void advance_exact_failure_time(Cert_tuple ct) const {
|
|
CGAL_precondition(cache_.find(ct) != cache_.end());
|
|
++ui_->certificate_advances_;
|
|
cache_[ct].pop_failure_time();
|
|
}
|
|
Time interval_from_exact_failure_time(Cert_tuple ct) const {
|
|
CGAL_precondition(cache_.find(ct) != cache_.end());
|
|
if (cache_[ct].failure_time() >= Exact_time(1)) {
|
|
return Time();
|
|
} else {
|
|
std::pair<double,double> ip= CGAL::to_interval(cache_[ct].failure_time());
|
|
return Time(ip.first, ip.second, ct);
|
|
}
|
|
}
|
|
|
|
void compute_exact_failure_time(Cert_tuple ct, Exact_time et) const {
|
|
CGAL_UD_DEBUG("Computing exact time for " << ct
|
|
<< " from " << et << "(" << cache_.size() << ")" << std::endl);
|
|
if (cache_.find(ct.opposite()) != cache_.end()) {
|
|
Cache_data cd = cache_[ct.opposite()];
|
|
cache_.erase(ct.opposite());
|
|
++ui_->certificate_advances_;
|
|
cd.pop_failure_time();
|
|
cache_[ct]= cd;
|
|
CGAL_postcondition(cache_.find(ct) != cache_.end());
|
|
}
|
|
if (cache_.find(ct) == cache_.end()) {
|
|
++ui_->kinetic_certificates_;
|
|
cache_.insert(typename Cache::value_type(ct,Cache_data(compute_exact_certificate(ct, et))));
|
|
CGAL_postcondition(cache_.find(ct) != cache_.end());
|
|
}
|
|
CGAL_postcondition(cache_.find(ct) != cache_.end());
|
|
while (cache_[ct].failure_time() < et) {
|
|
cache_[ct].pop_failure_time();
|
|
cache_[ct].pop_failure_time();
|
|
++ui_->certificate_advances_;
|
|
++ui_->certificate_advances_;
|
|
CGAL_postcondition(cache_.find(ct) != cache_.end());
|
|
}
|
|
CGAL_UD_DEBUG("Got " << cache_[ct].failure_time() << std::endl);
|
|
CGAL_UD_DEBUG("Check is " << check_.find(ct)->second.failure_time() << std::endl);
|
|
CGAL_postcondition(cache_[ct].failure_time() == check_.find(ct)->second.failure_time());
|
|
CGAL_postcondition(cache_.find(ct) != cache_.end());
|
|
if (exact_failure_time(ct) > 1) {
|
|
++ui_->unfailing_kinetic_certificates_;
|
|
}
|
|
}
|
|
|
|
const Exact_time& exact_current_time() const {
|
|
static Exact_time tmp;
|
|
//ensure_exact_failure_time(current_time().data(), current_time());
|
|
//Cert_tuple cct= ct.canonicalize();
|
|
CGAL_UD_DEBUG("Approximate is " << current_time() << std::endl);
|
|
if (current_time().data() == Cert_tuple()) {
|
|
tmp= Exact_time(CGAL::to_interval(current_time()).first);
|
|
return tmp;
|
|
} else {
|
|
if (!has_exact_failure_time(current_time().data())) {
|
|
++ui_->exact_current_time_certificates_;
|
|
}
|
|
ensure_exact_failure_time(current_time().data(),
|
|
current_time());
|
|
CGAL_UD_DEBUG("Exact current time is "
|
|
<< cache_[current_time().data()].failure_time() << std::endl);
|
|
|
|
return cache_[current_time().data()].failure_time();
|
|
}
|
|
}
|
|
|
|
const Exact_time& exact_failure_time(Cert_tuple ct) const {
|
|
CGAL_precondition(cache_.find(ct) != cache_.end());
|
|
return cache_.find(ct)->second.failure_time();
|
|
}
|
|
|
|
|
|
Exact_certificate compute_exact_certificate(Cert_tuple ct, Exact_time b) const {
|
|
Exact_certificate s= P::soc_(P::point(ct[0]),
|
|
P::point(ct[1]),
|
|
P::point(ct[2]),
|
|
P::point(ct[3]),
|
|
b, 1);
|
|
return s;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
INT join(INT a, INT b) const {
|
|
return INT(std::min(a.inf(), b.inf()),
|
|
std::max(a.sup(), b.sup()));
|
|
}
|
|
|
|
|
|
Exact_time check_failure_time(Cert_tuple t) const {
|
|
CGAL_precondition(check_.find(t) != check_.end());
|
|
return check_.find(t)->second.failure_time();
|
|
}
|
|
|
|
void refine_from_exact(Event_key e, Cert_tuple t) const {
|
|
P::simulator_handle()->event_time(e).refine(CGAL::to_interval(interval_from_exact_failure_time(t)));
|
|
}
|
|
|
|
|
|
CGAL::Comparison_result compare_concurrent(Event_key a,
|
|
Edge ea,
|
|
Event_key b,
|
|
Edge eb) const {
|
|
CGAL_UD_DEBUG("Perturbing " << a << " and " << b << std::endl);
|
|
|
|
Time ta= P::simulator_handle()->event_time(a);
|
|
Time tb= P::simulator_handle()->event_time(b);
|
|
Cert_tuple tua= ta.data();
|
|
Cert_tuple tub= tb.data();
|
|
CGAL_UD_DEBUG(tua << ": " << ta << " and " << tub << ": " << tb << std::endl);
|
|
|
|
double asz= CGAL::to_interval(ta).second - CGAL::to_interval(ta).first;
|
|
double bsz= CGAL::to_interval(tb).second - CGAL::to_interval(tb).first;
|
|
Exact_time eta;
|
|
Exact_time etb;
|
|
if (asz > bsz) {
|
|
if (!has_exact_failure_time(tua)) {
|
|
++ui_->comparison_certificates_;
|
|
}
|
|
ensure_exact_failure_time(tua, CGAL::to_interval(ta).first);
|
|
eta= exact_failure_time(tua);
|
|
refine_from_exact(a, tua);
|
|
|
|
if (eta > CGAL::to_interval(tb).second) {
|
|
CGAL_postcondition(check_failure_time(tua) > check_failure_time(tub));
|
|
return CGAL::LARGER;
|
|
} else if (eta < CGAL::to_interval(tb).first) {
|
|
CGAL_postcondition(check_failure_time(tua) < check_failure_time(tub));
|
|
return CGAL::SMALLER;
|
|
}
|
|
if (!has_exact_failure_time(tub)) {
|
|
++ui_->comparison_certificates_;
|
|
}
|
|
ensure_exact_failure_time(tub, CGAL::to_interval(tb).first);
|
|
etb= exact_failure_time(tub);
|
|
refine_from_exact(b, tub);
|
|
} else {
|
|
if (!has_exact_failure_time(tub)) {
|
|
++ui_->comparison_certificates_;
|
|
}
|
|
ensure_exact_failure_time(tub, CGAL::to_interval(tb).first);
|
|
etb= exact_failure_time(tub);
|
|
refine_from_exact(b, tub);
|
|
|
|
if (etb > CGAL::to_interval(ta).second) {
|
|
CGAL_postcondition(check_failure_time(tua) < check_failure_time(tub));
|
|
return CGAL::SMALLER;
|
|
} else if (etb < CGAL::to_interval(ta).first) {
|
|
CGAL_postcondition(check_failure_time(tua) > check_failure_time(tub));
|
|
return CGAL::LARGER;
|
|
}
|
|
if (!has_exact_failure_time(tua)) {
|
|
++ui_->comparison_certificates_;
|
|
}
|
|
ensure_exact_failure_time(tua, CGAL::to_interval(ta).first);
|
|
eta= exact_failure_time(tua);
|
|
refine_from_exact(a, tua);
|
|
}
|
|
|
|
CGAL_UD_DEBUG("Exact are " << eta << " and " << etb << std::endl);
|
|
CGAL_postcondition(eta == check_.find(tua)->second.failure_time());
|
|
CGAL_postcondition(etb == check_.find(tub)->second.failure_time());
|
|
return CGAL::compare(eta, etb);
|
|
}
|
|
|
|
CGAL::Sign sign_at(Point_key a, Point_key b,
|
|
Point_key c, Point_key d,
|
|
INT ct) const {
|
|
INT det= ui_->incircle(ui_->cur_interval(a,ct,0),
|
|
ui_->cur_interval(a,ct,1),
|
|
ui_->cur_interval(b,ct,0),
|
|
ui_->cur_interval(b,ct,1),
|
|
ui_->cur_interval(c,ct,0),
|
|
ui_->cur_interval(c,ct,1),
|
|
ui_->cur_interval(d,ct,0),
|
|
ui_->cur_interval(d,ct,1),
|
|
true);
|
|
|
|
if (det.sup() < 0) return CGAL::NEGATIVE;
|
|
else if (det.inf() > 0) return CGAL::POSITIVE;
|
|
else return CGAL::ZERO;
|
|
}
|
|
|
|
|
|
bool can_fail(Cert_tuple ct) const {
|
|
if (!ui_->is_active(ct[0]) && !ui_->is_active(ct[1])
|
|
&& !ui_->is_active(ct[2]) && !ui_->is_active(ct[3])) {
|
|
++ui_->constant_filtered_;
|
|
return false;
|
|
}
|
|
CGAL::Protect_FPU_rounding<true> prot;
|
|
|
|
|
|
INT curt= to_interval(P::simulator_handle()->current_time());
|
|
INT rct(curt.inf(), 1);
|
|
bool ret= (sign_at(ct[0],ct[1],ct[2],ct[3], rct) != CGAL::POSITIVE);
|
|
|
|
if (!ret) {
|
|
++ui_->interval2_filtered_;
|
|
return false;
|
|
} else {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
bool isolate_failure(const Cert_tuple& ct, double lb, double ub, int depth,
|
|
Time &ret) const {
|
|
int NS=20;
|
|
double ld= lb;
|
|
double step= (ub-ld)/NS;
|
|
INT failures;
|
|
bool has_zero=false;
|
|
bool has_negative=false;
|
|
bool certain=false;
|
|
for (int i=0; i< NS; ++i) {
|
|
double nld= std::min(ld+step, 1.0);
|
|
{
|
|
INT ci(ld, nld);
|
|
ld= nld;
|
|
CGAL::Sign sn= sign_at(ct[0],ct[1],ct[2],ct[3], ci);
|
|
if (sn == CGAL::NEGATIVE) {
|
|
CGAL_assertion(has_zero);
|
|
certain=true;
|
|
break;
|
|
} else if (sn == CGAL::ZERO) {
|
|
if (has_zero){
|
|
failures = join(failures, ci);
|
|
} else {
|
|
failures=ci;
|
|
has_zero=true;
|
|
}
|
|
} else if (sn == CGAL::POSITIVE) {
|
|
if (has_negative) break;
|
|
}
|
|
}
|
|
{
|
|
INT ci(nld, nld);
|
|
CGAL::Sign sn= sign_at(ct[0],ct[1],ct[2],ct[3], ci);
|
|
if (sn == CGAL::NEGATIVE) {
|
|
CGAL_assertion(has_zero);
|
|
certain=true;
|
|
break;
|
|
} else if (sn == CGAL::POSITIVE) {
|
|
if (has_negative) break;
|
|
}
|
|
}
|
|
|
|
}
|
|
if (has_negative || has_zero) {
|
|
if (depth == 2 || .7*(ub-lb) < (failures.sup() - failures.inf())) {
|
|
ret= Time(failures.inf(), failures.sup(), ct);
|
|
return certain;
|
|
} else {
|
|
return isolate_failure(ct, failures.inf(), failures.sup(), depth+1, ret);
|
|
}
|
|
} else {
|
|
++ui_->interval3_filtered_;
|
|
ret= Time();
|
|
return certain;
|
|
}
|
|
|
|
}
|
|
|
|
bool isolate_failure(Cert_tuple ct, double lb, Time &ret) const {
|
|
CGAL::Protect_FPU_rounding<true> prot;
|
|
return isolate_failure(ct, lb, 1.0, 0, ret);
|
|
}
|
|
|
|
|
|
typename Update_information::Handle ui_;
|
|
mutable std::map<Cert_tuple,Cache_data> cache_;
|
|
typename Simulation_traits::Kinetic_kernel::Positive_side_of_oriented_circle_2 soc_;
|
|
std::map<Cert_tuple, Exact_certificate> check_;
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct Visitor: public CGAL::Kinetic::Delaunay_triangulation_visitor_base_2 {
|
|
|
|
|
|
Visitor(Simulation_traits tr,
|
|
typename Update_information::Handle ui): tr_(tr), ui_(ui) {
|
|
}
|
|
|
|
|
|
|
|
bool test_and_add(Edge e, std::vector<Point_key> &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 <class TDS>
|
|
void initialize_events(const TDS &triangulation,
|
|
Indirect_kernel fk) {
|
|
ui_->num_edges_=triangulation.number_of_edges();
|
|
ui_->set_final_kernel(fk);
|
|
std::vector<Point_key> active;
|
|
for (typename TDS::Edge_iterator it= triangulation.edges_begin();
|
|
it != triangulation.edges_end(); ++it){
|
|
if (test_and_add(*it, active)) {
|
|
++ui_->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<Point_key> active;
|
|
test_and_add(e, active);
|
|
|
|
Edge em= TDS_helper::mirror_edge(e);
|
|
test_and_add(Edge(e.first, (e.second+1)%3), active);
|
|
test_and_add(Edge(e.first, (e.second+2)%3), active);
|
|
test_and_add(Edge(em.first, (em.second+1)%3), active);
|
|
test_and_add(Edge(em.first, (em.second+2)%3), active);
|
|
|
|
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());
|
|
++ui_->num_interpolations_;
|
|
/*for (unsigned int i=0; i< active.size(); ++i){
|
|
ui_->activate(active[i], true);
|
|
}*/
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
|
|
void active_clear() {
|
|
ui_->active_clear();
|
|
}
|
|
|
|
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_;
|
|
typename Update_information::Handle ui_;
|
|
|
|
};
|
|
|
|
|
|
|
|
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]))/(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<Table_key, Kinetic_point_2> MP;
|
|
|
|
|
|
|
|
|
|
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) {
|
|
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(MP(*c, interpolate_t1(time_, ic(*c), fc(*c))));
|
|
}
|
|
}
|
|
}
|
|
|
|
typename Simulation_traits::Simulator::Time time() const {
|
|
return time_;
|
|
}
|
|
|
|
std::ostream & write(std::ostream&out) const {
|
|
out << "Updating ";
|
|
for (unsigned int i=0; i< motions_.size(); ++i){
|
|
out << motions_[i].first << " ";
|
|
}
|
|
return out;
|
|
}
|
|
|
|
bool empty() const {
|
|
return motions_.empty();
|
|
}
|
|
|
|
void process() {
|
|
INT it= CGAL::to_interval(time_);
|
|
ui_->set_is_editing(true);
|
|
CGAL::Protect_FPU_rounding<true> 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(motions_[i].first, motions_[i].second, it);
|
|
}
|
|
ui_->set_is_editing(false);
|
|
}
|
|
typename Update_information::Handle ui_;
|
|
typename std::vector<MP> motions_;
|
|
typename Simulation_traits::Simulator::NT time_;
|
|
};
|
|
|
|
typedef CGAL::Kinetic::Delaunay_triangulation_2<Simulation_traits, Visitor, Triangulation, Traits> 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,
|
|
IK_current_coordinates ic,
|
|
IK_current_coordinates fc):
|
|
tr_(tr), kdel_(kdel),
|
|
ic_(ic), fc_(fc){
|
|
}
|
|
|
|
|
|
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(true);
|
|
|
|
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 {
|
|
/*std::cout << "Stopping point " << *it
|
|
<< " at " << fpoints_[it->to_index()]
|
|
<< " ( " << tr_.active_points_2_table_handle()->at(*it).x()(1)
|
|
<< tr_.active_points_2_table_handle()->at(*it).y()(1)
|
|
<< ")";*/
|
|
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(false);
|
|
}
|
|
|
|
Static_point_2 initial(Point_key pk) const {
|
|
return ic_(pk);
|
|
}
|
|
Static_point_2 final(Point_key pk) const {
|
|
return fc_(pk);
|
|
}
|
|
|
|
Simulation_traits tr_;
|
|
typename KDel::Handle kdel_;
|
|
IK_current_coordinates ic_, fc_;
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template <class It>
|
|
Updatable_Delaunay_triangulation_2(It b, It e): tr_(0,0) {
|
|
|
|
typename Indirect_kernel::Key_range rg= ik_.new_point_2s(b,e);
|
|
Triangulation tr(ik_);
|
|
|
|
tr.insert(rg.first, rg.second);
|
|
typename Update_information::Handle ui= new Update_information(ik_, tr_.active_points_2_table_handle());
|
|
|
|
Traits traits(tr_, ui);
|
|
|
|
traits.active_points_2_table_handle()->set_is_editing(true);
|
|
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(false);
|
|
|
|
|
|
|
|
kdel_= new KDel(traits, tr, Visitor(tr_, ui));
|
|
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<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);
|
|
|
|
tr_.simulator_handle()->new_final_event(Final_event(tr_,
|
|
kdel_,
|
|
ik_.current_coordinates_object(),
|
|
fk.current_coordinates_object()));
|
|
|
|
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().active_clear();
|
|
tr_.simulator_handle()->set_interval(0,1);
|
|
tr_.active_points_2_table_handle()->set_is_editing(true);
|
|
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(false);
|
|
|
|
|
|
Indirect_kernel fk;
|
|
fk.new_point_2s(pts.begin(), pts.end());
|
|
|
|
kdel_->visitor().initialize_events(kdel_->triangulation_data_structure(), 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(std::cout);
|
|
kdel_->visitor().stats_write(std::cout);
|
|
}
|
|
|
|
|
|
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 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();
|
|
if (is_hull_edge(e)){
|
|
typename Indirect_kernel::Orientation_2 o2= sk.orientation_2_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();
|
|
|
|
bool odd_parity=false;
|
|
bool infinity=false;
|
|
for (unsigned int i=0; i<4; ++i) {
|
|
if (infinity) {
|
|
ks[i-1]=ks[i];
|
|
} else {
|
|
if (ks[i] == Point_key()) {
|
|
infinity=true;
|
|
odd_parity= ((i%2)==1);
|
|
}
|
|
}
|
|
}
|
|
if (odd_parity) {
|
|
std::swap(ks[0], ks[1]);
|
|
}
|
|
CGAL::Orientation o=o2(ks[0], ks[1], ks[2]);
|
|
return o==CGAL::POSITIVE;
|
|
} else {
|
|
typename Indirect_kernel::Side_of_oriented_circle_2 soc
|
|
= sk.side_of_oriented_circle_2_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();
|
|
|
|
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;
|
|
}
|
|
Simulation_traits tr_;
|
|
typename KDel::Handle kdel_;
|
|
Indirect_kernel ik_;
|
|
};
|
|
|
|
CGAL_END_NAMESPACE
|
|
|
|
#endif
|
|
#undef CGAL_UD_DEBUG
|