// Copyright (c) 2005 Rijksuniversiteit Groningen (Netherlands) // All rights reserved. // // This file is part of CGAL (www.cgal.org); you may redistribute it under // the terms of the Q Public License version 1.0. // See the file LICENSE.QPL 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) : Nico Kruithof #ifndef CGAL_TRIANGULATE_MIXED_COMPLEX_3 #define CGAL_TRIANGULATE_MIXED_COMPLEX_3 #include #include #include #include #include #include CGAL_BEGIN_NAMESPACE template < class CMCT > class CMCT_Cell { public: typedef CMCT_Cell Self; typedef typename CMCT::Vertex_handle Vertex_handle; typedef typename CMCT::Rt_Simplex Rt_Simplex; CMCT_Cell() { } CMCT_Cell(Vertex_handle vs[], Rt_Simplex &sim) : sim_(sim) { for (int i=0; i<4; i++) _vs[i] = vs[i]; } CMCT_Cell(const Vertex_handle &vh0, const Vertex_handle &vh1, const Vertex_handle &vh2, const Vertex_handle &vh3, Rt_Simplex &sim) : sim_(sim) { _vs[0] = vh0; _vs[1] = vh1; _vs[2] = vh2; _vs[3] = vh3; } Vertex_handle operator[](int i) const { CGAL_assertion((0 <= i) && (i<4)); return _vs[i]; } Vertex_handle vertex(int i) const { CGAL_assertion((0 <= i) && (i<4)); return _vs[i]; } const Rt_Simplex &mixed_cell() const { return sim_; } bool operator==(const Self &other) const { return ((_vs[0] == other._vs[0]) && (_vs[1] == other._vs[1]) && (_vs[2] == other._vs[2]) && (_vs[3] == other._vs[3])); } bool operator!=(const Self &other) const { return !operator==(other); } private: Vertex_handle _vs[4]; Rt_Simplex sim_; }; template < class CMCT > class CMCT_Cell_iterator { public: typedef CMCT_Cell_iterator Self; typedef typename CMCT::Cell Cell; typedef typename CMCT::Rt_Finite_vertices_iterator Rt_Finite_vertices_iterator; typedef typename CMCT::Rt_Finite_edges_iterator Rt_Finite_edges_iterator; typedef typename CMCT::Rt_Finite_facets_iterator Rt_Finite_facets_iterator; typedef typename CMCT::Rt_Finite_cells_iterator Rt_Finite_cells_iterator; // types of an iterator: typedef std::forward_iterator_tag iterator_category; typedef Cell value_type; typedef std::ptrdiff_t difference_type; typedef value_type* pointer; typedef value_type& reference; CMCT_Cell_iterator(const CMCT *cmct_, int d=0) : dim(d), cmct(cmct_) { if (cmct->regular.number_of_vertices()==0) { dim = 4; return; } vit = cmct->regular.finite_vertices_begin(); eit = cmct->regular.finite_edges_begin(); fit = cmct->regular.finite_facets_begin(); cit = cmct->regular.finite_cells_begin(); cmct->construct_0_cell(vit, std::back_inserter(cells)); vit++; curr = cells.begin(); } CMCT_Cell_iterator(const CMCT_Cell_iterator ©) { dim=copy.dim; cmct = copy.cmct; vit=copy.vit; eit=copy.eit; fit=copy.fit; cit=copy.cit; for (typename std::vector::const_iterator it = copy.cells.begin(); it != copy.cells.end(); it++) { cells.push_back(*it); } CGAL_assertion(std::equal(copy.cells.begin(), copy.cells.end(), cells.begin())); int ncells = cells.size()-std::distance ((typename std::vector::const_iterator)copy.curr, (typename std::vector::const_iterator)copy.cells.end()); CGAL_assertion(ncells >= 0); curr = cells.begin(); while (ncells--!=0) curr++; CGAL_assertion (std::distance((typename std::vector::const_iterator)curr, (typename std::vector::const_iterator)cells.end()) == std::distance((typename std::vector::const_iterator)copy.curr, (typename std::vector::const_iterator)copy.cells.end())); } Self &operator=(const CMCT_Cell_iterator &other) { if (&other != this) { dim=other.dim; cmct = other.cmct; vit=other.vit; eit=other.eit; fit=other.fit; cit=other.cit; for (typename std::vector::const_iterator it = other.cells.begin(); it != other.cells.end(); it++) { cells.push_back(*it); } int ncells = cells.size() - std::distance(other.curr, other.cells.end()); CGAL_assertion(ncells > 0); curr = cells.begin(); while (ncells--!=0) curr++; CGAL_assertion(std::distance(curr, (typename std::vector::const_iterator) cells.end()) == std::distance(other.curr, other.cells.end())); } return *this; } Self & operator++() { CGAL_assertion(curr != cells.end()); curr++; if (curr != cells.end()) return *this; cells.clear(); while (cells.empty() && (dim < 4)) { switch (dim) { case 0: { if (vit == cmct->regular.finite_vertices_end()) { dim ++; } else { cmct->construct_0_cell(vit, std::back_inserter(cells)); vit ++; } break; } case 1: { if (eit == cmct->regular.finite_edges_end()) { dim ++; } else { cmct->construct_1_cell(eit, std::back_inserter(cells)); eit ++; } break; } case 2: { if (fit == cmct->regular.finite_facets_end()) { dim ++; } else { cmct->construct_2_cell(fit, std::back_inserter(cells)); fit ++; } break; } case 3: { if (cit == cmct->regular.finite_cells_end()) { dim ++; } else { cmct->construct_3_cell(cit, std::back_inserter(cells)); cit ++; } break; } }; } curr = cells.begin(); return *this; } CMCT_Cell_iterator & operator++(int i) { CMCT_Cell_iterator temp = *this; --*this; return temp; } Cell & operator*() const { CGAL_assertion(dim < 4); CGAL_assertion(curr != cells.end()); return *curr; } pointer operator->() const { CGAL_assertion(dim < 4); CGAL_assertion(curr != cells.end()); return &*curr; } operator pointer() { return *curr; } bool operator==(const CMCT_Cell_iterator &other) const { if ((dim == 4) || (other.dim == 4) ) return (dim==other.dim); return (*curr == *other.curr); } bool operator!=(const CMCT_Cell_iterator &other) const { return !(*this==other); } private: int dim; const CMCT *cmct; Rt_Finite_vertices_iterator vit; Rt_Finite_edges_iterator eit; Rt_Finite_facets_iterator fit; Rt_Finite_cells_iterator cit; std::vector cells; // Cells in the current mixed cell; //typename std::vector::const_iterator curr; typename std::vector::iterator curr; }; template class Combinatorial_mixed_complex_triangulator_3 { typedef Combinatorial_mixed_complex_triangulator_3 Self; public: typedef MixedComplexTraits_3 Regular; typedef typename Regular::Geom_traits Regular_traits; // NGHK: Make private again: private: typedef typename Regular::Vertex_handle Rt_Vertex_handle; typedef typename Regular::Edge Rt_Edge; typedef typename Regular::Facet Rt_Facet; typedef typename Regular::Cell_handle Rt_Cell_handle; typedef typename Regular::Finite_vertices_iterator Rt_Finite_vertices_iterator; typedef typename Regular::Finite_edges_iterator Rt_Finite_edges_iterator; typedef typename Regular::Finite_facets_iterator Rt_Finite_facets_iterator; typedef typename Regular::All_cells_iterator Rt_All_cells_iterator; typedef typename Regular::Finite_cells_iterator Rt_Finite_cells_iterator; typedef typename Regular::Cell_circulator Rt_Cell_circulator; typedef Triangulation_simplex_3 Rt_Simplex; typedef typename Regular::Bare_point Rt_Point; typedef typename Regular_traits::FT Rt_FT; typedef typename Regular::Weighted_point Rt_Weighted_point; typedef Compute_anchor_3 Compute_anchor; typedef std::pair Symb_anchor; typedef Symb_anchor Vertex; typedef const Vertex * Vertex_handle; typedef CMCT_Cell Cell; friend class CMCT_Cell_iterator; typedef CMCT_Cell_iterator Cell_iterator; // You might get type differences here: // The map that maps a Rt_Simplex to an iterator of the map // (used as union_find_structure) struct Anchor_map_iterator_tmp; typedef std::map Anchor_map; struct Anchor_map_iterator_tmp : Anchor_map::iterator { Anchor_map_iterator_tmp() : Anchor_map::iterator() {} Anchor_map_iterator_tmp(typename Anchor_map::iterator const &it) : Anchor_map::iterator(it) {} }; typedef typename Anchor_map::iterator Anchor_map_iterator; typedef typename Anchor_map::const_iterator Anchor_map_const_iterator; typedef std::set Vertex_container; typedef typename Vertex_container::iterator Vertex_container_it; typedef Vertex_container_it Vertex_iterator; typedef std::map Symb_vertex_map; typedef typename Symb_vertex_map::const_iterator Symb_vertex_map_const_it; class Is_no_vertex { const Self *ctmc; public: Is_no_vertex(const Self *ctmc_) : ctmc(ctmc_) {} bool operator()(const Symb_vertex_map_const_it & it) const { return (it->first != it->second); } }; //typedef Filter_iterator Vertex_iterator; // class Vertex_iterator { // typedef Self Combinatorial_mixed_complex_triangulator_3; // public: // // types of an iterator: // typedef std::forward_iterator_tag iterator_category; // typedef Vertex value_type; // typedef std::ptrdiff_t difference_type; // typedef value_type* pointer; // typedef value_type& reference; // Vertex_iterator(Symb_vertex_map_const_it it, Symb_vertex_map_const_it end) : // it(it), end(end) {} // Vertex_iterator(Symb_vertex_map_const_it end) : // it(end), end(end) {} // Vertex_iterator& operator++() { // do { ++it; } while (it != end && (it->first != it->second)); // return *this; // } // Vertex_iterator operator++(int) { // Vertex_iterator tmp(*this); // ++(*this); // return tmp; // } // reference operator*() const { return (it->first); } // pointer operator->() const { return (it->first); } // bool operator==(const Vertex_iterator other) { // return (other.it == it); // } // bool operator!=(const Vertex_iterator other) { // return !(other.it == it); // } // private: // Symb_vertex_map_const_it it, end; // }; public: Combinatorial_mixed_complex_triangulator_3(Regular const ®ular, bool verbose) : regular(regular), verbose(verbose), compute_anchor_obj(regular) { construct_vertices(); } void construct_vertices(); template void construct_vertices(OutputIteratorVertices vertices); Vertex_iterator vertices_begin() { return vertices.begin(); } Vertex_iterator vertices_end() { return vertices.end(); } Cell_iterator cells_begin() { return Cell_iterator(this); } Cell_iterator cells_end() { return Cell_iterator(this, 4); } template void construct_0_cell(Rt_Vertex_handle rt_vh, OutputIteratorCells out) const; template void construct_1_cell(const Rt_Edge &e, OutputIteratorCells out) const; template void construct_1_cell(Rt_Finite_edges_iterator eit, OutputIteratorCells out) const { construct_1_cell(*eit, out); } template void construct_2_cell(const Rt_Facet &f, OutputIteratorCells out) const; template void construct_2_cell(const Rt_Finite_facets_iterator &fit, OutputIteratorCells out) const { construct_2_cell(*fit, out); } template void construct_3_cell(Rt_Cell_handle rt_ch, OutputIteratorCells out) const; template typename Other_MixedComplexTraits_3::Bare_point location(const Vertex &v, const Other_MixedComplexTraits_3 &traits) const { typename Other_MixedComplexTraits_3::Bare_point p_del = orthocenter(v.first, traits); typename Other_MixedComplexTraits_3::Bare_point p_vor = orthocenter(v.second, traits); return traits.construct_anchor_point_3_object()(p_del, p_vor); } template typename Other_MixedComplexTraits_3::Bare_point location(const Vertex_handle vh, const Other_MixedComplexTraits_3 &traits) const { typename Other_MixedComplexTraits_3::Bare_point p_del = orthocenter(vh->first, traits); typename Other_MixedComplexTraits_3::Bare_point p_vor = orthocenter(vh->second, traits); typename Other_MixedComplexTraits_3::Bare_point result = traits.construct_anchor_point_3_object()(p_del, p_vor); return result; } template Bounded_side bounded_side(const typename Regular_traits::Bare_point &p, const Cell &c, const Other_MixedComplexTraits_3 &traits) const { typedef Other_MixedComplexTraits_3 Traits; typedef typename Traits::Bare_point::R::Tetrahedron_3 Tetrahedron; typedef Cartesian_converter< typename Regular_traits::Bare_point::R, typename Traits::Bare_point::R> Converter; typename Traits::Bare_point pts[5]; for (int i=0; i<4; i++) pts[i] = location(c[i], traits); pts[4] = Converter()(p); return Tetrahedron(pts[0],pts[1],pts[2],pts[3]).bounded_side(pts[4]); } private: template typename Other_MixedComplexTraits_3::Bare_point orthocenter(const Rt_Simplex &s, const Other_MixedComplexTraits_3 &traits) const { Weighted_converter_3 > converter; switch(s.dimension()) { case 0: { Rt_Vertex_handle vh = s; return converter(vh->point()); } case 1: { Rt_Edge e = s; return traits.construct_weighted_circumcenter_3_object() (converter(e.first->vertex(e.second)->point()), converter(e.first->vertex(e.third)->point())); } case 2: { Rt_Facet f = s; return traits.construct_weighted_circumcenter_3_object() (converter(f.first->vertex((f.second+1)&3)->point()), converter(f.first->vertex((f.second+2)&3)->point()), converter(f.first->vertex((f.second+3)&3)->point())); } case 3: { Rt_Cell_handle ch = s; return traits.construct_weighted_circumcenter_3_object() (converter(ch->vertex(0)->point()), converter(ch->vertex(1)->point()), converter(ch->vertex(2)->point()), converter(ch->vertex(3)->point())); } } CGAL_assertion(false); return typename Other_MixedComplexTraits_3::Weighted_point(); } Vertex_handle add_vertex(Symb_anchor anchor); template void add_cell(Vertex_handle vh[], int orient, Rt_Simplex &simplex, OutputIteratorCells cells) const; Vertex_handle get_vertex(Rt_Simplex &sDel, Rt_Simplex &sVor) const; void construct_anchor_del(Rt_Simplex const &sDel); void construct_anchor_vor(Rt_Simplex const &sVor); void construct_anchors(); const Rt_Simplex get_anchor_del(Rt_Simplex const &sDel) const { return find_anchor(anchor_del2, sDel)->first; } const Rt_Simplex get_anchor_vor(Rt_Simplex const &sVor) const { Anchor_map_const_iterator it = find_anchor(anchor_vor2, sVor); return it->first; } Anchor_map_const_iterator find_anchor(const Anchor_map &a_map, Rt_Simplex const&s) const { Anchor_map_const_iterator it = a_map.find(s); return find_anchor(a_map, it); } Anchor_map_const_iterator find_anchor(const Anchor_map &a_map, Anchor_map_const_iterator &start) const { CGAL_assertion(start != a_map.end()); Anchor_map_const_iterator it = start; while (it != it->second) it = it->second; return it; } Anchor_map_iterator find_anchor(Anchor_map &a_map, Anchor_map_iterator &start) { // do the union-find-trick: CGAL_assertion(start != a_map.end()); Anchor_map_iterator it1 = start; Anchor_map_iterator it2 = it1->second; while (it2 != it2->second) { it1->second = it2->second; // NGHK: changed the type for the map-iterator-hack it2->second = it1; it2 = it1->second; } return it2; } private: Regular const ®ular; bool verbose; Compute_anchor compute_anchor_obj; Anchor_map anchor_del2, anchor_vor2; Vertex_container vertices; }; template < class GT, class QuadraticSurface_3, class Cb = Triangulation_cell_base_3 > class Triangulated_mixed_complex_cell_3 : public Cb { public: typedef typename Cb::Triangulation_data_structure Triangulation_data_structure; typedef typename Triangulation_data_structure::Vertex_handle Vertex_handle; typedef typename Triangulation_data_structure::Cell_handle Cell_handle; typedef QuadraticSurface_3 Quadratic_surface; template < class TDS2 > struct Rebind_TDS { typedef typename Cb::template Rebind_TDS::Other Cb2; typedef Triangulated_mixed_complex_cell_3 Other; }; Triangulated_mixed_complex_cell_3() : Cb() { } Triangulated_mixed_complex_cell_3(Vertex_handle v0, Vertex_handle v1, Vertex_handle v2, Vertex_handle v3) : Cb(v0, v1, v2, v3) { } Quadratic_surface *surf; }; template < class GT, class Vb = Triangulation_vertex_base_3 > class Triangulated_mixed_complex_vertex_3 : public Vb { public: typedef typename Vb::Point Point; typedef typename Vb::Cell_handle Cell_handle; template < class TDS2 > struct Rebind_TDS { typedef typename Vb::template Rebind_TDS::Other Vb2; typedef Triangulated_mixed_complex_vertex_3 Other; }; Triangulated_mixed_complex_vertex_3() {} Triangulated_mixed_complex_vertex_3(const Point&p) : Vb(p) {} Triangulated_mixed_complex_vertex_3(const Point&p, Cell_handle c) : Vb(p, c) {} Sign sign() const { return Vb::cell()->surf->sign(Vb::point()); } }; template void Combinatorial_mixed_complex_triangulator_3:: construct_anchor_del(Rt_Simplex const &sDel) { Rt_Simplex s = compute_anchor_obj.anchor_del(sDel); anchor_del2[sDel] = Anchor_map_iterator(); Anchor_map_iterator it = anchor_del2.find(sDel); Anchor_map_iterator it2 = anchor_del2.find(s); CGAL_assertion(it != anchor_del2.end()); CGAL_assertion(it2 != anchor_del2.end()); it->second = it2; // degenerate simplices: if (compute_anchor_obj.is_degenerate()) { it = find_anchor(anchor_del2, it); typename Compute_anchor::Simplex_iterator degenerate_it; for (degenerate_it = compute_anchor_obj.equivalent_anchors_begin(); degenerate_it != compute_anchor_obj.equivalent_anchors_end(); degenerate_it++) { Anchor_map_iterator tmp; it2 = anchor_del2.find(*degenerate_it); CGAL_assertion(it2 != anchor_del2.end()); // Merge sets: while (it2 != it2->second) { tmp = it2->second; it2->second = it->second; it2 = tmp; CGAL_assertion(it2 != anchor_del2.end()); } it2->second = it->second; } } } template void Combinatorial_mixed_complex_triangulator_3:: construct_anchor_vor(Rt_Simplex const &sVor) { Rt_Simplex s = compute_anchor_obj.anchor_vor(sVor); anchor_vor2[sVor] = Anchor_map_iterator(); Anchor_map_iterator it = anchor_vor2.find(sVor); Anchor_map_iterator it2 = anchor_vor2.find(s); CGAL_assertion(it != anchor_vor2.end()); CGAL_assertion(it2 != anchor_vor2.end()); it->second = it2; // degenerate simplices: if (compute_anchor_obj.is_degenerate()) { it = find_anchor(anchor_vor2, it); typename Compute_anchor::Simplex_iterator degenerate_it; for (degenerate_it = compute_anchor_obj.equivalent_anchors_begin(); degenerate_it != compute_anchor_obj.equivalent_anchors_end(); degenerate_it++) { Anchor_map_iterator tmp; it2 = anchor_vor2.find(*degenerate_it); // Possibly not found for 2 Voronoi vertices with the same center, // If the first vertex is inserted and the second is already found. // see compute_anchor_obj.anchor_vor(Cell_handle) if (it2 != anchor_vor2.end()) { CGAL_assertion(it2 != anchor_vor2.end()); // Merge sets: while (it2 != it2->second) { tmp = it2->second; it2->second = it->second; it2 = tmp; CGAL_assertion(it2 != anchor_vor2.end()); } it2->second = it->second; } } } } template void Combinatorial_mixed_complex_triangulator_3:: construct_anchors() { Rt_Finite_vertices_iterator vit; Rt_Finite_edges_iterator eit; Rt_Finite_facets_iterator fit; Rt_Finite_cells_iterator cit; Rt_Simplex s; // Compute anchor points: for (vit=regular.finite_vertices_begin(); vit!=regular.finite_vertices_end(); vit++) { construct_anchor_del(Rt_Simplex(vit)); } for (eit=regular.finite_edges_begin(); eit!=regular.finite_edges_end(); eit++) { s = Rt_Simplex(*eit); construct_anchor_del(s); CGAL_assertion(s.dimension() == 1); } for (fit=regular.finite_facets_begin(); fit!=regular.finite_facets_end(); fit++) { s = Rt_Simplex(*fit); construct_anchor_del(s); CGAL_assertion(s.dimension() == 2); } for (cit=regular.finite_cells_begin(); cit!=regular.finite_cells_end(); cit++) { s = Rt_Simplex(cit); construct_anchor_del(s); construct_anchor_vor(s); CGAL_assertion(s.dimension() == 3); } for (fit=regular.finite_facets_begin(); fit!=regular.finite_facets_end(); fit++) { s = Rt_Simplex(*fit); construct_anchor_vor(s); CGAL_assertion(s.dimension() == 2); } for (eit=regular.finite_edges_begin(); eit!=regular.finite_edges_end(); eit++) { s = Rt_Simplex(*eit); construct_anchor_vor(s); CGAL_assertion(s.dimension() == 1); } for (vit=regular.finite_vertices_begin(); vit!=regular.finite_vertices_end(); vit++) { CGAL_assertion(vit->cell() != Rt_Cell_handle()); s = Rt_Simplex(vit); construct_anchor_vor(s); CGAL_assertion(s.dimension() == 0); } } // Constructs the vertices of the simplicial complex template void Combinatorial_mixed_complex_triangulator_3:: construct_vertices() { Rt_All_cells_iterator acit; Rt_Finite_cells_iterator cit; Rt_Finite_facets_iterator fit; Rt_Finite_edges_iterator eit; Rt_Finite_vertices_iterator vit; Rt_Cell_circulator ccir, cstart; Rt_Vertex_handle v1, v2, v3; Rt_Edge e; Rt_Cell_handle c1, c2; Rt_Simplex sDel, sVor; if (verbose) std::cout << "construct_anchors" << std::endl; construct_anchors(); if (verbose) std::cout << "9 "; // anchor dimDel=0, dimVor=3 for (cit=regular.finite_cells_begin(); cit!=regular.finite_cells_end(); cit++) { sVor = get_anchor_vor(Rt_Simplex(cit)); for (int i=0; i<4; i++) { sDel = get_anchor_del(Rt_Simplex(cit->vertex(i))); add_vertex(Symb_anchor(sDel,sVor)); } } if (verbose) std::cout << "8 "; // anchor dimDel=1, dimVor=3 for (cit = regular.finite_cells_begin(); cit != regular.finite_cells_end(); cit++) { sVor = get_anchor_vor(Rt_Simplex(cit)); for (int i=0; i<3; i++) { for (int j=i+1; j<4; j++) { sDel = get_anchor_del(Rt_Simplex(Rt_Edge(cit,i,j))); add_vertex(Symb_anchor(sDel,sVor)); } } } if (verbose) std::cout << "7 "; // anchor dimDel=2, dimVor=3 and dimDel=0, dimVor=2 for (fit = regular.finite_facets_begin(); fit != regular.finite_facets_end(); fit++) { // anchor dimDel=2, dimVor=3 c1 = fit->first; c2 = c1->neighbor(fit->second); sDel = get_anchor_del(*fit); if (!regular.is_infinite(c1)) { sVor = get_anchor_vor(c1); add_vertex(Symb_anchor(sDel,sVor)); } if (!regular.is_infinite(c2)) { sVor = get_anchor_vor(c2); add_vertex(Symb_anchor(sDel,sVor)); } // anchor dimDel=0, dimVor=2 sVor = get_anchor_vor(*fit); for (int i=1; i<4; i++) { sDel = get_anchor_del(Rt_Simplex(c1->vertex((fit->second+i)&3))); add_vertex(Symb_anchor(sDel,sVor)); } } if (verbose) std::cout << "6 "; // anchor dimDel=0, dimVor=1 for (eit=regular.finite_edges_begin(); eit!=regular.finite_edges_end(); eit++) { sVor = get_anchor_vor(*eit); v1 = eit->first->vertex(eit->second); v2 = eit->first->vertex(eit->third); sDel = get_anchor_del(v1); add_vertex(Symb_anchor(sDel,sVor)); sDel = get_anchor_del(v2); add_vertex(Symb_anchor(sDel,sVor)); } if (verbose) std::cout << "5 "; // anchor dimDel=3, dimVor=3 for (cit=regular.finite_cells_begin(); cit!=regular.finite_cells_end(); cit++) { sDel = get_anchor_del(Rt_Simplex(cit)); sVor = get_anchor_vor(Rt_Simplex(cit)); add_vertex(Symb_anchor(sDel,sVor)); } if (verbose) std::cout << "4 "; // anchor dimDel=0, dimVor=0 for (vit=regular.finite_vertices_begin(); vit!=regular.finite_vertices_end(); vit++) { sDel = get_anchor_del(Rt_Simplex(vit)); sVor = get_anchor_vor(Rt_Simplex(vit)); add_vertex(Symb_anchor(sDel,sVor)); } if (verbose) std::cout << "3 "; // anchor dimDel=1, dimVor=2 for (fit = regular.finite_facets_begin(); fit != regular.finite_facets_end(); fit++) { c1 = fit->first; c2 = c1->neighbor(fit->second); sVor = get_anchor_vor(Rt_Simplex(*fit)); for (int i=1; i<3; i++) { for (int j=i+1; j<4; j++) { e.first = c1; e.second = (fit->second+i)&3; e.third = (fit->second+j)&3; sDel = get_anchor_del(Rt_Simplex(e)); add_vertex(Symb_anchor(sDel,sVor)); } } } if (verbose) std::cout << "2 "; // anchor dimDel=2, dimVor=2 for (fit=regular.finite_facets_begin(); fit!=regular.finite_facets_end(); fit++) { c1 = fit->first; c2 = c1->neighbor(fit->second); sVor = get_anchor_vor(Rt_Simplex(*fit)); sDel = get_anchor_del(Rt_Simplex(*fit)); add_vertex(Symb_anchor(sDel,sVor)); } if (verbose) std::cout << "1" << std::endl; // anchor dimDel=1, dimVor=1 for (eit=regular.finite_edges_begin(); eit!=regular.finite_edges_end(); eit++) { v1 = eit->first->vertex(eit->second); v2 = eit->first->vertex(eit->third); sVor = get_anchor_vor(Rt_Simplex(*eit)); sDel = get_anchor_del(Rt_Simplex(*eit)); add_vertex(Symb_anchor(sDel,sVor)); } } // Constructs the vertices of the simplicial complex template template void Combinatorial_mixed_complex_triangulator_3:: construct_vertices(OutputIteratorVertices out) { for (Vertex_iterator it = vertices.begin(); it != vertices.end(); it++) { if (it->first == it->second) *out++ = *it; } } // Constructs the cells of the mixed complex corresponding // to Regular vertices template template void Combinatorial_mixed_complex_triangulator_3:: construct_0_cell(Rt_Vertex_handle rt_vh, OutputIteratorCells cells) const { Rt_Simplex sDel_v, sVor_v, sVor_e, sVor_f, sVor_c; Vertex_handle vh[4]; Rt_Simplex simplex(rt_vh); sDel_v = get_anchor_del(Rt_Simplex(rt_vh)); sVor_v = get_anchor_vor(Rt_Simplex(rt_vh)); vh[0] = get_vertex(sDel_v,sVor_v); std::list adj_cells; typename std::list::iterator adj_cell; regular.incident_cells(rt_vh, std::back_inserter(adj_cells)); // Construct cells: for (adj_cell = adj_cells.begin(); adj_cell != adj_cells.end(); adj_cell ++) { if (!regular.is_infinite(*adj_cell)) { sVor_c = get_anchor_vor(Rt_Simplex(*adj_cell)); vh[3] = get_vertex(sDel_v,sVor_c); int index = (*adj_cell)->index(rt_vh); for (int i=1; i<4; i++) { sVor_f = get_anchor_vor(Rt_Simplex(Rt_Facet(*adj_cell,(index+i)&3))); vh[2] = get_vertex(sDel_v,sVor_f); for (int j=1; j<4; j++) { if (j!=i) { sVor_e = get_anchor_vor(Rt_Simplex(Rt_Edge(*adj_cell,index,(index+j)&3))); vh[1] = get_vertex(sDel_v,sVor_e); if ((vh[0] != vh[1]) && (vh[1] != vh[2]) && (vh[2] != vh[3])) { CGAL_assertion(sVor_v != sVor_e); CGAL_assertion(sVor_e != sVor_f); CGAL_assertion(sVor_f != sVor_c); add_cell(vh,(index + (j==(i%3+1)? 1:0))&1, simplex, cells); } } } } } } } // Constructs 1-cells of the mixed complex corresponding to edges // of the regular triangulation template template void Combinatorial_mixed_complex_triangulator_3:: construct_1_cell(const Rt_Edge &e, OutputIteratorCells cells) const { Rt_Simplex sDel_v, sDel_e, sVor_e, sVor_f, sVor_c; Vertex_handle vh[4]; Rt_Vertex_handle v[2]; Rt_Simplex mixed_cell_simplex(e); sDel_e = get_anchor_del(Rt_Simplex(e)); sVor_e = get_anchor_vor(Rt_Simplex(e)); v[0] = e.first->vertex(e.second); v[1] = e.first->vertex(e.third); // Construct cells on the side of v[vi]: for (int vi=0; vi<2; vi++) { sDel_v = get_anchor_del(Rt_Simplex(v[vi])); if (!(sDel_v == sDel_e)) { Rt_Cell_circulator ccir, cstart; ccir = cstart = regular.incident_cells(e); do { if (!regular.is_infinite(ccir)) { int index0 = ccir->index(v[vi]); int index1 = ccir->index(v[1-vi]); sVor_c = get_anchor_vor(Rt_Simplex(ccir)); for (int fi=1; fi<4; fi++) { if (((index0+fi)&3) != index1) { sVor_f = get_anchor_vor(Rt_Simplex(Rt_Facet(ccir,(index0+fi)&3))); if ((sVor_c != sVor_f) && (sVor_f != sVor_e)) { vh[0] = get_vertex(sDel_v, sVor_e); vh[1] = get_vertex(sDel_e, sVor_e); vh[2] = get_vertex(sDel_e, sVor_f); vh[3] = get_vertex(sDel_e, sVor_c); int orient; if (((4+index1-index0)&3) == 1) { orient = (index1 + (fi==2))&1; } else { orient = (index1 + (fi==1))&1; } // vh: dimension are (01,11,12,13) add_cell(vh,orient,mixed_cell_simplex,cells); vh[1] = get_vertex(sDel_v, sVor_f); // vh: dimension are (01,02,12,13) add_cell(vh,1-orient,mixed_cell_simplex,cells); vh[2] = get_vertex(sDel_v, sVor_c); // vh: dimension are (01,02,03,13) add_cell(vh,orient,mixed_cell_simplex,cells); } } } } ccir ++; } while (ccir != cstart); } } } // Constructs 2-cells of the mixed complex corresponding to facets // of the regular triangulation template template void Combinatorial_mixed_complex_triangulator_3:: construct_2_cell(const Rt_Facet &f, OutputIteratorCells cells) const { Rt_Simplex sDel_v, sDel_e, sDel_f, sVor_f, sVor_c; Vertex_handle vh[4]; // Implicit function over vLabels is increasing ... Rt_Cell_handle rt_ch; int index; rt_ch = f.first; index = f.second; Rt_Simplex simplex(f); sDel_f = get_anchor_del(Rt_Simplex(f)); sVor_f = get_anchor_vor(Rt_Simplex(f)); for (int i=0; i<2; i++) { // Do this twice if (!regular.is_infinite(rt_ch)) { sVor_c = get_anchor_vor(Rt_Simplex(rt_ch)); vh[3] = get_vertex(sDel_f, sVor_c); Vertex_handle vh2 = get_vertex(sDel_f, sVor_f); if (vh2 != vh[3]) { // Facet and cell do not coincide .. for (int vi=1; vi<4; vi++) { sDel_v = get_anchor_del(Rt_Simplex(rt_ch->vertex((index+vi)&3))); //index_02[rt_ch].V[index][(index+vi)&3]; vh[0] = get_vertex(sDel_v, sVor_f); for (int ei=1; ei<4; ei++) { if (vi != ei) { vh[2] = vh2; int index0 = (index+vi)&3; int index1 = (index+ei)&3; int fi = (6+index-vi-ei)&3;//6-index-index0-index1; sDel_e = get_anchor_del(Rt_Simplex(Rt_Edge(rt_ch, index0, index1))); vh[1] = get_vertex(sDel_e, sVor_f); //index_12[rt_ch].V[index][(6+index-vi-ei)&3]; if ((vh[0] != vh[1]) && (vh[1] != vh[2])) { // index0: v0 // index1: v1 // index0+fi&3 == facet int orient; if (((4+index1-index0)&3) == 3) { orient = (index1 + (((4+index0-fi)&3)==2))&1; } else { orient = (index1 + (((4+index0-fi)&3)==1))&1; } add_cell(vh,orient,simplex,cells); vh[2] = get_vertex(sDel_e, sVor_c); add_cell(vh,1-orient,simplex,cells); vh[1] = get_vertex(sDel_v, sVor_c); add_cell(vh,orient,simplex,cells); } } } } } } // swap to the other cell Rt_Cell_handle ch_old = rt_ch; rt_ch = rt_ch->neighbor(index); index = rt_ch->index(ch_old); } CGAL_assertion(rt_ch == f.first); CGAL_assertion(index == f.second); } // Constructs 3-cells of the mixed complex corresponding to cells // of the regular triangulation template template void Combinatorial_mixed_complex_triangulator_3:: construct_3_cell(Rt_Cell_handle rt_ch, OutputIteratorCells cells) const { Rt_Simplex sDel_v, sDel_e, sDel_f, sDel_c, sVor_c; Vertex_handle vh[4]; // construct the tetrahedron: // C[ch], C[Facet(ch,fi)], C[Edge(ch,ei,vi)], C[ch->vertex(vi)] sDel_c = get_anchor_del(Rt_Simplex(rt_ch)); sVor_c = get_anchor_vor(Rt_Simplex(rt_ch)); Rt_Simplex simplex = Rt_Simplex(rt_ch); vh[0] = get_vertex(sDel_c, sVor_c); for (int fi=0; fi<4; fi++) { sDel_f = get_anchor_del(Rt_Simplex(Rt_Facet(rt_ch, fi))); vh[1] = get_vertex(sDel_f, sVor_c); if (vh[0] != vh[1]) { for (int vi=1; vi<4; vi++) { int index0 = (fi+vi)&3; sDel_v = get_anchor_del(Rt_Simplex(rt_ch->vertex(index0))); for (int ei=1; ei<4; ei++) { int index1 = (fi+ei)&3; if (vi != ei) { sDel_e = get_anchor_del(Rt_Simplex(Rt_Edge(rt_ch, index0, index1))); vh[2] = get_vertex(sDel_e, sVor_c); // index_13[rt_ch].V[edge_index[index0][index1]]; vh[3] = get_vertex(sDel_v, sVor_c); // index_03[rt_cit].V[index0]; if ((vh[1] != vh[2]) && (vh[2] != vh[3])) { int orient; if (((4+index1-index0)&3) == 1) { orient = (index1 + (vi==2))&1; } else { orient = (index1 + (vi==3))&1; } add_cell(vh, orient, simplex, cells); } } } } } } } // Adds a vertex to the simplicial complex template typename Combinatorial_mixed_complex_triangulator_3:: Vertex_handle Combinatorial_mixed_complex_triangulator_3:: add_vertex (Symb_anchor anchor) { Vertex_iterator vit = vertices.find(anchor); if (vit == vertices.end()) return &*(vertices.insert(anchor).first); return &*vit; } // Gets a vertex from the simplicial complex based on the anchors template typename Combinatorial_mixed_complex_triangulator_3:: Vertex_handle Combinatorial_mixed_complex_triangulator_3:: get_vertex (Rt_Simplex &sDel, Rt_Simplex &sVor) const { Rt_Simplex sDel2 = get_anchor_del(sDel); Rt_Simplex sVor2 = get_anchor_vor(sVor); CGAL_assertion(sDel == sDel2); CGAL_assertion(sVor == sVor2); Vertex_container_it it = vertices.find(Symb_anchor(sDel2,sVor2)); // Symb_vertex_map_const_it it = anchors.find(Symb_anchor(sDel2,sVor2)); CGAL_assertion(it != vertices.end()); Vertex_handle vh = &*it; CGAL_assertion(*vh != Vertex()); return vh; } // Adds a cell to the simplicial complex template template void Combinatorial_mixed_complex_triangulator_3:: add_cell(Vertex_handle vh[], int orient, Rt_Simplex &simplex, OutputIteratorCells cells) const { assert((orient==0) || (orient==1)); assert(*vh[0] != Vertex()); assert(*vh[1] != Vertex()); assert(*vh[2] != Vertex()); assert(*vh[3] != Vertex()); assert(*vh[0] != *vh[1]); assert(*vh[0] != *vh[2]); assert(*vh[0] != *vh[3]); assert(*vh[1] != *vh[2]); assert(*vh[1] != *vh[3]); assert(*vh[2] != *vh[3]); if (orient) { *cells++ = Cell(vh[0], vh[1], vh[2], vh[3], simplex); } else { *cells++ = Cell(vh[0], vh[1], vh[3], vh[2], simplex); } } template void triangulate_mixed_complex_3(MixedComplexTraits_3 &rt, typename MixedComplexTraits_3::Geom_traits::FT const & shrink_factor, OutputTriangulation_3 &tmc, TriangulatedMixedComplexObserver_3 &observer, bool verbose) { typedef MixedComplexTraits_3 Regular; typedef typename Regular::Finite_vertices_iterator Rt_Vertices_iterator; typedef typename Regular::Finite_edges_iterator Rt_Edges_iterator; typedef typename Regular::Finite_facets_iterator Rt_Facets_iterator; typedef typename Regular::Finite_cells_iterator Rt_Cells_iterator; typedef Triangulation_simplex_3 Rt_Simplex; typedef Combinatorial_mixed_complex_triangulator_3 CMCT; typedef typename CMCT::Vertex Cmct_Vertex; typedef typename CMCT::Vertex_handle Cmct_Vertex_handle; typedef typename CMCT::Cell Cmct_Cell; typedef typename CMCT::Vertex_iterator Cmct_Vertex_iterator; typedef Triangulation_incremental_builder_3 Triangulation_incremental_builder; typedef Skin_surface_traits_3 Mc_traits; typedef typename OutputTriangulation_3::Vertex_handle Out_Vertex_handle; typedef typename OutputTriangulation_3::Cell_handle Out_Cell_handle; CMCT mc_triangulator(rt, verbose); Triangulation_incremental_builder triangulation_incr_builder(tmc); std::map vertex_map; triangulation_incr_builder.begin_triangulation(3); { // Vertices if (verbose) std::cout << "Construct vertices" << std::endl; // std::list vertices; //std::list v2; //mc_triangulator.construct_vertices(std::back_inserter(vertices)); // { // NGHK: DEBUG CODE // Cmct_Vertex_iterator vit = mc_triangulator.vertices_begin(); // CGAL_assertion((int)std::distance(mc_triangulator.vertices_begin(), // mc_triangulator.vertices_end())== // (int)vertices.size()); // } for (Cmct_Vertex_iterator vit = mc_triangulator.vertices_begin(); vit != mc_triangulator.vertices_end(); vit++) { Out_Vertex_handle vh = triangulation_incr_builder.add_vertex(); vh->point() = mc_triangulator.location(*vit, Mc_traits(shrink_factor)); Cmct_Vertex_handle cmct_vh = &*vit; vertex_map[cmct_vh] = vh; observer.after_vertex_insertion((*vit).first, (*vit).second, vh); } } { // Cells std::vector cells; int nCells=0, nSimplices=0; // mixed cells corresponding to regular vertices if (verbose) std::cout << "Construct 0 cells" << std::endl; for (Rt_Vertices_iterator vit = rt.finite_vertices_begin(); vit != rt.finite_vertices_end(); vit ++) { mc_triangulator.construct_0_cell(vit, std::back_inserter(cells)); nCells += cells.size();nSimplices++; Rt_Simplex s(vit); for (typename std::vector::iterator it = cells.begin(); it != cells.end(); it++) { Out_Cell_handle ch = triangulation_incr_builder.add_cell(vertex_map[(it->vertex(0))], vertex_map[(it->vertex(1))], vertex_map[(it->vertex(2))], vertex_map[(it->vertex(3))]); observer.after_cell_insertion(s, ch); } cells.clear(); } // mixed cells corresponding to regular edges if (verbose) std::cout << "Construct 1 cells" << std::endl; for (Rt_Edges_iterator eit = rt.finite_edges_begin(); eit != rt.finite_edges_end(); eit ++) { mc_triangulator.construct_1_cell(eit, std::back_inserter(cells)); nCells += cells.size();nSimplices++; Rt_Simplex s(*eit); for (typename std::vector::iterator it = cells.begin(); it != cells.end(); it++) { Out_Cell_handle ch = triangulation_incr_builder.add_cell(vertex_map[(it->vertex(0))], vertex_map[(it->vertex(1))], vertex_map[(it->vertex(2))], vertex_map[(it->vertex(3))]); observer.after_cell_insertion(s, ch); } cells.clear(); } // mixed cells corresponding to regular facets if (verbose) std::cout << "Construct 2 cells" << std::endl; for (Rt_Facets_iterator fit = rt.finite_facets_begin(); fit != rt.finite_facets_end(); fit ++) { mc_triangulator.construct_2_cell(fit, std::back_inserter(cells)); nCells += cells.size();nSimplices++; Rt_Simplex s(*fit); for (typename std::vector::iterator it = cells.begin(); it != cells.end(); it++) { Out_Cell_handle ch = triangulation_incr_builder.add_cell(vertex_map[(it->vertex(0))], vertex_map[(it->vertex(1))], vertex_map[(it->vertex(2))], vertex_map[(it->vertex(3))]); observer.after_cell_insertion(s, ch); } cells.clear(); } // mixed cells corresponding to regular cells if (verbose) std::cout << "Construct 3 cells" << std::endl; for (Rt_Cells_iterator cit = rt.finite_cells_begin(); cit != rt.finite_cells_end(); cit ++) { mc_triangulator.construct_3_cell(cit, std::back_inserter(cells)); nCells += cells.size();nSimplices++; Rt_Simplex s(cit); for (typename std::vector::iterator it = cells.begin(); it != cells.end(); it++) { Out_Cell_handle ch = triangulation_incr_builder.add_cell(vertex_map[(it->vertex(0))], vertex_map[(it->vertex(1))], vertex_map[(it->vertex(2))], vertex_map[(it->vertex(3))]); observer.after_cell_insertion(s, ch); } cells.clear(); } CGAL_assertion(std::distance(mc_triangulator.cells_begin(), mc_triangulator.cells_end()) == nCells); } triangulation_incr_builder.end_triangulation(); // // mixed cells corresponding to regular edges // if (verbose) std::cout << "Construct 1 cells" << std::endl; // for (Rt_Finite_edges_iterator eit = regular.finite_edges_begin(); // eit != regular.finite_edges_end(); eit ++) { // construct_1_cell(eit, std::back_inserter(cells)); // } // // mixed cells corresponding to regular facets // if (verbose) std::cout << "Construct 2 cells" << std::endl; // for (Rt_Finite_facets_iterator fit = regular.finite_facets_begin(); // fit != regular.finite_facets_end(); fit ++) { // construct_2_cell(fit, std::back_inserter(cells)); // } // // mixed cells corresponding to regular cells // if (verbose) std::cout << "Construct 3 cells" << std::endl; // for (Rt_Finite_cells_iterator cit = regular.finite_cells_begin(); // cit != regular.finite_cells_end(); // cit++) { // construct_3_cell(cit, std::back_inserter(cells)); // } // triangulation_incr_builder.end_triangulation(); // anchors.clear(); // //remove_small_edges(); // { // NGHK: debug code: // CGAL_assertion(_tmc.is_valid()); // std::vector ch_vertices; // _tmc.incident_vertices(_tmc.infinite_vertex(), // std::back_inserter(ch_vertices)); // for (typename std::vector::iterator // vit = ch_vertices.begin(); vit != ch_vertices.end(); vit++) { // CGAL_assertion((*vit)->sign() == POSITIVE); // } // } } template < class MixedComplexTraits_3, class TriangulatedMixedComplex_3> void triangulate_mixed_complex_3(MixedComplexTraits_3 const ®ular, typename MixedComplexTraits_3::Geom_traits::FT const &shrink_factor, TriangulatedMixedComplex_3 &tmc, bool verbose) { Triangulated_mixed_complex_observer_3< TriangulatedMixedComplex_3, const MixedComplexTraits_3> observer(shrink_factor); triangulate_mixed_complex_3(regular, shrink_factor, tmc, observer, verbose); } CGAL_END_NAMESPACE #endif // CGAL_TRIANGULATE_MIXED_COMPLEX_H