Replace custom polyhedron class Enriched_polyhedron by a regular Polyhedron_3 + a call to compute_vertex_normal() (borrowed from Polyhedron demo).

The new code is shorter and easier to understand.
This commit is contained in:
Laurent Saboret 2009-04-10 14:40:47 +00:00
parent 5e81b086c8
commit c6ad02b857
16 changed files with 410 additions and 1073 deletions

View File

@ -0,0 +1,45 @@
#ifndef _COMPUTE_NORMAL_
#define _COMPUTE_NORMAL_
template <class Facet, class Kernel>
typename Kernel::Vector_3 compute_facet_normal(const Facet& f)
{
typedef typename Kernel::Point_3 Point;
typedef typename Kernel::Vector_3 Vector;
typedef typename Facet::Halfedge_around_facet_const_circulator HF_circulator;
Vector normal = CGAL::NULL_VECTOR;
HF_circulator he = f.facet_begin();
HF_circulator end = he;
CGAL_For_all(he,end)
{
const Point& prev = he->prev()->vertex()->point();
const Point& curr = he->vertex()->point();
const Point& next = he->next()->vertex()->point();
Vector n = CGAL::cross_product(next-curr,prev-curr);
normal = normal + (n / std::sqrt(n*n));
}
return normal / std::sqrt(normal * normal);
}
template <class Vertex, class Kernel>
typename Kernel::Vector_3 compute_vertex_normal(const Vertex& v)
{
typedef typename Kernel::Point_3 Point;
typedef typename Kernel::Vector_3 Vector;
typedef typename Vertex::Halfedge_around_vertex_const_circulator HV_circulator;
typedef typename Vertex::Facet Facet;
Vector normal = CGAL::NULL_VECTOR;
HV_circulator he = v.vertex_begin();
HV_circulator end = he;
CGAL_For_all(he,end)
{
if(!he->is_border())
{
Vector n = compute_facet_normal<Facet,Kernel>(*he->facet());
normal = normal + (n / std::sqrt(n*n));
}
}
return normal / std::sqrt(normal * normal);
}
#endif // _COMPUTE_NORMAL_

View File

@ -1,247 +0,0 @@
///////////////////////////////////////////////////////////////////////////
// //
// Class: Enriched_polyhedron //
// //
///////////////////////////////////////////////////////////////////////////
#ifndef _POLYGON_MESH_
#define _POLYGON_MESH_
// CGAL
#include <CGAL/Cartesian.h>
#include <CGAL/Polyhedron_3.h>
#include <list>
// Forward declarations
struct Vertex_normal;
struct Facet_normal;
// a refined facet with a normal
template <class Refs, class Tag, class Point_3_, class Norm>
class Enriched_facet : public CGAL::HalfedgeDS_face_base<Refs, Tag>
{
// normal
Norm m_normal;
public:
// life cycle
Enriched_facet()
{
}
// normal
typedef Norm Normal_3;
Normal_3& normal() { return m_normal; }
const Normal_3& normal() const { return m_normal; }
};
// a refined halfedge with a general tag
template <class Refs, class Tprev, class Tvertex, class Tface, class Norm>
class Enriched_halfedge : public CGAL::HalfedgeDS_halfedge_base<Refs,Tprev,Tvertex,Tface>
{
private:
public:
// life cycle
Enriched_halfedge()
{
}
};
// a refined vertex with a normal, tag and camera
template <class Refs, class Tag, class Point_3_, class Norm>
class Enriched_vertex : public CGAL::HalfedgeDS_vertex_base<Refs, Tag, Point_3_>
{
// normal
Norm m_normal;
public:
// life cycle
Enriched_vertex() {}
// repeat mandatory constructors
Enriched_vertex(const Point_3_& pt)
: CGAL::HalfedgeDS_vertex_base<Refs, Tag, Point_3_>(pt)
{
}
// normal
typedef Norm Normal_3;
Normal_3& normal() { return m_normal; }
const Normal_3& normal() const { return m_normal; }
};
// A redefined items class for the Polyhedron_3
// with a refined vertex class that contains a
// member for the normal vector and a refined
// facet with a normal vector instead of the
// plane equation (this is an alternative
// solution instead of using
// Polyhedron_traits_with_normals_3).
struct Enriched_items : public CGAL::Polyhedron_items_3
{
// wrap vertex
template <class Refs, class Traits>
struct Vertex_wrapper
{
typedef typename Traits::Point_3 Point;
typedef typename Traits::Vector_3 Normal;
typedef Enriched_vertex<Refs,
CGAL::Tag_true,
Point,
Normal> Vertex;
};
// wrap face
template <class Refs, class Traits>
struct Face_wrapper
{
typedef typename Traits::Point_3 Point;
typedef typename Traits::Vector_3 Normal;
typedef Enriched_facet<Refs,
CGAL::Tag_true,
Point,
Normal> Face;
};
// wrap halfedge
template <class Refs, class Traits>
struct Halfedge_wrapper
{
typedef typename Traits::Vector_3 Normal;
typedef Enriched_halfedge<Refs,
CGAL::Tag_true,
CGAL::Tag_true,
CGAL::Tag_true,
Normal> Halfedge;
};
};
// Enriched polyhedron
template <class PolyhedronTraits_3,
class PolyhedronItems_3 = Enriched_items>
class Enriched_polyhedron
: public CGAL::Polyhedron_3<PolyhedronTraits_3, PolyhedronItems_3>
{
// Private types
private:
typedef CGAL::Polyhedron_3<PolyhedronTraits_3, PolyhedronItems_3> Base;
// Public types
public:
typedef typename PolyhedronTraits_3::FT FT;
typedef typename PolyhedronTraits_3::Point_3 Point;
// Repeat Polyhedron_3 public types
typedef typename Base::HalfedgeDS HalfedgeDS;
typedef typename Base::Vertex Vertex;
typedef typename Base::Halfedge Halfedge;
typedef typename Base::Facet Facet;
typedef typename Base::Vertex_handle Vertex_handle;
typedef typename Base::Vertex_const_handle Vertex_const_handle;
typedef typename Base::Halfedge_handle Halfedge_handle;
typedef typename Base::Halfedge_const_handle Halfedge_const_handle;
typedef typename Base::Facet_handle Facet_handle;
typedef typename Base::Facet_const_handle Facet_const_handle;
typedef typename Base::Vertex_iterator Vertex_iterator;
typedef typename Base::Vertex_const_iterator Vertex_const_iterator;
typedef typename Base::Halfedge_iterator Halfedge_iterator;
typedef typename Base::Halfedge_const_iterator Halfedge_const_iterator;
typedef typename Base::Facet_iterator Facet_iterator;
typedef typename Base::Facet_const_iterator Facet_const_iterator;
typedef typename Base::Point_iterator Point_iterator;
typedef typename Base::Point_const_iterator Point_const_iterator;
typedef typename Base::Halfedge_around_facet_circulator Halfedge_around_facet_circulator;
typedef typename Base::Halfedge_around_facet_const_circulator Halfedge_around_facet_const_circulator;
typedef typename Base::Halfedge_around_vertex_circulator Halfedge_around_vertex_circulator;
typedef typename Base::Halfedge_around_vertex_const_circulator Halfedge_around_vertex_const_circulator;
public :
// Default constructor, copy constructor and operator =() are fine.
// Repeat Delaunay_triangulation_3 public methods
Base::halfedges_begin;
Base::halfedges_end;
Base::facets_begin;
Base::facets_end;
Base::vertices_begin;
Base::vertices_end;
// Compute normals using mesh connectivity (per facet, then per vertex)
void compute_normals_per_facet()
{
std::for_each(facets_begin(),facets_end(),Facet_normal());
}
void compute_normals_per_vertex()
{
std::for_each(vertices_begin(),vertices_end(),Vertex_normal());
}
void compute_normals()
{
compute_normals_per_facet();
compute_normals_per_vertex();
}
};
// compute facet normal (functor)
struct Facet_normal
{
template <class Facet>
void operator()(Facet& f)
{
typename Facet::Normal_3 sum = CGAL::NULL_VECTOR;
typename Facet::Halfedge_around_facet_circulator h = f.facet_begin();
do
{
typename Facet::Normal_3 normal = CGAL::cross_product(
h->next()->vertex()->point() - h->vertex()->point(),
h->next()->next()->vertex()->point() - h->next()->vertex()->point());
double sqnorm = normal * normal;
if(sqnorm != 0)
normal = normal / (double)std::sqrt(sqnorm);
sum = sum + normal;
}
while(++h != f.facet_begin());
double sqnorm = sum * sum;
if(sqnorm != 0.0)
f.normal() = sum / std::sqrt(sqnorm);
else
{
f.normal() = CGAL::NULL_VECTOR;
std::cerr << "degenerate face\n";
}
}
};
// compute vertex normal (functor)
struct Vertex_normal
{
template <class Vertex>
void operator()(Vertex& v)
{
typename Vertex::Normal_3 normal = CGAL::NULL_VECTOR;
typename Vertex::Halfedge_around_vertex_const_circulator pHalfedge = v.vertex_begin();
typename Vertex::Halfedge_around_vertex_const_circulator begin = pHalfedge;
CGAL_For_all(pHalfedge,begin)
if(!pHalfedge->is_border())
normal = normal + pHalfedge->facet()->normal();
double sqnorm = normal * normal;
if(sqnorm != 0.0f)
v.normal() = normal / (float)std::sqrt(sqnorm);
else
v.normal() = CGAL::NULL_VECTOR;
}
};
#endif // _POLYGON_MESH_

View File

@ -12,8 +12,8 @@
// CGAL
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Timer.h>
#include <CGAL/Memory_sizer.h>
#include <CGAL/boost/graph/properties.h>
#include <CGAL/Polyhedron_3.h>
#include <CGAL/IO/Polyhedron_iostream.h>
// This package
@ -25,12 +25,11 @@
#include <CGAL/IO/read_xyz_point_set.h>
#include <CGAL/IO/write_xyz_point_set.h>
#include "enriched_polyhedron.h"
#include "compute_normal.h"
#include <deque>
#include <cstdlib>
#include <fstream>
#include <cassert>
// ----------------------------------------------------------------------------
@ -222,12 +221,13 @@ int main(int argc, char * argv[])
PointList points;
// If OFF file format
std::cerr << "Open " << input_filename << " for reading..." << std::endl;
std::string extension = input_filename.substr(input_filename.find_last_of('.'));
if (extension == ".off" || extension == ".OFF")
{
// Read the mesh file in a polyhedron
std::ifstream stream(input_filename.c_str());
typedef Enriched_polyhedron<Kernel,Enriched_items> Polyhedron;
typedef CGAL::Polyhedron_3<Kernel> Polyhedron;
Polyhedron input_mesh;
CGAL::scan_OFF(stream, input_mesh, true /* verbose */);
if(!stream || !input_mesh.is_valid() || input_mesh.empty())
@ -236,15 +236,13 @@ int main(int argc, char * argv[])
return EXIT_FAILURE;
}
// Compute vertices' normals from connectivity
input_mesh.compute_normals();
// Convert vertices and normals to PointList
Polyhedron::Vertex_iterator v;
// Convert Polyhedron vertices to point set.
// Compute vertices' normals from connectivity.
Polyhedron::Vertex_const_iterator v;
for (v = input_mesh.vertices_begin(); v != input_mesh.vertices_end(); v++)
{
const Point& p = v->point();
const Vector& n = v->normal();
Vector n = compute_vertex_normal<Polyhedron::Vertex,Kernel>(*v);
points.push_back(Point_with_normal(p,n));
}
}
@ -269,11 +267,9 @@ int main(int argc, char * argv[])
}
// Print status
long memory = CGAL::Memory_sizer().virtual_size();
int nb_vertices = points.size();
std::cerr << "Read file " << input_filename << ": " << nb_vertices << " vertices, "
<< task_timer.time() << " seconds, "
<< (memory>>20) << " Mb allocated"
<< std::endl;
task_timer.reset();

View File

@ -40,7 +40,7 @@ Point_set_scene_item::Point_set_scene_item(const Polyhedron& input_mesh)
Polyhedron::Vertex_const_iterator v;
for (v = input_mesh.vertices_begin(); v != input_mesh.vertices_end(); v++)
{
Point p = v->point();
const Point& p = v->point();
Vector n = compute_vertex_normal<Polyhedron::Vertex,Kernel>(*v);
m_points->push_back(UI_point(p,n));
}

View File

@ -6,7 +6,7 @@
#include "Poisson.h"
#include "DialogOptions.h"
#include "PoissonDoc.h"
#include "enriched_polyhedron.h"
#include "compute_normal.h"
#include "read_pwc_point_set.h"
#include "read_g23_point_set.h"
#include "outlier_removal_wrt_camera_cone_angle_3.h"
@ -15,6 +15,7 @@
// CGAL
#include <CGAL/make_surface_mesh.h>
#include <CGAL/Implicit_surface_3.h>
#include <CGAL/Polyhedron_3.h>
#include <CGAL/IO/Polyhedron_iostream.h>
#include <CGAL/IO/File_scanner_OFF.h>
#include <CGAL/Timer.h>
@ -242,28 +243,24 @@ BOOL CPoissonDoc::OnOpenDocument(LPCTSTR lpszPathName)
// Read OFF file as a mesh and compute normals from connectivity
if (is_mesh)
{
// read file in polyhedron
typedef Enriched_polyhedron<Kernel> Polyhedron;
// Read the mesh file in a polyhedron
std::ifstream stream(lpszPathName);
typedef CGAL::Polyhedron_3<Kernel> Polyhedron;
Polyhedron input_mesh;
std::ifstream file_stream(lpszPathName);
CGAL::scan_OFF(file_stream, input_mesh, true /* verbose */);
if(!file_stream || !input_mesh.is_valid() || input_mesh.empty())
CGAL::scan_OFF(stream, input_mesh, true /* verbose */);
if(!stream || !input_mesh.is_valid() || input_mesh.empty())
{
prompt_message("Unable to read file");
return FALSE;
}
// Compute normals using mesh connectivity
input_mesh.compute_normals();
// Copy points to m_points
Polyhedron::Vertex_iterator v;
for(v = input_mesh.vertices_begin();
v != input_mesh.vertices_end();
v++)
// Convert Polyhedron vertices to point set.
// Compute vertices' normals from connectivity.
Polyhedron::Vertex_const_iterator v;
for (v = input_mesh.vertices_begin(); v != input_mesh.vertices_end(); v++)
{
const Point& p = v->point();
const Vector& n = v->normal();
Vector n = compute_vertex_normal<Polyhedron::Vertex,Kernel>(*v);
m_points.push_back(Point_with_normal(p,n));
}
}

View File

@ -0,0 +1,45 @@
#ifndef _COMPUTE_NORMAL_
#define _COMPUTE_NORMAL_
template <class Facet, class Kernel>
typename Kernel::Vector_3 compute_facet_normal(const Facet& f)
{
typedef typename Kernel::Point_3 Point;
typedef typename Kernel::Vector_3 Vector;
typedef typename Facet::Halfedge_around_facet_const_circulator HF_circulator;
Vector normal = CGAL::NULL_VECTOR;
HF_circulator he = f.facet_begin();
HF_circulator end = he;
CGAL_For_all(he,end)
{
const Point& prev = he->prev()->vertex()->point();
const Point& curr = he->vertex()->point();
const Point& next = he->next()->vertex()->point();
Vector n = CGAL::cross_product(next-curr,prev-curr);
normal = normal + (n / std::sqrt(n*n));
}
return normal / std::sqrt(normal * normal);
}
template <class Vertex, class Kernel>
typename Kernel::Vector_3 compute_vertex_normal(const Vertex& v)
{
typedef typename Kernel::Point_3 Point;
typedef typename Kernel::Vector_3 Vector;
typedef typename Vertex::Halfedge_around_vertex_const_circulator HV_circulator;
typedef typename Vertex::Facet Facet;
Vector normal = CGAL::NULL_VECTOR;
HV_circulator he = v.vertex_begin();
HV_circulator end = he;
CGAL_For_all(he,end)
{
if(!he->is_border())
{
Vector n = compute_facet_normal<Facet,Kernel>(*he->facet());
normal = normal + (n / std::sqrt(n*n));
}
}
return normal / std::sqrt(normal * normal);
}
#endif // _COMPUTE_NORMAL_

View File

@ -1,272 +0,0 @@
///////////////////////////////////////////////////////////////////////////
// //
// Class: Enriched_polyhedron //
// //
///////////////////////////////////////////////////////////////////////////
#ifndef _POLYGON_MESH_
#define _POLYGON_MESH_
// CGAL
#include <CGAL/Cartesian.h>
#include <CGAL/Polyhedron_3.h>
#include <list>
// Forward declarations
struct Vertex_normal;
struct Facet_normal;
// a refined facet with a normal
template <class Refs, class Tag, class Point_3_, class Norm>
class Enriched_facet : public CGAL::HalfedgeDS_face_base<Refs, Tag>
{
// normal
Norm m_normal;
public:
// life cycle
Enriched_facet()
{
}
// normal
typedef Norm Normal_3;
Normal_3& normal() { return m_normal; }
const Normal_3& normal() const { return m_normal; }
};
// a refined halfedge with a general tag
template <class Refs, class Tprev, class Tvertex, class Tface, class Norm>
class Enriched_halfedge : public CGAL::HalfedgeDS_halfedge_base<Refs,Tprev,Tvertex,Tface>
{
private:
public:
// life cycle
Enriched_halfedge()
{
}
};
// a refined vertex with a normal, tag and camera
template <class Refs, class Tag, class Point_3_, class Norm>
class Enriched_vertex : public CGAL::HalfedgeDS_vertex_base<Refs, Tag, Point_3_>
{
// normal
Norm m_normal;
public:
// life cycle
Enriched_vertex() {}
// repeat mandatory constructors
Enriched_vertex(const Point_3_& pt)
: CGAL::HalfedgeDS_vertex_base<Refs, Tag, Point_3_>(pt)
{
}
// normal
typedef Norm Normal_3;
Normal_3& normal() { return m_normal; }
const Normal_3& normal() const { return m_normal; }
};
// A redefined items class for the Polyhedron_3
// with a refined vertex class that contains a
// member for the normal vector and a refined
// facet with a normal vector instead of the
// plane equation (this is an alternative
// solution instead of using
// Polyhedron_traits_with_normals_3).
struct Enriched_items : public CGAL::Polyhedron_items_3
{
// wrap vertex
template <class Refs, class Traits>
struct Vertex_wrapper
{
typedef typename Traits::Point_3 Point;
typedef typename Traits::Vector_3 Normal;
typedef Enriched_vertex<Refs,
CGAL::Tag_true,
Point,
Normal> Vertex;
};
// wrap face
template <class Refs, class Traits>
struct Face_wrapper
{
typedef typename Traits::Point_3 Point;
typedef typename Traits::Vector_3 Normal;
typedef Enriched_facet<Refs,
CGAL::Tag_true,
Point,
Normal> Face;
};
// wrap halfedge
template <class Refs, class Traits>
struct Halfedge_wrapper
{
typedef typename Traits::Vector_3 Normal;
typedef Enriched_halfedge<Refs,
CGAL::Tag_true,
CGAL::Tag_true,
CGAL::Tag_true,
Normal> Halfedge;
};
};
// Enriched polyhedron
template <class PolyhedronTraits_3,
class PolyhedronItems_3 = Enriched_items>
class Enriched_polyhedron
: public CGAL::Polyhedron_3<PolyhedronTraits_3, PolyhedronItems_3>
{
// Private types
private:
typedef CGAL::Polyhedron_3<PolyhedronTraits_3, PolyhedronItems_3> Base;
// Auxiliary class to build a triangles iterator
template <class Node> // Node is Facet
struct Project_triangle {
typedef Node argument_type;
typedef typename PolyhedronTraits_3::Triangle_3 Triangle;
typedef Triangle result_type;
typedef typename PolyhedronTraits_3::Point_3 Point;
Triangle operator()(const Node& f) const {
Halfedge_const_handle he = f.halfedge();
const Point& a = he->vertex()->point();
const Point& b = he->next()->vertex()->point();
const Point& c = he->next()->next()->vertex()->point();
return Triangle(a,b,c);
}
};
// Public types
public:
typedef typename PolyhedronTraits_3::FT FT;
typedef typename PolyhedronTraits_3::Point_3 Point;
// Repeat Polyhedron_3 public types
typedef typename Base::HalfedgeDS HalfedgeDS;
typedef typename Base::Vertex Vertex;
typedef typename Base::Halfedge Halfedge;
typedef typename Base::Facet Facet;
typedef typename Base::Vertex_handle Vertex_handle;
typedef typename Base::Vertex_const_handle Vertex_const_handle;
typedef typename Base::Halfedge_handle Halfedge_handle;
typedef typename Base::Halfedge_const_handle Halfedge_const_handle;
typedef typename Base::Facet_handle Facet_handle;
typedef typename Base::Facet_const_handle Facet_const_handle;
typedef typename Base::Vertex_iterator Vertex_iterator;
typedef typename Base::Vertex_const_iterator Vertex_const_iterator;
typedef typename Base::Halfedge_iterator Halfedge_iterator;
typedef typename Base::Halfedge_const_iterator Halfedge_const_iterator;
typedef typename Base::Facet_iterator Facet_iterator;
typedef typename Base::Facet_const_iterator Facet_const_iterator;
typedef typename Base::Point_iterator Point_iterator;
typedef typename Base::Point_const_iterator Point_const_iterator;
typedef typename Base::Halfedge_around_facet_circulator Halfedge_around_facet_circulator;
typedef typename Base::Halfedge_around_facet_const_circulator Halfedge_around_facet_const_circulator;
typedef typename Base::Halfedge_around_vertex_circulator Halfedge_around_vertex_circulator;
typedef typename Base::Halfedge_around_vertex_const_circulator Halfedge_around_vertex_const_circulator;
// Iterator over triangles
typedef CGAL::Iterator_project<Facet_const_iterator, Project_triangle<Facet> >
Triangle_const_iterator;
public :
// Default constructor, copy constructor and operator =() are fine.
// Repeat Delaunay_triangulation_3 public methods
Base::halfedges_begin;
Base::halfedges_end;
Base::facets_begin;
Base::facets_end;
Base::vertices_begin;
Base::vertices_end;
// Get first/last iterators over triangles.
Triangle_const_iterator triangles_begin() const { return Triangle_const_iterator(facets_begin()); }
Triangle_const_iterator triangles_end() const { return Triangle_const_iterator(facets_end()); }
// Compute normals using mesh connectivity (per facet, then per vertex)
void compute_normals_per_facet()
{
std::for_each(facets_begin(),facets_end(),Facet_normal());
}
void compute_normals_per_vertex()
{
std::for_each(vertices_begin(),vertices_end(),Vertex_normal());
}
void compute_normals()
{
compute_normals_per_facet();
compute_normals_per_vertex();
}
};
// compute facet normal (functor)
struct Facet_normal
{
template <class Facet>
void operator()(Facet& f)
{
typename Facet::Normal_3 sum = CGAL::NULL_VECTOR;
typename Facet::Halfedge_around_facet_circulator h = f.facet_begin();
do
{
typename Facet::Normal_3 normal = CGAL::cross_product(
h->next()->vertex()->point() - h->vertex()->point(),
h->next()->next()->vertex()->point() - h->next()->vertex()->point());
double sqnorm = normal * normal;
if(sqnorm != 0)
normal = normal / (double)std::sqrt(sqnorm);
sum = sum + normal;
}
while(++h != f.facet_begin());
double sqnorm = sum * sum;
if(sqnorm != 0.0)
f.normal() = sum / std::sqrt(sqnorm);
else
{
f.normal() = CGAL::NULL_VECTOR;
std::cerr << "degenerate face\n";
}
}
};
// compute vertex normal (functor)
struct Vertex_normal
{
template <class Vertex>
void operator()(Vertex& v)
{
typename Vertex::Normal_3 normal = CGAL::NULL_VECTOR;
typename Vertex::Halfedge_around_vertex_const_circulator pHalfedge = v.vertex_begin();
typename Vertex::Halfedge_around_vertex_const_circulator begin = pHalfedge;
CGAL_For_all(pHalfedge,begin)
if(!pHalfedge->is_border())
normal = normal + pHalfedge->facet()->normal();
double sqnorm = normal * normal;
if(sqnorm != 0.0f)
v.normal() = normal / (float)std::sqrt(sqnorm);
else
v.normal() = CGAL::NULL_VECTOR;
}
};
#endif // _POLYGON_MESH_

View File

@ -11,6 +11,7 @@
// CGAL
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Timer.h>
#include <CGAL/Polyhedron_3.h>
#include <CGAL/IO/Polyhedron_iostream.h>
#include <CGAL/Surface_mesh_default_triangulation_3.h>
#include <CGAL/make_surface_mesh.h>
@ -23,7 +24,7 @@
#include <CGAL/Point_with_normal_3.h>
#include <CGAL/IO/read_xyz_point_set.h>
#include "enriched_polyhedron.h"
#include "compute_normal.h"
#include <deque>
#include <cstdlib>
@ -114,12 +115,13 @@ int main(int argc, char * argv[])
PointList points;
// If OFF file format
std::cerr << "Open " << input_filename << " for reading..." << std::endl;
std::string extension = input_filename.substr(input_filename.find_last_of('.'));
if (extension == ".off" || extension == ".OFF")
{
// Read the mesh file in a polyhedron
std::ifstream stream(input_filename.c_str());
typedef Enriched_polyhedron<Kernel,Enriched_items> Polyhedron;
typedef CGAL::Polyhedron_3<Kernel> Polyhedron;
Polyhedron input_mesh;
CGAL::scan_OFF(stream, input_mesh, true /* verbose */);
if(!stream || !input_mesh.is_valid() || input_mesh.empty())
@ -128,15 +130,13 @@ int main(int argc, char * argv[])
return EXIT_FAILURE;
}
// Compute vertices' normals from connectivity
input_mesh.compute_normals();
// Convert vertices and normals to PointList
Polyhedron::Vertex_iterator v;
// Convert Polyhedron vertices to point set.
// Compute vertices' normals from connectivity.
Polyhedron::Vertex_const_iterator v;
for (v = input_mesh.vertices_begin(); v != input_mesh.vertices_end(); v++)
{
const Point& p = v->point();
const Vector& n = v->normal();
Vector n = compute_vertex_normal<Polyhedron::Vertex,Kernel>(*v);
points.push_back(Point_with_normal(p,n));
}
}

View File

@ -0,0 +1,45 @@
#ifndef _COMPUTE_NORMAL_
#define _COMPUTE_NORMAL_
template <class Facet, class Kernel>
typename Kernel::Vector_3 compute_facet_normal(const Facet& f)
{
typedef typename Kernel::Point_3 Point;
typedef typename Kernel::Vector_3 Vector;
typedef typename Facet::Halfedge_around_facet_const_circulator HF_circulator;
Vector normal = CGAL::NULL_VECTOR;
HF_circulator he = f.facet_begin();
HF_circulator end = he;
CGAL_For_all(he,end)
{
const Point& prev = he->prev()->vertex()->point();
const Point& curr = he->vertex()->point();
const Point& next = he->next()->vertex()->point();
Vector n = CGAL::cross_product(next-curr,prev-curr);
normal = normal + (n / std::sqrt(n*n));
}
return normal / std::sqrt(normal * normal);
}
template <class Vertex, class Kernel>
typename Kernel::Vector_3 compute_vertex_normal(const Vertex& v)
{
typedef typename Kernel::Point_3 Point;
typedef typename Kernel::Vector_3 Vector;
typedef typename Vertex::Halfedge_around_vertex_const_circulator HV_circulator;
typedef typename Vertex::Facet Facet;
Vector normal = CGAL::NULL_VECTOR;
HV_circulator he = v.vertex_begin();
HV_circulator end = he;
CGAL_For_all(he,end)
{
if(!he->is_border())
{
Vector n = compute_facet_normal<Facet,Kernel>(*he->facet());
normal = normal + (n / std::sqrt(n*n));
}
}
return normal / std::sqrt(normal * normal);
}
#endif // _COMPUTE_NORMAL_

View File

@ -1,247 +0,0 @@
///////////////////////////////////////////////////////////////////////////
// //
// Class: Enriched_polyhedron //
// //
///////////////////////////////////////////////////////////////////////////
#ifndef _POLYGON_MESH_
#define _POLYGON_MESH_
// CGAL
#include <CGAL/Cartesian.h>
#include <CGAL/Polyhedron_3.h>
#include <list>
// Forward declarations
struct Vertex_normal;
struct Facet_normal;
// a refined facet with a normal
template <class Refs, class Tag, class Point_3_, class Norm>
class Enriched_facet : public CGAL::HalfedgeDS_face_base<Refs, Tag>
{
// normal
Norm m_normal;
public:
// life cycle
Enriched_facet()
{
}
// normal
typedef Norm Normal_3;
Normal_3& normal() { return m_normal; }
const Normal_3& normal() const { return m_normal; }
};
// a refined halfedge with a general tag
template <class Refs, class Tprev, class Tvertex, class Tface, class Norm>
class Enriched_halfedge : public CGAL::HalfedgeDS_halfedge_base<Refs,Tprev,Tvertex,Tface>
{
private:
public:
// life cycle
Enriched_halfedge()
{
}
};
// a refined vertex with a normal, tag and camera
template <class Refs, class Tag, class Point_3_, class Norm>
class Enriched_vertex : public CGAL::HalfedgeDS_vertex_base<Refs, Tag, Point_3_>
{
// normal
Norm m_normal;
public:
// life cycle
Enriched_vertex() {}
// repeat mandatory constructors
Enriched_vertex(const Point_3_& pt)
: CGAL::HalfedgeDS_vertex_base<Refs, Tag, Point_3_>(pt)
{
}
// normal
typedef Norm Normal_3;
Normal_3& normal() { return m_normal; }
const Normal_3& normal() const { return m_normal; }
};
// A redefined items class for the Polyhedron_3
// with a refined vertex class that contains a
// member for the normal vector and a refined
// facet with a normal vector instead of the
// plane equation (this is an alternative
// solution instead of using
// Polyhedron_traits_with_normals_3).
struct Enriched_items : public CGAL::Polyhedron_items_3
{
// wrap vertex
template <class Refs, class Traits>
struct Vertex_wrapper
{
typedef typename Traits::Point_3 Point;
typedef typename Traits::Vector_3 Normal;
typedef Enriched_vertex<Refs,
CGAL::Tag_true,
Point,
Normal> Vertex;
};
// wrap face
template <class Refs, class Traits>
struct Face_wrapper
{
typedef typename Traits::Point_3 Point;
typedef typename Traits::Vector_3 Normal;
typedef Enriched_facet<Refs,
CGAL::Tag_true,
Point,
Normal> Face;
};
// wrap halfedge
template <class Refs, class Traits>
struct Halfedge_wrapper
{
typedef typename Traits::Vector_3 Normal;
typedef Enriched_halfedge<Refs,
CGAL::Tag_true,
CGAL::Tag_true,
CGAL::Tag_true,
Normal> Halfedge;
};
};
// Enriched polyhedron
template <class PolyhedronTraits_3,
class PolyhedronItems_3 = Enriched_items>
class Enriched_polyhedron
: public CGAL::Polyhedron_3<PolyhedronTraits_3, PolyhedronItems_3>
{
// Private types
private:
typedef CGAL::Polyhedron_3<PolyhedronTraits_3, PolyhedronItems_3> Base;
// Public types
public:
typedef typename PolyhedronTraits_3::FT FT;
typedef typename PolyhedronTraits_3::Point_3 Point;
// Repeat Polyhedron_3 public types
typedef typename Base::HalfedgeDS HalfedgeDS;
typedef typename Base::Vertex Vertex;
typedef typename Base::Halfedge Halfedge;
typedef typename Base::Facet Facet;
typedef typename Base::Vertex_handle Vertex_handle;
typedef typename Base::Vertex_const_handle Vertex_const_handle;
typedef typename Base::Halfedge_handle Halfedge_handle;
typedef typename Base::Halfedge_const_handle Halfedge_const_handle;
typedef typename Base::Facet_handle Facet_handle;
typedef typename Base::Facet_const_handle Facet_const_handle;
typedef typename Base::Vertex_iterator Vertex_iterator;
typedef typename Base::Vertex_const_iterator Vertex_const_iterator;
typedef typename Base::Halfedge_iterator Halfedge_iterator;
typedef typename Base::Halfedge_const_iterator Halfedge_const_iterator;
typedef typename Base::Facet_iterator Facet_iterator;
typedef typename Base::Facet_const_iterator Facet_const_iterator;
typedef typename Base::Point_iterator Point_iterator;
typedef typename Base::Point_const_iterator Point_const_iterator;
typedef typename Base::Halfedge_around_facet_circulator Halfedge_around_facet_circulator;
typedef typename Base::Halfedge_around_facet_const_circulator Halfedge_around_facet_const_circulator;
typedef typename Base::Halfedge_around_vertex_circulator Halfedge_around_vertex_circulator;
typedef typename Base::Halfedge_around_vertex_const_circulator Halfedge_around_vertex_const_circulator;
public :
// Default constructor, copy constructor and operator =() are fine.
// Repeat Delaunay_triangulation_3 public methods
Base::halfedges_begin;
Base::halfedges_end;
Base::facets_begin;
Base::facets_end;
Base::vertices_begin;
Base::vertices_end;
// Compute normals using mesh connectivity (per facet, then per vertex)
void compute_normals_per_facet()
{
std::for_each(facets_begin(),facets_end(),Facet_normal());
}
void compute_normals_per_vertex()
{
std::for_each(vertices_begin(),vertices_end(),Vertex_normal());
}
void compute_normals()
{
compute_normals_per_facet();
compute_normals_per_vertex();
}
};
// compute facet normal (functor)
struct Facet_normal
{
template <class Facet>
void operator()(Facet& f)
{
typename Facet::Normal_3 sum = CGAL::NULL_VECTOR;
typename Facet::Halfedge_around_facet_circulator h = f.facet_begin();
do
{
typename Facet::Normal_3 normal = CGAL::cross_product(
h->next()->vertex()->point() - h->vertex()->point(),
h->next()->next()->vertex()->point() - h->next()->vertex()->point());
double sqnorm = normal * normal;
if(sqnorm != 0)
normal = normal / (double)std::sqrt(sqnorm);
sum = sum + normal;
}
while(++h != f.facet_begin());
double sqnorm = sum * sum;
if(sqnorm != 0.0)
f.normal() = sum / std::sqrt(sqnorm);
else
{
f.normal() = CGAL::NULL_VECTOR;
std::cerr << "degenerate face\n";
}
}
};
// compute vertex normal (functor)
struct Vertex_normal
{
template <class Vertex>
void operator()(Vertex& v)
{
typename Vertex::Normal_3 normal = CGAL::NULL_VECTOR;
typename Vertex::Halfedge_around_vertex_const_circulator pHalfedge = v.vertex_begin();
typename Vertex::Halfedge_around_vertex_const_circulator begin = pHalfedge;
CGAL_For_all(pHalfedge,begin)
if(!pHalfedge->is_border())
normal = normal + pHalfedge->facet()->normal();
double sqnorm = normal * normal;
if(sqnorm != 0.0f)
v.normal() = normal / (float)std::sqrt(sqnorm);
else
v.normal() = CGAL::NULL_VECTOR;
}
};
#endif // _POLYGON_MESH_

View File

@ -11,6 +11,7 @@
// CGAL
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Timer.h>
#include <CGAL/Polyhedron_3.h>
#include <CGAL/IO/Polyhedron_iostream.h>
#include <CGAL/Surface_mesh_default_triangulation_3.h>
#include <CGAL/make_surface_mesh.h>
@ -23,7 +24,7 @@
#include <CGAL/Point_with_normal_3.h>
#include <CGAL/IO/read_xyz_point_set.h>
#include "enriched_polyhedron.h"
#include "compute_normal.h"
#include <deque>
#include <cstdlib>
@ -109,12 +110,13 @@ int main(int argc, char * argv[])
PointList points;
// If OFF file format
std::cerr << "Open " << input_filename << " for reading..." << std::endl;
std::string extension = input_filename.substr(input_filename.find_last_of('.'));
if (extension == ".off" || extension == ".OFF")
{
// Read the mesh file in a polyhedron
std::ifstream stream(input_filename.c_str());
typedef Enriched_polyhedron<Kernel,Enriched_items> Polyhedron;
typedef CGAL::Polyhedron_3<Kernel> Polyhedron;
Polyhedron input_mesh;
CGAL::scan_OFF(stream, input_mesh, true /* verbose */);
if(!stream || !input_mesh.is_valid() || input_mesh.empty())
@ -123,15 +125,13 @@ int main(int argc, char * argv[])
return EXIT_FAILURE;
}
// Compute vertices' normals from connectivity
input_mesh.compute_normals();
// Convert vertices and normals to PointList
Polyhedron::Vertex_iterator v;
// Convert Polyhedron vertices to point set.
// Compute vertices' normals from connectivity.
Polyhedron::Vertex_const_iterator v;
for (v = input_mesh.vertices_begin(); v != input_mesh.vertices_end(); v++)
{
const Point& p = v->point();
const Vector& n = v->normal();
Vector n = compute_vertex_normal<Polyhedron::Vertex,Kernel>(*v);
points.push_back(Point_with_normal(p,n));
}
}

View File

@ -0,0 +1,177 @@
// Copyright (c) 2005-2009 INRIA (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org); you may redistribute it under
// the terms of the Q Public License version 1.0.
// See the file LICENSE.QPL distributed with CGAL.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $URL$
// $Id$
//
//
// Author(s) : Laurent Saboret, Pierre Alliez
#ifndef CGAL_POLYHEDRON_CONNECTED_COMPONENTS_H
#define CGAL_POLYHEDRON_CONNECTED_COMPONENTS_H
#include <CGAL/Polyhedron_3.h>
#include <map>
#include <list>
CGAL_BEGIN_NAMESPACE
// ----------------------------------------------------------------------------
// Private section
// ----------------------------------------------------------------------------
namespace CGALi {
/// Get any vertex with tag == tag_value.
///
/// @commentheading Template Parameters:
/// @param Polyhedron an instance of CGAL::Polyhedron_3<>.
///
/// @return a list of pairs (component size, a vertex of the component),
/// ordered by size.
template<class Polyhedron>
typename Polyhedron::Vertex_handle
get_any_vertex_tag(Polyhedron& polyhedron,
std::map<typename Polyhedron::Vertex*, int>& tags,
const int tag_value)
{
typedef typename Polyhedron::Vertex_handle Vertex_handle;
typedef typename Polyhedron::Vertex_iterator Vertex_iterator;
for (Vertex_iterator it = polyhedron.vertices_begin();
it != polyhedron.vertices_end();
it++)
{
if (tags[&*it] == tag_value)
return it;
}
return NULL;
}
/// Tag a "free" connected component as "done".
///
/// @commentheading Template Parameters:
/// @param Polyhedron an instance of CGAL::Polyhedron_3<>.
///
/// @return the size (number of vertices) of the component.
template<class Polyhedron>
unsigned int tag_component(Polyhedron& polyhedron,
typename Polyhedron::Vertex_handle pSeedVertex,
std::map<typename Polyhedron::Vertex*, int>& tags,
const int tag_free,
const int tag_done)
{
typedef typename Polyhedron::Vertex_handle Vertex_handle;
typedef typename Polyhedron::Vertex_iterator Vertex_iterator;
typedef typename Polyhedron::Halfedge_around_vertex_circulator
Halfedge_around_vertex_circulator;
unsigned int number_of_vertices = 0; // size (number of vertices) of the component
std::list<Vertex_handle> vertices;
vertices.push_front(pSeedVertex);
while (!vertices.empty())
{
Vertex_handle pVertex = vertices.front();
vertices.pop_front();
// Skip vertex if already done
if (tags[&*pVertex] == tag_done)
continue;
// Mark vertex done
tags[&*pVertex] = tag_done;
number_of_vertices++;
// Add free neighbors to the list
Halfedge_around_vertex_circulator cir, cir_end;
cir = pVertex->vertex_begin();
cir_end = cir;
CGAL_For_all(cir,cir_end)
{
Vertex_handle neighbor = cir->opposite()->vertex();
if (tags[&*neighbor] == tag_free)
vertices.push_front(neighbor);
}
}
return number_of_vertices;
}
} /* namespace CGALi */
// ----------------------------------------------------------------------------
// Public section
// ----------------------------------------------------------------------------
/// Compute the list of all connected components of a polyhedron.
///
/// @commentheading Template Parameters:
/// @param Polyhedron an instance of CGAL::Polyhedron_3<> that supports positions.
///
/// @return a list of pairs (component size, a halfedge of the component),
/// ordered by size.
template<class Polyhedron>
std::multimap<unsigned int, typename Polyhedron::Halfedge_handle>
get_polyhedron_connected_components(Polyhedron& polyhedron)
{
// Implementation note:
// We tag vertices instead of halfedges to save a factor 6.
// The drawback is that we require the Polyhedron_3<> to support positions.
// TODO: replace std::map to tag vertices by a property map.
Assert_compile_time_tag(Polyhedron::Supports_halfedge_vertex(), Tag_true());
std::map<typename Polyhedron::Vertex*, int> tags;
typedef typename Polyhedron::Halfedge_handle Halfedge_handle;
typedef typename Polyhedron::Vertex_handle Vertex_handle;
typedef typename Polyhedron::Vertex_iterator Vertex_iterator;
/// list of all connected components of a polyhedron, ordered by size.
std::multimap<unsigned int, Halfedge_handle> components;
// Tag all mesh vertices as "free".
const int tag_free = 0;
const int tag_done = 1;
for (Vertex_iterator it = polyhedron.vertices_begin();
it != polyhedron.vertices_end();
it++)
{
tags[&*it] = tag_free;
}
// For each component
Vertex_handle seed_vertex = NULL;
while((seed_vertex = CGALi::get_any_vertex_tag(polyhedron, tags, tag_free)) != NULL)
{
// Tag it as "done" and compute its size
unsigned int component_size = CGALi::tag_component(polyhedron, seed_vertex, tags, tag_free, tag_done);
// Add component to list, ordered by size
components.insert(std::make_pair(component_size, seed_vertex->halfedge()));
}
return components;
}
CGAL_END_NAMESPACE
#endif // CGAL_POLYHEDRON_CONNECTED_COMPONENTS_H

View File

@ -11,6 +11,7 @@
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Timer.h>
#include <CGAL/Memory_sizer.h>
#include <CGAL/Polyhedron_3.h>
#include <CGAL/IO/Polyhedron_iostream.h>
#include <CGAL/Surface_mesh_default_triangulation_3.h>
#include <CGAL/make_surface_mesh.h>
@ -21,7 +22,7 @@
#include <CGAL/Point_with_normal_3.h>
#include <CGAL/IO/read_xyz_point_set.h>
#include "enriched_polyhedron.h"
#include "compute_normal.h"
#include <deque>
#include <cstdlib>
@ -102,12 +103,13 @@ int main(int argc, char * argv[])
PointList points;
// If OFF file format
std::cerr << "Open " << input_filename << " for reading..." << std::endl;
std::string extension = input_filename.substr(input_filename.find_last_of('.'));
if (extension == ".off" || extension == ".OFF")
{
// Read the mesh file in a polyhedron
std::ifstream stream(input_filename.c_str());
typedef Enriched_polyhedron<Kernel,Enriched_items> Polyhedron;
typedef CGAL::Polyhedron_3<Kernel> Polyhedron;
Polyhedron input_mesh;
CGAL::scan_OFF(stream, input_mesh, true /* verbose */);
if(!stream || !input_mesh.is_valid() || input_mesh.empty())
@ -117,15 +119,13 @@ int main(int argc, char * argv[])
continue;
}
// Compute vertices' normals from connectivity
input_mesh.compute_normals();
// Convert vertices and normals to PointList
Polyhedron::Vertex_iterator v;
// Convert Polyhedron vertices to point set.
// Compute vertices' normals from connectivity.
Polyhedron::Vertex_const_iterator v;
for (v = input_mesh.vertices_begin(); v != input_mesh.vertices_end(); v++)
{
const Point& p = v->point();
const Vector& n = v->normal();
Vector n = compute_vertex_normal<Polyhedron::Vertex,Kernel>(*v);
points.push_back(Point_with_normal(p,n));
}
}

View File

@ -0,0 +1,45 @@
#ifndef _COMPUTE_NORMAL_
#define _COMPUTE_NORMAL_
template <class Facet, class Kernel>
typename Kernel::Vector_3 compute_facet_normal(const Facet& f)
{
typedef typename Kernel::Point_3 Point;
typedef typename Kernel::Vector_3 Vector;
typedef typename Facet::Halfedge_around_facet_const_circulator HF_circulator;
Vector normal = CGAL::NULL_VECTOR;
HF_circulator he = f.facet_begin();
HF_circulator end = he;
CGAL_For_all(he,end)
{
const Point& prev = he->prev()->vertex()->point();
const Point& curr = he->vertex()->point();
const Point& next = he->next()->vertex()->point();
Vector n = CGAL::cross_product(next-curr,prev-curr);
normal = normal + (n / std::sqrt(n*n));
}
return normal / std::sqrt(normal * normal);
}
template <class Vertex, class Kernel>
typename Kernel::Vector_3 compute_vertex_normal(const Vertex& v)
{
typedef typename Kernel::Point_3 Point;
typedef typename Kernel::Vector_3 Vector;
typedef typename Vertex::Halfedge_around_vertex_const_circulator HV_circulator;
typedef typename Vertex::Facet Facet;
Vector normal = CGAL::NULL_VECTOR;
HV_circulator he = v.vertex_begin();
HV_circulator end = he;
CGAL_For_all(he,end)
{
if(!he->is_border())
{
Vector n = compute_facet_normal<Facet,Kernel>(*he->facet());
normal = normal + (n / std::sqrt(n*n));
}
}
return normal / std::sqrt(normal * normal);
}
#endif // _COMPUTE_NORMAL_

View File

@ -1,247 +0,0 @@
///////////////////////////////////////////////////////////////////////////
// //
// Class: Enriched_polyhedron //
// //
///////////////////////////////////////////////////////////////////////////
#ifndef _POLYGON_MESH_
#define _POLYGON_MESH_
// CGAL
#include <CGAL/Cartesian.h>
#include <CGAL/Polyhedron_3.h>
#include <list>
// Forward declarations
struct Vertex_normal;
struct Facet_normal;
// a refined facet with a normal
template <class Refs, class Tag, class Point_3_, class Norm>
class Enriched_facet : public CGAL::HalfedgeDS_face_base<Refs, Tag>
{
// normal
Norm m_normal;
public:
// life cycle
Enriched_facet()
{
}
// normal
typedef Norm Normal_3;
Normal_3& normal() { return m_normal; }
const Normal_3& normal() const { return m_normal; }
};
// a refined halfedge with a general tag
template <class Refs, class Tprev, class Tvertex, class Tface, class Norm>
class Enriched_halfedge : public CGAL::HalfedgeDS_halfedge_base<Refs,Tprev,Tvertex,Tface>
{
private:
public:
// life cycle
Enriched_halfedge()
{
}
};
// a refined vertex with a normal, tag and camera
template <class Refs, class Tag, class Point_3_, class Norm>
class Enriched_vertex : public CGAL::HalfedgeDS_vertex_base<Refs, Tag, Point_3_>
{
// normal
Norm m_normal;
public:
// life cycle
Enriched_vertex() {}
// repeat mandatory constructors
Enriched_vertex(const Point_3_& pt)
: CGAL::HalfedgeDS_vertex_base<Refs, Tag, Point_3_>(pt)
{
}
// normal
typedef Norm Normal_3;
Normal_3& normal() { return m_normal; }
const Normal_3& normal() const { return m_normal; }
};
// A redefined items class for the Polyhedron_3
// with a refined vertex class that contains a
// member for the normal vector and a refined
// facet with a normal vector instead of the
// plane equation (this is an alternative
// solution instead of using
// Polyhedron_traits_with_normals_3).
struct Enriched_items : public CGAL::Polyhedron_items_3
{
// wrap vertex
template <class Refs, class Traits>
struct Vertex_wrapper
{
typedef typename Traits::Point_3 Point;
typedef typename Traits::Vector_3 Normal;
typedef Enriched_vertex<Refs,
CGAL::Tag_true,
Point,
Normal> Vertex;
};
// wrap face
template <class Refs, class Traits>
struct Face_wrapper
{
typedef typename Traits::Point_3 Point;
typedef typename Traits::Vector_3 Normal;
typedef Enriched_facet<Refs,
CGAL::Tag_true,
Point,
Normal> Face;
};
// wrap halfedge
template <class Refs, class Traits>
struct Halfedge_wrapper
{
typedef typename Traits::Vector_3 Normal;
typedef Enriched_halfedge<Refs,
CGAL::Tag_true,
CGAL::Tag_true,
CGAL::Tag_true,
Normal> Halfedge;
};
};
// Enriched polyhedron
template <class PolyhedronTraits_3,
class PolyhedronItems_3 = Enriched_items>
class Enriched_polyhedron
: public CGAL::Polyhedron_3<PolyhedronTraits_3, PolyhedronItems_3>
{
// Private types
private:
typedef CGAL::Polyhedron_3<PolyhedronTraits_3, PolyhedronItems_3> Base;
// Public types
public:
typedef typename PolyhedronTraits_3::FT FT;
typedef typename PolyhedronTraits_3::Point_3 Point;
// Repeat Polyhedron_3 public types
typedef typename Base::HalfedgeDS HalfedgeDS;
typedef typename Base::Vertex Vertex;
typedef typename Base::Halfedge Halfedge;
typedef typename Base::Facet Facet;
typedef typename Base::Vertex_handle Vertex_handle;
typedef typename Base::Vertex_const_handle Vertex_const_handle;
typedef typename Base::Halfedge_handle Halfedge_handle;
typedef typename Base::Halfedge_const_handle Halfedge_const_handle;
typedef typename Base::Facet_handle Facet_handle;
typedef typename Base::Facet_const_handle Facet_const_handle;
typedef typename Base::Vertex_iterator Vertex_iterator;
typedef typename Base::Vertex_const_iterator Vertex_const_iterator;
typedef typename Base::Halfedge_iterator Halfedge_iterator;
typedef typename Base::Halfedge_const_iterator Halfedge_const_iterator;
typedef typename Base::Facet_iterator Facet_iterator;
typedef typename Base::Facet_const_iterator Facet_const_iterator;
typedef typename Base::Point_iterator Point_iterator;
typedef typename Base::Point_const_iterator Point_const_iterator;
typedef typename Base::Halfedge_around_facet_circulator Halfedge_around_facet_circulator;
typedef typename Base::Halfedge_around_facet_const_circulator Halfedge_around_facet_const_circulator;
typedef typename Base::Halfedge_around_vertex_circulator Halfedge_around_vertex_circulator;
typedef typename Base::Halfedge_around_vertex_const_circulator Halfedge_around_vertex_const_circulator;
public :
// Default constructor, copy constructor and operator =() are fine.
// Repeat Delaunay_triangulation_3 public methods
Base::halfedges_begin;
Base::halfedges_end;
Base::facets_begin;
Base::facets_end;
Base::vertices_begin;
Base::vertices_end;
// Compute normals using mesh connectivity (per facet, then per vertex)
void compute_normals_per_facet()
{
std::for_each(facets_begin(),facets_end(),Facet_normal());
}
void compute_normals_per_vertex()
{
std::for_each(vertices_begin(),vertices_end(),Vertex_normal());
}
void compute_normals()
{
compute_normals_per_facet();
compute_normals_per_vertex();
}
};
// compute facet normal (functor)
struct Facet_normal
{
template <class Facet>
void operator()(Facet& f)
{
typename Facet::Normal_3 sum = CGAL::NULL_VECTOR;
typename Facet::Halfedge_around_facet_circulator h = f.facet_begin();
do
{
typename Facet::Normal_3 normal = CGAL::cross_product(
h->next()->vertex()->point() - h->vertex()->point(),
h->next()->next()->vertex()->point() - h->next()->vertex()->point());
double sqnorm = normal * normal;
if(sqnorm != 0)
normal = normal / (double)std::sqrt(sqnorm);
sum = sum + normal;
}
while(++h != f.facet_begin());
double sqnorm = sum * sum;
if(sqnorm != 0.0)
f.normal() = sum / std::sqrt(sqnorm);
else
{
f.normal() = CGAL::NULL_VECTOR;
std::cerr << "degenerate face\n";
}
}
};
// compute vertex normal (functor)
struct Vertex_normal
{
template <class Vertex>
void operator()(Vertex& v)
{
typename Vertex::Normal_3 normal = CGAL::NULL_VECTOR;
typename Vertex::Halfedge_around_vertex_const_circulator pHalfedge = v.vertex_begin();
typename Vertex::Halfedge_around_vertex_const_circulator begin = pHalfedge;
CGAL_For_all(pHalfedge,begin)
if(!pHalfedge->is_border())
normal = normal + pHalfedge->facet()->normal();
double sqnorm = normal * normal;
if(sqnorm != 0.0f)
v.normal() = normal / (float)std::sqrt(sqnorm);
else
v.normal() = CGAL::NULL_VECTOR;
}
};
#endif // _POLYGON_MESH_

View File

@ -11,6 +11,7 @@
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Timer.h>
#include <CGAL/Memory_sizer.h>
#include <CGAL/Polyhedron_3.h>
#include <CGAL/IO/Polyhedron_iostream.h>
#include <CGAL/Surface_mesh_default_triangulation_3.h>
#include <CGAL/make_surface_mesh.h>
@ -21,7 +22,7 @@
#include <CGAL/Point_with_normal_3.h>
#include <CGAL/IO/read_xyz_point_set.h>
#include "enriched_polyhedron.h"
#include "compute_normal.h"
#include <deque>
#include <cstdlib>
@ -101,12 +102,13 @@ int main(int argc, char * argv[])
PointList points;
// If OFF file format
std::cerr << "Open " << input_filename << " for reading..." << std::endl;
std::string extension = input_filename.substr(input_filename.find_last_of('.'));
if (extension == ".off" || extension == ".OFF")
{
// Read the mesh file in a polyhedron
std::ifstream stream(input_filename.c_str());
typedef Enriched_polyhedron<Kernel,Enriched_items> Polyhedron;
typedef CGAL::Polyhedron_3<Kernel> Polyhedron;
Polyhedron input_mesh;
CGAL::scan_OFF(stream, input_mesh, true /* verbose */);
if(!stream || !input_mesh.is_valid() || input_mesh.empty())
@ -116,15 +118,13 @@ int main(int argc, char * argv[])
continue;
}
// Compute vertices' normals from connectivity
input_mesh.compute_normals();
// Convert vertices and normals to PointList
Polyhedron::Vertex_iterator v;
// Convert Polyhedron vertices to point set.
// Compute vertices' normals from connectivity.
Polyhedron::Vertex_const_iterator v;
for (v = input_mesh.vertices_begin(); v != input_mesh.vertices_end(); v++)
{
const Point& p = v->point();
const Vector& n = v->normal();
Vector n = compute_vertex_normal<Polyhedron::Vertex,Kernel>(*v);
points.push_back(Point_with_normal(p,n));
}
}