mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-05-20 03:43:52 +00:00
Update eigen to v5.0.1 and libigl to v2.6.0. (#11311)
* Update eigen from v3.3.7 to v5.0.1. This updates eigen from v3.3.7 released on December 11, 2018-12-11 to v5.0.1 released on 2025-11-11. There have be a large number of bug-fixes, optimizations, and improvements between these releases. See the details at; https://gitlab.com/libeigen/eigen/-/releases It retains the previous custom minimal `CMakeLists.txt`, and adds a README-OrcaSlicer.md that explains what version and parts of the upstream eigen release have been included, and where the full release can be found. * Update libigl from v2.0.0 (or older) to v2.6.0. This updates libigl from what was probably v2.0.0 released on 2018-10-16 to v2.6.0 released on 2025-05-15. It's possible the old version was even older than that but there is no version indicators in the code and I ran out of patience identifying missing changes and only went back as far as v2.0.0. There have been a large number of bug-fixes, optimizations, and improvements between these versions. See the following for details; https://github.com/libigl/libigl/releases I retained the minimal custom `CMakeLists.txt`, added `README.md` from the libigl distribution which identifies the version, and added a README-OrcaSlicer.md that details the version and parts that have been included. * Update libslic3r for libigl v2.6.0 changes. This updates libslic3r for all changes moving to eigen v5.0.1 and libigl v2.6.0. Despite the large number of updates to both dependencies, no changes were required for the eigen update, and only one change was required for the libigl update. For libigl, `igl::Hit` was changed to a template taking the Scalar type to use. Previously it was hard-coded to `float`, so to minimize possible impact I've updated all places it is used from `igl::Hit` to `igl::Hit<float>`. * Add compiler option `-DNOMINMAX` for libigl with MSVC. MSVC by default defines `min(()` and `max()` macros that break `std::numeric_limits<>::max()`. The upstream cmake that we don't include adds `-DNOMINMAX` for the libigl module when compiling with MSVC, so we need to add the same thing here. * Fix src/libslic3r/TriangleMeshDeal.cpp for the unmodified upstream libigl. This fixes `TriangleMeshDeal.cpp` to work with the unmodified upstream libigl v2.6.0. loop.{h,cpp} implementation. This file and feature was added in PR "BBS Port: Mesh Subdivision" (#12150) which included changes to `loop.{h,cpp}` in the old version of libigl. This PR avoids modifying the included dependencies, and uses the updated upstream versions of those files without any modifications, which requires fixing TriangleMeshDeal.cpp to work with them. In particular, the modifications made to `loop.{h,cpp}` included changing the return type from void to bool, adding additional validation checking of the input meshes, and returning false if they failed validation. These added checks looked unnecessary and would only have caught problems if the input mesh was very corrupt. To make `TriangleMeshDeal.cpp` work without this built-in checking functionality, I removed checking/handling of any `false` return value. There was also a hell of a lot of redundant copying and casting back and forth between float and double, so I cleaned that up. The input and output meshs use floats for the vertexes, and there would be no accuracy benefits from casting to and from doubles for the simple weighted average operations done by igl::loop(). So this just uses `Eigen:Map` to use the original input mesh vertex data directly without requiring any copy or casting. * Move eigen from included `deps_src` to externaly fetched `deps`. This copys what PrusaSlicer did and moved it from an included dependency under `deps_src` to an externaly fetched dependency under `deps`. This requires updating some `CMakeList.txt` configs and removing the old and obsolete `cmake/modules/FindEigen3.cmake`. The details of when this was done in PrusaSlicer and the followup fixes are at; *21116995d7* https://github.com/prusa3d/PrusaSlicer/issues/13608 * https://github.com/prusa3d/PrusaSlicer/pull/13609 *e3c277b9eeFor some reason I don't fully understand this also required fixing `src/slic3r/GUI/GUI_App.cpp` by adding `#include <boost/nowide/cstdio.hpp>` to fix an `error: ‘remove’ is not a member of ‘boost::nowide'`. The main thing I don't understand is how it worked before. Note that this include is in the PrusaSlicer version of this file, but it also significantly deviates from what is currently in OrcaSlicer in many other ways. * Whups... I missed adding the deps/Eigen/Eigen.cmake file... * Tidy some whitespace indenting in CMakeLists.txt. * Ugh... tabs indenting needing fixes. * Change the include order of deps/Eigen. It turns out that although Boost includes some references to Eigen, Eigen also includes some references to Boost for supporting some of it's additional numeric types. I don't think it matters much since we are not using these features, but I think technically its more correct to say Eigen depends on Boost than the other way around, so I've re-ordered them. * Add source for Eigen 5.0.1 download to flatpak yml config. * Add explicit `DEPENDS dep_Boost to deps/Eigen. I missed this before. This ensures we don't rely on include orders to make sure Boost is installed before we configure Eigen. * Add `DEPENDS dep_Boost dep_GMP dep_MPFR` to deps/Eigen. It turns out Eigen can also use GMP and MPFR for multi-precision and multi-precision-rounded numeric types if they are available. Again, I don't think we are using these so it doesn't really matter, but it is technically correct and ensures they are there if we ever do need them. * Fix deps DEPENDENCY ordering for GMP, MPFR, Eigen, and CGAL. I think this is finally correct. Apparently CGAL also optionally depends on Eigen, so the correct dependency order from lowest to highest is GMP, MPFR, Eigen, and CGAL. --------- Co-authored-by: Donovan Baarda <dbaarda@google.com> Co-authored-by: Noisyfox <timemanager.rick@gmail.com>
This commit is contained in:
43
deps_src/libigl/igl/predicates/delaunay_triangulation.cpp
Normal file
43
deps_src/libigl/igl/predicates/delaunay_triangulation.cpp
Normal file
@@ -0,0 +1,43 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2022 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 "delaunay_triangulation.h"
|
||||
#include "predicates.h"
|
||||
#include "../delaunay_triangulation.h"
|
||||
|
||||
template<
|
||||
typename DerivedV,
|
||||
typename DerivedF
|
||||
>
|
||||
IGL_INLINE void igl::predicates::delaunay_triangulation(
|
||||
const Eigen::MatrixBase<DerivedV>& V,
|
||||
Eigen::PlainObjectBase<DerivedF>& F)
|
||||
{
|
||||
const auto orient2d =
|
||||
[](const double *pa, const double *pb, const double *pc)
|
||||
{
|
||||
Eigen::Vector2d pav; pav << pa[0], pa[1];
|
||||
Eigen::Vector2d pbv; pbv << pb[0], pb[1];
|
||||
Eigen::Vector2d pcv; pcv << pc[0], pc[1];
|
||||
return int(igl::predicates::orient2d(pav, pbv, pcv));
|
||||
};
|
||||
const auto incircle =
|
||||
[](const double *pa, const double *pb, const double *pc, const double *pd)
|
||||
{
|
||||
Eigen::Vector2d pav; pav << pa[0], pa[1];
|
||||
Eigen::Vector2d pbv; pbv << pb[0], pb[1];
|
||||
Eigen::Vector2d pcv; pcv << pc[0], pc[1];
|
||||
Eigen::Vector2d pdv; pdv << pd[0], pd[1];
|
||||
return int(igl::predicates::incircle(pav, pbv, pcv, pdv));
|
||||
};
|
||||
igl::delaunay_triangulation(V, orient2d, incircle, F);
|
||||
}
|
||||
|
||||
#ifdef STATIC_LIBRARY
|
||||
template igl::predicates::delaunay_triangulation<Eigen::MatrixXd,Eigen::MatrixXi>(const Eigen::MatrixXd &, Eigen::MatrixXi &);
|
||||
#endif
|
||||
39
deps_src/libigl/igl/predicates/delaunay_triangulation.h
Normal file
39
deps_src/libigl/igl/predicates/delaunay_triangulation.h
Normal file
@@ -0,0 +1,39 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2022 Alec Jacobson <alecjacobson@gmail.com>
|
||||
// Copyright (C) 2016 Qingan Zhou <qnzhou@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_PREDICATES_DELAUNAY_TRIANGULATION_H
|
||||
#define IGL_PREDICATES_DELAUNAY_TRIANGULATION_H
|
||||
|
||||
#include "../igl_inline.h"
|
||||
#include <Eigen/Core>
|
||||
|
||||
namespace igl
|
||||
{
|
||||
namespace predicates
|
||||
{
|
||||
/// Given a set of points in 2D, return a Delaunay triangulation of these
|
||||
/// points using predicates.
|
||||
///
|
||||
/// @param[in] V #V by 2 list of vertex positions
|
||||
/// @param[out] F #F by 3 of faces in Delaunay triangulation.
|
||||
template<
|
||||
typename DerivedV,
|
||||
typename DerivedF
|
||||
>
|
||||
IGL_INLINE void delaunay_triangulation(
|
||||
const Eigen::MatrixBase<DerivedV>& V,
|
||||
Eigen::PlainObjectBase<DerivedF>& F);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef IGL_STATIC_LIBRARY
|
||||
# include "delaunay_triangulation.cpp"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
185
deps_src/libigl/igl/predicates/ear_clipping.cpp
Normal file
185
deps_src/libigl/igl/predicates/ear_clipping.cpp
Normal file
@@ -0,0 +1,185 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2019 Hanxiao Shen <hanxiao@cs.nyu.edu>
|
||||
//
|
||||
// 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 "ear_clipping.h"
|
||||
#include "predicates.h"
|
||||
#include "segment_segment_intersect.h"
|
||||
#include "../turning_number.h"
|
||||
|
||||
template <
|
||||
typename DerivedP,
|
||||
typename DerivedRT,
|
||||
typename DerivedF,
|
||||
typename DerivedI>
|
||||
IGL_INLINE void igl::predicates::ear_clipping(
|
||||
const Eigen::MatrixBase<DerivedP>& P,
|
||||
const Eigen::MatrixBase<DerivedRT>& RT,
|
||||
Eigen::PlainObjectBase<DerivedF>& eF,
|
||||
Eigen::PlainObjectBase<DerivedI>& I)
|
||||
{
|
||||
typedef typename DerivedF::Scalar Index;
|
||||
typedef typename DerivedP::Scalar Scalar;
|
||||
static_assert(std::is_same<typename DerivedI::Scalar,
|
||||
typename DerivedF::Scalar>::value,
|
||||
"index type should be consistent");
|
||||
|
||||
// check whether vertex i is an ear
|
||||
auto is_ear = [](
|
||||
const Eigen::MatrixBase<DerivedP>& P,
|
||||
const Eigen::MatrixBase<DerivedRT>& RT,
|
||||
const Eigen::Matrix<Index,Eigen::Dynamic,1>& L,
|
||||
const Eigen::Matrix<Index,Eigen::Dynamic,1>& R,
|
||||
const Index i
|
||||
){
|
||||
|
||||
// check if any edge in the leftover polygon intersects triangle (a,b,i)
|
||||
|
||||
Index a = L(i), b = R(i);
|
||||
if(RT(i) != 0 || RT(a) != 0 || RT(b) != 0) return false;
|
||||
Eigen::Matrix<Scalar,1,2> pa = P.row(a);
|
||||
Eigen::Matrix<Scalar,1,2> pb = P.row(b);
|
||||
Eigen::Matrix<Scalar,1,2> pi = P.row(i);
|
||||
auto r = igl::predicates::orient2d(pa, pi, pb);
|
||||
if(r == igl::predicates::Orientation::NEGATIVE ||
|
||||
r == igl::predicates::Orientation::COLLINEAR) return false;
|
||||
|
||||
// check edge (b, R(b))
|
||||
Index k = b;
|
||||
Index l = R(b);
|
||||
Eigen::Matrix<Scalar, 1, 2> pk = P.row(k);
|
||||
Eigen::Matrix<Scalar, 1, 2> pl = P.row(l);
|
||||
auto r1 = igl::predicates::orient2d(pb, pl, pa);
|
||||
auto r2 = igl::predicates::orient2d(pi, pl, pb);
|
||||
if (l == a) return true; // single triangle
|
||||
if (r1 != igl::predicates::Orientation::POSITIVE &&
|
||||
r2 != igl::predicates::Orientation::POSITIVE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// iterate through all edges do not have common endpoints with a, b
|
||||
k = l;
|
||||
l = R(k);
|
||||
while (l != a) {
|
||||
pk = P.row(k);
|
||||
pl = P.row(l);
|
||||
if (igl::predicates::segment_segment_intersect(pa, pb, pk, pl) ||
|
||||
igl::predicates::segment_segment_intersect(pa, pi, pk, pl) ||
|
||||
igl::predicates::segment_segment_intersect(pi, pb, pk, pl)
|
||||
){
|
||||
return false;
|
||||
}
|
||||
k = l;
|
||||
l = R(k);
|
||||
}
|
||||
|
||||
// check edge (L(a), a)
|
||||
pk = P.row(k);
|
||||
pl = P.row(l);
|
||||
r1 = igl::predicates::orient2d(pb, pk, pl);
|
||||
r2 = igl::predicates::orient2d(pi, pa, pk);
|
||||
if (r1 != igl::predicates::Orientation::POSITIVE &&
|
||||
r2 != igl::predicates::Orientation::POSITIVE
|
||||
){
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
Eigen::Matrix<Index,Eigen::Dynamic,1> L(P.rows());
|
||||
Eigen::Matrix<Index,Eigen::Dynamic,1> R(P.rows());
|
||||
for(int i = 0;i < P.rows(); i++){
|
||||
L(i) = Index((i - 1 + P.rows()) % P.rows());
|
||||
R(i) = Index((i + 1) % P.rows());
|
||||
}
|
||||
|
||||
Eigen::Matrix<Index, Eigen::Dynamic, 1> ears; // mark ears
|
||||
Eigen::Matrix<Index, Eigen::Dynamic, 1> X; // clipped vertices
|
||||
ears.setZero(P.rows());
|
||||
X.setZero(P.rows());
|
||||
|
||||
// initialize ears
|
||||
for(int i = 0; i < P.rows(); i++){
|
||||
ears(i) = is_ear(P, RT, L, R, i);
|
||||
}
|
||||
|
||||
// clip ears until none left
|
||||
while(ears.maxCoeff()==1){
|
||||
|
||||
// find the first ear
|
||||
Index e = 0;
|
||||
while(e < ears.rows() && ears(e) != 1) e++;
|
||||
|
||||
// find valid neighbors
|
||||
Index a = L(e), b = R(e);
|
||||
if(a == b) break;
|
||||
|
||||
// clip ear and store face
|
||||
eF.conservativeResize(eF.rows()+1,3);
|
||||
eF.bottomRows(1)<<a, e, b;
|
||||
L(b) = a;
|
||||
L(e) = -1;
|
||||
R(a) = b;
|
||||
R(e) = -1;
|
||||
ears(e) = 0; // mark vertex e as non-ear
|
||||
|
||||
// update neighbor's ear status
|
||||
ears(a) = is_ear(P, RT, L, R, a);
|
||||
ears(b) = is_ear(P, RT, L, R, b);
|
||||
X(e) = 1;
|
||||
|
||||
// when only one edge left
|
||||
// mark the endpoints as clipped
|
||||
if(L(a) == b && R(b) == a){
|
||||
X(a) = 1;
|
||||
X(b) = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// collect remaining vertices if theres any
|
||||
for(int i = 0;i < X.rows(); i++)
|
||||
{
|
||||
X(i) = 1 - X(i);
|
||||
}
|
||||
I.resize(X.sum());
|
||||
Index j=0;
|
||||
for(Index i = 0;i < X.rows(); i++)
|
||||
{
|
||||
if(X(i) == 1)
|
||||
{
|
||||
I(j++) = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename DerivedP,
|
||||
typename DerivedF>
|
||||
IGL_INLINE bool igl::predicates::ear_clipping(
|
||||
const Eigen::MatrixBase<DerivedP>& P,
|
||||
Eigen::PlainObjectBase<DerivedF>& eF)
|
||||
{
|
||||
if(turning_number(P) < 0)
|
||||
{
|
||||
// reverse input
|
||||
const auto rP = P.colwise().reverse().eval();
|
||||
const bool ret = igl::predicates::ear_clipping(rP, eF);
|
||||
// flip output
|
||||
eF = eF.rowwise().reverse();
|
||||
return ret;
|
||||
}
|
||||
const Eigen::Matrix<typename DerivedP::Scalar, Eigen::Dynamic, 1> RT =
|
||||
Eigen::Matrix<typename DerivedP::Scalar, Eigen::Dynamic, 1>::Zero(P.rows());
|
||||
Eigen::Matrix<typename DerivedF::Scalar, Eigen::Dynamic, 1> I;
|
||||
igl::predicates::ear_clipping(P, RT, eF, I);
|
||||
return I.size() == 0;
|
||||
}
|
||||
|
||||
#ifdef IGL_STATIC_LIBRARY
|
||||
template bool igl::predicates::ear_clipping<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>>&);
|
||||
template void igl::predicates::ear_clipping<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<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::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>>&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>>&);
|
||||
#endif
|
||||
63
deps_src/libigl/igl/predicates/ear_clipping.h
Normal file
63
deps_src/libigl/igl/predicates/ear_clipping.h
Normal file
@@ -0,0 +1,63 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2019 Hanxiao Shen <hanxiao@cs.nyu.edu>
|
||||
//
|
||||
// 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_PREDICATES_EAR_CLIPPING_H
|
||||
#define IGL_PREDICATES_EAR_CLIPPING_H
|
||||
|
||||
#include <Eigen/Core>
|
||||
#include "../igl_inline.h"
|
||||
|
||||
namespace igl
|
||||
{
|
||||
namespace predicates
|
||||
{
|
||||
/// Implementation of ear clipping triangulation algorithm for a 2D polygon.
|
||||
/// https://www.geometrictools.com/Documentation/TriangulationByEarClipping.pdf
|
||||
/// If the polygon is simple and oriented counter-clockwise, all vertices
|
||||
/// will be clipped and the result mesh is (P,eF) Otherwise, the function
|
||||
/// will try to clip as many ears as possible.
|
||||
///
|
||||
/// @param[in] P : n*2, size n 2D polygon
|
||||
/// @param[in] RT: n*1, preserved vertices (do not clip) marked as 1, otherwise 0
|
||||
/// @param[out] eF: clipped ears, in original index of P
|
||||
/// @param[out] I : size #nP vector, maps index from nP to P, e.g. nP's ith vertex is origianlly I(i) in P
|
||||
///
|
||||
/// \pre To result in a proper mesh, P should be oriented counter-clockwise
|
||||
/// with no self-intersections.
|
||||
///
|
||||
/// \note This implementation does not handle polygons with holes.
|
||||
///
|
||||
/// \bug https://github.com/libigl/libigl/issues/1563
|
||||
template <
|
||||
typename DerivedP,
|
||||
typename DerivedRT,
|
||||
typename DerivedF,
|
||||
typename DerivedI>
|
||||
IGL_INLINE void ear_clipping(
|
||||
const Eigen::MatrixBase<DerivedP>& P,
|
||||
const Eigen::MatrixBase<DerivedRT>& RT,
|
||||
Eigen::PlainObjectBase<DerivedF>& eF,
|
||||
Eigen::PlainObjectBase<DerivedI>& I);
|
||||
/// \overload
|
||||
/// \brief Reverses P if necessary. Orientation of output will match input
|
||||
/// \return true if mesh is proper (should correspond to input being a
|
||||
/// simple polygon in either orientation), false otherwise.
|
||||
template <typename DerivedP, typename DerivedF>
|
||||
IGL_INLINE bool ear_clipping(
|
||||
const Eigen::MatrixBase<DerivedP>& P,
|
||||
Eigen::PlainObjectBase<DerivedF>& eF);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef IGL_STATIC_LIBRARY
|
||||
# include "ear_clipping.cpp"
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
298
deps_src/libigl/igl/predicates/find_intersections.cpp
Normal file
298
deps_src/libigl/igl/predicates/find_intersections.cpp
Normal file
@@ -0,0 +1,298 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2022 Vladimir S. FONOV <vladimir.fonov@gmail.com>
|
||||
// Copyright (C) 2024 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 "find_intersections.h"
|
||||
|
||||
#include "../AABB.h"
|
||||
#include "../triangle_triangle_intersect_shared_edge.h"
|
||||
#include "../triangle_triangle_intersect_shared_vertex.h"
|
||||
#include "../find.h"
|
||||
#include "../list_to_matrix.h"
|
||||
#include "../placeholders.h"
|
||||
#include "triangle_triangle_intersect.h"
|
||||
#include "../triangle_triangle_intersect.h"
|
||||
#include <stdio.h>
|
||||
// atomic
|
||||
#include <igl/parallel_for.h>
|
||||
#include <atomic>
|
||||
#include <mutex>
|
||||
|
||||
template <
|
||||
typename DerivedV1,
|
||||
typename DerivedF1,
|
||||
typename DerivedV2,
|
||||
typename DerivedF2,
|
||||
typename DerivedIF,
|
||||
typename DerivedCP >
|
||||
IGL_INLINE bool igl::predicates::find_intersections(
|
||||
const igl::AABB<DerivedV1,3> & tree1,
|
||||
const Eigen::MatrixBase<DerivedV1> & V1,
|
||||
const Eigen::MatrixBase<DerivedF1> & F1,
|
||||
const Eigen::MatrixBase<DerivedV2> & V2,
|
||||
const Eigen::MatrixBase<DerivedF2> & F2,
|
||||
const bool first_only,
|
||||
Eigen::PlainObjectBase<DerivedIF> & IF,
|
||||
Eigen::PlainObjectBase<DerivedCP> & CP)
|
||||
{
|
||||
const bool detect_only = true;
|
||||
constexpr bool stinker = false;
|
||||
using AABBTree=igl::AABB<DerivedV1,3>;
|
||||
using Scalar=typename DerivedV1::Scalar;
|
||||
static_assert(
|
||||
std::is_same<Scalar,typename DerivedV2::Scalar>::value,
|
||||
"V1 and V2 must have the same scalar type");
|
||||
using RowVector3S=Eigen::Matrix<Scalar,1,3>;
|
||||
|
||||
// Determine if V1,F1 and V2,F2 point to the same data
|
||||
const bool self_test = (&V1 == &V2) && (&F1 == &F2);
|
||||
if(stinker){ printf("%s\n",self_test?"🍎&(V1,F1) == 🍎&(V2,F2)":"🍎≠🍊"); }
|
||||
|
||||
int num_if = 0;
|
||||
// mutex
|
||||
std::mutex append_mutex;
|
||||
const auto append_intersection =
|
||||
[&IF,&CP,&num_if,&append_mutex]( const int f1, const int f2, const bool coplanar = false)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(append_mutex);
|
||||
if(num_if >= IF.rows())
|
||||
{
|
||||
IF.conservativeResize(2*IF.rows()+1,2);
|
||||
CP.conservativeResize(IF.rows());
|
||||
}
|
||||
CP(num_if) = coplanar;
|
||||
IF.row(num_if) << f1,f2;
|
||||
num_if++;
|
||||
};
|
||||
|
||||
// Returns corner in ith face opposite of shared edge; -1 otherwise
|
||||
const auto shared_edge = [&F1](const int f, const int g)->int
|
||||
{
|
||||
for(int c = 0;c<3;c++)
|
||||
{
|
||||
int s = F1(f,(c+1)%3);
|
||||
int d = F1(f,(c+2)%3);
|
||||
for(int e = 0;e<3;e++)
|
||||
{
|
||||
//// Find in opposite direction on gth face
|
||||
//if(F1(g,e) == d && F1(g,(e+1)%3) == s)
|
||||
// Find in either direction on gth face
|
||||
if(
|
||||
(F1(g,e) == d && F1(g,(e+1)%3) == s) ||
|
||||
(F1(g,e) == s && F1(g,(e+1)%3) == d))
|
||||
{
|
||||
return c;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
};
|
||||
// Returns corner of shared vertex in ith face; -1 otherwise
|
||||
const auto shared_vertex = [&F1](const int f, const int g, int & sf, int & sg)->bool
|
||||
{
|
||||
for(sf = 0;sf<3;sf++)
|
||||
{
|
||||
for(sg = 0;sg<3;sg++)
|
||||
{
|
||||
if(F1(g,sg) == F1(f,sf))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
RowVector3S dummy;
|
||||
|
||||
igl::parallel_for(F2.rows(),[&](const int f2)
|
||||
{
|
||||
if(stinker){ printf("f2: %d\n",f2); }
|
||||
Eigen::AlignedBox<Scalar,3> box;
|
||||
box.extend( V2.row( F2(f2,0) ).transpose() );
|
||||
box.extend( V2.row( F2(f2,1) ).transpose() );
|
||||
box.extend( V2.row( F2(f2,2) ).transpose() );
|
||||
std::vector<const AABBTree*> candidates;
|
||||
tree1.append_intersecting_leaves(box, candidates);
|
||||
for(const auto * candidate : candidates)
|
||||
{
|
||||
const int f1 = candidate->m_primitive;
|
||||
if(stinker){ printf(" f1: %d\n",f1); }
|
||||
bool found_intersection = false;
|
||||
bool yes_shared_verted = false;
|
||||
bool yes_shared_edge = false;
|
||||
if(self_test)
|
||||
{
|
||||
// Skip self-test and direction f2>=f1 (assumes by symmetry we'll find
|
||||
// the other direction since we're testing all pairs)
|
||||
if(f1 >= f2)
|
||||
{
|
||||
if(stinker){ printf(" ⏭\n"); }
|
||||
continue;
|
||||
}
|
||||
const int c = shared_edge(f1,f2);
|
||||
yes_shared_edge = c != -1;
|
||||
if(yes_shared_edge)
|
||||
{
|
||||
if(stinker){ printf(" ⚠️ shared edge\n"); }
|
||||
if(stinker)
|
||||
{
|
||||
printf(" %d: %d %d %d\n",f1,F1(f1,0),F1(f1,1),F1(f1,2));
|
||||
printf(" %d: %d %d %d\n",f2,F1(f2,0),F1(f2,1),F1(f2,2));
|
||||
printf(" edge: %d %d\n",F1(f1,(c+1)%3),F1(f1,(c+2)%3));
|
||||
}
|
||||
found_intersection = igl::triangle_triangle_intersect_shared_edge(
|
||||
V1,F1,f1,c,V1.row(F1(f1,c)),f2,1e-8);
|
||||
if(found_intersection)
|
||||
{
|
||||
append_intersection(f1,f2,true);
|
||||
}
|
||||
}else
|
||||
{
|
||||
int sf,sg;
|
||||
yes_shared_verted = shared_vertex(f1,f2,sf,sg);
|
||||
if(yes_shared_verted)
|
||||
{
|
||||
if(stinker){ printf(" ⚠️ shared vertex\n"); }
|
||||
// Just to be sure. c≠sf
|
||||
const int c = (sf+1)%3;
|
||||
assert(F1(f1,sf) == F1(f2,sg));
|
||||
found_intersection = igl::triangle_triangle_intersect_shared_vertex(
|
||||
V1,F1,f1,sf,c,V1.row(F1(f1,c)),f2,sg,1e-14);
|
||||
if(found_intersection && detect_only)
|
||||
{
|
||||
// But wait? Couldn't these be coplanar?
|
||||
append_intersection(f1,f2,false);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
// This logic is confusing.
|
||||
if(
|
||||
!self_test ||
|
||||
(!yes_shared_verted && !yes_shared_edge) ||
|
||||
(yes_shared_verted && found_intersection && !detect_only))
|
||||
{
|
||||
bool coplanar = false;
|
||||
RowVector3S v1,v2;
|
||||
const bool tt_found_intersection =
|
||||
triangle_triangle_intersect(
|
||||
V2.row(F2(f2,0)).template head<3>().eval(),
|
||||
V2.row(F2(f2,1)).template head<3>().eval(),
|
||||
V2.row(F2(f2,2)).template head<3>().eval(),
|
||||
V1.row(F1(f1,0)).template head<3>().eval(),
|
||||
V1.row(F1(f1,1)).template head<3>().eval(),
|
||||
V1.row(F1(f1,2)).template head<3>().eval(),
|
||||
coplanar);
|
||||
if(found_intersection && !tt_found_intersection)
|
||||
{
|
||||
// We failed to find the edge. Mark it as an intersection but don't
|
||||
// include edge.
|
||||
append_intersection(f1,f2,coplanar);
|
||||
}else if(tt_found_intersection)
|
||||
{
|
||||
found_intersection = true;
|
||||
append_intersection(f1,f2,coplanar);
|
||||
}
|
||||
}
|
||||
if(stinker) { printf(" %s\n",found_intersection? "☠️":"❌"); }
|
||||
if(num_if && first_only) { return; }
|
||||
}
|
||||
if(num_if && first_only) { return; }
|
||||
},1000);
|
||||
IF.conservativeResize(num_if,2);
|
||||
CP.conservativeResize(IF.rows());
|
||||
return IF.rows();
|
||||
}
|
||||
|
||||
template <
|
||||
typename DerivedV1,
|
||||
typename DerivedF1,
|
||||
typename DerivedV2,
|
||||
typename DerivedF2,
|
||||
typename DerivedIF,
|
||||
typename DerivedCP>
|
||||
IGL_INLINE bool igl::predicates::find_intersections(
|
||||
const Eigen::MatrixBase<DerivedV1> & V1,
|
||||
const Eigen::MatrixBase<DerivedF1> & F1,
|
||||
const Eigen::MatrixBase<DerivedV2> & V2,
|
||||
const Eigen::MatrixBase<DerivedF2> & F2,
|
||||
const bool first_only,
|
||||
Eigen::PlainObjectBase<DerivedIF> & IF,
|
||||
Eigen::PlainObjectBase<DerivedCP> & CP)
|
||||
{
|
||||
igl::AABB<DerivedV1,3> tree1;
|
||||
tree1.init(V1,F1);
|
||||
return find_intersections(tree1,V1,F1,V2,F2,first_only,IF,CP);
|
||||
}
|
||||
|
||||
template <
|
||||
typename DerivedV1,
|
||||
typename DerivedF1,
|
||||
typename DerivedV2,
|
||||
typename DerivedF2,
|
||||
typename DerivedIF,
|
||||
typename DerivedCP,
|
||||
typename DerivedEV,
|
||||
typename DerivedEE,
|
||||
typename DerivedEI>
|
||||
IGL_INLINE bool igl::predicates::find_intersections(
|
||||
const Eigen::MatrixBase<DerivedV1> & V1,
|
||||
const Eigen::MatrixBase<DerivedF1> & F1,
|
||||
const Eigen::MatrixBase<DerivedV2> & V2,
|
||||
const Eigen::MatrixBase<DerivedF2> & F2,
|
||||
Eigen::PlainObjectBase<DerivedIF> & IF,
|
||||
Eigen::PlainObjectBase<DerivedCP> & CP,
|
||||
Eigen::PlainObjectBase<DerivedEV> & EV,
|
||||
Eigen::PlainObjectBase<DerivedEE> & EE,
|
||||
Eigen::PlainObjectBase<DerivedEI> & EI)
|
||||
{
|
||||
igl::AABB<DerivedV1,3> tree1;
|
||||
tree1.init(V1,F1);
|
||||
return find_intersections(tree1,V1,F1,V2,F2,IF,CP,EV,EE,EI);
|
||||
}
|
||||
|
||||
template <
|
||||
typename DerivedV1,
|
||||
typename DerivedF1,
|
||||
typename DerivedV2,
|
||||
typename DerivedF2,
|
||||
typename DerivedIF,
|
||||
typename DerivedCP,
|
||||
typename DerivedEV,
|
||||
typename DerivedEE,
|
||||
typename DerivedEI>
|
||||
IGL_INLINE bool igl::predicates::find_intersections(
|
||||
const igl::AABB<DerivedV1,3> & tree1,
|
||||
const Eigen::MatrixBase<DerivedV1> & V1,
|
||||
const Eigen::MatrixBase<DerivedF1> & F1,
|
||||
const Eigen::MatrixBase<DerivedV2> & V2,
|
||||
const Eigen::MatrixBase<DerivedF2> & F2,
|
||||
Eigen::PlainObjectBase<DerivedIF> & IF,
|
||||
Eigen::PlainObjectBase<DerivedCP> & CP,
|
||||
Eigen::PlainObjectBase<DerivedEV> & EV,
|
||||
Eigen::PlainObjectBase<DerivedEE> & EE,
|
||||
Eigen::PlainObjectBase<DerivedEI> & EI)
|
||||
{
|
||||
if(!find_intersections(tree1,V1,F1,V2,F2,false,IF,CP)) { return false; }
|
||||
std::vector<int> EI_vec = igl::find((CP.array()==false).eval());
|
||||
igl::list_to_matrix(EI_vec,EI);
|
||||
const auto IF_EI = IF(EI_vec,igl::placeholders::all).eval();
|
||||
igl::triangle_triangle_intersect(V1,F1,V2,F2,IF_EI,EV,EE);
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef IGL_STATIC_LIBRARY
|
||||
// Explicit template instantiation
|
||||
// generated by autoexplicit.sh
|
||||
template bool igl::predicates::find_intersections<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<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Array<bool, -1, 1, 0, -1, 1>, 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::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&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Array<bool, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -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> >&);
|
||||
// generated by autoexplicit.sh
|
||||
template bool igl::predicates::find_intersections<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<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Array<bool, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(igl::AABB<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 3> const&, 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&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Array<bool, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -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> >&);
|
||||
// generated by autoexplicit.sh
|
||||
template bool igl::predicates::find_intersections<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<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Array<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::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, bool, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Array<bool, -1, 1, 0, -1, 1> >&);
|
||||
#endif
|
||||
118
deps_src/libigl/igl/predicates/find_intersections.h
Normal file
118
deps_src/libigl/igl/predicates/find_intersections.h
Normal file
@@ -0,0 +1,118 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2024 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_FAST_FIND_INTERSECTIONS_H
|
||||
#define IGL_FAST_FIND_INTERSECTIONS_H
|
||||
|
||||
#include "../igl_inline.h"
|
||||
#include <Eigen/Core>
|
||||
|
||||
namespace igl
|
||||
{
|
||||
template <typename DerivedV, int DIM> class AABB;
|
||||
namespace predicates
|
||||
{
|
||||
/// Identify triangles where two meshes interesect
|
||||
/// using AABBTree and igl::predicates::triangle_triangle_intersect.
|
||||
///
|
||||
/// @param[in] tree1 AABB tree for the first mesh
|
||||
/// @param[in] V1 #V1 by 3 list representing vertices on the first mesh
|
||||
/// @param[in] F1 #F1 by 3 list representing triangles on the first mesh
|
||||
/// @param[in] V2 #V2 by 3 list representing vertices on the second mesh
|
||||
/// @param[in] F2 #F2 by 3 list representing triangles on the second mesh
|
||||
/// @param[out] IF #IF by 2 list of intersecting triangle pairs, so that
|
||||
/// F1(IF(i,0),:) intersects F2(IF(i,1),:)
|
||||
/// @param[out] CP #IF list of whether the intersection is coplanar
|
||||
///
|
||||
/// \see copyleft::cgal::intersect_other
|
||||
template <
|
||||
typename DerivedV1,
|
||||
typename DerivedF1,
|
||||
typename DerivedV2,
|
||||
typename DerivedF2,
|
||||
typename DerivedIF,
|
||||
typename DerivedCP>
|
||||
IGL_INLINE bool find_intersections(
|
||||
const AABB<DerivedV1,3> & tree1,
|
||||
const Eigen::MatrixBase<DerivedV1> & V1,
|
||||
const Eigen::MatrixBase<DerivedF1> & F1,
|
||||
const Eigen::MatrixBase<DerivedV2> & V2,
|
||||
const Eigen::MatrixBase<DerivedF2> & F2,
|
||||
const bool first_only,
|
||||
Eigen::PlainObjectBase<DerivedIF> & IF,
|
||||
Eigen::PlainObjectBase<DerivedCP> & CP);
|
||||
/// \overload
|
||||
/// \brief Tree built internally.
|
||||
template <
|
||||
typename DerivedV1,
|
||||
typename DerivedF1,
|
||||
typename DerivedV2,
|
||||
typename DerivedF2,
|
||||
typename DerivedIF,
|
||||
typename DerivedCP>
|
||||
IGL_INLINE bool find_intersections(
|
||||
const Eigen::MatrixBase<DerivedV1> & V1,
|
||||
const Eigen::MatrixBase<DerivedF1> & F1,
|
||||
const Eigen::MatrixBase<DerivedV2> & V2,
|
||||
const Eigen::MatrixBase<DerivedF2> & F2,
|
||||
const bool first_only,
|
||||
Eigen::PlainObjectBase<DerivedIF> & IF,
|
||||
Eigen::PlainObjectBase<DerivedCP> & CP);
|
||||
/// @param[out] EV #EV by 3 list of vertex positions of intersection segments
|
||||
/// @param[out] EE #EE by 2 list of edge indices into EV
|
||||
/// @param[out] EI #EI by 1 list of indices into rows IF indicating source of
|
||||
/// intersection.
|
||||
template <
|
||||
typename DerivedV1,
|
||||
typename DerivedF1,
|
||||
typename DerivedV2,
|
||||
typename DerivedF2,
|
||||
typename DerivedIF,
|
||||
typename DerivedCP,
|
||||
typename DerivedEV,
|
||||
typename DerivedEE,
|
||||
typename DerivedEI>
|
||||
IGL_INLINE bool find_intersections(
|
||||
const Eigen::MatrixBase<DerivedV1> & V1,
|
||||
const Eigen::MatrixBase<DerivedF1> & F1,
|
||||
const Eigen::MatrixBase<DerivedV2> & V2,
|
||||
const Eigen::MatrixBase<DerivedF2> & F2,
|
||||
Eigen::PlainObjectBase<DerivedIF> & IF,
|
||||
Eigen::PlainObjectBase<DerivedCP> & CP,
|
||||
Eigen::PlainObjectBase<DerivedEV> & EV,
|
||||
Eigen::PlainObjectBase<DerivedEE> & EE,
|
||||
Eigen::PlainObjectBase<DerivedEI> & EI);
|
||||
template <
|
||||
typename DerivedV1,
|
||||
typename DerivedF1,
|
||||
typename DerivedV2,
|
||||
typename DerivedF2,
|
||||
typename DerivedIF,
|
||||
typename DerivedCP,
|
||||
typename DerivedEV,
|
||||
typename DerivedEE,
|
||||
typename DerivedEI>
|
||||
IGL_INLINE bool find_intersections(
|
||||
const igl::AABB<DerivedV1,3> & tree1,
|
||||
const Eigen::MatrixBase<DerivedV1> & V1,
|
||||
const Eigen::MatrixBase<DerivedF1> & F1,
|
||||
const Eigen::MatrixBase<DerivedV2> & V2,
|
||||
const Eigen::MatrixBase<DerivedF2> & F2,
|
||||
Eigen::PlainObjectBase<DerivedIF> & IF,
|
||||
Eigen::PlainObjectBase<DerivedCP> & CP,
|
||||
Eigen::PlainObjectBase<DerivedEV> & EV,
|
||||
Eigen::PlainObjectBase<DerivedEE> & EE,
|
||||
Eigen::PlainObjectBase<DerivedEI> & EI);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef IGL_STATIC_LIBRARY
|
||||
# include "find_intersections.cpp"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
54
deps_src/libigl/igl/predicates/find_self_intersections.cpp
Normal file
54
deps_src/libigl/igl/predicates/find_self_intersections.cpp
Normal file
@@ -0,0 +1,54 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2024 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 "find_intersections.h"
|
||||
#include "find_self_intersections.h"
|
||||
|
||||
template <
|
||||
typename DerivedV,
|
||||
typename DerivedF,
|
||||
typename DerivedIF,
|
||||
typename DerivedCP>
|
||||
IGL_INLINE bool igl::predicates::find_self_intersections(
|
||||
const Eigen::MatrixBase<DerivedV> & V,
|
||||
const Eigen::MatrixBase<DerivedF> & F,
|
||||
const bool first_only,
|
||||
Eigen::PlainObjectBase<DerivedIF> & IF,
|
||||
Eigen::PlainObjectBase<DerivedCP> & CP)
|
||||
{
|
||||
// This is really just a wrapper around fast_find_intersections which will
|
||||
// internally detect that V,F are the second set
|
||||
return find_intersections( V,F,V,F,first_only,IF,CP);
|
||||
}
|
||||
|
||||
template <
|
||||
typename DerivedV,
|
||||
typename DerivedF,
|
||||
typename DerivedIF,
|
||||
typename DerivedCP,
|
||||
typename DerivedEV,
|
||||
typename DerivedEE,
|
||||
typename DerivedEI>
|
||||
bool igl::predicates::find_self_intersections(
|
||||
const Eigen::MatrixBase<DerivedV> & V,
|
||||
const Eigen::MatrixBase<DerivedF> & F,
|
||||
Eigen::PlainObjectBase<DerivedIF> & IF,
|
||||
Eigen::PlainObjectBase<DerivedCP> & CP,
|
||||
Eigen::PlainObjectBase<DerivedEV> & EV,
|
||||
Eigen::PlainObjectBase<DerivedEE> & EE,
|
||||
Eigen::PlainObjectBase<DerivedEI> & EI)
|
||||
{
|
||||
return find_intersections( V,F,V,F,IF,CP,EV,EE,EI);
|
||||
}
|
||||
|
||||
#ifdef IGL_STATIC_LIBRARY
|
||||
// Explicit template instantiation
|
||||
// generated by autoexplicit.sh
|
||||
template bool igl::predicates::find_self_intersections<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::Array<bool, -1, 1, 0, -1, 1>, 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::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<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Array<bool, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -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> >&);
|
||||
// generated by autoexplicit.sh
|
||||
template bool igl::predicates::find_self_intersections<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::Array<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&, bool, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Array<bool, -1, 1, 0, -1, 1> >&);
|
||||
#endif
|
||||
67
deps_src/libigl/igl/predicates/find_self_intersections.h
Normal file
67
deps_src/libigl/igl/predicates/find_self_intersections.h
Normal file
@@ -0,0 +1,67 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2024 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_PREDICATES_FIND_SELF_INTERSECTIONS_H
|
||||
#define IGL_PREDICATES_FIND_SELF_INTERSECTIONS_H
|
||||
|
||||
#include "../igl_inline.h"
|
||||
#include <Eigen/Core>
|
||||
|
||||
namespace igl
|
||||
{
|
||||
namespace predicates
|
||||
{
|
||||
/// Identify triangle-triangle interesections within the same mesh using
|
||||
/// AABBTree and igl::predicates::triangle_triangle_intersect.
|
||||
///
|
||||
/// @param[in] V #V by 3 list representing vertices on the first mesh
|
||||
/// @param[in] F #F by 3 list representing triangles on the first mesh
|
||||
/// @param[out] IF #IF by 2 list of intersecting triangle pairs, so that
|
||||
/// F1(IF(i,0),:) intersects F2(IF(i,1),:)
|
||||
/// @param[out] CP #IF list of whether the intersection is coplanar
|
||||
///
|
||||
/// \see copyleft::cgal::SelfIntersectMesh
|
||||
template <
|
||||
typename DerivedV,
|
||||
typename DerivedF,
|
||||
typename DerivedIF,
|
||||
typename DerivedCP>
|
||||
IGL_INLINE bool find_self_intersections(
|
||||
const Eigen::MatrixBase<DerivedV> & V,
|
||||
const Eigen::MatrixBase<DerivedF> & F,
|
||||
const bool first_only,
|
||||
Eigen::PlainObjectBase<DerivedIF> & IF,
|
||||
Eigen::PlainObjectBase<DerivedCP> & CP);
|
||||
/// @param[out] EV #EV by 3 list of vertex positions of intersection segments
|
||||
/// @param[out] EE #EE by 2 list of edge indices into EV
|
||||
/// @param[out] EI #EI by 1 list of indices into rows IF indicating source of
|
||||
/// intersection.
|
||||
template <
|
||||
typename DerivedV,
|
||||
typename DerivedF,
|
||||
typename DerivedIF,
|
||||
typename DerivedCP,
|
||||
typename DerivedEV,
|
||||
typename DerivedEE,
|
||||
typename DerivedEI>
|
||||
IGL_INLINE bool find_self_intersections(
|
||||
const Eigen::MatrixBase<DerivedV> & V,
|
||||
const Eigen::MatrixBase<DerivedF> & F,
|
||||
Eigen::PlainObjectBase<DerivedIF> & IF,
|
||||
Eigen::PlainObjectBase<DerivedCP> & CP,
|
||||
Eigen::PlainObjectBase<DerivedEV> & EV,
|
||||
Eigen::PlainObjectBase<DerivedEE> & EE,
|
||||
Eigen::PlainObjectBase<DerivedEI> & EI);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef IGL_STATIC_LIBRARY
|
||||
# include "find_self_intersections.cpp"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2022 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 "lexicographic_triangulation.h"
|
||||
#include "../lexicographic_triangulation.h"
|
||||
#include "predicates.h"
|
||||
|
||||
template<
|
||||
typename DerivedV,
|
||||
typename DerivedF
|
||||
>
|
||||
IGL_INLINE void igl::predicates::lexicographic_triangulation(
|
||||
const Eigen::MatrixBase<DerivedV>& V,
|
||||
Eigen::PlainObjectBase<DerivedF>& F)
|
||||
{
|
||||
const auto orient2d =
|
||||
[](const double *pa, const double *pb, const double *pc)
|
||||
{
|
||||
Eigen::Vector2d pav; pav << pa[0], pa[1];
|
||||
Eigen::Vector2d pbv; pbv << pb[0], pb[1];
|
||||
Eigen::Vector2d pcv; pcv << pc[0], pc[1];
|
||||
return int(igl::predicates::orient2d(pav, pbv, pcv));
|
||||
};
|
||||
igl::lexicographic_triangulation(V, orient2d, F);
|
||||
}
|
||||
|
||||
#ifdef STATIC_LIBRARY
|
||||
template igl::predicates::lexicographic_triangulation<Eigen::MatrixXd,Eigen::MatrixXi>(const Eigen::MatrixXd &, Eigen::MatrixXi &);
|
||||
#endif
|
||||
38
deps_src/libigl/igl/predicates/lexicographic_triangulation.h
Normal file
38
deps_src/libigl/igl/predicates/lexicographic_triangulation.h
Normal file
@@ -0,0 +1,38 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2022 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_PREDICATES_LEXICOGRAPHIC_TRIANGULATION_H
|
||||
#define IGL_PREDICATES_LEXICOGRAPHIC_TRIANGULATION_H
|
||||
|
||||
#include "../igl_inline.h"
|
||||
#include <Eigen/Core>
|
||||
|
||||
namespace igl
|
||||
{
|
||||
namespace predicates
|
||||
{
|
||||
/// Given a set of points in 2D, return a lexicographic triangulation of
|
||||
/// these points using predicates.
|
||||
///
|
||||
/// @param[in] V #V by 2 list of vertex positions
|
||||
/// @param[out] F #F by 3 of faces in Delaunay triangulation.
|
||||
template<
|
||||
typename DerivedV,
|
||||
typename DerivedF
|
||||
>
|
||||
IGL_INLINE void lexicographic_triangulation(
|
||||
const Eigen::MatrixBase<DerivedV>& V,
|
||||
Eigen::PlainObjectBase<DerivedF>& F);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef IGL_STATIC_LIBRARY
|
||||
# include "lexicographic_triangulation.cpp"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2019 Hanxiao Shen <hanxiao@cs.nyu.edu>
|
||||
//
|
||||
// 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 "point_inside_convex_polygon.h"
|
||||
|
||||
template <typename DerivedP, typename DerivedQ>
|
||||
IGL_INLINE bool igl::predicates::point_inside_convex_polygon(
|
||||
const Eigen::MatrixBase<DerivedP>& P,
|
||||
const Eigen::MatrixBase<DerivedQ>& q
|
||||
){
|
||||
EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(DerivedP, Eigen::Dynamic, 2);
|
||||
EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(DerivedQ, 1, 2);
|
||||
typedef typename DerivedP::Scalar Scalar;
|
||||
for(int i=0;i<P.rows();i++){
|
||||
int i_1 = (i+1) % P.rows();
|
||||
Eigen::Matrix<Scalar,1,2> a = P.row(i);
|
||||
Eigen::Matrix<Scalar,1,2> b = P.row(i_1);
|
||||
auto r = igl::predicates::orient2d(a,b,q);
|
||||
if(r == igl::predicates::Orientation::COLLINEAR ||
|
||||
r == igl::predicates::Orientation::NEGATIVE)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef IGL_STATIC_LIBRARY
|
||||
template bool igl::predicates::point_inside_convex_polygon<Eigen::Matrix<double, -1, 2, 0, -1, 2>, Eigen::Matrix<double, 1, 2, 1, 1, 2> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 2, 0, -1, 2> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> > const&);
|
||||
#endif
|
||||
38
deps_src/libigl/igl/predicates/point_inside_convex_polygon.h
Normal file
38
deps_src/libigl/igl/predicates/point_inside_convex_polygon.h
Normal file
@@ -0,0 +1,38 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2019 Hanxiao Shen <hanxiao@cs.nyu.edu>
|
||||
//
|
||||
// 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_PREDICATES_POINT_INSIDE_CONVEX_POLYGON_H
|
||||
#define IGL_PREDICATES_POINT_INSIDE_CONVEX_POLYGON_H
|
||||
|
||||
|
||||
|
||||
#include "../igl_inline.h"
|
||||
#include <Eigen/Core>
|
||||
#include "predicates.h"
|
||||
|
||||
namespace igl
|
||||
{
|
||||
namespace predicates
|
||||
{
|
||||
/// check whether 2d point lies inside 2d convex polygon
|
||||
/// @param[in] P: n*2 polygon, n >= 3
|
||||
/// @param[in] q: 2d query point
|
||||
/// @return true if point is inside polygon
|
||||
template <typename DerivedP, typename DerivedQ>
|
||||
IGL_INLINE bool point_inside_convex_polygon(
|
||||
const Eigen::MatrixBase<DerivedP>& P,
|
||||
const Eigen::MatrixBase<DerivedQ>& q
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef IGL_STATIC_LIBRARY
|
||||
# include "point_inside_convex_polygon.cpp"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
248
deps_src/libigl/igl/predicates/polygons_to_triangles.cpp
Normal file
248
deps_src/libigl/igl/predicates/polygons_to_triangles.cpp
Normal file
@@ -0,0 +1,248 @@
|
||||
#include "polygons_to_triangles.h"
|
||||
#include "ear_clipping.h"
|
||||
#include "../sort.h"
|
||||
#include "../placeholders.h"
|
||||
#include "../PlainMatrix.h"
|
||||
#include <Eigen/Eigenvalues>
|
||||
|
||||
template <
|
||||
typename DerivedV,
|
||||
typename DerivedI,
|
||||
typename DerivedC,
|
||||
typename DerivedF,
|
||||
typename DerivedJ>
|
||||
IGL_INLINE void igl::predicates::polygons_to_triangles(
|
||||
const Eigen::MatrixBase<DerivedV> & V,
|
||||
const Eigen::MatrixBase<DerivedI> & I,
|
||||
const Eigen::MatrixBase<DerivedC> & C,
|
||||
Eigen::PlainObjectBase<DerivedF> & F,
|
||||
Eigen::PlainObjectBase<DerivedJ> & J)
|
||||
{
|
||||
typedef Eigen::Index Index;
|
||||
// Each polygon results in #sides-2 triangles. So ∑#sides-2
|
||||
F.resize(C(C.size()-1) - (C.size()-1)*2,3);
|
||||
J.resize(F.rows());
|
||||
{
|
||||
Index f = 0;
|
||||
for(Index p = 0;p<C.size()-1;p++)
|
||||
{
|
||||
const Index np = C(p+1)-C(p);
|
||||
Eigen::MatrixXi pF;
|
||||
if(np == 3)
|
||||
{
|
||||
pF = (Eigen::MatrixXi(1,3)<<0,1,2).finished();
|
||||
}else
|
||||
{
|
||||
// Make little copy of this polygon with an initial fan
|
||||
PlainMatrix<DerivedV,Eigen::Dynamic> pV(np,V.cols());
|
||||
for(Index c = 0;c<np;c++)
|
||||
{
|
||||
pV.row(c) = V.row(I(C(p)+c));
|
||||
}
|
||||
// Use PCA to project to 2D
|
||||
Eigen::MatrixXd S;
|
||||
switch(V.cols())
|
||||
{
|
||||
case 2:
|
||||
S = V.template cast<double>();
|
||||
break;
|
||||
case 3:
|
||||
{
|
||||
Eigen::MatrixXd P = (pV.rowwise() - pV.colwise().mean()).template cast<double>();
|
||||
Eigen::Matrix3d O = P.transpose() * P;
|
||||
Eigen::EigenSolver<Eigen::Matrix3d> es(O);
|
||||
Eigen::Matrix3d C = es.eigenvectors().real();
|
||||
{
|
||||
Eigen::Vector3d _1;
|
||||
Eigen::Vector3i I;
|
||||
igl::sort(es.eigenvalues().real().eval(),1,false,_1,I);
|
||||
C = C(igl::placeholders::all,I).eval();
|
||||
}
|
||||
S = P*C.leftCols(2);
|
||||
break;
|
||||
}
|
||||
default: assert(false && "dim>3 not supported");
|
||||
}
|
||||
|
||||
Eigen::VectorXi RT = Eigen::VectorXi::Zero(S.rows(),1);
|
||||
Eigen::VectorXi _I;
|
||||
Eigen::MatrixXd _nS;
|
||||
|
||||
// compute signed area
|
||||
{
|
||||
double area = 0;
|
||||
for(Index c = 0;c<np;c++)
|
||||
{
|
||||
area += S((c+0)%np,0)*S((c+1)%np,1) - S((c+1)%np,0)*S((c+0)%np,1);
|
||||
}
|
||||
//prIndexf("area: %g\n",area);
|
||||
if(area<0)
|
||||
{
|
||||
S.col(0) *= -1;
|
||||
}
|
||||
}
|
||||
|
||||
// This is a really low quality triangulator and will contain nearly
|
||||
// degenerate elements which become degenerate or worse when unprojected
|
||||
// back to 3D.
|
||||
// igl::predicates::ear_clipping does not gracefully fail when the input
|
||||
// is not simple. Instead it (tends?) to output too few triangles.
|
||||
if(! igl::predicates::ear_clipping(S,pF) )
|
||||
{
|
||||
// Fallback, use a fan
|
||||
//std::cout<<igl::matlab_format(S,"S")<<std::endl;
|
||||
//std::cout<<igl::matlab_format(RT,"RT")<<std::endl;
|
||||
//std::cout<<igl::matlab_format(_I,"I")<<std::endl;
|
||||
//std::cout<<igl::matlab_format(pF,"pF")<<std::endl;
|
||||
//std::cout<<igl::matlab_format(_nS,"nS")<<std::endl;
|
||||
//std::cout<<std::endl;
|
||||
|
||||
pF.resize(np-2,3);
|
||||
for(Index c = 0;c<np;c++)
|
||||
{
|
||||
if(c>0 && c<np-1)
|
||||
{
|
||||
pF(c-1,0) = 0;
|
||||
pF(c-1,1) = c;
|
||||
pF(c-1,2) = c+1;
|
||||
}
|
||||
}
|
||||
}
|
||||
assert(pF.rows() == np-2);
|
||||
|
||||
// Could at least flip edges of degenerate edges
|
||||
|
||||
//if(pF.rows()>1)
|
||||
//{
|
||||
// // Delaunay-ize
|
||||
// Eigen::MatrixXd pl;
|
||||
// igl::edge_lengths(pV,pF,pl);
|
||||
|
||||
// typedef Eigen::Matrix<Index,Eigen::Dynamic,2> MatrixX2I;
|
||||
// typedef Eigen::Matrix<Index,Eigen::Dynamic,1> VectorXI;
|
||||
// MatrixX2I E,uE;
|
||||
// VectorXI EMAP;
|
||||
// std::vector<std::vector<Index> > uE2E;
|
||||
// igl::unique_edge_map(pF, E, uE, EMAP, uE2E);
|
||||
// typedef Index Index;
|
||||
// typedef double Scalar;
|
||||
// const Index num_faces = pF.rows();
|
||||
// std::vector<Index> Q;
|
||||
// Q.reserve(uE2E.size());
|
||||
// for (size_t uei=0; uei<uE2E.size(); uei++)
|
||||
// {
|
||||
// Q.push_back(uei);
|
||||
// }
|
||||
// while(!Q.empty())
|
||||
// {
|
||||
// const Index uei = Q.back();
|
||||
// Q.pop_back();
|
||||
// if (uE2E[uei].size() == 2)
|
||||
// {
|
||||
// double w;
|
||||
// igl::is_Indexrinsic_delaunay(pl,uE2E,num_faces,uei,w);
|
||||
// prIndexf("%d : %0.17f\n",uei,w);
|
||||
// if(w<-1e-7)
|
||||
// {
|
||||
// prIndexf(" flippin'\n");
|
||||
// //
|
||||
// // v1 v1
|
||||
// // /|\ / \
|
||||
// // c/ | \b c/f1 \b
|
||||
// // v3 /f2|f1\ v4 => v3 /__f__\ v4
|
||||
// // \ e / \ f2 /
|
||||
// // d\ | /a d\ /a
|
||||
// // \|/ \ /
|
||||
// // v2 v2
|
||||
// //
|
||||
// // hmm... is the flip actually in the other direction?
|
||||
// const Index f1 = uE2E[uei][0]%num_faces;
|
||||
// const Index f2 = uE2E[uei][1]%num_faces;
|
||||
// const Index c1 = uE2E[uei][0]/num_faces;
|
||||
// const Index c2 = uE2E[uei][1]/num_faces;
|
||||
// const size_t e_24 = f1 + ((c1 + 1) % 3) * num_faces;
|
||||
// const size_t e_41 = f1 + ((c1 + 2) % 3) * num_faces;
|
||||
// const size_t e_13 = f2 + ((c2 + 1) % 3) * num_faces;
|
||||
// const size_t e_32 = f2 + ((c2 + 2) % 3) * num_faces;
|
||||
// const size_t ue_24 = EMAP(e_24);
|
||||
// const size_t ue_41 = EMAP(e_41);
|
||||
// const size_t ue_13 = EMAP(e_13);
|
||||
// const size_t ue_32 = EMAP(e_32);
|
||||
// // new edge lengths
|
||||
// const Index v1 = pF(f1, (c1+1)%3);
|
||||
// const Index v2 = pF(f1, (c1+2)%3);
|
||||
// const Index v4 = pF(f1, c1);
|
||||
// const Index v3 = pF(f2, c2);
|
||||
// {
|
||||
// const Scalar e = pl(f1,c1);
|
||||
// const Scalar a = pl(f1,(c1+1)%3);
|
||||
// const Scalar b = pl(f1,(c1+2)%3);
|
||||
// const Scalar c = pl(f2,(c2+1)%3);
|
||||
// const Scalar d = pl(f2,(c2+2)%3);
|
||||
// const double f = (pV.row(v3)-pV.row(v4)).norm();
|
||||
// // New order
|
||||
// pl(f1,0) = f;
|
||||
// pl(f1,1) = b;
|
||||
// pl(f1,2) = c;
|
||||
// pl(f2,0) = f;
|
||||
// pl(f2,1) = d;
|
||||
// pl(f2,2) = a;
|
||||
// }
|
||||
// prIndexf("%d,%d %d,%d -> %d,%d\n",uE(uei,0),uE(uei,1),v1,v2,v3,v4);
|
||||
// igl::flip_edge(pF, E, uE, EMAP, uE2E, uei);
|
||||
// std::cout<<" "<<pl.row(f1)<<std::endl;
|
||||
// std::cout<<" "<<pl.row(f2)<<std::endl;
|
||||
// //// new edge lengths, slow!
|
||||
// //igl::edge_lengths(pV,pF,pl);
|
||||
// // recompute edge lengths of two faces. (extra work on untouched
|
||||
// // edges)
|
||||
// for(Index f : {f1,f2})
|
||||
// {
|
||||
// for(Index c=0;c<3;c++)
|
||||
// {
|
||||
// pl(f,c) =
|
||||
// (pV.row(pF(f,(c+1)%3))-pV.row(pF(f,(c+2)%3))).norm();
|
||||
// }
|
||||
// }
|
||||
// std::cout<<" "<<pl.row(f1)<<std::endl;
|
||||
// std::cout<<" "<<pl.row(f2)<<std::endl;
|
||||
// std::cout<<std::endl;
|
||||
|
||||
// Q.push_back(ue_24);
|
||||
// Q.push_back(ue_41);
|
||||
// Q.push_back(ue_13);
|
||||
// Q.push_back(ue_32);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
// // check for self-loops (I claim these cannot happen)
|
||||
// for(Index f = 0;f<pF.rows();f++)
|
||||
// {
|
||||
// for(Index c =0;c<3;c++)
|
||||
// {
|
||||
// assert(pF(f,c) != pF(f,(c+1)%3) && "self loops should not exist");
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
}
|
||||
// Copy Indexo global list
|
||||
for(Index i = 0;i<pF.rows();i++)
|
||||
{
|
||||
for(Index c =0;c<3;c++)
|
||||
{
|
||||
F(f,c) = I(C(p)+pF(i,c));
|
||||
}
|
||||
J(f) = p;
|
||||
f++;
|
||||
}
|
||||
|
||||
}
|
||||
assert(f == F.rows());
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef IGL_STATIC_LIBRARY
|
||||
// Explicit template instantiation
|
||||
#endif
|
||||
50
deps_src/libigl/igl/predicates/polygons_to_triangles.h
Normal file
50
deps_src/libigl/igl/predicates/polygons_to_triangles.h
Normal file
@@ -0,0 +1,50 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2020 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_POLYGONS_TO_TRIANGLES_H
|
||||
#define IGL_POLYGONS_TO_TRIANGLES_H
|
||||
|
||||
#include "../igl_inline.h"
|
||||
#include <Eigen/Core>
|
||||
#include <vector>
|
||||
|
||||
namespace igl
|
||||
{
|
||||
namespace predicates
|
||||
{
|
||||
/// Given a polygon mesh, trivially triangulate each polygon with a fan. This
|
||||
/// purely combinatorial triangulation will work well for convex/flat polygons
|
||||
/// and degrade otherwise.
|
||||
///
|
||||
/// @param[in] V #V by dim list of vertex positions
|
||||
/// @param[in] I #I vectorized list of polygon corner indices into rows of some matrix V
|
||||
/// @param[in] C #polygons+1 list of cumulative polygon sizes so that C(i+1)-C(i) =
|
||||
/// size of the ith polygon, and so I(C(i)) through I(C(i+1)-1) are the
|
||||
/// indices of the ith polygon
|
||||
/// @param[out] F #F by 3 list of triangle indices into rows of V
|
||||
/// @param[out] J #F list of indices into 0:#P-1 of corresponding polygon
|
||||
///
|
||||
template <
|
||||
typename DerivedV,
|
||||
typename DerivedI,
|
||||
typename DerivedC,
|
||||
typename DerivedF,
|
||||
typename DerivedJ>
|
||||
IGL_INLINE void polygons_to_triangles(
|
||||
const Eigen::MatrixBase<DerivedV> & V,
|
||||
const Eigen::MatrixBase<DerivedI> & I,
|
||||
const Eigen::MatrixBase<DerivedC> & C,
|
||||
Eigen::PlainObjectBase<DerivedF> & F,
|
||||
Eigen::PlainObjectBase<DerivedJ> & J);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef IGL_STATIC_LIBRARY
|
||||
# include "polygons_to_triangles.cpp"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
177
deps_src/libigl/igl/predicates/predicates.cpp
Normal file
177
deps_src/libigl/igl/predicates/predicates.cpp
Normal file
@@ -0,0 +1,177 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2019 Qingnan Zhou <qnzhou@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 "./predicates.h"
|
||||
// This is a different file also called predicates.h
|
||||
#include <predicates.h>
|
||||
#include <type_traits>
|
||||
|
||||
namespace igl {
|
||||
namespace predicates {
|
||||
|
||||
using REAL = IGL_PREDICATES_REAL;
|
||||
|
||||
#ifdef LIBIGL_PREDICATES_USE_FLOAT
|
||||
#define IGL_PREDICATES_ASSERT_SCALAR(Vector) \
|
||||
static_assert( \
|
||||
std::is_same<typename Vector::Scalar, float>::value, \
|
||||
"Shewchuk's exact predicates only support float")
|
||||
#else
|
||||
#define IGL_PREDICATES_ASSERT_SCALAR(Vector) \
|
||||
static_assert( \
|
||||
std::is_same<typename Vector::Scalar, double>::value || \
|
||||
std::is_same<typename Vector::Scalar, float>::value, \
|
||||
"Shewchuk's exact predicates only support float and double")
|
||||
#endif
|
||||
|
||||
IGL_INLINE void exactinit() {
|
||||
// Thread-safe initialization using Meyers' singleton
|
||||
class MySingleton {
|
||||
public:
|
||||
static MySingleton& instance() {
|
||||
static MySingleton instance;
|
||||
return instance;
|
||||
}
|
||||
private:
|
||||
MySingleton() { ::exactinit(); }
|
||||
};
|
||||
MySingleton::instance();
|
||||
}
|
||||
|
||||
template<typename Vector2D>
|
||||
IGL_INLINE Orientation orient2d(
|
||||
const Eigen::MatrixBase<Vector2D>& pa,
|
||||
const Eigen::MatrixBase<Vector2D>& pb,
|
||||
const Eigen::MatrixBase<Vector2D>& pc)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Vector2D, 2);
|
||||
IGL_PREDICATES_ASSERT_SCALAR(Vector2D);
|
||||
|
||||
using Point = Eigen::Matrix<REAL, 2, 1>;
|
||||
Point a{pa[0], pa[1]};
|
||||
Point b{pb[0], pb[1]};
|
||||
Point c{pc[0], pc[1]};
|
||||
|
||||
const auto r = ::orient2d(a.data(), b.data(), c.data());
|
||||
|
||||
if (r > 0) return Orientation::POSITIVE;
|
||||
else if (r < 0) return Orientation::NEGATIVE;
|
||||
else return Orientation::COLLINEAR;
|
||||
}
|
||||
|
||||
template<typename Vector3D>
|
||||
IGL_INLINE Orientation orient3d(
|
||||
const Eigen::MatrixBase<Vector3D>& pa,
|
||||
const Eigen::MatrixBase<Vector3D>& pb,
|
||||
const Eigen::MatrixBase<Vector3D>& pc,
|
||||
const Eigen::MatrixBase<Vector3D>& pd)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Vector3D, 3);
|
||||
IGL_PREDICATES_ASSERT_SCALAR(Vector3D);
|
||||
|
||||
using Point = Eigen::Matrix<REAL, 3, 1>;
|
||||
Point a{pa[0], pa[1], pa[2]};
|
||||
Point b{pb[0], pb[1], pb[2]};
|
||||
Point c{pc[0], pc[1], pc[2]};
|
||||
Point d{pd[0], pd[1], pd[2]};
|
||||
|
||||
const auto r = ::orient3d(a.data(), b.data(), c.data(), d.data());
|
||||
|
||||
if (r > 0) return Orientation::POSITIVE;
|
||||
else if (r < 0) return Orientation::NEGATIVE;
|
||||
else return Orientation::COPLANAR;
|
||||
}
|
||||
|
||||
template<typename Vector2D>
|
||||
IGL_INLINE Orientation incircle(
|
||||
const Eigen::MatrixBase<Vector2D>& pa,
|
||||
const Eigen::MatrixBase<Vector2D>& pb,
|
||||
const Eigen::MatrixBase<Vector2D>& pc,
|
||||
const Eigen::MatrixBase<Vector2D>& pd)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Vector2D, 2);
|
||||
IGL_PREDICATES_ASSERT_SCALAR(Vector2D);
|
||||
|
||||
using Point = Eigen::Matrix<REAL, 2, 1>;
|
||||
Point a{pa[0], pa[1]};
|
||||
Point b{pb[0], pb[1]};
|
||||
Point c{pc[0], pc[1]};
|
||||
Point d{pd[0], pd[1]};
|
||||
|
||||
const auto r = ::incircle(a.data(), b.data(), c.data(), d.data());
|
||||
|
||||
if (r > 0) return Orientation::INSIDE;
|
||||
else if (r < 0) return Orientation::OUTSIDE;
|
||||
else return Orientation::COCIRCULAR;
|
||||
}
|
||||
|
||||
template<typename Vector3D>
|
||||
IGL_INLINE Orientation insphere(
|
||||
const Eigen::MatrixBase<Vector3D>& pa,
|
||||
const Eigen::MatrixBase<Vector3D>& pb,
|
||||
const Eigen::MatrixBase<Vector3D>& pc,
|
||||
const Eigen::MatrixBase<Vector3D>& pd,
|
||||
const Eigen::MatrixBase<Vector3D>& pe)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Vector3D, 3);
|
||||
IGL_PREDICATES_ASSERT_SCALAR(Vector3D);
|
||||
|
||||
using Point = Eigen::Matrix<REAL, 3, 1>;
|
||||
Point a{pa[0], pa[1], pa[2]};
|
||||
Point b{pb[0], pb[1], pb[2]};
|
||||
Point c{pc[0], pc[1], pc[2]};
|
||||
Point d{pd[0], pd[1], pd[2]};
|
||||
Point e{pe[0], pe[1], pe[2]};
|
||||
|
||||
const auto r = ::insphere(a.data(), b.data(), c.data(), d.data(), e.data());
|
||||
|
||||
if (r > 0) return Orientation::INSIDE;
|
||||
else if (r < 0) return Orientation::OUTSIDE;
|
||||
else return Orientation::COSPHERICAL;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#undef IGL_PREDICATES_ASSERT_SCALAR
|
||||
|
||||
#ifdef IGL_STATIC_LIBRARY
|
||||
// Explicit template instantiation
|
||||
|
||||
#define IGL_ORIENT2D(Vector) template igl::predicates::Orientation igl::predicates::orient2d<Vector>(const Eigen::MatrixBase<Vector>&, const Eigen::MatrixBase<Vector>&, const Eigen::MatrixBase<Vector>&)
|
||||
#define IGL_INCIRCLE(Vector) template igl::predicates::Orientation igl::predicates::incircle<Vector>(const Eigen::MatrixBase<Vector>&, const Eigen::MatrixBase<Vector>&, const Eigen::MatrixBase<Vector>&, const Eigen::MatrixBase<Vector>&)
|
||||
#define IGL_ORIENT3D(Vector) template igl::predicates::Orientation igl::predicates::orient3d<Vector>(const Eigen::MatrixBase<Vector>&, const Eigen::MatrixBase<Vector>&, const Eigen::MatrixBase<Vector>&, const Eigen::MatrixBase<Vector>&)
|
||||
#define IGL_INSPHERE(Vector) template igl::predicates::Orientation igl::predicates::insphere<Vector>(const Eigen::MatrixBase<Vector>&, const Eigen::MatrixBase<Vector>&, const Eigen::MatrixBase<Vector>&, const Eigen::MatrixBase<Vector>&, const Eigen::MatrixBase<Vector>&)
|
||||
|
||||
#define IGL_MATRIX(T, R, C) Eigen::Matrix<T, R, C>
|
||||
IGL_ORIENT2D(IGL_MATRIX(float, 1, 2));
|
||||
IGL_INCIRCLE(IGL_MATRIX(float, 1, 2));
|
||||
IGL_ORIENT2D(IGL_MATRIX(float, 2, 1));
|
||||
IGL_INCIRCLE(IGL_MATRIX(float, 2, 1));
|
||||
IGL_ORIENT3D(IGL_MATRIX(float, 1, 3));
|
||||
IGL_INSPHERE(IGL_MATRIX(float, 1, 3));
|
||||
IGL_ORIENT3D(IGL_MATRIX(float, 3, 1));
|
||||
IGL_INSPHERE(IGL_MATRIX(float, 3, 1));
|
||||
|
||||
#ifndef LIBIGL_PREDICATES_USE_FLOAT
|
||||
IGL_ORIENT2D(IGL_MATRIX(double, 1, 2));
|
||||
IGL_INCIRCLE(IGL_MATRIX(double, 1, 2));
|
||||
IGL_ORIENT2D(IGL_MATRIX(double, 2, 1));
|
||||
IGL_INCIRCLE(IGL_MATRIX(double, 2, 1));
|
||||
IGL_ORIENT3D(IGL_MATRIX(double, 1, 3));
|
||||
IGL_INSPHERE(IGL_MATRIX(double, 1, 3));
|
||||
IGL_ORIENT3D(IGL_MATRIX(double, 3, 1));
|
||||
IGL_INSPHERE(IGL_MATRIX(double, 3, 1));
|
||||
#endif
|
||||
#undef IGL_MATRIX
|
||||
|
||||
#undef IGL_ORIENT2D
|
||||
#undef IGL_ORIENT3D
|
||||
#undef IGL_INCIRCLE
|
||||
#undef IGL_INSPHERE
|
||||
|
||||
#endif
|
||||
108
deps_src/libigl/igl/predicates/predicates.h
Normal file
108
deps_src/libigl/igl/predicates/predicates.h
Normal file
@@ -0,0 +1,108 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2019 Qingnan Zhou <qnzhou@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/.
|
||||
#pragma once
|
||||
#ifndef IGL_PREDICATES_PREDICATES_H
|
||||
#define IGL_PREDICATES_PREDICATES_H
|
||||
|
||||
#include "../igl_inline.h"
|
||||
#include <Eigen/Core>
|
||||
|
||||
namespace igl {
|
||||
namespace predicates {
|
||||
/// Types of orientations and other predicate results.
|
||||
///
|
||||
/// \fileinfo
|
||||
enum class Orientation {
|
||||
POSITIVE=1, INSIDE=1,
|
||||
NEGATIVE=-1, OUTSIDE=-1,
|
||||
COLLINEAR=0, COPLANAR=0, COCIRCULAR=0, COSPHERICAL=0, DEGENERATE=0
|
||||
};
|
||||
|
||||
/// Initialize internal variable used by predciates. Must be called before
|
||||
/// using exact predicates. It is safe to call this function from multiple
|
||||
/// threads.
|
||||
///
|
||||
/// \fileinfo
|
||||
IGL_INLINE void exactinit();
|
||||
|
||||
/// Compute the orientation of the triangle formed by pa, pb, pc.
|
||||
///
|
||||
/// @param[in] pa 2D point on line
|
||||
/// @param[in] pb 2D point on line
|
||||
/// @param[in] pc 2D query point.
|
||||
/// @return POSITIVE if pa, pb, pc are counterclockwise oriented.
|
||||
/// NEGATIVE if they are clockwise oriented.
|
||||
/// COLLINEAR if they are collinear.
|
||||
///
|
||||
/// \fileinfo
|
||||
template<typename Vector2D>
|
||||
IGL_INLINE Orientation orient2d(
|
||||
const Eigen::MatrixBase<Vector2D>& pa,
|
||||
const Eigen::MatrixBase<Vector2D>& pb,
|
||||
const Eigen::MatrixBase<Vector2D>& pc);
|
||||
/// Compute the orientation of the tetrahedron formed by pa, pb, pc, pd.
|
||||
///
|
||||
/// @param[in] pa 2D point on plane
|
||||
/// @param[in] pb 2D point on plane
|
||||
/// @param[in] pc 2D point on plane
|
||||
/// @param[in] pd 2D query point
|
||||
/// @return POSITIVE if pd is "below" the oriented plane formed by pa, pb and pc.
|
||||
/// NEGATIVE if pd is "above" the plane.
|
||||
/// COPLANAR if pd is on the plane.
|
||||
///
|
||||
/// \fileinfo
|
||||
template<typename Vector3D>
|
||||
IGL_INLINE Orientation orient3d(
|
||||
const Eigen::MatrixBase<Vector3D>& pa,
|
||||
const Eigen::MatrixBase<Vector3D>& pb,
|
||||
const Eigen::MatrixBase<Vector3D>& pc,
|
||||
const Eigen::MatrixBase<Vector3D>& pd);
|
||||
/// Decide whether a point is inside/outside/on a circle.
|
||||
///
|
||||
/// @param[in] pa 2D point on circle
|
||||
/// @param[in] pb 2D point on circle
|
||||
/// @param[in] pc 2D point on circle
|
||||
/// @param[in] pd 2D point query
|
||||
/// @return INSIDE if pd is inside of the circle defined by pa, pb and pc.
|
||||
/// OUSIDE if pd is outside of the circle.
|
||||
/// COCIRCULAR pd is exactly on the circle.
|
||||
///
|
||||
/// \fileinfo
|
||||
template<typename Vector2D>
|
||||
IGL_INLINE Orientation incircle(
|
||||
const Eigen::MatrixBase<Vector2D>& pa,
|
||||
const Eigen::MatrixBase<Vector2D>& pb,
|
||||
const Eigen::MatrixBase<Vector2D>& pc,
|
||||
const Eigen::MatrixBase<Vector2D>& pd);
|
||||
/// Decide whether a point is inside/outside/on a sphere.
|
||||
///
|
||||
/// @param[in] pa 2D point on sphere
|
||||
/// @param[in] pb 2D point on sphere
|
||||
/// @param[in] pc 2D point on sphere
|
||||
/// @param[in] pd 2D point on sphere
|
||||
/// @param[in] pe 2D point query
|
||||
/// @return INSIDE if pe is inside of the sphere defined by pa, pb, pc and pd.
|
||||
/// OUSIDE if pe is outside of the sphere.
|
||||
/// COSPHERICAL pd is exactly on the sphere.
|
||||
///
|
||||
/// \fileinfo
|
||||
template<typename Vector3D>
|
||||
IGL_INLINE Orientation insphere(
|
||||
const Eigen::MatrixBase<Vector3D>& pa,
|
||||
const Eigen::MatrixBase<Vector3D>& pb,
|
||||
const Eigen::MatrixBase<Vector3D>& pc,
|
||||
const Eigen::MatrixBase<Vector3D>& pd,
|
||||
const Eigen::MatrixBase<Vector3D>& pe);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef IGL_STATIC_LIBRARY
|
||||
# include "predicates.cpp"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
50
deps_src/libigl/igl/predicates/segment_segment_intersect.cpp
Normal file
50
deps_src/libigl/igl/predicates/segment_segment_intersect.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2019 Hanxiao Shen <hanxiao@cs.nyu.edu>
|
||||
//
|
||||
// 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 "segment_segment_intersect.h"
|
||||
|
||||
// https://www.geeksforgeeks.org/check-if-two-given-line-segments-intersect/
|
||||
template <typename DerivedP>
|
||||
IGL_INLINE bool igl::predicates::segment_segment_intersect(
|
||||
const Eigen::MatrixBase<DerivedP>& a,
|
||||
const Eigen::MatrixBase<DerivedP>& b,
|
||||
const Eigen::MatrixBase<DerivedP>& c,
|
||||
const Eigen::MatrixBase<DerivedP>& d
|
||||
)
|
||||
{
|
||||
auto t1 = igl::predicates::orient2d(a,b,c);
|
||||
auto t2 = igl::predicates::orient2d(b,c,d);
|
||||
auto t3 = igl::predicates::orient2d(a,b,d);
|
||||
auto t4 = igl::predicates::orient2d(a,c,d);
|
||||
|
||||
// assume m,n,p are colinear, check whether p is in range [m,n]
|
||||
auto on_segment = [](
|
||||
const Eigen::MatrixBase<DerivedP>& m,
|
||||
const Eigen::MatrixBase<DerivedP>& n,
|
||||
const Eigen::MatrixBase<DerivedP>& p
|
||||
){
|
||||
return ((p(0) >= std::min(m(0),n(0))) &&
|
||||
(p(0) <= std::max(m(0),n(0))) &&
|
||||
(p(1) >= std::min(m(1),n(1))) &&
|
||||
(p(1) <= std::max(m(1),n(1))));
|
||||
};
|
||||
|
||||
// colinear case
|
||||
if((t1 == igl::predicates::Orientation::COLLINEAR && on_segment(a,b,c)) ||
|
||||
(t2 == igl::predicates::Orientation::COLLINEAR && on_segment(c,d,b)) ||
|
||||
(t3 == igl::predicates::Orientation::COLLINEAR && on_segment(a,b,d)) ||
|
||||
(t4 == igl::predicates::Orientation::COLLINEAR && on_segment(c,d,a)))
|
||||
return true;
|
||||
|
||||
// ordinary case
|
||||
return (t1 != t3 && t2 != t4);
|
||||
}
|
||||
|
||||
#ifdef IGL_STATIC_LIBRARY
|
||||
template bool igl::predicates::segment_segment_intersect<Eigen::Matrix<double, 1, 2, 1, 1, 2> >(Eigen::MatrixBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> > const&);
|
||||
#endif
|
||||
39
deps_src/libigl/igl/predicates/segment_segment_intersect.h
Normal file
39
deps_src/libigl/igl/predicates/segment_segment_intersect.h
Normal file
@@ -0,0 +1,39 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2019 Hanxiao Shen <hanxiao@cs.nyu.edu>
|
||||
//
|
||||
// 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_PREDICATES_SEGMENT_SEGMENT_INTERSECT_H
|
||||
#define IGL_PREDICATES_SEGMENT_SEGMENT_INTERSECT_H
|
||||
|
||||
#include "../igl_inline.h"
|
||||
#include "predicates.h"
|
||||
#include <Eigen/Core>
|
||||
namespace igl
|
||||
{
|
||||
namespace predicates
|
||||
{
|
||||
/// Given two segments in 2d test whether they intersect each other
|
||||
/// using predicates orient2d
|
||||
///
|
||||
/// @param[in] A: 1st endpoint of segment 1
|
||||
/// @param[in] B: 2st endpoint of segment 1
|
||||
/// @param[in] C: 1st endpoint of segment 2
|
||||
/// @param[in] D: 2st endpoint of segment 2
|
||||
/// @return true if they intersect
|
||||
template <typename DerivedP>
|
||||
IGL_INLINE bool segment_segment_intersect(
|
||||
const Eigen::MatrixBase<DerivedP>& A,
|
||||
const Eigen::MatrixBase<DerivedP>& B,
|
||||
const Eigen::MatrixBase<DerivedP>& C,
|
||||
const Eigen::MatrixBase<DerivedP>& D
|
||||
);
|
||||
}
|
||||
}
|
||||
#ifndef IGL_STATIC_LIBRARY
|
||||
# include "segment_segment_intersect.cpp"
|
||||
#endif
|
||||
#endif
|
||||
318
deps_src/libigl/igl/predicates/triangle_triangle_intersect.cpp
Normal file
318
deps_src/libigl/igl/predicates/triangle_triangle_intersect.cpp
Normal file
@@ -0,0 +1,318 @@
|
||||
#include "triangle_triangle_intersect.h"
|
||||
#include "predicates.h"
|
||||
#include <Eigen/Core>
|
||||
#include <Eigen/Geometry>
|
||||
|
||||
template <typename Vector3D>
|
||||
IGL_INLINE bool igl::predicates::triangle_triangle_intersect(
|
||||
const Vector3D & p1,
|
||||
const Vector3D & q1,
|
||||
const Vector3D & r1,
|
||||
const Vector3D & p2,
|
||||
const Vector3D & q2,
|
||||
const Vector3D & r2,
|
||||
bool & coplanar)
|
||||
{
|
||||
coplanar = false;
|
||||
// yet another translation of tri_tri_intersect.c [Guigue & Devillers]
|
||||
exactinit();
|
||||
using Vector2D = Eigen::Matrix<typename Vector3D::Scalar,2,1>;
|
||||
|
||||
constexpr Orientation COPLANAR = igl::predicates::Orientation::COPLANAR;
|
||||
constexpr Orientation NEGATIVE = igl::predicates::Orientation::NEGATIVE;
|
||||
constexpr Orientation POSITIVE = igl::predicates::Orientation::POSITIVE;
|
||||
|
||||
// Determine for each vertex of one triangle if it's above, below or on the
|
||||
// plane of the other triangle.
|
||||
|
||||
// SUB(v1,p2,r2)
|
||||
// SUB(v2,q2,r2)
|
||||
// CROSS(N2,v1,v2)
|
||||
// SUB(v1,p1,r2)
|
||||
// dp1 = DOT(v1,N2);
|
||||
// dp1 = (p1-r2).dot( (p2-r2).cross(q2-r2) );
|
||||
const Orientation dp1 = orient3d(p2,q2,r2,p1);
|
||||
const Orientation dq1 = orient3d(p2,q2,r2,q1);
|
||||
const Orientation dr1 = orient3d(p2,q2,r2,r1);
|
||||
|
||||
const auto same_non_coplanar = [&NEGATIVE,&COPLANAR,&POSITIVE](
|
||||
const Orientation a,
|
||||
const Orientation b,
|
||||
const Orientation c)
|
||||
{
|
||||
return (a == POSITIVE && b == POSITIVE && c == POSITIVE) ||
|
||||
(a == NEGATIVE && b == NEGATIVE && c == NEGATIVE);
|
||||
};
|
||||
if(same_non_coplanar(dp1,dq1,dr1)) { return false; }
|
||||
|
||||
|
||||
const Orientation dp2 = orient3d(p1,q1,r1,p2);
|
||||
const Orientation dq2 = orient3d(p1,q1,r1,q2);
|
||||
const Orientation dr2 = orient3d(p1,q1,r1,r2);
|
||||
|
||||
// Theoreticaly, this should have already been fired above
|
||||
if(same_non_coplanar(dp2,dq2,dr2)) { return false; }
|
||||
|
||||
const auto tri_tri_overlap_test_2d = [&NEGATIVE,&COPLANAR,&POSITIVE](
|
||||
const Vector2D & p1,
|
||||
const Vector2D & q1,
|
||||
const Vector2D & r1,
|
||||
const Vector2D & p2,
|
||||
const Vector2D & q2,
|
||||
const Vector2D & r2)->bool
|
||||
{
|
||||
const auto ccw_tri_tri_intersection_2d = [&NEGATIVE,&COPLANAR,&POSITIVE](
|
||||
const Vector2D & p1,
|
||||
const Vector2D & q1,
|
||||
const Vector2D & r1,
|
||||
const Vector2D & p2,
|
||||
const Vector2D & q2,
|
||||
const Vector2D & r2)->bool
|
||||
{
|
||||
const auto INTERSECTION_TEST_VERTEX = [&NEGATIVE,&COPLANAR,&POSITIVE](
|
||||
const Vector2D & P1,
|
||||
const Vector2D & Q1,
|
||||
const Vector2D & R1,
|
||||
const Vector2D & P2,
|
||||
const Vector2D & Q2,
|
||||
const Vector2D & R2)->bool
|
||||
{
|
||||
if (orient2d(R2,P2,Q1) != NEGATIVE)
|
||||
if (orient2d(R2,Q2,Q1) != POSITIVE)
|
||||
if (orient2d(P1,P2,Q1) == POSITIVE) {
|
||||
if (orient2d(P1,Q2,Q1) != POSITIVE) return 1;
|
||||
else return 0;} else {
|
||||
if (orient2d(P1,P2,R1) != NEGATIVE)
|
||||
if (orient2d(Q1,R1,P2) != NEGATIVE) return 1;
|
||||
else return 0;
|
||||
else return 0;}
|
||||
else
|
||||
if (orient2d(P1,Q2,Q1) != POSITIVE)
|
||||
if (orient2d(R2,Q2,R1) != POSITIVE)
|
||||
if (orient2d(Q1,R1,Q2) != NEGATIVE) return 1;
|
||||
else return 0;
|
||||
else return 0;
|
||||
else return 0;
|
||||
else
|
||||
if (orient2d(R2,P2,R1) != NEGATIVE)
|
||||
if (orient2d(Q1,R1,R2) != NEGATIVE)
|
||||
if (orient2d(P1,P2,R1) != NEGATIVE) return 1;
|
||||
else return 0;
|
||||
else
|
||||
if (orient2d(Q1,R1,Q2) != NEGATIVE) {
|
||||
if (orient2d(R2,R1,Q2) != NEGATIVE) return 1;
|
||||
else return 0; }
|
||||
else return 0;
|
||||
else return 0;
|
||||
};
|
||||
const auto INTERSECTION_TEST_EDGE = [&NEGATIVE,&COPLANAR,&POSITIVE](
|
||||
const Vector2D & P1,
|
||||
const Vector2D & Q1,
|
||||
const Vector2D & R1,
|
||||
const Vector2D & P2,
|
||||
const Vector2D & Q2,
|
||||
const Vector2D & R2)->bool
|
||||
{
|
||||
if (orient2d(R2,P2,Q1) != NEGATIVE) {
|
||||
if (orient2d(P1,P2,Q1) != NEGATIVE) {
|
||||
if (orient2d(P1,Q1,R2) != NEGATIVE) return 1;
|
||||
else return 0;} else {
|
||||
if (orient2d(Q1,R1,P2) != NEGATIVE){
|
||||
if (orient2d(R1,P1,P2) != NEGATIVE) return 1; else return 0;}
|
||||
else return 0; }
|
||||
} else {
|
||||
if (orient2d(R2,P2,R1) != NEGATIVE) {
|
||||
if (orient2d(P1,P2,R1) != NEGATIVE) {
|
||||
if (orient2d(P1,R1,R2) != NEGATIVE) return 1;
|
||||
else {
|
||||
if (orient2d(Q1,R1,R2) != NEGATIVE) return 1; else return 0;}}
|
||||
else return 0; }
|
||||
else return 0; }
|
||||
};
|
||||
if ( orient2d(p2,q2,p1) != NEGATIVE ) {
|
||||
if ( orient2d(q2,r2,p1) != NEGATIVE ) {
|
||||
if ( orient2d(r2,p2,p1) != NEGATIVE ) return 1;
|
||||
else return INTERSECTION_TEST_EDGE(p1,q1,r1,p2,q2,r2);
|
||||
} else {
|
||||
if ( orient2d(r2,p2,p1) != NEGATIVE )
|
||||
return INTERSECTION_TEST_EDGE(p1,q1,r1,r2,p2,q2);
|
||||
else return INTERSECTION_TEST_VERTEX(p1,q1,r1,p2,q2,r2);}}
|
||||
else {
|
||||
if ( orient2d(q2,r2,p1) != NEGATIVE ) {
|
||||
if ( orient2d(r2,p2,p1) != NEGATIVE )
|
||||
return INTERSECTION_TEST_EDGE(p1,q1,r1,q2,r2,p2);
|
||||
else return INTERSECTION_TEST_VERTEX(p1,q1,r1,q2,r2,p2);}
|
||||
else return INTERSECTION_TEST_VERTEX(p1,q1,r1,r2,p2,q2);}
|
||||
return false;
|
||||
};
|
||||
if ( orient2d(p1,q1,r1) == NEGATIVE )
|
||||
if ( orient2d(p2,q2,r2) == NEGATIVE )
|
||||
return ccw_tri_tri_intersection_2d(p1,r1,q1,p2,r2,q2);
|
||||
else
|
||||
return ccw_tri_tri_intersection_2d(p1,r1,q1,p2,q2,r2);
|
||||
else
|
||||
if ( orient2d(p2,q2,r2) == NEGATIVE )
|
||||
return ccw_tri_tri_intersection_2d(p1,q1,r1,p2,r2,q2);
|
||||
else
|
||||
return ccw_tri_tri_intersection_2d(p1,q1,r1,p2,q2,r2);
|
||||
|
||||
};
|
||||
|
||||
const auto coplanar_tri_tri3d = [&tri_tri_overlap_test_2d,&NEGATIVE,&COPLANAR,&POSITIVE](
|
||||
const Vector3D & p1,
|
||||
const Vector3D & q1,
|
||||
const Vector3D & r1,
|
||||
const Vector3D & p2,
|
||||
const Vector3D & q2,
|
||||
const Vector3D & r2)->bool
|
||||
{
|
||||
Vector3D normal_1 = (q1-p1).cross(r1-p1);
|
||||
const auto n_x = ((normal_1[0]<0)?-normal_1[0]:normal_1[0]);
|
||||
const auto n_y = ((normal_1[1]<0)?-normal_1[1]:normal_1[1]);
|
||||
const auto n_z = ((normal_1[2]<0)?-normal_1[2]:normal_1[2]);
|
||||
Vector2D P1,Q1,R1,P2,Q2,R2;
|
||||
if (( n_x > n_z ) && ( n_x >= n_y )) {
|
||||
// Project onto plane YZ
|
||||
|
||||
P1[0] = q1[2]; P1[1] = q1[1];
|
||||
Q1[0] = p1[2]; Q1[1] = p1[1];
|
||||
R1[0] = r1[2]; R1[1] = r1[1];
|
||||
|
||||
P2[0] = q2[2]; P2[1] = q2[1];
|
||||
Q2[0] = p2[2]; Q2[1] = p2[1];
|
||||
R2[0] = r2[2]; R2[1] = r2[1];
|
||||
|
||||
} else if (( n_y > n_z ) && ( n_y >= n_x )) {
|
||||
// Project onto plane XZ
|
||||
|
||||
P1[0] = q1[0]; P1[1] = q1[2];
|
||||
Q1[0] = p1[0]; Q1[1] = p1[2];
|
||||
R1[0] = r1[0]; R1[1] = r1[2];
|
||||
|
||||
P2[0] = q2[0]; P2[1] = q2[2];
|
||||
Q2[0] = p2[0]; Q2[1] = p2[2];
|
||||
R2[0] = r2[0]; R2[1] = r2[2];
|
||||
|
||||
} else {
|
||||
// Project onto plane XY
|
||||
|
||||
P1[0] = p1[0]; P1[1] = p1[1];
|
||||
Q1[0] = q1[0]; Q1[1] = q1[1];
|
||||
R1[0] = r1[0]; R1[1] = r1[1];
|
||||
|
||||
P2[0] = p2[0]; P2[1] = p2[1];
|
||||
Q2[0] = q2[0]; Q2[1] = q2[1];
|
||||
R2[0] = r2[0]; R2[1] = r2[1];
|
||||
}
|
||||
|
||||
return tri_tri_overlap_test_2d(P1,Q1,R1,P2,Q2,R2);
|
||||
exit(1);
|
||||
return false;
|
||||
};
|
||||
|
||||
const auto TRI_TRI_3D = [&coplanar_tri_tri3d,&coplanar,&NEGATIVE,&COPLANAR,&POSITIVE](
|
||||
const Vector3D & p1,
|
||||
const Vector3D & q1,
|
||||
const Vector3D & r1,
|
||||
const Vector3D & p2,
|
||||
const Vector3D & q2,
|
||||
const Vector3D & r2,
|
||||
const Orientation dp2,
|
||||
const Orientation dq2,
|
||||
const Orientation dr2)->bool
|
||||
{
|
||||
const auto CHECK_MIN_MAX = [&NEGATIVE,&COPLANAR,&POSITIVE](
|
||||
const Vector3D & p1,
|
||||
const Vector3D & q1,
|
||||
const Vector3D & r1,
|
||||
const Vector3D & p2,
|
||||
const Vector3D & q2,
|
||||
const Vector3D & r2)->bool
|
||||
{
|
||||
if (orient3d(p2,p1,q1,q2) == POSITIVE) { return false; }
|
||||
if (orient3d(p2,r1,p1,r2) == POSITIVE) { return false; }
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
|
||||
if (dp2 == POSITIVE) {
|
||||
if (dq2 == POSITIVE) return CHECK_MIN_MAX(p1,r1,q1,r2,p2,q2) ;
|
||||
else if (dr2 == POSITIVE) return CHECK_MIN_MAX(p1,r1,q1,q2,r2,p2);
|
||||
else return CHECK_MIN_MAX(p1,q1,r1,p2,q2,r2);
|
||||
} else if (dp2 == NEGATIVE) {
|
||||
if (dq2 == NEGATIVE) return CHECK_MIN_MAX(p1,q1,r1,r2,p2,q2);
|
||||
else if (dr2 == NEGATIVE) return CHECK_MIN_MAX(p1,q1,r1,q2,r2,p2);
|
||||
else return CHECK_MIN_MAX(p1,r1,q1,p2,q2,r2);
|
||||
} else {
|
||||
if (dq2 == NEGATIVE) {
|
||||
if (dr2 == POSITIVE || dr2 == COPLANAR) return CHECK_MIN_MAX(p1,r1,q1,q2,r2,p2);
|
||||
else return CHECK_MIN_MAX(p1,q1,r1,p2,q2,r2);
|
||||
}
|
||||
else if (dq2 == POSITIVE) {
|
||||
if (dr2 == POSITIVE) return CHECK_MIN_MAX(p1,r1,q1,p2,q2,r2);
|
||||
else return CHECK_MIN_MAX(p1,q1,r1,q2,r2,p2);
|
||||
}
|
||||
else {
|
||||
if (dr2 == POSITIVE) return CHECK_MIN_MAX(p1,q1,r1,r2,p2,q2);
|
||||
else if (dr2 == NEGATIVE) return CHECK_MIN_MAX(p1,r1,q1,r2,p2,q2);
|
||||
else
|
||||
{
|
||||
coplanar = coplanar_tri_tri3d(p1,q1,r1,p2,q2,r2);
|
||||
return coplanar;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (dp1 == POSITIVE) {
|
||||
if (dq1 == POSITIVE) return TRI_TRI_3D(r1,p1,q1,p2,r2,q2,dp2,dr2,dq2);
|
||||
else if (dr1 == POSITIVE) return TRI_TRI_3D(q1,r1,p1,p2,r2,q2,dp2,dr2,dq2) ;
|
||||
else return TRI_TRI_3D(p1,q1,r1,p2,q2,r2,dp2,dq2,dr2);
|
||||
} else if (dp1 == NEGATIVE) {
|
||||
if (dq1 == NEGATIVE) return TRI_TRI_3D(r1,p1,q1,p2,q2,r2,dp2,dq2,dr2);
|
||||
else if (dr1 == NEGATIVE) return TRI_TRI_3D(q1,r1,p1,p2,q2,r2,dp2,dq2,dr2);
|
||||
else return TRI_TRI_3D(p1,q1,r1,p2,r2,q2,dp2,dr2,dq2);
|
||||
} else {
|
||||
if (dq1 == NEGATIVE) {
|
||||
// why COPLANAR here? It seems so haphazard.
|
||||
if (dr1 == POSITIVE || dr1 == COPLANAR) return TRI_TRI_3D(q1,r1,p1,p2,r2,q2,dp2,dr2,dq2);
|
||||
else return TRI_TRI_3D(p1,q1,r1,p2,q2,r2,dp2,dq2,dr2);
|
||||
}
|
||||
else if (dq1 == POSITIVE) {
|
||||
if (dr1 == POSITIVE) return TRI_TRI_3D(p1,q1,r1,p2,r2,q2,dp2,dr2,dq2);
|
||||
else return TRI_TRI_3D(q1,r1,p1,p2,q2,r2,dp2,dq2,dr2);
|
||||
}
|
||||
else {
|
||||
if (dr1 == POSITIVE) return TRI_TRI_3D(r1,p1,q1,p2,q2,r2,dp2,dq2,dr2);
|
||||
else if (dr1 == NEGATIVE) return TRI_TRI_3D(r1,p1,q1,p2,r2,q2,dp2,dr2,dq2);
|
||||
else
|
||||
{
|
||||
coplanar = coplanar_tri_tri3d(p1,q1,r1,p2,q2,r2);
|
||||
return coplanar;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#ifdef IGL_STATIC_LIBRARY
|
||||
// Explicit template specialization
|
||||
// template using Eigen::Vector3d.
|
||||
template bool igl::predicates::triangle_triangle_intersect<Eigen::Vector3d>(
|
||||
const Eigen::Vector3d & p1,
|
||||
const Eigen::Vector3d & q1,
|
||||
const Eigen::Vector3d & r1,
|
||||
const Eigen::Vector3d & p2,
|
||||
const Eigen::Vector3d & q2,
|
||||
const Eigen::Vector3d & r2,
|
||||
bool & coplanar);
|
||||
template bool igl::predicates::triangle_triangle_intersect<Eigen::RowVector3d>(
|
||||
const Eigen::RowVector3d & p1,
|
||||
const Eigen::RowVector3d & q1,
|
||||
const Eigen::RowVector3d & r1,
|
||||
const Eigen::RowVector3d & p2,
|
||||
const Eigen::RowVector3d & q2,
|
||||
const Eigen::RowVector3d & r2,
|
||||
bool & coplanar);
|
||||
#endif
|
||||
25
deps_src/libigl/igl/predicates/triangle_triangle_intersect.h
Normal file
25
deps_src/libigl/igl/predicates/triangle_triangle_intersect.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#ifndef IGL_PREDICATES_TRIANGLE_TRIANGLE_INTERSECT_H
|
||||
#define IGL_PREDICATES_TRIANGLE_TRIANGLE_INTERSECT_H
|
||||
#include "../igl_inline.h"
|
||||
|
||||
namespace igl
|
||||
{
|
||||
namespace predicates
|
||||
{
|
||||
template <typename Vector3D>
|
||||
IGL_INLINE bool triangle_triangle_intersect(
|
||||
const Vector3D & a1,
|
||||
const Vector3D & a2,
|
||||
const Vector3D & a3,
|
||||
const Vector3D & b1,
|
||||
const Vector3D & b2,
|
||||
const Vector3D & b3,
|
||||
bool & coplanar);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef IGL_STATIC_LIBRARY
|
||||
#include "triangle_triangle_intersect.cpp"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user