|
@@ -1,23 +1,159 @@
|
|
|
+// This file is part of libigl, a simple c++ geometry processing library.
|
|
|
+//
|
|
|
+// Copyright (C) 2016 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/.
|
|
|
#include "minkowski_sum.h"
|
|
|
#include "mesh_boolean.h"
|
|
|
|
|
|
#include "../../slice_mask.h"
|
|
|
#include "../../unique.h"
|
|
|
+#include "../../get_seconds.h"
|
|
|
+#include "../../edges.h"
|
|
|
+#include "../cgal/assign_scalar.h"
|
|
|
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
|
|
|
+#include <cassert>
|
|
|
+#include <vector>
|
|
|
+template <
|
|
|
+ typename DerivedVA,
|
|
|
+ typename DerivedFA,
|
|
|
+ typename DerivedVB,
|
|
|
+ typename DerivedFB,
|
|
|
+ typename DerivedW,
|
|
|
+ typename DerivedG,
|
|
|
+ typename DerivedJ>
|
|
|
+IGL_INLINE void igl::copyleft::boolean::minkowski_sum(
|
|
|
+ const Eigen::PlainObjectBase<DerivedVA> & VA,
|
|
|
+ const Eigen::PlainObjectBase<DerivedFA> & FA,
|
|
|
+ const Eigen::PlainObjectBase<DerivedVB> & VB,
|
|
|
+ const Eigen::PlainObjectBase<DerivedFB> & FB,
|
|
|
+ const bool resolve_overlaps,
|
|
|
+ Eigen::PlainObjectBase<DerivedW> & W,
|
|
|
+ Eigen::PlainObjectBase<DerivedG> & G,
|
|
|
+ Eigen::PlainObjectBase<DerivedJ> & J)
|
|
|
+{
|
|
|
+ using namespace std;
|
|
|
+ using namespace Eigen;
|
|
|
+ assert(FA.cols() == 3 && "FA must contain a closed triangle mesh");
|
|
|
+ assert(FB.cols() <= FA.cols() &&
|
|
|
+ "FB must contain lower diemnsional simplices than FA");
|
|
|
+ const auto tictoc = []()->double
|
|
|
+ {
|
|
|
+ static double t_start;
|
|
|
+ double now = igl::get_seconds();
|
|
|
+ double interval = now-t_start;
|
|
|
+ t_start = now;
|
|
|
+ return interval;
|
|
|
+ };
|
|
|
+ tictoc();
|
|
|
+ Matrix<typename DerivedFB::Scalar,Dynamic,2> EB;
|
|
|
+ edges(FB,EB);
|
|
|
+ Matrix<typename DerivedFA::Scalar,Dynamic,2> EA(0,2);
|
|
|
+ if(FB.cols() == 3)
|
|
|
+ {
|
|
|
+ edges(FA,EA);
|
|
|
+ }
|
|
|
+ // number of copies of A along edges of B
|
|
|
+ const int n_ab = EB.rows();
|
|
|
+ // number of copies of B along edges of A
|
|
|
+ const int n_ba = EA.rows();
|
|
|
+
|
|
|
+ vector<DerivedW> vW(n_ab + n_ba);
|
|
|
+ vector<DerivedG> vG(n_ab + n_ba);
|
|
|
+ vector<DerivedJ> vJ(n_ab + n_ba);
|
|
|
+ vector<int> offsets(n_ab + n_ba + 1);
|
|
|
+ offsets[0] = 0;
|
|
|
+ // sweep A along edges of B
|
|
|
+ for(int e = 0;e<n_ab;e++)
|
|
|
+ {
|
|
|
+ Matrix<typename DerivedJ::Scalar,Dynamic,1> eJ;
|
|
|
+ minkowski_sum(
|
|
|
+ VA,
|
|
|
+ FA,
|
|
|
+ VB.row(EB(e,0)).eval(),
|
|
|
+ VB.row(EB(e,1)).eval(),
|
|
|
+ false,
|
|
|
+ vW[e],
|
|
|
+ vG[e],
|
|
|
+ eJ);
|
|
|
+ assert(vG[e].rows() == eJ.rows());
|
|
|
+ assert(eJ.cols() == 1);
|
|
|
+ vJ[e].resize(vG[e].rows(),2);
|
|
|
+ vJ[e].col(0) = eJ;
|
|
|
+ vJ[e].col(1).setConstant(e);
|
|
|
+ offsets[e+1] = offsets[e] + vW[e].rows();
|
|
|
+ }
|
|
|
+ // sweep B along edges of A
|
|
|
+ for(int e = 0;e<n_ba;e++)
|
|
|
+ {
|
|
|
+ Matrix<typename DerivedJ::Scalar,Dynamic,1> eJ;
|
|
|
+ const int ee = n_ab+e;
|
|
|
+ minkowski_sum(
|
|
|
+ VB,
|
|
|
+ FB,
|
|
|
+ VA.row(EA(e,0)).eval(),
|
|
|
+ VA.row(EA(e,1)).eval(),
|
|
|
+ false,
|
|
|
+ vW[ee],
|
|
|
+ vG[ee],
|
|
|
+ eJ);
|
|
|
+ vJ[ee].resize(vG[ee].rows(),2);
|
|
|
+ vJ[ee].col(0) = eJ.array() + (FA.rows()+1);
|
|
|
+ vJ[ee].col(1).setConstant(ee);
|
|
|
+ }
|
|
|
+ // Combine meshes
|
|
|
+ int n=0,m=0;
|
|
|
+ for_each(vW.begin(),vW.end(),[&n](const DerivedW & w){n+=w.rows();});
|
|
|
+ for_each(vG.begin(),vG.end(),[&m](const DerivedG & g){m+=g.rows();});
|
|
|
+ assert(n == offsets.back());
|
|
|
+
|
|
|
+ W.resize(n,3);
|
|
|
+ G.resize(m,3);
|
|
|
+ J.resize(m,2);
|
|
|
+ {
|
|
|
+ int m_off = 0,n_off = 0;
|
|
|
+ for(int i = 0;i<vG.size();i++)
|
|
|
+ {
|
|
|
+ W.block(n_off,0,vW[i].rows(),3) = vW[i];
|
|
|
+ G.block(m_off,0,vG[i].rows(),3) = vG[i].array()+offsets[i];
|
|
|
+ J.block(m_off,0,vJ[i].rows(),2) = vJ[i];
|
|
|
+ n_off += vW[i].rows();
|
|
|
+ m_off += vG[i].rows();
|
|
|
+ }
|
|
|
+ assert(n == n_off);
|
|
|
+ assert(m == m_off);
|
|
|
+ }
|
|
|
+ if(resolve_overlaps)
|
|
|
+ {
|
|
|
+ Eigen::Matrix<typename DerivedJ::Scalar, Eigen::Dynamic,1> SJ;
|
|
|
+ mesh_boolean(
|
|
|
+ DerivedW(W),
|
|
|
+ DerivedG(G),
|
|
|
+ Matrix<typename DerivedW::Scalar,Dynamic,Dynamic>(),
|
|
|
+ Matrix<typename DerivedG::Scalar,Dynamic,Dynamic>(),
|
|
|
+ MESH_BOOLEAN_TYPE_UNION,
|
|
|
+ W,
|
|
|
+ G,
|
|
|
+ SJ);
|
|
|
+ J = slice(DerivedJ(J),SJ,1);
|
|
|
+ }
|
|
|
+}
|
|
|
|
|
|
template <
|
|
|
typename DerivedVA,
|
|
|
typename DerivedFA,
|
|
|
- typename Deriveds,
|
|
|
- typename Derivedd,
|
|
|
+ typename sType, int sCols, int sOptions,
|
|
|
+ typename dType, int dCols, int dOptions,
|
|
|
typename DerivedW,
|
|
|
typename DerivedG,
|
|
|
typename DerivedJ>
|
|
|
IGL_INLINE void igl::copyleft::boolean::minkowski_sum(
|
|
|
const Eigen::PlainObjectBase<DerivedVA> & VA,
|
|
|
const Eigen::PlainObjectBase<DerivedFA> & FA,
|
|
|
- const Eigen::PlainObjectBase<Deriveds> & s,
|
|
|
- const Eigen::PlainObjectBase<Derivedd> & d,
|
|
|
+ const Eigen::Matrix<sType,1,sCols,sOptions> & s,
|
|
|
+ const Eigen::Matrix<dType,1,dCols,dOptions> & d,
|
|
|
const bool resolve_overlaps,
|
|
|
Eigen::PlainObjectBase<DerivedW> & W,
|
|
|
Eigen::PlainObjectBase<DerivedG> & G,
|
|
@@ -25,6 +161,8 @@ IGL_INLINE void igl::copyleft::boolean::minkowski_sum(
|
|
|
{
|
|
|
using namespace Eigen;
|
|
|
using namespace std;
|
|
|
+ assert(s.cols() == 3 && "s should be a 3d point");
|
|
|
+ assert(d.cols() == 3 && "d should be a 3d point");
|
|
|
// silly base case
|
|
|
if(FA.size() == 0)
|
|
|
{
|
|
@@ -41,13 +179,13 @@ IGL_INLINE void igl::copyleft::boolean::minkowski_sum(
|
|
|
// number of vertices
|
|
|
const int n = VA.rows();
|
|
|
// duplicate vertices at s and d, we'll remove unreferernced later
|
|
|
- DerivedW WW(2*n,dim);
|
|
|
+ W.resize(2*n,dim);
|
|
|
for(int i = 0;i<n;i++)
|
|
|
{
|
|
|
for(int j = 0;j<dim;j++)
|
|
|
{
|
|
|
- WW (i,j) = VA(i,j) + s(j);
|
|
|
- WW(i+n,j) = VA(i,j) + d(j);
|
|
|
+ W (i,j) = VA(i,j) + s(j);
|
|
|
+ W(i+n,j) = VA(i,j) + d(j);
|
|
|
}
|
|
|
}
|
|
|
// number of faces
|
|
@@ -189,8 +327,8 @@ IGL_INLINE void igl::copyleft::boolean::minkowski_sum(
|
|
|
assert(nq == k);
|
|
|
}
|
|
|
|
|
|
- MatrixXI GG(GT.rows()+2*GQ.rows(),3);
|
|
|
- GG<<
|
|
|
+ G.resize(GT.rows()+2*GQ.rows(),3);
|
|
|
+ G<<
|
|
|
GT,
|
|
|
GQ.col(0), GQ.col(1), GQ.col(2),
|
|
|
GQ.col(0), GQ.col(2), GQ.col(3);
|
|
@@ -198,9 +336,9 @@ IGL_INLINE void igl::copyleft::boolean::minkowski_sum(
|
|
|
J<<JT,DerivedJ::Constant(2*GQ.rows(),1,2*m+1);
|
|
|
if(resolve_overlaps)
|
|
|
{
|
|
|
- DerivedJ SJ;
|
|
|
+ Eigen::Matrix<typename DerivedJ::Scalar, Eigen::Dynamic,1> SJ;
|
|
|
mesh_boolean(
|
|
|
- WW,GG,
|
|
|
+ DerivedW(W),DerivedG(G),
|
|
|
Matrix<typename DerivedVA::Scalar,Dynamic,Dynamic>(),MatrixXI(),
|
|
|
MESH_BOOLEAN_TYPE_UNION,
|
|
|
W,G,SJ);
|
|
@@ -211,16 +349,16 @@ IGL_INLINE void igl::copyleft::boolean::minkowski_sum(
|
|
|
template <
|
|
|
typename DerivedVA,
|
|
|
typename DerivedFA,
|
|
|
- typename Deriveds,
|
|
|
- typename Derivedd,
|
|
|
+ typename sType, int sCols, int sOptions,
|
|
|
+ typename dType, int dCols, int dOptions,
|
|
|
typename DerivedW,
|
|
|
typename DerivedG,
|
|
|
typename DerivedJ>
|
|
|
IGL_INLINE void igl::copyleft::boolean::minkowski_sum(
|
|
|
const Eigen::PlainObjectBase<DerivedVA> & VA,
|
|
|
const Eigen::PlainObjectBase<DerivedFA> & FA,
|
|
|
- const Eigen::PlainObjectBase<Deriveds> & s,
|
|
|
- const Eigen::PlainObjectBase<Derivedd> & d,
|
|
|
+ const Eigen::Matrix<sType,1,sCols,sOptions> & s,
|
|
|
+ const Eigen::Matrix<dType,1,dCols,dOptions> & d,
|
|
|
Eigen::PlainObjectBase<DerivedW> & W,
|
|
|
Eigen::PlainObjectBase<DerivedG> & G,
|
|
|
Eigen::PlainObjectBase<DerivedJ> & J)
|