mirror of
https://github.com/FULU-Foundation/OrcaSlicer-bambulab.git
synced 2026-05-18 03:19:06 -07:00
Fixing dep build script on Windows and removing some warnings. Use bundled igl by default. Not building with the dependency scripts if not explicitly stated. This way, it will stay in Fix the libigl patch to include C source files in header only mode.
548 lines
25 KiB
C++
548 lines
25 KiB
C++
// This file is part of libigl, a simple c++ geometry processing library.
|
|
//
|
|
// Copyright (C) 2015 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 "extract_cells.h"
|
|
#include "closest_facet.h"
|
|
#include "order_facets_around_edge.h"
|
|
#include "outer_facet.h"
|
|
#include "submesh_aabb_tree.h"
|
|
#include "../../extract_manifold_patches.h"
|
|
#include "../../facet_components.h"
|
|
#include "../../get_seconds.h"
|
|
#include "../../triangle_triangle_adjacency.h"
|
|
#include "../../unique_edge_map.h"
|
|
#include "../../vertex_triangle_adjacency.h"
|
|
|
|
#include <CGAL/AABB_tree.h>
|
|
#include <CGAL/AABB_traits.h>
|
|
#include <CGAL/AABB_triangle_primitive.h>
|
|
#include <CGAL/intersections.h>
|
|
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
|
|
|
|
#include <iostream>
|
|
#include <vector>
|
|
#include <queue>
|
|
#include <map>
|
|
#include <set>
|
|
|
|
//#define EXTRACT_CELLS_DEBUG
|
|
|
|
template<
|
|
typename DerivedV,
|
|
typename DerivedF,
|
|
typename DerivedC >
|
|
IGL_INLINE size_t igl::copyleft::cgal::extract_cells(
|
|
const Eigen::PlainObjectBase<DerivedV>& V,
|
|
const Eigen::PlainObjectBase<DerivedF>& F,
|
|
Eigen::PlainObjectBase<DerivedC>& cells)
|
|
{
|
|
const size_t num_faces = F.rows();
|
|
// Construct edge adjacency
|
|
Eigen::MatrixXi E, uE;
|
|
Eigen::VectorXi EMAP;
|
|
std::vector<std::vector<size_t> > uE2E;
|
|
igl::unique_edge_map(F, E, uE, EMAP, uE2E);
|
|
// Cluster into manifold patches
|
|
Eigen::VectorXi P;
|
|
igl::extract_manifold_patches(F, EMAP, uE2E, P);
|
|
// Extract cells
|
|
DerivedC per_patch_cells;
|
|
const size_t num_cells =
|
|
igl::copyleft::cgal::extract_cells(V,F,P,E,uE,uE2E,EMAP,per_patch_cells);
|
|
// Distribute per-patch cell information to each face
|
|
cells.resize(num_faces, 2);
|
|
for (size_t i=0; i<num_faces; i++)
|
|
{
|
|
cells.row(i) = per_patch_cells.row(P[i]);
|
|
}
|
|
return num_cells;
|
|
}
|
|
|
|
|
|
template<
|
|
typename DerivedV,
|
|
typename DerivedF,
|
|
typename DerivedP,
|
|
typename DerivedE,
|
|
typename DeriveduE,
|
|
typename uE2EType,
|
|
typename DerivedEMAP,
|
|
typename DerivedC >
|
|
IGL_INLINE size_t igl::copyleft::cgal::extract_cells(
|
|
const Eigen::PlainObjectBase<DerivedV>& V,
|
|
const Eigen::PlainObjectBase<DerivedF>& F,
|
|
const Eigen::PlainObjectBase<DerivedP>& P,
|
|
const Eigen::PlainObjectBase<DerivedE>& E,
|
|
const Eigen::PlainObjectBase<DeriveduE>& uE,
|
|
const std::vector<std::vector<uE2EType> >& uE2E,
|
|
const Eigen::PlainObjectBase<DerivedEMAP>& EMAP,
|
|
Eigen::PlainObjectBase<DerivedC>& cells)
|
|
{
|
|
// Trivial base case
|
|
if(P.size() == 0)
|
|
{
|
|
assert(F.size() == 0);
|
|
cells.resize(0,2);
|
|
return 0;
|
|
}
|
|
|
|
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
|
|
typedef Kernel::Point_3 Point_3;
|
|
typedef Kernel::Plane_3 Plane_3;
|
|
typedef Kernel::Segment_3 Segment_3;
|
|
typedef Kernel::Triangle_3 Triangle;
|
|
typedef std::vector<Triangle>::iterator Iterator;
|
|
typedef CGAL::AABB_triangle_primitive<Kernel, Iterator> Primitive;
|
|
typedef CGAL::AABB_traits<Kernel, Primitive> AABB_triangle_traits;
|
|
typedef CGAL::AABB_tree<AABB_triangle_traits> Tree;
|
|
|
|
#ifdef EXTRACT_CELLS_DEBUG
|
|
const auto & tictoc = []() -> double
|
|
{
|
|
static double t_start = igl::get_seconds();
|
|
double diff = igl::get_seconds()-t_start;
|
|
t_start += diff;
|
|
return diff;
|
|
};
|
|
const auto log_time = [&](const std::string& label) -> void {
|
|
std::cout << "extract_cells." << label << ": "
|
|
<< tictoc() << std::endl;
|
|
};
|
|
tictoc();
|
|
#else
|
|
// no-op
|
|
const auto log_time = [](const std::string){};
|
|
#endif
|
|
const size_t num_faces = F.rows();
|
|
typedef typename DerivedF::Scalar Index;
|
|
assert(P.size() > 0);
|
|
const size_t num_patches = P.maxCoeff()+1;
|
|
|
|
// Extract all cells...
|
|
DerivedC raw_cells;
|
|
const size_t num_raw_cells =
|
|
extract_cells_single_component(V,F,P,uE,uE2E,EMAP,raw_cells);
|
|
log_time("extract_single_component_cells");
|
|
|
|
// Compute triangle-triangle adjacency data-structure
|
|
std::vector<std::vector<std::vector<Index > > > TT,_1;
|
|
igl::triangle_triangle_adjacency(E, EMAP, uE2E, false, TT, _1);
|
|
log_time("compute_face_adjacency");
|
|
|
|
// Compute connected components of the mesh
|
|
Eigen::VectorXi C, counts;
|
|
igl::facet_components(TT, C, counts);
|
|
log_time("form_components");
|
|
|
|
const size_t num_components = counts.size();
|
|
// components[c] --> list of face indices into F of faces in component c
|
|
std::vector<std::vector<size_t> > components(num_components);
|
|
// Loop over all faces
|
|
for (size_t i=0; i<num_faces; i++)
|
|
{
|
|
components[C[i]].push_back(i);
|
|
}
|
|
// Convert vector lists to Eigen lists...
|
|
// and precompute data-structures for each component
|
|
std::vector<std::vector<size_t> > VF,VFi;
|
|
igl::vertex_triangle_adjacency(V.rows(), F, VF, VFi);
|
|
std::vector<Eigen::VectorXi> Is(num_components);
|
|
std::vector<
|
|
CGAL::AABB_tree<
|
|
CGAL::AABB_traits<
|
|
Kernel,
|
|
CGAL::AABB_triangle_primitive<
|
|
Kernel, std::vector<
|
|
Kernel::Triangle_3 >::iterator > > > > trees(num_components);
|
|
std::vector< std::vector<Kernel::Triangle_3 > >
|
|
triangle_lists(num_components);
|
|
std::vector<std::vector<bool> > in_Is(num_components);
|
|
|
|
// Find outer facets, their orientations and cells for each component
|
|
Eigen::VectorXi outer_facets(num_components);
|
|
Eigen::VectorXi outer_facet_orientation(num_components);
|
|
Eigen::VectorXi outer_cells(num_components);
|
|
for (size_t i=0; i<num_components; i++)
|
|
{
|
|
Is[i].resize(components[i].size());
|
|
std::copy(components[i].begin(), components[i].end(),Is[i].data());
|
|
bool flipped;
|
|
igl::copyleft::cgal::outer_facet(V, F, Is[i], outer_facets[i], flipped);
|
|
outer_facet_orientation[i] = flipped?1:0;
|
|
outer_cells[i] = raw_cells(P[outer_facets[i]], outer_facet_orientation[i]);
|
|
}
|
|
#ifdef EXTRACT_CELLS_DEBUG
|
|
log_time("outer_facet_per_component");
|
|
#endif
|
|
|
|
// Compute barycenter of a triangle in mesh (V,F)
|
|
//
|
|
// Inputs:
|
|
// fid index into F
|
|
// Returns row-vector of barycenter coordinates
|
|
const auto get_triangle_center = [&V,&F](const size_t fid)
|
|
{
|
|
return ((V.row(F(fid,0))+V.row(F(fid,1))+V.row(F(fid,2)))/3.0).eval();
|
|
};
|
|
std::vector<std::vector<size_t> > nested_cells(num_raw_cells);
|
|
std::vector<std::vector<size_t> > ambient_cells(num_raw_cells);
|
|
std::vector<std::vector<size_t> > ambient_comps(num_components);
|
|
// Only bother if there's more than one component
|
|
if(num_components > 1)
|
|
{
|
|
// construct bounding boxes for each component
|
|
DerivedV bbox_min(num_components, 3);
|
|
DerivedV bbox_max(num_components, 3);
|
|
// Assuming our mesh (in exact numbers) fits in the range of double.
|
|
bbox_min.setConstant(std::numeric_limits<double>::max());
|
|
bbox_max.setConstant(std::numeric_limits<double>::min());
|
|
// Loop over faces
|
|
for (size_t i=0; i<num_faces; i++)
|
|
{
|
|
// component of this face
|
|
const auto comp_id = C[i];
|
|
const auto& f = F.row(i);
|
|
for (size_t j=0; j<3; j++)
|
|
{
|
|
for(size_t d=0;d<3;d++)
|
|
{
|
|
bbox_min(comp_id,d) = std::min(bbox_min(comp_id,d), V(f[j],d));
|
|
bbox_max(comp_id,d) = std::max(bbox_max(comp_id,d), V(f[j],d));
|
|
}
|
|
}
|
|
}
|
|
// Return true if box of component ci intersects that of cj
|
|
const auto bbox_intersects = [&bbox_max,&bbox_min](size_t ci, size_t cj)
|
|
{
|
|
return !(
|
|
bbox_max(ci,0) < bbox_min(cj,0) ||
|
|
bbox_max(ci,1) < bbox_min(cj,1) ||
|
|
bbox_max(ci,2) < bbox_min(cj,2) ||
|
|
bbox_max(cj,0) < bbox_min(ci,0) ||
|
|
bbox_max(cj,1) < bbox_min(ci,1) ||
|
|
bbox_max(cj,2) < bbox_min(ci,2));
|
|
};
|
|
|
|
// Loop over components. This section is O(m²)
|
|
for (size_t i=0; i<num_components; i++)
|
|
{
|
|
// List of components that could overlap with component i
|
|
std::vector<size_t> candidate_comps;
|
|
candidate_comps.reserve(num_components);
|
|
// Loop over components
|
|
for (size_t j=0; j<num_components; j++)
|
|
{
|
|
if (i == j) continue;
|
|
if (bbox_intersects(i,j)) candidate_comps.push_back(j);
|
|
}
|
|
|
|
const size_t num_candidate_comps = candidate_comps.size();
|
|
if (num_candidate_comps == 0) continue;
|
|
|
|
// Build aabb tree for this component.
|
|
submesh_aabb_tree(V,F,Is[i],trees[i],triangle_lists[i],in_Is[i]);
|
|
|
|
// Get query points on each candidate component: barycenter of
|
|
// outer-facet
|
|
DerivedV queries(num_candidate_comps, 3);
|
|
for (size_t j=0; j<num_candidate_comps; j++)
|
|
{
|
|
const size_t index = candidate_comps[j];
|
|
queries.row(j) = get_triangle_center(outer_facets[index]);
|
|
}
|
|
|
|
// Gather closest facets in ith component to each query point and their
|
|
// orientations
|
|
const auto& I = Is[i];
|
|
const auto& tree = trees[i];
|
|
const auto& in_I = in_Is[i];
|
|
const auto& triangles = triangle_lists[i];
|
|
|
|
Eigen::VectorXi closest_facets, closest_facet_orientations;
|
|
closest_facet(
|
|
V,
|
|
F,
|
|
I,
|
|
queries,
|
|
uE2E,
|
|
EMAP,
|
|
VF,
|
|
VFi,
|
|
tree,
|
|
triangles,
|
|
in_I,
|
|
closest_facets,
|
|
closest_facet_orientations);
|
|
// Loop over all candidates
|
|
for (size_t j=0; j<num_candidate_comps; j++)
|
|
{
|
|
const size_t index = candidate_comps[j];
|
|
const size_t closest_patch = P[closest_facets[j]];
|
|
const size_t closest_patch_side = closest_facet_orientations[j] ? 0:1;
|
|
// The cell id of the closest patch
|
|
const size_t ambient_cell =
|
|
raw_cells(closest_patch,closest_patch_side);
|
|
if (ambient_cell != (size_t)outer_cells[i])
|
|
{
|
|
// ---> component index inside component i, because the cell of the
|
|
// closest facet on i to component index is **not** the same as the
|
|
// "outer cell" of component i: component index is **not** outside of
|
|
// component i (therefore it's inside).
|
|
nested_cells[ambient_cell].push_back(outer_cells[index]);
|
|
ambient_cells[outer_cells[index]].push_back(ambient_cell);
|
|
ambient_comps[index].push_back(i);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef EXTRACT_CELLS_DEBUG
|
|
log_time("nested_relationship");
|
|
#endif
|
|
|
|
const size_t INVALID = std::numeric_limits<size_t>::max();
|
|
const size_t INFINITE_CELL = num_raw_cells;
|
|
std::vector<size_t> embedded_cells(num_raw_cells, INVALID);
|
|
for (size_t i=0; i<num_components; i++) {
|
|
const size_t outer_cell = outer_cells[i];
|
|
const auto& ambient_comps_i = ambient_comps[i];
|
|
const auto& ambient_cells_i = ambient_cells[outer_cell];
|
|
const size_t num_ambient_comps = ambient_comps_i.size();
|
|
assert(num_ambient_comps == ambient_cells_i.size());
|
|
if (num_ambient_comps > 0) {
|
|
size_t embedded_comp = INVALID;
|
|
size_t embedded_cell = INVALID;
|
|
for (size_t j=0; j<num_ambient_comps; j++) {
|
|
if (ambient_comps[ambient_comps_i[j]].size() ==
|
|
num_ambient_comps-1) {
|
|
embedded_comp = ambient_comps_i[j];
|
|
embedded_cell = ambient_cells_i[j];
|
|
break;
|
|
}
|
|
}
|
|
assert(embedded_comp != INVALID);
|
|
assert(embedded_cell != INVALID);
|
|
embedded_cells[outer_cell] = embedded_cell;
|
|
} else {
|
|
embedded_cells[outer_cell] = INFINITE_CELL;
|
|
}
|
|
}
|
|
for (size_t i=0; i<num_patches; i++) {
|
|
if (embedded_cells[raw_cells(i,0)] != INVALID) {
|
|
raw_cells(i,0) = embedded_cells[raw_cells(i, 0)];
|
|
}
|
|
if (embedded_cells[raw_cells(i,1)] != INVALID) {
|
|
raw_cells(i,1) = embedded_cells[raw_cells(i, 1)];
|
|
}
|
|
}
|
|
|
|
size_t count = 0;
|
|
std::vector<size_t> mapped_indices(num_raw_cells+1, INVALID);
|
|
// Always map infinite cell to index 0.
|
|
mapped_indices[INFINITE_CELL] = count;
|
|
count++;
|
|
|
|
for (size_t i=0; i<num_patches; i++) {
|
|
const size_t old_positive_cell_id = raw_cells(i, 0);
|
|
const size_t old_negative_cell_id = raw_cells(i, 1);
|
|
size_t positive_cell_id, negative_cell_id;
|
|
if (mapped_indices[old_positive_cell_id] == INVALID) {
|
|
mapped_indices[old_positive_cell_id] = count;
|
|
positive_cell_id = count;
|
|
count++;
|
|
} else {
|
|
positive_cell_id = mapped_indices[old_positive_cell_id];
|
|
}
|
|
if (mapped_indices[old_negative_cell_id] == INVALID) {
|
|
mapped_indices[old_negative_cell_id] = count;
|
|
negative_cell_id = count;
|
|
count++;
|
|
} else {
|
|
negative_cell_id = mapped_indices[old_negative_cell_id];
|
|
}
|
|
raw_cells(i, 0) = positive_cell_id;
|
|
raw_cells(i, 1) = negative_cell_id;
|
|
}
|
|
cells = raw_cells;
|
|
#ifdef EXTRACT_CELLS_DEBUG
|
|
log_time("finalize");
|
|
#endif
|
|
return count;
|
|
}
|
|
|
|
template<
|
|
typename DerivedV,
|
|
typename DerivedF,
|
|
typename DerivedP,
|
|
typename DeriveduE,
|
|
typename uE2EType,
|
|
typename DerivedEMAP,
|
|
typename DerivedC>
|
|
IGL_INLINE size_t igl::copyleft::cgal::extract_cells_single_component(
|
|
const Eigen::PlainObjectBase<DerivedV>& V,
|
|
const Eigen::PlainObjectBase<DerivedF>& F,
|
|
const Eigen::PlainObjectBase<DerivedP>& P,
|
|
const Eigen::PlainObjectBase<DeriveduE>& uE,
|
|
const std::vector<std::vector<uE2EType> >& uE2E,
|
|
const Eigen::PlainObjectBase<DerivedEMAP>& EMAP,
|
|
Eigen::PlainObjectBase<DerivedC>& cells)
|
|
{
|
|
const size_t num_faces = F.rows();
|
|
// Input:
|
|
// index index into #F*3 list of undirect edges
|
|
// Returns index into face
|
|
const auto edge_index_to_face_index = [&num_faces](size_t index)
|
|
{
|
|
return index % num_faces;
|
|
};
|
|
// Determine if a face (containing undirected edge {s,d} is consistently
|
|
// oriented with directed edge {s,d} (or otherwise it is with {d,s})
|
|
//
|
|
// Inputs:
|
|
// fid face index into F
|
|
// s source index of edge
|
|
// d destination index of edge
|
|
// Returns true if face F(fid,:) is consistent with {s,d}
|
|
const auto is_consistent =
|
|
[&F](const size_t fid, const size_t s, const size_t d) -> bool
|
|
{
|
|
if ((size_t)F(fid, 0) == s && (size_t)F(fid, 1) == d) return false;
|
|
if ((size_t)F(fid, 1) == s && (size_t)F(fid, 2) == d) return false;
|
|
if ((size_t)F(fid, 2) == s && (size_t)F(fid, 0) == d) return false;
|
|
|
|
if ((size_t)F(fid, 0) == d && (size_t)F(fid, 1) == s) return true;
|
|
if ((size_t)F(fid, 1) == d && (size_t)F(fid, 2) == s) return true;
|
|
if ((size_t)F(fid, 2) == d && (size_t)F(fid, 0) == s) return true;
|
|
throw "Invalid face!";
|
|
return false;
|
|
};
|
|
|
|
const size_t num_unique_edges = uE.rows();
|
|
const size_t num_patches = P.maxCoeff() + 1;
|
|
|
|
// Build patch-patch adjacency list.
|
|
std::vector<std::map<size_t, size_t> > patch_adj(num_patches);
|
|
for (size_t i=0; i<num_unique_edges; i++) {
|
|
const size_t s = uE(i,0);
|
|
const size_t d = uE(i,1);
|
|
const auto adj_faces = uE2E[i];
|
|
const size_t num_adj_faces = adj_faces.size();
|
|
if (num_adj_faces > 2) {
|
|
for (size_t j=0; j<num_adj_faces; j++) {
|
|
const size_t patch_j = P[edge_index_to_face_index(adj_faces[j])];
|
|
for (size_t k=j+1; k<num_adj_faces; k++) {
|
|
const size_t patch_k = P[edge_index_to_face_index(adj_faces[k])];
|
|
if (patch_adj[patch_j].find(patch_k) == patch_adj[patch_j].end()) {
|
|
patch_adj[patch_j].insert({patch_k, i});
|
|
}
|
|
if (patch_adj[patch_k].find(patch_j) == patch_adj[patch_k].end()) {
|
|
patch_adj[patch_k].insert({patch_j, i});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
const int INVALID = std::numeric_limits<int>::max();
|
|
std::vector<size_t> cell_labels(num_patches * 2);
|
|
for (size_t i=0; i<num_patches; i++) cell_labels[i] = i;
|
|
std::vector<std::set<size_t> > equivalent_cells(num_patches*2);
|
|
std::vector<bool> processed(num_unique_edges, false);
|
|
|
|
size_t label_count=0;
|
|
for (size_t i=0; i<num_patches; i++) {
|
|
for (const auto& entry : patch_adj[i]) {
|
|
const size_t neighbor_patch = entry.first;
|
|
const size_t uei = entry.second;
|
|
if (processed[uei]) continue;
|
|
processed[uei] = true;
|
|
|
|
const auto& adj_faces = uE2E[uei];
|
|
const size_t num_adj_faces = adj_faces.size();
|
|
assert(num_adj_faces > 2);
|
|
|
|
const size_t s = uE(uei,0);
|
|
const size_t d = uE(uei,1);
|
|
|
|
std::vector<int> signed_adj_faces;
|
|
for (auto ej : adj_faces)
|
|
{
|
|
const size_t fid = edge_index_to_face_index(ej);
|
|
bool cons = is_consistent(fid, s, d);
|
|
signed_adj_faces.push_back((fid+1)*(cons ? 1:-1));
|
|
}
|
|
{
|
|
// Sort adjacent faces cyclically around {s,d}
|
|
Eigen::VectorXi order;
|
|
// order[f] will reveal the order of face f in signed_adj_faces
|
|
order_facets_around_edge(V, F, s, d, signed_adj_faces, order);
|
|
for (size_t j=0; j<num_adj_faces; j++) {
|
|
const size_t curr_idx = j;
|
|
const size_t next_idx = (j+1)%num_adj_faces;
|
|
const size_t curr_patch_idx =
|
|
P[edge_index_to_face_index(adj_faces[order[curr_idx]])];
|
|
const size_t next_patch_idx =
|
|
P[edge_index_to_face_index(adj_faces[order[next_idx]])];
|
|
const bool curr_cons = signed_adj_faces[order[curr_idx]] > 0;
|
|
const bool next_cons = signed_adj_faces[order[next_idx]] > 0;
|
|
const size_t curr_cell_idx = curr_patch_idx*2 + (curr_cons?0:1);
|
|
const size_t next_cell_idx = next_patch_idx*2 + (next_cons?1:0);
|
|
equivalent_cells[curr_cell_idx].insert(next_cell_idx);
|
|
equivalent_cells[next_cell_idx].insert(curr_cell_idx);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
size_t count=0;
|
|
cells.resize(num_patches, 2);
|
|
cells.setConstant(INVALID);
|
|
const auto extract_equivalent_cells = [&](size_t i) {
|
|
if (cells(i/2, i%2) != INVALID) return;
|
|
std::queue<size_t> Q;
|
|
Q.push(i);
|
|
cells(i/2, i%2) = count;
|
|
while (!Q.empty()) {
|
|
const size_t index = Q.front();
|
|
Q.pop();
|
|
for (const auto j : equivalent_cells[index]) {
|
|
if (cells(j/2, j%2) == INVALID) {
|
|
cells(j/2, j%2) = count;
|
|
Q.push(j);
|
|
}
|
|
}
|
|
}
|
|
count++;
|
|
};
|
|
for (size_t i=0; i<num_patches; i++) {
|
|
extract_equivalent_cells(i*2);
|
|
extract_equivalent_cells(i*2+1);
|
|
}
|
|
|
|
assert((cells.array() != INVALID).all());
|
|
return count;
|
|
}
|
|
|
|
|
|
#ifdef IGL_STATIC_LIBRARY
|
|
// Explicit template instantiation
|
|
// generated by autoexplicit.sh
|
|
template unsigned long igl::copyleft::cgal::extract_cells<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, -1, 1, -1, -1>, Eigen::Matrix<int, -1, 3, 1, -1, 3>, 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::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, -1, 1, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, std::vector<std::vector<unsigned long, std::allocator<unsigned long> >, std::allocator<std::vector<unsigned long, std::allocator<unsigned long> > > > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
|
|
// generated by autoexplicit.sh
|
|
template unsigned long igl::copyleft::cgal::extract_cells<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, -1, 1, -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::Matrix<int, -1, -1, 0, -1, -1>, unsigned long, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, -1, 1, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, std::vector<std::vector<unsigned long, std::allocator<unsigned long> >, std::allocator<std::vector<unsigned long, std::allocator<unsigned long> > > > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
|
|
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
|
|
template unsigned long igl::copyleft::cgal::extract_cells<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -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::Matrix<int, -1, -1, 0, -1, -1>, unsigned long, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, std::vector<std::vector<unsigned long, std::allocator<unsigned long> >, std::allocator<std::vector<unsigned long, std::allocator<unsigned long> > > > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
|
|
template unsigned long igl::copyleft::cgal::extract_cells<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
|
|
#ifdef WIN32
|
|
template unsigned __int64 igl::copyleft::cgal::extract_cells<class Eigen::Matrix<class CGAL::Lazy_exact_nt<class CGAL::Gmpq>, -1, -1, 0, -1, -1>, class Eigen::Matrix<int, -1, -1, 0, -1, -1>, class Eigen::Matrix<int, -1, 1, 0, -1, 1>, class Eigen::Matrix<int, -1, -1, 0, -1, -1>, class Eigen::Matrix<int, -1, -1, 0, -1, -1>, unsigned __int64, class Eigen::Matrix<int, -1, 1, 0, -1, 1>, class Eigen::Matrix<int, -1, -1, 0, -1, -1>>(class Eigen::PlainObjectBase<class Eigen::Matrix<class CGAL::Lazy_exact_nt<class CGAL::Gmpq>, -1, -1, 0, -1, -1>> const &, class Eigen::PlainObjectBase<class Eigen::Matrix<int, -1, -1, 0, -1, -1>> const &, class Eigen::PlainObjectBase<class Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, class Eigen::PlainObjectBase<class Eigen::Matrix<int, -1, -1, 0, -1, -1>> const &, class Eigen::PlainObjectBase<class Eigen::Matrix<int, -1, -1, 0, -1, -1>> const &, class std::vector<class std::vector<unsigned __int64, class std::allocator<unsigned __int64>>, class std::allocator<class std::vector<unsigned __int64, class std::allocator<unsigned __int64>>>> const &, class Eigen::PlainObjectBase<class Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, class Eigen::PlainObjectBase<class Eigen::Matrix<int, -1, -1, 0, -1, -1>> &);
|
|
template unsigned __int64 igl::copyleft::cgal::extract_cells<class Eigen::Matrix<class CGAL::Lazy_exact_nt<class CGAL::Gmpq>, -1, -1, 1, -1, -1>, class Eigen::Matrix<int, -1, -1, 0, -1, -1>, class Eigen::Matrix<int, -1, 1, 0, -1, 1>, class Eigen::Matrix<int, -1, -1, 0, -1, -1>, class Eigen::Matrix<int, -1, -1, 0, -1, -1>, unsigned __int64, class Eigen::Matrix<int, -1, 1, 0, -1, 1>, class Eigen::Matrix<int, -1, -1, 0, -1, -1>>(class Eigen::PlainObjectBase<class Eigen::Matrix<class CGAL::Lazy_exact_nt<class CGAL::Gmpq>, -1, -1, 1, -1, -1>> const &, class Eigen::PlainObjectBase<class Eigen::Matrix<int, -1, -1, 0, -1, -1>> const &, class Eigen::PlainObjectBase<class Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, class Eigen::PlainObjectBase<class Eigen::Matrix<int, -1, -1, 0, -1, -1>> const &, class Eigen::PlainObjectBase<class Eigen::Matrix<int, -1, -1, 0, -1, -1>> const &, class std::vector<class std::vector<unsigned __int64, class std::allocator<unsigned __int64>>, class std::allocator<class std::vector<unsigned __int64, class std::allocator<unsigned __int64>>>> const &, class Eigen::PlainObjectBase<class Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, class Eigen::PlainObjectBase<class Eigen::Matrix<int, -1, -1, 0, -1, -1>> &);
|
|
template unsigned __int64 igl::copyleft::cgal::extract_cells<class Eigen::Matrix<class CGAL::Lazy_exact_nt<class CGAL::Gmpq>, -1, -1, 1, -1, -1>, class Eigen::Matrix<int, -1, 3, 1, -1, 3>, class Eigen::Matrix<int, -1, 1, 0, -1, 1>, class Eigen::Matrix<int, -1, -1, 0, -1, -1>, class Eigen::Matrix<int, -1, -1, 0, -1, -1>, unsigned __int64, class Eigen::Matrix<int, -1, 1, 0, -1, 1>, class Eigen::Matrix<int, -1, -1, 0, -1, -1>>(class Eigen::PlainObjectBase<class Eigen::Matrix<class CGAL::Lazy_exact_nt<class CGAL::Gmpq>, -1, -1, 1, -1, -1>> const &, class Eigen::PlainObjectBase<class Eigen::Matrix<int, -1, 3, 1, -1, 3>> const &, class Eigen::PlainObjectBase<class Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, class Eigen::PlainObjectBase<class Eigen::Matrix<int, -1, -1, 0, -1, -1>> const &, class Eigen::PlainObjectBase<class Eigen::Matrix<int, -1, -1, 0, -1, -1>> const &, class std::vector<class std::vector<unsigned __int64, class std::allocator<unsigned __int64>>, class std::allocator<class std::vector<unsigned __int64, class std::allocator<unsigned __int64>>>> const &, class Eigen::PlainObjectBase<class Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, class Eigen::PlainObjectBase<class Eigen::Matrix<int, -1, -1, 0, -1, -1>> &);
|
|
#endif
|
|
#endif
|