add a constructor from a FaceGraph

The first version code is from @afabri
This commit is contained in:
Sébastien Loriot 2016-09-16 17:21:09 +02:00
parent 4ee96e11c0
commit f1f82785ac
5 changed files with 302 additions and 140 deletions

View File

@ -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<PolygonMesh>::%halfedge_descriptor` as key type
a value type convertible to `std::size_t`
\tparam FaceIndexMap a class model of `ReadablePropertyMap` with
`boost::graph_traits<PolygonMesh>::%face_descriptor` as key type
a value type convertible to `std::size_t`
*/
template <class PolygonMesh, class HalfedgeIndexMap, class FaceIndexMap>
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

View File

@ -0,0 +1,82 @@
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Surface_mesh.h>
#include <CGAL/Polyhedron_3.h>
#include <CGAL/boost/graph/graph_traits_Polyhedron_3.h>
#include <CGAL/boost/graph/properties_Polyhedron_3.h>
#include <CGAL/boost/graph/graph_traits_Surface_mesh.h>
#include <CGAL/boost/graph/properties_Surface_mesh.h>
#include <CGAL/Polyhedron_items_with_id_3.h>
#include <CGAL/Nef_polyhedron_3.h>
#include <CGAL/IO/Nef_polyhedron_iostream_3.h>
#include <CGAL/OFF_to_nef_3.h>
#include <sstream>
#include <fstream>
#include <iostream>
typedef CGAL::Exact_predicates_exact_constructions_kernel K;
typedef CGAL::Surface_mesh<K::Point_3> Polygon_mesh;
typedef CGAL::Polyhedron_3<K> Polyhedron;
typedef CGAL::Polyhedron_3<K, CGAL::Polyhedron_items_with_id_3> Polyhedron_with_indices;
typedef CGAL::Nef_polyhedron_3<K> Nef_polyhedron;
template <class PolygonMesh>
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);
}

View File

@ -20,13 +20,15 @@
// Miguel Granados <granados@mpi-sb.mpg.de>
// Susan Hert <hert@mpi-sb.mpg.de>
// Lutz Kettner <kettner@mpi-sb.mpg.de>
#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 <CGAL/Circulator_project.h>
#include <CGAL/normal_vector_newell_3.h>
#include <CGAL/Nef_S2/SM_point_locator.h>
#include <CGAL/Nef_3/SNC_indexed_items.h>
#include <CGAL/boost/graph/helpers.h>
#undef CGAL_NEF_DEBUG
#define CGAL_NEF_DEBUG 29
@ -108,77 +110,81 @@ struct Facet_plane_3 {
}
};
template<typename Items, typename Polyhedron, typename SNC_structure>
class Index_adder {
template<typename Items, typename Polyhedron, typename SNC_structure, typename HalfedgeIndexMap>
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<Polyhedron>::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<typename Polyhedron, typename SNC_structure>
class Index_adder<CGAL::SNC_indexed_items, Polyhedron, SNC_structure> {
template<typename PolygonMesh, typename SNC_structure, typename HalfedgeIndexMap>
class Face_graph_index_adder<CGAL::SNC_indexed_items, PolygonMesh, SNC_structure, HalfedgeIndexMap> {
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<Halfedge_const_handle,
SHalfedge_handle> Hash;
typedef typename boost::graph_traits<PolygonMesh>::halfedge_descriptor halfedge_descriptor;
typedef typename boost::graph_traits<PolygonMesh>::face_descriptor face_descriptor;
Polyhedron& P;
typedef Halfedge_around_face_circulator<PolygonMesh>
Halfedge_around_facet_const_circulator;
typedef std::vector<SHalfedge_handle> 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<HalfedgeIndexMap>::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 <class Polyhedron_, class SNC_structure>
void polyhedron_3_to_nef_3(Polyhedron_& P, SNC_structure& S)
template <class PolygonMesh, class SNC_structure, class FaceIndexMap, class HalfedgeIndexMap>
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<PolygonMesh, vertex_point_t>::type PMap;
typedef typename SNC_structure::Plane_3 Plane;
typedef typename SNC_structure::Vector_3 Vector_3;
typedef typename boost::graph_traits<PolygonMesh>::vertex_descriptor vertex_descriptor;
typedef typename boost::graph_traits<PolygonMesh>::halfedge_descriptor halfedge_descriptor;
typedef typename boost::graph_traits<PolygonMesh>::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<PolygonMesh>
Halfedge_around_vertex_const_circulator;
Index_adder<typename SNC_structure::Items,
Polyhedron, SNC_structure> 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<Vector_3> normals(num_faces(P));
BOOST_FOREACH(face_descriptor f, faces(P)){
Vertex_around_face_circulator<PolygonMesh> 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<typename SNC_structure::Items,
PolygonMesh, SNC_structure,HalfedgeIndexMap> 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 "<<pv.point());
CGAL_NEF_TRACEN("v "<< get(pmap,pv));
SM_decorator SM(&*nv);
Halfedge_around_vertex_const_circulator pe = pv.vertex_begin(), pe_prev(pe);
CGAL_assertion_code(Halfedge_around_vertex_const_circulator pe_0(pe));
CGAL_assertion( pe != 0 );
Halfedge_around_vertex_const_circulator pec(pv,P), pec_prev(pec), done(pec);
halfedge_descriptor pe = *pec, pe_prev= *pec_prev;
CGAL_assertion_code(Halfedge_around_vertex_const_circulator pe_0(pec));
// CGAL_assertion( pe != 0 );
Point_3 pe_target_0(pe->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<Plane>::get_plane(pe_prev->facet(),pe_prev->facet()->plane()).is_degenerate());
CGAL_assertion(pe_prev->is_border() ||
internal::Plane_constructor<Plane>::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<Plane>::get_plane(pe_prev->facet(),pe_prev->facet()->plane()).has_on(pe_target));
CGAL_assertion(pe_prev->is_border() ||
internal::Plane_constructor<Plane>::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<Plane>::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<Plane>::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<Plane>::get_plane(pe_prev->facet(),pe_prev->facet()->plane()).is_degenerate());
CGAL_assertion(pe_prev->is_border() ||
internal::Plane_constructor<Plane>::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<Plane>::get_plane(pe_prev->facet(),pe_prev->facet()->plane()).has_on(pe_target_0));
CGAL_assertion(pe_prev->is_border() ||
internal::Plane_constructor<Plane>::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<Plane>::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 <class Polyhedron, class SNC_structure>
void polyhedron_3_to_nef_3(Polyhedron& P, SNC_structure& S)
{
typedef typename boost::property_map<Polyhedron, face_external_index_t>::type FIMap;
FIMap fimap = get(CGAL::face_external_index,P);
typedef typename boost::property_map<Polyhedron, halfedge_external_index_t>::type HIMap;
HIMap himap = get(CGAL::halfedge_external_index,P);
polygon_mesh_to_nef_3(P, S, fimap, himap);
}
template <class SM, class SNC_structure>
void polygon_mesh_to_nef_3(SM& sm, SNC_structure& snc)
{
typedef typename boost::property_map<SM, face_index_t>::type FIMap;
FIMap fimap = get(CGAL::face_index,sm);
typedef typename boost::property_map<SM, boost::halfedge_index_t>::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

View File

@ -49,7 +49,7 @@
#include <CGAL/Nef_3/Mark_bounded_volumes.h>
#include <CGAL/IO/Verbose_ostream.h>
#include <CGAL/Nef_3/polyhedron_3_to_nef_3.h>
#include <CGAL/Nef_3/polygon_mesh_to_nef_3.h>
#include <CGAL/Nef_3/shell_to_nef_3.h>
#include <CGAL/Polyhedron_incremental_builder_3.h>
#include <CGAL/Polyhedron_3.h>
@ -64,6 +64,9 @@
#include <CGAL/Constrained_triangulation_face_base_2.h>
#include <list>
#include <boost/type_traits/is_same.hpp>
#include <boost/utility/enable_if.hpp>
// RO: includes for "vertex cycle to Nef" constructor
#include <CGAL/Nef_3/vertex_cycle_to_nef_3.h>
#include <CGAL/Vector_3.h>
@ -606,6 +609,41 @@ protected:
delegate(mbv);
set_snc(snc());
}
template <class PolygonMesh>
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<PolygonMesh, SNC_structure>(const_cast<PolygonMesh&>(pm), snc());
build_external_structure();
simplify();
CGAL::Mark_bounded_volumes<Nef_polyhedron_3> mbv(true);
delegate(mbv);
set_snc(snc());
}
template <class PolygonMesh, class HalfedgeIndexMap, class FaceIndexMap>
explicit Nef_polyhedron_3(const PolygonMesh& pm,
const HalfedgeIndexMap& him,
const FaceIndexMap& fim,
typename boost::disable_if <
boost::is_same<FaceIndexMap, bool>
>::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<PolygonMesh, SNC_structure>(const_cast<PolygonMesh&>(pm), snc(), fim, him);
build_external_structure();
simplify();
CGAL::Mark_bounded_volumes<Nef_polyhedron_3> 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

View File

@ -33,30 +33,30 @@ namespace CGAL {
template <class Handle, class Vector>
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 "<<n);
}
template <class IC, class Vector, class VertexPointMap>
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 "<<n);
}