Merge remote-tracking branch 'cgal/6.1.x-branch' into 'cgal/main'

This commit is contained in:
Sébastien Loriot 2025-09-03 16:57:03 +02:00
commit 72cfcc4156
11 changed files with 353 additions and 58 deletions

View File

@ -63,7 +63,7 @@ struct Parabola_segment_2 : public Parabola_2< Gt >
}
int compute_k(const FT tt, const FT STEP) const {
return int(CGAL::to_double(CGAL::sqrt(tt / STEP)));
return int(CGAL::to_double(CGAL::approximate_sqrt(tt / STEP)));
}
// s0 and s1 define a desired drawing "range"

View File

@ -22,8 +22,8 @@
#include <CGAL/AABB_face_graph_triangle_primitive.h>
#include <CGAL/AABB_halfedge_graph_segment_primitive.h>
#include <CGAL/AABB_tree/internal/AABB_drawing_traits.h>
//#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Simple_cartesian.h>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Side_of_triangle_mesh.h>
#include <CGAL/bounding_box.h>
@ -60,7 +60,7 @@ typedef Edge_container Ec;
typedef Triangle_container Tc;
typedef Viewer_interface Vi;
typedef CGAL::Simple_cartesian<double> Simple_kernel;
typedef CGAL::Exact_predicates_inexact_constructions_kernel Simple_kernel;
typedef Simple_kernel::FT FT;
typedef Simple_kernel::Point_3 Point;
typedef std::pair<Point,FT> Point_distance;
@ -81,24 +81,25 @@ Simple_kernel::Vector_3 random_vector()
return Simple_kernel::Vector_3(x,y,z);
}
template< typename Mesh>
struct PPMAP;
//functor for tbb parallelization
template <typename SM_Tree>
template <typename SM_Tree, bool is_signed>
class FillGridSize {
std::size_t grid_size;
Point_distance (&distance_function)[100][100];
FT diag;
FT& max_distance_function;
std::vector<SM_Tree*>&sm_trees;
bool is_signed;
CGAL::qglviewer::ManipulatedFrame* frame;
public:
FillGridSize(std::size_t grid_size, FT diag, Point_distance (&distance_function)[100][100],
FT& max_distance_function, std::vector<SM_Tree*>& sm_trees,
bool is_signed, CGAL::qglviewer::ManipulatedFrame* frame)
CGAL::qglviewer::ManipulatedFrame* frame)
: grid_size(grid_size), distance_function (distance_function), diag(diag),
max_distance_function(max_distance_function),
sm_trees(sm_trees), is_signed(is_signed), frame(frame)
sm_trees(sm_trees), frame(frame)
{
}
template<typename Range>
@ -137,7 +138,7 @@ public:
max_distance_function = (std::max)(min, max_distance_function);
if(is_signed)
if constexpr (is_signed)
{
if(!min_sm_tree)
{
@ -145,17 +146,12 @@ public:
max_distance_function = DBL_MAX;//(std::max)(min, max_distance_function);
continue;
}
typedef typename SM_Tree::size_type size_type;
Simple_kernel::Vector_3 random_vec = random_vector();
CGAL::Side_of_triangle_mesh<SMesh, Simple_kernel, PPMAP<SMesh>, SM_Tree> side_of(*min_sm_tree);
const Simple_kernel::Point_3& p = distance_function[i][j].first;
const FT unsigned_distance = distance_function[i][j].second;
// get sign through ray casting (random vector)
Simple_kernel::Ray_3 ray(p, random_vec);
size_type nbi = min_sm_tree->number_of_intersected_primitives(ray);
FT sign ( (nbi&1) == 0 ? 1 : -1);
FT sign ( side_of(p)==CGAL::ON_UNBOUNDED_SIDE ? 1 : -1);
distance_function[i][j].second = sign * unsigned_distance;
}
}
@ -191,9 +187,7 @@ public:
GLubyte* getData(){return data; }
};
typedef CGAL::Simple_cartesian<double> Simple_kernel;
//typedef CGAL::Exact_predicates_inexact_constructions_kernel Simple_kernel;
template< typename Mesh>
struct PPMAP
{
@ -390,8 +384,8 @@ private:
mutable Simple_kernel::FT m_max_distance_function;
mutable std::vector<float> tex_map;
mutable Cut_planes_types m_cut_plane;
template <typename SM_Tree>
void compute_distance_function(QMap<QObject*, SM_Tree*> *sm_trees, bool is_signed = false)const
template <bool is_signed = false, typename SM_Tree>
void compute_distance_function(QMap<QObject*, SM_Tree*> *sm_trees)const
{
m_max_distance_function = FT(0);
@ -402,11 +396,11 @@ private:
if(!(is_signed && !CGAL::is_closed(*qobject_cast<Scene_surface_mesh_item*>(sm_trees->key(sm_tree))->polyhedron())))
closed_sm_trees.push_back(sm_tree);
#ifndef CGAL_LINKED_WITH_TBB
FillGridSize<SM_Tree> f(m_grid_size, diag, m_distance_function, m_max_distance_function, closed_sm_trees, is_signed, frame);
FillGridSize<SM_Tree, is_signed> f(m_grid_size, diag, m_distance_function, m_max_distance_function, closed_sm_trees, frame);
HackRange range(0, static_cast<std::size_t>(m_grid_size*m_grid_size));
f(range);
#else
FillGridSize<SM_Tree> f(m_grid_size, diag, m_distance_function, m_max_distance_function, closed_sm_trees, is_signed, frame);
FillGridSize<SM_Tree, is_signed> f(m_grid_size, diag, m_distance_function, m_max_distance_function, closed_sm_trees, frame);
tbb::parallel_for(tbb::blocked_range<size_t>(0, m_grid_size*m_grid_size), f);
#endif
}
@ -459,7 +453,7 @@ private:
break;
case SIGNED_FACETS:
if (!facet_sm_trees || facet_sm_trees->empty() ) { return; }
compute_distance_function( facet_sm_trees, true);
compute_distance_function<true>( facet_sm_trees);
break;
case UNSIGNED_EDGES:

View File

@ -12,5 +12,4 @@ Number_types
Profiling_tools
STL_Extension
Stream_support
TDS_2
Triangulation_2

View File

@ -45,10 +45,227 @@
#include <CGAL/Polygon_mesh_processing/refine_with_plane.h>
#ifndef CGAL_PLANE_CLIP_DO_NOT_USE_TRIANGULATION
#include <CGAL/Triangulation_vertex_base_with_info_2.h>
#include <CGAL/Triangulation_face_base_with_info_2.h>
#include <CGAL/Constrained_Delaunay_triangulation_2.h>
#include <CGAL/Projection_traits_3.h>
#include <CGAL/mark_domain_in_triangulation.h>
#include <CGAL/Delaunay_mesh_face_base_2.h>
#include <boost/iterator/transform_iterator.hpp>
#endif
namespace CGAL {
namespace Polygon_mesh_processing {
namespace internal {
#ifndef CGAL_PLANE_CLIP_DO_NOT_USE_TRIANGULATION
template <class Traits,
class TriangleMesh,
class VertexPointMap,
class Visitor>
void close_and_triangulate(TriangleMesh& tm, VertexPointMap vpm, typename Traits::Vector_3 plane_normal, Visitor& visitor)
{
using vertex_descriptor = typename boost::graph_traits<TriangleMesh>::vertex_descriptor;
using halfedge_descriptor = typename boost::graph_traits<TriangleMesh>::halfedge_descriptor;
using face_descriptor = typename boost::graph_traits<TriangleMesh>::face_descriptor;
using P_traits = Projection_traits_3<Traits>;
using Vb = Triangulation_vertex_base_with_info_2<vertex_descriptor, P_traits>;
using Fb = CGAL::Delaunay_mesh_face_base_2<P_traits>;
using TDS = Triangulation_data_structure_2<Vb, Fb>;
using Itag = No_constraint_intersection_tag;
using CDT = Constrained_Delaunay_triangulation_2<P_traits, TDS, Itag>;
P_traits p_traits(plane_normal);
std::vector<std::pair<typename Traits::Point_3, vertex_descriptor>> points;
std::vector<std::pair<vertex_descriptor, vertex_descriptor>> csts;
halfedge_descriptor href = boost::graph_traits<TriangleMesh>::null_halfedge ();
bool first=true;
for (halfedge_descriptor h : halfedges(tm))
{
if (is_border(h, tm))
{
if (first)
{
href=h;
first=false;
}
vertex_descriptor src = source(h, tm), tgt = target(h, tm);
points.emplace_back(get(vpm, tgt), tgt);
csts.emplace_back(src, tgt);
}
}
if (points.empty()) return;
CDT cdt(p_traits);
cdt.insert(points.begin(), points.end());
// TODO: in case of degenerate edges, we don't triangulate but it's kind of an issue on our side
if (cdt.number_of_vertices()!=points.size()) return;
typedef CGAL::dynamic_vertex_property_t<typename CDT::Vertex_handle> V_tag;
typename boost::property_map<TriangleMesh, V_tag>::type v2v = get(V_tag(), tm);
for (auto vh : cdt.finite_vertex_handles())
put(v2v, vh->info(), vh);
for (auto vv : csts)
cdt.insert_constraint(get(v2v, vv.first), get(v2v, vv.second));
mark_domain_in_triangulation(cdt);
typename CDT::Edge edge_ref;
CGAL_assertion_code(bool OK =)
cdt.is_edge(get(v2v, csts[0].first), get(v2v, csts[0].second), edge_ref.first, edge_ref.second);
CGAL_assertion(OK);
if (!edge_ref.first->is_in_domain()) edge_ref = cdt.mirror_edge(edge_ref);
CGAL_assertion(edge_ref.first->is_in_domain());
bool flip_ori = ( edge_ref.first->vertex( (edge_ref.second+1)%3 )->info() != source(href, tm) );
CGAL_assertion(
( !flip_ori &&
edge_ref.first->vertex( (edge_ref.second+1)%3 )->info() == source(href, tm) &&
edge_ref.first->vertex( (edge_ref.second+2)%3 )->info() == target(href, tm) )
||
( flip_ori &&
edge_ref.first->vertex( (edge_ref.second+2)%3 )->info() == source(href, tm) &&
edge_ref.first->vertex( (edge_ref.second+1)%3 )->info() == target(href, tm) )
);
for (auto fh : cdt.finite_face_handles())
{
if (!fh->is_in_domain()) continue;
std::array<vertex_descriptor,3> vrts = make_array(fh->vertex(0)->info(),
fh->vertex(1)->info(),
fh->vertex(2)->info());
if (flip_ori) std::swap(vrts[0], vrts[1]);
CGAL_assertion(Euler::can_add_face(vrts, tm));
visitor.before_face_copy(boost::graph_traits<TriangleMesh>::null_face(), tm, tm);
face_descriptor f = Euler::add_face(vrts, tm);
visitor.after_face_copy(boost::graph_traits<TriangleMesh>::null_face(), tm, f, tm);
}
}
template <class Traits,
class PolygonMesh,
class VertexPointMap,
class Visitor>
bool close(PolygonMesh& pm, VertexPointMap vpm, typename Traits::Vector_3 plane_normal, Visitor& visitor)
{
//using vertex_descriptor = typename boost::graph_traits<PolygonMesh>::vertex_descriptor;
using halfedge_descriptor = typename boost::graph_traits<PolygonMesh>::halfedge_descriptor;
// using face_descriptor = typename boost::graph_traits<PolygonMesh>::face_descriptor;
using Point_3 = typename Traits::Point_3;
using P_traits = Projection_traits_3<Traits>;
std::vector< std::vector<Point_3> > polygons;
std::vector< halfedge_descriptor > border_cycles;
std::vector< Bbox_3 > bboxes;
typedef CGAL::dynamic_halfedge_property_t<bool> H_tag;
typename boost::property_map<PolygonMesh, H_tag>::type
is_hedge_selected = get(H_tag(), pm, false);
for (halfedge_descriptor h : halfedges(pm))
{
if (is_border(h, pm) && get(is_hedge_selected, h)==false)
{
border_cycles.push_back(h);
polygons.emplace_back();
bboxes.emplace_back();
for (halfedge_descriptor he : CGAL::halfedges_around_face(h, pm))
{
put(is_hedge_selected, he, true);
polygons.back().push_back(get(vpm, target(he, pm)));
bboxes.back()+=polygons.back().back().bbox();
}
}
}
if (bboxes.empty()) return true;
Bbox_3 gbox;
for (const Bbox_3& bb : bboxes)
gbox+=bb;
// arrange polygons
int axis = 0;
if ((gbox.ymax()-gbox.ymin()) > (gbox.xmax()-gbox.xmin())) axis=1;
if ((gbox.zmax()-gbox.zmin()) > ((gbox.max)(axis)-(gbox.min)(axis))) axis=2;
std::vector<std::size_t> poly_ids(polygons.size());
std::iota(poly_ids.begin(), poly_ids.end(), 0);
std::sort(poly_ids.begin(), poly_ids.end(),
[&bboxes, axis](std::size_t i, std::size_t j)
{
return (bboxes[i].min)(axis) < (bboxes[j].min)(axis);
});
std::vector<std::size_t> simply_connected_faces;
std::vector<bool> handled(poly_ids.size(), false);
P_traits ptraits(plane_normal);
for (std::size_t pid=0; pid<poly_ids.size()-1; ++pid)
{
std::size_t curr_poly_id = poly_ids[pid];
if (handled[curr_poly_id]) continue;
std::vector<std::size_t> nested;
for (std::size_t npid=pid+1; npid<poly_ids.size(); ++npid)
{
std::size_t next_poly_id = poly_ids[npid];
if (do_overlap(bboxes[curr_poly_id], bboxes[next_poly_id]))
{
//TODO: what about tanjencies?
//TODO: check orientation for predicate
if (bounded_side_2(polygons[curr_poly_id].begin(), polygons[curr_poly_id].end(),
polygons[next_poly_id].front(), ptraits) == ON_BOUNDED_SIDE)
{
nested.push_back(next_poly_id);
handled[next_poly_id]=true;
}
}
else
break; // no further overlaps
}
handled[curr_poly_id] = true;
if (nested.empty())
simply_connected_faces.push_back(curr_poly_id);
}
if (!handled[poly_ids.back()])
simply_connected_faces.push_back(poly_ids.back());
for (std::size_t id : simply_connected_faces)
{
halfedge_descriptor h = border_cycles[id];
visitor.before_face_copy(boost::graph_traits<PolygonMesh>::null_face(), pm, pm);
Euler::fill_hole(h, pm);
visitor.after_face_copy(boost::graph_traits<PolygonMesh>::null_face(), pm, face(h, pm), pm);
}
return simply_connected_faces.size()==poly_ids.size();
}
#endif
template <class Plane_3,
class TriangleMesh,
class NamedParameters>
@ -791,7 +1008,7 @@ bool clip(PolygonMesh& pm,
Default_visitor default_visitor;
using Visitor_ref = typename internal_np::Lookup_named_param_def<internal_np::visitor_t, NamedParameters, Default_visitor>::reference;
Visitor_ref visitor = choose_parameter(get_parameter_reference(np, internal_np::visitor), default_visitor);
constexpr bool has_visitor = !std::is_same_v<Default_visitor, std::remove_cv_t<std::remove_reference_t<Visitor_ref>>>;
// constexpr bool has_visitor = !std::is_same_v<Default_visitor, std::remove_cv_t<std::remove_reference_t<Visitor_ref>>>;
typedef typename internal_np::Lookup_named_param_def <
internal_np::concurrency_tag_t,
@ -834,6 +1051,8 @@ bool clip(PolygonMesh& pm,
if (clip_volume && !is_closed(pm)) clip_volume=false;
if (clip_volume && !use_compact_clipper) use_compact_clipper=true;
CGAL_precondition(!clip_volume || !triangulate || does_bound_a_volume(pm));
auto fcc = get(dynamic_face_property_t<std::size_t>(), pm);
std::size_t nbcc = connected_components(pm, fcc, CGAL::parameters::edge_is_constrained_map(ecm));
@ -865,35 +1084,12 @@ bool clip(PolygonMesh& pm,
if (clip_volume)
{
std::vector<halfedge_descriptor> borders;
extract_boundary_cycles(pm, std::back_inserter(borders));
for (halfedge_descriptor h : borders)
{
#ifndef CGAL_PLANE_CLIP_DO_NOT_USE_TRIANGULATION
//TODO: add in the traits construct_orthogonal_vector
if (triangulate)
{
Euler::fill_hole(h, pm); // visitor call done in the triangulation visitor
if constexpr (!has_visitor)
{
triangulate_face(face(h,pm), pm, parameters::vertex_point_map(vpm).geom_traits(traits));
}
internal::close_and_triangulate<GT>(pm, vpm, plane.orthogonal_vector(), visitor);
else
{
using Base_visitor = std::remove_cv_t<std::remove_reference_t<Visitor_ref>>;
internal::Visitor_wrapper_for_triangulate_face<PolygonMesh, Base_visitor> visitor_wrapper(pm, visitor);
triangulate_face(face(h,pm), pm, parameters::vertex_point_map(vpm).geom_traits(traits).visitor(visitor_wrapper));
}
}
else
#endif
{
visitor.before_face_copy(boost::graph_traits<PolygonMesh>::null_face(), pm, pm);
Euler::fill_hole(h, pm);
visitor.after_face_copy(boost::graph_traits<PolygonMesh>::null_face(), pm, face(h, pm), pm);
}
}
if (!internal::close<GT>(pm, vpm, plane.orthogonal_vector(), visitor))
internal::close_and_triangulate<GT>(pm, vpm, plane.orthogonal_vector(), visitor);
}
return true;

View File

@ -1689,8 +1689,9 @@ bounded_error_squared_Hausdorff_distance_impl(const TriangleMesh1& tm1,
// Thus, subdivision can only decrease the min, and the upper bound.
Local_bounds<Kernel, Face_handle_1, Face_handle_2> bounds(triangle_bounds.upper);
// Ensure 'uface' is initialized in case the upper bound is not changed by the subdivision
// Ensure 'lface' and 'uface' are initialized in case the bounds are not changed by the subdivision
bounds.tm2_uface = triangle_bounds.tm2_uface;
bounds.tm2_lface = triangle_bounds.tm2_lface;
TM2_hd_traits traversal_traits_tm2(sub_t1_bbox, tm2, vpm2, bounds, global_bounds, infinity_value);
tm2_tree.traversal_with_priority(sub_triangles[i], traversal_traits_tm2);

View File

@ -73,6 +73,7 @@ create_single_source_cgal_program("test_isolevel_refinement.cpp")
create_single_source_cgal_program("test_corefinement_nm_bo.cpp")
create_single_source_cgal_program("test_corefinement_cavities.cpp")
create_single_source_cgal_program("issue_8730.cpp")
create_single_source_cgal_program("issue_7164.cpp")
# create_single_source_cgal_program("test_pmp_repair_self_intersections.cpp")
find_package(Eigen3 3.2.0 QUIET) #(requires 3.2.0 or greater)

View File

@ -0,0 +1,61 @@
#include <CGAL/Surface_mesh.h>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Polygon_mesh_processing/polygon_soup_to_polygon_mesh.h>
#include <CGAL/Polygon_mesh_processing/distance.h>
#include <CGAL/Random.h>
using Kernel = CGAL::Exact_predicates_inexact_constructions_kernel;
using Point_3 = Kernel::Point_3;
using Mesh = CGAL::Surface_mesh<Point_3>;
namespace PMP = CGAL::Polygon_mesh_processing;
int main(/*int argc, char** argv*/)
{
// A simple triangle
std::vector<Point_3> pts_A;
std::vector<std::vector<size_t>> trs_A;
pts_A.emplace_back( 0.26641936088212415, 0.2664193608821242, 0.73358063911787585);
pts_A.emplace_back(-0.14011519816541251, 0.6017979969632727, 1.1810107045967466);
pts_A.emplace_back(-0.14011519816541279,-0.1810107045967464, 0.39820200303672726);
trs_A.emplace_back(std::vector<size_t>{0,1,2});
Mesh A;
PMP::polygon_soup_to_polygon_mesh(pts_A, trs_A, A);
// An open tetrahedron
std::vector<Point_3> pts_B;
std::vector<std::vector<size_t>> trs_B;
pts_B.emplace_back(0,0,0);
pts_B.emplace_back(1,1,0);
pts_B.emplace_back(1,0,1);
pts_B.emplace_back(0,1,1);
trs_B.emplace_back(std::vector<size_t>{0,1,2});
trs_B.emplace_back(std::vector<size_t>{3,1,0});
trs_B.emplace_back(std::vector<size_t>{3,2,1});
Mesh B;
PMP::polygon_soup_to_polygon_mesh(pts_B, trs_B, B);
double bound = 0.01 * 0.42149467833714593;
PMP::bounded_error_Hausdorff_distance<CGAL::Sequential_tag>(A, B, bound);
PMP::bounded_error_Hausdorff_distance<CGAL::Sequential_tag>(B, A, bound);
// The bug was possible with closed models
std::vector<Point_3> pts_C;
std::vector<std::vector<size_t>> trs_C;
pts_C.emplace_back(0,0,0);
pts_C.emplace_back(1,1,0);
pts_C.emplace_back(1,0,1);
pts_C.emplace_back(0,1,1);
pts_C.emplace_back(0.75,0.75,0);
trs_C.emplace_back(std::vector<size_t>{0,1,2});
trs_C.emplace_back(std::vector<size_t>{3,1,0});
trs_C.emplace_back(std::vector<size_t>{3,2,1});
trs_C.emplace_back(std::vector<size_t>{0,2,4});
trs_C.emplace_back(std::vector<size_t>{3,0,4});
trs_C.emplace_back(std::vector<size_t>{3,4,2});
Mesh C;
PMP::polygon_soup_to_polygon_mesh(pts_C, trs_C, C);
PMP::bounded_error_Hausdorff_distance<CGAL::Sequential_tag>(A, C, bound);
PMP::bounded_error_Hausdorff_distance<CGAL::Sequential_tag>(C, A, bound);
return EXIT_SUCCESS;
}

View File

@ -555,6 +555,49 @@ void test()
PMP::clip(tm1, K::Plane_3(0,0,-1,1), CGAL::parameters::use_compact_clipper(true).allow_self_intersections(true));
assert(vertices(tm1).size()==176);
}
// non-simply connected output faces
{
TriangleMesh tm1;
CGAL::make_hexahedron(CGAL::Bbox_3(-3.5,-0.5,-0.5, -2.5,0.5,0.5), tm1);
PMP::reverse_face_orientations(tm1);
CGAL::make_hexahedron(CGAL::Bbox_3(-4,-1,-1, -2,1,1), tm1);
CGAL::make_hexahedron(CGAL::Bbox_3(-1,-1,-1, 1,1,1), tm1);
CGAL::make_hexahedron(CGAL::Bbox_3(2,-1,-1, 4,1,1), tm1);
CGAL::make_hexahedron(CGAL::Bbox_3(5,-1,-1, 7,1,1), tm1);
CGAL::make_hexahedron(CGAL::Bbox_3(-1,2,-1, 1,4,1), tm1);
CGAL::make_hexahedron(CGAL::Bbox_3(2,2,-1, 4,4,1), tm1);
CGAL::make_hexahedron(CGAL::Bbox_3(5,2,-1, 7,4,1), tm1);
CGAL::make_hexahedron(CGAL::Bbox_3(-1,5,-1, 1,7,1), tm1);
CGAL::make_hexahedron(CGAL::Bbox_3(2,5,-1, 4,7,1), tm1);
CGAL::make_hexahedron(CGAL::Bbox_3(5,5,-1, 7,7,1), tm1);
PMP::clip(tm1, K::Plane_3(0,0,1,0), CGAL::parameters::do_not_triangulate_faces(true).clip_volume(true));
assert(vertices(tm1).size()==88);
assert(faces(tm1).size()==72);
}
{
TriangleMesh tm1;
CGAL::make_hexahedron(CGAL::Bbox_3(-1,-1,-1, 1,1,1), tm1);
CGAL::make_hexahedron(CGAL::Bbox_3(-3,-3,-3, 3,3,3), tm1);
CGAL::make_hexahedron(CGAL::Bbox_3(-5,-5,-5, 5,5,5), tm1);
CGAL::make_hexahedron(CGAL::Bbox_3(-7,-7,-7, 7,7,7), tm1);
PMP::reverse_face_orientations(tm1);
CGAL::make_hexahedron(CGAL::Bbox_3(-0.5,-0.5,-0.5, 0.5,0.5,0.5), tm1);
CGAL::make_hexahedron(CGAL::Bbox_3(-2,-2,-2, 2,2,2), tm1);
CGAL::make_hexahedron(CGAL::Bbox_3(-4,-4,-4, 4,4,4), tm1);
CGAL::make_hexahedron(CGAL::Bbox_3(-6,-6,-6, 6,6,6), tm1);
CGAL::make_hexahedron(CGAL::Bbox_3(-8,-8,-8, 8,8,8), tm1);
PMP::clip(tm1, K::Plane_3(0,0,1,0), CGAL::parameters::do_not_triangulate_faces(true).clip_volume(true));
assert(vertices(tm1).size()==72);
assert(faces(tm1).size()==79);
}
}
template <class Mesh>

View File

@ -14,7 +14,7 @@
#ifndef CGAL_CONSTRAINED_DELAUNAY_TRIANGULATION_FACE_BASE_2_H
#define CGAL_CONSTRAINED_DELAUNAY_TRIANGULATION_FACE_BASE_2_H
#include <CGAL/license/Mesh_2.h>
#include <CGAL/license/Triangulation_2.h>
#include <CGAL/assertions.h>

View File

@ -13,7 +13,7 @@
#ifndef CGAL_DELAUNAY_FACE_BASE_2_H
#define CGAL_DELAUNAY_FACE_BASE_2_H
#include <CGAL/license/Mesh_2.h>
#include <CGAL/license/Triangulation_2.h>
#include <CGAL/Constrained_Delaunay_triangulation_face_base_2.h>

View File

@ -13,7 +13,7 @@
#ifndef CGAL_DELAUNAY_VERTEX_BASE_2_H
#define CGAL_DELAUNAY_VERTEX_BASE_2_H
#include <CGAL/license/Mesh_2.h>
#include <CGAL/license/Triangulation_2.h>
#include <CGAL/Triangulation_vertex_base_2.h>