Browse Source

CGAL cdt with triangle's api (#1811)

* CGAL cdt with triangle's api

* special template for windows

* more special tempaltes for windows

* templates; expose cgal kernel

* fix test

* list->queue micro optimization; bool flag; templates

* Update min_size.cpp

special template for windows
Alec Jacobson 4 years ago
parent
commit
e9ff3a9e96

+ 4 - 0
include/igl/copyleft/cgal/assign.cpp

@@ -49,6 +49,10 @@ igl::copyleft::cgal::assign(
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template instantiation
 // generated by autoexplicit.sh
+template void igl::copyleft::cgal::assign<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> >&);
+// generated by autoexplicit.sh
+template void igl::copyleft::cgal::assign<Eigen::Matrix<double, 1, -1, 1, 1, -1>, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, 1, 3, 1, 1, 3> >(Eigen::MatrixBase<Eigen::Matrix<double, 1, -1, 1, 1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, 1, 3, 1, 1, 3> >&);
+// generated by autoexplicit.sh
 template void igl::copyleft::cgal::assign<Eigen::Matrix<double, -1, 3, 1, -1, 3>, Eigen::Matrix<double, -1, 3, 0, -1, 3> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 1, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&);
 // generated by autoexplicit.sh
 template void igl::copyleft::cgal::assign<Eigen::Matrix<float, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 3, 0, -1, 3> >(Eigen::MatrixBase<Eigen::Matrix<float, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&);

+ 148 - 0
include/igl/copyleft/cgal/triangulate.cpp

@@ -0,0 +1,148 @@
+#include "triangulate.h"
+#include "assign_scalar.h"
+#include "../../list_to_matrix.h"
+#include <CGAL/Point_2.h>
+#include <CGAL/Segment_2.h>
+#include <CGAL/Triangle_2.h>
+#include <CGAL/Constrained_Delaunay_triangulation_2.h>
+#include <CGAL/Constrained_triangulation_plus_2.h>
+#include <CGAL/Triangulation_face_base_with_info_2.h>
+#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
+#include <queue>
+
+template <
+  typename Kernel,
+  typename DerivedV,
+  typename DerivedE,
+  typename DerivedH,
+  typename DerivedV2,
+  typename DerivedF2>
+IGL_INLINE void igl::copyleft::cgal::triangulate(
+  const Eigen::MatrixBase<DerivedV> & V,
+  const Eigen::MatrixBase<DerivedE> & E,
+  const Eigen::MatrixBase<DerivedH> & H,
+  const bool retain_convex_hull,
+  Eigen::PlainObjectBase<DerivedV2> & TV,
+  Eigen::PlainObjectBase<DerivedF2> & TF)
+{
+  struct FaceInfo2
+  {
+    FaceInfo2(){}
+    bool visited = false;
+    bool in_domain = true;
+  };
+
+  typedef Eigen::Index Index;
+  //typedef CGAL::Epeck Kernel;
+  typedef CGAL::Point_2<Kernel>    Point_2;
+  typedef CGAL::Segment_2<Kernel>  Segment_2;
+  typedef CGAL::Triangle_2<Kernel> Triangle_2;
+  typedef CGAL::Triangulation_vertex_base_2<Kernel>  TVB_2;
+  typedef CGAL::Triangulation_face_base_with_info_2<FaceInfo2,Kernel>    TFB_2;
+  typedef CGAL::Constrained_triangulation_face_base_2<Kernel,TFB_2> CTFB_2;
+  typedef CGAL::Triangulation_data_structure_2<TVB_2,CTFB_2> TDS_2;
+  typedef CGAL::Exact_intersections_tag Itag;
+  typedef CGAL::Constrained_Delaunay_triangulation_2<Kernel,TDS_2,Itag> CDT_2;
+  typedef CGAL::Constrained_triangulation_plus_2<CDT_2> CDT_plus_2;
+  typedef typename CDT_plus_2::Face_handle Face_handle;
+
+  CDT_plus_2 cdt;
+  // Insert all points
+  std::vector<Point_2> points;points.reserve(V.rows());
+  for(Eigen::Index i = 0;i<V.rows();i++)
+  {
+    Point_2 p(V(i,0),V(i,1));
+    cdt.insert(p);
+    points.emplace_back(p);
+  }
+  // Insert all edges 
+  for(Eigen::Index e = 0;e<E.rows();e++)
+  {
+    cdt.insert_constraint(points[E(e,0)],points[E(e,1)]);
+  }
+
+  // https://doc.cgal.org/latest/Triangulation_2/index.html#title30
+  //
+  // "remove" connected component of face start by marking faces as
+  // in_domain = false. start should not yet be visited.
+  const auto remove_cc = [&](Face_handle start)
+  {
+    std::queue<Face_handle> queue;
+    queue.push(start);
+    while(!queue.empty())
+    {
+      Face_handle fh = queue.front();
+      queue.pop();
+      if(!fh->info().visited)
+      {
+        fh->info().visited = true;
+        fh->info().in_domain = false;
+        for(int i = 0; i < 3; i++)
+        {
+          typename CDT_plus_2::Edge e(fh,i);
+          Face_handle n = fh->neighbor(i);
+          if(!n->info().visited && !cdt.is_constrained(e))
+          {
+            queue.push(n);
+          }
+        }
+      }
+    }
+  };
+
+  // If _not_ meshsing convex hull, remove anything connected to infinite face
+  if(!retain_convex_hull)
+  {
+    remove_cc(cdt.infinite_face());
+  }
+  // remove holes
+  for(Eigen::Index h = 0;h<H.rows();h++)
+  {
+    remove_cc(cdt.locate({H(h,0),H(h,1)}));
+  }
+
+  std::vector<CGAL::Point_2<Kernel> > vertices;
+  std::vector<std::vector<Index> > faces;
+  // Read off vertices of the cdt, remembering index
+  std::map<typename CDT_plus_2::Vertex_handle,Index> v2i;
+  size_t count=0;
+  for (
+    auto itr = cdt.finite_vertices_begin();
+    itr != cdt.finite_vertices_end();
+    itr++)
+  {
+    vertices.push_back(itr->point());
+    v2i[itr] = count;
+    count++;
+  }
+  // Read off faces and store index triples
+  for (
+    auto itr = cdt.finite_faces_begin();
+    itr != cdt.finite_faces_end();
+    itr++)
+  {
+    if(itr->info().in_domain)
+    {
+      faces.push_back(
+        { v2i[itr->vertex(0)], v2i[itr->vertex(1)], v2i[itr->vertex(2)] });
+    }
+  }
+  TV.resize(vertices.size(),2);
+  for(int v = 0;v<vertices.size();v++)
+  {
+    for(int d = 0;d<2;d++)
+    {
+      assign_scalar(vertices[v][d], TV(v,d));
+    }
+  }
+  list_to_matrix(faces,TF);
+
+}
+
+
+#ifdef IGL_STATIC_LIBRARY
+// Explicit template instantiation
+template void igl::copyleft::cgal::triangulate<CGAL::Epeck, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, const bool , Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
+template void igl::copyleft::cgal::triangulate<CGAL::Epick, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&,       const bool , Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
+template void igl::copyleft::cgal::triangulate<CGAL::Epeck, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&,       const bool , Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
+#endif

+ 57 - 0
include/igl/copyleft/cgal/triangulate.h

@@ -0,0 +1,57 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+//
+// Copyright (C) 2021 Alec Jacobson
+//
+// 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_TRIANGULATE_H
+#define IGL_COPYLEFT_CGAL_TRIANGULATE_H
+
+#include "../../igl_inline.h"
+#include <string>
+#include <Eigen/Core>
+
+namespace igl
+{
+  namespace copyleft
+  {
+    namespace cgal
+    {
+      // Triangulate the interior of a polygon using the triangle library.
+      //
+      // Inputs:
+      //   V #V by 2 list of 2D vertex positions
+      //   E #E by 2 list of vertex ids forming unoriented edges of the boundary of the polygon
+      //   H #H by 2 coordinates of points contained inside holes of the polygon
+      //   retain_convex_hull  whether to retain convex hull {true} or trim away
+      //     all faces reachable from infinite by traversing across
+      //     non-constrained edges {false}.  {true → "c" flag in `triangle`}
+      // Outputs:
+      //   V2  #V2 by 2  coordinates of the vertives of the generated triangulation
+      //   F2  #F2 by 3  list of indices forming the faces of the generated triangulation
+      //
+      // See also: igl::triangle::triangulate
+      template <
+        typename Kernel,
+        typename DerivedV,
+        typename DerivedE,
+        typename DerivedH,
+        typename DerivedV2,
+        typename DerivedF2>
+      IGL_INLINE void triangulate(
+        const Eigen::MatrixBase<DerivedV> & V,
+        const Eigen::MatrixBase<DerivedE> & E,
+        const Eigen::MatrixBase<DerivedH> & H,
+        const bool retain_convex_hull,
+        Eigen::PlainObjectBase<DerivedV2> & V2,
+        Eigen::PlainObjectBase<DerivedF2> & F2);
+    }
+  }
+}
+
+#ifndef IGL_STATIC_LIBRARY
+#  include "triangulate.cpp"
+#endif
+
+#endif

+ 1 - 0
include/igl/list_to_matrix.cpp

@@ -227,5 +227,6 @@ template bool igl::list_to_matrix<unsigned __int64,class Eigen::Matrix<__int64,-
 template bool igl::list_to_matrix<unsigned __int64,class Eigen::Matrix<long,-1,1,0,-1,1> >(class std::vector<unsigned __int64,class std::allocator<unsigned __int64> > const &,class Eigen::PlainObjectBase<class Eigen::Matrix<long,-1,1,0,-1,1> > &);
 template bool igl::list_to_matrix<unsigned long long,class Eigen::Matrix<int,-1,1,0,-1,1> >(class std::vector<unsigned long long,class std::allocator<unsigned long long> > const &,class Eigen::PlainObjectBase<class Eigen::Matrix<int,-1,1,0,-1,1> > &);
 template bool igl::list_to_matrix<unsigned long, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(std::vector<unsigned long, std::allocator<unsigned long> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
+template bool igl::list_to_matrix<__int64,class Eigen::Matrix<int,-1,-1,0,-1,-1> >(class std::vector<class std::vector<__int64,class std::allocator<__int64> >,class std::allocator<class std::vector<__int64,class std::allocator<__int64> > > > const &,class Eigen::PlainObjectBase<class Eigen::Matrix<int,-1,-1,0,-1,-1> > &);
 #endif
 #endif

+ 3 - 0
include/igl/max_size.cpp

@@ -36,4 +36,7 @@ template int igl::max_size<std::vector<int, std::allocator<int> > >(std::vector<
 template int igl::max_size<std::vector<double, std::allocator<double> > >(std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > > const&);
 template int igl::max_size<std::vector<bool, std::allocator<bool> > >(std::vector<std::vector<bool, std::allocator<bool> >, std::allocator<std::vector<bool, std::allocator<bool> > > > const&);
 template int igl::max_size<std::vector<float, std::allocator<float> > >(std::vector<std::vector<float, std::allocator<float> >, std::allocator<std::vector<float, std::allocator<float> > > > const&);
+#ifdef WIN32
+template int igl::max_size<class std::vector<__int64,class std::allocator<__int64> > >(class std::vector<class std::vector<__int64,class std::allocator<__int64> >,class std::allocator<class std::vector<__int64,class std::allocator<__int64> > > > const &);
+#endif
 #endif

+ 3 - 0
include/igl/min_size.cpp

@@ -42,4 +42,7 @@ template int igl::min_size<std::vector<int, std::allocator<int> > >(std::vector<
 template int igl::min_size<std::vector<double, std::allocator<double> > >(std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > > const&);
 template int igl::min_size<std::vector<bool, std::allocator<bool> > >(std::vector<std::vector<bool, std::allocator<bool> >, std::allocator<std::vector<bool, std::allocator<bool> > > > const&);
 template int igl::min_size<std::vector<float, std::allocator<float> > >(std::vector<std::vector<float, std::allocator<float> >, std::allocator<std::vector<float, std::allocator<float> > > > const&);
+#ifdef WIN32
+template int igl::min_size<class std::vector<__int64, class std::allocator<__int64> > >(class std::vector<class std::vector<__int64, class std::allocator<__int64> >, class std::allocator<class std::vector<__int64, class std::allocator<__int64> > > > const&);
+#endif
 #endif

+ 2 - 0
include/igl/triangle/triangulate.cpp

@@ -171,6 +171,8 @@ IGL_INLINE void igl::triangle::triangulate(
 
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template instantiation
+// generated by autoexplicit.sh
+template void igl::triangle::triangulate<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 template void igl::triangle::triangulate<Eigen::Matrix<double, -1, -1, 1, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 1, -1, -1>, Eigen::Matrix<double, -1, -1, 1, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 1, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 1, -1, -1> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 1, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 template void igl::triangle::triangulate<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 #endif

+ 41 - 0
tests/include/igl/copyleft/cgal/triangulate.cpp

@@ -0,0 +1,41 @@
+#include <test_common.h>
+#include <igl/copyleft/cgal/triangulate.h>
+#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
+
+TEST_CASE("igl_copyleft_cgal_triangulate: sqannulus", "[igl/copyleft/cgal]")
+{
+  Eigen::MatrixXd V(8,2);
+  V<<0,0,3,0,3,3,0,3,
+     1,1,1,2,2,2,2,1;
+  Eigen::MatrixXi E(8,2);
+  E<<0,1,1,2,2,3,3,0,
+     4,5,5,6,6,7,7,4;
+  Eigen::MatrixXd H(1,2);
+  H<<1.5,1.5;
+  Eigen::MatrixXd TV;
+  Eigen::MatrixXi TF;
+  igl::copyleft::cgal::triangulate<CGAL::Epeck>(V,E,H,false,TV,TF);
+  Eigen::MatrixXd gt_TV(8,2);
+  gt_TV<<
+  0,0,
+  3,0,
+  3,3,
+  0,3,
+  1,1,
+  1,2,
+  2,2,
+  2,1;
+  Eigen::MatrixXi gt_TF(8,3);
+  gt_TF<<
+  7,4,0,
+  7,0,1,
+  3,0,4,
+  3,5,6,
+  3,4,5,
+  2,6,1,
+  2,3,6,
+  6,7,1;
+  test_common::assert_eq(TV,gt_TV);
+  test_common::assert_eq(TF,gt_TF);
+}
+