libigl v2.5.0
Loading...
Searching...
No Matches
WindingNumberAABB.h
Go to the documentation of this file.
1// This file is part of libigl, a simple c++ geometry processing library.
2//
3// Copyright (C) 2014 Alec Jacobson <alecjacobson@gmail.com>
4//
5// This Source Code Form is subject to the terms of the Mozilla Public License
6// v. 2.0. If a copy of the MPL was not distributed with this file, You can
7// obtain one at http://mozilla.org/MPL/2.0/.
8
9// # MUTUAL DEPENDENCY ISSUE FOR HEADER ONLY VERSION
10// MUST INCLUDE winding_number.h first before guard:
11#include "winding_number.h"
12
13#ifndef IGL_WINDINGNUMBERAABB_H
14#define IGL_WINDINGNUMBERAABB_H
15#include "WindingNumberTree.h"
16#include "PlainMatrix.h"
17
18namespace igl
19{
22 template <
23 typename Scalar,
24 typename Index>
25 class WindingNumberAABB : public WindingNumberTree<Scalar,Index>
26 {
27 protected:
28 // WindingNumberTree defines Point
34 public:
41 public:
43 total_positive_area(std::numeric_limits<Scalar>::infinity()),
45 {}
46
50 template <typename DerivedV, typename DerivedF>
51 inline WindingNumberAABB(
52 const Eigen::MatrixBase<DerivedV> & V,
53 const Eigen::MatrixBase<DerivedF> & F);
54 inline WindingNumberAABB(
61 template <typename DerivedV, typename DerivedF>
62 inline void set_mesh(
63 const Eigen::MatrixBase<DerivedV> & V,
64 const Eigen::MatrixBase<DerivedF> & F);
65 inline void init();
66 inline bool inside(const Point & p) const;
67 inline virtual void grow();
68 // Compute min and max corners
69 inline void compute_min_max_corners();
70 inline Scalar max_abs_winding_number(const Point & p) const;
71 inline Scalar max_simple_abs_winding_number(const Point & p) const;
72 };
73}
74
75// Implementation
76
77#include "winding_number.h"
78
79#include "barycenter.h"
80#include "median.h"
81#include "doublearea.h"
82#include "per_face_normals.h"
83
84#include <limits>
85#include <vector>
86#include <iostream>
87
88// Minimum number of faces in a hierarchy element (this is probably dependent
89// on speed of machine and compiler optimization)
90#ifndef WindingNumberAABB_MIN_F
91# define WindingNumberAABB_MIN_F 100
92#endif
93
94template <typename Scalar, typename Index>
95 template <typename DerivedV, typename DerivedF>
97 const Eigen::MatrixBase<DerivedV> & V,
98 const Eigen::MatrixBase<DerivedF> & F)
99{
100 // static assert that DerivedF::ColsAtCompileTime == 3 or Eigen::Dynamic
101 static_assert(
102 DerivedF::ColsAtCompileTime == 3 || DerivedF::ColsAtCompileTime == Eigen::Dynamic,
103 "F should have 3 or Dynamic columns");
105 init();
106}
107
108template <typename Scalar, typename Index>
110{
111 assert(max_corner.size() == 3);
112 assert(min_corner.size() == 3);
114 Eigen::Matrix<Scalar,Eigen::Dynamic,1> dblA;
115 doublearea((*this->Vptr),(this->F),dblA);
116 total_positive_area = dblA.sum()/2.0;
117}
118
119template <typename Scalar, typename Index>
120template <typename DerivedV, typename DerivedF>
122 const Eigen::MatrixBase<DerivedV> & V,
123 const Eigen::MatrixBase<DerivedF> & F):
124 WindingNumberTree<Scalar,Index>(V,F),
125 min_corner(),
126 max_corner(),
128 std::numeric_limits<Scalar>::infinity()),
130{
131 init();
132}
133
134template <typename Scalar, typename Index>
138 WindingNumberTree<Scalar,Index>(parent,F),
139 min_corner(),
140 max_corner(),
142 std::numeric_limits<Scalar>::infinity()),
144{
145 init();
146}
147
148template <typename Scalar, typename Index>
150{
151 // Clear anything that already exists
152 this->delete_children();
153
154 //cout<<"cap.rows(): "<<(this->cap).rows()<<endl;
155 //cout<<"F.rows(): "<<(this->F).rows()<<endl;
156
157 // Base cases
158 if(
159 (this->F).rows() <= (WindingNumberAABB_MIN_F>0?WindingNumberAABB_MIN_F:0) ||
160 ((this->cap).rows() - 2) >= (this->F).rows())
161 {
162 // Don't grow
163 return;
164 }
165
166 // Compute longest direction
167 int max_d = -1;
168 Scalar max_len =
169 -std::numeric_limits<Scalar>::infinity();
170 for(int d = 0;d<min_corner.size();d++)
171 {
172 if( (max_corner[d] - min_corner[d]) > max_len )
173 {
174 max_len = (max_corner[d] - min_corner[d]);
175 max_d = d;
176 }
177 }
178 // Compute facet barycenters
179 Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic> BC;
180 barycenter((*this->Vptr),(this->F),BC);
181
182
183 // Blerg, why is selecting rows so difficult
184
185 Scalar split_value;
186 // Split in longest direction
187 switch(split_method)
188 {
190 // Determine median
191 median(BC.col(max_d),split_value);
192 break;
193 default:
194 assert(false);
196 split_value = 0.5*(max_corner[max_d] + min_corner[max_d]);
197 break;
198 }
199 //cout<<"c: "<<0.5*(max_corner[max_d] + min_corner[max_d])<<" "<<
200 // "m: "<<split_value<<endl;;
201
202 std::vector<int> id( (this->F).rows());
203 for(int i = 0;i<(this->F).rows();i++)
204 {
205 if(BC(i,max_d) <= split_value)
206 {
207 id[i] = 0; //left
208 }else
209 {
210 id[i] = 1; //right
211 }
212 }
213
214 const int lefts = (int) count(id.begin(),id.end(),0);
215 const int rights = (int) count(id.begin(),id.end(),1);
216 if(lefts == 0 || rights == 0)
217 {
218 // badly balanced base case (could try to recut)
219 return;
220 }
221 assert(lefts+rights == (this->F).rows());
222 MatrixXF leftF(lefts, (this->F).cols());
223 MatrixXF rightF(rights,(this->F).cols());
224 int left_i = 0;
225 int right_i = 0;
226 for(int i = 0;i<(this->F).rows();i++)
227 {
228 if(id[i] == 0)
229 {
230 leftF.row(left_i++) = (this->F).row(i);
231 }else if(id[i] == 1)
232 {
233 rightF.row(right_i++) = (this->F).row(i);
234 }else
235 {
236 assert(false);
237 }
238 }
239 assert(right_i == rightF.rows());
240 assert(left_i == leftF.rows());
241 // Finally actually grow children and Recursively grow
242 WindingNumberAABB<Scalar,Index> * leftWindingNumberAABB =
243 new WindingNumberAABB<Scalar,Index>(*this,leftF);
244 leftWindingNumberAABB->grow();
245 this->children.push_back(leftWindingNumberAABB);
246 WindingNumberAABB<Scalar,Index> * rightWindingNumberAABB =
247 new WindingNumberAABB<Scalar,Index>(*this,rightF);
248 rightWindingNumberAABB->grow();
249 this->children.push_back(rightWindingNumberAABB);
250}
251
252template <typename Scalar, typename Index>
254{
255 assert(p.size() == max_corner.size());
256 assert(p.size() == min_corner.size());
257 for(int i = 0;i<p.size();i++)
258 {
260 //if( p(i) < min_corner(i) || p(i) >= max_corner(i))
261 // **MUST** be conservative
262 if( p(i) < min_corner(i) || p(i) > max_corner(i))
263 {
264 return false;
265 }
266 }
267 return true;
268}
269
270template <typename Scalar, typename Index>
272{
273 // initialize corners
274 for(int d = 0;d<min_corner.size();d++)
275 {
276 min_corner[d] = std::numeric_limits<typename Point::Scalar>::infinity();
277 max_corner[d] = -std::numeric_limits<typename Point::Scalar>::infinity();
278 }
279
280 this->center = Point(0,0,0);
281 // Loop over facets
282 for(int i = 0;i<(this->F).rows();i++)
283 {
284 for(int j = 0;j<(this->F).cols();j++)
285 {
286 for(int d = 0;d<min_corner.size();d++)
287 {
288 min_corner[d] =
289 (*this->Vptr)((this->F)(i,j),d) < min_corner[d] ?
290 (*this->Vptr)((this->F)(i,j),d) : min_corner[d];
291 max_corner[d] =
292 (*this->Vptr)((this->F)(i,j),d) > max_corner[d] ?
293 (*this->Vptr)((this->F)(i,j),d) : max_corner[d];
294 }
295 // This is biased toward vertices incident on more than one face, but
296 // perhaps that's good
297 this->center += (*this->Vptr).row((this->F)(i,j));
298 }
299 }
300 // Average
301 this->center.array() /= (this->F).size();
302
303 //cout<<"min_corner: "<<this->min_corner.transpose()<<endl;
304 //cout<<"Center: "<<this->center.transpose()<<endl;
305 //cout<<"max_corner: "<<this->max_corner.transpose()<<endl;
306 //cout<<"Diag center: "<<((this->max_corner + this->min_corner)*0.5).transpose()<<endl;
307 //cout<<endl;
308
309 this->radius = (max_corner-min_corner).norm()/2.0;
310}
311
312template <typename Scalar, typename Index>
313inline Scalar
315{
316 // Only valid if not inside
317 if(inside(p))
318 {
319 return std::numeric_limits<Scalar>::infinity();
320 }
321 // Q: we know the total positive area so what's the most this could project
322 // to? Remember it could be layered in the same direction.
323 return std::numeric_limits<Scalar>::infinity();
324}
325
326template <typename Scalar, typename Index>
327inline Scalar
329 const Point & p) const
330{
331 // Only valid if not inside
332 if(inside(p))
333 {
334 return std::numeric_limits<Scalar>::infinity();
335 }
336 // Max simple is the same as sum of positive winding number contributions of
337 // bounding box
338
339 // begin precomputation
340 //MatrixXd BV((int)pow(2,3),3);
341 typedef
342 Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic>
343 MatrixXS;
344 typedef
345 Eigen::Matrix<Index,Eigen::Dynamic,Eigen::Dynamic>
346 MatrixXF;
347 MatrixXS BV((int)(1<<3),3);
348 BV <<
357 MatrixXF BF(2*2*3,3);
358 BF <<
359 0,6,4,
360 0,2,6,
361 0,3,2,
362 0,1,3,
363 2,7,6,
364 2,3,7,
365 4,6,7,
366 4,7,5,
367 0,4,5,
368 0,5,1,
369 1,5,7,
370 1,7,3;
371 MatrixXS BFN;
372 per_face_normals(BV,BF,BFN);
373 // end of precomputation
374
375 // Only keep those with positive dot products
376 MatrixXF PBF(BF.rows(),BF.cols());
377 int pbfi = 0;
378 Point p2c = 0.5*(min_corner+max_corner)-p;
379 for(int i = 0;i<BFN.rows();i++)
380 {
381 if(p2c.dot(BFN.row(i)) > 0)
382 {
383 PBF.row(pbfi++) = BF.row(i);
384 }
385 }
386 PBF.conservativeResize(pbfi,PBF.cols());
387 return igl::winding_number(BV,PBF,p);
388}
389
390#endif
Point max_corner
Definition WindingNumberAABB.h:32
virtual void grow()
Definition WindingNumberAABB.h:149
typename WindingNumberTree< Scalar, Index >::MatrixXF MatrixXF
Definition WindingNumberAABB.h:30
Scalar max_simple_abs_winding_number(const Point &p) const
Definition WindingNumberAABB.h:328
enum igl::WindingNumberAABB::SplitMethod split_method
bool inside(const Point &p) const
Definition WindingNumberAABB.h:253
Scalar total_positive_area
Definition WindingNumberAABB.h:33
SplitMethod
Definition WindingNumberAABB.h:36
@ MEDIAN_ON_LONGEST_AXIS
Definition WindingNumberAABB.h:38
@ NUM_SPLIT_METHODS
Definition WindingNumberAABB.h:39
@ CENTER_ON_LONGEST_AXIS
Definition WindingNumberAABB.h:37
WindingNumberAABB()
Definition WindingNumberAABB.h:42
void compute_min_max_corners()
Definition WindingNumberAABB.h:271
Scalar max_abs_winding_number(const Point &p) const
Definition WindingNumberAABB.h:314
void init()
Definition WindingNumberAABB.h:109
Point min_corner
Definition WindingNumberAABB.h:31
void set_mesh(const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F)
Initialize the hierarchy to a given mesh.
Definition WindingNumberAABB.h:96
typename WindingNumberTree< Scalar, Index >::Point Point
Definition WindingNumberAABB.h:29
Space partitioning tree for computing winding number hierarchically.
Definition WindingNumberTree.h:24
std::list< WindingNumberTree * > children
Definition WindingNumberTree.h:36
std::shared_ptr< MatrixXS > Vptr
Definition WindingNumberTree.h:47
MatrixXF cap
Definition WindingNumberTree.h:51
void delete_children()
Definition WindingNumberTree.h:225
Eigen::Matrix< Index, Eigen::Dynamic, Eigen::Dynamic > MatrixXF
Definition WindingNumberTree.h:42
void set_mesh(const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F)
Definition WindingNumberTree.h:184
MatrixXF F
Definition WindingNumberTree.h:49
WindingNumberTree()
Definition WindingNumberTree.h:155
Eigen::Matrix< Scalar, Eigen::Dynamic, Eigen::Dynamic > MatrixXS
Definition WindingNumberTree.h:39
Point center
Definition WindingNumberTree.h:55
Eigen::Matrix< Scalar, 1, 3 > Point
Definition WindingNumberTree.h:26
Scalar radius
Definition WindingNumberTree.h:53
const WindingNumberTree * parent
Definition WindingNumberTree.h:35
Definition AABB.h:18
void per_face_normals(const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, const Eigen::MatrixBase< DerivedZ > &Z, Eigen::PlainObjectBase< DerivedN > &N)
Compute face normals via vertex position list, face list.
void winding_number(const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, const Eigen::MatrixBase< DerivedO > &O, Eigen::PlainObjectBase< DerivedW > &W)
Computes the generalized winding number at each dim-dimensional query point in O with respect to the ...
void doublearea(const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, Eigen::PlainObjectBase< DeriveddblA > &dblA)
Computes twice the area for each input triangle or quad.
void count(const Eigen::SparseMatrix< XType > &X, const int dim, Eigen::SparseVector< SType > &S)
Count the number of non-zeros in the columns or rows of a sparse matrix.
void barycenter(const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedBC > &BC)
Computes the barycenter of every simplex.
bool median(const Eigen::MatrixBase< DerivedV > &V, mType &m)
Compute the median of an eigen vector.
Definition PlainMatrix.h:18