7 #ifdef NUKLEI_HAS_PARTIAL_VIEW
10 #ifndef CGAL_EIGEN3_ENABLED
11 # define CGAL_EIGEN3_ENABLED 1
14 #include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
15 #include <CGAL/pca_estimate_normals.h>
16 #include <CGAL/jet_estimate_normals.h>
17 #include <CGAL/mst_orient_normals.h>
18 #include <CGAL/property_map.h>
19 #include <CGAL/IO/read_off_points.h>
20 #include <CGAL/IO/read_xyz_points.h>
21 #include <CGAL/IO/write_xyz_points.h>
23 #include <CGAL/trace.h>
24 #include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
25 #include <CGAL/Polyhedron_3.h>
26 #include <CGAL/IO/Polyhedron_iostream.h>
27 #include <CGAL/Surface_mesh_default_triangulation_3.h>
28 #include <CGAL/make_surface_mesh.h>
29 #include <CGAL/Implicit_surface_3.h>
30 #include <CGAL/IO/output_surface_facets_to_polyhedron.h>
31 #include <CGAL/Poisson_reconstruction_function.h>
32 #include <CGAL/Point_with_normal_3.h>
33 #include <CGAL/property_map.h>
34 #include <CGAL/IO/read_xyz_points.h>
35 #include <CGAL/compute_average_spacing.h>
38 #include <CGAL/Simple_cartesian.h>
39 #include <CGAL/AABB_tree.h>
40 #include <CGAL/AABB_traits.h>
41 #include <CGAL/Polyhedron_3.h>
42 #if CGAL_VERSION_NR >= 1040300000
43 #include <CGAL/AABB_face_graph_triangle_primitive.h>
45 #include <CGAL/AABB_polyhedron_triangle_primitive.h>
47 #include <CGAL/property_map.h>
48 #include <CGAL/IO/read_off_points.h>
49 #include <CGAL/IO/read_xyz_points.h>
50 #include <CGAL/IO/write_xyz_points.h>
51 #include <CGAL/IO/Polyhedron_iostream.h>
53 #include <CGAL/squared_distance_3.h>
54 #include <CGAL/Point_with_normal_3.h>
62 #include <boost/filesystem.hpp>
63 #ifdef NUKLEI_HAS_PARTIAL_VIEW
64 #include <trimesh/TriMesh.h>
70 #ifdef NUKLEI_HAS_PARTIAL_VIEW
73 namespace meshing_types {
75 typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
77 typedef Kernel::FT FT;
78 typedef Kernel::Point_3 Point;
79 typedef CGAL::Point_with_normal_3<Kernel> Point_with_normal;
80 typedef Kernel::Sphere_3 Sphere;
81 typedef std::vector<Point_with_normal> PointList;
82 typedef CGAL::Polyhedron_3<Kernel> Polyhedron;
83 typedef CGAL::Poisson_reconstruction_function<Kernel> Poisson_reconstruction_function;
84 typedef CGAL::Surface_mesh_default_triangulation_3 STr;
85 typedef CGAL::Surface_mesh_complex_2_in_triangulation_3<STr> C2t3;
86 typedef CGAL::Implicit_surface_3<Kernel, Poisson_reconstruction_function> Surface_3;
90 typedef Kernel::Vector_3 Vector;
93 typedef std::pair<Point, Vector> PointVectorPair;
96 typedef CGAL::Polyhedron_3< CGAL::Simple_cartesian<double> > SimplePolyhedron;
98 namespace view_types {
99 typedef CGAL::Simple_cartesian<double> K;
100 typedef K::Point_3 Point;
101 typedef K::Plane_3 Plane;
102 typedef K::Vector_3 Vector;
103 typedef K::Segment_3 Segment;
104 typedef K::Line_3 Line;
105 typedef SimplePolyhedron Polyhedron;
106 #if CGAL_VERSION_NR >= 1040300000
107 typedef CGAL::AABB_face_graph_triangle_primitive<Polyhedron> Primitive;
109 typedef CGAL::AABB_polyhedron_triangle_primitive<K,Polyhedron> Primitive;
111 typedef CGAL::AABB_traits<K, Primitive> Traits;
112 typedef CGAL::AABB_tree<Traits> Tree;
113 typedef Tree::Object_and_primitive_id Object_and_primitive_id;
114 typedef Tree::Primitive_id Primitive_id;
117 typedef CGAL::Point_with_normal_3<K> Point_with_normal;
118 typedef std::vector<Point_with_normal> PointList;
125 #ifdef NUKLEI_HAS_PARTIAL_VIEW
126 static void buildAABBTree(decoration<int>& deco,
const int aabbKey,
127 SimplePolyhedron& poly)
129 using namespace view_types;
131 boost::shared_ptr<Tree> tree(
new Tree);
134 #if CGAL_VERSION_NR >= 1040300000
135 tree.reset(
new Tree(faces(poly).first, faces(poly).second, poly));
137 tree.reset(
new Tree(poly.facets_begin(),poly.facets_end()));
139 tree->accelerate_distance_queries();
141 if (deco.has_key(aabbKey)) deco.erase(aabbKey);
142 deco.insert(aabbKey, tree);
148 NUKLEI_TRACE_BEGIN();
149 #ifdef NUKLEI_HAS_PARTIAL_VIEW
151 boost::shared_ptr<SimplePolyhedron> poly(
new SimplePolyhedron);
154 using namespace meshing_types;
156 std::list<PointVectorPair> points;
161 nuklei::Vector3 v = i->getLoc();
162 Point p(v.X(),v.Y(),v.Z());
163 points.push_back(std::make_pair(p, Vector()));
167 const int nb_neighbors = 16;
168 #if CGAL_VERSION_NR >= 1040800000
169 CGAL::jet_estimate_normals<CGAL::Sequential_tag>
170 (points.begin(), points.end(),
171 CGAL::First_of_pair_property_map<PointVectorPair>(),
172 CGAL::Second_of_pair_property_map<PointVectorPair>(),
175 CGAL::jet_estimate_normals(points.begin(), points.end(),
176 CGAL::First_of_pair_property_map<PointVectorPair>(),
177 CGAL::Second_of_pair_property_map<PointVectorPair>(),
180 std::list<PointVectorPair>::iterator unoriented_points_begin =
181 CGAL::mst_orient_normals(points.begin(), points.end(),
182 CGAL::First_of_pair_property_map<PointVectorPair>(),
183 CGAL::Second_of_pair_property_map<PointVectorPair>(),
188 points.erase(unoriented_points_begin, points.end());
191 std::list<PointVectorPair>(points).swap(points);
195 std::ofstream stream(
"/tmp/xyz_points_and_normals.xyz");
197 !CGAL::write_xyz_points_and_normals(stream,
198 points.begin(), points.end(),
199 CGAL::First_of_pair_property_map<PointVectorPair>(),
200 CGAL::Second_of_pair_property_map<PointVectorPair>()))
201 std::cerr <<
"Error writing temp file" << std::endl;
207 FT sm_distance = 0.05;
215 for (std::list<PointVectorPair>::const_iterator i = points.begin(); i != points.end(); ++i)
217 pl.push_back(Point_with_normal(i->first, i->second));
224 Poisson_reconstruction_function
function(
225 pl.begin(), pl.end(),
226 #if CGAL_VERSION_NR < 1040300000
227 CGAL::make_normal_of_point_with_normal_pmap(pl.begin())
228 #elif CGAL_VERSION_NR < 1041200000
229 CGAL::make_normal_of_point_with_normal_pmap(PointList::value_type())
231 CGAL::make_normal_of_point_with_normal_map(PointList::value_type())
237 if ( !
function.compute_implicit_function() )
241 #if CGAL_VERSION_NR >= 1040800000
242 FT average_spacing = CGAL::compute_average_spacing<CGAL::Sequential_tag>
243 (pl.begin(), pl.end(),
246 FT average_spacing = CGAL::compute_average_spacing(pl.begin(), pl.end(),
252 Point inner_point =
function.get_inner_point();
253 Sphere bsphere =
function.bounding_sphere();
254 FT radius = std::sqrt(bsphere.squared_radius());
258 FT sm_sphere_radius = 5.0 * radius;
259 FT sm_dichotomy_error = sm_distance*average_spacing/1000.0;
260 Surface_3 surface(
function,
261 Sphere(inner_point,sm_sphere_radius*sm_sphere_radius),
262 sm_dichotomy_error/sm_sphere_radius);
265 CGAL::Surface_mesh_default_criteria_3<STr> criteria(sm_angle,
266 sm_radius*average_spacing,
267 sm_distance*average_spacing);
272 CGAL::make_surface_mesh(c2t3,
275 CGAL::Manifold_with_boundary_tag());
277 if(tr.number_of_vertices() == 0)
280 Polyhedron output_mesh;
281 CGAL::output_surface_facets_to_polyhedron(c2t3, output_mesh);
282 std::stringstream stream;
283 stream << output_mesh;
284 CGAL::scan_OFF(stream, *poly,
true );
285 if(!stream || !poly->is_valid() || poly->empty())
291 if (deco_.has_key(MESH_KEY)) deco_.erase(MESH_KEY);
292 deco_.insert(MESH_KEY, poly);
294 buildAABBTree(deco_, AABBTREE_KEY, *poly);
296 NUKLEI_THROW(
"This function requires the partial view build of Nuklei. See http://renaud-detry.net/nuklei/group__install.html");
301 void KernelCollection::writeMeshToOffFile(
const std::string& filename)
const
303 NUKLEI_TRACE_BEGIN();
304 #ifdef NUKLEI_HAS_PARTIAL_VIEW
305 if (!deco_.has_key(MESH_KEY))
306 NUKLEI_THROW(
"Undefined mesh. Call buildMesh() first.");
307 std::ofstream out(filename.c_str());
308 out << *deco_.get< boost::shared_ptr<SimplePolyhedron> >(MESH_KEY);
310 NUKLEI_THROW(
"This function requires the partial view build of Nuklei. See http://renaud-detry.net/nuklei/group__install.html");
315 void KernelCollection::writeMeshToPlyFile(
const std::string& filename)
const
317 NUKLEI_TRACE_BEGIN();
318 #ifdef NUKLEI_HAS_PARTIAL_VIEW
319 boost::filesystem::path offfile =
320 boost::filesystem::unique_path(
"/tmp/nuklei-%%%%-%%%%-%%%%-%%%%.off");
321 boost::filesystem::path plyfile =
322 boost::filesystem::unique_path(
"/tmp/nuklei-%%%%-%%%%-%%%%-%%%%.ply");
323 writeMeshToOffFile(offfile.native());
324 boost::shared_ptr<trimesh::TriMesh> mesh(trimesh::TriMesh::read(offfile.native()));
325 mesh->write(plyfile.native());
328 nuklei::copy_file(plyfile.string(), filename);
330 NUKLEI_THROW(
"This function requires the partial view build of Nuklei. See http://renaud-detry.net/nuklei/group__install.html");
335 void KernelCollection::readMeshFromOffFile(
const std::string& filename)
337 NUKLEI_TRACE_BEGIN();
338 #ifdef NUKLEI_HAS_PARTIAL_VIEW
339 boost::shared_ptr<SimplePolyhedron> poly(
new SimplePolyhedron);
340 std::ifstream in(filename.c_str());
341 CGAL::scan_OFF(in, *poly,
true );
342 if(!in || !poly->is_valid() || poly->empty())
346 if (deco_.has_key(MESH_KEY)) deco_.erase(MESH_KEY);
347 deco_.insert(MESH_KEY, poly);
348 buildAABBTree(deco_, AABBTREE_KEY, *poly);
350 NUKLEI_THROW(
"This function requires the partial view build of Nuklei. See http://renaud-detry.net/nuklei/group__install.html");
355 void KernelCollection::readMeshFromPlyFile(
const std::string& filename)
357 NUKLEI_TRACE_BEGIN();
358 #ifdef NUKLEI_HAS_PARTIAL_VIEW
359 boost::filesystem::path offfile =
360 boost::filesystem::unique_path(
"/tmp/nuklei-%%%%-%%%%-%%%%-%%%%.off");
361 boost::filesystem::path plyfile =
362 boost::filesystem::unique_path(
"/tmp/nuklei-%%%%-%%%%-%%%%-%%%%.ply");
365 nuklei::copy_file(filename, plyfile.string());
366 boost::shared_ptr<trimesh::TriMesh> mesh(trimesh::TriMesh::read(plyfile.native()));
367 mesh->write(offfile.native());
368 readMeshFromOffFile(offfile.native());
370 NUKLEI_THROW(
"This function requires the partial view build of Nuklei. See http://renaud-detry.net/nuklei/group__install.html");