Merge remote-tracking branch 'cgal/6.0.x-branch' in master

This commit is contained in:
Sébastien Loriot 2025-03-31 15:32:56 +02:00
commit 5ed3b0d266
15 changed files with 217 additions and 58 deletions

View File

@ -162,7 +162,7 @@ namespace CGAL {
/// test if adart->beta(ai)->beta(aj) exists and is not marked for amark
bool is_unmarked2(Dart_descriptor adart, unsigned int ai, unsigned int aj,
typename Map::size_type amark) const
size_type amark) const
{ return
!mmap->is_marked(mmap->beta(adart, ai, aj), amark);
}
@ -207,6 +207,8 @@ namespace CGAL {
/// true iff this iterator is basic
typedef Tag_true Basic_iterator;
typedef typename Map::size_type size_type;
public:
/// Main constructor.
CMap_dart_iterator(Map& amap, Dart_descriptor adart):
@ -261,7 +263,7 @@ namespace CGAL {
protected:
/// test if adart->beta(ai) exists and is not marked for amark
bool is_unmarked(Dart_descriptor adart, unsigned int ai, unsigned amark) const
bool is_unmarked(Dart_descriptor adart, unsigned int ai, size_type amark) const
{ return !mmap->is_marked(mmap->beta(adart,ai), amark); }
/// test if adart->beta(ai)->beta(aj) exists
@ -270,7 +272,7 @@ namespace CGAL {
/// test if adart->beta(ai)->beta(aj) exists and is not marked for amark
bool is_unmarked2(Dart_descriptor adart, unsigned int ai, unsigned int aj,
unsigned amark) const
size_type amark) const
{ return !mmap->is_marked(mmap->beta(adart, ai, aj), amark); }
protected:

View File

@ -313,7 +313,7 @@ The \scip web site is <A HREF="https://www.scipopt.org/">`https://www.scipopt.or
\osqp (Operator Splitting Quadratic Program) is currently one of the fastest open source solvers for convex Quadratic Programs (QP).
In \cgal, \osqp provides an optional solver for the quadratic programming used in the \ref PkgShapeRegularization package.
In order to use \osqp in \cgal programs, the executables should be linked with the CMake imported target `CGAL::OSQP_support` provided in `CGAL_OSQP_support.cmake`.
In order to use \osqp in \cgal programs, the executables should be linked with the CMake imported target `CGAL::OSQP_support` provided in `CGAL_OSQP_support.cmake`. \cgal is compatible with \osqp version 1.0.0.
The \osqp web site is <A HREF="https://osqp.org">`https://osqp.org`</A>.

View File

@ -40,7 +40,7 @@ namespace CGAL {
namespace KSP_3 {
namespace internal {
const std::tuple<unsigned char, unsigned char, unsigned char>
inline const std::tuple<unsigned char, unsigned char, unsigned char>
get_idx_color(std::size_t idx) {
CGAL::Random rand(static_cast<unsigned int>(idx));
@ -50,7 +50,7 @@ get_idx_color(std::size_t idx) {
static_cast<unsigned char>(rand.get_int(32, 192)));
}
CGAL::IO::Color get_color(std::size_t idx) {
inline CGAL::IO::Color get_color(std::size_t idx) {
CGAL::Random rand(static_cast<unsigned int>(idx));
return CGAL::IO::Color(rand.get_int(32, 192), rand.get_int(32, 192), rand.get_int(32, 192));
}
@ -929,7 +929,7 @@ void dump_polygon(const std::vector<typename K::Point_3>& pts, const std::string
saver.export_polygon_soup_3(pts2, filename);
}
void dump_polygona(const std::vector<CGAL::Epick::Point_3>& pts, const std::string& filename) {
inline void dump_polygona(const std::vector<CGAL::Epick::Point_3>& pts, const std::string& filename) {
Saver<CGAL::Epick> saver;
std::vector<std::vector<CGAL::Epick::Point_3> > pts2;
pts2.push_back(pts);
@ -937,30 +937,31 @@ void dump_polygona(const std::vector<CGAL::Epick::Point_3>& pts, const std::stri
saver.export_polygon_soup_3(pts2, filename);
}
void dump_polygons(const std::vector<std::vector<CGAL::Epick::Point_3> >& pts, const std::string& filename) {
Saver<CGAL::Epick> saver;
saver.export_polygon_soup_3(pts, filename);
}
void dump_polygons(const std::vector<std::vector<std::vector<CGAL::Epick::Point_3> > >& pts, const std::string& filename) {
inline void dump_polygons(const std::vector<std::vector<CGAL::Epick::Point_3> >& pts, const std::string& filename) {
Saver<CGAL::Epick> saver;
saver.export_polygon_soup_3(pts, filename);
}
void dump_indexed_triangles(const std::vector<CGAL::Epick::Point_3>& pts, const std::vector<std::size_t>& tris, const std::string& filename) {
inline void dump_polygons(const std::vector<std::vector<std::vector<CGAL::Epick::Point_3> > >& pts, const std::string& filename) {
Saver<CGAL::Epick> saver;
saver.export_polygon_soup_3(pts, filename);
}
inline void dump_indexed_triangles(const std::vector<CGAL::Epick::Point_3>& pts, const std::vector<std::size_t>& tris, const std::string& filename) {
Saver<CGAL::Epick> saver;
saver.export_indexed_triangles_3(pts, tris, filename);
}
void dump_indexed_polygons(const std::vector<CGAL::Epick::Point_3>& pts, const std::vector<std::vector<std::size_t> >& polys, const std::string& filename) {
inline void dump_indexed_polygons(const std::vector<CGAL::Epick::Point_3>& pts, const std::vector<std::vector<std::size_t> >& polys, const std::string& filename) {
Saver<CGAL::Epick> saver;
saver.export_indexed_polygons_3(pts, polys, filename);
}
void dump_polygons(const std::vector<std::vector<CGAL::Epick::Point_3> >& pts, const std::vector<CGAL::IO::Color>& colors, const std::string& filename) {
inline void dump_polygons(const std::vector<std::vector<CGAL::Epick::Point_3> >& pts, const std::vector<CGAL::IO::Color>& colors, const std::string& filename) {
Saver<CGAL::Epick> saver;
saver.export_polygon_soup_3(pts, colors, filename);
@ -1005,7 +1006,7 @@ void dump_polygons(
saver.export_polygon_soup_3(polygons, name);
}
void dump_points(const std::vector<CGAL::Epick::Point_3>& pts, const std::vector<CGAL::Epick::Vector_3>& normals, const std::vector<CGAL::IO::Color>& colors, const std::string& filename) {
inline void dump_points(const std::vector<CGAL::Epick::Point_3>& pts, const std::vector<CGAL::Epick::Vector_3>& normals, const std::vector<CGAL::IO::Color>& colors, const std::string& filename) {
Saver<CGAL::Epick> saver;
saver.export_points_3(pts, normals, colors, filename);
}

View File

@ -334,8 +334,17 @@ void detect_vertex_incident_patches(const PolygonMesh& pmesh,
for(vertex_descriptor vit :vertices(pmesh))
{
// Look only at feature vertices
if(!get(edge_is_feature_map, edge(halfedge(vit, pmesh), pmesh)))
continue;
bool skip=true;
for(halfedge_descriptor he : halfedges_around_target(vit, pmesh))
{
if(get(edge_is_feature_map, edge(he, pmesh)))
{
skip=false;
break;
}
}
if (skip) continue;
// Loop on incident facets of vit
typename VertexIncidentPatchesMap::value_type& id_set = vertex_incident_patches_map[vit];

View File

@ -712,8 +712,6 @@ private:
bool
point_out_prism_return_local_id(const Point_3 &point, const ePoint_3 &epoint, const std::vector<unsigned int> &prismindex, const unsigned int jump, int &id) const
{
Vector_3 bmin, bmax;
Orientation ori = ON_ORIENTED_BOUNDARY; // to avoid maybe uninitialized warning
for (unsigned int i = 0; i < prismindex.size(); i++){

View File

@ -69,6 +69,7 @@ create_single_source_cgal_program("test_degenerate_pmp_clip_split_corefine.cpp")
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("test_pmp_repair_self_intersections.cpp")
find_package(Eigen3 3.2.0 QUIET) #(requires 3.2.0 or greater)

View File

@ -0,0 +1,145 @@
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Surface_mesh.h>
#include <CGAL/Polygon_mesh_processing/detect_features.h>
using Kernel = CGAL::Exact_predicates_inexact_constructions_kernel;
using Point_3 = Kernel::Point_3;
using Surface_mesh = CGAL::Surface_mesh<Point_3>;
using vertex_index = Surface_mesh::vertex_index;
using halfedge_index = Surface_mesh::halfedge_index;
using face_index = Surface_mesh::face_index;
using edge_index = Surface_mesh::edge_index;
std::vector<Point_3> points = {
{0,0,0},
{0,0.5,0},
{0,1,0},
{0.5,0,0},
{0.5,0.5,0},
{0.5,1,0},
{1,0,0},
{1,0.5,0},
{1,1,0},
{0,0,0.5},
{0,0.5,0.5},
{0,1,0.5},
{0.5,0,0.5},
{0.5,1,0.5},
{1,0,0.5},
{1,0.5,0.5},
{1,1,0.5},
{0,0,1},
{0,0.5,1},
{0,1,1},
{0.5,0,1},
{0.5,0.5,1},
{0.5,1,1},
{1,0,1},
{1,0.5,1},
{1,1,1}
};
std::vector<std::array<int, 3>> faces = {
{7,4,5},
{7,6,4},
{7,5,8},
{4,2,5},
{2,4,1},
{11,5,2},
{11,13,5},
{11,2,10},
{2,1,10},
{11,10,18},
{11,18,19},
{10,17,18},
{10,9,17},
{20,18,17},
{20,21,18},
{12,20,17},
{12,14,20},
{12,17,9},
{3,12,9},
{3,6,12},
{3,9,0},
{3,0,1},
{9,1,0},
{1,9,10},
{3,1,4},
{6,3,4},
{12,6,14},
{6,7,14},
{15,14,7},
{14,15,23},
{15,7,8},
{15,8,16},
{24,15,16},
{16,8,13},
{22,16,13},
{13,8,5},
{22,25,16},
{22,13,19},
{13,11,19},
{22,19,21},
{21,24,22},
{19,18,21},
{21,23,24},
{22,24,25},
{24,16,25},
{23,21,20},
{24,23,15},
{14,23,20}
};
int main()
{
Surface_mesh mesh;
std::vector<vertex_index> vertices(points.size());
for (size_t i = 0; i < points.size(); ++i)
{
vertices[i] = mesh.add_vertex(points[i]);
}
for (size_t i = 0; i < faces.size(); ++i)
{
vertex_index v0 = vertices[faces[i][0]];
vertex_index v1 = vertices[faces[i][1]];
vertex_index v2 = vertices[faces[i][2]];
mesh.add_face(v0, v1, v2);
}
auto vertexToPatches = mesh.add_property_map<vertex_index, std::set<size_t>>("v:patches").first;
auto faceToPatch = mesh.add_property_map<face_index, size_t>("f:patch", (std::numeric_limits<size_t>::max)()).first;
auto edgeToIsFeature = mesh.add_property_map<edge_index, bool>("e:is_feature", false).first;
double angle_in_deg = 90;
CGAL::Polygon_mesh_processing::detect_sharp_edges(mesh, angle_in_deg, edgeToIsFeature);
auto number_of_patches = CGAL::Polygon_mesh_processing::
connected_components(mesh, faceToPatch,
CGAL::parameters::edge_is_constrained_map(edgeToIsFeature));
assert(number_of_patches==6);
CGAL::Polygon_mesh_processing::detect_vertex_incident_patches(mesh,
faceToPatch, vertexToPatches, edgeToIsFeature);
std::array<int,4> degrees = CGAL::make_array(0,0,0,0);
for (auto v : mesh.vertices())
{
auto d = vertexToPatches[v].size();
assert(d<4);
degrees[d]+=1;
}
assert(degrees[0]==6);
assert(degrees[1]==0);
assert(degrees[2]==12);
assert(degrees[3]==8);
return 0;
}

View File

@ -216,15 +216,12 @@ public:
set_qlu_data(q_x.get(), l_x.get(), u_x.get());
// Problem settings.
OSQPSettings *settings = (OSQPSettings *) malloc(sizeof(OSQPSettings));
OSQPSettings *settings = OSQPSettings_new();
CGAL_assertion(settings);
// Structures.
OSQPCscMatrix* P = static_cast<OSQPCscMatrix*>(malloc(sizeof(OSQPCscMatrix)));
OSQPCscMatrix* A = static_cast<OSQPCscMatrix*>(malloc(sizeof(OSQPCscMatrix)));
csc_set_data(A, m, n, A_nnz, A_x.get(), A_i.get(), A_p.get());
csc_set_data(P, n, n, P_nnz, P_x.get(), P_i.get(), P_p.get());
OSQPCscMatrix* A = OSQPCscMatrix_new(m, n, A_nnz, A_x.get(), A_i.get(), A_p.get());
OSQPCscMatrix* P = OSQPCscMatrix_new(n, n, P_nnz, P_x.get(), P_i.get(), P_p.get());
// Set solver settings.
osqp_set_default_settings(settings);
@ -254,9 +251,9 @@ public:
}
osqp_cleanup(solver);
if (A) free(A);
if (P) free(P);
if (settings) free(settings);
if (A) OSQPCscMatrix_free(A);
if (P) OSQPCscMatrix_free(P);
if (settings) OSQPSettings_free(settings);
return (exitflag == 0);
}

View File

@ -5,18 +5,21 @@ namespace CGAL {
*
* \brief constructs the straight skeleton-based extrusion of a polygon with holes.
*
* Given a polygon with holes and a set of weights, the skeleton extrusion is a volume constructed
* from the weighted straight skeleton by associating a height to the vertices of the skeleton,
* which corresponds to the time at the vertex. The input polygon is placed at `z = 0`.
*
* This function allows cropping the extruded skeleton at a maximum height, using the optional
* `maximum_height()` named parameter.
* Given a polygon with holes and a set of weights (or angles) associated to its edges,
* the skeleton extrusion is a volume constructed from the weighted straight skeleton
* by associating a height to the vertices of the skeleton, which corresponds to the time
* at the vertex. The input polygon is placed at `z = 0`.
*
* The result is a closed, 2-manifold surface triangle mesh. Note that this mesh can have non-local
* self-intersections if a maximal height is provided due to possible (geometric) non-manifold occurrences.
*
* @tparam PolygonWithHoles must be a model of `SequenceContainer` with value type `InK::Point_2` (e.g. `Polygon_2<InK>`)
or a model of `GeneralPolygonWithHoles_2` (e.g. `Polygon_with_holes_2<InK>`).
* It is possible to crop the extruded skeleton at a maximum height using the optional
* `maximum_height()` named parameter. A maximum height must be specified if the weights (or angles)
* associated to the edges of the input polygon correspond an outward extrusion, i.e. if no weight
* is greater than zero (or no angle is smaller than `90` degrees).
*
* @tparam Polygon must be a model of `SequenceContainer` with value type `InK::Point_2` (e.g. `Polygon_2<InK>`)
or a model of `GeneralPolygonWithHoles_2` (e.g. `Polygon_with_holes_2<InK>`).
* @tparam PolygonMesh a model of `MutableFaceGraph`
* @tparam NamedParameters a sequence of \ref bgl_namedparameters "Named Parameters"
*
@ -42,7 +45,7 @@ namespace CGAL {
* \cgalParamType{a model of `Range` whose value type is a model of `Range` whose value type is `FT`}
* \cgalParamDefault{an empty range (uniform weights are used)}
* \cgalParamExtra{Angles are measured in degrees and should be strictly within `0` and `180` degrees
* and should be eitger all acute (inward extrusion) or all obtuse (outward extrusion).}
* and should be either all acute (inward extrusion) or all obtuse (outward extrusion).}
* \cgalParamExtra{This parameter is ignored if the `weights` parameter is provided.}
* \cgalParamExtra{The conversion to weights involves trigonometry and will be inexact,
* even when using a number type with exact square roots.}

View File

@ -125,7 +125,7 @@ create_partial_exterior_weighted_straight_skeleton_2(const FT& aMaxOffset,
typedef typename Kernel_traits<Point_2>::Kernel IK;
typedef typename IK::FT IFT;
static_assert((std::is_same<typename std::iterator_traits<WeightIterator>::value_type, IFT>::value));
static_assert((std::is_same<typename std::iterator_traits<WeightIterator>::value_type, IFT>::value), "Vertices and weights should have the same FT");
std::shared_ptr<Straight_skeleton_2<K> > rSkeleton;

View File

@ -147,7 +147,7 @@ create_exterior_weighted_straight_skeleton_2(const FT& max_offset,
using IK = typename Kernel_traits<Point_2>::Kernel;
using IFT = typename IK::FT;
static_assert((std::is_same<typename std::iterator_traits<WeightIterator>::value_type, IFT>::value));
static_assert((std::is_same<typename std::iterator_traits<WeightIterator>::value_type, IFT>::value), "Vertices and weights should have the same FT");
std::shared_ptr<Straight_skeleton_2<K> > skeleton;

View File

@ -41,16 +41,18 @@ typedef CGAL::Timer Timer;
namespace CGAL {
template<typename K>
class Test_polygon_2 : public CGAL::Polygon_2<K> {
struct Test_polygon_2 : public CGAL::Polygon_2<K> {
typedef CGAL::Polygon_2<K> Base;
Test_polygon_2() { }
Test_polygon_2(const Base&);
public:
using Base::Base;
};
template<typename K>
class Test_polygon_with_holes_2 : public CGAL::Polygon_with_holes_2<K> {
struct Test_polygon_with_holes_2 : public CGAL::Polygon_with_holes_2<K> {
typedef CGAL::Polygon_with_holes_2<K> Base;
Test_polygon_with_holes_2() { }
Test_polygon_with_holes_2(const Base&);
public:
using Base::Base;

View File

@ -28,16 +28,18 @@ typedef CGAL::Exact_predicates_exact_constructions_kernel_with_sqrt EPECK_w_sqr
namespace CGAL {
template<typename K>
class Test_polygon_2 : public CGAL::Polygon_2<K> {
struct Test_polygon_2 : public CGAL::Polygon_2<K> {
typedef CGAL::Polygon_2<K> Base;
Test_polygon_2() { }
Test_polygon_2(const Base&);
public:
using Base::Base;
};
template<typename K>
class Test_polygon_with_holes_2 : public CGAL::Polygon_with_holes_2<K> {
struct Test_polygon_with_holes_2 : public CGAL::Polygon_with_holes_2<K> {
typedef CGAL::Polygon_with_holes_2<K> Base;
Test_polygon_with_holes_2() { }
Test_polygon_with_holes_2(const Base&);
public:
using Base::Base;

View File

@ -86,8 +86,8 @@ inline constexpr FT default_extrusion_height()
}
// @todo Maybe this postprocessing is not really necessary? Do users really care if the point
// is not perfectly above the input contour edge (it generally cannot be anyway if the kernel is not exact except for some
// specific cases)?
// is not perfectly above the input contour edge (it generally cannot be anyway if the kernel
// is not exact except for some specific cases)?
#define CGAL_SLS_SNAP_TO_VERTICAL_SLABS
#ifdef CGAL_SLS_SNAP_TO_VERTICAL_SLABS
@ -205,17 +205,19 @@ public:
}
// can't modify the position yet because we need arrange_polygons() to still work properly
//
// @fixme on paper one could create a polygon thin-enough w.r.t. the max weight value
// such thatthere is a skeleton vertex that wants to be snapped to two different sides...
void on_offset_point(const Point_2& op,
SS_Halfedge_const_handle hook) const
{
CGAL_assertion(hook->is_bisector());
#ifdef CGAL_SLS_SNAP_TO_VERTICAL_SLABS
// @fixme on paper one could create a polygon thin-enough w.r.t. the max weight value such that
// there is a skeleton vertex that wants to be snapped to two different sides...
CGAL_assertion(m_snapped_positions.count(op) == 0);
CGAL_precondition(hook->is_bisector());
HDS_Halfedge_const_handle canonical_hook = (hook < hook->opposite()) ? hook : hook->opposite();
m_offset_points[canonical_hook] = op;
#ifdef CGAL_SLS_SNAP_TO_VERTICAL_SLABS
CGAL_precondition(m_snapped_positions.count(op) == 0);
SS_Halfedge_const_handle contour_h1 = hook->defining_contour_edge();
CGAL_assertion(contour_h1->opposite()->is_border());
@ -225,9 +227,6 @@ public:
const bool is_h1_vertical = (contour_h1->weight() == m_vertical_weight);
const bool is_h2_vertical = (contour_h2->weight() == m_vertical_weight);
// this can happen when the offset is passing through vertices
m_offset_points[canonical_hook] = op;
// if both are vertical, it's the common vertex (which has to exist)
if(is_h1_vertical && is_h2_vertical)
{
@ -691,7 +690,7 @@ public:
#ifdef CGAL_SLS_SNAP_TO_VERTICAL_SLABS
Visitor visitor(*ss_ptr, offset_points, vertical_weight, snapped_positions);
#else
Visitor visitor(*ss_ptr, vertical_weight, offset_points);
Visitor visitor(*ss_ptr, offset_points);
#endif
Offset_builder ob(*ss_ptr, Offset_builder_traits(), visitor);
Offset_polygons raw_output;

View File

@ -123,7 +123,7 @@ int main(int argc, char** argv)
// reassemble the mesh
Triangle_mesh final_mesh;
std::size_t nv=0, nf=0, ne=0;
Triangle_mesh::size_type nv = 0, nf = 0, ne = 0;
for (int i=0; i< number_of_parts; ++i)
{
meshes[i].collect_garbage();