// Copyright (c) 1997-2002,2005 Max-Planck-Institute Saarbruecken (Germany). // 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 // General Public License as published by the Free Software Foundation, // either version 3 of the License, or (at your option) any later version. // // 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$ // SPDX-License-Identifier: GPL-3.0+ // // // Author(s) : Michael Seel // Miguel Granados // Susan Hert // Lutz Kettner // Ralf Osbild // Peter Hachenberger #ifndef CGAL_NEF_POLYHEDRON_3_H #define CGAL_NEF_POLYHEDRON_3_H #include #include #include #include #include #include #include #include #include #include #include #ifdef CGAL_NEF_VISUAL_HULL #include #else #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // RO: includes for "vertex cycle to Nef" constructor #include #include #include #ifdef CGAL_NEF_VISUAL_HULL #include #endif #undef CGAL_NEF_DEBUG #define CGAL_NEF_DEBUG 11 #include namespace CGAL { template class Nef_polyhedron_3; template class Nef_polyhedron_3_rep; template std::ostream& operator<<(std::ostream& os, Nef_polyhedron_3& NP); template std::istream& operator>>(std::istream& os, Nef_polyhedron_3& NP); template class Nef_polyhedron_3_rep { typedef Nef_polyhedron_3_rep Self; friend class Nef_polyhedron_3; public: typedef CGAL::SNC_structure SNC_structure; typedef CGAL::SNC_decorator SNC_decorator; typedef CGAL::SNC_const_decorator SNC_const_decorator; typedef CGAL::Binary_operation Binary_operation; typedef CGAL::SNC_constructor SNC_constructor; typedef CGAL::SNC_external_structure SNC_external_structure; typedef CGAL::SNC_point_locator SNC_point_locator; typedef CGAL::SNC_simplify SNC_simplify; typedef CGAL::SNC_point_locator_by_spatial_subdivision SNC_point_locator_default; typedef typename SNC_structure::Sphere_map Sphere_map; typedef CGAL::SM_decorator SM_decorator; typedef CGAL::SM_const_decorator SM_const_decorator; typedef CGAL::SNC_SM_overlayer SM_overlayer; typedef CGAL::SM_point_locator SM_point_locator; private: SNC_structure snc_; SNC_point_locator* pl_; public: Nef_polyhedron_3_rep() : snc_(), pl_() {} ~Nef_polyhedron_3_rep() { CGAL_NEF_TRACEN( "Nef_polyhedron_3_rep: destroying SNC structure "<<&snc_<< ", point locator "<::Items, typename Mark_ = bool> class Nef_polyhedron_3 : public CGAL::Handle_for< Nef_polyhedron_3_rep >, public SNC_const_decorator > { public: /*{\Mtypes 7}*/ typedef Kernel_ Kernel; typedef Kernel_ Traits; typedef Items_ Items; typedef Mark_ Mark; typedef Nef_polyhedron_3 Self; typedef Nef_polyhedron_3 Nef_polyhedron; typedef Handle_for< Nef_polyhedron_3_rep > Base; typedef typename Kernel::Point_3 Point_3; typedef typename Kernel::Plane_3 Plane_3; typedef typename Kernel::Vector_3 Vector_3; typedef typename Kernel::Segment_3 Segment_3; typedef typename Kernel::Aff_transformation_3 Aff_transformation_3; #if (! defined _MSC_VER) || (_MSC_VER >= 1900) // VC++ < 2017 has a problem to digest the following typedef, // and does not need the using statements -- AF // The left and right part of these typedefs have the same name. It is // very important to qualify the left part with the CGAL:: namespace, no // to confuse g++. -- Laurent Rineau, 2010/09/13 typedef CGAL::SNC_structure SNC_structure; typedef CGAL::SNC_const_decorator SNC_const_decorator; using SNC_const_decorator::set_snc; using SNC_const_decorator::is_standard; using SNC_const_decorator::is_bounded; #endif struct Polylines_tag {}; struct Points_tag {}; enum Boundary { EXCLUDED=0, INCLUDED=1 }; /*{\Menum construction selection.}*/ typedef enum { EMPTY=0, COMPLETE=1 } Content; /*{\Menum construction selection}*/ typedef enum { DEFAULT, NAIVE, WALKING, SPATIAL_SUBDIVISION } Location_mode; /*{\Menum selection flag for the point location mode.}*/ protected: struct AND { Mark operator()(const Mark& b1, const Mark& b2, bool /* inverted */ =false)const { return b1&&b2; } }; struct OR { Mark operator()(const Mark& b1, const Mark& b2, bool /* inverted */ =false) const { return b1||b2; } }; struct DIFF { Mark operator()(const Mark& b1, const Mark& b2, bool inverted=false) const { return (inverted) ? !b1&&b2 : b1&&!b2 ; } }; struct XOR { Mark operator()(const Mark& b1, const Mark& b2, bool /* inverted */ =false) const { return (b1&&!b2)||(!b1&&b2); } }; public: typedef Nef_polyhedron_3_rep Nef_rep; typedef typename Nef_rep::SM_decorator SM_decorator; typedef typename Nef_rep::SM_const_decorator SM_const_decorator; protected: typedef typename Nef_rep::SNC_decorator SNC_decorator; typedef typename Nef_rep::SNC_constructor SNC_constructor; typedef typename Nef_rep::SNC_external_structure SNC_external_structure; typedef typename Nef_rep::Binary_operation Binary_operation; typedef typename Nef_rep::SNC_point_locator SNC_point_locator; typedef typename Nef_rep::SNC_point_locator_default SNC_point_locator_default; typedef CGAL::Combine_with_halfspace Combine_with_halfspace; public: enum Intersection_mode { CLOSED_HALFSPACE = Combine_with_halfspace::CLOSED_HALFSPACE, OPEN_HALFSPACE = Combine_with_halfspace::OPEN_HALFSPACE, PLANE_ONLY = Combine_with_halfspace::PLANE_ONLY}; protected: typedef typename Nef_rep::SM_overlayer SM_overlayer; typedef typename Nef_rep::SM_point_locator SM_point_locator; typedef typename Nef_rep::SNC_simplify SNC_simplify; typedef typename Nef_rep::Sphere_map Sphere_map; public: typedef CGAL::Nef_polyhedron_S2 Nef_polyhedron_S2; protected: SNC_structure& snc() { return this->ptr()->snc_; } const SNC_structure& snc() const { return this->ptr()->snc_; } SNC_point_locator*& pl() { return this->ptr()->pl_; } const SNC_point_locator* pl() const { return this->ptr()->pl_; } friend std::ostream& operator<< <> (std::ostream& os, Nef_polyhedron_3& NP); friend std::istream& operator>> <> (std::istream& is, Nef_polyhedron_3& NP); typedef typename SNC_decorator::Vertex_handle Vertex_handle; typedef typename SNC_decorator::Halfedge_handle Halfedge_handle; typedef typename SNC_decorator::Halffacet_handle Halffacet_handle; typedef typename SNC_decorator::Volume_handle Volume_handle; public: typedef typename SNC_structure::Sphere_point Sphere_point; typedef typename SNC_structure::Sphere_segment Sphere_segment; typedef typename SNC_structure::Sphere_circle Sphere_circle; typedef typename SNC_structure::Vertex_base Vertex; typedef typename SNC_structure::Halfedge_base Halfedge; typedef typename SNC_structure::Halffacet_base Halffacet; typedef typename SNC_structure::Volume_base Volume; typedef typename SNC_structure::Vertex_const_handle Vertex_const_handle; typedef typename SNC_structure::Halfedge_const_handle Halfedge_const_handle; typedef typename SNC_structure::Halffacet_const_handle Halffacet_const_handle; typedef typename SNC_structure::Volume_const_handle Volume_const_handle; typedef typename SNC_structure::SHalfedge_around_svertex_circulator SHalfedge_around_svertex_circulator; typedef typename SNC_structure::SHalfedge_around_svertex_const_circulator SHalfedge_around_svertex_const_circulator; typedef typename SNC_structure::SHalfedge_around_facet_circulator SHalfedge_around_facet_circulator; typedef typename SNC_structure::SHalfedge_around_facet_const_circulator SHalfedge_around_facet_const_circulator; typedef typename SNC_structure::SHalfedge_around_sface_const_circulator SHalfedge_around_sface_const_circulator; typedef typename SNC_structure::Halffacet_cycle_const_iterator Halffacet_cycle_const_iterator; typedef typename SNC_structure::Halffacet_cycle_iterator Halffacet_cycle_iterator; typedef typename SNC_structure::Infi_box Infi_box; typedef typename SNC_structure::Size_type Size_type; typedef Size_type size_type; typedef typename Kernel::RT RT; public: typedef typename SM_decorator::SVertex_handle SVertex_handle; typedef typename SM_decorator::SHalfedge_handle SHalfedge_handle; typedef typename SM_decorator::SFace_handle SFace_handle; typedef typename SM_decorator::SVertex_const_handle SVertex_const_handle; typedef typename SM_decorator::SHalfedge_const_handle SHalfedge_const_handle; typedef typename SM_decorator::SHalfloop_const_handle SHalfloop_const_handle; typedef typename SM_decorator::SFace_const_handle SFace_const_handle; typedef typename SNC_decorator::Vertex_iterator Vertex_iterator; typedef typename SNC_decorator::Halfedge_iterator Halfedge_iterator; typedef typename SNC_decorator::Halffacet_iterator Halffacet_iterator; typedef typename SNC_structure::Shell_entry_iterator Shell_entry_iterator; typedef typename SNC_decorator::Volume_iterator Volume_iterator; typedef typename SNC_structure::Vertex_const_iterator Vertex_const_iterator; typedef typename SNC_structure::Halfedge_const_iterator Halfedge_const_iterator; typedef typename SNC_structure::Halffacet_const_iterator Halffacet_const_iterator; typedef typename SNC_structure::Volume_const_iterator Volume_const_iterator; typedef typename SNC_structure::Shell_entry_const_iterator Shell_entry_const_iterator; typedef typename SM_decorator::SVertex_iterator SVertex_iterator; typedef typename SM_decorator::SHalfedge_iterator SHalfedge_iterator; typedef typename SM_decorator::SHalfloop_iterator SHalfloop_iterator; typedef typename SM_decorator::SFace_iterator SFace_iterator; typedef typename SM_decorator::SVertex_const_iterator SVertex_const_iterator; typedef typename SM_decorator::SHalfedge_const_iterator SHalfedge_const_iterator; typedef typename SM_decorator::SHalfloop_const_iterator SHalfloop_const_iterator; typedef typename SM_decorator::SFace_const_iterator SFace_const_iterator; typedef typename SNC_decorator::SFace_cycle_const_iterator SFace_cycle_const_iterator; typedef typename SNC_decorator::Association Association; protected: void initialize_infibox_vertices(Content space) { SNC_constructor C(snc()); Infi_box::initialize_infibox_vertices(C, space == COMPLETE); } void check_h_for_intersection_of_12_cube_edges_and_add_vertices (const Plane_3& p); void create_intersection_vertex_of_h_and_e(); void init_cube_vertices_depending_on_h(const Plane_3& p); void add_h_to_local_view_of_v(); public: void build_external_structure() { SNC_external_structure es(snc(), pl()); es.build_external_structure(); } public: /*{\Mcreation 3}*/ Nef_polyhedron_3( Content space = EMPTY); /*{\Mcreate creates an instance |\Mvar| of type |\Mname| and initializes it to the empty set if |space == EMPTY| and to the whole space if |space == COMPLETE|.}*/ explicit Nef_polyhedron_3(const Plane_3& p, Boundary b = INCLUDED); /*{\Mcreate creates a Nef polyhedron |\Mvar| containing the halfspace on the negative side of |p| including |p| if |b==INCLUDED|, excluding |p| if |b==EXCLUDED|.}*/ Nef_polyhedron_3(const Nef_polyhedron_3& N1) : Base(N1) , SNC_const_decorator() { set_snc(snc()); } Nef_polyhedron_3& operator=(const Nef_polyhedron_3& N1) { Base::operator=(N1); set_snc(snc()); return (*this); } ~Nef_polyhedron_3() { CGAL_NEF_TRACEN("~Nef_polyhedron_3: destructor called for snc "<<&snc()<< ", pl "< Nef_polyhedron_3 (II v_first, II v_last, const CGAL::Vector_3 &normal, bool verb = false) { CGAL_NEF_TRACEN("construction from vertex cycle (main part)"); // project and triangulate vertices, // convert result to Nef_polyhedron CGAL_precondition (!CGAL::is_empty_range (v_first, v_last)); bool is_nef = vertex_cycle_to_nef_3 (snc(), v_first, v_last, normal, verb); if (is_nef) { // TO DO: // Wie kann der eigene point_locator pl() eingebunden werden? // Wie kann der Konstruktor umgangen werden? typedef CGAL::SNC_point_locator_by_spatial_subdivision > Point_locator; Point_locator Pl; SNC_external_structure es(snc(), &Pl); es.build_external_structure(); *this = Nef_polyhedron(snc(), &Pl); } else { *this = Nef_polyhedron(); } set_snc (snc()); CGAL_expensive_postcondition (is_valid()); } // RO: "vertex cycle to Nef" constructor (normal computation) template Nef_polyhedron_3 (II v_first, II v_last, bool verb = false) { CGAL_NEF_TRACEN("construction from vertex cycle (normal computation)"); // compute normal vector CGAL_precondition (!CGAL::is_empty_range (v_first, v_last)); CGAL::Vector_3 normal; normal_vector_newell_3 (v_first, v_last, normal); // call "main" constructor *this = Nef_polyhedron_3 (v_first, v_last, normal, verb); set_snc (snc()); } template class Sphere_map_creator { typedef typename SNC_structure::SM_decorator SM_decorator; typedef typename SNC_structure::Vertex_handle Vertex_handle; typedef typename SNC_structure::SVertex_handle SVertex_handle; typedef typename SNC_structure::SFace_handle SFace_handle; typedef typename SNC_structure::Sphere_point Sphere_point; public: Sphere_map_creator() {} template void create_end_sphere_map(SNC_structure& snc, point_iterator cur, point_iterator prev) { Vertex_handle v(snc.new_vertex(*cur, true)); SM_decorator SM(&*v); SVertex_handle sv(v->new_svertex(Sphere_point(ORIGIN+(*prev-*cur)), true)); SFace_handle sf(v->new_sface()); SM.link_as_isolated_vertex(sv,sf); } template void create_sphere_map(SNC_structure& snc, point_iterator cur, point_iterator prev, point_iterator next) { Vertex_handle v(snc.new_vertex(*cur, true)); SM_decorator SM(&*v); SVertex_handle sv1(v->new_svertex(Sphere_point(ORIGIN+(*prev-*cur)), true)); SVertex_handle sv2(v->new_svertex(Sphere_point(ORIGIN+(*next-*cur)), true)); SFace_handle sf(v->new_sface()); SM.link_as_isolated_vertex(sv1,sf); SM.link_as_isolated_vertex(sv2,sf); } }; template class Sphere_map_creator { typedef typename SNC_structure::SM_decorator SM_decorator; typedef typename SNC_structure::Vertex_handle Vertex_handle; typedef typename SNC_structure::SVertex_handle SVertex_handle; typedef typename SNC_structure::SFace_handle SFace_handle; typedef typename SNC_structure::Sphere_point Sphere_point; bool first; int index; public: Sphere_map_creator() : first(true), index(0) {} template void create_end_sphere_map(SNC_structure& snc, point_iterator cur, point_iterator prev) { Vertex_handle v(snc.new_vertex(*cur, true)); SM_decorator SM(&*v); SVertex_handle sv(v->new_svertex(Sphere_point(ORIGIN+(*prev-*cur)), true)); SFace_handle sf(v->new_sface()); SM.link_as_isolated_vertex(sv,sf); if(first) { sv->set_index(); index = sv->get_index(); first = false; } else sv->set_index(index); } template void create_sphere_map(SNC_structure& snc, point_iterator cur, point_iterator prev, point_iterator next) { Vertex_handle v(snc.new_vertex(*cur, true)); SM_decorator SM(&*v); SVertex_handle sv1(v->new_svertex(Sphere_point(ORIGIN+(*prev-*cur)), true)); SVertex_handle sv2(v->new_svertex(Sphere_point(ORIGIN+(*next-*cur)), true)); SFace_handle sf(v->new_sface()); SM.link_as_isolated_vertex(sv1,sf); SM.link_as_isolated_vertex(sv2,sf); sv1->set_index(index); sv2->set_index(); index = sv2->get_index(); } }; template Nef_polyhedron_3(InputIterator begin, InputIterator end, Polylines_tag) { typedef typename std::iterator_traits::value_type point_iterator_pair; typedef typename point_iterator_pair::first_type point_iterator; empty_rep(); set_snc(snc()); initialize_infibox_vertices(EMPTY); point_iterator pbegin, pend, pnext, pprev; Sphere_map_creator smc; for(;begin != end; ++begin) { pend = begin->second; pprev = pnext = pbegin = begin->first; ++pnext; CGAL_assertion(pnext != pend); smc.create_end_sphere_map(snc(),pbegin,pnext); for(++pbegin,++pnext; pnext!=pend; ++pbegin,++pprev,++pnext) smc.create_sphere_map(snc(),pbegin,pprev,pnext); smc.create_end_sphere_map(snc(),pbegin,pprev); } build_external_structure(); simplify(); } explicit Nef_polyhedron_3(const Segment_3& s) { empty_rep(); set_snc(snc()); initialize_infibox_vertices(EMPTY); Sphere_map_creator smc; std::vector endpoints(2); endpoints[0]=s.source(); endpoints[1]=s.target(); smc.create_end_sphere_map(snc(),&endpoints[0],&endpoints[1]); smc.create_end_sphere_map(snc(),&endpoints[1],&endpoints[0]); build_external_structure(); simplify(); } template Nef_polyhedron_3(InputIterator begin, InputIterator end, Points_tag) { empty_rep(); set_snc(snc()); initialize_infibox_vertices(EMPTY); for(InputIterator it=begin; it!=end;++it) { Vertex_handle v(snc().new_vertex(*it, true)); SM_decorator SM(&*v); v->new_sface(); } build_external_structure(); simplify(); } explicit Nef_polyhedron_3(const Point_3& p) { empty_rep(); set_snc(snc()); initialize_infibox_vertices(EMPTY); Vertex_handle v(snc().new_vertex(p, true)); SM_decorator SM(&*v); v->new_sface(); build_external_structure(); simplify(); } template class T3, class T4 > Nef_polyhedron_3( CGAL::Polyhedron_3& P) { CGAL_NEF_TRACEN("construction from Polyhedron_3"); SNC_structure rsnc; *this = Nef_polyhedron_3(rsnc, new SNC_point_locator_default, false); initialize_infibox_vertices(EMPTY); polyhedron_3_to_nef_3 , SNC_structure>( P, snc()); build_external_structure(); simplify(); CGAL::Mark_bounded_volumes mbv(true); delegate(mbv); set_snc(snc()); } template explicit Nef_polyhedron_3(const PolygonMesh& pm) { CGAL_NEF_TRACEN("construction from PolygonMesh with internal index maps"); SNC_structure rsnc; *this = Nef_polyhedron_3(rsnc, new SNC_point_locator_default, false); initialize_infibox_vertices(EMPTY); polygon_mesh_to_nef_3(const_cast(pm), snc()); build_external_structure(); simplify(); CGAL::Mark_bounded_volumes mbv(true); delegate(mbv); set_snc(snc()); } template explicit Nef_polyhedron_3(const PolygonMesh& pm, const HalfedgeIndexMap& him, const FaceIndexMap& fim, typename boost::disable_if < boost::is_same >::type* = NULL // disambiguate with another constructor ) { CGAL_NEF_TRACEN("construction from PolygonMesh"); SNC_structure rsnc; *this = Nef_polyhedron_3(rsnc, new SNC_point_locator_default, false); initialize_infibox_vertices(EMPTY); polygon_mesh_to_nef_3(const_cast(pm), snc(), fim, him); build_external_structure(); simplify(); CGAL::Mark_bounded_volumes mbv(true); delegate(mbv); set_snc(snc()); } Nef_polyhedron_3(const Nef_polyhedron& N, SFace_const_iterator sf) { SNC_structure rsnc; *this = Nef_polyhedron_3(rsnc, new SNC_point_locator_default, false); initialize_infibox_vertices(EMPTY); shell_to_nef_3(N, sf, snc()); build_external_structure(); simplify(); CGAL::Mark_bounded_volumes mbv(true); delegate(mbv); set_snc(snc()); } protected: template class Triangulation_handler2 { typedef typename CGAL::Triangulation_vertex_base_2 Vb; typedef typename CGAL::Constrained_triangulation_face_base_2 Fb; typedef typename CGAL::Triangulation_data_structure_2 TDS; typedef typename CGAL::Constrained_triangulation_2 CT; typedef typename CT::Face_handle Face_handle; typedef typename CT::Vertex_handle CTVertex_handle; typedef typename CT::Finite_faces_iterator Finite_face_iterator; typedef typename CT::Edge Edge; CT ct; CGAL::Unique_hash_map visited; CGAL::Unique_hash_map ctv2v; Finite_face_iterator fi; Plane_3 supporting_plane; public: Triangulation_handler2(Halffacet_const_handle f) : visited(false), supporting_plane(f->plane()) { Halffacet_cycle_const_iterator fci; for(fci=f->facet_cycles_begin(); fci!=f->facet_cycles_end(); ++fci) { if(fci.is_shalfedge()) { SHalfedge_around_facet_const_circulator sfc(fci), send(sfc); CGAL_For_all(sfc,send) { CGAL_NEF_TRACEN(" insert point" << sfc->source()->source()->point()); CTVertex_handle ctv = ct.insert(sfc->source()->source()->point()); ctv2v[ctv] = sfc->source()->source(); } } } for(fci=f->facet_cycles_begin(); fci!=f->facet_cycles_end(); ++fci) { if(fci.is_shalfedge()) { SHalfedge_around_facet_const_circulator sfc(fci), send(sfc); CGAL_For_all(sfc,send) { CGAL_NEF_TRACEN(" insert constraint" << sfc->source()->source()->point() << "->" << sfc->source()->twin()->source()->point()); ct.insert_constraint(sfc->source()->source()->point(), sfc->source()->twin()->source()->point()); } } } CGAL_assertion(ct.is_valid()); CGAL_NEF_TRACEN("number of finite triangles " << ct.number_of_faces()); typename CT::Face_handle infinite = ct.infinite_face(); typename CT::Vertex_handle ctv = infinite->vertex(1); if(ct.is_infinite(ctv)) ctv = infinite->vertex(2); CGAL_assertion(!ct.is_infinite(ctv)); typename CT::Face_handle opposite; typename CT::Face_circulator vc(ctv,infinite); do { opposite = vc++; } while(!ct.is_constrained(typename CT::Edge(vc,vc->index(opposite)))); typename CT::Face_handle first = vc; CGAL_assertion(!ct.is_infinite(first)); traverse_triangulation(first, first->index(opposite)); fi = ct.finite_faces_begin(); } void traverse_triangulation(Face_handle f, int parent) { visited[f] = true; if(!ct.is_constrained(Edge(f,ct.cw(parent))) && !visited[f->neighbor(ct.cw(parent))]) { Face_handle child(f->neighbor(ct.cw(parent))); traverse_triangulation(child, child->index(f)); } if(!ct.is_constrained(Edge(f,ct.ccw(parent))) && !visited[f->neighbor(ct.ccw(parent))]) { Face_handle child(f->neighbor(ct.ccw(parent))); traverse_triangulation(child, child->index(f)); } } template bool get_next_triangle(Triangle_3& tr) { while(fi != ct.finite_faces_end() && visited[fi] == false) ++fi; if(fi == ct.finite_faces_end()) return false; tr = Triangle_3(fi->vertex(0)->point(), fi->vertex(1)->point(), fi->vertex(2)->point()); ++fi; return true; } bool same_orientation(Plane_3 p1) const { if(p1.a() != 0) return CGAL::sign(p1.a()) == CGAL::sign(supporting_plane.a()); if(p1.b() != 0) return CGAL::sign(p1.b()) == CGAL::sign(supporting_plane.b()); return CGAL::sign(p1.c()) == CGAL::sign(supporting_plane.c()); } template void handle_triangles(PIB& pib, Index& VI) { while(fi != ct.finite_faces_end() && visited[fi] == false) ++fi; while(fi != ct.finite_faces_end()) { Plane_3 plane(fi->vertex(0)->point(), fi->vertex(1)->point(), fi->vertex(2)->point()); pib.begin_facet(); if(same_orientation(plane)) { pib.add_vertex_to_facet(VI[ctv2v[fi->vertex(0)]]); pib.add_vertex_to_facet(VI[ctv2v[fi->vertex(1)]]); pib.add_vertex_to_facet(VI[ctv2v[fi->vertex(2)]]); } else { pib.add_vertex_to_facet(VI[ctv2v[fi->vertex(0)]]); pib.add_vertex_to_facet(VI[ctv2v[fi->vertex(2)]]); pib.add_vertex_to_facet(VI[ctv2v[fi->vertex(1)]]); } pib.end_facet(); do { ++fi; } while(fi != ct.finite_faces_end() && visited[fi] == false); } } }; template class Build_polyhedron : public CGAL::Modifier_base { class Visitor { typedef typename CGAL::Projection_traits_xy_3 XY; typedef typename CGAL::Projection_traits_yz_3 YZ; typedef typename CGAL::Projection_traits_xz_3 XZ; const Object_index& VI; Polyhedron_incremental_builder_3& B; const SNC_const_decorator& D; public: Visitor(Polyhedron_incremental_builder_3& BB, const SNC_const_decorator& sd, Object_index& vi) : VI(vi), B(BB), D(sd){} void visit(Halffacet_const_handle opposite_facet) { CGAL_NEF_TRACEN("Build_polyhedron: visit facet " << opposite_facet->plane()); CGAL_assertion(Infi_box::is_standard(opposite_facet->plane())); SHalfedge_const_handle se; Halffacet_cycle_const_iterator fc; Halffacet_const_handle f = opposite_facet->twin(); SHalfedge_around_facet_const_circulator sfc1(f->facet_cycles_begin()), sfc2(sfc1); if(++f->facet_cycles_begin() != f->facet_cycles_end() || ++(++(++sfc1)) != sfc2) { Vector_3 orth = f->plane().orthogonal_vector(); int c = CGAL::abs(orth[0]) > CGAL::abs(orth[1]) ? 0 : 1; c = CGAL::abs(orth[2]) > CGAL::abs(orth[c]) ? 2 : c; if(c == 0) { Triangulation_handler2 th(f); th.handle_triangles(B, VI); } else if(c == 1) { Triangulation_handler2 th(f); th.handle_triangles(B, VI); } else if(c == 2) { Triangulation_handler2 th(f); th.handle_triangles(B, VI); } else CGAL_error_msg( "wrong value"); } else { B.begin_facet(); fc = f->facet_cycles_begin(); se = SHalfedge_const_handle(fc); CGAL_assertion(se!=0); SHalfedge_around_facet_const_circulator hc_start(se); SHalfedge_around_facet_const_circulator hc_end(hc_start); CGAL_For_all(hc_start,hc_end) { CGAL_NEF_TRACEN(" add vertex " << hc_start->source()->center_vertex()->point()); B.add_vertex_to_facet(VI[hc_start->source()->center_vertex()]); } B.end_facet(); } } void visit(SFace_const_handle) {} void visit(Halfedge_const_handle) {} void visit(Vertex_const_handle) {} void visit(SHalfedge_const_handle) {} void visit(SHalfloop_const_handle) {} }; public: const SNC_const_decorator& scd; Object_index VI; Build_polyhedron(const SNC_const_decorator& s) : scd(s), VI(s.vertices_begin(),s.vertices_end(),'V') {} void operator()( HDS& hds) { Polyhedron_incremental_builder_3 B(hds, true); int skip_volumes; if(Infi_box::extended_kernel()) { B.begin_surface(scd.number_of_vertices()-8, scd.number_of_facets()-6, scd.number_of_edges()-12); skip_volumes = 2; } else { B.begin_surface(scd.number_of_vertices(), 2*scd.number_of_vertices()-4, 3*scd.number_of_vertices()-6); skip_volumes = 1; } int vertex_index = 0; Vertex_const_iterator v; CGAL_forall_vertices(v,scd) { if(Infi_box::is_standard(v->point())) { VI[v]=vertex_index++; B.add_vertex(v->point()); } } Visitor V(B,scd,VI); Volume_const_handle c; CGAL_forall_volumes(c,scd) if(skip_volumes-- <= 0) scd.visit_shell_objects(SFace_const_handle(c->shells_begin()),V); B.end_surface(); if ( B.error() ) B.rollback(); } }; template class Build_polyhedron2 : public CGAL::Modifier_base { class Find_holes { Unique_hash_map& omit_vertex; int nov, nof; public: Find_holes(Unique_hash_map& omit_vertex_) : omit_vertex(omit_vertex_), nov(0), nof(0) {} void visit(Halffacet_const_handle f) { ++nof; Halffacet_cycle_const_iterator fc = f->facet_cycles_begin(); for(++fc; fc != f->facet_cycles_end(); ++fc) { if(fc.is_shalfedge()) { --nof; SHalfedge_around_facet_const_circulator sfc(fc), send(sfc); CGAL_For_all(sfc, send) { omit_vertex[sfc->source()->source()] = true; --nov; } } else if(fc.is_shalfloop()) { SHalfloop_const_handle sl(fc); omit_vertex[sl->incident_sface()->center_vertex()]; --nov; } else CGAL_error_msg( "wrong handle type"); } } void visit(Vertex_const_handle) { ++nov; } void visit(SFace_const_handle) {} void visit(Halfedge_const_handle) {} void visit(SHalfedge_const_handle) {} void visit(SHalfloop_const_handle) {} int number_of_vertices() const { return nov; } int number_of_facets() const { return nof; } }; class Add_vertices { Polyhedron_incremental_builder_3& B; Unique_hash_map& omit_vertex; Object_index& VI; int vertex_index; public: Add_vertices(Polyhedron_incremental_builder_3& B_, Unique_hash_map& omit_vertex_, Object_index& VI_) : B(B_), omit_vertex(omit_vertex_), VI(VI_), vertex_index(0) {} void visit(Vertex_const_handle v) { if(omit_vertex[v]) return; VI[v]=vertex_index++; B.add_vertex(v->point()); } void visit(Halffacet_const_handle) {} void visit(SFace_const_handle) {} void visit(Halfedge_const_handle) {} void visit(SHalfedge_const_handle) {} void visit(SHalfloop_const_handle) {} }; class Visitor { const Object_index& VI; Polyhedron_incremental_builder_3& B; const Unique_hash_map& omit_vertex; SNC_const_decorator& D; public: Visitor(Polyhedron_incremental_builder_3& BB, const Unique_hash_map& omit_vertex_, SNC_const_decorator& sd, Object_index& vi) : VI(vi), B(BB), omit_vertex(omit_vertex_), D(sd){} void visit(Halffacet_const_handle opposite_facet) { CGAL_NEF_TRACEN("Build_polyhedron: visit facet " << opposite_facet->plane()); CGAL_assertion(Infi_box::is_standard(opposite_facet->plane())); SHalfedge_const_handle se; Halffacet_cycle_const_iterator fc; Halffacet_const_handle f = opposite_facet->twin(); fc = f->facet_cycles_begin(); se = SHalfedge_const_handle(fc); CGAL_assertion(se!=0); if(omit_vertex[se->source()->source()]) return; B.begin_facet(); SHalfedge_around_facet_const_circulator hc_start(se); SHalfedge_around_facet_const_circulator hc_end(hc_start); CGAL_For_all(hc_start,hc_end) { CGAL_NEF_TRACEN(" add vertex " << hc_start->source()->center_vertex()->point()); B.add_vertex_to_facet(VI[hc_start->source()->center_vertex()]); } B.end_facet(); } void visit(SFace_const_handle) {} void visit(Halfedge_const_handle) {} void visit(Vertex_const_handle) {} void visit(SHalfedge_const_handle) {} void visit(SHalfloop_const_handle) {} }; public: SFace_const_handle sf; SNC_const_decorator& scd; Object_index VI; Unique_hash_map omit_vertex; Build_polyhedron2(SFace_const_handle sf_, SNC_const_decorator& s) : sf(sf_), scd(s), VI(s.vertices_begin(),s.vertices_end(),'V'), omit_vertex(false) {} void operator()(HDS& hds) { Polyhedron_incremental_builder_3 B(hds, true); Find_holes F(omit_vertex); scd.visit_shell_objects(sf, F); B.begin_surface(F.number_of_vertices(), F.number_of_facets(), F.number_of_vertices()+F.number_of_facets()-2); Add_vertices A(B,omit_vertex, VI); scd.visit_shell_objects(sf, A); Visitor V(B,omit_vertex, scd,VI); scd.visit_shell_objects(sf, V); B.end_surface(); if ( B.error() ) B.rollback(); } }; public: void delegate( Modifier_base& modifier, bool compute_external = false, bool do_simplify = true) { // calls the `operator()' of the `modifier'. Precondition: The // `modifier' returns a consistent representation. if( this->is_shared()) clone_rep(); modifier(snc()); if(compute_external) { SNC_external_structure es(snc()); es.clear_external_structure(); build_external_structure(); } if(do_simplify) simplify(); CGAL_expensive_postcondition( is_valid()); } struct SNC_and_PL { SNC_structure* sncp; SNC_point_locator* pl; SNC_and_PL(SNC_structure* s, SNC_point_locator* p) : sncp(s), pl(p) {} }; void delegate( Modifier_base& modifier, bool compute_external = false, bool do_simplify = false) { // calls the `operator()' of the `modifier'. Precondition: The // `modifier' returns a consistent representation. if( this->is_shared()) clone_rep(); SNC_and_PL sncpl(&snc(),pl()); modifier(sncpl); pl() = sncpl.pl; if(compute_external) { SNC_external_structure es(snc()); es.clear_external_structure(); build_external_structure(); } if(do_simplify) simplify(); CGAL_expensive_postcondition( is_valid()); } public: template void convert_to_Polyhedron(Polyhedron& P) const { convert_to_polyhedron(P); } template void convert_to_polyhedron(Polyhedron& P) const { typedef typename Polyhedron::HalfedgeDS HalfedgeDS; CGAL_precondition(is_simple()); P.clear(); Build_polyhedron bp(*this); P.delegate(bp); } template void convert_inner_shell_to_polyhedron(SFace_const_iterator sf, Polyhedron& P) { typedef typename Polyhedron::HalfedgeDS HalfedgeDS; P.clear(); Build_polyhedron2 bp(sf, *this); P.delegate(bp); } bool is_valid( bool verb = false, int level = 0) { // checks the combinatorial consistency. Verbose_ostream verr(verb); verr << "begin CGAL::Nef_polyhedron_3<...>::is_valid( verb=true, " "level = " << level << "):" << std::endl; SNC_decorator D(snc()); bool valid = D.is_valid(verb, level); verr << "end of CGAL::Nef_polyhedron_3<...>::is_valid(): structure is " << ( valid ? "valid." : "NOT VALID.") << std::endl; return valid; } bool is_simple() const { Halfedge_const_iterator e; CGAL_forall_edges(e,snc()) if(!is_edge_2manifold(e)) return false; CGAL_NEF_TRACEN("there is no edge with non-manifold situation"); Vertex_const_iterator v; CGAL_forall_vertices(v,snc()) if(!is_vertex_2manifold(v)) return false; CGAL_NEF_TRACEN("there is no vertex with non-manifold situation"); /* Halffacet_iterator f; CGAL_forall_halffacets(f,snc()) if(!is_facet_simple(f)) return false; CGAL_NEF_TRACEN("there are no holes"); */ return true; } bool is_convex() const { Vertex_const_iterator v; CGAL_forall_vertices(v, *this) { SM_const_decorator SD(&*v); if(std::distance(SD.sfaces_begin(),SD.sfaces_end())!=2) return false; if(!Infi_box::is_standard(v->point())) continue; SFace_const_iterator sf; CGAL_forall_sfaces(sf,SD) { if(sf->volume() == Infi_box::getNirvana(snc())) continue; if(std::distance(sf->sface_cycles_begin(),sf->sface_cycles_end())!=1) return false; SFace_cycle_const_iterator sfi(sf->sface_cycles_begin()); if(!sfi.is_shalfedge()) return false; SHalfedge_const_handle se(sf->sface_cycles_begin()); SHalfedge_around_sface_const_circulator sec(se),send(sec); CGAL_For_all(sec,send) if(spherical_orientation(sec->source()->point(), sec->snext()->source()->point(), sec->snext()->snext()->source()->point())<0) { std::cerr << "vertex at " << v->point() << " is not convex" << std::endl; return false; } } } return true; } private: bool is_edge_2manifold(const Halfedge_const_handle& e) const { SM_decorator SD; SHalfedge_around_svertex_const_circulator c(SD.first_out_edge(e)), c2(c); if(c == 0) { CGAL_assertion(circulator_size(c) !=2); return false; } if(++c == c2){ CGAL_assertion(circulator_size(c) !=2); return false; } if(++c != c2) { CGAL_assertion(circulator_size(c) !=2); return false; } CGAL_assertion(circulator_size(c) == 2); return true; } bool is_vertex_2manifold(const Vertex_const_handle& v) const { SFace_const_iterator sfi(v->sfaces_begin()); if (++sfi != v->sfaces_last()) return false; return true; } bool is_facet_simple(const Halffacet_const_handle& f) const { bool found_first = false; Halffacet_cycle_const_iterator it; CGAL_forall_facet_cycles_of(it,f) if (found_first || !it.is_shalfedge()) return false; else found_first = true; return true; } public: void clear(Content space = EMPTY) { *this = Nef_polyhedron_3(space); } /*{\Mop makes |\Mvar| the empty set if |space == EMPTY| and the full space if |space == COMPLETE|.}*/ bool is_empty() const { /*{\Mop returns true if |\Mvar| is empty, false otherwise.}*/ if(Infi_box::extended_kernel()) return this->number_of_vertices() == 8 && this->number_of_edges() == 12 && this->number_of_facets() == 6 && this->number_of_volumes() == 2 && (++this->volumes_begin())->mark() == false; else return this->number_of_vertices() == 0 && this->number_of_edges() == 0 && this->number_of_facets() == 0 && this->number_of_volumes() == 1 && (this->volumes_begin())->mark() == false; } bool is_space() const { /*{\Mop returns true if |\Mvar| is the whole space, false otherwise.}*/ if(Infi_box::extended_kernel()) return this->number_of_vertices() == 8 && this->number_of_edges() == 12 && this->number_of_facets() == 6 && this->number_of_volumes() == 2 && (++this->volumes_begin())->mark() == true; else return this->number_of_vertices() == 0 && this->number_of_edges() == 0 && this->number_of_facets() == 0 && this->number_of_volumes() == 1 && (this->volumes_begin())->mark() == true; } /*{\Xtext \headerline{Destructive Operations}}*/ protected: void clone_rep() { *this = Nef_polyhedron_3(snc(), pl()); } void empty_rep() { SNC_structure rsnc; delete pl(); *this = Nef_polyhedron_3(rsnc, new SNC_point_locator_default,false); } public: Nef_polyhedron_3( const SNC_structure& W, SNC_point_locator* _pl = new SNC_point_locator_default, bool clone_pl = true, bool clone_snc = true); /*{\Xcreate makes |\Mvar| a new object. If |cloneit==true| then the underlying structure of |W| is copied into |\Mvar|.}*/ // TODO: granados: define behavior when clone=false /*{\Moperations 4 3 }*/ void simplify() { SNC_simplify simp(snc()); bool simplified = simp.simplify(); CGAL_NEF_TRACEN( "simplify(): structure simplified? "< V(false, snc().number_of_vertices()); Unique_hash_map E(false, snc().number_of_halfedges()); Unique_hash_map F(false, snc().number_of_halffacets()); Vertex_iterator v; Halfedge_iterator e; Halffacet_iterator f; CGAL_forall_vertices( v, snc()) V[Vertex_handle(v)] = true; CGAL_forall_halfedges( e, snc()) E[Halfedge_handle(e)] = true; CGAL_forall_halffacets( f, snc()) F[Halffacet_handle(f)] = true; bool updated = pl()->update( V, E, F); CGAL_NEF_TRACEN("simplify(): point locator structure updated? " << updated); #else SNC_point_locator* old_pl = pl(); pl() = pl()->clone(); pl()->initialize(&snc()); delete old_pl; #endif } } public: Nef_polyhedron_S2 get_sphere_map(Vertex_const_handle v) const { return Nef_polyhedron_S2(*v); } void extract_complement(); /*{\Xop converts |\Mvar| to its complement. }*/ void extract_interior(); /*{\Xop converts |\Mvar| to its interior. }*/ void extract_boundary(); /*{\Xop converts |\Mvar| to its boundary. }*/ void extract_closure() /*{\Xop converts |\Mvar| to its closure. }*/ { CGAL_NEF_TRACEN("extract closure"); if( this->is_shared()) clone_rep(); extract_complement(); extract_interior(); extract_complement(); } void extract_regularization() /*{\Xop converts |\Mvar| to its regularization. }*/ { CGAL_NEF_TRACEN("extract regularization"); if( this->is_shared()) clone_rep(); extract_interior(); extract_closure(); } /*{\Mtext \headerline{Constructive Operations}}*/ Nef_polyhedron_3 complement() const /*{\Mop returns the complement of |\Mvar| in the plane. }*/ { Nef_polyhedron_3 res = *this; res.extract_complement(); return res; } Nef_polyhedron_3 interior() const /*{\Mop returns the interior of |\Mvar|. }*/ { Nef_polyhedron_3 res = *this; res.extract_interior(); return res; } Nef_polyhedron_3 closure() const /*{\Mop returns the closure of |\Mvar|. }*/ { Nef_polyhedron_3 res = *this; res.extract_closure(); return res; } Nef_polyhedron_3 boundary() const /*{\Mop returns the boundary of |\Mvar|. }*/ { Nef_polyhedron_3 res = *this; res.extract_boundary(); return res; } Nef_polyhedron_3 regularization() const /*{\Mop returns the regularized polyhedron (closure of the interior).}*/ { Nef_polyhedron_3 res = *this; res.extract_regularization(); return res; } Nef_polyhedron_3 intersection(const Nef_polyhedron_3& N1) const /*{\Mop returns |\Mvar| $\cap$ |N1|. }*/ { CGAL_NEF_TRACEN(" intersection between nef3 "<<&*this<<" and "<<&N1); if (is_empty()) return *this; if (N1.is_empty()) return N1; if (is_space()) return N1; if (N1.is_space()) return *this; AND _and; SNC_structure rsnc; Nef_polyhedron_3 res(rsnc, new SNC_point_locator_default, false); Binary_operation bo( res.snc()); bo(res.pl(), snc(), pl(), N1.snc(), N1.pl(), _and); return res; } Nef_polyhedron_3 intersection(const Plane_3& plane, Intersection_mode im) const { AND _and; SNC_structure rsnc; Nef_polyhedron_3 res(rsnc, new SNC_point_locator_default, false); Combine_with_halfspace cwh(res.snc(), res.pl()); cwh.combine_with_halfspace(snc(), plane, _and, static_cast(im)); return res; } Nef_polyhedron_3 join(const Nef_polyhedron_3& N1) const /*{\Mop returns |\Mvar| $\cup$ |N1|. }*/ { CGAL_NEF_TRACEN(" join between nef3 "<<&*this<<" and "<<&N1); if (is_empty()) return N1; if (N1.is_empty()) return *this; if (is_space()) return *this; if (N1.is_space()) return N1; OR _or; //CGAL::binop_intersection_tests_allpairs tests_impl; SNC_structure rsnc; Nef_polyhedron_3 res(rsnc, new SNC_point_locator_default, false); Binary_operation bo(res.snc()); bo(res.pl(), snc(), pl(), N1.snc(), N1.pl(), _or); return res; } Nef_polyhedron_3 difference(const Nef_polyhedron_3& N1) const /*{\Mop returns |\Mvar| $-$ |N1|. }*/ { CGAL_NEF_TRACEN(" difference between nef3 "<<&*this<<" and "<<&N1); if (is_empty()) return *this; if (N1.is_empty()) return *this; if (is_space()) return N1.complement(); if (N1.is_space()) return Nef_polyhedron_3(EMPTY); DIFF _diff; //CGAL::binop_intersection_tests_allpairs tests_impl; SNC_structure rsnc; Nef_polyhedron_3 res(rsnc, new SNC_point_locator_default, false); Binary_operation bo(res.snc()); bo(res.pl(), snc(), pl(), N1.snc(), N1.pl(), _diff); return res; } Nef_polyhedron_3 symmetric_difference(const Nef_polyhedron_3& N1) const /*{\Mop returns the symmectric difference |\Mvar - T| $\cup$ |T - \Mvar|. }*/ { CGAL_NEF_TRACEN(" symmetic difference between nef3 "<<&*this<<" and "<<&N1); if (is_empty()) return N1; if (N1.is_empty()) return *this; if (is_space()) return Nef_polyhedron_3(EMPTY); if (N1.is_space()) return Nef_polyhedron_3(EMPTY); XOR _xor; //CGAL::binop_intersection_tests_allpairs tests_impl; SNC_structure rsnc; Nef_polyhedron_3 res(rsnc, new SNC_point_locator_default, false); Binary_operation bo(res.snc()); bo(res.pl(), snc(), pl(), N1.snc(), N1.pl(), _xor); return res; } /*{\Mtext Additionally there are operators |*,+,-,^,!| which implement the binary operations \emph{intersection}, \emph{union}, \emph{difference}, \emph{symmetric difference}, and the unary operation \emph{complement}. There are also the corresponding modification operations |*=,+=,-=,^=|.}*/ Nef_polyhedron_3 operator*(const Nef_polyhedron_3& N1) const { return intersection(N1); } Nef_polyhedron_3 operator+(const Nef_polyhedron_3& N1) const { return join(N1); } Nef_polyhedron_3 operator-(const Nef_polyhedron_3& N1) const { return difference(N1); } Nef_polyhedron_3 operator^(const Nef_polyhedron_3& N1) const { return symmetric_difference(N1); } Nef_polyhedron_3 operator!() const { return complement(); } Nef_polyhedron_3& operator*=(const Nef_polyhedron_3& N1) { #ifdef CGAL_NEF_VISUAL_HULL CGAL_NEF_SETDTHREAD(19*43*71); std::cerr << "visual hull code " << std::endl; std::cerr << *this << std::endl; std::cerr << const_cast(N1) << std::endl; AND _and; typename CGAL::Modifying_binary_operation mbo(this->snc()); mbo(const_cast(N1.snc()), N1.pl(), pl(), _and); return *this; #else *this = intersection(N1); return *this; #endif } Nef_polyhedron_3& operator+=(const Nef_polyhedron_3& N1) { *this = join(N1); return *this; } Nef_polyhedron_3& operator-=(const Nef_polyhedron_3& N1) { *this = difference(N1); return *this; } Nef_polyhedron_3& operator^=(const Nef_polyhedron_3& N1) { *this = symmetric_difference(N1); return *this; } /*{\Mtext There are also comparison operations like |<,<=,>,>=,==,!=| which implement the relations subset, subset or equal, superset, superset or equal, equality, inequality.}*/ bool operator==(const Nef_polyhedron_3& N1) const { CGAL_NEF_TRACEN(" equality comparision between nef3 "<<&*this<<" and "<<&N1); return symmetric_difference(N1).is_empty(); } bool operator!=(const Nef_polyhedron_3& N1) const { CGAL_NEF_TRACEN(" inequality comparision between nef3 "<<&*this<<" and "<<&N1); return !operator==(N1); } bool operator<(const Nef_polyhedron_3& N1) const { return !N1.difference(*this).is_empty() && difference(N1).is_empty(); } bool operator>(const Nef_polyhedron_3& N1) const { return difference(*this).is_empty() && !difference(N1).is_empty(); } bool operator<=(const Nef_polyhedron_3& N1) const { return difference(N1).is_empty(); } bool operator>=(const Nef_polyhedron_3& N1) const { return N1.difference(*this).is_empty(); } bool is_90degree_rotation(const Aff_transformation_3& aff) const { if(aff.hm(0,3) != 0) return false; if(aff.hm(1,3) != 0) return false; if(aff.hm(2,3) != 0) return false; if(CGAL_NTS abs(aff.hm(0,0)) + CGAL_NTS abs(aff.hm(0,1)) + CGAL_NTS abs(aff.hm(0,2)) != aff.hm(3,3)) return false; if(CGAL_NTS abs(aff.hm(1,0)) + CGAL_NTS abs(aff.hm(1,1)) + CGAL_NTS abs(aff.hm(1,2)) != aff.hm(3,3)) return false; if(CGAL_NTS abs(aff.hm(2,0)) + CGAL_NTS abs(aff.hm(2,1)) + CGAL_NTS abs(aff.hm(2,2)) != aff.hm(3,3)) return false; if(CGAL_NTS abs(aff.hm(0,0)) + CGAL_NTS abs(aff.hm(1,0)) + CGAL_NTS abs(aff.hm(2,0)) != aff.hm(3,3)) return false; if(CGAL_NTS abs(aff.hm(0,1)) + CGAL_NTS abs(aff.hm(1,1)) + CGAL_NTS abs(aff.hm(2,1)) != aff.hm(3,3)) return false; if(CGAL_NTS abs(aff.hm(0,2)) + CGAL_NTS abs(aff.hm(1,2)) + CGAL_NTS abs(aff.hm(2,2)) != aff.hm(3,3)) return false; return true; } bool is_scaling(const Aff_transformation_3& aff) const { if(aff.hm(0,3) != 0) return false; if(aff.hm(1,3) != 0) return false; if(aff.hm(2,3) != 0) return false; if(aff.hm(0,1) != 0) return false; if(aff.hm(0,2) != 0) return false; if(aff.hm(1,0) != 0) return false; if(aff.hm(1,2) != 0) return false; if(aff.hm(2,0) != 0) return false; if(aff.hm(2,1) != 0) return false; if(aff.hm(0,0) != aff.hm(1,1)) return false; if(aff.hm(0,0) != aff.hm(2,2)) return false; return true; } void change_orientation(bool full = false) { Halffacet_handle ftemp; Volume_handle vtemp; SVertex_handle svtemp; SHalfedge_handle setemp; SFace_handle sftemp; SVertex_iterator sv; CGAL_forall_svertices(sv, snc()) { if (!sv->is_isolated()) sv->out_sedge() = sv->out_sedge()->twin(); } SHalfedge_iterator se; CGAL_forall_shalfedges(se, snc()) { if(se->is_twin()) { svtemp = se->source(); se->source() = se->twin()->source(); se->twin()->source() = svtemp; if(full) { ftemp = se->facet(); se->facet() = se->twin()->facet(); se->twin()->facet() = ftemp; } // sftemp = se->incident_sface(); // se->incident_sface() = se->twin()->incident_sface(); // se->twin()->incident_sface() = sftemp; } setemp = se->sprev(); se->sprev() = se->snext(); se->snext() = setemp; se->circle() = se->circle().opposite(); if(full) { setemp = se->prev(); se->prev() = se->next(); se->next() = setemp; } } if(full) { Halffacet_iterator f; CGAL_forall_facets(f, snc()) { vtemp = f->incident_volume(); f->incident_volume() = f->twin()->incident_volume(); f->twin()->incident_volume() = vtemp; Halffacet_cycle_iterator fc(f->facet_cycles_begin()), fct(f->twin()->facet_cycles_begin()); while(fc!=f->facet_cycles_end()) { CGAL_assertion(fct!=f->twin()->facet_cycles_end()); if(fc.is_shalfedge()) { CGAL_assertion(fct.is_shalfedge()); setemp = fc; *fc = *fct; *fct = make_object(setemp); } ++fc; ++fct; } } CGAL_forall_halffacets(f, snc()) { Halffacet_cycle_iterator fc(f->facet_cycles_begin()); for(;fc!=f->facet_cycles_end();++fc) { if(fc.is_shalfedge()) { setemp = fc; SHalfedge_around_facet_circulator hfc(setemp),hend(hfc); ++hfc; CGAL_For_all(hfc,hend) { if ( CGAL::lexicographically_xyz_smaller(hfc->source()->source()->point(), setemp->source()->source()->point())) setemp = hfc; } *fc = make_object(setemp); } } } } } void transform( const Aff_transformation_3& aff) { if( this->is_shared()) clone_rep(); // only linear transform for the origin-centered sphere maps Aff_transformation_3 linear( aff.hm(0,0), aff.hm(0,1), aff.hm(0,2), aff.hm(1,0), aff.hm(1,1), aff.hm(1,2), aff.hm(2,0), aff.hm(2,1), aff.hm(2,2), aff.hm(3,3)); SNC_constructor cstr(snc()); std::list vertex_list; std::list corner_list; std::list delete_list; typename std::list::iterator li; typename std::list::iterator li2; bool ninety = is_90degree_rotation(aff); bool scale = is_scaling(aff); Vertex_iterator vi; CGAL_forall_vertices( vi, snc()) { CGAL_NEF_TRACEN("transform vertex "); if(scale) { if(is_standard(vi)) vi->point() = vi->point().transform( aff); else if(!Infi_box::is_infibox_corner(vi->point())) { vi->point() = normalized(Infi_box::normalize_transformed_vertex(vi->point().transform(aff))); } } else if (!is_standard(vi) && !ninety) { if(Infi_box::is_infibox_corner(vi->point())) corner_list.push_back(vi); vertex_list.push_back(vi); } else { vi->point() = vi->point().transform( aff); SM_decorator sdeco(&*vi); sdeco.transform( linear); } } if(!this->is_bounded() && !ninety && !scale) { Halffacet_iterator fi; CGAL_forall_facets(fi, snc()) { if(!is_standard(fi) || is_bounded(fi)) continue; Plane_3 pt = fi->plane(); pt = pt.transform(aff); std::list points(Infi_box::find_points_of_box_with_plane(cstr,pt)); std::list newVertices; newVertices = Infi_box::create_vertices_on_infibox(cstr, pt, points, fi->mark(), fi->twin()->incident_volume()->mark(), fi->incident_volume()->mark()); for(li = newVertices.begin(); li != newVertices.end(); ++li) { if(Infi_box::is_infibox_corner((*li)->point())) { li2 = corner_list.begin(); while(li2 != corner_list.end() && (*li2)->point() != (*li)->point()) ++li2; CGAL_assertion(li2 != corner_list.end()); delete_list.push_back(*li2); *li2 = *li; } } } for(li = vertex_list.begin(); li != vertex_list.end();++li) { SM_decorator SD(&**li); if(Infi_box::is_complex_facet_infibox_intersection(**li)) { Halffacet_handle hf[2]; int i=0; SHalfedge_iterator sei; CGAL_forall_sedges(sei,SD) { if(!Infi_box::is_sedge_on_infibox(sei)) { hf[i] = sei->facet(); if(hf[i]->is_twin()) hf[i] = hf[i]->twin(); ++i; } if(i>1) break; } } } Association A; SNC_external_structure es(snc()); es.clear_external_structure(); for(li = vertex_list.begin(); li != vertex_list.end();++li){ if(Infi_box::is_complex_facet_infibox_intersection(**li)) { Vertex_handle v2; Vertex_handle v1 = cstr.create_for_infibox_overlay(*li); v1->point() = normalized(Infi_box::normalize_transformed_vertex((*li)->point().transform(aff))); SM_decorator sdeco(&*v1); sdeco.transform(linear); switch(Infi_box::type_of_infibox_point(v1->point())) { case 1: v2 = cstr.create_from_point_on_infibox_facet(v1->point()); break; case 2: v2 = cstr.create_from_point_on_infibox_edge(v1->point()); break; case 3: v2 = cstr.create_from_point_on_infibox_vertex(v1->point()); li2 = corner_list.begin(); while(li2 != corner_list.end() && (*li2)->point() != v2->point()) ++li2; if(li2 != corner_list.end()) delete_list.push_back(*li2); break; default: CGAL_error_msg( "wrong value"); } Vertex_handle v = snc().new_vertex(v1->point(), (*li)->mark()); SM_overlayer O(&*v); O.subdivide(&*v1, &*v2, A); AND _and; O.select(_and); O.simplify(A); snc().delete_vertex(v1); snc().delete_vertex(v2); } if(Infi_box::is_infibox_corner((*li)->point())) { SM_decorator SD(&**li); if(SD.number_of_svertices() < 4) continue; li2 = corner_list.begin(); while(li2 != corner_list.end() && (*li2)->point() != (*li)->point()) ++li2; CGAL_assertion(li2 != corner_list.end()); if(*li == *li2) { delete_list.push_back(*li2); *li2 = cstr.create_from_point_on_infibox_vertex((*li)->point()); } } else snc().delete_vertex(*li); } for(li = delete_list.begin(); li != delete_list.end(); ++li) snc().delete_vertex(*li); if(!aff.is_even()) change_orientation(); while(cstr.erase_redundant_vertices()) ; cstr.correct_infibox_sedge_marks(); build_external_structure(); cstr.correct_infibox_sface_marks(); // are the upcoming lines necessary? SNC_point_locator* old_pl = pl(); pl() = pl()->clone(); pl()->initialize(&snc()); delete old_pl; } else { Halffacet_iterator fi; CGAL_forall_halffacets(fi,snc()) { if(is_standard(fi) || ninety) { fi->plane() = fi->plane().transform( aff); #ifdef CGAL_NEF3_FACET_WITH_BOX typedef typename Halffacet::Box Box; bool first = true; Halffacet_cycle_iterator cycle_it = fi->facet_cycles_begin(); if( cycle_it.is_shalfedge() ) { SHalfedge_iterator edge_it(cycle_it); SHalfedge_around_facet_circulator start( edge_it ), end( edge_it ); CGAL_For_all( start, end ) { const Point_3& p = start->source()->source()->point(); typename Kernel::FT q[3]; q[0] = p.x(); q[1] = p.y(); q[2] = p.z(); if(first) { fi->b = Box(q,q); first = false; } else fi->b.extend(q); } } else CGAL_error_msg( "is facet first cycle a SHalfloop?"); #endif } } if(!aff.is_even()) change_orientation(true); if(aff.homogeneous(0,1) != 0 || aff.homogeneous(0,2) != 0 || aff.homogeneous(1,0) != 0 || aff.homogeneous(1,2) != 0 || aff.homogeneous(2,0) != 0 || aff.homogeneous(2,1) != 0 || aff.homogeneous(0,0) != aff.homogeneous(1,1) || aff.homogeneous(0,0) != aff.homogeneous(2,2) || !this->is_bounded()) { SNC_point_locator* old_pl = pl(); pl() = pl()->clone(); pl()->initialize(&snc()); delete old_pl; } else pl()->transform(aff); } SNC_constructor C(snc()); C.assign_indices(); } /*{\Mtext \headerline{Exploration} As Nef polyhedra are the result of forming complements and intersections starting from a set |H| of halfspaces which are defined by oriented planes in three space. The corresponding structure is represented by an extended wuerzburg structure $W = (V,E,F,C)$. For topological queries within |W| the following types and operations allow exploration access to this structure.}*/ /*{\Mtypes 3}*/ typedef CGAL::SNC_SM_explorer SM_explorer; SM_explorer SMexplorer(Vertex_const_handle v) const { SM_const_decorator SMCD(&*v); return SM_explorer(SMCD); } typedef typename SNC_structure::Object_list Object_list; typedef typename SNC_structure::Object_handle Object_handle; /*{\Mtypemember a generic handle to an object of the underlying plane map. The kind of object |(vertex, halfedge, face)| can be determined and the object can be assigned to a corresponding handle by the three functions:\\ |bool assign(Vertex_const_handle& h, Object_handle)|\\ |bool assign(Edge_const_handle& h, Object_handle)|\\ |bool assign(Facet_const_handle& h, Object_handle)|\\ |bool assign(Volume_const_handle& h, Object_handle)|\\ where each function returns |true| iff the assignment to |h| was done.}*/ /*{\Moperations 3 1 }*/ bool contains(Object_handle /*h*/) const /*{\Mop returns true iff the object |h| is contained in the set represented by |\Mvar|.}*/ // { SNC_point_locator PL(snc()); return PL.mark(h);} { CGAL_error_msg( "not implemented."); return false;} bool contained_in_boundary(Object_handle h) const /*{\Mop returns true iff the object |h| is contained in the $2$-skeleton of |\Mvar|.}*/ { Vertex_const_handle v; Halfedge_const_handle e; Halffacet_const_handle f; return ( assign(v,h) || assign(e,h) || assign(f,h) ); } Object_handle locate(const Point_3& p) const /*{\Mop returns a generic handle |h| to an object (vertex, edge, facet, volume) of the underlying SNC which contains the point |p| in its relative interior. The point |p| is contained in the set represented by |\Mvar| if |\Mvar.contains(h)| is true.}*/ { CGAL_NEF_TRACEN( "locating point..."); CGAL_assertion( pl() != NULL); Object_handle o = pl()->locate(p); Vertex_handle v; Halfedge_handle e; Halffacet_handle f; Volume_handle c; if(assign(v,o)) return make_object(Vertex_const_handle(v)); if(assign(e,o)) return make_object(Halfedge_const_handle(e)); if(assign(f,o)) return make_object(Halffacet_const_handle(f)); if(assign(c,o)) return make_object(Volume_const_handle(c)); return Object_handle(); } /*{\Mimplementation Nef polyhedra are implemented on top of an extended Wuerzburg structure data structure (EWS) and use linear space in the number of vertices, edges and facets. Operations like empty take constant time. The operations clear, complement, interior, closure, boundary, regularization, input and output take linear time. All binary set operations and comparison operations take time $O(N^2)$ where $N$ is the size of the output plus the size of the input. The point location operations run in linear query time without any preprocessing.}*/ /*{\Mexample Nef polyhedra are parameterized by a so called extended geometric kernel. There's currently only one such kernel based on a homogeneous representation of extended points called |Extended_homogeneous|. The kernel is parameterized by a multiprecision integer type. The member types of |Nef_polyhedron_3< Extended_homogeneous_3 >| map to corresponding types of the CGAL geometry kernel (e.g. |Nef_polyhedron::Plane_3| equals |CGAL::Homogeneous::Plane_3| in the example below). \begin{Mverb} #include #include #include #include using namespace CGAL; typedef Extended_homogeneous Extended_kernel; typedef Nef_polyhedron_3 Nef_polyhedron; typedef Nef_polyhedron::Plane_3 Plane_3; int main() { Nef_polyhedron N1(Plane_3(1,0,0,0)); Nef_polyhedron N2(Plane_3(0,1,0,0), Nef_polyhedron::EXCLUDED); Nef_polyhedron N3 = N1 * N2; // line (*) return 0; } \end{Mverb} After line (*) |N3| is the intersection of |N1| and |N2|.}*/ std::size_t bytes() { // bytes used for the Nef_polyhedron_3. return sizeof(Self) + (snc().bytes() - sizeof(SNC_structure)); } std::size_t bytes_reduced() { // bytes used for the Nef_polyhedron_3. std::cout << sizeof(Self) + (snc().bytes_reduced2() - sizeof(SNC_structure)) << std::endl; return sizeof(Self) + (snc().bytes_reduced() - sizeof(SNC_structure)); } }; // end of Nef_polyhedron_3 template Nef_polyhedron_3:: Nef_polyhedron_3( Content space) { CGAL_NEF_TRACEN("construction from empty or space."); empty_rep(); set_snc(snc()); if(Infi_box::extended_kernel()) { initialize_infibox_vertices(space); build_external_structure(); } else { build_external_structure(); snc().volumes_begin()->mark() = (space == COMPLETE) ? 1 : 0; } } template Nef_polyhedron_3:: Nef_polyhedron_3(const Plane_3& h, Boundary b) { CGAL_NEF_TRACEN("construction from plane "<initialize(&snc2); AND _and; Binary_operation bo(snc()); bo(pl(), snc1, pl1, snc2, pl2, _and); delete pl1; delete pl2; } else CGAL_error_msg ("Constructor is only available with extended kernels"); */ } template Nef_polyhedron_3:: Nef_polyhedron_3( const SNC_structure& W, SNC_point_locator* _pl, bool clone_pl, bool clone_snc) { CGAL_assertion( clone_snc == true || clone_pl == false); // TODO: granados: define behavior when clone=false // CGAL_NEF_TRACEN("construction from an existing SNC structure (clone="<copy_on_write(); if(clone_snc) { snc() = W; set_snc(snc()); } if(clone_pl) { pl() = _pl->clone(); pl()->initialize(&snc()); } else pl() = _pl; } template void Nef_polyhedron_3:: extract_complement() { CGAL_NEF_TRACEN("extract complement"); if( this->is_shared()) clone_rep(); SNC_decorator D(snc()); Vertex_iterator v; CGAL_forall_vertices(v,D){ v->mark() = !v->mark(); SM_decorator SM(&*v); SM.extract_complement(); } Halffacet_iterator f; CGAL_forall_halffacets(f,D) f->mark() = !f->mark(); Volume_iterator c; CGAL_forall_volumes(c,D) // if(!(Infi_box::extended_kernel && c==D.volumes_begin())) c->mark() = !c->mark(); } template void Nef_polyhedron_3:: extract_interior() { CGAL_NEF_TRACEN("extract interior"); if (this->is_shared()) clone_rep(); SNC_decorator D(snc()); Vertex_iterator v; CGAL_forall_vertices(v,D){ v->mark() = false; SM_decorator SM(&*v); SM.extract_interior(); } Halffacet_iterator f; CGAL_forall_halffacets(f,D) f->mark() = false; simplify(); } template void Nef_polyhedron_3:: extract_boundary() { CGAL_NEF_TRACEN("extract boundary"); if (this->is_shared()) clone_rep(); SNC_decorator D(snc()); Vertex_iterator v; CGAL_forall_vertices(v,D) { v->mark() = true; SM_decorator SM(&*v); SM.extract_boundary(); } Halffacet_iterator f; CGAL_forall_halffacets(f,D) f->mark() = true; Volume_iterator c; CGAL_forall_volumes(c,D) c->mark() = false; simplify(); } } //namespace CGAL #include #endif //CGAL_NEF_POLYHEDRON_3_H