mirror of https://github.com/CGAL/cgal
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:
parent
5e81b086c8
commit
c6ad02b857
|
|
@ -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_
|
||||||
|
|
@ -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_
|
|
||||||
|
|
@ -12,8 +12,8 @@
|
||||||
// CGAL
|
// CGAL
|
||||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||||
#include <CGAL/Timer.h>
|
#include <CGAL/Timer.h>
|
||||||
#include <CGAL/Memory_sizer.h>
|
|
||||||
#include <CGAL/boost/graph/properties.h>
|
#include <CGAL/boost/graph/properties.h>
|
||||||
|
#include <CGAL/Polyhedron_3.h>
|
||||||
#include <CGAL/IO/Polyhedron_iostream.h>
|
#include <CGAL/IO/Polyhedron_iostream.h>
|
||||||
|
|
||||||
// This package
|
// This package
|
||||||
|
|
@ -25,12 +25,11 @@
|
||||||
#include <CGAL/IO/read_xyz_point_set.h>
|
#include <CGAL/IO/read_xyz_point_set.h>
|
||||||
#include <CGAL/IO/write_xyz_point_set.h>
|
#include <CGAL/IO/write_xyz_point_set.h>
|
||||||
|
|
||||||
#include "enriched_polyhedron.h"
|
#include "compute_normal.h"
|
||||||
|
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <cassert>
|
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
@ -222,12 +221,13 @@ int main(int argc, char * argv[])
|
||||||
PointList points;
|
PointList points;
|
||||||
|
|
||||||
// If OFF file format
|
// If OFF file format
|
||||||
|
std::cerr << "Open " << input_filename << " for reading..." << std::endl;
|
||||||
std::string extension = input_filename.substr(input_filename.find_last_of('.'));
|
std::string extension = input_filename.substr(input_filename.find_last_of('.'));
|
||||||
if (extension == ".off" || extension == ".OFF")
|
if (extension == ".off" || extension == ".OFF")
|
||||||
{
|
{
|
||||||
// Read the mesh file in a polyhedron
|
// Read the mesh file in a polyhedron
|
||||||
std::ifstream stream(input_filename.c_str());
|
std::ifstream stream(input_filename.c_str());
|
||||||
typedef Enriched_polyhedron<Kernel,Enriched_items> Polyhedron;
|
typedef CGAL::Polyhedron_3<Kernel> Polyhedron;
|
||||||
Polyhedron input_mesh;
|
Polyhedron input_mesh;
|
||||||
CGAL::scan_OFF(stream, input_mesh, true /* verbose */);
|
CGAL::scan_OFF(stream, input_mesh, true /* verbose */);
|
||||||
if(!stream || !input_mesh.is_valid() || input_mesh.empty())
|
if(!stream || !input_mesh.is_valid() || input_mesh.empty())
|
||||||
|
|
@ -236,15 +236,13 @@ int main(int argc, char * argv[])
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute vertices' normals from connectivity
|
// Convert Polyhedron vertices to point set.
|
||||||
input_mesh.compute_normals();
|
// Compute vertices' normals from connectivity.
|
||||||
|
Polyhedron::Vertex_const_iterator v;
|
||||||
// Convert vertices and normals to PointList
|
|
||||||
Polyhedron::Vertex_iterator v;
|
|
||||||
for (v = input_mesh.vertices_begin(); v != input_mesh.vertices_end(); v++)
|
for (v = input_mesh.vertices_begin(); v != input_mesh.vertices_end(); v++)
|
||||||
{
|
{
|
||||||
const Point& p = v->point();
|
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));
|
points.push_back(Point_with_normal(p,n));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -269,11 +267,9 @@ int main(int argc, char * argv[])
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print status
|
// Print status
|
||||||
long memory = CGAL::Memory_sizer().virtual_size();
|
|
||||||
int nb_vertices = points.size();
|
int nb_vertices = points.size();
|
||||||
std::cerr << "Read file " << input_filename << ": " << nb_vertices << " vertices, "
|
std::cerr << "Read file " << input_filename << ": " << nb_vertices << " vertices, "
|
||||||
<< task_timer.time() << " seconds, "
|
<< task_timer.time() << " seconds, "
|
||||||
<< (memory>>20) << " Mb allocated"
|
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
task_timer.reset();
|
task_timer.reset();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ Point_set_scene_item::Point_set_scene_item(const Polyhedron& input_mesh)
|
||||||
Polyhedron::Vertex_const_iterator v;
|
Polyhedron::Vertex_const_iterator v;
|
||||||
for (v = input_mesh.vertices_begin(); v != input_mesh.vertices_end(); 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);
|
Vector n = compute_vertex_normal<Polyhedron::Vertex,Kernel>(*v);
|
||||||
m_points->push_back(UI_point(p,n));
|
m_points->push_back(UI_point(p,n));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
#include "Poisson.h"
|
#include "Poisson.h"
|
||||||
#include "DialogOptions.h"
|
#include "DialogOptions.h"
|
||||||
#include "PoissonDoc.h"
|
#include "PoissonDoc.h"
|
||||||
#include "enriched_polyhedron.h"
|
#include "compute_normal.h"
|
||||||
#include "read_pwc_point_set.h"
|
#include "read_pwc_point_set.h"
|
||||||
#include "read_g23_point_set.h"
|
#include "read_g23_point_set.h"
|
||||||
#include "outlier_removal_wrt_camera_cone_angle_3.h"
|
#include "outlier_removal_wrt_camera_cone_angle_3.h"
|
||||||
|
|
@ -15,6 +15,7 @@
|
||||||
// CGAL
|
// CGAL
|
||||||
#include <CGAL/make_surface_mesh.h>
|
#include <CGAL/make_surface_mesh.h>
|
||||||
#include <CGAL/Implicit_surface_3.h>
|
#include <CGAL/Implicit_surface_3.h>
|
||||||
|
#include <CGAL/Polyhedron_3.h>
|
||||||
#include <CGAL/IO/Polyhedron_iostream.h>
|
#include <CGAL/IO/Polyhedron_iostream.h>
|
||||||
#include <CGAL/IO/File_scanner_OFF.h>
|
#include <CGAL/IO/File_scanner_OFF.h>
|
||||||
#include <CGAL/Timer.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
|
// Read OFF file as a mesh and compute normals from connectivity
|
||||||
if (is_mesh)
|
if (is_mesh)
|
||||||
{
|
{
|
||||||
// read file in polyhedron
|
// Read the mesh file in a polyhedron
|
||||||
typedef Enriched_polyhedron<Kernel> Polyhedron;
|
std::ifstream stream(lpszPathName);
|
||||||
|
typedef CGAL::Polyhedron_3<Kernel> Polyhedron;
|
||||||
Polyhedron input_mesh;
|
Polyhedron input_mesh;
|
||||||
std::ifstream file_stream(lpszPathName);
|
CGAL::scan_OFF(stream, input_mesh, true /* verbose */);
|
||||||
CGAL::scan_OFF(file_stream, input_mesh, true /* verbose */);
|
if(!stream || !input_mesh.is_valid() || input_mesh.empty())
|
||||||
if(!file_stream || !input_mesh.is_valid() || input_mesh.empty())
|
|
||||||
{
|
{
|
||||||
prompt_message("Unable to read file");
|
prompt_message("Unable to read file");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute normals using mesh connectivity
|
// Convert Polyhedron vertices to point set.
|
||||||
input_mesh.compute_normals();
|
// Compute vertices' normals from connectivity.
|
||||||
|
Polyhedron::Vertex_const_iterator v;
|
||||||
// Copy points to m_points
|
for (v = input_mesh.vertices_begin(); v != input_mesh.vertices_end(); v++)
|
||||||
Polyhedron::Vertex_iterator v;
|
|
||||||
for(v = input_mesh.vertices_begin();
|
|
||||||
v != input_mesh.vertices_end();
|
|
||||||
v++)
|
|
||||||
{
|
{
|
||||||
const Point& p = v->point();
|
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));
|
m_points.push_back(Point_with_normal(p,n));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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_
|
||||||
|
|
@ -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_
|
|
||||||
|
|
@ -11,6 +11,7 @@
|
||||||
// CGAL
|
// CGAL
|
||||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||||
#include <CGAL/Timer.h>
|
#include <CGAL/Timer.h>
|
||||||
|
#include <CGAL/Polyhedron_3.h>
|
||||||
#include <CGAL/IO/Polyhedron_iostream.h>
|
#include <CGAL/IO/Polyhedron_iostream.h>
|
||||||
#include <CGAL/Surface_mesh_default_triangulation_3.h>
|
#include <CGAL/Surface_mesh_default_triangulation_3.h>
|
||||||
#include <CGAL/make_surface_mesh.h>
|
#include <CGAL/make_surface_mesh.h>
|
||||||
|
|
@ -23,7 +24,7 @@
|
||||||
#include <CGAL/Point_with_normal_3.h>
|
#include <CGAL/Point_with_normal_3.h>
|
||||||
#include <CGAL/IO/read_xyz_point_set.h>
|
#include <CGAL/IO/read_xyz_point_set.h>
|
||||||
|
|
||||||
#include "enriched_polyhedron.h"
|
#include "compute_normal.h"
|
||||||
|
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
@ -114,12 +115,13 @@ int main(int argc, char * argv[])
|
||||||
PointList points;
|
PointList points;
|
||||||
|
|
||||||
// If OFF file format
|
// If OFF file format
|
||||||
|
std::cerr << "Open " << input_filename << " for reading..." << std::endl;
|
||||||
std::string extension = input_filename.substr(input_filename.find_last_of('.'));
|
std::string extension = input_filename.substr(input_filename.find_last_of('.'));
|
||||||
if (extension == ".off" || extension == ".OFF")
|
if (extension == ".off" || extension == ".OFF")
|
||||||
{
|
{
|
||||||
// Read the mesh file in a polyhedron
|
// Read the mesh file in a polyhedron
|
||||||
std::ifstream stream(input_filename.c_str());
|
std::ifstream stream(input_filename.c_str());
|
||||||
typedef Enriched_polyhedron<Kernel,Enriched_items> Polyhedron;
|
typedef CGAL::Polyhedron_3<Kernel> Polyhedron;
|
||||||
Polyhedron input_mesh;
|
Polyhedron input_mesh;
|
||||||
CGAL::scan_OFF(stream, input_mesh, true /* verbose */);
|
CGAL::scan_OFF(stream, input_mesh, true /* verbose */);
|
||||||
if(!stream || !input_mesh.is_valid() || input_mesh.empty())
|
if(!stream || !input_mesh.is_valid() || input_mesh.empty())
|
||||||
|
|
@ -128,15 +130,13 @@ int main(int argc, char * argv[])
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute vertices' normals from connectivity
|
// Convert Polyhedron vertices to point set.
|
||||||
input_mesh.compute_normals();
|
// Compute vertices' normals from connectivity.
|
||||||
|
Polyhedron::Vertex_const_iterator v;
|
||||||
// Convert vertices and normals to PointList
|
|
||||||
Polyhedron::Vertex_iterator v;
|
|
||||||
for (v = input_mesh.vertices_begin(); v != input_mesh.vertices_end(); v++)
|
for (v = input_mesh.vertices_begin(); v != input_mesh.vertices_end(); v++)
|
||||||
{
|
{
|
||||||
const Point& p = v->point();
|
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));
|
points.push_back(Point_with_normal(p,n));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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_
|
||||||
|
|
@ -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_
|
|
||||||
|
|
@ -11,6 +11,7 @@
|
||||||
// CGAL
|
// CGAL
|
||||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||||
#include <CGAL/Timer.h>
|
#include <CGAL/Timer.h>
|
||||||
|
#include <CGAL/Polyhedron_3.h>
|
||||||
#include <CGAL/IO/Polyhedron_iostream.h>
|
#include <CGAL/IO/Polyhedron_iostream.h>
|
||||||
#include <CGAL/Surface_mesh_default_triangulation_3.h>
|
#include <CGAL/Surface_mesh_default_triangulation_3.h>
|
||||||
#include <CGAL/make_surface_mesh.h>
|
#include <CGAL/make_surface_mesh.h>
|
||||||
|
|
@ -23,7 +24,7 @@
|
||||||
#include <CGAL/Point_with_normal_3.h>
|
#include <CGAL/Point_with_normal_3.h>
|
||||||
#include <CGAL/IO/read_xyz_point_set.h>
|
#include <CGAL/IO/read_xyz_point_set.h>
|
||||||
|
|
||||||
#include "enriched_polyhedron.h"
|
#include "compute_normal.h"
|
||||||
|
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
@ -109,12 +110,13 @@ int main(int argc, char * argv[])
|
||||||
PointList points;
|
PointList points;
|
||||||
|
|
||||||
// If OFF file format
|
// If OFF file format
|
||||||
|
std::cerr << "Open " << input_filename << " for reading..." << std::endl;
|
||||||
std::string extension = input_filename.substr(input_filename.find_last_of('.'));
|
std::string extension = input_filename.substr(input_filename.find_last_of('.'));
|
||||||
if (extension == ".off" || extension == ".OFF")
|
if (extension == ".off" || extension == ".OFF")
|
||||||
{
|
{
|
||||||
// Read the mesh file in a polyhedron
|
// Read the mesh file in a polyhedron
|
||||||
std::ifstream stream(input_filename.c_str());
|
std::ifstream stream(input_filename.c_str());
|
||||||
typedef Enriched_polyhedron<Kernel,Enriched_items> Polyhedron;
|
typedef CGAL::Polyhedron_3<Kernel> Polyhedron;
|
||||||
Polyhedron input_mesh;
|
Polyhedron input_mesh;
|
||||||
CGAL::scan_OFF(stream, input_mesh, true /* verbose */);
|
CGAL::scan_OFF(stream, input_mesh, true /* verbose */);
|
||||||
if(!stream || !input_mesh.is_valid() || input_mesh.empty())
|
if(!stream || !input_mesh.is_valid() || input_mesh.empty())
|
||||||
|
|
@ -123,15 +125,13 @@ int main(int argc, char * argv[])
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute vertices' normals from connectivity
|
// Convert Polyhedron vertices to point set.
|
||||||
input_mesh.compute_normals();
|
// Compute vertices' normals from connectivity.
|
||||||
|
Polyhedron::Vertex_const_iterator v;
|
||||||
// Convert vertices and normals to PointList
|
|
||||||
Polyhedron::Vertex_iterator v;
|
|
||||||
for (v = input_mesh.vertices_begin(); v != input_mesh.vertices_end(); v++)
|
for (v = input_mesh.vertices_begin(); v != input_mesh.vertices_end(); v++)
|
||||||
{
|
{
|
||||||
const Point& p = v->point();
|
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));
|
points.push_back(Point_with_normal(p,n));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
@ -11,6 +11,7 @@
|
||||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||||
#include <CGAL/Timer.h>
|
#include <CGAL/Timer.h>
|
||||||
#include <CGAL/Memory_sizer.h>
|
#include <CGAL/Memory_sizer.h>
|
||||||
|
#include <CGAL/Polyhedron_3.h>
|
||||||
#include <CGAL/IO/Polyhedron_iostream.h>
|
#include <CGAL/IO/Polyhedron_iostream.h>
|
||||||
#include <CGAL/Surface_mesh_default_triangulation_3.h>
|
#include <CGAL/Surface_mesh_default_triangulation_3.h>
|
||||||
#include <CGAL/make_surface_mesh.h>
|
#include <CGAL/make_surface_mesh.h>
|
||||||
|
|
@ -21,7 +22,7 @@
|
||||||
#include <CGAL/Point_with_normal_3.h>
|
#include <CGAL/Point_with_normal_3.h>
|
||||||
#include <CGAL/IO/read_xyz_point_set.h>
|
#include <CGAL/IO/read_xyz_point_set.h>
|
||||||
|
|
||||||
#include "enriched_polyhedron.h"
|
#include "compute_normal.h"
|
||||||
|
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
@ -102,12 +103,13 @@ int main(int argc, char * argv[])
|
||||||
PointList points;
|
PointList points;
|
||||||
|
|
||||||
// If OFF file format
|
// If OFF file format
|
||||||
|
std::cerr << "Open " << input_filename << " for reading..." << std::endl;
|
||||||
std::string extension = input_filename.substr(input_filename.find_last_of('.'));
|
std::string extension = input_filename.substr(input_filename.find_last_of('.'));
|
||||||
if (extension == ".off" || extension == ".OFF")
|
if (extension == ".off" || extension == ".OFF")
|
||||||
{
|
{
|
||||||
// Read the mesh file in a polyhedron
|
// Read the mesh file in a polyhedron
|
||||||
std::ifstream stream(input_filename.c_str());
|
std::ifstream stream(input_filename.c_str());
|
||||||
typedef Enriched_polyhedron<Kernel,Enriched_items> Polyhedron;
|
typedef CGAL::Polyhedron_3<Kernel> Polyhedron;
|
||||||
Polyhedron input_mesh;
|
Polyhedron input_mesh;
|
||||||
CGAL::scan_OFF(stream, input_mesh, true /* verbose */);
|
CGAL::scan_OFF(stream, input_mesh, true /* verbose */);
|
||||||
if(!stream || !input_mesh.is_valid() || input_mesh.empty())
|
if(!stream || !input_mesh.is_valid() || input_mesh.empty())
|
||||||
|
|
@ -117,15 +119,13 @@ int main(int argc, char * argv[])
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute vertices' normals from connectivity
|
// Convert Polyhedron vertices to point set.
|
||||||
input_mesh.compute_normals();
|
// Compute vertices' normals from connectivity.
|
||||||
|
Polyhedron::Vertex_const_iterator v;
|
||||||
// Convert vertices and normals to PointList
|
|
||||||
Polyhedron::Vertex_iterator v;
|
|
||||||
for (v = input_mesh.vertices_begin(); v != input_mesh.vertices_end(); v++)
|
for (v = input_mesh.vertices_begin(); v != input_mesh.vertices_end(); v++)
|
||||||
{
|
{
|
||||||
const Point& p = v->point();
|
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));
|
points.push_back(Point_with_normal(p,n));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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_
|
||||||
|
|
@ -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_
|
|
||||||
|
|
@ -11,6 +11,7 @@
|
||||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||||
#include <CGAL/Timer.h>
|
#include <CGAL/Timer.h>
|
||||||
#include <CGAL/Memory_sizer.h>
|
#include <CGAL/Memory_sizer.h>
|
||||||
|
#include <CGAL/Polyhedron_3.h>
|
||||||
#include <CGAL/IO/Polyhedron_iostream.h>
|
#include <CGAL/IO/Polyhedron_iostream.h>
|
||||||
#include <CGAL/Surface_mesh_default_triangulation_3.h>
|
#include <CGAL/Surface_mesh_default_triangulation_3.h>
|
||||||
#include <CGAL/make_surface_mesh.h>
|
#include <CGAL/make_surface_mesh.h>
|
||||||
|
|
@ -21,7 +22,7 @@
|
||||||
#include <CGAL/Point_with_normal_3.h>
|
#include <CGAL/Point_with_normal_3.h>
|
||||||
#include <CGAL/IO/read_xyz_point_set.h>
|
#include <CGAL/IO/read_xyz_point_set.h>
|
||||||
|
|
||||||
#include "enriched_polyhedron.h"
|
#include "compute_normal.h"
|
||||||
|
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
@ -101,12 +102,13 @@ int main(int argc, char * argv[])
|
||||||
PointList points;
|
PointList points;
|
||||||
|
|
||||||
// If OFF file format
|
// If OFF file format
|
||||||
|
std::cerr << "Open " << input_filename << " for reading..." << std::endl;
|
||||||
std::string extension = input_filename.substr(input_filename.find_last_of('.'));
|
std::string extension = input_filename.substr(input_filename.find_last_of('.'));
|
||||||
if (extension == ".off" || extension == ".OFF")
|
if (extension == ".off" || extension == ".OFF")
|
||||||
{
|
{
|
||||||
// Read the mesh file in a polyhedron
|
// Read the mesh file in a polyhedron
|
||||||
std::ifstream stream(input_filename.c_str());
|
std::ifstream stream(input_filename.c_str());
|
||||||
typedef Enriched_polyhedron<Kernel,Enriched_items> Polyhedron;
|
typedef CGAL::Polyhedron_3<Kernel> Polyhedron;
|
||||||
Polyhedron input_mesh;
|
Polyhedron input_mesh;
|
||||||
CGAL::scan_OFF(stream, input_mesh, true /* verbose */);
|
CGAL::scan_OFF(stream, input_mesh, true /* verbose */);
|
||||||
if(!stream || !input_mesh.is_valid() || input_mesh.empty())
|
if(!stream || !input_mesh.is_valid() || input_mesh.empty())
|
||||||
|
|
@ -116,15 +118,13 @@ int main(int argc, char * argv[])
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute vertices' normals from connectivity
|
// Convert Polyhedron vertices to point set.
|
||||||
input_mesh.compute_normals();
|
// Compute vertices' normals from connectivity.
|
||||||
|
Polyhedron::Vertex_const_iterator v;
|
||||||
// Convert vertices and normals to PointList
|
|
||||||
Polyhedron::Vertex_iterator v;
|
|
||||||
for (v = input_mesh.vertices_begin(); v != input_mesh.vertices_end(); v++)
|
for (v = input_mesh.vertices_begin(); v != input_mesh.vertices_end(); v++)
|
||||||
{
|
{
|
||||||
const Point& p = v->point();
|
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));
|
points.push_back(Point_with_normal(p,n));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue