mirror of https://github.com/CGAL/cgal
Merge remote-tracking branch 'cgal/6.1.x-branch' into 'cgal/main'
This commit is contained in:
commit
72cfcc4156
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -12,5 +12,4 @@ Number_types
|
|||
Profiling_tools
|
||||
STL_Extension
|
||||
Stream_support
|
||||
TDS_2
|
||||
Triangulation_2
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
Loading…
Reference in New Issue