diff --git a/Nef_3/doc/Nef_3/CGAL/Nef_polyhedron_3.h b/Nef_3/doc/Nef_3/CGAL/Nef_polyhedron_3.h index 6a33b924560..2e3edfb6030 100644 --- a/Nef_3/doc/Nef_3/CGAL/Nef_polyhedron_3.h +++ b/Nef_3/doc/Nef_3/CGAL/Nef_polyhedron_3.h @@ -1187,6 +1187,26 @@ public: */ Nef_polyhedron_3(Polyhedron& P); +/*! + creates a Nef polyhedron, which represents the same point set as + the polyhedral surface `pm` does. `him` and `fim` must be both initialized + so that halfedges and faces are indexed in `[0, num_halfedges(pm)[` + and `[0, num_faces(pm)[` respectively. If `PolygonMesh` has an internal + halfedge index map and an internal face index map, the last two parameters + can be omitted. + \tparam PolygonMesh a model of `FaceListGraph` and `VertexListGraph`. + \tparam HalfedgeIndexMap a class model of `ReadablePropertyMap` with + `boost::graph_traits::%halfedge_descriptor` as key type + a value type convertible to `std::size_t` + \tparam FaceIndexMap a class model of `ReadablePropertyMap` with + `boost::graph_traits::%face_descriptor` as key type + a value type convertible to `std::size_t` +*/ + template + explicit Nef_polyhedron_3(const PolygonMesh& pm, + const HalfedgeIndexMap& him, + const FaceIndexMap& fim); + /*! creates a Nef polyhedron consisting of a single polygon spanned by the list of points in the iterator range diff --git a/Nef_3/examples/Nef_3/surface_mesh_to_nef.cpp b/Nef_3/examples/Nef_3/surface_mesh_to_nef.cpp new file mode 100644 index 00000000000..fba541f22b7 --- /dev/null +++ b/Nef_3/examples/Nef_3/surface_mesh_to_nef.cpp @@ -0,0 +1,82 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include +#include +#include + +typedef CGAL::Exact_predicates_exact_constructions_kernel K; +typedef CGAL::Surface_mesh Polygon_mesh; +typedef CGAL::Polyhedron_3 Polyhedron; +typedef CGAL::Polyhedron_3 Polyhedron_with_indices; +typedef CGAL::Nef_polyhedron_3 Nef_polyhedron; + +template +void fill_cube(PolygonMesh& pm) +{ + std::string input = +"OFF\n\ +8 12 0\n\ +-1 -1 -1\n\ +-1 1 -1\n\ +1 1 -1\n\ +1 -1 -1\n\ +-1 -1 1\n\ +-1 1 1\n\ +1 1 1\n\ +1 -1 1\n\ +3 0 1 3\n\ +3 3 1 2\n\ +3 0 4 1\n\ +3 1 4 5\n\ +3 3 2 7\n\ +3 7 2 6\n\ +3 4 0 3\n\ +3 7 4 3\n\ +3 6 4 7\n\ +3 6 5 4\n\ +3 1 5 6\n\ +3 2 1 6"; + + std::stringstream ss; + ss << input; + ss >> pm; +} + +int main() +{ + // construction from a Surface_mesh + Polygon_mesh input; + fill_cube(input); + Nef_polyhedron nef(input); + + Polygon_mesh output; + std::ofstream out; + + // construction from a Polyhedron_3 + Polyhedron input_bis; + fill_cube(input_bis); + Nef_polyhedron nef_bis(input_bis); + + // construction from a Polyhedron_3 with indices + Polyhedron_with_indices input_ter; + fill_cube(input_ter); + set_halfedgeds_items_id(input_ter); + Nef_polyhedron nef_ter( input_ter, + get(CGAL::halfedge_index,input_ter), + get(CGAL::face_index, input_ter) ); + + assert(nef==nef_bis); + assert(nef==nef_ter); +} + diff --git a/Nef_3/include/CGAL/Nef_3/polyhedron_3_to_nef_3.h b/Nef_3/include/CGAL/Nef_3/polygon_mesh_to_nef_3.h similarity index 55% rename from Nef_3/include/CGAL/Nef_3/polyhedron_3_to_nef_3.h rename to Nef_3/include/CGAL/Nef_3/polygon_mesh_to_nef_3.h index 7485c2db142..0e209cd9790 100644 --- a/Nef_3/include/CGAL/Nef_3/polyhedron_3_to_nef_3.h +++ b/Nef_3/include/CGAL/Nef_3/polygon_mesh_to_nef_3.h @@ -20,13 +20,15 @@ // Miguel Granados // Susan Hert // Lutz Kettner -#ifndef CGAL_NEF_POLYHEDRON_3_TO_NEF_3_H -#define CGAL_NEF_POLYHEDRON_3_TO_NEF_3_H +// Andreas Fabri + +#ifndef CGAL_POLYGON_MESH_TO_NEF_3_H +#define CGAL_POLYGON_MESH_TO_NEF_3_H -#include #include #include #include +#include #undef CGAL_NEF_DEBUG #define CGAL_NEF_DEBUG 29 @@ -108,77 +110,81 @@ struct Facet_plane_3 { } }; -template -class Index_adder { +template +class Face_graph_index_adder { typedef typename SNC_structure::SHalfedge_handle SHalfedge_handle; - - typedef typename Polyhedron::Halfedge_around_vertex_const_circulator - Halfedge_around_vertex_const_circulator; + + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; public: - Index_adder(Polyhedron& ) {} - void set_hash(Halfedge_around_vertex_const_circulator, + Face_graph_index_adder(Polyhedron&, HalfedgeIndexMap ) {} + void set_hash(halfedge_descriptor, SHalfedge_handle) {} void resolve_indexes() {} }; -template -class Index_adder { +template +class Face_graph_index_adder { typedef typename SNC_structure::SHalfedge_handle SHalfedge_handle; - - typedef typename Polyhedron::Halfedge_const_handle - Halfedge_const_handle; - typedef typename Polyhedron::Facet_const_iterator - Facet_const_iterator; - typedef typename Polyhedron::Halfedge_around_vertex_const_circulator - Halfedge_around_vertex_const_circulator; - typedef typename Polyhedron::Halfedge_around_facet_const_circulator - Halfedge_around_facet_const_circulator; - typedef typename CGAL::Unique_hash_map Hash; + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef typename boost::graph_traits::face_descriptor face_descriptor; - Polyhedron& P; + typedef Halfedge_around_face_circulator + Halfedge_around_facet_const_circulator; + typedef std::vector Hash; + + PolygonMesh& P; + HalfedgeIndexMap him; Hash hash; - public: - Index_adder(Polyhedron& P_) : P(P_) {} +public: + Face_graph_index_adder(PolygonMesh& P_, HalfedgeIndexMap him) : P(P_), him(him) + { + hash.resize(num_halfedges(P)); + } - void set_hash(Halfedge_around_vertex_const_circulator evc, + void set_hash(halfedge_descriptor evc, SHalfedge_handle se) { - hash[evc] = se; + hash[get(him,evc)] = se; } - void resolve_indexes() { - Facet_const_iterator fi; - for(fi = P.facets_begin(); fi != P.facets_end(); ++fi) { + void resolve_indexes() + { + BOOST_FOREACH(face_descriptor fi, faces(P)) { Halfedge_around_facet_const_circulator - fc(fi->facet_begin()), end(fc); - hash[fc]->set_index(); - hash[fc]->twin()->set_index(); - hash[fc]->twin()->source()->set_index(); - int se = hash[fc]->get_index(); - int set = hash[fc]->twin()->get_index(); - int sv = hash[fc]->twin()->source()->get_index(); + fc(halfedge(fi,P),P), end(fc); + typename boost::property_traits::value_type + index = get(him,*fc); + hash[index]->set_index(); + hash[index]->twin()->set_index(); + hash[index]->twin()->source()->set_index(); + int se = hash[index]->get_index(); + int set = hash[index]->twin()->get_index(); + int sv = hash[index]->twin()->source()->get_index(); ++fc; CGAL_For_all(fc, end) { - hash[fc]->set_index(se); - hash[fc]->twin()->set_index(set); - hash[fc]->source()->set_index(sv); - hash[fc]->twin()->source()->set_index(); - sv = hash[fc]->twin()->source()->get_index(); + index = get(him,*fc); + hash[index]->set_index(se); + hash[index]->twin()->set_index(set); + hash[index]->source()->set_index(sv); + hash[index]->twin()->source()->set_index(); + sv = hash[index]->twin()->source()->get_index(); } - hash[fc]->source()->set_index(sv); + hash[get(him,*fc)]->source()->set_index(sv); } } }; -template -void polyhedron_3_to_nef_3(Polyhedron_& P, SNC_structure& S) +template +void polygon_mesh_to_nef_3(PolygonMesh& P, SNC_structure& S, FaceIndexMap fimap, HalfedgeIndexMap himap) { - typedef Polyhedron_ Polyhedron; - typedef typename Polyhedron::Facet::Plane_3 Plane; - typedef typename Polyhedron::Traits::Kernel Kernel; + typedef typename boost::property_map::type PMap; + typedef typename SNC_structure::Plane_3 Plane; + typedef typename SNC_structure::Vector_3 Vector_3; + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef typename boost::graph_traits::face_descriptor face_descriptor; typedef typename SNC_structure::SM_decorator SM_decorator; typedef typename SNC_structure::Vertex_handle Vertex_handle; typedef typename SNC_structure::SVertex_handle SVertex_handle; @@ -188,81 +194,67 @@ void polyhedron_3_to_nef_3(Polyhedron_& P, SNC_structure& S) typedef typename SNC_structure::Sphere_point Sphere_point; typedef typename SNC_structure::Sphere_circle Sphere_circle; - typedef typename Polyhedron::Halfedge_around_vertex_const_circulator + typedef Halfedge_around_target_circulator Halfedge_around_vertex_const_circulator; - Index_adder index_adder(P); - CGAL_NEF_TRACEN(" calculating facet's planes..."); - std::transform( P.facets_begin(), P.facets_end(), - P.planes_begin(), Facet_plane_3()); + PMap pmap = get(CGAL::vertex_point,P); - typename Polyhedron::Vertex_iterator pvi; - for( pvi = P.vertices_begin(); pvi != P.vertices_end(); ++pvi ) { - typename Polyhedron::Vertex pv = *pvi; + std::vector normals(num_faces(P)); + + BOOST_FOREACH(face_descriptor f, faces(P)){ + Vertex_around_face_circulator vafc(halfedge(f,P),P), done(vafc); + Vector_3 v; + normal_vector_newell_3(vafc, done, pmap, v); + normals[get(fimap,f)] = - v; + } + + Face_graph_index_adder index_adder(P,himap); + + + BOOST_FOREACH(vertex_descriptor pv, vertices(P) ) { Vertex_handle nv = S.new_vertex(); - nv->point() = pv.point(); + nv->point() = get(pmap,pv); nv->mark() = true; - CGAL_NEF_TRACEN("v "<opposite()->vertex()->point()); - Point_3 sp_point_0(CGAL::ORIGIN+(pe_target_0-pv.point())); + Point_3 pe_target_0(get(pmap,target(opposite(pe,P),P))); + Point_3 sp_point_0(CGAL::ORIGIN+(pe_target_0 - get(pmap,pv))); Sphere_point sp_0(sp_point_0); SVertex_handle sv_0 = SM.new_svertex(sp_0); sv_0->mark() = true; - pe++; - CGAL_assertion(pe != pv.vertex_begin()); + pec++; + pe = *pec; + //CGAL_assertion(pe != pv->vertex_begin()); SVertex_handle sv_prev = sv_0; bool with_border = false; do { - // CGAL_assertion(!pe->is_border()); - CGAL_assertion(pe_prev->face() == pe->opposite()->face()); - CGAL_assertion(pe_prev->vertex()->point()==pv.point()); - CGAL_assertion(pe->vertex()->point()==pv.point()); + CGAL_assertion(face(pe_prev,P) == face(opposite(pe,P),P)); + CGAL_assertion(get(pmap,target(pe_prev,P)) == get(pmap,pv)); + CGAL_assertion(get(pmap,target(pe,P)) == get(pmap,pv)); - Point_3 pe_target = pe->opposite()->vertex()->point(); - Point_3 sp_point = CGAL::ORIGIN+(pe_target-pv.point()); + Point_3 pe_target = get(pmap,target(opposite(pe,P),P)); + Point_3 sp_point = CGAL::ORIGIN+(pe_target - get(pmap,pv)); Sphere_point sp(sp_point); SVertex_handle sv = SM.new_svertex(sp); sv->mark() = true; - // CGAL_NEF_TRACEN(pe_prev->facet()->plane()); CGAL_NEF_TRACEN(pe_target); - CGAL_NEF_TRACEN(pe_prev->opposite()->vertex()->point()); + CGAL_NEF_TRACEN(get(pmap,target(opposite(pe_prev,P),P))); - /* - if(pe_prev->facet()->plane().is_degenerate()) { - typename Polyhedron::Halfedge_around_facet_const_circulator fc(pv.vertex_begin()), fcend(fc); - std::cerr << "wrong cycle " << std::endl; - CGAL_For_all(fc,fcend) { - std::cerr << " " << fc->vertex()->point() << std::endl; - } - } - */ - CGAL_assertion(pe_prev->is_border() || - !internal::Plane_constructor::get_plane(pe_prev->facet(),pe_prev->facet()->plane()).is_degenerate()); - CGAL_assertion(pe_prev->is_border() || - internal::Plane_constructor::get_plane(pe_prev->facet(),pe_prev->facet()->plane()). - has_on(pe_prev->opposite()->vertex()->point())); - CGAL_assertion(pe_prev->is_border() || - internal::Plane_constructor::get_plane(pe_prev->facet(),pe_prev->facet()->plane()).has_on(pe_target)); - CGAL_assertion(pe_prev->is_border() || - internal::Plane_constructor::get_plane(pe_prev->facet(),pe_prev->facet()->plane()).has_on(pv.point())); - - if(pe_prev->is_border()) + if(is_border(pe_prev,P)) with_border = true; else { - typename Kernel::Plane_3 ss_plane - (CGAL::ORIGIN, - internal::Plane_constructor::get_opposite_orthogonal_vector(pe_prev->facet()->plane())); + Plane ss_plane( CGAL::ORIGIN, normals[get(fimap,face(pe_prev,P))] ); Sphere_circle ss_circle(ss_plane); CGAL_assertion(ss_circle.has_on(sp)); @@ -277,36 +269,23 @@ void polyhedron_3_to_nef_3(Polyhedron_& P, SNC_structure& S) } sv_prev = sv; - pe_prev = pe; - ++pe; + pec_prev = pec; + ++pec; + pe = *pec; + pe_prev = *pec_prev; } - while( pe != pv.vertex_begin() ); + while( pec != done ); - CGAL_assertion(pe_prev->face() == pe_0->opposite()->face()); - CGAL_assertion(pe_prev->vertex()->point()==pv.point()); - CGAL_assertion(pe_0->vertex()->point()==pv.point()); - - CGAL_NEF_TRACEN(internal::Plane_constructor::get_plane(pe_prev->facet(),pe_prev->facet()->plane())); - CGAL_NEF_TRACEN(pe_target_0); - CGAL_NEF_TRACEN(pe_prev->opposite()->vertex()->point()); - CGAL_assertion(pe_prev->is_border() || - !internal::Plane_constructor::get_plane(pe_prev->facet(),pe_prev->facet()->plane()).is_degenerate()); - CGAL_assertion(pe_prev->is_border() || - internal::Plane_constructor::get_plane(pe_prev->facet(),pe_prev->facet()->plane()). - has_on(pe_prev->opposite()->vertex()->point())); - CGAL_assertion(pe_prev->is_border() || - internal::Plane_constructor::get_plane(pe_prev->facet(),pe_prev->facet()->plane()).has_on(pe_target_0)); - CGAL_assertion(pe_prev->is_border() || - internal::Plane_constructor::get_plane(pe_prev->facet(),pe_prev->facet()->plane()).has_on(pv.point())); + CGAL_assertion(face(pe_prev,P) == face(opposite(*pe_0,P),P)); + CGAL_assertion(get(pmap,target(pe_prev,P)) == get(pmap,pv)); + CGAL_assertion(get(pmap,target(*pe_0,P)) == get(pmap,pv)); SHalfedge_handle e; - if(pe_prev->is_border()) { + if(is_border(pe_prev,P)) { with_border = true; e = sv_prev->out_sedge(); } else { - typename Kernel::Plane_3 ss_plane - (CGAL::ORIGIN, - internal::Plane_constructor::get_opposite_orthogonal_vector(pe_prev->facet()->plane())); + Plane ss_plane( CGAL::ORIGIN, normals[get(fimap,face(pe_prev,P))] ); Sphere_circle ss_circle(ss_plane); CGAL_assertion(ss_plane.has_on(sv_prev->point())); @@ -338,8 +317,28 @@ void polyhedron_3_to_nef_3(Polyhedron_& P, SNC_structure& S) index_adder.resolve_indexes(); } +template +void polyhedron_3_to_nef_3(Polyhedron& P, SNC_structure& S) +{ + typedef typename boost::property_map::type FIMap; + FIMap fimap = get(CGAL::face_external_index,P); + typedef typename boost::property_map::type HIMap; + HIMap himap = get(CGAL::halfedge_external_index,P); + polygon_mesh_to_nef_3(P, S, fimap, himap); +} + +template +void polygon_mesh_to_nef_3(SM& sm, SNC_structure& snc) +{ + typedef typename boost::property_map::type FIMap; + FIMap fimap = get(CGAL::face_index,sm); + typedef typename boost::property_map::type HIMap; + HIMap himap = get(boost::halfedge_index,sm); + + polygon_mesh_to_nef_3(sm, snc, fimap, himap); +} } //namespace CGAL -#endif //CGAL_NEF_POLYHEDRON_3_TO_NEF_3_H +#endif //CGAL_POLYGON_MESH_TO_NEF_3_H diff --git a/Nef_3/include/CGAL/Nef_polyhedron_3.h b/Nef_3/include/CGAL/Nef_polyhedron_3.h index 9f3c59bfae1..7800056405d 100644 --- a/Nef_3/include/CGAL/Nef_polyhedron_3.h +++ b/Nef_3/include/CGAL/Nef_polyhedron_3.h @@ -49,7 +49,7 @@ #include #include -#include +#include #include #include #include @@ -64,6 +64,9 @@ #include #include +#include +#include + // RO: includes for "vertex cycle to Nef" constructor #include #include @@ -606,6 +609,41 @@ protected: 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) @@ -1264,6 +1302,7 @@ protected: 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 diff --git a/Nef_3/include/CGAL/normal_vector_newell_3.h b/Nef_3/include/CGAL/normal_vector_newell_3.h index 3aa0503ba97..5fcdf4b6a9d 100644 --- a/Nef_3/include/CGAL/normal_vector_newell_3.h +++ b/Nef_3/include/CGAL/normal_vector_newell_3.h @@ -33,30 +33,30 @@ namespace CGAL { template CGAL_MEDIUM_INLINE -void newell_single_step_3( Handle p, Handle q, Vector& n ) +void newell_single_step_3( const Handle& p, const Handle& q, Vector& n ) { n = Vector( n.hx() - * p->hw() * p->hw() - * q->hw() * q->hw() + * p.hw() * p.hw() + * q.hw() * q.hw() + n.hw() - * ( p->hy() * q->hw() - q->hy() * p->hw()) - * ( p->hz() * q->hw() + q->hz() * p->hw()), + * ( p.hy() * q.hw() - q.hy() * p.hw()) + * ( p.hz() * q.hw() + q.hz() * p.hw()), n.hy() - * p->hw() * p->hw() - * q->hw() * q->hw() + * p.hw() * p.hw() + * q.hw() * q.hw() + n.hw() - * ( p->hz() * q->hw() - q->hz() * p->hw()) - * ( p->hx() * q->hw() + q->hx() * p->hw()), + * ( p.hz() * q.hw() - q.hz() * p.hw()) + * ( p.hx() * q.hw() + q.hx() * p.hw()), n.hz() - * p->hw() * p->hw() - * q->hw() * q->hw() + * p.hw() * p.hw() + * q.hw() * q.hw() + n.hw() - * ( p->hx() * q->hw() - q->hx() * p->hw()) - * ( p->hy() * q->hw() + q->hy() * p->hw()), + * ( p.hx() * q.hw() - q.hx() * p.hw()) + * ( p.hy() * q.hw() + q.hy() * p.hw()), n.hw() - * p->hw() * p->hw() - * q->hw() * q->hw() + * p.hw() * p.hw() + * q.hw() * q.hw() ); } @@ -82,11 +82,33 @@ void normal_vector_newell_3( IC first, IC last, Vector& n ) IC prev = first; ++first; while( first != last) { - newell_single_step_3( prev, first, n); + newell_single_step_3( *prev, *first, n); prev = first; ++first; } - newell_single_step_3( prev, start_point, n); + newell_single_step_3( *prev, *start_point, n); + CGAL_NEF_TRACEN("newell normal vector "< +void normal_vector_newell_3( IC first, IC last, VertexPointMap vpm, Vector& n ) +{ + CGAL_assertion( !CGAL::is_empty_range( first, last)); + // Compute facet normals via the Newell-method as described in + // Filippo Tampieri: Newell's Method for Computing the Plane + // Equation of a Polygon. Graphics Gems III, David Kirk, + // AP Professional, 1992. + // The code works with cartesian and with semi-rational points. + n = Vector( 0, 0, 0); // init current normal to 0 + IC start_point = first; + IC prev = first; + ++first; + while( first != last) { + newell_single_step_3( get(vpm,*prev), get(vpm,*first), n); + prev = first; + ++first; + } + newell_single_step_3( get(vpm,*prev), get(vpm,*start_point), n); CGAL_NEF_TRACEN("newell normal vector "<