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
17namespace igl
18{
21 template <
22 typename Point,
23 typename DerivedV,
24 typename DerivedF >
25 class WindingNumberAABB : public WindingNumberTree<Point,DerivedV,DerivedF>
26 {
27 protected:
30 typename DerivedV::Scalar total_positive_area;
31 public:
38 public:
40 total_positive_area(std::numeric_limits<typename DerivedV::Scalar>::infinity()),
42 {}
47 inline WindingNumberAABB(
48 const Eigen::MatrixBase<DerivedV> & V,
49 const Eigen::MatrixBase<DerivedF> & F);
50 inline WindingNumberAABB(
52 const Eigen::MatrixBase<DerivedF> & F);
57 inline void set_mesh(
58 const Eigen::MatrixBase<DerivedV> & V,
59 const Eigen::MatrixBase<DerivedF> & F);
60 inline void init();
61 inline bool inside(const Point & p) const;
62 inline virtual void grow();
63 // Compute min and max corners
64 inline void compute_min_max_corners();
65 inline typename DerivedV::Scalar max_abs_winding_number(const Point & p) const;
66 inline typename DerivedV::Scalar max_simple_abs_winding_number(const Point & p) const;
67 };
68}
69
70// Implementation
71
72#include "winding_number.h"
73
74#include "barycenter.h"
75#include "median.h"
76#include "doublearea.h"
77#include "per_face_normals.h"
78
79#include <limits>
80#include <vector>
81#include <iostream>
82
83// Minimum number of faces in a hierarchy element (this is probably dependent
84// on speed of machine and compiler optimization)
85#ifndef WindingNumberAABB_MIN_F
86# define WindingNumberAABB_MIN_F 100
87#endif
88
89template <typename Point, typename DerivedV, typename DerivedF>
91 const Eigen::MatrixBase<DerivedV> & V,
92 const Eigen::MatrixBase<DerivedF> & F)
93{
95 init();
96}
97
98template <typename Point, typename DerivedV, typename DerivedF>
100{
101 using namespace Eigen;
102 assert(max_corner.size() == 3);
103 assert(min_corner.size() == 3);
104 compute_min_max_corners();
105 Eigen::Matrix<typename DerivedV::Scalar,Eigen::Dynamic,1> dblA;
106 doublearea(this->getV(),this->getF(),dblA);
107 total_positive_area = dblA.sum()/2.0;
108}
109
110template <typename Point, typename DerivedV, typename DerivedF>
112 const Eigen::MatrixBase<DerivedV> & V,
113 const Eigen::MatrixBase<DerivedF> & F):
114 WindingNumberTree<Point,DerivedV,DerivedF>(V,F),
115 min_corner(),
116 max_corner(),
117 total_positive_area(
118 std::numeric_limits<typename DerivedV::Scalar>::infinity()),
119 split_method(MEDIAN_ON_LONGEST_AXIS)
120{
121 init();
122}
123
124template <typename Point, typename DerivedV, typename DerivedF>
127 const Eigen::MatrixBase<DerivedF> & F):
128 WindingNumberTree<Point,DerivedV,DerivedF>(parent,F),
129 min_corner(),
130 max_corner(),
131 total_positive_area(
132 std::numeric_limits<typename DerivedV::Scalar>::infinity()),
133 split_method(MEDIAN_ON_LONGEST_AXIS)
134{
135 init();
136}
137
138template <typename Point, typename DerivedV, typename DerivedF>
140{
141 using namespace std;
142 using namespace Eigen;
143 // Clear anything that already exists
144 this->delete_children();
145
146 //cout<<"cap.rows(): "<<this->getcap().rows()<<endl;
147 //cout<<"F.rows(): "<<this->getF().rows()<<endl;
148
149 // Base cases
150 if(
151 this->getF().rows() <= (WindingNumberAABB_MIN_F>0?WindingNumberAABB_MIN_F:0) ||
152 (this->getcap().rows() - 2) >= this->getF().rows())
153 {
154 // Don't grow
155 return;
156 }
157
158 // Compute longest direction
159 int max_d = -1;
160 typename DerivedV::Scalar max_len =
161 -numeric_limits<typename DerivedV::Scalar>::infinity();
162 for(int d = 0;d<min_corner.size();d++)
163 {
164 if( (max_corner[d] - min_corner[d]) > max_len )
165 {
166 max_len = (max_corner[d] - min_corner[d]);
167 max_d = d;
168 }
169 }
170 // Compute facet barycenters
171 Eigen::Matrix<typename DerivedV::Scalar,Eigen::Dynamic,Eigen::Dynamic> BC;
172 barycenter(this->getV(),this->getF(),BC);
173
174
175 // Blerg, why is selecting rows so difficult
176
177 typename DerivedV::Scalar split_value;
178 // Split in longest direction
179 switch(split_method)
180 {
181 case MEDIAN_ON_LONGEST_AXIS:
182 // Determine median
183 median(BC.col(max_d),split_value);
184 break;
185 default:
186 assert(false);
187 case CENTER_ON_LONGEST_AXIS:
188 split_value = 0.5*(max_corner[max_d] + min_corner[max_d]);
189 break;
190 }
191 //cout<<"c: "<<0.5*(max_corner[max_d] + min_corner[max_d])<<" "<<
192 // "m: "<<split_value<<endl;;
193
194 vector<int> id( this->getF().rows());
195 for(int i = 0;i<this->getF().rows();i++)
196 {
197 if(BC(i,max_d) <= split_value)
198 {
199 id[i] = 0; //left
200 }else
201 {
202 id[i] = 1; //right
203 }
204 }
205
206 const int lefts = (int) count(id.begin(),id.end(),0);
207 const int rights = (int) count(id.begin(),id.end(),1);
208 if(lefts == 0 || rights == 0)
209 {
210 // badly balanced base case (could try to recut)
211 return;
212 }
213 assert(lefts+rights == this->getF().rows());
214 DerivedF leftF(lefts, this->getF().cols());
215 DerivedF rightF(rights,this->getF().cols());
216 int left_i = 0;
217 int right_i = 0;
218 for(int i = 0;i<this->getF().rows();i++)
219 {
220 if(id[i] == 0)
221 {
222 leftF.row(left_i++) = this->getF().row(i);
223 }else if(id[i] == 1)
224 {
225 rightF.row(right_i++) = this->getF().row(i);
226 }else
227 {
228 assert(false);
229 }
230 }
231 assert(right_i == rightF.rows());
232 assert(left_i == leftF.rows());
233 // Finally actually grow children and Recursively grow
234 WindingNumberAABB<Point,DerivedV,DerivedF> * leftWindingNumberAABB =
236 leftWindingNumberAABB->grow();
237 this->children.push_back(leftWindingNumberAABB);
238 WindingNumberAABB<Point,DerivedV,DerivedF> * rightWindingNumberAABB =
240 rightWindingNumberAABB->grow();
241 this->children.push_back(rightWindingNumberAABB);
242}
243
244template <typename Point, typename DerivedV, typename DerivedF>
246{
247 assert(p.size() == max_corner.size());
248 assert(p.size() == min_corner.size());
249 for(int i = 0;i<p.size();i++)
250 {
252 //if( p(i) < min_corner(i) || p(i) >= max_corner(i))
253 // **MUST** be conservative
254 if( p(i) < min_corner(i) || p(i) > max_corner(i))
255 {
256 return false;
257 }
258 }
259 return true;
260}
261
262template <typename Point, typename DerivedV, typename DerivedF>
264{
265 using namespace std;
266 // initialize corners
267 for(int d = 0;d<min_corner.size();d++)
268 {
269 min_corner[d] = numeric_limits<typename Point::Scalar>::infinity();
270 max_corner[d] = -numeric_limits<typename Point::Scalar>::infinity();
271 }
272
273 this->center = Point(0,0,0);
274 // Loop over facets
275 for(int i = 0;i<this->getF().rows();i++)
276 {
277 for(int j = 0;j<this->getF().cols();j++)
278 {
279 for(int d = 0;d<min_corner.size();d++)
280 {
281 min_corner[d] =
282 this->getV()(this->getF()(i,j),d) < min_corner[d] ?
283 this->getV()(this->getF()(i,j),d) : min_corner[d];
284 max_corner[d] =
285 this->getV()(this->getF()(i,j),d) > max_corner[d] ?
286 this->getV()(this->getF()(i,j),d) : max_corner[d];
287 }
288 // This is biased toward vertices incident on more than one face, but
289 // perhaps that's good
290 this->center += this->getV().row(this->getF()(i,j));
291 }
292 }
293 // Average
294 this->center.array() /= this->getF().size();
295
296 //cout<<"min_corner: "<<this->min_corner.transpose()<<endl;
297 //cout<<"Center: "<<this->center.transpose()<<endl;
298 //cout<<"max_corner: "<<this->max_corner.transpose()<<endl;
299 //cout<<"Diag center: "<<((this->max_corner + this->min_corner)*0.5).transpose()<<endl;
300 //cout<<endl;
301
302 this->radius = (max_corner-min_corner).norm()/2.0;
303}
304
305template <typename Point, typename DerivedV, typename DerivedF>
306inline typename DerivedV::Scalar
308{
309 using namespace std;
310 // Only valid if not inside
311 if(inside(p))
312 {
313 return numeric_limits<typename DerivedV::Scalar>::infinity();
314 }
315 // Q: we know the total positive area so what's the most this could project
316 // to? Remember it could be layered in the same direction.
317 return numeric_limits<typename DerivedV::Scalar>::infinity();
318}
319
320template <typename Point, typename DerivedV, typename DerivedF>
321inline typename DerivedV::Scalar
323 const Point & p) const
324{
325 using namespace std;
326 using namespace Eigen;
327 // Only valid if not inside
328 if(inside(p))
329 {
330 return numeric_limits<typename DerivedV::Scalar>::infinity();
331 }
332 // Max simple is the same as sum of positive winding number contributions of
333 // bounding box
334
335 // begin precomputation
336 //MatrixXd BV((int)pow(2,3),3);
337 typedef
338 Eigen::Matrix<typename DerivedV::Scalar,Eigen::Dynamic,Eigen::Dynamic>
339 MatrixXS;
340 typedef
341 Eigen::Matrix<typename DerivedF::Scalar,Eigen::Dynamic,Eigen::Dynamic>
342 MatrixXF;
343 MatrixXS BV((int)(1<<3),3);
344 BV <<
345 min_corner[0],min_corner[1],min_corner[2],
346 min_corner[0],min_corner[1],max_corner[2],
347 min_corner[0],max_corner[1],min_corner[2],
348 min_corner[0],max_corner[1],max_corner[2],
349 max_corner[0],min_corner[1],min_corner[2],
350 max_corner[0],min_corner[1],max_corner[2],
351 max_corner[0],max_corner[1],min_corner[2],
352 max_corner[0],max_corner[1],max_corner[2];
353 MatrixXF BF(2*2*3,3);
354 BF <<
355 0,6,4,
356 0,2,6,
357 0,3,2,
358 0,1,3,
359 2,7,6,
360 2,3,7,
361 4,6,7,
362 4,7,5,
363 0,4,5,
364 0,5,1,
365 1,5,7,
366 1,7,3;
367 MatrixXS BFN;
368 per_face_normals(BV,BF,BFN);
369 // end of precomputation
370
371 // Only keep those with positive dot products
372 MatrixXF PBF(BF.rows(),BF.cols());
373 int pbfi = 0;
374 Point p2c = 0.5*(min_corner+max_corner)-p;
375 for(int i = 0;i<BFN.rows();i++)
376 {
377 if(p2c.dot(BFN.row(i)) > 0)
378 {
379 PBF.row(pbfi++) = BF.row(i);
380 }
381 }
382 PBF.conservativeResize(pbfi,PBF.cols());
383 return igl::winding_number(BV,PBF,p);
384}
385
386// This is a bullshit template because AABB annoyingly needs templates for bad
387// combinations of 3D V with DIM=2 AABB
388//
389// _Define_ as a no-op rather than monkeying around with the proper code above
390namespace igl
391{
392 template <> inline igl::WindingNumberAABB<Eigen::Matrix<double, 1, 3, 1, 1, 3>,Eigen::Matrix<double, -1, 2, 0, -1, 2>,Eigen::Matrix<int, -1, 2, 0, -1, 2>>::WindingNumberAABB(const Eigen::MatrixBase<Eigen::Matrix<double, -1, 2, 0, -1, 2>> & , const Eigen::MatrixBase<Eigen::Matrix<int, -1, 2, 0, -1, 2>> & ){};
393 template <> inline void igl::WindingNumberAABB<Eigen::Matrix<double, 1, 3, 1, 1, 3>,Eigen::Matrix<double, -1, 2, 0, -1, 2>,Eigen::Matrix<int, -1, 2, 0, -1, 2>>::grow(){};
394 template <> inline void igl::WindingNumberAABB<Eigen::Matrix<double, 1, 3, 1, 1, 3>,Eigen::Matrix<double, -1, 2, 0, -1, 2>,Eigen::Matrix<int, -1, 2, 0, -1, 2>>::init(){};
395
396}
397
398#endif
Class for building an AABB tree to implement the divide and conquer algorithm described in [Jacobson ...
Definition WindingNumberAABB.h:26
virtual void grow()
Definition WindingNumberAABB.h:139
Point min_corner
Definition WindingNumberAABB.h:28
DerivedV::Scalar total_positive_area
Definition WindingNumberAABB.h:30
void set_mesh(const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F)
Initialize the hierarchy to a given mesh.
Definition WindingNumberAABB.h:90
WindingNumberAABB()
Definition WindingNumberAABB.h:39
SplitMethod
Definition WindingNumberAABB.h:33
@ CENTER_ON_LONGEST_AXIS
Definition WindingNumberAABB.h:34
@ MEDIAN_ON_LONGEST_AXIS
Definition WindingNumberAABB.h:35
@ NUM_SPLIT_METHODS
Definition WindingNumberAABB.h:36
DerivedV::Scalar max_simple_abs_winding_number(const Point &p) const
Definition WindingNumberAABB.h:322
Point max_corner
Definition WindingNumberAABB.h:29
enum igl::WindingNumberAABB::SplitMethod split_method
bool inside(const Point &p) const
Definition WindingNumberAABB.h:245
void init()
Definition WindingNumberAABB.h:99
DerivedV::Scalar max_abs_winding_number(const Point &p) const
Definition WindingNumberAABB.h:307
void compute_min_max_corners()
Definition WindingNumberAABB.h:263
Space partitioning tree for computing winding number hierarchically.
Definition WindingNumberTree.h:25
Eigen::Matrix< typename DerivedF::Scalar, Eigen::Dynamic, Eigen::Dynamic > MatrixXF
Definition WindingNumberTree.h:45
const WindingNumberTree * parent
Definition WindingNumberTree.h:38
DerivedV & V
Definition WindingNumberTree.h:49
virtual void set_mesh(const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F)
Definition WindingNumberTree.h:189
Eigen::Matrix< typename DerivedV::Scalar, Eigen::Dynamic, Eigen::Dynamic > MatrixXS
Definition WindingNumberTree.h:42
MatrixXF F
Definition WindingNumberTree.h:53
Definition AABB.h:17
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.