7 #ifdef NUKLEI_HAS_PARTIAL_VIEW
9 #ifndef CGAL_EIGEN3_ENABLED
10 # define CGAL_EIGEN3_ENABLED 1
13 #include <CGAL/Simple_cartesian.h>
14 #include <CGAL/AABB_tree.h>
15 #include <CGAL/AABB_traits.h>
16 #include <CGAL/Polyhedron_3.h>
17 #if CGAL_VERSION_NR >= 1040300000
18 #include <CGAL/AABB_face_graph_triangle_primitive.h>
20 #include <CGAL/AABB_polyhedron_triangle_primitive.h>
22 #include <CGAL/property_map.h>
23 #include <CGAL/IO/read_off_points.h>
24 #include <CGAL/IO/read_xyz_points.h>
25 #include <CGAL/IO/write_xyz_points.h>
26 #include <CGAL/IO/Polyhedron_iostream.h>
28 #include <CGAL/squared_distance_3.h>
29 #include <CGAL/Point_with_normal_3.h>
36 #include <boost/shared_ptr.hpp>
40 #ifdef NUKLEI_HAS_PARTIAL_VIEW
42 typedef CGAL::Simple_cartesian<double> K;
43 typedef K::Point_3 Point;
44 typedef K::Plane_3 Plane;
45 typedef K::Vector_3 Vector;
46 typedef K::Segment_3 Segment;
47 typedef K::Line_3 Line;
48 typedef CGAL::Polyhedron_3<K> Polyhedron;
49 #if CGAL_VERSION_NR >= 1040300000
50 typedef CGAL::AABB_face_graph_triangle_primitive<Polyhedron> Primitive;
52 typedef CGAL::AABB_polyhedron_triangle_primitive<K,Polyhedron> Primitive;
54 typedef CGAL::AABB_traits<K, Primitive> Traits;
55 typedef CGAL::AABB_tree<Traits> Tree;
56 typedef Tree::Object_and_primitive_id Object_and_primitive_id;
57 typedef Tree::Primitive_id Primitive_id;
59 typedef CGAL::Point_with_normal_3<K> Point_with_normal;
60 typedef std::vector<Point_with_normal> PointList;
66 typedef std::vector< std::pair< Vector3, std::vector<int> > > viewcache_t;
68 #ifdef NUKLEI_HAS_PARTIAL_VIEW
71 inline bool isVisible(
const Vector3& wtarget,
72 const Vector3& wnormal,
73 const Vector3& wcamera,
74 const Polyhedron& poly,
78 if (std::fabs(wnormal.SquaredLength()-1) < FLOATTOL)
80 Vector3 ctot = la::normalized(wtarget-wcamera);
81 double dot = wnormal.Dot(ctot);
82 if (std::acos(std::fabs(dot)) > (80./180*M_PI))
88 Point camera(wcamera.X(), wcamera.Y(), wcamera.Z());
89 Point target(wtarget.X(), wtarget.Y(), wtarget.Z());
92 Segment segment_query(camera,target);
95 std::list<Object_and_primitive_id> intersections;
96 tree.all_intersections(segment_query, std::back_inserter(intersections));
98 int self_intersect = 0;
99 for (std::list<Object_and_primitive_id>::const_iterator intersection = intersections.begin();
100 intersection != intersections.end(); ++intersection)
102 Object_and_primitive_id op = *intersection;
103 CGAL::Object
object = op.first;
104 Point intersectionPoint;
105 if(CGAL::assign(intersectionPoint,
object))
107 double sq2 = squared_distance(intersectionPoint, target);
108 if (sq2 < tolerance*tolerance) self_intersect++;
117 int num_inter = intersections.size();
118 if (self_intersect > 1)
119 NUKLEI_LOG(
"Number of self-intersections (" << self_intersect <<
") greater than 1");
125 if (num_inter - self_intersect > 0)
130 if (num_inter > 1 && visible)
131 NUKLEI_INFO(
"Strange visibility at" << target);
137 inline bool isVisible(
const Vector3& wtarget,
138 const Vector3& wcamera,
139 const Polyhedron& poly,
143 return isVisible(wtarget,
154 const coord_t& tolerance)
const
156 NUKLEI_TRACE_BEGIN();
157 #ifdef NUKLEI_HAS_PARTIAL_VIEW
158 if (!deco_.has_key(MESH_KEY))
159 NUKLEI_THROW(
"Undefined mesh. Call buildMesh() first.");
160 if (!deco_.has_key(AABBTREE_KEY))
161 NUKLEI_THROW(
"Undefined AABB tree. Call buildMesh() first.");
163 return isVisible(p, viewpoint,
164 *deco_.get< boost::shared_ptr<Polyhedron> >(MESH_KEY),
165 *deco_.get< boost::shared_ptr<Tree> >(AABBTREE_KEY),
168 NUKLEI_THROW(
"This function requires the partial view build of Nuklei. See http://renaud-detry.net/nuklei/group__install.html");
174 const coord_t& tolerance)
const
176 NUKLEI_TRACE_BEGIN();
177 #ifdef NUKLEI_HAS_PARTIAL_VIEW
178 if (!deco_.has_key(MESH_KEY))
179 NUKLEI_THROW(
"Undefined mesh. Call buildMesh() first.");
180 if (!deco_.has_key(AABBTREE_KEY))
181 NUKLEI_THROW(
"Undefined AABB tree. Call buildMesh() first.");
183 return isVisible(p.loc_, p.dir_, viewpoint,
184 *deco_.get< boost::shared_ptr<Polyhedron> >(MESH_KEY),
185 *deco_.get< boost::shared_ptr<Tree> >(AABBTREE_KEY),
188 NUKLEI_THROW(
"This function requires the partial view build of Nuklei. See http://renaud-detry.net/nuklei/group__install.html");
196 const bool useViewcache,
197 const bool useRayToSurfacenormalAngle)
const
199 NUKLEI_TRACE_BEGIN();
205 #ifdef NUKLEI_HAS_PARTIAL_VIEW
206 if (!deco_.has_key(MESH_KEY))
207 NUKLEI_THROW(
"Undefined mesh. Call buildMesh() first.");
208 if (!deco_.has_key(AABBTREE_KEY))
209 NUKLEI_THROW(
"Undefined AABB tree. Call buildMesh() first.");
211 const Polyhedron& poly = *deco_.get< boost::shared_ptr<Polyhedron> >(MESH_KEY);
212 const Tree& tree = *deco_.get< boost::shared_ptr<Tree> >(AABBTREE_KEY);
216 Vector3 p = v->getLoc();
217 Vector3 normal = Vector3::ZERO;
218 if (useRayToSurfacenormalAngle)
220 if (isVisible(p, normal, viewpoint, poly, tree, tolerance))
221 index_collection.push_back(std::distance(
begin(), v));
224 NUKLEI_THROW(
"This function requires the partial view build of Nuklei. See http://renaud-detry.net/nuklei/group__install.html");
229 if (!deco_.has_key(VIEWCACHE_KEY))
230 NUKLEI_THROW(
"Undefined view cache. Call buildPartialViewCache() first.");
232 const viewcache_t &viewIndex = *deco_.get< boost::shared_ptr<viewcache_t> >(VIEWCACHE_KEY);
234 double minDist = 1e6;
235 viewcache_t::const_iterator closest =
as_const(viewIndex).begin();
236 for (viewcache_t::const_iterator oo =
as_const(viewIndex).
begin(); oo != viewIndex.end(); ++oo)
238 double tmp = (viewpoint-oo->first).SquaredLength();
239 if (tmp < minDist*minDist)
245 for (std::vector<int>::const_iterator i = closest->second.begin(); i != closest->second.end(); ++i)
246 index_collection.push_back(*i);
248 return index_collection;
255 const bool useViewcache,
256 const bool useRayToSurfacenormalAngle)
const
258 NUKLEI_TRACE_BEGIN();
259 #ifdef NUKLEI_HAS_PARTIAL_VIEW
260 return partialView< std::vector<int> >(viewpoint, tolerance, useViewcache, useRayToSurfacenormalAngle);
262 NUKLEI_THROW(
"This function requires the partial view build of Nuklei. See http://renaud-detry.net/nuklei/group__install.html");
270 const bool useViewcache,
271 const bool useRayToSurfacenormalAngle)
const
273 NUKLEI_TRACE_BEGIN();
274 #ifdef NUKLEI_HAS_PARTIAL_VIEW
276 typedef const_partialview_iterator::index_container
278 typedef const_partialview_iterator::index_container_ptr
280 typedef const_partialview_iterator::index_t
283 index_container_ptr index_collection(
new index_container);
284 *index_collection = partialView< index_container >(viewpoint, tolerance, useViewcache, useRayToSurfacenormalAngle);
288 NUKLEI_THROW(
"This function requires the partial view build of Nuklei. See http://renaud-detry.net/nuklei/group__install.html");
295 NUKLEI_TRACE_BEGIN();
296 #ifdef NUKLEI_HAS_PARTIAL_VIEW
298 double stdev =
as_const(*this).moments()->getLocH();
300 std::vector< Vector3 > keys;
301 for (
int o = 0; o < 10000; ++o)
308 double minDist2 = .15;
309 std::vector< Vector3 > tmp = keys;
311 for (std::vector<Vector3>::const_iterator
317 for (std::vector<Vector3>::const_iterator
319 j != keys.end(); ++j)
321 if ( (iLoc - *j).SquaredLength() < minDist2*minDist2 )
329 keys.push_back(iLoc);
334 boost::shared_ptr<viewcache_t> viewIndex(
new viewcache_t());
336 for (
unsigned int o = 0; o < keys.size(); ++o)
338 Vector3 key = keys.at(o);
339 Vector3 vp =
mean + key*stdev*20;
340 std::vector<int> vi =
as_const(*this).partialView(vp, meshTol,
false, useRayToSurfacenormalAngle);
344 for (std::vector<int>::iterator i = vi.begin(); i != vi.end(); ++i)
352 viewIndex->push_back(std::make_pair(key, vi));
355 if (deco_.has_key(VIEWCACHE_KEY)) deco_.erase(VIEWCACHE_KEY);
356 deco_.insert(VIEWCACHE_KEY, viewIndex);
361 for (viewcache_t::iterator o = viewIndex->begin(); o != viewIndex->end(); ++o)
366 for (viewcache_t::iterator oo = viewIndex->begin(); oo != viewIndex->end(); ++oo)
368 if (oo == o)
continue;
369 double dd = (o->first-oo->first).Length();
373 for (std::vector<int>::iterator j = oo->second.begin(); j != oo->second.end(); ++j)
376 if (near.
size() == 0)
continue;
378 k->setLoc(
mean + oo->first*stdev*20);
387 i->setDescriptor(cd);
389 for (std::vector<int>::iterator j = o->second.begin(); j != o->second.end(); ++j)
392 near.
back().setLoc(near.
back().getLoc()+Vector3(0.001, 0, 0));
395 if (near.
size() == 0)
continue;
397 k->setLoc(
mean + o->first*stdev*20);
405 NUKLEI_THROW(
"This function requires the partial view build of Nuklei. See http://renaud-detry.net/nuklei/group__install.html");