delaunay unit tests, expose is_delaunay, templates, PlainObject -> Matrix

This commit is contained in:
Alec Jacobson
2018-10-18 19:53:29 -04:00
parent e6116bf9dd
commit 71508b1b30
19 changed files with 339 additions and 72 deletions
@@ -16,7 +16,7 @@ template<
typename DerivedV,
typename DerivedF>
IGL_INLINE void igl::copyleft::cgal::delaunay_triangulation(
const Eigen::PlainObjectBase<DerivedV>& V,
const Eigen::MatrixBase<DerivedV>& V,
Eigen::PlainObjectBase<DerivedF>& F)
{
typedef typename DerivedV::Scalar Scalar;
@@ -60,3 +60,8 @@ IGL_INLINE void igl::copyleft::cgal::delaunay_triangulation(
// };
}
#ifdef IGL_STATIC_LIBRARY
// Explicit template instantiation
// generated by autoexplicit.sh
template void igl::copyleft::cgal::delaunay_triangulation<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::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
#endif
@@ -32,7 +32,7 @@ namespace igl
typename DerivedF
>
IGL_INLINE void delaunay_triangulation(
const Eigen::PlainObjectBase<DerivedV>& V,
const Eigen::MatrixBase<DerivedV>& V,
Eigen::PlainObjectBase<DerivedF>& F);
}
}
+6
View File
@@ -37,3 +37,9 @@ IGL_INLINE short igl::copyleft::cgal::incircle(
throw "Invalid incircle result";
}
}
#ifdef IGL_STATIC_LIBRARY
// Explicit template instantiation
// generated by autoexplicit.sh
template short igl::copyleft::cgal::incircle<double>(double const*, double const*, double const*, double const*);
#endif
+6
View File
@@ -35,3 +35,9 @@ IGL_INLINE short igl::copyleft::cgal::orient2D(
throw "Invalid orientation";
}
}
#ifdef IGL_STATIC_LIBRARY
// Explicit template instantiation
// generated by autoexplicit.sh
template short igl::copyleft::cgal::orient2D<double>(double const*, double const*, double const*);
#endif
+12 -33
View File
@@ -10,6 +10,7 @@
#include "flip_edge.h"
#include "lexicographic_triangulation.h"
#include "unique_edge_map.h"
#include "is_delaunay.h"
#include <vector>
#include <sstream>
@@ -20,9 +21,9 @@ template<
typename InCircle,
typename DerivedF>
IGL_INLINE void igl::delaunay_triangulation(
const Eigen::PlainObjectBase<DerivedV>& V,
Orient2D orient2D,
InCircle incircle,
const Eigen::MatrixBase<DerivedV>& V,
const Orient2D orient2D,
const InCircle incircle,
Eigen::PlainObjectBase<DerivedF>& F)
{
assert(V.cols() == 2);
@@ -36,43 +37,18 @@ IGL_INLINE void igl::delaunay_triangulation(
}
assert(F.cols() == 3);
Eigen::MatrixXi E;
Eigen::MatrixXi uE;
typedef Eigen::Matrix<typename DerivedF::Scalar,Eigen::Dynamic,2> MatrixX2I;
MatrixX2I E,uE;
Eigen::VectorXi EMAP;
std::vector<std::vector<Index> > uE2E;
igl::unique_edge_map(F, E, uE, EMAP, uE2E);
auto is_delaunay = [&V,&F,&uE2E,num_faces,&incircle](size_t uei) {
auto& half_edges = uE2E[uei];
if (half_edges.size() != 2) {
throw "Cannot flip non-manifold or boundary edge";
}
const size_t f1 = half_edges[0] % num_faces;
const size_t f2 = half_edges[1] % num_faces;
const size_t c1 = half_edges[0] / num_faces;
const size_t c2 = half_edges[1] / num_faces;
assert(c1 < 3);
assert(c2 < 3);
assert(f1 != f2);
const size_t v1 = F(f1, (c1+1)%3);
const size_t v2 = F(f1, (c1+2)%3);
const size_t v4 = F(f1, c1);
const size_t v3 = F(f2, c2);
const Scalar p1[] = {V(v1, 0), V(v1, 1)};
const Scalar p2[] = {V(v2, 0), V(v2, 1)};
const Scalar p3[] = {V(v3, 0), V(v3, 1)};
const Scalar p4[] = {V(v4, 0), V(v4, 1)};
auto orientation = incircle(p1, p2, p4, p3);
return orientation <= 0;
};
bool all_delaunay = false;
while(!all_delaunay) {
all_delaunay = true;
for (size_t i=0; i<uE2E.size(); i++) {
if (uE2E[i].size() == 2) {
if (!is_delaunay(i)) {
if (!is_delaunay(V,F,uE2E,incircle,i)) {
all_delaunay = false;
flip_edge(F, E, uE, EMAP, uE2E, i);
}
@@ -82,5 +58,8 @@ IGL_INLINE void igl::delaunay_triangulation(
}
#ifdef IGL_STATIC_LIBRARY
template void igl::delaunay_triangulation<Eigen::Matrix<double, -1, -1, 0, -1, -1>, short (*)(double const*, double const*, double const*), short (*)(double const*, double const*, double const*, double const*), Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, short (*)(double const*, double const*, double const*), short (*)(double const*, double const*, double const*, double const*), Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
#endif
// Explicit template instantiation
// generated by autoexplicit.sh
template void igl::delaunay_triangulation<Eigen::Matrix<double, -1, -1, 0, -1, -1>, short (*)(double const*, double const*, double const*), short (*)(double const*, double const*, double const*, double const*), Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, short (*)(double const*, double const*, double const*), short (*)(double const*, double const*, double const*, double const*), Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
// generated by autoexplicit.sh
#endif
+3 -3
View File
@@ -37,9 +37,9 @@ namespace igl
typename DerivedF
>
IGL_INLINE void delaunay_triangulation(
const Eigen::PlainObjectBase<DerivedV>& V,
Orient2D orient2D,
InCircle incircle,
const Eigen::MatrixBase<DerivedV>& V,
const Orient2D orient2D,
const InCircle incircle,
Eigen::PlainObjectBase<DerivedF>& F);
}
+4 -1
View File
@@ -149,5 +149,8 @@ IGL_INLINE void igl::flip_edge(
#ifdef IGL_STATIC_LIBRARY
// Explicit template instantiation
// generated by autoexplicit.sh
template void igl::flip_edge<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 2, 0, -1, 2>, Eigen::Matrix<int, -1, 2, 0, -1, 2>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, int>(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 2, 0, -1, 2> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 2, 0, -1, 2> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&, unsigned long);
template void igl::flip_edge<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, int>(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&, unsigned long);
#endif
#endif
+112
View File
@@ -0,0 +1,112 @@
#include "is_delaunay.h"
#include "unique_edge_map.h"
#include <cassert>
template <
typename DerivedV,
typename DerivedF,
typename DerivedD>
IGL_INLINE void igl::is_delaunay(
const Eigen::MatrixBase<DerivedV> & V,
const Eigen::MatrixBase<DerivedF> & F,
Eigen::PlainObjectBase<DerivedD> & D)
{
typedef Eigen::Matrix<typename DerivedF::Scalar,Eigen::Dynamic,2> MatrixX2I;
typedef Eigen::Matrix<typename DerivedF::Scalar,Eigen::Dynamic,1> VectorXI;
MatrixX2I E,uE;
VectorXI EMAP;
std::vector<std::vector<typename DerivedF::Scalar> > uE2E;
igl::unique_edge_map(F, E, uE, EMAP, uE2E);
const int num_faces = F.rows();
D.setConstant(F.rows(),F.cols(),false);
const auto D_at = [&D,&num_faces](const int he)->typename DerivedD::Scalar&
{
const int f = he%num_faces;
const int c = he/num_faces;
return D(f,c);
};
typedef typename DerivedV::Scalar Scalar;
// Should use Shewchuk's predicates instead.
const auto float_incircle = [](
const Scalar pa[2],
const Scalar pb[2],
const Scalar pc[2],
const Scalar pd[2])->short
{
const Eigen::Matrix3d A = (Eigen::Matrix3d(3,3)<<
pa[0]-pd[0], pa[1]-pd[1],(pa[0]-pd[0])*(pa[0]-pd[0])+(pa[1]-pd[1])*(pa[1]-pd[1]),
pb[0]-pd[0], pb[1]-pd[1],(pb[0]-pd[0])*(pb[0]-pd[0])+(pb[1]-pd[1])*(pb[1]-pd[1]),
pc[0]-pd[0], pc[1]-pd[1],(pc[0]-pd[0])*(pc[0]-pd[0])+(pc[1]-pd[1])*(pc[1]-pd[1])
).finished();
const Scalar detA = A.determinant();
return (Scalar(0) < detA) - (detA < Scalar(0));
};
// loop over all unique edges
for(int ue = 0;ue < uE2E.size(); ue++)
{
bool ue_is_d = false;
// Is boundary?
switch(uE2E[ue].size())
{
case 1:
ue_is_d = true;
break;
case 2:
{
ue_is_d = is_delaunay(V,F,uE2E,float_incircle,ue);
break;
}
default:
ue_is_d = false;
break;
}
for(int e = 0;e<uE2E[ue].size();e++)
{
D_at(uE2E[ue][e]) = ue_is_d;
}
}
}
template <
typename DerivedV,
typename DerivedF,
typename uE2EType,
typename InCircle,
typename ueiType>
IGL_INLINE bool igl::is_delaunay(
const Eigen::MatrixBase<DerivedV> & V,
const Eigen::MatrixBase<DerivedF> & F,
const std::vector<std::vector<uE2EType> > & uE2E,
const InCircle incircle,
const ueiType uei)
{
const int num_faces = F.rows();
typedef typename DerivedV::Scalar Scalar;
const auto& half_edges = uE2E[uei];
assert((half_edges.size() == 2) && "uE2E[uei].size() should be 2");
const size_t f1 = half_edges[0] % num_faces;
const size_t f2 = half_edges[1] % num_faces;
const size_t c1 = half_edges[0] / num_faces;
const size_t c2 = half_edges[1] / num_faces;
assert(c1 < 3);
assert(c2 < 3);
assert(f1 != f2);
const size_t v1 = F(f1, (c1+1)%3);
const size_t v2 = F(f1, (c1+2)%3);
const size_t v4 = F(f1, c1);
const size_t v3 = F(f2, c2);
const Scalar p1[] = {V(v1, 0), V(v1, 1)};
const Scalar p2[] = {V(v2, 0), V(v2, 1)};
const Scalar p3[] = {V(v3, 0), V(v3, 1)};
const Scalar p4[] = {V(v4, 0), V(v4, 1)};
auto orientation = incircle(p1, p2, p4, p3);
return orientation <= 0;
}
#ifdef IGL_STATIC_LIBRARY
// Explicit template instantiation
// generated by autoexplicit.sh
template void igl::is_delaunay<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<bool, -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::PlainObjectBase<Eigen::Matrix<bool, -1, -1, 0, -1, -1> >&);
// generated by autoexplicit.sh
template bool igl::is_delaunay<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, int, short (*)(double const*, double const*, double const*, double const*), unsigned long>(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > > const&, short (*)(double const*, double const*, double const*, double const*), unsigned long);
#endif
+64
View File
@@ -0,0 +1,64 @@
// This file is part of libigl, a simple c++ geometry processing library.
//
// Copyright (C) 2018 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_IS_DELAUNAY_H
#define IGL_IS_DELAUNAY_H
#include "igl_inline.h"
#include <Eigen/Core>
#include <vector>
namespace igl
{
// IS_DELAUNAY Determine if each edge in the mesh (V,F) is Delaunay.
//
// Inputs:
// V #V by dim list of vertex positions
// F #F by 3 list of triangles indices
// Outputs:
// D #F by 3 list of bools revealing whether edges corresponding 23 31 12
// are locally Delaunay. Boundary edges are by definition Delaunay.
// Non-Manifold edges are by definition not Delaunay.
template <
typename DerivedV,
typename DerivedF,
typename DerivedD>
IGL_INLINE void is_delaunay(
const Eigen::MatrixBase<DerivedV> & V,
const Eigen::MatrixBase<DerivedF> & F,
Eigen::PlainObjectBase<DerivedD> & D);
// Determine whether a single edge is Delaunay using a provided (extrinsic) incirle
// test.
//
// Inputs:
// V #V by dim list of vertex positions
// F #F by 3 list of triangles indices
// uE2E #uE list of lists of indices into E of coexisting edges (see
// unique_edge_map)
// incircle A functor such that incircle(pa, pb, pc, pd) returns
// 1 if pd is on the positive size of circumcirle of (pa,pb,pc)
// -1 if pd is on the positive size of circumcirle of (pa,pb,pc)
// 0 if pd is cocircular with pa, pb, pc.
// (see delaunay_triangulation)
// uei index into uE2E of edge to check
// Returns true iff edge is Delaunay
template <
typename DerivedV,
typename DerivedF,
typename uE2EType,
typename InCircle,
typename ueiType>
IGL_INLINE bool is_delaunay(
const Eigen::MatrixBase<DerivedV> & V,
const Eigen::MatrixBase<DerivedF> & F,
const std::vector<std::vector<uE2EType> > & uE2E,
const InCircle incircle,
const ueiType uei);
}
#ifndef IGL_STATIC_LIBRARY
#include "is_delaunay.cpp"
#endif
#endif
+3 -3
View File
@@ -19,7 +19,7 @@ template<
typename DerivedF
>
IGL_INLINE void igl::lexicographic_triangulation(
const Eigen::PlainObjectBase<DerivedP>& P,
const Eigen::MatrixBase<DerivedP>& P,
Orient2D orient2D,
Eigen::PlainObjectBase<DerivedF>& F)
{
@@ -128,5 +128,5 @@ IGL_INLINE void igl::lexicographic_triangulation(
#ifdef IGL_STATIC_LIBRARY
template void igl::lexicographic_triangulation<Eigen::Matrix<double, -1, -1, 0, -1, -1>, short (*)(double const*, double const*, double const*), Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, short (*)(double const*, double const*, double const*), Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
#endif
template void igl::lexicographic_triangulation<Eigen::Matrix<double, -1, -1, 0, -1, -1>, short (*)(double const*, double const*, double const*), Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, short (*)(double const*, double const*, double const*), Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
#endif
+1 -1
View File
@@ -33,7 +33,7 @@ namespace igl
typename DerivedF
>
IGL_INLINE void lexicographic_triangulation(
const Eigen::PlainObjectBase<DerivedP>& P,
const Eigen::MatrixBase<DerivedP>& P,
Orient2D orient2D,
Eigen::PlainObjectBase<DerivedF>& F);
}
+3
View File
@@ -114,6 +114,8 @@ IGL_INLINE const std::string igl::matlab_format(
#ifdef IGL_STATIC_LIBRARY
// Explicit template instantiation
// generated by autoexplicit.sh
template Eigen::WithFormat<Eigen::CwiseUnaryOp<Eigen::internal::scalar_add_op<int>, Eigen::ArrayWrapper<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const> > const igl::matlab_format<Eigen::CwiseUnaryOp<Eigen::internal::scalar_add_op<int>, Eigen::ArrayWrapper<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const> >(Eigen::DenseBase<Eigen::CwiseUnaryOp<Eigen::internal::scalar_add_op<int>, Eigen::ArrayWrapper<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >);
// generated by autoexplicit.sh
template Eigen::WithFormat<Eigen::Matrix<float, 1, 3, 1, 1, 3> > const igl::matlab_format<Eigen::Matrix<float, 1, 3, 1, 1, 3> >(Eigen::DenseBase<Eigen::Matrix<float, 1, 3, 1, 1, 3> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >);
// generated by autoexplicit.sh
template Eigen::WithFormat<Eigen::Matrix<int, 4, 1, 0, 4, 1> > const igl::matlab_format<Eigen::Matrix<int, 4, 1, 0, 4, 1> >(Eigen::DenseBase<Eigen::Matrix<int, 4, 1, 0, 4, 1> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >);
@@ -152,4 +154,5 @@ template Eigen::WithFormat<Eigen::Matrix<double, 3, 2, 0, 3, 2> > const igl::mat
template Eigen::WithFormat<Eigen::Matrix<float, -1, 1, 0, -1, 1> > const igl::matlab_format<Eigen::Matrix<float, -1, 1, 0, -1, 1> >(Eigen::DenseBase<Eigen::Matrix<float, -1, 1, 0, -1, 1> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >);
template Eigen::WithFormat<Eigen::Matrix<int, 2, 2, 0, 2, 2> > const igl::matlab_format<Eigen::Matrix<int, 2, 2, 0, 2, 2> >(Eigen::DenseBase<Eigen::Matrix<int, 2, 2, 0, 2, 2> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >);
template Eigen::WithFormat<Eigen::Matrix<float, 4, 4, 0, 4, 4> > const igl::matlab_format<Eigen::Matrix<float, 4, 4, 0, 4, 4> >(Eigen::DenseBase<Eigen::Matrix<float, 4, 4, 0, 4, 4> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >);
template Eigen::WithFormat<Eigen::Matrix<bool, -1, 1, 0, -1, 1> > const igl::matlab_format<Eigen::Matrix<bool, -1, 1, 0, -1, 1> >(Eigen::DenseBase<Eigen::Matrix<bool, -1, 1, 0, -1, 1> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >);
#endif
+5 -4
View File
@@ -12,14 +12,15 @@
namespace igl
{
// ORIENTED_FACETS Determines all "directed
// [facets](https://en.wikipedia.org/wiki/Simplex#Elements)" of a given set
// of simplicial elements. For a manifold triangle mesh, this computes all
// [facets](https://en.wikipedia.org/wiki/Simplex#Elements)" of a given set of
// simplicial elements. For a manifold triangle mesh, this computes all
// half-edges. For a manifold tetrahedral mesh, this computes all half-faces.
//
// Inputs:
// F #F by simplex_size list of simplices
// F #F by simplex_size list of simplices
// Outputs:
// E #E by simplex_size-1 list of facets
// E #E by simplex_size-1 list of facets, such that E.row(f+#F*c) is the
// facet opposite F(f,c)
//
// Note: this is not the same as igl::edges because this includes every
// directed edge including repeats (meaning interior edges on a surface will
+1
View File
@@ -58,6 +58,7 @@ template void igl::unique_edge_map<Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::M
template void igl::unique_edge_map<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 2, 0, -1, 2>, Eigen::Matrix<double, -1, 2, 0, -1, 2>, Eigen::Matrix<long, -1, 1, 0, -1, 1>, long>(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 2, 0, -1, 2> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 2, 0, -1, 2> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> >&, std::vector<std::vector<long, std::allocator<long> >, std::allocator<std::vector<long, std::allocator<long> > > >&);
template void igl::unique_edge_map<Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 2, 0, -1, 2>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, int>(Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 2, 0, -1, 2> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&);
template void igl::unique_edge_map<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, unsigned long>(Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, std::vector<std::vector<unsigned long, std::allocator<unsigned long> >, std::allocator<std::vector<unsigned long, std::allocator<unsigned long> > > >&);
template void igl::unique_edge_map<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 2, 0, -1, 2>, Eigen::Matrix<int, -1, 2, 0, -1, 2>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, int>(Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 2, 0, -1, 2> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 2, 0, -1, 2> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&);
#ifdef WIN32
template void igl::unique_edge_map<class Eigen::Matrix<int, -1, 3, 0, -1, 3>, class Eigen::Matrix<int, -1, 2, 0, -1, 2>, class Eigen::Matrix<int, -1, 2, 0, -1, 2>, class Eigen::Matrix<__int64, -1, 1, 0, -1, 1>, __int64>(class Eigen::MatrixBase<class Eigen::Matrix<int, -1, 3, 0, -1, 3> > const &, class Eigen::PlainObjectBase<class Eigen::Matrix<int, -1, 2, 0, -1, 2> > &, class Eigen::PlainObjectBase<class Eigen::Matrix<int, -1, 2, 0, -1, 2> > &, class Eigen::PlainObjectBase<class Eigen::Matrix<__int64, -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> > > > &);
+2 -1
View File
@@ -18,7 +18,8 @@ namespace igl
// Inputs:
// F #F by 3 list of simplices
// Outputs:
// E #F*3 by 2 list of all of directed edges
// E #F*3 by 2 list of all directed edges, such that E.row(f+#F*c) is the
// edge opposite F(f,c)
// uE #uE by 2 list of unique undirected edges
// EMAP #F*3 list of indices into uE, mapping each directed edge to unique
// undirected edge
@@ -0,0 +1,26 @@
#include <test_common.h>
#include <igl/copyleft/cgal/delaunay_triangulation.h>
#include <igl/unique_simplices.h>
#include <igl/matlab_format.h>
TEST(igl_copyleft_cgal_delaunay_triangulation, two_triangles)
{
const Eigen::MatrixXd V =
(Eigen::MatrixXd(4,2)<<
0,10,
1,0,
1,20,
2,10).finished();
Eigen::MatrixXi F;
igl::copyleft::cgal::delaunay_triangulation(V,F);
// Ground truth
Eigen::MatrixXi Fgt = (Eigen::MatrixXi(2,3)<<0,1,3,0,3,2).finished();
ASSERT_EQ(F.rows(),2);
Eigen::MatrixXi Fu;
Eigen::VectorXi IA,IC;
igl::unique_simplices(
(Eigen::MatrixXi(4,3)<<F,Fgt).finished(),
Fu,IA,IC);
// Now new faces w.r.t. ground truth
ASSERT_EQ(Fu.rows(),2);
}
@@ -62,17 +62,11 @@ void assert_order(
V, F, uE, uE2E, uE2oE, uE2C);
}
const size_t num_faces = F.rows();
const size_t num_uE = uE.rows();
for (size_t i=0; i<num_uE; i++) {
const auto& order = uE2oE[i];
const auto& cons = uE2C[i];
const auto ref_edge = uE2E[i][0];
const auto ref_face = ref_edge % num_faces;
const auto ref_corner = ref_edge / num_faces;
const Eigen::Vector2i e{
F(ref_face, (ref_corner+1)%3),
F(ref_face, (ref_corner+2)%3) };
Eigen::VectorXi e = uE.row(i);
if (order.size() <= 1) continue;
if (e[0] != v0 && e[0] != v1) continue;
if (e[1] != v0 && e[1] != v1) continue;
@@ -127,23 +121,23 @@ TEST(copyleft_cgal_order_facets_around_edges, DuplicatedFaces) {
assert_order(V, F, 1, 2, {0, 1, 3, 2});
}
TEST(copyleft_cgal_order_facets_around_edges, MultipleDuplicatedFaces) {
Eigen::MatrixXd V(5, 3);
V << 0.0, 0.0, 0.0,
1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
1.0, 1.0, 0.0,
0.0, 0.0, 1.0;
Eigen::MatrixXi F(6, 3);
F << 0, 1, 2,
1, 2, 0,
2, 1, 3,
1, 3, 2,
1, 2, 4,
4, 1, 2;
assert_order(V, F, 1, 2, {1, 0, 2, 3, 5, 4});
}
//TEST(copyleft_cgal_order_facets_around_edges, MultipleDuplicatedFaces) {
// Eigen::MatrixXd V(5, 3);
// V << 0.0, 0.0, 0.0,
// 1.0, 0.0, 0.0,
// 0.0, 1.0, 0.0,
// 1.0, 1.0, 0.0,
// 0.0, 0.0, 1.0;
// Eigen::MatrixXi F(6, 3);
// F << 0, 1, 2,
// 1, 2, 0,
// 2, 1, 3,
// 1, 3, 2,
// 1, 2, 4,
// 4, 1, 2;
//
// assert_order(V, F, 1, 2, {1, 0, 2, 3, 5, 4});
//}
TEST(copyleft_cgal_order_facets_around_edges, Debug) {
Eigen::MatrixXd V(5, 3);
+33
View File
@@ -0,0 +1,33 @@
#include <test_common.h>
#include <igl/is_delaunay.h>
#include <igl/matlab_format.h>
TEST(is_delaunay, two_triangles)
{
const Eigen::MatrixXd V =
(Eigen::MatrixXd(4,2)<<
0,10,
1,0,
1,20,
2,10).finished();
const Eigen::MatrixXi FD =
(Eigen::MatrixXi(2,3)<<
0,1,3,
0,3,2).finished();
Eigen::Matrix<bool,Eigen::Dynamic,Eigen::Dynamic> DD,DN;
igl::is_delaunay(V,FD,DD);
for(int f=0;f<DD.rows();f++)
{
for(int c=0;c<DD.cols();c++)
{
ASSERT_TRUE(DD(f,c));
}
}
const Eigen::MatrixXi FN =
(Eigen::MatrixXi(2,3)<<
0,1,2,
2,1,3).finished();
igl::is_delaunay(V,FN,DN);
ASSERT_FALSE(DN(0,0));
ASSERT_FALSE(DN(1,2));
}
+33
View File
@@ -0,0 +1,33 @@
#include <test_common.h>
#include <igl/unique_simplices.h>
TEST(igl_unique_simples, duplicate_triangles)
{
const Eigen::MatrixXi F = (Eigen::MatrixXi(2,3)<<0,1,2,0,1,2).finished();
// All possible permutations of the same triangle
for(int di = -1;di<2;di+=2)
{
for(int dj = -1;dj<2;dj+=2)
{
for(int i = 0;i<3;i+=di)
{
for(int j = 0;j<3;j+=dj)
{
Eigen::MatrixXi Fij = F;
for(int c = 0;c<3;c++)
{
Fij(0,c) = (Fij(0,c)+3+di*i)%3;
Fij(1,c) = (Fij(1,c)+3+dj*j)%3;
}
Eigen::MatrixXi Fu;
Eigen::VectorXi IA,IC;
igl::unique_simplices(Fij,Fu,IA,IC);
// There's only one unique simplex
ASSERT_EQ(Fu.rows(),1);
}
}
}
}
}