mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-10-25 17:51:10 -06:00
Merged branch 'dev_native' into lm_sla_supports_auto
Added igl library files
This commit is contained in:
commit
7681d00ee5
2865 changed files with 142806 additions and 22325 deletions
377
src/igl/WindingNumberAABB.h
Normal file
377
src/igl/WindingNumberAABB.h
Normal file
|
|
@ -0,0 +1,377 @@
|
|||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2014 Alec Jacobson <alecjacobson@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License
|
||||
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
// obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
// # MUTUAL DEPENDENCY ISSUE FOR HEADER ONLY VERSION
|
||||
// MUST INCLUDE winding_number.h first before guard:
|
||||
#include "winding_number.h"
|
||||
|
||||
#ifndef IGL_WINDINGNUMBERAABB_H
|
||||
#define IGL_WINDINGNUMBERAABB_H
|
||||
#include "WindingNumberTree.h"
|
||||
|
||||
namespace igl
|
||||
{
|
||||
template <
|
||||
typename Point,
|
||||
typename DerivedV,
|
||||
typename DerivedF >
|
||||
class WindingNumberAABB : public WindingNumberTree<Point,DerivedV,DerivedF>
|
||||
{
|
||||
protected:
|
||||
Point min_corner;
|
||||
Point max_corner;
|
||||
typename DerivedV::Scalar total_positive_area;
|
||||
public:
|
||||
enum SplitMethod
|
||||
{
|
||||
CENTER_ON_LONGEST_AXIS = 0,
|
||||
MEDIAN_ON_LONGEST_AXIS = 1,
|
||||
NUM_SPLIT_METHODS = 2
|
||||
} split_method;
|
||||
public:
|
||||
inline WindingNumberAABB():
|
||||
total_positive_area(std::numeric_limits<typename DerivedV::Scalar>::infinity()),
|
||||
split_method(MEDIAN_ON_LONGEST_AXIS)
|
||||
{}
|
||||
inline WindingNumberAABB(
|
||||
const Eigen::MatrixBase<DerivedV> & V,
|
||||
const Eigen::MatrixBase<DerivedF> & F);
|
||||
inline WindingNumberAABB(
|
||||
const WindingNumberTree<Point,DerivedV,DerivedF> & parent,
|
||||
const Eigen::MatrixBase<DerivedF> & F);
|
||||
// Initialize some things
|
||||
inline void set_mesh(
|
||||
const Eigen::MatrixBase<DerivedV> & V,
|
||||
const Eigen::MatrixBase<DerivedF> & F);
|
||||
inline void init();
|
||||
inline bool inside(const Point & p) const;
|
||||
inline virtual void grow();
|
||||
// Compute min and max corners
|
||||
inline void compute_min_max_corners();
|
||||
inline typename DerivedV::Scalar max_abs_winding_number(const Point & p) const;
|
||||
inline typename DerivedV::Scalar max_simple_abs_winding_number(const Point & p) const;
|
||||
};
|
||||
}
|
||||
|
||||
// Implementation
|
||||
|
||||
#include "winding_number.h"
|
||||
|
||||
#include "barycenter.h"
|
||||
#include "median.h"
|
||||
#include "doublearea.h"
|
||||
#include "per_face_normals.h"
|
||||
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
// Minimum number of faces in a hierarchy element (this is probably dependent
|
||||
// on speed of machine and compiler optimization)
|
||||
#ifndef WindingNumberAABB_MIN_F
|
||||
# define WindingNumberAABB_MIN_F 100
|
||||
#endif
|
||||
|
||||
template <typename Point, typename DerivedV, typename DerivedF>
|
||||
inline void igl::WindingNumberAABB<Point,DerivedV,DerivedF>::set_mesh(
|
||||
const Eigen::MatrixBase<DerivedV> & V,
|
||||
const Eigen::MatrixBase<DerivedF> & F)
|
||||
{
|
||||
igl::WindingNumberTree<Point,DerivedV,DerivedF>::set_mesh(V,F);
|
||||
init();
|
||||
}
|
||||
|
||||
template <typename Point, typename DerivedV, typename DerivedF>
|
||||
inline void igl::WindingNumberAABB<Point,DerivedV,DerivedF>::init()
|
||||
{
|
||||
using namespace Eigen;
|
||||
assert(max_corner.size() == 3);
|
||||
assert(min_corner.size() == 3);
|
||||
compute_min_max_corners();
|
||||
Eigen::Matrix<typename DerivedV::Scalar,Eigen::Dynamic,1> dblA;
|
||||
doublearea(this->getV(),this->getF(),dblA);
|
||||
total_positive_area = dblA.sum()/2.0;
|
||||
}
|
||||
|
||||
template <typename Point, typename DerivedV, typename DerivedF>
|
||||
inline igl::WindingNumberAABB<Point,DerivedV,DerivedF>::WindingNumberAABB(
|
||||
const Eigen::MatrixBase<DerivedV> & V,
|
||||
const Eigen::MatrixBase<DerivedF> & F):
|
||||
WindingNumberTree<Point,DerivedV,DerivedF>(V,F),
|
||||
min_corner(),
|
||||
max_corner(),
|
||||
total_positive_area(
|
||||
std::numeric_limits<typename DerivedV::Scalar>::infinity()),
|
||||
split_method(MEDIAN_ON_LONGEST_AXIS)
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
template <typename Point, typename DerivedV, typename DerivedF>
|
||||
inline igl::WindingNumberAABB<Point,DerivedV,DerivedF>::WindingNumberAABB(
|
||||
const WindingNumberTree<Point,DerivedV,DerivedF> & parent,
|
||||
const Eigen::MatrixBase<DerivedF> & F):
|
||||
WindingNumberTree<Point,DerivedV,DerivedF>(parent,F),
|
||||
min_corner(),
|
||||
max_corner(),
|
||||
total_positive_area(
|
||||
std::numeric_limits<typename DerivedV::Scalar>::infinity()),
|
||||
split_method(MEDIAN_ON_LONGEST_AXIS)
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
template <typename Point, typename DerivedV, typename DerivedF>
|
||||
inline void igl::WindingNumberAABB<Point,DerivedV,DerivedF>::grow()
|
||||
{
|
||||
using namespace std;
|
||||
using namespace Eigen;
|
||||
// Clear anything that already exists
|
||||
this->delete_children();
|
||||
|
||||
//cout<<"cap.rows(): "<<this->getcap().rows()<<endl;
|
||||
//cout<<"F.rows(): "<<this->getF().rows()<<endl;
|
||||
|
||||
// Base cases
|
||||
if(
|
||||
this->getF().rows() <= (WindingNumberAABB_MIN_F>0?WindingNumberAABB_MIN_F:0) ||
|
||||
(this->getcap().rows() - 2) >= this->getF().rows())
|
||||
{
|
||||
// Don't grow
|
||||
return;
|
||||
}
|
||||
|
||||
// Compute longest direction
|
||||
int max_d = -1;
|
||||
typename DerivedV::Scalar max_len =
|
||||
-numeric_limits<typename DerivedV::Scalar>::infinity();
|
||||
for(int d = 0;d<min_corner.size();d++)
|
||||
{
|
||||
if( (max_corner[d] - min_corner[d]) > max_len )
|
||||
{
|
||||
max_len = (max_corner[d] - min_corner[d]);
|
||||
max_d = d;
|
||||
}
|
||||
}
|
||||
// Compute facet barycenters
|
||||
Eigen::Matrix<typename DerivedV::Scalar,Eigen::Dynamic,Eigen::Dynamic> BC;
|
||||
barycenter(this->getV(),this->getF(),BC);
|
||||
|
||||
|
||||
// Blerg, why is selecting rows so difficult
|
||||
|
||||
typename DerivedV::Scalar split_value;
|
||||
// Split in longest direction
|
||||
switch(split_method)
|
||||
{
|
||||
case MEDIAN_ON_LONGEST_AXIS:
|
||||
// Determine median
|
||||
median(BC.col(max_d),split_value);
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
case CENTER_ON_LONGEST_AXIS:
|
||||
split_value = 0.5*(max_corner[max_d] + min_corner[max_d]);
|
||||
break;
|
||||
}
|
||||
//cout<<"c: "<<0.5*(max_corner[max_d] + min_corner[max_d])<<" "<<
|
||||
// "m: "<<split_value<<endl;;
|
||||
|
||||
vector<int> id( this->getF().rows());
|
||||
for(int i = 0;i<this->getF().rows();i++)
|
||||
{
|
||||
if(BC(i,max_d) <= split_value)
|
||||
{
|
||||
id[i] = 0; //left
|
||||
}else
|
||||
{
|
||||
id[i] = 1; //right
|
||||
}
|
||||
}
|
||||
|
||||
const int lefts = (int) count(id.begin(),id.end(),0);
|
||||
const int rights = (int) count(id.begin(),id.end(),1);
|
||||
if(lefts == 0 || rights == 0)
|
||||
{
|
||||
// badly balanced base case (could try to recut)
|
||||
return;
|
||||
}
|
||||
assert(lefts+rights == this->getF().rows());
|
||||
DerivedF leftF(lefts, this->getF().cols());
|
||||
DerivedF rightF(rights,this->getF().cols());
|
||||
int left_i = 0;
|
||||
int right_i = 0;
|
||||
for(int i = 0;i<this->getF().rows();i++)
|
||||
{
|
||||
if(id[i] == 0)
|
||||
{
|
||||
leftF.row(left_i++) = this->getF().row(i);
|
||||
}else if(id[i] == 1)
|
||||
{
|
||||
rightF.row(right_i++) = this->getF().row(i);
|
||||
}else
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
assert(right_i == rightF.rows());
|
||||
assert(left_i == leftF.rows());
|
||||
// Finally actually grow children and Recursively grow
|
||||
WindingNumberAABB<Point,DerivedV,DerivedF> * leftWindingNumberAABB =
|
||||
new WindingNumberAABB<Point,DerivedV,DerivedF>(*this,leftF);
|
||||
leftWindingNumberAABB->grow();
|
||||
this->children.push_back(leftWindingNumberAABB);
|
||||
WindingNumberAABB<Point,DerivedV,DerivedF> * rightWindingNumberAABB =
|
||||
new WindingNumberAABB<Point,DerivedV,DerivedF>(*this,rightF);
|
||||
rightWindingNumberAABB->grow();
|
||||
this->children.push_back(rightWindingNumberAABB);
|
||||
}
|
||||
|
||||
template <typename Point, typename DerivedV, typename DerivedF>
|
||||
inline bool igl::WindingNumberAABB<Point,DerivedV,DerivedF>::inside(const Point & p) const
|
||||
{
|
||||
assert(p.size() == max_corner.size());
|
||||
assert(p.size() == min_corner.size());
|
||||
for(int i = 0;i<p.size();i++)
|
||||
{
|
||||
//// Perfect matching is **not** robust
|
||||
//if( p(i) < min_corner(i) || p(i) >= max_corner(i))
|
||||
// **MUST** be conservative
|
||||
if( p(i) < min_corner(i) || p(i) > max_corner(i))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Point, typename DerivedV, typename DerivedF>
|
||||
inline void igl::WindingNumberAABB<Point,DerivedV,DerivedF>::compute_min_max_corners()
|
||||
{
|
||||
using namespace std;
|
||||
// initialize corners
|
||||
for(int d = 0;d<min_corner.size();d++)
|
||||
{
|
||||
min_corner[d] = numeric_limits<typename Point::Scalar>::infinity();
|
||||
max_corner[d] = -numeric_limits<typename Point::Scalar>::infinity();
|
||||
}
|
||||
|
||||
this->center = Point(0,0,0);
|
||||
// Loop over facets
|
||||
for(int i = 0;i<this->getF().rows();i++)
|
||||
{
|
||||
for(int j = 0;j<this->getF().cols();j++)
|
||||
{
|
||||
for(int d = 0;d<min_corner.size();d++)
|
||||
{
|
||||
min_corner[d] =
|
||||
this->getV()(this->getF()(i,j),d) < min_corner[d] ?
|
||||
this->getV()(this->getF()(i,j),d) : min_corner[d];
|
||||
max_corner[d] =
|
||||
this->getV()(this->getF()(i,j),d) > max_corner[d] ?
|
||||
this->getV()(this->getF()(i,j),d) : max_corner[d];
|
||||
}
|
||||
// This is biased toward vertices incident on more than one face, but
|
||||
// perhaps that's good
|
||||
this->center += this->getV().row(this->getF()(i,j));
|
||||
}
|
||||
}
|
||||
// Average
|
||||
this->center.array() /= this->getF().size();
|
||||
|
||||
//cout<<"min_corner: "<<this->min_corner.transpose()<<endl;
|
||||
//cout<<"Center: "<<this->center.transpose()<<endl;
|
||||
//cout<<"max_corner: "<<this->max_corner.transpose()<<endl;
|
||||
//cout<<"Diag center: "<<((this->max_corner + this->min_corner)*0.5).transpose()<<endl;
|
||||
//cout<<endl;
|
||||
|
||||
this->radius = (max_corner-min_corner).norm()/2.0;
|
||||
}
|
||||
|
||||
template <typename Point, typename DerivedV, typename DerivedF>
|
||||
inline typename DerivedV::Scalar
|
||||
igl::WindingNumberAABB<Point,DerivedV,DerivedF>::max_abs_winding_number(const Point & p) const
|
||||
{
|
||||
using namespace std;
|
||||
// Only valid if not inside
|
||||
if(inside(p))
|
||||
{
|
||||
return numeric_limits<typename DerivedV::Scalar>::infinity();
|
||||
}
|
||||
// Q: we know the total positive area so what's the most this could project
|
||||
// to? Remember it could be layered in the same direction.
|
||||
return numeric_limits<typename DerivedV::Scalar>::infinity();
|
||||
}
|
||||
|
||||
template <typename Point, typename DerivedV, typename DerivedF>
|
||||
inline typename DerivedV::Scalar
|
||||
igl::WindingNumberAABB<Point,DerivedV,DerivedF>::max_simple_abs_winding_number(
|
||||
const Point & p) const
|
||||
{
|
||||
using namespace std;
|
||||
using namespace Eigen;
|
||||
// Only valid if not inside
|
||||
if(inside(p))
|
||||
{
|
||||
return numeric_limits<typename DerivedV::Scalar>::infinity();
|
||||
}
|
||||
// Max simple is the same as sum of positive winding number contributions of
|
||||
// bounding box
|
||||
|
||||
// begin precomputation
|
||||
//MatrixXd BV((int)pow(2,3),3);
|
||||
typedef
|
||||
Eigen::Matrix<typename DerivedV::Scalar,Eigen::Dynamic,Eigen::Dynamic>
|
||||
MatrixXS;
|
||||
typedef
|
||||
Eigen::Matrix<typename DerivedF::Scalar,Eigen::Dynamic,Eigen::Dynamic>
|
||||
MatrixXF;
|
||||
MatrixXS BV((int)(1<<3),3);
|
||||
BV <<
|
||||
min_corner[0],min_corner[1],min_corner[2],
|
||||
min_corner[0],min_corner[1],max_corner[2],
|
||||
min_corner[0],max_corner[1],min_corner[2],
|
||||
min_corner[0],max_corner[1],max_corner[2],
|
||||
max_corner[0],min_corner[1],min_corner[2],
|
||||
max_corner[0],min_corner[1],max_corner[2],
|
||||
max_corner[0],max_corner[1],min_corner[2],
|
||||
max_corner[0],max_corner[1],max_corner[2];
|
||||
MatrixXF BF(2*2*3,3);
|
||||
BF <<
|
||||
0,6,4,
|
||||
0,2,6,
|
||||
0,3,2,
|
||||
0,1,3,
|
||||
2,7,6,
|
||||
2,3,7,
|
||||
4,6,7,
|
||||
4,7,5,
|
||||
0,4,5,
|
||||
0,5,1,
|
||||
1,5,7,
|
||||
1,7,3;
|
||||
MatrixXS BFN;
|
||||
per_face_normals(BV,BF,BFN);
|
||||
// end of precomputation
|
||||
|
||||
// Only keep those with positive dot products
|
||||
MatrixXF PBF(BF.rows(),BF.cols());
|
||||
int pbfi = 0;
|
||||
Point p2c = 0.5*(min_corner+max_corner)-p;
|
||||
for(int i = 0;i<BFN.rows();i++)
|
||||
{
|
||||
if(p2c.dot(BFN.row(i)) > 0)
|
||||
{
|
||||
PBF.row(pbfi++) = BF.row(i);
|
||||
}
|
||||
}
|
||||
PBF.conservativeResize(pbfi,PBF.cols());
|
||||
return igl::winding_number(BV,PBF,p);
|
||||
}
|
||||
|
||||
#endif
|
||||
Loading…
Add table
Add a link
Reference in a new issue