// Copyright (c) 2005 Stanford University (USA). // All rights reserved. // // This file is part of CGAL (www.cgal.org); you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public License as // published by the Free Software Foundation; version 2.1 of the License. // See the file LICENSE.LGPL distributed with CGAL. // // Licensees holding a valid commercial license may use this file in // accordance with the commercial license agreement provided with the software. // // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // // $URL$ // $Id$ // // // Author(s) : Daniel Russel #ifndef CGAL_KINETIC_KINETIC_DELAUNAY_2_H #define CGAL_KINETIC_KINETIC_DELAUNAY_2_H #include #include #include #include #include #include #include #include #include #include #include #include #include CGAL_KINETIC_BEGIN_NAMESPACE #define CGAL_DELAUNAY_2_DEBUG(x) template struct Delaunay_2_event_base { Delaunay_2_event_base(const typename KDel::Certificate &c, const typename KDel::Edge &e, KDel *kdel): c_(c), e_(e), d_(kdel) {} typename KDel::Certificate &certificate() const { return c_; } const typename KDel::Edge edge() const { return e_; } KDel* kdel() { return d_; } void process() { d_->flip(e_, c_); } typename KDel::Certificate c_; const typename KDel::Edge e_; KDel *d_; }; template class Delaunay_edge_failure_event: public Delaunay_2_event_base { typedef Delaunay_2_event_base P; public: //! Make sure that the s has been advanced Delaunay_edge_failure_event(typename K::SOC_certificate &s, const typename K::Edge &e, K *kdel): P(s, e, kdel) { } void write(std::ostream &out) const { out << "Flip " << K::TDS_helper::origin(P::edge())->point() << "," << K::TDS_helper::destination(P::edge())->point(); } }; template class Delaunay_hull_edge_failure_event: public Delaunay_2_event_base { typedef Delaunay_2_event_base P; public: //! Make sure that the s has been advanced Delaunay_hull_edge_failure_event(typename K::O2_certificate &s, const typename K::Edge &e, K *kdel): P(s,e,kdel) { //if (!s.empty()) s_.pop(); } void write(std::ostream &out) const { out << "Flip " << K::TDS_helper::origin(P::edge())->point() << "," << K::TDS_helper::destination(P::edge())->point(); } }; template std::ostream& operator<<(std::ostream &out, const Delaunay_edge_failure_event &e) { e.write(out); return out; } template std::ostream& operator<<(std::ostream &out, const Delaunay_hull_edge_failure_event &e) { e.write(out); return out; } //! A 2D kinetic Delaunay triangulation. /*! Points are added via the Moving_point_table, so the public interface is very limited. See kinetic_Delaunay_2.cc for a useage example. */ template , CGAL::Kinetic::Delaunay_triangulation_face_base_2 > > > class Delaunay_triangulation_2: public Ref_counted > { public: typedef Simulation_traits_t Simulation_traits; typedef Delaunay_triangulation_2 This; typedef typename Simulation_traits::Kinetic_kernel Kinetic_kernel; typedef typename Simulation_traits::Simulator Simulator; typedef typename Simulation_traits::Active_points_2_table Moving_point_table; typedef typename Moving_point_table::Key Point_key; typedef typename Simulator::Event_key Event_key; //typedef typename Simulator::Root_stack Root_stack; typedef typename Simulator::Time Time; typedef typename Delaunay::Edge_circulator Edge_circulator; typedef typename Delaunay::Face_circulator Face_circulator; typedef typename Delaunay::Finite_edges_iterator Finite_edges_iterator; //typedef typename Delaunay::Edge_iterator Edge_iterator; typedef typename Delaunay::Geom_traits::Point_2 Del_point; typedef typename Delaunay::Vertex_handle Vertex_handle; typedef typename Delaunay::Face_handle Face_handle; typedef typename Delaunay::Edge Edge; typedef typename Delaunay::All_faces_iterator Face_iterator; typedef typename Delaunay::All_edges_iterator Edge_iterator; typedef typename Kinetic_kernel::Positive_side_of_oriented_circle_2 SOC; typedef typename Kinetic_kernel::Positive_orientation_2 O2; typedef typename SOC::result_type SOC_certificate; typedef typename O2::result_type O2_certificate; typedef O2_certificate Certificate; typedef internal::Triangulation_data_structure_helper_2 TDS_helper; typedef Delaunay_edge_failure_event SOC_event; typedef Delaunay_hull_edge_failure_event O2_event; friend class Delaunay_edge_failure_event; friend class Delaunay_hull_edge_failure_event; typedef typename CGAL::Kinetic::Simulator_kds_listener Simulator_listener; friend class CGAL::Kinetic::Simulator_kds_listener; typedef typename CGAL::Kinetic::Active_objects_listener_helper Moving_point_table_listener; friend class CGAL::Kinetic::Active_objects_listener_helper; public: Delaunay_triangulation_2(Simulation_traits st, Visitor w= Visitor()): traits_(st), del_(traits_.instantaneous_kernel_object()), soc_(traits_.kinetic_kernel_object().positive_side_of_oriented_circle_2_object()), o2_(traits_.kinetic_kernel_object().positive_orientation_2_object()), watcher_(w), has_certificates_(true){ siml_ = Simulator_listener(st.simulator_handle(), this); motl_= Moving_point_table_listener(st.active_points_2_table_handle(), this); } //! Just write the objects in order; void write(std::ostream &out) const { out << del_; } typedef Delaunay Triangulation; const Triangulation &triangulation(const typename Simulator::NT &t) const { //update_instantaneous_kernel_time(); del_.geom_traits().set_time(t); return del_; } const Simulation_traits& simulation_traits_object() const { return traits_; } typedef typename Delaunay::Triangulation_data_structure Triangulation_data_structure; const Triangulation_data_structure &triangulation_data_structure() const { return del_.tds(); } /*const std::set& recent_edges() const { return new_edges_; }*/ //! Verify that the current state of the void audit() const { if (!has_certificates_) return; CGAL_KINETIC_LOG(CGAL::Kinetic::LOG_SOME, "Auditing delaunay" << std::endl); CGAL_KINETIC_LOG(CGAL::Kinetic::LOG_LOTS, *this); if (del_.dimension() != 2) return; Delaunay sdel(traits_.instantaneous_kernel_object()); sdel.geom_traits().set_time(traits_.simulator_handle()->rational_current_time()); for (typename Delaunay::Finite_vertices_iterator cit= del_.finite_vertices_begin(); cit != del_.finite_vertices_end(); ++cit){ sdel.insert(cit->point()); } /* sdel.insert(traits_.active_points_2_table_handle()->keys_begin(), traits_.active_points_2_table_handle()->keys_end());*/ CGAL_KINETIC_LOG(CGAL::Kinetic::LOG_LOTS, sdel << std::endl); if (del_.dimension() != sdel.dimension()) { CGAL_KINETIC_LOG(CGAL::Kinetic::LOG_NONE, "AUDIT FAILURE Dimensions don't match in audit" << std::endl); return; } CGAL_exactness_assertion(del_.dimension() == sdel.dimension()); for (typename Delaunay::All_vertices_iterator vit = del_.all_vertices_begin(); vit != del_.all_vertices_end(); ++vit) { if (vit->point() != Point_key()) { if (vit->neighbors_is_changed()) { CGAL_KINETIC_LOG(CGAL::Kinetic::LOG_NONE, "AUDIT FAILURE neighbors is changed " << vit->point() << std::endl); CGAL_exactness_assertion(!vit->neighbors_is_changed()); } if (vit->neighbors() != vit->degree()) { CGAL_KINETIC_LOG(CGAL::Kinetic::LOG_NONE, "AUDIT FAILURE stored degree is " << vit->neighbors() << " and actual is " << vit->degree() << " for " << vit->point() << std::endl); CGAL_exactness_assertion(vit->neighbors() == vit->degree()); } } } for (typename Delaunay::All_vertices_iterator vit = sdel.all_vertices_begin(); vit != sdel.all_vertices_end(); ++vit) { bool found=false; //Object_key k= vit->point(); for (typename Delaunay::All_vertices_iterator vit2= del_.all_vertices_begin(); vit2 != del_.all_vertices_end(); ++vit2) { //Object_key k2= vit2->point(); if (vit->point() == vit2->point()) { found=true; //int d= vit->degree(); //int d2= vit2->degree(); if (vit->degree() != vit2->degree()) { CGAL_KINETIC_LOG(CGAL::Kinetic::LOG_NONE, "AUDIT FAILURE Degrees don't match in: " << vit->point() << std::endl); } CGAL_exactness_assertion(vit->degree() == vit2->degree()); } } if (!found) { CGAL_KINETIC_LOG(CGAL::Kinetic::LOG_NONE, "AUDIT FAILURE Matching vertex not found: " << vit->point() << std::endl); } CGAL_exactness_assertion(found); } del_.geom_traits().set_time(traits_.simulator_handle()->rational_current_time()); typename Simulation_traits::Instantaneous_kernel::Side_of_oriented_circle_2 ic2 = del_.geom_traits().side_of_oriented_circle_2_object(); for (typename Delaunay::Finite_edges_iterator fit = del_.finite_edges_begin(); fit != del_.finite_edges_end(); ++fit){ Point_key k0= fit->first->vertex((fit->second+1)%3)->point(); Point_key k2= fit->first->vertex((fit->second+2)%3)->point(); Point_key k3= TDS_helper::mirror_vertex(*fit)->point(); Point_key k1= TDS_helper::third_vertex(*fit)->point(); if (k1== Point_key() || k3== Point_key()) continue; typename Simulation_traits::Static_kernel::Point_2 p0= del_.geom_traits().static_object(k0); typename Simulation_traits::Static_kernel::Point_2 p1= del_.geom_traits().static_object(k1); typename Simulation_traits::Static_kernel::Point_2 p2= del_.geom_traits().static_object(k2); typename Simulation_traits::Static_kernel::Point_2 p3= del_.geom_traits().static_object(k3); if (ic2(k0, k1, k2, k3) != CGAL::ON_POSITIVE_SIDE) { CGAL_KINETIC_LOG(CGAL::Kinetic::LOG_NONE, "AUDIT FAILURE Failed certificate: " << k0 << " " << k1 << " " << k2 << " " << k3 << std::endl); CGAL_KINETIC_LOG(CGAL::Kinetic::LOG_NONE, "AUDIT FAILURE Points are: " << p0 << ": " << p1 << ": " << p2 << ": " << p3 << std::endl); } CGAL_exactness_assertion(ic2(k0, k1, k2, k3) == CGAL::ON_POSITIVE_SIDE); } for (typename Delaunay::Edge_iterator fit = del_.edges_begin(); fit != del_.edges_end(); ++fit){ if (TDS_helper::origin(*fit)->degree()==3 || TDS_helper::destination(*fit)->degree()==3 /*|| del_.is_edge(TDS_helper::third_vertex(*fit), TDS_helper::mirror_vertex(*fit))*/) { if (TDS_helper::get_undirected_edge_label(*fit) != Event_key()) { CGAL_KINETIC_LOG(CGAL::Kinetic::LOG_NONE, "AUDIT FAILURE certificate on degree 3 edge: " << TDS_helper::origin(*fit)->point() << " " << TDS_helper::destination(*fit)->point() << TDS_helper::origin(*fit)->degree() << " " << TDS_helper::destination(*fit)->degree() << std::endl); } CGAL_exactness_assertion(TDS_helper::get_undirected_edge_label(*fit) == Event_key()); } else { if (TDS_helper::get_undirected_edge_label(*fit) == Event_key()) { CGAL_KINETIC_LOG(CGAL::Kinetic::LOG_NONE, "AUDIT FAILURE no certificate on edge: " << TDS_helper::origin(*fit)->point() << " " << TDS_helper::destination(*fit)->point() << std::endl); CGAL_KINETIC_LOG(CGAL::Kinetic::LOG_NONE, "AUDIT FAILURE degrees are: " << TDS_helper::origin(*fit)->degree() << " " << TDS_helper::destination(*fit)->degree() << std::endl); } CGAL_exactness_assertion(TDS_helper::get_undirected_edge_label(*fit) != Event_key()); } } } void set_has_certificates(bool tf) { if (tf == has_certificates_){ } else { if (tf==true) { CGAL_KINETIC_LOG(CGAL::Kinetic::LOG_SOME, "DELAUNAY2: Creating certificates."<< std::endl); for (typename Delaunay::All_vertices_iterator vit = del_.all_vertices_begin(); vit != del_.all_vertices_end(); ++vit) { int deg=vit->degree(); CGAL_assertion(deg >=3); Vertex_handle vh= vit; vh->set_neighbors(deg); CGAL_DELAUNAY_2_DEBUG(std::cout << "Set degree of " << vit->point() << " to " << deg << std::endl); //vit->set_neighbors_is_changed(false); } for (Edge_iterator eit = del_.all_edges_begin(); eit != del_.all_edges_end(); ++eit) { TDS_helper::set_undirected_edge_label(*eit, Event_key()); update_edge(*eit); } watcher_.create_faces(del_.all_faces_begin(), del_.all_faces_end()); } else { for (typename Delaunay::Edge_iterator it = del_.edges_begin(); it != del_.edges_end(); ++it){ if (TDS_helper::get_undirected_edge_label(*it) != Event_key()){ traits_.simulator_handle()->delete_event(TDS_helper::get_undirected_edge_label(*it)); TDS_helper::set_undirected_edge_label(*it, Event_key()); } } } has_certificates_=tf; } } bool has_certificates() { return has_certificates_; } void erase(Point_key k) { // erase all incident certificates Vertex_handle vh= vhs_[k]; if (vh == Vertex_handle()) { CGAL_KINETIC_LOG(CGAL::Kinetic::LOG_SOME, "Point " << k << " is not in triangulation on removal."<< std::endl); return; } watcher_.remove_vertex(vh); if (has_certificates_) { Face_circulator fc= vh->incident_faces(), fe=fc; if (fc != NULL) { do { for (unsigned int j=0; j<3; ++j) { Edge e(fc, j); Event_key k= TDS_helper::get_undirected_edge_label(e); if (k.is_valid()) { traits_.simulator_handle()->delete_event(k); TDS_helper::set_undirected_edge_label(e, Event_key()); } fc->vertex(j)->set_neighbors_is_changed(true); } ++fc; } while (fc != fe); } } // remove from triangulation del_.geom_traits().set_time(traits_.simulator_handle()->rational_current_time()); del_.remove(vh); //new_edges_.clear(); if (del_.dimension()==2 && has_certificates_) { std::vector faces; del_.get_conflicts(k,std::back_inserter(faces)); for (unsigned int i=0; i< faces.size(); ++i) { for (unsigned int j=0; j<3; ++j) { Edge e(faces[i],j); //Event_key k= TDS_helper::get_undirected_edge_label(e); // a bit redundant for certificates which don't fail update_edge(e); //new_edges_.insert(e); } } watcher_.create_faces(faces.begin(), faces.end()); } } //! The assertion will catch that the object is in the same sorted order void set(Point_key k) { //std::cout << "Object changed " << k << std::endl; //new_edges_.clear(); if (del_.dimension() != 2) { CGAL_KINETIC_LOG(CGAL::Kinetic::LOG_SOME,"Triangulation is still 1D.\n"); return; } Vertex_handle vh= vhs_[k]; if (vh == Vertex_handle()) { CGAL_KINETIC_LOG(CGAL::Kinetic::LOG_SOME, "Point " << k << " is not in triangulation on set."<< std::endl); return; } if (has_certificates_) { Edge_circulator ec= vh->incident_edges(), ef=ec; if (ec != NULL) { do { if (TDS_helper::get_undirected_edge_label(*ec) != Event_key()) { traits_.simulator_handle()->delete_event(TDS_helper::get_undirected_edge_label(*ec)); TDS_helper::set_undirected_edge_label(*ec, Event_key()); } ++ec; } while (ec != ef); } Face_circulator fc= vh->incident_faces(), fe= fc; if (fc != NULL) { do { int i= fc->index(vh); Edge e(fc, i); if (TDS_helper::get_undirected_edge_label(e) != Event_key()) { traits_.simulator_handle()->delete_event(TDS_helper::get_undirected_edge_label(e)); TDS_helper::set_undirected_edge_label(e, Event_key()); } ++fc; } while (fc != fe); } } watcher_.modify_vertex(vh); if (has_certificates_) { Edge_circulator ec= vh->incident_edges(), ef=ec; if (ec != NULL) { do { update_edge(*ec); ++ec; } while (ec != ef); } Face_circulator fc= vh->incident_faces(), fe= fc; if (fc != NULL) { do { int i= fc->index(vh); update_edge(Edge(fc, i)); ++fc; } while (fc != fe); } } //write(std::cout); } //! /*! Some old certificate edges will be lost, have to find all conflicts first */ void insert(Point_key k) { CGAL_DELAUNAY_2_DEBUG(std::cout << "Inserting " << k << std::endl); bool was_2d= (del_.dimension()==2); del_.geom_traits().set_time(traits_.simulator_handle()->rational_current_time()); if (was_2d && has_certificates_) { //std::cout << "removing extra certificates.\n"; std::vector faces; del_.get_conflicts(k, std::back_inserter(faces)); for (unsigned int i=0; i< faces.size(); ++i) { Face_handle f= faces[i]; for (unsigned int j=0; j<3; ++j) { f->vertex(j)->set_neighbors_is_changed(true); Edge e(f, j); Event_key k= TDS_helper::get_undirected_edge_label(e); if (k != Event_key()) { traits_.simulator_handle()->delete_event(k); TDS_helper::set_undirected_edge_label(e, Event_key()); } } } watcher_.remove_faces(faces.begin(), faces.end()); if (faces.empty()) { CGAL_KINETIC_LOG(CGAL::Kinetic::LOG_SOME, "DELAUNAY vertex not successfully inserted " << k << std::endl); return; } } vhs_[k]= del_.insert(k); CGAL_assertion(vhs_[k] != Vertex_handle()); vhs_[k]->set_neighbors(vhs_[k]->degree()); CGAL_DELAUNAY_2_DEBUG(std::cout << "Vertex " << vhs_[k]->point() << " has " << vhs_[k]->neighbors() << std::endl); watcher_.create_vertex(vhs_[k]); // now have to update if (!was_2d && del_.dimension()==2) { //std::cout << "Creating certificates from scratch.\n"; if (has_certificates_) { has_certificates_=false; set_has_certificates(true); } } else if (del_.dimension() == 2 && has_certificates_) { Vertex_handle vh= vhs_[k]; Edge_circulator ec= vh->incident_edges(), ef=ec; do { if (TDS_helper::get_undirected_edge_label(*ec) == Event_key()) { update_edge(*ec); } ++ec; } while (ec != ef); Face_circulator fc= vh->incident_faces(), fe= fc; do { int i= fc->index(vh); Edge e(fc, i); if (TDS_helper::get_undirected_edge_label(e) == Event_key()) { update_edge(e); } ++fc; } while (fc != fe); } //write(std::cout); if (del_.dimension()==2) audit(); } Edge flip(const Edge &e, Certificate cert) { CGAL_KINETIC_LOG(CGAL::Kinetic::LOG_SOME, "DELAUNAY Flipping edge " << TDS_helper::origin(e)->point() << TDS_helper::destination(e)->point() << std::endl); //CGAL_KINETIC_LOG(CGAL::Kinetic::LOG_NONE, TDS_helper::destination(e)->point() << std::endl); //CGAL_KINETIC_LOG(CGAL::Kinetic::LOG_SOME, " at " << traits_.simulator()->current_time() << std::endl); Face_handle face= e.first; int index= e.second; int mirror_index = face->mirror_index(index); Face_handle mirror_face = face->neighbor(index); if (del_.is_edge(TDS_helper::third_vertex(e), TDS_helper::mirror_vertex(e))) { // we have a numeric error, lets try to rebuild the neighboring certificates CGAL_KINETIC_LOG(CGAL::Kinetic::LOG_SOME, "DELAUNAY ERROR not flipping unflippable edge" << std::endl); //make this better double ub=to_interval(traits_.simulator_handle()->next_event_time()).second; ub= std::max(ub+.0000001, nextafter(ub, std::numeric_limits::max())); Time t=ub; //cert.pop_failure_time(); Event_key k =traits_.simulator_handle()->new_event(t, O2_event(cert, e, this)); TDS_helper::set_undirected_edge_label(e, k); return e; } for (unsigned int i=0; i<3; ++i) { Edge e0(face, i); if (e0.second != index && TDS_helper::get_undirected_edge_label(e0) != Event_key()) { traits_.simulator_handle()->delete_event(TDS_helper::get_undirected_edge_label(e0)); TDS_helper::set_undirected_edge_label(e0, Event_key()); } face->vertex(i)->set_neighbors_is_changed(true); Edge e1(mirror_face, i); if (e1.second != mirror_index && TDS_helper::get_undirected_edge_label(e1) != Event_key()) { traits_.simulator_handle()->delete_event(TDS_helper::get_undirected_edge_label(e1)); TDS_helper::set_undirected_edge_label(e1, Event_key()); } mirror_face->vertex(i)->set_neighbors_is_changed(true); } TDS_helper::set_undirected_edge_label(e, Event_key()); watcher_.before_flip(e); del_.tds().flip(face,index); // we also know that CGAL preserves the edge index of the flipped edge mirror_index = mirror_face->index(face); index= face->index(mirror_face); Edge flipped_edge(face,index); //CGAL_postcondition(del_.is_face(face)); { Time t= cert.failure_time(); cert.pop_failure_time(); Event_key k =traits_.simulator_handle()->new_event(t, O2_event(cert, flipped_edge, this)); TDS_helper::set_undirected_edge_label(flipped_edge, k); } mirror_index = face->mirror_index(index); mirror_face = face->neighbor(index); for (unsigned int i=0; i<3; ++i) { Edge e0(face, i); update_edge(e0); Edge e1(mirror_face, i); update_edge(e1); } //write(std::cout); //new_edges_.clear(); //new_edges_.insert(flipped_edge); CGAL_KINETIC_LOG(CGAL::Kinetic::LOG_SOME, "Created " << TDS_helper::origin(flipped_edge)->point()); CGAL_KINETIC_LOG(CGAL::Kinetic::LOG_SOME, TDS_helper::destination(flipped_edge)->point() << std::endl); watcher_.after_flip(flipped_edge); return flipped_edge; } Visitor &visitor() { return watcher_; } const Visitor &visitor() const { return watcher_; } protected: Simulation_traits traits_; Simulator_listener siml_; Moving_point_table_listener motl_; Delaunay del_; std::map vhs_; SOC soc_; O2 o2_; //std::set new_edges_; Visitor watcher_; bool has_certificates_; const typename Moving_point_table::Data& point(Point_key k) const { return traits_.active_points_2_table_handle()->at(k); } /*void add_certificate_around_vertex(Face_handle f0, Face_handle f1) { int i0= (e.second+1)%3; Face_handle n0= ce.first->neighbor(i0); Vertex_handle v0=ce.first->vertex((e.second+2)%3); Edge e0(n0,n0->index(v0)); int i1= (e.second+2)%3; Face_handle n1= ce.first->neighbor(i1); Vertex_handle v1=ce.first->vertex((e.second+1)%3); Edge e1(n1, n1->index(v1)); CGAL_assertion(v0 != v1); CGAL_assertion(n0 != n1); if (TDS_helper::mirror_edge(e1) == e0 && !TDS_helper::get_undirected_edge_label(e1).is_valid()) { CGAL_KINETIC_LOG(CGAL::Kinetic::LOG_LOTS, "DELAUNAY adding certificate to edge " << TDS_helper::origin(e1)->point() << " " << TDS_helper::destination(e1)->point() << std::endl;); new_certificate(e0); } else { std::cout << "Not adding certificate to edge " << TDS_helper::origin(e1)->point() << " " << TDS_helper::destination(e1)->point() << " or " << TDS_helper::origin(e0)->point() << " " << TDS_helper::destination(e0)->point(); if (TDS_helper::get_undirected_edge_label(e1).is_valid()) { std::cout << " because it is there"; } std::cout << std::endl; } }*/ bool is_hull_edge(const Edge &e) const { 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(); } SOC_certificate compute_failure_time(const 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(); //bool odd_parity=false; //bool infinity=false; SOC_certificate s=soc_(point(ks[0]), point(ks[1]), point(ks[2]), point(ks[3]), traits_.simulator_handle()->current_time(), traits_.simulator_handle()->end_time()); return s; } O2_certificate compute_hull_failure_time(const 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(); 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].is_valid()) { infinity=true; odd_parity= ((i%2)==1); } } } if (odd_parity) { std::swap(ks[0], ks[1]); } O2_certificate s=o2_(point(ks[0]), point(ks[1]), point(ks[2]), traits_.simulator_handle()->current_time(), traits_.simulator_handle()->end_time()); return s; } void update_vertex(Vertex_handle vh) { if (!vh->neighbors_is_changed()) { } else { int deg= vh->degree(); if (deg ==3 && vh->neighbors() != 3) { CGAL_DELAUNAY_2_DEBUG(std::cout << "Degree 3 for " << vh->point() << std::endl); vh->set_neighbors(deg); typename Delaunay::Edge_circulator ec= del_.incident_edges(vh); do { if (TDS_helper::get_undirected_edge_label(*ec) != Event_key()) { traits_.simulator_handle()->delete_event(TDS_helper::get_undirected_edge_label(*ec)); } TDS_helper::set_undirected_edge_label(*ec, Event_key()); ++ec; } while (ec != del_.incident_edges(vh)); } else if (vh->neighbors()==3 && deg != 3) { CGAL_DELAUNAY_2_DEBUG(std::cout << "Degree 4 for " << vh->point() << std::endl); vh->set_neighbors(deg); typename Delaunay::Edge_circulator ec= del_.incident_edges(vh); do { if (TDS_helper::get_undirected_edge_label(*ec) == Event_key()) { // check other vertex, it it is not changed and not 3, build Vertex_handle ov= ec->first->vertex((ec->second+1)%3); if (ov== vh) { ov= ec->first->vertex((ec->second+2)%3); } if (!ov->neighbors_is_changed() && ov->neighbors() != 3){ new_certificate(*ec); CGAL_DELAUNAY_2_DEBUG(std::cout << "New cert for " << TDS_helper::origin(*ec)->point() << " " << TDS_helper::destination(*ec)->point() << std::endl); } else { CGAL_DELAUNAY_2_DEBUG(std::cout << "Not creating cert for " << TDS_helper::origin(*ec)->point() << " " << TDS_helper::destination(*ec)->point() << std::endl); } } ++ec; } while (ec != del_.incident_edges(vh)); } else { vh->set_neighbors(deg); } CGAL_DELAUNAY_2_DEBUG( std::cout << "Vertex " << vh->point() << " has " << vh->neighbors() << std::endl); } } void new_certificate( const Edge &e) { CGAL_precondition(TDS_helper::get_undirected_edge_label(e) == Event_key()); CGAL_DELAUNAY_2_DEBUG(std::cout << "Making certificate for " << TDS_helper::origin(e)->point() << " " << TDS_helper::destination(e)->point() << " which would make " << TDS_helper::mirror_vertex(e)->point() << " " << TDS_helper::third_vertex(e)->point() << std::endl); /*if (del_.is_edge(TDS_helper::mirror_vertex(e), TDS_helper::third_vertex(e))) { std::cout << "Skipping" << std::endl; return; }*/ Event_key k; if (static_cast(is_hull_edge(e))) { O2_certificate s= compute_hull_failure_time(e); Time t= s.failure_time(); s.pop_failure_time(); k =traits_.simulator_handle()->new_event(t, O2_event(s, e, this)); } else { SOC_certificate s= compute_failure_time(e); Time t= s.failure_time(); s.pop_failure_time(); k =traits_.simulator_handle()->new_event(t, O2_event(s, e, this)); } TDS_helper::set_undirected_edge_label(e, k); } void update_edge(const Edge &e) { CGAL_DELAUNAY_2_DEBUG(std::cout << "Updating edge edge " << TDS_helper::origin(e)->point() << " " << TDS_helper::destination(e)->point() << std::endl); Vertex_handle ov=TDS_helper::origin(e); Vertex_handle dv=TDS_helper::destination(e); update_vertex(ov); update_vertex(dv); CGAL_assertion(!ov->neighbors_is_changed()); CGAL_assertion(!dv->neighbors_is_changed()); if (TDS_helper::get_undirected_edge_label(e) != Event_key()) { CGAL_DELAUNAY_2_DEBUG(std::cout << "Already has event " << std::endl); } else if (ov->neighbors() ==3 || dv->neighbors() ==3) { CGAL_DELAUNAY_2_DEBUG(std::cout << "One end has 3 " << std::endl); } else { CGAL_DELAUNAY_2_DEBUG(std::cout << "New certificate" << std::endl); new_certificate(e); } } //! rebuild a certificates /*! I need to check if there is a valid one before since I use change_object to initialize the certificates of a new object. */ /*void rebuild_certificate( const Edge &e) { if (TDS_helper::get_undirected_edge_label(e).is_valid()) { traits_.simulator_handle()->delete_event(TDS_helper::get_undirected_edge_label(e)); TDS_helper::set_undirected_edge_label(e, Event_key()); compute_certificate(e); } else { std::cout << "Not rebuilding for edge " << TDS_helper::origin(e)->point() << " " << TDS_helper::destination(e)->point() << std::endl; } }*/ }; template std::ostream &operator<<(std::ostream &out, const Delaunay_triangulation_2 &kd) { kd.write(out); return out; } CGAL_KINETIC_END_NAMESPACE #endif