Browse Source

Merge branch 'main' of github.com:libigl/libigl

Alec Jacobson 2 years ago
parent
commit
0262ef5866
3 changed files with 126 additions and 27 deletions
  1. 112 18
      include/igl/point_mesh_squared_distance.cpp
  2. 11 9
      include/igl/readPLY.cpp
  3. 3 0
      include/igl/readPLY.h

+ 112 - 18
include/igl/point_mesh_squared_distance.cpp

@@ -9,14 +9,29 @@
 #include "AABB.h"
 #include <cassert>
 
+namespace 
+{
+  // Sigh. This is a somewhat elaborate way of making
+  // igl::point_mesh_squared_distance build a correctly dimensioned AABB tree
+  // regardless of whether it has #columns known at compile time or not.
+  //
+  // The pattern below uses a class which can be partially specialized on
+  // whether columns are dynamic. For each case, we call this helper function at
+  // the top which has a known dimension as an extra template argument.
+  //
+  // In this case, the _code_ for the 2D and 3D cases is the same, so we avoid
+  // duplicating lines of code that only differ in the dimension. The cost
+  // appears to be spelling out _all_ of the template types over and over again
+  // making this all harder to parse.
 template <
+  int DIM,
   typename DerivedP,
   typename DerivedV,
   typename DerivedEle,
   typename DerivedsqrD,
   typename DerivedI,
   typename DerivedC>
-IGL_INLINE void igl::point_mesh_squared_distance(
+IGL_INLINE void point_mesh_squared_distance(
   const Eigen::MatrixBase<DerivedP> & P,
   const Eigen::MatrixBase<DerivedV> & V,
   const Eigen::MatrixBase<DerivedEle> & Ele,
@@ -24,28 +39,107 @@ IGL_INLINE void igl::point_mesh_squared_distance(
   Eigen::PlainObjectBase<DerivedI> & I,
   Eigen::PlainObjectBase<DerivedC> & C)
 {
-  using namespace std;
-  const size_t dim = P.cols();
-  assert((dim == 2 || dim == 3) && "P.cols() should be 2 or 3");
-  assert(P.cols() == V.cols() && "P.cols() should equal V.cols()");
-  switch(dim)
+  static_assert(DIM == 2 || DIM == 3, "DIM must be 2 or 3");
+  // Common code for 2D and 3D
+  igl::AABB<DerivedV, DIM> tree;
+  tree.init(V,Ele);
+  tree.squared_distance(V,Ele,P,sqrD,I,C);
+}
+
+// Class whose templates can be specialized on whether V has dynamic columns or
+// not.
+template <
+  typename DerivedP,
+  typename DerivedV,
+  typename DerivedEle,
+  typename DerivedsqrD,
+  typename DerivedI,
+  typename DerivedC,
+  bool DynamicCols> 
+struct DIM_Handler;
+
+// Handle the case where V has dynamic columns
+template <
+  typename DerivedP,
+  typename DerivedV,
+  typename DerivedEle,
+  typename DerivedsqrD,
+  typename DerivedI,
+  typename DerivedC>
+struct DIM_Handler<
+  DerivedP, DerivedV, DerivedEle, DerivedsqrD, DerivedI, DerivedC,
+  true>
+{
+  static void compute(
+    const Eigen::MatrixBase<DerivedP> & P,
+    const Eigen::MatrixBase<DerivedV> & V,
+    const Eigen::MatrixBase<DerivedEle> & Ele,
+    Eigen::PlainObjectBase<DerivedsqrD> & sqrD,
+    Eigen::PlainObjectBase<DerivedI> & I,
+    Eigen::PlainObjectBase<DerivedC> & C)
   {
-    default:
-      assert(false && "Unsupported dim");
-      // fall-through and pray
-    case 3:
+    if(V.cols() == 2)
     {
-      AABB<DerivedV,3> tree;
-      tree.init(V,Ele);
-      return tree.squared_distance(V,Ele,P,sqrD,I,C);
-    }
-    case 2:
+      point_mesh_squared_distance<2>(P,V,Ele,sqrD,I,C);
+    }else if(V.cols() == 3)
+    {
+      point_mesh_squared_distance<3>(P,V,Ele,sqrD,I,C);
+    }else
     {
-      AABB<DerivedV,2> tree;
-      tree.init(V,Ele);
-      return tree.squared_distance(V,Ele,P,sqrD,I,C);
+      assert(false && "V must be 2D or 3D");
     }
   }
+};
+
+// Handle the case where V has fixed size columns
+template <
+  typename DerivedP,
+  typename DerivedV,
+  typename DerivedEle,
+  typename DerivedsqrD,
+  typename DerivedI,
+  typename DerivedC>
+struct DIM_Handler<
+  DerivedP, DerivedV, DerivedEle, DerivedsqrD, DerivedI, DerivedC, 
+  false>
+{
+  static void compute(
+    const Eigen::MatrixBase<DerivedP> & P,
+    const Eigen::MatrixBase<DerivedV> & V,
+    const Eigen::MatrixBase<DerivedEle> & Ele,
+    Eigen::PlainObjectBase<DerivedsqrD> & sqrD,
+    Eigen::PlainObjectBase<DerivedI> & I,
+    Eigen::PlainObjectBase<DerivedC> & C)
+  {
+    static_assert(DerivedV::ColsAtCompileTime == 2 || DerivedV::ColsAtCompileTime == 3, "V must be 2D or 3D");
+    point_mesh_squared_distance<DerivedV::ColsAtCompileTime>(P,V,Ele,sqrD,I,C);
+  }
+};
+}
+
+template <
+  typename DerivedP,
+  typename DerivedV,
+  typename DerivedEle,
+  typename DerivedsqrD,
+  typename DerivedI,
+  typename DerivedC>
+IGL_INLINE void igl::point_mesh_squared_distance(
+  const Eigen::MatrixBase<DerivedP> & P,
+  const Eigen::MatrixBase<DerivedV> & V,
+  const Eigen::MatrixBase<DerivedEle> & Ele,
+  Eigen::PlainObjectBase<DerivedsqrD> & sqrD,
+  Eigen::PlainObjectBase<DerivedI> & I,
+  Eigen::PlainObjectBase<DerivedC> & C)
+{
+  DIM_Handler<
+    DerivedP, 
+    DerivedV, 
+    DerivedEle, 
+    DerivedsqrD, 
+    DerivedI, 
+    DerivedC,
+    DerivedV::ColsAtCompileTime == Eigen::Dynamic>::compute(P,V,Ele,sqrD,I,C);
 }
 
 #ifdef IGL_STATIC_LIBRARY

+ 11 - 9
include/igl/readPLY.cpp

@@ -396,15 +396,15 @@ IGL_INLINE bool readPLY(
   file.read(ply_stream);
 
   if (!vertices || !tinyply_buffer_to_matrix(*vertices,V,vertices->count,3) ) {
-    V.resize(0,0);
+    // Don't do this because V might have non-trivial compile-time size V.resize(0,0);
   }
 
   if (!normals || !tinyply_buffer_to_matrix(*normals,N,normals->count,3) ) {
-    N.resize(0,0);
+    // Don't do this (see above) N.resize(0,0);
   }
 
   if (!texcoords || !tinyply_buffer_to_matrix(*texcoords,UV,texcoords->count,2) ) {
-    UV.resize(0,0);
+    // Don't do this (see above) UV.resize(0,0);
   }
 
   //HACK: Unfortunately, tinyply doesn't store list size as a separate variable
@@ -418,22 +418,24 @@ IGL_INLINE bool readPLY(
 
       // all strips should have tristrips->count elements
       if(!tinyply_tristrips_to_faces(*tristrips, F , tristrips->count, el_count))
-        F.resize(0,0);
+      {
+        // Don't do this (see above) F.resize(0,0);
+      }
 
     } else {
-      F.resize(0,0);
+      // Don't do this (see above) F.resize(0,0);
     }
   }
 
   if(!edges || !tinyply_buffer_to_matrix(*edges,E, edges->count,2)) {
-    E.resize(0,0);
+    // Don't do this (see above) E.resize(0,0);
   }
 
   /// convert vertex data:
   Vheader=_vertex_header;
   if(_vertex_header.empty())
   {
-    VD.resize(0,0);
+    // Don't do this (see above) VD.resize(0,0);
   }
   else
   {
@@ -445,7 +447,7 @@ IGL_INLINE bool readPLY(
   Fheader=_face_header;
   if(_face_header.empty())
   {
-    FD.resize(0,0);
+    // Don't do this (see above) FD.resize(0,0);
   }
   else
   {
@@ -457,7 +459,7 @@ IGL_INLINE bool readPLY(
   Eheader=_edge_header;
   if(_edge_header.empty())
   {
-    ED.resize(0,0);
+    // Don't do this (see above) ED.resize(0,0);
   }
   else
   {

+ 3 - 0
include/igl/readPLY.h

@@ -28,6 +28,9 @@ namespace igl
   /// @param[out] Eheader (#E) list of edge data headers
   /// @param[out] comments (*) file comments
   /// @return true on success, false on errors
+  ///
+  /// \note Unlike previous versions, all matrices are left untouched if they
+  /// are not read from the file. 
   template <
     typename DerivedV,
     typename DerivedF,