Просмотр исходного кода

minkowski sum

Former-commit-id: ac2663afa951eb5190987feb0fe0b676394f47ba
Alec Jacobson 9 лет назад
Родитель
Сommit
0b2babc3a0

+ 153 - 15
include/igl/copyleft/boolean/minkowski_sum.cpp

@@ -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)

+ 48 - 9
include/igl/copyleft/boolean/minkowski_sum.h

@@ -1,3 +1,10 @@
+// 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/.
 #ifndef IGL_COPYLEFT_CGAL_MINKOWSKI_SUM_H
 #define IGL_COPYLEFT_CGAL_MINKOWSKI_SUM_H
 
@@ -11,6 +18,39 @@ namespace igl
     namespace boolean
     {
       // Compute the Minkowski sum of a closed triangle mesh (V,F) and a
+      // set of simplices in 3D.
+      //
+      // Inputs:
+      //   VA  #VA by 3 list of mesh vertices in 3D
+      //   FA  #FA by 3 list of triangle indices into VA
+      //   VB  #VB by 3 list of mesh vertices in 3D
+      //   FB  #FB by ss list of simplex indices into VB, ss<=3
+      //   resolve_overlaps  whether or not to resolve self-union. If false
+      //     then result may contain self-intersections if input mesh is
+      //     non-convex.
+      // Outputs:
+      //   W  #W by 3 list of mesh vertices in 3D
+      //   G  #G by 3 list of triangle indices into W
+      //   J  #G by 2 list of indices into 
+      //   
+      template <
+        typename DerivedVA,
+        typename DerivedFA,
+        typename DerivedVB,
+        typename DerivedFB,
+        typename DerivedW,
+        typename DerivedG,
+        typename DerivedJ>
+      IGL_INLINE void 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);
+      // Compute the Minkowski sum of a closed triangle mesh (V,F) and a
       // segment [s,d] in 3D.
       //
       // Inputs:
@@ -29,16 +69,16 @@ namespace igl
       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 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,
@@ -46,20 +86,19 @@ namespace igl
       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 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);
-
     }
   }
 }