delaunay unit tests, expose is_delaunay, templates, PlainObject -> Matrix
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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> > > > &);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user