mirror of https://github.com/CGAL/cgal
Merge remote-tracking branch 'cgal/master' into CGAL-Qt6-GF
# Conflicts: # GraphicsView/demo/Bounding_volumes/CMakeLists.txt
This commit is contained in:
commit
51627e3505
|
|
@ -1,6 +1,6 @@
|
|||
|
||||
/*!
|
||||
\ingroup PkgAlgebraicFoundationsInteroperabilityConcepts
|
||||
\ingroup PkgAlgebraicFoundationsAlgebraicStructuresConcepts
|
||||
\cgalConcept
|
||||
|
||||
Two types `A` and `B` are a model of the `ExplicitInteroperable`
|
||||
|
|
@ -27,4 +27,3 @@ class ExplicitInteroperable {
|
|||
public:
|
||||
|
||||
}; /* end ExplicitInteroperable */
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
|
||||
/*!
|
||||
\ingroup PkgAlgebraicFoundationsFractionsConcepts
|
||||
\ingroup PkgAlgebraicFoundationsAlgebraicStructuresConcepts
|
||||
\cgalConcept
|
||||
|
||||
A type is considered as a `Fraction`, if there is a reasonable way to
|
||||
|
|
@ -17,4 +17,3 @@ class Fraction {
|
|||
public:
|
||||
|
||||
}; /* end Fraction */
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
|
||||
/*!
|
||||
\ingroup PkgAlgebraicFoundationsConcepts
|
||||
\ingroup PkgAlgebraicFoundationsAlgebraicStructuresConcepts
|
||||
\cgalConcept
|
||||
|
||||
A model of the concept `FromDoubleConstructible` is required
|
||||
|
|
@ -27,4 +27,3 @@ FromDoubleConstructible(const double& d);
|
|||
/// @}
|
||||
|
||||
}; /* end FromDoubleConstructible */
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
|
||||
/*!
|
||||
\ingroup PkgAlgebraicFoundationsConcepts
|
||||
\ingroup PkgAlgebraicFoundationsAlgebraicStructuresConcepts
|
||||
\cgalConcept
|
||||
|
||||
A model of the concept `FromIntConstructible` is required
|
||||
|
|
@ -28,4 +28,3 @@ FromIntConstructible(int& i);
|
|||
/// @}
|
||||
|
||||
}; /* end FromIntConstructible */
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
|
||||
/*!
|
||||
\ingroup PkgAlgebraicFoundationsInteroperabilityConcepts
|
||||
\ingroup PkgAlgebraicFoundationsAlgebraicStructuresConcepts
|
||||
\cgalConcept
|
||||
|
||||
Two types `A` and `B` are a model of the concept
|
||||
|
|
@ -29,4 +29,3 @@ class ImplicitInteroperable {
|
|||
public:
|
||||
|
||||
}; /* end ImplicitInteroperable */
|
||||
|
||||
|
|
|
|||
|
|
@ -12,3 +12,4 @@ create_single_source_cgal_program("triangle_soup_wrap.cpp")
|
|||
create_single_source_cgal_program("point_set_wrap.cpp")
|
||||
create_single_source_cgal_program("wrap_from_cavity.cpp")
|
||||
create_single_source_cgal_program("mixed_inputs_wrap.cpp")
|
||||
create_single_source_cgal_program("volumetric_wrap.cpp")
|
||||
|
|
|
|||
|
|
@ -16,9 +16,9 @@ using K = CGAL::Exact_predicates_inexact_constructions_kernel;
|
|||
using Point_3 = K::Point_3;
|
||||
using Segment_3 = K::Segment_3;
|
||||
|
||||
using Face = std::array<std::size_t, 3>;
|
||||
using Segments = std::vector<Segment_3>;
|
||||
using Points = std::vector<Point_3>;
|
||||
using Face = std::array<std::size_t, 3>;
|
||||
using Faces = std::vector<Face>;
|
||||
|
||||
using Mesh = CGAL::Surface_mesh<Point_3>;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,173 @@
|
|||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/Surface_mesh.h>
|
||||
|
||||
#include <CGAL/alpha_wrap_3.h>
|
||||
|
||||
#include <CGAL/tetrahedral_remeshing.h>
|
||||
#include <CGAL/Tetrahedral_remeshing/Remeshing_cell_base_3.h>
|
||||
#include <CGAL/Tetrahedral_remeshing/Remeshing_vertex_base_3.h>
|
||||
#include <CGAL/Simplicial_mesh_cell_base_3.h>
|
||||
#include <CGAL/Simplicial_mesh_vertex_base_3.h>
|
||||
|
||||
#include <CGAL/Polygon_mesh_processing/bbox.h>
|
||||
#include <CGAL/Polygon_mesh_processing/IO/polygon_mesh_io.h>
|
||||
#include <CGAL/property_map.h>
|
||||
#include <CGAL/Real_timer.h>
|
||||
|
||||
#include <CGAL/Delaunay_triangulation_3.h>
|
||||
#include <CGAL/draw_triangulation_3.h>
|
||||
|
||||
#include <CGAL/IO/Triangulation_off_ostream_3.h>
|
||||
#include <CGAL/IO/File_medit.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
namespace PMP = CGAL::Polygon_mesh_processing;
|
||||
namespace AW3i = CGAL::Alpha_wraps_3::internal;
|
||||
|
||||
using K = CGAL::Exact_predicates_inexact_constructions_kernel;
|
||||
using Point_3 = K::Point_3;
|
||||
|
||||
using Points = std::vector<Point_3>;
|
||||
using Face = std::array<std::size_t, 3>;
|
||||
using Faces = std::vector<Face>;
|
||||
|
||||
using Mesh = CGAL::Surface_mesh<Point_3>;
|
||||
|
||||
// If we provide a triangulation, AW3 uses its Gt, so we have to make the Gt stack explicit
|
||||
using Gtb = AW3i::Alpha_wrap_AABB_geom_traits<K>; // provides Ball_3
|
||||
using Gt = CGAL::Robust_circumcenter_filtered_traits_3<Gtb>; // better inexact constructions (not mandatory)
|
||||
|
||||
// Since we are going to use tetrahedral remeshing on the underlying triangulation,
|
||||
// we need special vertex and cell base types that meets the requirements of the
|
||||
// tetrahedral remeshing concepts
|
||||
using Vbbb = AW3i::Alpha_wrap_triangulation_vertex_base_3<K>;
|
||||
using Vbb = CGAL::Simplicial_mesh_vertex_base_3<K, int, int, int, int, Vbbb>;
|
||||
using Vb = CGAL::Tetrahedral_remeshing::Remeshing_vertex_base_3<K, Vbb>;
|
||||
|
||||
using Cbbb = AW3i::Alpha_wrap_triangulation_cell_base_3<K>;
|
||||
using Cbb = CGAL::Simplicial_mesh_cell_base_3<K, int, int, Cbbb>;
|
||||
using Cb = CGAL::Tetrahedral_remeshing::Remeshing_cell_base_3<K, Cbb>;
|
||||
|
||||
using Tds = CGAL::Triangulation_data_structure_3<Vb, Cb>;
|
||||
|
||||
using Delaunay_triangulation = CGAL::Delaunay_triangulation_3<Gt, Tds, CGAL::Fast_location>;
|
||||
|
||||
// because the Fast_location does all kinds of rebinding shenanigans + T3_hierarchy is in the stack...
|
||||
using Triangulation = CGAL::Triangulation_3<typename Delaunay_triangulation::Geom_traits,
|
||||
typename Delaunay_triangulation::Triangulation_data_structure>;
|
||||
|
||||
using Facet = Triangulation::Facet;
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
// Read the input
|
||||
const std::string filename = (argc > 1) ? argv[1] : CGAL::data_file_path("meshes/bull.off");
|
||||
std::cout << "Reading " << filename << "..." << std::endl;
|
||||
|
||||
Points points;
|
||||
Faces faces;
|
||||
if(!CGAL::IO::read_polygon_soup(filename, points, faces) || faces.empty())
|
||||
{
|
||||
std::cerr << "Invalid input." << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
std::cout << "Input: " << points.size() << " vertices, " << faces.size() << " faces" << std::endl;
|
||||
|
||||
// Compute the alpha and offset values
|
||||
const double relative_alpha = (argc > 2) ? std::stod(argv[2]) : 20.;
|
||||
const double relative_offset = (argc > 3) ? std::stod(argv[3]) : 600.;
|
||||
|
||||
CGAL::Bbox_3 bbox;
|
||||
for(const Point_3& p : points)
|
||||
bbox += p.bbox();
|
||||
|
||||
const double diag_length = std::sqrt(CGAL::square(bbox.xmax() - bbox.xmin()) +
|
||||
CGAL::square(bbox.ymax() - bbox.ymin()) +
|
||||
CGAL::square(bbox.zmax() - bbox.zmin()));
|
||||
|
||||
const double alpha = diag_length / relative_alpha;
|
||||
const double offset = diag_length / relative_offset;
|
||||
std::cout << "alpha: " << alpha << ", offset: " << offset << std::endl;
|
||||
|
||||
// Construct the wrap
|
||||
CGAL::Real_timer t;
|
||||
t.start();
|
||||
|
||||
using Oracle = CGAL::Alpha_wraps_3::internal::Triangle_soup_oracle<K>;
|
||||
|
||||
Oracle oracle(K{});
|
||||
oracle.add_triangle_soup(points, faces, CGAL::parameters::default_values());
|
||||
|
||||
CGAL::Alpha_wraps_3::internal::Alpha_wrap_3<Oracle, Delaunay_triangulation> aw3(oracle);
|
||||
Mesh wrap;
|
||||
aw3(alpha, offset, wrap);
|
||||
|
||||
t.stop();
|
||||
std::cout << "Result: " << num_vertices(wrap) << " vertices, " << num_faces(wrap) << " faces" << std::endl;
|
||||
std::cout << "Took " << t.time() << " s." << std::endl;
|
||||
|
||||
// Get the interior tetrahedrization
|
||||
auto dt = aw3.triangulation();
|
||||
|
||||
// Save the result
|
||||
std::string input_name = std::string(filename);
|
||||
input_name = input_name.substr(input_name.find_last_of("/") + 1, input_name.length() - 1);
|
||||
input_name = input_name.substr(0, input_name.find_last_of("."));
|
||||
std::string output_name = input_name
|
||||
+ "_" + std::to_string(static_cast<int>(relative_alpha))
|
||||
+ "_" + std::to_string(static_cast<int>(relative_offset)) + ".off";
|
||||
std::cout << "Writing to " << output_name << std::endl;
|
||||
CGAL::IO::write_polygon_mesh(output_name, wrap, CGAL::parameters::stream_precision(17));
|
||||
|
||||
// Remesh the interior of the wrap
|
||||
const Delaunay_triangulation& aw3_dt = aw3.triangulation();
|
||||
const Triangulation& aw3_tr = static_cast<const Triangulation&>(aw3_dt);
|
||||
Triangulation tr = aw3_tr; // intentional copy
|
||||
|
||||
std::cout << "BEFORE: " << tr.number_of_vertices() << " vertices, " << tr.number_of_cells() << " cells" << std::endl;
|
||||
|
||||
// Set up the c3t3 information
|
||||
for(auto v : tr.finite_vertex_handles())
|
||||
v->set_dimension(3);
|
||||
|
||||
for(auto c : tr.finite_cell_handles())
|
||||
{
|
||||
if(c->is_outside())
|
||||
c->set_subdomain_index(0);
|
||||
else
|
||||
c->set_subdomain_index(1);
|
||||
|
||||
// if the neighboring cell has a different outside info, put the vertices
|
||||
// of the common face on the surface boundary
|
||||
for(int i=0; i<4; ++i)
|
||||
{
|
||||
if(c->neighbor(i)->is_outside() != c->is_outside())
|
||||
{
|
||||
c->set_surface_patch_index(i, 1);
|
||||
for(int j=1; j<4; ++j)
|
||||
c->vertex((i+j)%4)->set_dimension(2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::ofstream out_before("before_remeshing.mesh");
|
||||
CGAL::IO::write_MEDIT(out_before, tr);
|
||||
|
||||
// edge length of equilateral triangle with circumradius alpha
|
||||
// const double l = 2 * alpha * 0.8660254037844386; // sqrt(3)/2
|
||||
|
||||
// edge length of regular tetrahedron with circumradius alpha
|
||||
const double l = 1.6329931618554521 * alpha; // sqrt(8/3)
|
||||
|
||||
CGAL::tetrahedral_isotropic_remeshing(tr, l, CGAL::parameters::remesh_boundaries(false));
|
||||
|
||||
std::cout << "AFTER: " << tr.number_of_vertices() << " vertices, " << tr.number_of_cells() << " cells" << std::endl;
|
||||
|
||||
std::ofstream out_after("after_remeshing.mesh");
|
||||
CGAL::IO::write_MEDIT(out_after, tr);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2019-2022 Google LLC (USA).
|
||||
// Copyright (c) 2019-2023 Google LLC (USA).
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of CGAL (www.cgal.org).
|
||||
|
|
@ -29,16 +29,25 @@
|
|||
|
||||
#include <CGAL/license/Alpha_wrap_3.h>
|
||||
|
||||
#include <CGAL/Alpha_wrap_3/internal/Alpha_wrap_triangulation_cell_base_3.h>
|
||||
#include <CGAL/Alpha_wrap_3/internal/Alpha_wrap_triangulation_vertex_base_3.h>
|
||||
#include <CGAL/Alpha_wrap_3/internal/Alpha_wrap_AABB_geom_traits.h>
|
||||
#include <CGAL/Alpha_wrap_3/internal/gate_priority_queue.h>
|
||||
#include <CGAL/Alpha_wrap_3/internal/geometry_utils.h>
|
||||
#include <CGAL/Alpha_wrap_3/internal/oracles.h>
|
||||
|
||||
#include <CGAL/Delaunay_triangulation_3.h>
|
||||
#include <CGAL/Triangulation_data_structure_3.h>
|
||||
#include <CGAL/Delaunay_triangulation_cell_base_3.h>
|
||||
#include <CGAL/Delaunay_triangulation_cell_base_with_circumcenter_3.h>
|
||||
#include <CGAL/Robust_weighted_circumcenter_filtered_traits_3.h>
|
||||
|
||||
#include <CGAL/Cartesian_converter.h>
|
||||
#include <CGAL/Simple_cartesian.h>
|
||||
|
||||
#include <CGAL/boost/graph/Euler_operations.h>
|
||||
#include <CGAL/boost/graph/named_params_helper.h>
|
||||
#include <CGAL/Default.h>
|
||||
#include <CGAL/Named_function_parameters.h>
|
||||
#include <CGAL/Modifiable_priority_queue.h>
|
||||
#include <CGAL/Polygon_mesh_processing/bbox.h>
|
||||
|
|
@ -50,16 +59,9 @@
|
|||
#include <CGAL/Polygon_mesh_processing/stitch_borders.h> // only if non-manifoldness is not treated
|
||||
#include <CGAL/property_map.h>
|
||||
#include <CGAL/Real_timer.h>
|
||||
#include <CGAL/Delaunay_triangulation_3.h>
|
||||
#include <CGAL/Triangulation_data_structure_3.h>
|
||||
#include <CGAL/Delaunay_triangulation_cell_base_3.h>
|
||||
#include <CGAL/Triangulation_cell_base_with_info_3.h>
|
||||
#include <CGAL/Delaunay_triangulation_cell_base_with_circumcenter_3.h>
|
||||
#include <CGAL/Triangulation_vertex_base_with_info_3.h>
|
||||
#include <CGAL/Robust_weighted_circumcenter_filtered_traits_3.h>
|
||||
|
||||
#include <array>
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <fstream>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
|
|
@ -74,30 +76,11 @@ namespace CGAL {
|
|||
namespace Alpha_wraps_3 {
|
||||
namespace internal {
|
||||
|
||||
template <typename Cb>
|
||||
class Cell_base_with_timestamp
|
||||
: public Cb
|
||||
{
|
||||
std::size_t time_stamp_;
|
||||
namespace {
|
||||
|
||||
public:
|
||||
template <typename... Args>
|
||||
Cell_base_with_timestamp(const Args&... args) : Cb(args...), time_stamp_(-1) { }
|
||||
namespace AW3i = ::CGAL::Alpha_wraps_3::internal;
|
||||
|
||||
Cell_base_with_timestamp(const Cell_base_with_timestamp& other) : Cb(other), time_stamp_(other.time_stamp_) { }
|
||||
|
||||
typedef CGAL::Tag_true Has_timestamp;
|
||||
|
||||
std::size_t time_stamp() const { return time_stamp_; }
|
||||
void set_time_stamp(const std::size_t& ts) { time_stamp_ = ts; }
|
||||
|
||||
template <class TDS>
|
||||
struct Rebind_TDS
|
||||
{
|
||||
typedef typename Cb::template Rebind_TDS<TDS>::Other Cb2;
|
||||
typedef Cell_base_with_timestamp<Cb2> Other;
|
||||
};
|
||||
};
|
||||
} // unnamed namespace
|
||||
|
||||
struct Wrapping_default_visitor
|
||||
{
|
||||
|
|
@ -125,11 +108,34 @@ struct Wrapping_default_visitor
|
|||
void on_alpha_wrapping_end(const AlphaWrapper&) { };
|
||||
};
|
||||
|
||||
template <typename Oracle>
|
||||
template <typename Oracle_,
|
||||
typename Triangulation_ = CGAL::Default>
|
||||
class Alpha_wrap_3
|
||||
{
|
||||
using Oracle = Oracle_;
|
||||
|
||||
// Triangulation
|
||||
using Base_GT = typename Oracle::Geom_traits;
|
||||
using Geom_traits = Robust_circumcenter_filtered_traits_3<Base_GT>;
|
||||
using Default_Gt = CGAL::Robust_circumcenter_filtered_traits_3<Base_GT>;
|
||||
|
||||
using Default_Vb = Alpha_wrap_triangulation_vertex_base_3<Default_Gt>;
|
||||
using Default_Cb = Alpha_wrap_triangulation_cell_base_3<Default_Gt>;
|
||||
using Default_Cbt = Cell_base_with_timestamp<Default_Cb>; // determinism
|
||||
using Default_Tds = CGAL::Triangulation_data_structure_3<Default_Vb, Default_Cbt>;
|
||||
using Default_Triangulation = CGAL::Delaunay_triangulation_3<Default_Gt, Default_Tds, Fast_location>;
|
||||
|
||||
using Triangulation = typename Default::Get<Triangulation_, Default_Triangulation>::type;
|
||||
|
||||
using Cell_handle = typename Triangulation::Cell_handle;
|
||||
using Facet = typename Triangulation::Facet;
|
||||
using Vertex_handle = typename Triangulation::Vertex_handle;
|
||||
using Locate_type = typename Triangulation::Locate_type;
|
||||
|
||||
using Gate = internal::Gate<Triangulation>;
|
||||
using Alpha_PQ = Modifiable_priority_queue<Gate, Less_gate, Gate_ID_PM<Triangulation>, CGAL_BOOST_PAIRING_HEAP>;
|
||||
|
||||
// Use the geom traits from the triangulation, and trust the (advanced) user that provided it
|
||||
using Geom_traits = typename Triangulation::Geom_traits;
|
||||
|
||||
using FT = typename Geom_traits::FT;
|
||||
using Point_3 = typename Geom_traits::Point_3;
|
||||
|
|
@ -143,34 +149,6 @@ class Alpha_wrap_3
|
|||
using SC_Iso_cuboid_3 = SC::Iso_cuboid_3;
|
||||
using SC2GT = Cartesian_converter<SC, Geom_traits>;
|
||||
|
||||
struct Cell_info
|
||||
{
|
||||
bool is_outside = false;
|
||||
};
|
||||
|
||||
enum Vertex_info
|
||||
{
|
||||
DEFAULT = 0,
|
||||
BBOX_VERTEX,
|
||||
SEED_VERTEX
|
||||
};
|
||||
|
||||
using Vb = Triangulation_vertex_base_3<Geom_traits>;
|
||||
using Vbi = Triangulation_vertex_base_with_info_3<Vertex_info, Geom_traits, Vb>;
|
||||
using Cbb = Delaunay_triangulation_cell_base_3<Geom_traits>;
|
||||
using Cb = Delaunay_triangulation_cell_base_with_circumcenter_3<Geom_traits, Cbb>;
|
||||
using Cbi = Triangulation_cell_base_with_info_3<Cell_info, Geom_traits, Cb>;
|
||||
using Cbt = Cell_base_with_timestamp<Cbi>;
|
||||
using Tds = Triangulation_data_structure_3<Vbi, Cbt>;
|
||||
using Dt = Delaunay_triangulation_3<Geom_traits, Tds, Fast_location>;
|
||||
|
||||
using Cell_handle = typename Dt::Cell_handle;
|
||||
using Facet = typename Dt::Facet;
|
||||
using Vertex_handle = typename Dt::Vertex_handle;
|
||||
using Locate_type = typename Dt::Locate_type;
|
||||
|
||||
using Gate = internal::Gate<Dt>;
|
||||
using Alpha_PQ = Modifiable_priority_queue<Gate, Less_gate, Gate_ID_PM<Dt>, CGAL_BOOST_PAIRING_HEAP>;
|
||||
|
||||
protected:
|
||||
const Oracle m_oracle;
|
||||
|
|
@ -179,7 +157,7 @@ protected:
|
|||
FT m_alpha, m_sq_alpha;
|
||||
FT m_offset, m_sq_offset;
|
||||
|
||||
Dt m_dt;
|
||||
Triangulation m_tr;
|
||||
Alpha_PQ m_queue;
|
||||
|
||||
public:
|
||||
|
|
@ -187,7 +165,7 @@ public:
|
|||
Alpha_wrap_3(const Oracle& oracle)
|
||||
:
|
||||
m_oracle(oracle),
|
||||
m_dt(Geom_traits(oracle.geom_traits())),
|
||||
m_tr(Geom_traits(oracle.geom_traits())),
|
||||
// used to set up the initial MPQ, use some arbitrary not-too-small value
|
||||
m_queue(4096)
|
||||
{
|
||||
|
|
@ -197,9 +175,9 @@ public:
|
|||
}
|
||||
|
||||
public:
|
||||
const Geom_traits& geom_traits() const { return m_dt.geom_traits(); }
|
||||
Dt& triangulation() { return m_dt; }
|
||||
const Dt& triangulation() const { return m_dt; }
|
||||
const Geom_traits& geom_traits() const { return m_tr.geom_traits(); }
|
||||
Triangulation& triangulation() { return m_tr; }
|
||||
const Triangulation& triangulation() const { return m_tr; }
|
||||
const Alpha_PQ& queue() const { return m_queue; }
|
||||
|
||||
double default_alpha() const
|
||||
|
|
@ -216,13 +194,13 @@ private:
|
|||
const Point_3& circumcenter(const Cell_handle c) const
|
||||
{
|
||||
// We only cross an infinite facet once, so this isn't going to be recomputed many times
|
||||
if(m_dt.is_infinite(c))
|
||||
if(m_tr.is_infinite(c))
|
||||
{
|
||||
const int inf_index = c->index(m_dt.infinite_vertex());
|
||||
const int inf_index = c->index(m_tr.infinite_vertex());
|
||||
c->set_circumcenter(
|
||||
geom_traits().construct_circumcenter_3_object()(m_dt.point(c, (inf_index+1)&3),
|
||||
m_dt.point(c, (inf_index+2)&3),
|
||||
m_dt.point(c, (inf_index+3)&3)));
|
||||
geom_traits().construct_circumcenter_3_object()(m_tr.point(c, (inf_index+1)&3),
|
||||
m_tr.point(c, (inf_index+2)&3),
|
||||
m_tr.point(c, (inf_index+3)&3)));
|
||||
}
|
||||
|
||||
return c->circumcenter(geom_traits());
|
||||
|
|
@ -418,11 +396,11 @@ private:
|
|||
for(int i=0; i<8; ++i)
|
||||
{
|
||||
const Point_3 bp = SC2GT()(m_bbox.vertex(i));
|
||||
Vertex_handle bv = m_dt.insert(bp);
|
||||
Vertex_handle bv = m_tr.insert(bp);
|
||||
#ifdef CGAL_AW3_DEBUG_INITIALIZATION
|
||||
std::cout << "\t" << bp << std::endl;
|
||||
#endif
|
||||
bv->info() = BBOX_VERTEX;
|
||||
bv->type() = AW3i::Vertex_type:: BBOX_VERTEX;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -433,7 +411,7 @@ private:
|
|||
// that the refinement point is separated from the existing point set.
|
||||
bool cavity_cell_outside_tag(const Cell_handle ch)
|
||||
{
|
||||
CGAL_precondition(!m_dt.is_infinite(ch));
|
||||
CGAL_precondition(!m_tr.is_infinite(ch));
|
||||
|
||||
const Tetrahedron_with_outside_info<Geom_traits> tet(ch, geom_traits());
|
||||
if(m_oracle.do_intersect(tet))
|
||||
|
|
@ -536,8 +514,8 @@ private:
|
|||
// This problem only appears when the seed and icosahedron vertices are close to the offset surface,
|
||||
// which usually happens for large alpha values.
|
||||
|
||||
Vertex_handle seed_v = m_dt.insert(seed_p);
|
||||
seed_v->info() = SEED_VERTEX;
|
||||
Vertex_handle seed_v = m_tr.insert(seed_p);
|
||||
seed_v->type() = AW3i::Vertex_type:: SEED_VERTEX;
|
||||
seed_vs.push_back(seed_v);
|
||||
|
||||
// Icosahedron vertices (see also BGL::make_icosahedron())
|
||||
|
|
@ -573,8 +551,8 @@ private:
|
|||
if(bbox.has_on_unbounded_side(seed_neighbor_p))
|
||||
continue;
|
||||
|
||||
Vertex_handle ico_v = m_dt.insert(seed_neighbor_p, seed_v /*hint*/);
|
||||
ico_v->info() = SEED_VERTEX;
|
||||
Vertex_handle ico_v = m_tr.insert(seed_neighbor_p, seed_v /*hint*/);
|
||||
ico_v->type() = AW3i::Vertex_type:: SEED_VERTEX;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -587,26 +565,26 @@ private:
|
|||
}
|
||||
|
||||
#ifdef CGAL_AW3_DEBUG_INITIALIZATION
|
||||
std::cout << m_dt.number_of_vertices() - 8 /*bbox*/ << " vertice(s) due to seeds" << std::endl;
|
||||
std::cout << m_tr.number_of_vertices() - 8 /*bbox*/ << " vertice(s) due to seeds" << std::endl;
|
||||
#endif
|
||||
|
||||
for(Vertex_handle seed_v : seed_vs)
|
||||
{
|
||||
std::vector<Cell_handle> inc_cells;
|
||||
inc_cells.reserve(64);
|
||||
m_dt.incident_cells(seed_v, std::back_inserter(inc_cells));
|
||||
m_tr.incident_cells(seed_v, std::back_inserter(inc_cells));
|
||||
for(Cell_handle ch : inc_cells)
|
||||
ch->info().is_outside = cavity_cell_outside_tag(ch);
|
||||
ch->is_outside() = cavity_cell_outside_tag(ch);
|
||||
}
|
||||
|
||||
// Might as well go through the full triangulation since only seeds should have been inserted
|
||||
for(Cell_handle ch : m_dt.all_cell_handles())
|
||||
for(Cell_handle ch : m_tr.all_cell_handles())
|
||||
{
|
||||
if(!ch->info().is_outside)
|
||||
if(!ch->is_outside())
|
||||
continue;
|
||||
|
||||
// When the algorithm starts from a manually dug hole, infinite cells are tagged "inside"
|
||||
CGAL_assertion(!m_dt.is_infinite(ch));
|
||||
CGAL_assertion(!m_tr.is_infinite(ch));
|
||||
|
||||
for(int i=0; i<4; ++i)
|
||||
push_facet(std::make_pair(ch, i));
|
||||
|
|
@ -627,17 +605,17 @@ private:
|
|||
// init queue with all convex hull facets
|
||||
bool initialize_from_infinity()
|
||||
{
|
||||
for(Cell_handle ch : m_dt.all_cell_handles())
|
||||
for(Cell_handle ch : m_tr.all_cell_handles())
|
||||
{
|
||||
if(m_dt.is_infinite(ch))
|
||||
if(m_tr.is_infinite(ch))
|
||||
{
|
||||
ch->info().is_outside = true;
|
||||
const int inf_index = ch->index(m_dt.infinite_vertex());
|
||||
ch->is_outside() = true;
|
||||
const int inf_index = ch->index(m_tr.infinite_vertex());
|
||||
push_facet(std::make_pair(ch, inf_index));
|
||||
}
|
||||
else
|
||||
{
|
||||
ch->info().is_outside = false;
|
||||
ch->is_outside() = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -659,13 +637,13 @@ public:
|
|||
|
||||
clear(output_mesh);
|
||||
|
||||
CGAL_assertion_code(for(auto cit=m_dt.finite_cells_begin(), cend=m_dt.finite_cells_end(); cit!=cend; ++cit))
|
||||
CGAL_assertion_code(for(auto cit=m_tr.finite_cells_begin(), cend=m_tr.finite_cells_end(); cit!=cend; ++cit))
|
||||
CGAL_assertion(cit->tds_data().is_clear());
|
||||
|
||||
for(auto cit=m_dt.finite_cells_begin(), cend=m_dt.finite_cells_end(); cit!=cend; ++cit)
|
||||
for(auto cit=m_tr.finite_cells_begin(), cend=m_tr.finite_cells_end(); cit!=cend; ++cit)
|
||||
{
|
||||
Cell_handle seed = cit;
|
||||
if(seed->info().is_outside || seed->tds_data().processed())
|
||||
if(seed->is_outside() || seed->tds_data().processed())
|
||||
continue;
|
||||
|
||||
std::queue<Cell_handle> to_visit;
|
||||
|
|
@ -678,7 +656,7 @@ public:
|
|||
while(!to_visit.empty())
|
||||
{
|
||||
const Cell_handle cell = to_visit.front();
|
||||
CGAL_assertion(!cell->info().is_outside && !m_dt.is_infinite(cell));
|
||||
CGAL_assertion(!cell->is_outside() && !m_tr.is_infinite(cell));
|
||||
|
||||
to_visit.pop();
|
||||
|
||||
|
|
@ -690,17 +668,17 @@ public:
|
|||
for(int fid=0; fid<4; ++fid)
|
||||
{
|
||||
const Cell_handle neighbor = cell->neighbor(fid);
|
||||
if(neighbor->info().is_outside)
|
||||
if(neighbor->is_outside())
|
||||
{
|
||||
// There shouldn't be any artificial vertex on the inside/outside boundary
|
||||
// (past initialization)
|
||||
// CGAL_assertion(cell->vertex((fid + 1)&3)->info() == DEFAULT);
|
||||
// CGAL_assertion(cell->vertex((fid + 2)&3)->info() == DEFAULT);
|
||||
// CGAL_assertion(cell->vertex((fid + 3)&3)->info() == DEFAULT);
|
||||
// CGAL_assertion(cell->vertex((fid + 1)&3)->type() == AW3i::Vertex_type:: DEFAULT);
|
||||
// CGAL_assertion(cell->vertex((fid + 2)&3)->type() == AW3i::Vertex_type:: DEFAULT);
|
||||
// CGAL_assertion(cell->vertex((fid + 3)&3)->type() == AW3i::Vertex_type:: DEFAULT);
|
||||
|
||||
points.push_back(m_dt.point(cell, Dt::vertex_triple_index(fid, 0)));
|
||||
points.push_back(m_dt.point(cell, Dt::vertex_triple_index(fid, 1)));
|
||||
points.push_back(m_dt.point(cell, Dt::vertex_triple_index(fid, 2)));
|
||||
points.push_back(m_tr.point(cell, Triangulation::vertex_triple_index(fid, 0)));
|
||||
points.push_back(m_tr.point(cell, Triangulation::vertex_triple_index(fid, 1)));
|
||||
points.push_back(m_tr.point(cell, Triangulation::vertex_triple_index(fid, 2)));
|
||||
faces.push_back({idx, idx + 1, idx + 2});
|
||||
idx += 3;
|
||||
}
|
||||
|
|
@ -722,7 +700,7 @@ public:
|
|||
CGAL_assertion(is_closed(output_mesh));
|
||||
}
|
||||
|
||||
for(auto cit=m_dt.finite_cells_begin(), cend=m_dt.finite_cells_end(); cit!=cend; ++cit)
|
||||
for(auto cit=m_tr.finite_cells_begin(), cend=m_tr.finite_cells_end(); cit!=cend; ++cit)
|
||||
cit->tds_data().clear();
|
||||
|
||||
CGAL_postcondition(!is_empty(output_mesh));
|
||||
|
|
@ -742,7 +720,7 @@ public:
|
|||
std::cout << "> Extract wrap... ()" << std::endl;
|
||||
#endif
|
||||
|
||||
CGAL_assertion_code(for(Vertex_handle v : m_dt.finite_vertex_handles()))
|
||||
CGAL_assertion_code(for(Vertex_handle v : m_tr.finite_vertex_handles()))
|
||||
CGAL_assertion(!is_non_manifold(v));
|
||||
|
||||
clear(output_mesh);
|
||||
|
|
@ -754,26 +732,26 @@ public:
|
|||
std::unordered_map<Vertex_handle, std::size_t> vertex_to_id;
|
||||
std::size_t nv = 0;
|
||||
|
||||
for(auto fit=m_dt.finite_facets_begin(), fend=m_dt.finite_facets_end(); fit!=fend; ++fit)
|
||||
for(auto fit=m_tr.finite_facets_begin(), fend=m_tr.finite_facets_end(); fit!=fend; ++fit)
|
||||
{
|
||||
Facet f = *fit;
|
||||
if(!f.first->info().is_outside)
|
||||
f = m_dt.mirror_facet(f);
|
||||
if(!f.first->is_outside())
|
||||
f = m_tr.mirror_facet(f);
|
||||
|
||||
const Cell_handle c = f.first;
|
||||
const int s = f.second;
|
||||
const Cell_handle nh = c->neighbor(s);
|
||||
if(c->info().is_outside == nh->info().is_outside)
|
||||
if(c->is_outside() == nh->is_outside())
|
||||
continue;
|
||||
|
||||
std::array<std::size_t, 3> ids;
|
||||
for(int pos=0; pos<3; ++pos)
|
||||
{
|
||||
Vertex_handle vh = c->vertex(Dt::vertex_triple_index(s, pos));
|
||||
Vertex_handle vh = c->vertex(Triangulation::vertex_triple_index(s, pos));
|
||||
auto insertion_res = vertex_to_id.emplace(vh, nv);
|
||||
if(insertion_res.second) // successful insertion, never-seen-before vertex
|
||||
{
|
||||
points.push_back(m_dt.point(vh));
|
||||
points.push_back(m_tr.point(vh));
|
||||
++nv;
|
||||
}
|
||||
|
||||
|
|
@ -817,14 +795,14 @@ public:
|
|||
private:
|
||||
bool is_traversable(const Facet& f) const
|
||||
{
|
||||
return less_squared_radius_of_min_empty_sphere(m_sq_alpha, f, m_dt);
|
||||
return less_squared_radius_of_min_empty_sphere(m_sq_alpha, f, m_tr);
|
||||
}
|
||||
|
||||
bool compute_steiner_point(const Cell_handle ch,
|
||||
const Cell_handle neighbor,
|
||||
Point_3& steiner_point) const
|
||||
{
|
||||
CGAL_precondition(!m_dt.is_infinite(neighbor));
|
||||
CGAL_precondition(!m_tr.is_infinite(neighbor));
|
||||
|
||||
typename Geom_traits::Construct_ball_3 ball = geom_traits().construct_ball_3_object();
|
||||
typename Geom_traits::Construct_vector_3 vector = geom_traits().construct_vector_3_object();
|
||||
|
|
@ -920,7 +898,7 @@ private:
|
|||
// e.g. from DT3
|
||||
Facet_queue_status facet_status(const Facet& f) const
|
||||
{
|
||||
CGAL_precondition(!m_dt.is_infinite(f));
|
||||
CGAL_precondition(!m_tr.is_infinite(f));
|
||||
|
||||
#ifdef CGAL_AW3_DEBUG_FACET_STATUS
|
||||
std::cout << "facet status: "
|
||||
|
|
@ -933,10 +911,10 @@ private:
|
|||
const Cell_handle ch = f.first;
|
||||
const int id = f.second;
|
||||
const Cell_handle nh = ch->neighbor(id);
|
||||
if(m_dt.is_infinite(nh))
|
||||
if(m_tr.is_infinite(nh))
|
||||
return TRAVERSABLE;
|
||||
|
||||
if(nh->info().is_outside)
|
||||
if(nh->is_outside())
|
||||
{
|
||||
#ifdef CGAL_AW3_DEBUG_FACET_STATUS
|
||||
std::cout << "Neighbor already outside" << std::endl;
|
||||
|
|
@ -947,8 +925,9 @@ private:
|
|||
// push if facet is connected to artificial vertices
|
||||
for(int i=0; i<3; ++i)
|
||||
{
|
||||
const Vertex_handle vh = ch->vertex(Dt::vertex_triple_index(id, i));
|
||||
if(vh->info() == BBOX_VERTEX || vh->info() == SEED_VERTEX)
|
||||
const Vertex_handle vh = ch->vertex(Triangulation::vertex_triple_index(id, i));
|
||||
if(vh->type() == AW3i::Vertex_type:: BBOX_VERTEX ||
|
||||
vh->type() == AW3i::Vertex_type:: SEED_VERTEX)
|
||||
{
|
||||
#ifdef CGAL_AW3_DEBUG_FACET_STATUS
|
||||
std::cout << "artificial facet due to artificial vertex #" << i << std::endl;
|
||||
|
|
@ -974,7 +953,7 @@ private:
|
|||
|
||||
bool push_facet(const Facet& f)
|
||||
{
|
||||
CGAL_precondition(f.first->info().is_outside);
|
||||
CGAL_precondition(f.first->is_outside());
|
||||
|
||||
// skip if f is already in queue
|
||||
if(m_queue.contains_with_bounds_check(Gate(f)))
|
||||
|
|
@ -986,9 +965,9 @@ private:
|
|||
|
||||
const Cell_handle ch = f.first;
|
||||
const int id = f.second;
|
||||
const Point_3& p0 = m_dt.point(ch, (id+1)&3);
|
||||
const Point_3& p1 = m_dt.point(ch, (id+2)&3);
|
||||
const Point_3& p2 = m_dt.point(ch, (id+3)&3);
|
||||
const Point_3& p0 = m_tr.point(ch, (id+1)&3);
|
||||
const Point_3& p1 = m_tr.point(ch, (id+2)&3);
|
||||
const Point_3& p2 = m_tr.point(ch, (id+3)&3);
|
||||
|
||||
// @todo should prob be the real value we compare to alpha instead of squared_radius
|
||||
const FT sqr = geom_traits().compute_squared_radius_3_object()(p0, p1, p2);
|
||||
|
|
@ -1022,7 +1001,7 @@ private:
|
|||
m_offset = FT(offset);
|
||||
m_sq_offset = square(m_offset);
|
||||
|
||||
m_dt.clear();
|
||||
m_tr.clear();
|
||||
m_queue.clear();
|
||||
|
||||
insert_bbox_corners();
|
||||
|
|
@ -1052,7 +1031,7 @@ private:
|
|||
// const& to something that will be popped, but safe as `ch` && `id` are extracted before the pop
|
||||
const Gate& gate = m_queue.top();
|
||||
const Facet& f = gate.facet();
|
||||
CGAL_precondition(!m_dt.is_infinite(f));
|
||||
CGAL_precondition(!m_tr.is_infinite(f));
|
||||
|
||||
const Cell_handle ch = f.first;
|
||||
const int id = f.second;
|
||||
|
|
@ -1060,11 +1039,11 @@ private:
|
|||
|
||||
#ifdef CGAL_AW3_DEBUG_QUEUE
|
||||
static int fid = 0;
|
||||
std::cout << m_dt.number_of_vertices() << " DT vertices" << std::endl;
|
||||
std::cout << m_tr.number_of_vertices() << " DT vertices" << std::endl;
|
||||
std::cout << m_queue.size() << " facets in the queue" << std::endl;
|
||||
std::cout << "Face " << fid++ << "\n"
|
||||
<< "c = " << &*ch << " (" << m_dt.is_infinite(ch) << "), n = " << &*neighbor << " (" << m_dt.is_infinite(neighbor) << ")" << "\n"
|
||||
<< m_dt.point(ch, (id+1)&3) << "\n" << m_dt.point(ch, (id+2)&3) << "\n" << m_dt.point(ch, (id+3)&3) << std::endl;
|
||||
<< "c = " << &*ch << " (" << m_tr.is_infinite(ch) << "), n = " << &*neighbor << " (" << m_tr.is_infinite(neighbor) << ")" << "\n"
|
||||
<< m_tr.point(ch, (id+1)&3) << "\n" << m_tr.point(ch, (id+2)&3) << "\n" << m_tr.point(ch, (id+3)&3) << std::endl;
|
||||
std::cout << "Priority: " << gate.priority() << std::endl;
|
||||
#endif
|
||||
|
||||
|
|
@ -1080,13 +1059,13 @@ private:
|
|||
std::string face_name = "results/steps/face_" + std::to_string(static_cast<int>(i++)) + ".xyz";
|
||||
std::ofstream face_out(face_name);
|
||||
face_out.precision(17);
|
||||
face_out << "3\n" << m_dt.point(ch, (id+1)&3) << "\n" << m_dt.point(ch, (id+2)&3) << "\n" << m_dt.point(ch, (id+3)&3) << std::endl;
|
||||
face_out << "3\n" << m_tr.point(ch, (id+1)&3) << "\n" << m_tr.point(ch, (id+2)&3) << "\n" << m_tr.point(ch, (id+3)&3) << std::endl;
|
||||
face_out.close();
|
||||
#endif
|
||||
|
||||
if(m_dt.is_infinite(neighbor))
|
||||
if(m_tr.is_infinite(neighbor))
|
||||
{
|
||||
neighbor->info().is_outside = true;
|
||||
neighbor->is_outside() = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -1100,14 +1079,16 @@ private:
|
|||
// locate cells that are going to be destroyed and remove their facet from the queue
|
||||
int li, lj = 0;
|
||||
Locate_type lt;
|
||||
const Cell_handle conflict_cell = m_dt.locate(steiner_point, lt, li, lj, neighbor);
|
||||
CGAL_assertion(lt != Dt::VERTEX);
|
||||
const Cell_handle conflict_cell = m_tr.locate(steiner_point, lt, li, lj, neighbor);
|
||||
CGAL_assertion(lt != Triangulation::VERTEX);
|
||||
|
||||
// Using small vectors like in Triangulation_3 does not bring any runtime improvement
|
||||
std::vector<Facet> boundary_facets;
|
||||
std::vector<Cell_handle> conflict_zone;
|
||||
boundary_facets.reserve(32);
|
||||
conflict_zone.reserve(32);
|
||||
m_dt.find_conflicts(steiner_point, conflict_cell,
|
||||
|
||||
m_tr.find_conflicts(steiner_point, conflict_cell,
|
||||
std::back_inserter(boundary_facets),
|
||||
std::back_inserter(conflict_zone));
|
||||
|
||||
|
|
@ -1125,7 +1106,7 @@ private:
|
|||
|
||||
for(const Facet& f : boundary_facets)
|
||||
{
|
||||
const Facet mf = m_dt.mirror_facet(f); // boundary facets have incident cells in the CZ
|
||||
const Facet mf = m_tr.mirror_facet(f); // boundary facets have incident cells in the CZ
|
||||
if(m_queue.contains_with_bounds_check(Gate(mf)))
|
||||
m_queue.erase(Gate(mf));
|
||||
}
|
||||
|
|
@ -1133,18 +1114,20 @@ private:
|
|||
visitor.before_Steiner_point_insertion(*this, steiner_point);
|
||||
|
||||
// Actual insertion of the Steiner point
|
||||
Vertex_handle vh = m_dt.insert(steiner_point, lt, conflict_cell, li, lj);
|
||||
vh->info() = DEFAULT;
|
||||
// We could use TDS functions to avoid recomputing the conflict zone, but in practice
|
||||
// it does not bring any runtime improvements
|
||||
Vertex_handle vh = m_tr.insert(steiner_point, lt, conflict_cell, li, lj);
|
||||
vh->type() = AW3i::Vertex_type:: DEFAULT;
|
||||
|
||||
visitor.after_Steiner_point_insertion(*this, vh);
|
||||
|
||||
std::vector<Cell_handle> new_cells;
|
||||
new_cells.reserve(32);
|
||||
m_dt.incident_cells(vh, std::back_inserter(new_cells));
|
||||
m_tr.incident_cells(vh, std::back_inserter(new_cells));
|
||||
for(const Cell_handle& ch : new_cells)
|
||||
{
|
||||
// std::cout << "new cell has time stamp " << ch->time_stamp() << std::endl;
|
||||
ch->info().is_outside = m_dt.is_infinite(ch);
|
||||
ch->is_outside() = m_tr.is_infinite(ch);
|
||||
}
|
||||
|
||||
// Push all new boundary facets to the queue.
|
||||
|
|
@ -1156,25 +1139,25 @@ private:
|
|||
{
|
||||
for(int i=0; i<4; ++i)
|
||||
{
|
||||
if(m_dt.is_infinite(ch, i))
|
||||
if(m_tr.is_infinite(ch, i))
|
||||
continue;
|
||||
|
||||
const Cell_handle nh = ch->neighbor(i);
|
||||
if(nh->info().is_outside == ch->info().is_outside) // not on the boundary
|
||||
if(nh->is_outside() == ch->is_outside()) // not on the boundary
|
||||
continue;
|
||||
|
||||
const Facet boundary_f = std::make_pair(ch, i);
|
||||
if(ch->info().is_outside)
|
||||
if(ch->is_outside())
|
||||
push_facet(boundary_f);
|
||||
else
|
||||
push_facet(m_dt.mirror_facet(boundary_f));
|
||||
push_facet(m_tr.mirror_facet(boundary_f));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// tag neighbor as OUTSIDE
|
||||
neighbor->info().is_outside = true;
|
||||
neighbor->is_outside() = true;
|
||||
|
||||
// for each finite facet of neighbor, push it to the queue
|
||||
for(int i=0; i<4; ++i)
|
||||
|
|
@ -1188,10 +1171,10 @@ private:
|
|||
visitor.on_flood_fill_end(*this);
|
||||
|
||||
// Check that no useful facet has been ignored
|
||||
CGAL_postcondition_code(for(auto fit=m_dt.finite_facets_begin(), fend=m_dt.finite_facets_end(); fit!=fend; ++fit) {)
|
||||
CGAL_postcondition_code( if(fit->first->info().is_outside == fit->first->neighbor(fit->second)->info().is_outside) continue;)
|
||||
CGAL_postcondition_code(for(auto fit=m_tr.finite_facets_begin(), fend=m_tr.finite_facets_end(); fit!=fend; ++fit) {)
|
||||
CGAL_postcondition_code( if(fit->first->is_outside() == fit->first->neighbor(fit->second)->is_outside()) continue;)
|
||||
CGAL_postcondition_code( Facet f = *fit;)
|
||||
CGAL_postcondition_code( if(!fit->first->info().is_outside) f = m_dt.mirror_facet(f);)
|
||||
CGAL_postcondition_code( if(!fit->first->is_outside()) f = m_tr.mirror_facet(f);)
|
||||
CGAL_postcondition( facet_status(f) == IRRELEVANT);
|
||||
CGAL_postcondition_code(})
|
||||
}
|
||||
|
|
@ -1199,13 +1182,13 @@ private:
|
|||
private:
|
||||
bool is_non_manifold(Vertex_handle v) const
|
||||
{
|
||||
CGAL_precondition(!m_dt.is_infinite(v));
|
||||
CGAL_precondition(!m_tr.is_infinite(v));
|
||||
|
||||
bool is_non_manifold = false;
|
||||
|
||||
std::vector<Cell_handle> inc_cells;
|
||||
inc_cells.reserve(64);
|
||||
m_dt.incident_cells(v, std::back_inserter(inc_cells));
|
||||
m_tr.incident_cells(v, std::back_inserter(inc_cells));
|
||||
|
||||
// Flood one inside and outside CC.
|
||||
// Process both an inside and an outside CC to also detect edge pinching.
|
||||
|
|
@ -1218,7 +1201,7 @@ private:
|
|||
for(Cell_handle ic : inc_cells)
|
||||
{
|
||||
ic->tds_data().clear();
|
||||
if(ic->info().is_outside)
|
||||
if(ic->is_outside())
|
||||
outside_start = ic;
|
||||
else if(inside_start == Cell_handle())
|
||||
inside_start = ic;
|
||||
|
|
@ -1253,7 +1236,7 @@ private:
|
|||
CGAL_assertion(neigh_c->has_vertex(v));
|
||||
|
||||
if(neigh_c->tds_data().processed() ||
|
||||
neigh_c->info().is_outside != curr_c->info().is_outside) // do not cross the boundary
|
||||
neigh_c->is_outside() != curr_c->is_outside()) // do not cross the boundary
|
||||
continue;
|
||||
|
||||
cells_to_visit.push(neigh_c);
|
||||
|
|
@ -1278,7 +1261,7 @@ private:
|
|||
|
||||
bool is_non_manifold(Cell_handle c) const
|
||||
{
|
||||
CGAL_precondition(!m_dt.is_infinite(c));
|
||||
CGAL_precondition(!m_tr.is_infinite(c));
|
||||
|
||||
for(int i=0; i<4; ++i)
|
||||
{
|
||||
|
|
@ -1294,7 +1277,7 @@ private:
|
|||
{
|
||||
// Not the best complexity, but it's not important: this function is purely for information
|
||||
// Better complexity --> see PMP::non_manifold_vertices + throw
|
||||
for(const Vertex_handle v : m_dt.finite_vertex_handles())
|
||||
for(const Vertex_handle v : m_tr.finite_vertex_handles())
|
||||
if(is_non_manifold(v))
|
||||
return true;
|
||||
|
||||
|
|
@ -1307,18 +1290,18 @@ private:
|
|||
bool remove_bbox_vertices()
|
||||
{
|
||||
bool do_remove = true;
|
||||
auto vit = m_dt.finite_vertices_begin();
|
||||
auto vit = m_tr.finite_vertices_begin();
|
||||
for(std::size_t i=0; i<8; ++i)
|
||||
{
|
||||
Vertex_handle v = vit++;
|
||||
|
||||
std::vector<Cell_handle> inc_cells;
|
||||
inc_cells.reserve(64);
|
||||
m_dt.finite_incident_cells(v, std::back_inserter(inc_cells));
|
||||
m_tr.finite_incident_cells(v, std::back_inserter(inc_cells));
|
||||
|
||||
for(Cell_handle c : inc_cells)
|
||||
{
|
||||
if(!c->info().is_outside)
|
||||
if(!c->is_outside())
|
||||
{
|
||||
do_remove = false;
|
||||
break;
|
||||
|
|
@ -1333,11 +1316,11 @@ private:
|
|||
if(!do_remove)
|
||||
return false;
|
||||
|
||||
vit = m_dt.finite_vertices_begin();
|
||||
vit = m_tr.finite_vertices_begin();
|
||||
for(std::size_t i=0; i<8; ++i)
|
||||
{
|
||||
Vertex_handle v = vit++;
|
||||
m_dt.remove(v);
|
||||
m_tr.remove(v);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
@ -1355,7 +1338,7 @@ public:
|
|||
// remove_bbox_vertices();
|
||||
|
||||
std::stack<Vertex_handle> non_manifold_vertices; // @todo sort somehow?
|
||||
for(Vertex_handle v : m_dt.finite_vertex_handles())
|
||||
for(Vertex_handle v : m_tr.finite_vertex_handles())
|
||||
{
|
||||
if(is_non_manifold(v))
|
||||
non_manifold_vertices.push(v);
|
||||
|
|
@ -1365,15 +1348,20 @@ public:
|
|||
auto has_artificial_vertex = [](Cell_handle c) -> bool
|
||||
{
|
||||
for(int i=0; i<4; ++i)
|
||||
if(c->vertex(i)->info() == BBOX_VERTEX || c->vertex(i)->info() == SEED_VERTEX)
|
||||
{
|
||||
if(c->vertex(i)->type() == AW3i::Vertex_type:: BBOX_VERTEX ||
|
||||
c->vertex(i)->type() == AW3i::Vertex_type:: SEED_VERTEX)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
auto is_on_boundary = [](Cell_handle c, int i) -> bool
|
||||
{
|
||||
return (c->info().is_outside != c->neighbor(i)->info().is_outside);
|
||||
return (c->is_outside() != c->neighbor(i)->is_outside());
|
||||
};
|
||||
|
||||
auto count_boundary_facets = [&](Cell_handle c, Vertex_handle v) -> int
|
||||
|
|
@ -1395,17 +1383,17 @@ public:
|
|||
// auto sq_circumradius = [&](Cell_handle c) -> FT
|
||||
// {
|
||||
// const Point_3& cc = circumcenter(c);
|
||||
// return geom_traits().compute_squared_distance_3_object()(m_dt.point(c, 0), cc);
|
||||
// return geom_traits().compute_squared_distance_3_object()(m_tr.point(c, 0), cc);
|
||||
// };
|
||||
|
||||
auto sq_longest_edge = [&](Cell_handle c) -> FT
|
||||
{
|
||||
return (std::max)({ squared_distance(m_dt.point(c, 0), m_dt.point(c, 1)),
|
||||
squared_distance(m_dt.point(c, 0), m_dt.point(c, 2)),
|
||||
squared_distance(m_dt.point(c, 0), m_dt.point(c, 3)),
|
||||
squared_distance(m_dt.point(c, 1), m_dt.point(c, 2)),
|
||||
squared_distance(m_dt.point(c, 3), m_dt.point(c, 3)),
|
||||
squared_distance(m_dt.point(c, 2), m_dt.point(c, 3)) });
|
||||
return (std::max)({ squared_distance(m_tr.point(c, 0), m_tr.point(c, 1)),
|
||||
squared_distance(m_tr.point(c, 0), m_tr.point(c, 2)),
|
||||
squared_distance(m_tr.point(c, 0), m_tr.point(c, 3)),
|
||||
squared_distance(m_tr.point(c, 1), m_tr.point(c, 2)),
|
||||
squared_distance(m_tr.point(c, 3), m_tr.point(c, 3)),
|
||||
squared_distance(m_tr.point(c, 2), m_tr.point(c, 3)) });
|
||||
};
|
||||
|
||||
#ifdef CGAL_AW3_DEBUG_MANIFOLDNESS
|
||||
|
|
@ -1450,7 +1438,7 @@ public:
|
|||
|
||||
std::vector<Cell_handle> inc_cells;
|
||||
inc_cells.reserve(64);
|
||||
m_dt.finite_incident_cells(v, std::back_inserter(inc_cells));
|
||||
m_tr.finite_incident_cells(v, std::back_inserter(inc_cells));
|
||||
|
||||
#define CGAL_AW3_USE_BRUTE_FORCE_MUTABLE_PRIORITY_QUEUE
|
||||
#ifndef CGAL_AW3_USE_BRUTE_FORCE_MUTABLE_PRIORITY_QUEUE
|
||||
|
|
@ -1464,10 +1452,10 @@ public:
|
|||
std::sort(cit, cend, comparer);
|
||||
#endif
|
||||
Cell_handle ic = *cit;
|
||||
CGAL_assertion(!m_dt.is_infinite(ic));
|
||||
CGAL_assertion(!m_tr.is_infinite(ic));
|
||||
|
||||
// This is where new material is added
|
||||
ic->info().is_outside = false;
|
||||
ic->is_outside() = false;
|
||||
|
||||
#ifdef CGAL_AW3_DEBUG_DUMP_EVERY_STEP
|
||||
static int i = 0;
|
||||
|
|
@ -1484,14 +1472,14 @@ public:
|
|||
|
||||
std::vector<Vertex_handle> adj_vertices;
|
||||
adj_vertices.reserve(64);
|
||||
m_dt.finite_adjacent_vertices(v, std::back_inserter(adj_vertices));
|
||||
m_tr.finite_adjacent_vertices(v, std::back_inserter(adj_vertices));
|
||||
|
||||
for(Vertex_handle nv : adj_vertices)
|
||||
if(is_non_manifold(nv))
|
||||
non_manifold_vertices.push(nv);
|
||||
}
|
||||
|
||||
CGAL_assertion_code(for(Vertex_handle v : m_dt.finite_vertex_handles()))
|
||||
CGAL_assertion_code(for(Vertex_handle v : m_tr.finite_vertex_handles()))
|
||||
CGAL_assertion(!is_non_manifold(v));
|
||||
}
|
||||
|
||||
|
|
@ -1508,12 +1496,12 @@ private:
|
|||
const Facet& current_f = current_gate.facet();
|
||||
const Cell_handle ch = current_f.first;
|
||||
const int id = current_f.second;
|
||||
const Point_3& p0 = m_dt.point(ch, (id+1)&3);
|
||||
const Point_3& p1 = m_dt.point(ch, (id+2)&3);
|
||||
const Point_3& p2 = m_dt.point(ch, (id+3)&3);
|
||||
const Point_3& p0 = m_tr.point(ch, (id+1)&3);
|
||||
const Point_3& p1 = m_tr.point(ch, (id+2)&3);
|
||||
const Point_3& p2 = m_tr.point(ch, (id+3)&3);
|
||||
const FT sqr = geom_traits().compute_squared_radius_3_object()(p0, p1, p2);
|
||||
|
||||
std::cout << "At Facet with VID " << get(Gate_ID_PM<Dt>(), current_gate) << std::endl;
|
||||
std::cout << "At Facet with VID " << get(Gate_ID_PM<Triangulation>(), current_gate) << std::endl;
|
||||
|
||||
if(current_gate.priority() != sqr)
|
||||
std::cerr << "Error: facet in queue has wrong priority" << std::endl;
|
||||
|
|
@ -1546,13 +1534,13 @@ private:
|
|||
std::size_t nv = 0;
|
||||
std::size_t nf = 0;
|
||||
|
||||
for(auto fit=m_dt.finite_facets_begin(), fend=m_dt.finite_facets_end(); fit!=fend; ++fit)
|
||||
for(auto fit=m_tr.finite_facets_begin(), fend=m_tr.finite_facets_end(); fit!=fend; ++fit)
|
||||
{
|
||||
Cell_handle c = fit->first;
|
||||
int s = fit->second;
|
||||
|
||||
Cell_handle nc = c->neighbor(s);
|
||||
if(only_boundary_faces && (c->info().is_outside == nc->info().is_outside))
|
||||
if(only_boundary_faces && (c->is_outside() == nc->is_outside()))
|
||||
continue;
|
||||
|
||||
std::array<std::size_t, 3> ids;
|
||||
|
|
@ -1562,7 +1550,7 @@ private:
|
|||
auto insertion_res = vertex_to_id.emplace(v, nv);
|
||||
if(insertion_res.second)
|
||||
{
|
||||
vertices_ss << m_dt.point(v) << "\n";
|
||||
vertices_ss << m_tr.point(v) << "\n";
|
||||
++nv;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -36,24 +36,24 @@ struct Tetrahedron_with_outside_info
|
|||
using Triangle_3 = typename Kernel::Triangle_3;
|
||||
|
||||
template <typename CellHandle>
|
||||
Tetrahedron_with_outside_info(const CellHandle ch, const K& k)
|
||||
Tetrahedron_with_outside_info(const CellHandle c, const K& k)
|
||||
{
|
||||
typename K::Construct_bbox_3 bbox = k.construct_bbox_3_object();
|
||||
typename K::Construct_tetrahedron_3 tetrahedron = k.construct_tetrahedron_3_object();
|
||||
typename K::Construct_triangle_3 triangle = k.construct_triangle_3_object();
|
||||
|
||||
m_tet = tetrahedron(ch->vertex(0)->point(), ch->vertex(1)->point(),
|
||||
ch->vertex(2)->point(), ch->vertex(3)->point());
|
||||
m_tet = tetrahedron(c->vertex(0)->point(), c->vertex(1)->point(),
|
||||
c->vertex(2)->point(), c->vertex(3)->point());
|
||||
m_bbox = bbox(m_tet);
|
||||
|
||||
for(int i=0; i<4; ++i)
|
||||
{
|
||||
if(ch->neighbor(i)->info().is_outside)
|
||||
if(c->neighbor(i)->is_outside())
|
||||
m_b.set(i, true);
|
||||
|
||||
m_triangles[i] = triangle(ch->vertex((i+1)& 3)->point(),
|
||||
ch->vertex((i+2)& 3)->point(),
|
||||
ch->vertex((i+3)& 3)->point());
|
||||
m_triangles[i] = triangle(c->vertex((i+1)& 3)->point(),
|
||||
c->vertex((i+2)& 3)->point(),
|
||||
c->vertex((i+3)& 3)->point());
|
||||
m_tbox[i] = bbox(m_triangles[i]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,97 @@
|
|||
// Copyright (c) 2019-2023 Google LLC (USA).
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of CGAL (www.cgal.org).
|
||||
//
|
||||
// $URL$
|
||||
// $Id$
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
// Author(s) : Mael Rouxel-Labbé
|
||||
|
||||
#ifndef CGAL_ALPHA_WRAP_TRIANGULATION_CELL_BASE_3_H
|
||||
#define CGAL_ALPHA_WRAP_TRIANGULATION_CELL_BASE_3_H
|
||||
|
||||
#include <CGAL/license/Alpha_wrap_3.h>
|
||||
|
||||
#include <CGAL/Delaunay_triangulation_cell_base_with_circumcenter_3.h>
|
||||
|
||||
namespace CGAL {
|
||||
namespace Alpha_wraps_3 {
|
||||
namespace internal {
|
||||
|
||||
template < typename GT,
|
||||
typename Cb = CGAL::Delaunay_triangulation_cell_base_with_circumcenter_3<GT> >
|
||||
class Alpha_wrap_triangulation_cell_base_3
|
||||
: public Cb
|
||||
{
|
||||
private:
|
||||
bool outside = false;
|
||||
|
||||
public:
|
||||
typedef typename Cb::Vertex_handle Vertex_handle;
|
||||
typedef typename Cb::Cell_handle Cell_handle;
|
||||
|
||||
template < typename TDS2 >
|
||||
struct Rebind_TDS
|
||||
{
|
||||
using Cb2 = typename Cb::template Rebind_TDS<TDS2>::Other;
|
||||
using Other = Alpha_wrap_triangulation_cell_base_3<GT, Cb2>;
|
||||
};
|
||||
|
||||
Alpha_wrap_triangulation_cell_base_3()
|
||||
: Cb()
|
||||
{}
|
||||
|
||||
Alpha_wrap_triangulation_cell_base_3(Vertex_handle v0, Vertex_handle v1,
|
||||
Vertex_handle v2, Vertex_handle v3)
|
||||
: Cb(v0, v1, v2, v3)
|
||||
{}
|
||||
|
||||
Alpha_wrap_triangulation_cell_base_3(Vertex_handle v0, Vertex_handle v1,
|
||||
Vertex_handle v2, Vertex_handle v3,
|
||||
Cell_handle n0, Cell_handle n1,
|
||||
Cell_handle n2, Cell_handle n3)
|
||||
: Cb(v0, v1, v2, v3, n0, n1, n2, n3)
|
||||
{}
|
||||
|
||||
bool is_outside() const { return outside; }
|
||||
bool& is_outside() { return outside; }
|
||||
};
|
||||
|
||||
template <typename Cb>
|
||||
class Cell_base_with_timestamp
|
||||
: public Cb
|
||||
{
|
||||
std::size_t time_stamp_;
|
||||
|
||||
public:
|
||||
using Has_timestamp = CGAL::Tag_true;
|
||||
|
||||
template <class TDS>
|
||||
struct Rebind_TDS
|
||||
{
|
||||
using Cb2 = typename Cb::template Rebind_TDS<TDS>::Other;
|
||||
using Other = Cell_base_with_timestamp<Cb2>;
|
||||
};
|
||||
|
||||
public:
|
||||
template <typename... Args>
|
||||
Cell_base_with_timestamp(const Args&... args)
|
||||
: Cb(args...), time_stamp_(-1)
|
||||
{ }
|
||||
|
||||
Cell_base_with_timestamp(const Cell_base_with_timestamp& other)
|
||||
: Cb(other), time_stamp_(other.time_stamp_)
|
||||
{ }
|
||||
|
||||
public:
|
||||
std::size_t time_stamp() const { return time_stamp_; }
|
||||
void set_time_stamp(const std::size_t& ts) { time_stamp_ = ts; }
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace Alpha_wraps_3
|
||||
} // namespace CGAL
|
||||
|
||||
#endif // CGAL_ALPHA_WRAP_TRIANGULATION_CELL_BASE_3_H
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
// Copyright (c) 2019-2023 Google LLC (USA).
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of CGAL (www.cgal.org).
|
||||
//
|
||||
// $URL$
|
||||
// $Id$
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
// Author(s) : Mael Rouxel-Labbé
|
||||
|
||||
#ifndef CGAL_ALPHA_WRAP_TRIANGULATION_VERTEX_BASE_3_H
|
||||
#define CGAL_ALPHA_WRAP_TRIANGULATION_VERTEX_BASE_3_H
|
||||
|
||||
#include <CGAL/license/Alpha_wrap_3.h>
|
||||
|
||||
#include <CGAL/Triangulation_vertex_base_3.h>
|
||||
|
||||
namespace CGAL {
|
||||
namespace Alpha_wraps_3 {
|
||||
namespace internal {
|
||||
|
||||
enum class Vertex_type
|
||||
{
|
||||
DEFAULT = 0,
|
||||
BBOX_VERTEX,
|
||||
SEED_VERTEX
|
||||
};
|
||||
|
||||
template <typename GT,
|
||||
typename Vb = Triangulation_vertex_base_3<GT> >
|
||||
class Alpha_wrap_triangulation_vertex_base_3
|
||||
: public Vb
|
||||
{
|
||||
private:
|
||||
Vertex_type vertex_type = Vertex_type::DEFAULT;
|
||||
|
||||
public:
|
||||
using Cell_handle = typename Vb::Cell_handle;
|
||||
using Point = typename Vb::Point;
|
||||
|
||||
template <typename TDS2>
|
||||
struct Rebind_TDS
|
||||
{
|
||||
using Vb2 = typename Vb::template Rebind_TDS<TDS2>::Other;
|
||||
using Other = Alpha_wrap_triangulation_vertex_base_3<GT, Vb2>;
|
||||
};
|
||||
|
||||
public:
|
||||
Alpha_wrap_triangulation_vertex_base_3()
|
||||
: Vb() {}
|
||||
|
||||
Alpha_wrap_triangulation_vertex_base_3(const Point& p)
|
||||
: Vb(p) {}
|
||||
|
||||
Alpha_wrap_triangulation_vertex_base_3(const Point& p, Cell_handle c)
|
||||
: Vb(p, c) {}
|
||||
|
||||
Alpha_wrap_triangulation_vertex_base_3(Cell_handle c)
|
||||
: Vb(c) {}
|
||||
|
||||
public:
|
||||
const Vertex_type& type() const { return vertex_type; }
|
||||
Vertex_type& type() { return vertex_type; }
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace Alpha_wraps_3
|
||||
} // namespace CGAL
|
||||
|
||||
#endif // CGAL_ALPHA_WRAP_TRIANGULATION_VERTEX_BASE_3_H
|
||||
|
|
@ -1,19 +1,16 @@
|
|||
#ifndef CGAL_APOLLONIUS_GRAPH_2_TEST_H
|
||||
#define CGAL_APOLLONIUS_GRAPH_2_TEST_H
|
||||
|
||||
#include <cassert>
|
||||
#include <CGAL/enum.h>
|
||||
#include <CGAL/use.h>
|
||||
|
||||
#include <CGAL/Vector_2.h> // this is done in order to avoid error
|
||||
// when the Segment_2_Segment_2_intersection.h file is included from
|
||||
// the Triangulation_euclidean_traits_2.h file.
|
||||
|
||||
#include <CGAL/Apollonius_graph_2.h>
|
||||
#include <CGAL/Apollonius_graph_hierarchy_2.h>
|
||||
#include <CGAL/Apollonius_graph_traits_2.h>
|
||||
#include <CGAL/Apollonius_graph_filtered_traits_2.h>
|
||||
//#include <CGAL/new_traits/Apollonius_graph_new_filtered_traits_2.h>
|
||||
|
||||
#include <cassert>
|
||||
#include <CGAL/enum.h>
|
||||
#include <CGAL/use.h>
|
||||
#include <CGAL/Random.h>
|
||||
|
||||
|
||||
#include "IO/Null_output_stream.h"
|
||||
|
||||
|
|
@ -839,24 +836,29 @@ bool test_algo_generic(InputStream& is)
|
|||
// file I/O methods
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
std::ofstream ofs("ag_testsuite.tmp");
|
||||
std::string fname = "ag_testsuite_" + std::to_string(CGAL::Random().get_seed()) + ".tmp";
|
||||
std::cout << "writing to " << fname << std::endl;
|
||||
|
||||
std::ofstream ofs(fname);
|
||||
assert( ofs );
|
||||
ag.file_output(ofs);
|
||||
ofs.close();
|
||||
|
||||
std::ifstream ifs("ag_testsuite.tmp");
|
||||
std::ifstream ifs(fname);
|
||||
assert( ifs );
|
||||
ag.file_input(ifs);
|
||||
ifs.close();
|
||||
assert( ag.is_valid() );
|
||||
}
|
||||
{
|
||||
std::ofstream ofs("ag_testsuite.tmp");
|
||||
std::string fname = "ag_testsuite_" + std::to_string(CGAL::Random().get_seed()) + ".tmp";
|
||||
std::cout << "writing to " << fname << std::endl;
|
||||
std::ofstream ofs(fname);
|
||||
assert( ofs );
|
||||
ofs << ag;
|
||||
ofs.close();
|
||||
|
||||
std::ifstream ifs("ag_testsuite.tmp");
|
||||
std::ifstream ifs(fname);
|
||||
assert( ifs );
|
||||
ifs >> ag;
|
||||
ifs.close();
|
||||
|
|
|
|||
|
|
@ -5651,10 +5651,24 @@ must model the basic concept `ArrangementBasicTopologyTraits`. A model
|
|||
of this basic concept holds the (\dcel) data structure used to
|
||||
represent the arrangement cells (i.e., vertices, edges, and facets)
|
||||
and the incidence relations between them. At this point we do not
|
||||
expose the concepts that refine the basic concept. The package
|
||||
contains one topology traits, namely,
|
||||
`Arr_spherical_topology_traits_2`. It can serve as a topology traits
|
||||
for an arrangement embedded on a sphere. More precisely, for an
|
||||
expose the concepts that refine the basic concept. The package
|
||||
contains three topology traits class templates, namely,
|
||||
`Arr_bounded_planar_topology_traits_2`,
|
||||
`Arr_unb_planar_topology_traits_2`, and
|
||||
`Arr_spherical_topology_traits_2`. The first two are internally used
|
||||
to define any instance of the class template
|
||||
`Arrangement_2<GeometryTraits_2, Dcel>`. In particular, an instance
|
||||
`Arrangement_2<Geometry_traits_2, Dcel_>` is derived from the instance
|
||||
`Arrangement_on_surface_2<Geometry_traits_2,Topology_traits>`, where
|
||||
the `Topology_traits` type is selected based on the provided geometry
|
||||
traits `Geometry_traits_2`, or more precisely, on the boundary
|
||||
conditions defined by the geometry traits. If all sides of the
|
||||
boundary of the parameter space are closed, the instance
|
||||
`Arr_bounded_planar_topology_traits_2<Geometry_traits_2,Dcel_>` is
|
||||
selected; otherwise the instance
|
||||
`Arr_unb_planar_topology_traits_2<Geometry_traits_2,Dcel_>` is
|
||||
selected. The third topology traits serves as a topology traits for
|
||||
an arrangement embedded on a sphere. More precisely, for an
|
||||
arrangement embedded on a sphere defined over a parameter space, the
|
||||
left and right boundary sides of which are identified, and the top and
|
||||
bottom boundary sides are contracted.
|
||||
|
|
|
|||
|
|
@ -26,45 +26,37 @@ one of the integral types above.
|
|||
|
||||
|
||||
*/
|
||||
template< typename Coefficient >
|
||||
template <typename Coefficient>
|
||||
class Arr_algebraic_segment_traits_2 {
|
||||
public:
|
||||
|
||||
/// \name Types
|
||||
/// @{
|
||||
|
||||
/*!
|
||||
Value to specify whether a point should be in the interior
|
||||
of a segment, or its minimal point,
|
||||
or its maximal point in lexicographic order.
|
||||
*/
|
||||
/*! Value to specify whether a point should be in the interior of a segment, or
|
||||
* its minimal point, or its maximal point in lexicographic order.
|
||||
*/
|
||||
enum Site_of_point { POINT_IN_INTERIOR = 0, MIN_ENDPOINT = -1, MAX_ENDPOINT = 1 };
|
||||
|
||||
/*!
|
||||
the type for bivariate polynomials,
|
||||
with innermost coefficient type `Coefficient`.
|
||||
Constitutes a model of the concept `Polynomial_d`
|
||||
with two variables.
|
||||
|
||||
\sa `CGAL::Polynomial_d`
|
||||
*/
|
||||
/*! the type for bivariate polynomials, with innermost coefficient type
|
||||
* `Coefficient`. Constitutes a model of the concept `Polynomial_d` with two
|
||||
* variables.
|
||||
*
|
||||
* \sa `CGAL::Polynomial_d`
|
||||
*/
|
||||
typedef unspecified_type Polynomial_2;
|
||||
|
||||
/*!
|
||||
model for the concept
|
||||
`AlgebraicKernel_1`
|
||||
*/
|
||||
/*! model for the concept `AlgebraicKernel_1`
|
||||
*/
|
||||
typedef unspecified_type Algebraic_kernel_1;
|
||||
|
||||
/*!
|
||||
represents coordinates of points.
|
||||
Typedef from `Algebraic_kernel_1::Algebraic_real_1`
|
||||
*/
|
||||
/*! represents coordinates of points.
|
||||
* Typedef from `Algebraic_kernel_1::Algebraic_real_1`
|
||||
*/
|
||||
typedef unspecified_type Algebraic_real_1;
|
||||
|
||||
/*!
|
||||
Typedef from `Algebraic_kernel_1::Bound`
|
||||
*/
|
||||
/*! Typedef from `Algebraic_kernel_1::Bound`
|
||||
*/
|
||||
typedef unspecified_type Bound;
|
||||
|
||||
/// @}
|
||||
|
|
@ -74,46 +66,41 @@ typedef unspecified_type Bound;
|
|||
|
||||
/*!
|
||||
|
||||
*/
|
||||
*/
|
||||
Construct_curve_2 construct_curve_2_object() const;
|
||||
|
||||
/*!
|
||||
|
||||
*/
|
||||
*/
|
||||
Construct_point_2 construct_point_2_object() const;
|
||||
|
||||
/*!
|
||||
|
||||
*/
|
||||
*/
|
||||
Construct_x_monotone_segment_2 construct_x_monotone_segment_2_object() const;
|
||||
|
||||
/// @}
|
||||
|
||||
/*!
|
||||
|
||||
|
||||
*/
|
||||
*/
|
||||
class Construct_curve_2 {
|
||||
public:
|
||||
|
||||
/// \name Object Creation Functors
|
||||
/// @{
|
||||
|
||||
/*!
|
||||
Returns a `Curve_2` object that represents the curve defined by
|
||||
the polynomial `p`
|
||||
*/
|
||||
/*! Returns a `Curve_2` object that represents the curve defined by the
|
||||
* polynomial `p`
|
||||
*/
|
||||
Curve_2 operator() (Polynomial_2 p);
|
||||
|
||||
/*!
|
||||
Returns a `Curve_2` object specified by `s`.
|
||||
The passed string represents the defining polynomial of the curve
|
||||
and must be given in a MAPLE-readable format using "x" as first
|
||||
and "y" as second variable, e.g.,
|
||||
"(x^3*y-2*x)*(-6*x-y^3*x^6)"
|
||||
for integer coefficients, and "3/2*x*y^4-5/7*x^2+3/1"
|
||||
for rational coefficients.
|
||||
*/
|
||||
/*! Returns a `Curve_2` object specified by `s`. The passed string represents
|
||||
* the defining polynomial of the curve and must be given in a MAPLE-readable
|
||||
* format using "x" as first and "y" as second variable, e.g.,
|
||||
* \f$(x^3*y-2*x)*(-6*x-y^3*x^6)\f$ for integer coefficients, and
|
||||
* \f$3/2*x*y^4-5/7*x^2+3/1\f$ for rational coefficients.
|
||||
*/
|
||||
Curve_2 operator() (std::string s);
|
||||
|
||||
/// @}
|
||||
|
|
@ -122,49 +109,42 @@ Curve_2 operator() (std::string s);
|
|||
|
||||
/*!
|
||||
|
||||
|
||||
*/
|
||||
*/
|
||||
class Construct_point_2 {
|
||||
public:
|
||||
|
||||
/// \name Object Creation Functors
|
||||
/// @{
|
||||
|
||||
/*!
|
||||
Returns a `Point_2` object that represents the `arcno`-th
|
||||
point in the fiber of `cv` at \f$ x\f$-coordinate `x`,
|
||||
counted from the bottom, starting with zero.
|
||||
\pre (`cv` must not have a vertical line at `x`,
|
||||
and \f$ 0\leq arcno < c\f$, where \f$ c\f$ is the number of points
|
||||
in the fiber of `cv` at `x`.)
|
||||
*/
|
||||
/*! Returns a `Point_2` object that represents the `arcno`-th
|
||||
* point in the fiber of `cv` at \f$ x\f$-coordinate `x`,
|
||||
* counted from the bottom, starting with zero.
|
||||
* \pre (`cv` must not have a vertical line at `x`,
|
||||
* and \f$ 0\leq arcno < c\f$, where \f$ c\f$ is the number of points
|
||||
* in the fiber of `cv` at `x`.)
|
||||
*/
|
||||
Point_2 operator() (Algebraic_real_1 x, Curve_2 cv, int arcno);
|
||||
|
||||
/*!
|
||||
Returns a `Point_2` object that represents the
|
||||
point on `xcv` at \f$ x\f$-coordinate `x`
|
||||
\pre (`x` is in the \f$ x\f$-range of `xcv`.)
|
||||
*/
|
||||
/*! Returns a `Point_2` object that represents the
|
||||
* point on `xcv` at \f$ x\f$-coordinate `x`
|
||||
* \pre (`x` is in the \f$ x\f$-range of `xcv`.)
|
||||
*/
|
||||
Point_2 operator() (Algebraic_real_1 x, X_monotone_curve_2 xcv);
|
||||
|
||||
/*!
|
||||
Returns a `Point_2` object that represents (x,y)
|
||||
*/
|
||||
/*! Returns a `Point_2` object that represents (x,y)
|
||||
*/
|
||||
Point_2 operator() (Algebraic_real_1 x, Algebraic_real_1 y);
|
||||
|
||||
/*!
|
||||
Returns a `Point_2` object that represents (x,y)
|
||||
*/
|
||||
/*! Returns a `Point_2` object that represents (x,y)
|
||||
*/
|
||||
Point_2 operator() (Coefficient x, Coefficient y);
|
||||
|
||||
/*!
|
||||
Returns a `Point_2` object that represents (x,y)
|
||||
*/
|
||||
/*! Returns a `Point_2` object that represents (x,y)
|
||||
*/
|
||||
Point_2 operator() (Bound x, Bound y);
|
||||
|
||||
/*!
|
||||
Returns a `Point_2` object that represents (x,y)
|
||||
*/
|
||||
/*! Returns a `Point_2` object that represents (x,y)
|
||||
*/
|
||||
Point_2 operator() (int x, int y);
|
||||
|
||||
/// @}
|
||||
|
|
@ -173,91 +153,86 @@ Point_2 operator() (int x, int y);
|
|||
|
||||
/*!
|
||||
|
||||
|
||||
*/
|
||||
*/
|
||||
class Construct_x_monotone_segment_2 {
|
||||
public:
|
||||
|
||||
/// \name Object Creation Functors
|
||||
/// @{
|
||||
|
||||
/*!
|
||||
Writes a sequence of `X_monotone_curve_2` objects (terminal
|
||||
segments) into `out`. These terminal segments compose an
|
||||
\f$ x\f$-monotone (or vertical) segment of the curve `cv` that
|
||||
starts in `end_min`, and ends in `end_max`.
|
||||
\pre (`end_min` must have a unique \f$ x\f$-monotone segment
|
||||
to its right, or `end_max` must have a unique
|
||||
\f$ x\f$-monotone segment to its left. Furthermore,
|
||||
`end_min` and `end_max` must be connected
|
||||
by an \f$ x\f$-monotone segment of `cv`)
|
||||
*/
|
||||
template<class OutputIterator> OutputIterator
|
||||
operator() (Curve_2 cv, Point_2 end_min, Point_2 end_max,
|
||||
OutputIterator out);
|
||||
/*! inserts a sequence of `X_monotone_curve_2` objects (terminal segments) into
|
||||
* an output container given through an output iterator. These terminal segments
|
||||
* compose an \f$x\f$-monotone (or vertical) segment of a given curve that
|
||||
* starts in `end_min`, and ends in `end_max`.
|
||||
*
|
||||
* \param cv The input curve.
|
||||
* \param end_min The starting point.
|
||||
* \param end_max The ending point.
|
||||
* \param oi The output iterator that points at the output container.
|
||||
* \return The past-the-end iterator of the output container.
|
||||
*
|
||||
* \pre `end_min` must have a unique \f$x\f$-monotone segment to its right, or
|
||||
* `end_max` must have a unique \f$x\f$-monotone segment to its left.
|
||||
* Furthermore, `end_min` and `end_max` must be connected by an
|
||||
* \f$x\f$-monotone segment of `cv`)
|
||||
*/
|
||||
template <typename OutputIterator>
|
||||
OutputIterator operator() (Curve_2 cv, Point_2 end_min, Point_2 end_max,
|
||||
OutputIterator oi);
|
||||
|
||||
/*!
|
||||
Writes a sequence of `X_monotone_curve_2` objects into `out`.
|
||||
These segments form an \f$ x\f$-monotone (or vertical)
|
||||
segment of the curve `cv`.
|
||||
/*! inserts a sequence of `X_monotone_curve_2` objects into an output container
|
||||
* given through an output iterator. These segments form an \f$x\f$-monotone
|
||||
* (or vertical) segment of the curve `cv`.
|
||||
*
|
||||
* If `site_of_p==POINT_IN_INTERIOR`, the maximal segment is
|
||||
* returned that contains `p` in its interior.
|
||||
*
|
||||
* returned that contains `p` as its left endpoint.
|
||||
*
|
||||
* returned that contains `p` as its left endpoint.
|
||||
*
|
||||
* \pre (If `site_of_p==POINT_IN_INTERIOR`, `p`
|
||||
* must be an interior point of an \f$x\f$-monotone or a vertical
|
||||
* segment.
|
||||
* must either have a unique \f$x\f$-monotone segment to the right,
|
||||
* or a vertical segment from `p` upwards.
|
||||
* must either have a unique \f$x\f$-monotone segment to the left,
|
||||
* or a vertical segment from `p` downwards.)
|
||||
*/
|
||||
template <typename OutputIterator>
|
||||
OutputIterator operator() (Curve_2 cv, Point_2 p, Site_of_point site_of_p,
|
||||
OutputIterator out);
|
||||
|
||||
If `site_of_p==POINT_IN_INTERIOR`, the maximal segment is
|
||||
returned that contains `p` in its interior.
|
||||
|
||||
returned that contains `p` as its left endpoint.
|
||||
|
||||
returned that contains `p` as its left endpoint.
|
||||
\pre (If `site_of_p==POINT_IN_INTERIOR`, `p`
|
||||
must be an interior point of an \f$ x\f$-monotone or a vertical
|
||||
segment.
|
||||
must either have a unique \f$ x\f$-monotone segment to the right,
|
||||
or a vertical segment from `p` upwards.
|
||||
must either have a unique \f$ x\f$-monotone segment to the left,
|
||||
or a vertical segment from `p` downwards.)
|
||||
*/
|
||||
template<class OutputIterator> OutputIterator
|
||||
operator() (Curve_2 cv, Point_2 p,
|
||||
Site_of_point site_of_p,
|
||||
OutputIterator out);
|
||||
|
||||
/*!
|
||||
Writes a sequence of `X_monotone_curve_2` objects into `out`.
|
||||
These segments form a straight-line segment connecting
|
||||
the points `p` and `q`. If `p` and `q` share the
|
||||
same \f$ x\f$-coordinate, the constructed vertical segment consists of
|
||||
only one `X_monotone_curve_2` object and can be computed
|
||||
efficiently. In the non-vertical case,
|
||||
the construction is only possible if `p` and `q`
|
||||
have both rational x- and y-coordinates.
|
||||
\pre (`p` must not be equal to `q`.)
|
||||
|
||||
*/
|
||||
template<class OutputIterator> OutputIterator
|
||||
operator() (Point_2 p, Point_2 q,
|
||||
OutputIterator out);
|
||||
/*! inserts a sequence of `X_monotone_curve_2` objects into an output container
|
||||
* given through an output iterator. These segments form a straight-line
|
||||
* segment connecting the points `p` and `q`. If `p` and `q` share the same
|
||||
* \f$x\f$-coordinate, the constructed vertical segment consists of only one
|
||||
* `X_monotone_curve_2` object and can be computed efficiently. In the
|
||||
* non-vertical case, the construction is only possible if `p` and `q` have both
|
||||
* rational x- and y-coordinates.
|
||||
*
|
||||
* \pre (`p` must not be equal to `q`.)
|
||||
*/
|
||||
template <typename OutputIterator>
|
||||
OutputIterator operator() (Point_2 p, Point_2 q, OutputIterator out);
|
||||
|
||||
/// @}
|
||||
|
||||
}; /* end Arr_algebraic_segment_traits_2::Construct_x_monotone_segment_2 */
|
||||
|
||||
/*!
|
||||
|
||||
|
||||
Models the `ArrangementTraits_2::Curve_2` concept.
|
||||
Represents algebraic curves. Internally, the type stores
|
||||
topological-geometric information about the particular curve.
|
||||
In order to use internal caching, instances should only be created
|
||||
using the `Construct_curve_2` functor of the traits class.
|
||||
|
||||
*/
|
||||
/*! Models the `ArrangementTraits_2::Curve_2` concept.
|
||||
* Represents algebraic curves. Internally, the type stores
|
||||
* topological-geometric information about the particular curve.
|
||||
* In order to use internal caching, instances should only be created
|
||||
* using the `Construct_curve_2` functor of the traits class.
|
||||
*/
|
||||
class Curve_2 {
|
||||
public:
|
||||
|
||||
/// \name Modifiers
|
||||
/// @{
|
||||
|
||||
/*!
|
||||
returns the defining polynomial of the curve.
|
||||
/*! returns the defining polynomial of the curve.
|
||||
*/
|
||||
Polynomial_2 polynomial () const;
|
||||
|
||||
|
|
@ -265,124 +240,105 @@ Polynomial_2 polynomial () const;
|
|||
|
||||
}; /* end Arr_algebraic_segment_traits_2::Curve_2 */
|
||||
|
||||
/*!
|
||||
/*! Models the `ArrangementBasicTraits_2::Point_2` concept.
|
||||
* Represents points in \f$ \mathbb{R}^2\f$. Intersection points of algebraic
|
||||
* curves are in general non-rational, so we need a data structure that is
|
||||
* capable of representing arbitrary points with algebraic coordinates.
|
||||
*
|
||||
* The traits class represents algebraic coordinates by the type
|
||||
* `Algebraic_real_1`, which is a model of the `AlgebraicReal_1` concept.
|
||||
* A point \f$ p\f$ is stored by a triple \f$ (x,cv,arcno)\f$,
|
||||
* where \f$ x\f$ is the \f$ x\f$-coordinate of a point, \f$ cv\f$ is an instance
|
||||
* of `Curve_2` that contains the point, (and has no vertical line at \f$ x\f$),
|
||||
* and \f$ arcno\f$ is an `int`, denoting that \f$ p\f$ is met as the
|
||||
* \f$arcno\f$-th point when shooting a vertical ray at \f$ x\f$, starting from
|
||||
* \f$-\infty\f$ (where counting starts with \f$ 0\f$).
|
||||
*
|
||||
* In addition to the methods listed below, the copy constructor and assignment
|
||||
* operator for `Point_2` objects are also supported.
|
||||
*
|
||||
* The functor `Construct_point_2` constructs `Point_2` instances.
|
||||
*/
|
||||
|
||||
|
||||
Models the `ArrangementBasicTraits_2::Point_2` concept.
|
||||
Represents points in \f$ \mathbb{R}^2\f$. Intersection points of algebraic curves
|
||||
are in general non-rational, so we need a data structure that is capable
|
||||
of representing arbitrary points with algebraic coordinates.
|
||||
|
||||
The traits class represents algebraic coordinates by the type
|
||||
`Algebraic_real_1`, which is a model of the `AlgebraicReal_1`
|
||||
concept.
|
||||
A point \f$ p\f$ is stored by a triple \f$ (x,cv,arcno)\f$,
|
||||
where \f$ x\f$ is the \f$ x\f$-coordinate of a point, \f$ cv\f$ is an instance
|
||||
of `Curve_2` that contains the point, (and has no vertical line at \f$ x\f$),
|
||||
and \f$ arcno\f$ is an `int`, denoting that \f$ p\f$ is met as the \f$ arcno\f$-th
|
||||
point when shooting a vertical ray at \f$ x\f$, starting from \f$ -\infty\f$
|
||||
(where counting starts with \f$ 0\f$).
|
||||
|
||||
In addition to the methods listed below, the copy constructor and assignment
|
||||
operator for `Point_2` objects are also supported.
|
||||
|
||||
The functor `Construct_point_2` constructs `Point_2` instances.
|
||||
|
||||
*/
|
||||
class Point_2 {
|
||||
public:
|
||||
|
||||
/// \name Modifiers
|
||||
/// @{
|
||||
|
||||
/*!
|
||||
returns the \f$ x\f$-coordinate of `p`.
|
||||
*/
|
||||
/*! returns the \f$ x\f$-coordinate of `p`.
|
||||
*/
|
||||
Algebraic_real_1 x () const;
|
||||
|
||||
/*!
|
||||
returns the \f$ y\f$-coordinates of `p`.
|
||||
|
||||
<B>Attention:</B> As described above, points are not stored
|
||||
by their \f$ y\f$-coordinate in `Algebraic_real_1` representation. In fact,
|
||||
this representation must be computed on demand, and might become quite
|
||||
costly for points defined by high-degree polynomials. Therefore, it is
|
||||
recommended to avoid to call this function as much as possible.
|
||||
*/
|
||||
/*! returns the \f$ y\f$-coordinates of `p`.
|
||||
*
|
||||
* <B>Attention:</B> As described above, points are not stored
|
||||
* by their \f$ y\f$-coordinate in `Algebraic_real_1` representation. In fact,
|
||||
* this representation must be computed on demand, and might become quite
|
||||
* costly for points defined by high-degree polynomials. Therefore, it is
|
||||
* recommended to avoid to call this function as much as possible.
|
||||
*/
|
||||
Algebraic_real_1 y () const;
|
||||
|
||||
/*!
|
||||
returns a `Curve_2` instance that `p`is part of.
|
||||
*/
|
||||
/*! returns a `Curve_2` instance that `p`is part of.
|
||||
*/
|
||||
Curve_2 curve () const;
|
||||
|
||||
/*!
|
||||
returns the arc number of `p`.
|
||||
*/
|
||||
/*! returns the arc number of `p`.
|
||||
*/
|
||||
int arcno () const;
|
||||
|
||||
/*!
|
||||
returns double-approximations of the \f$ x\f$- and \f$ y\f$-coordinates.
|
||||
*/
|
||||
/*! returns double-approximations of the \f$ x\f$- and \f$ y\f$-coordinates.
|
||||
*/
|
||||
std::pair<double,double> to_double () const;
|
||||
|
||||
/// @}
|
||||
|
||||
}; /* end Arr_algebraic_segment_traits_2::Point_2 */
|
||||
|
||||
/*!
|
||||
|
||||
|
||||
Models the `ArrangementBasicTraits_2::X_monotone_curve_2` concept.
|
||||
Represents terminal segments of an algebraic curves,
|
||||
that means vertical segments or \f$ x\f$-monotone segments with no critical
|
||||
\f$ x\f$-coordinate in the interior of their \f$ x\f$-range.
|
||||
Terminal segments might either be bounded or unbounded.
|
||||
By definition, each interior point of
|
||||
a non-vertical segment has the same arc number (see the documentation of
|
||||
type `Point_2` above, which is called the <I>arc number</I> of the segment
|
||||
(note the arc number at the endpoints might differ).
|
||||
Such segments are represented internally by a 4-tuple \f$ (p,q,cv,arcno)\f$,
|
||||
where \f$ p\f$ and \f$ q\f$ are the endpoints, \f$ cv\f$ is the <I>supporting curve</I>
|
||||
that the segment belongs to, and arcno is the arc number of the segment.
|
||||
|
||||
Arbitrary (weakly) \f$ x\f$-monotone segments are presented by a range
|
||||
of `X_monotone_curve_2` instances, whose union equals the segment.
|
||||
The functor `Construct_x_monotone_segment_2` allows their construction.
|
||||
To construct all (maximal) terminal segments of a curve,
|
||||
use the `Make_x_monotone_2` functor supplied by the traits class.
|
||||
|
||||
*/
|
||||
/*! Models the `ArrangementBasicTraits_2::X_monotone_curve_2` concept.
|
||||
* Represents terminal segments of an algebraic curves, that means vertical
|
||||
* segments or \f$ x\f$-monotone segments with no critical \f$ x\f$-coordinate
|
||||
* in the interior of their \f$ x\f$-range. Terminal segments might either be
|
||||
* bounded or unbounded. By definition, each interior point of a non-vertical
|
||||
* segment has the same arc number (see the documentation of type `Point_2`
|
||||
* above, which is called the <I>arc number</I> of the segment (note the arc
|
||||
* number at the endpoints might differ). Such segments are represented
|
||||
* internally by a 4-tuple \f$ (p,q,cv,arcno)\f$, where \f$ p\f$ and \f$ q\f$
|
||||
* are the endpoints, \f$ cv\f$ is the <I>supporting curve</I> that the segment
|
||||
* belongs to, and arcno is the arc number of the segment.
|
||||
*
|
||||
* Arbitrary (weakly) \f$ x\f$-monotone segments are presented by a range
|
||||
* of `X_monotone_curve_2` instances, whose union equals the segment.
|
||||
* The functor `Construct_x_monotone_segment_2` allows their construction.
|
||||
* To construct all (maximal) terminal segments of a curve,
|
||||
* use the `Make_x_monotone_2` functor supplied by the traits class.
|
||||
*/
|
||||
class X_monotone_curve_2 {
|
||||
public:
|
||||
|
||||
/// \name Modifiers
|
||||
/// @{
|
||||
|
||||
/*!
|
||||
returns the supporting algebraic curve of `s`.
|
||||
*/
|
||||
/*! returns the supporting algebraic curve of `s`.
|
||||
*/
|
||||
Curve_2 curve () const;
|
||||
|
||||
/*!
|
||||
returns whether `s` is a vertical segment.
|
||||
*/
|
||||
/*! returns whether `s` is a vertical segment.
|
||||
*/
|
||||
bool is_vertical () const;
|
||||
|
||||
/*!
|
||||
returns whether `s` has a finite endpoint on the left
|
||||
*/
|
||||
/*! returns whether `s` has a finite endpoint on the left
|
||||
*/
|
||||
bool is_finite (CGAL::Arr_curve_end ce) const;
|
||||
|
||||
/*!
|
||||
\pre (The corresponding curve end is finite)
|
||||
*/
|
||||
/*! \pre (The corresponding curve end is finite)
|
||||
*/
|
||||
Point_2 curve_end (CGAL::Arr_curve_end ce) const;
|
||||
|
||||
/*!
|
||||
returns the arc number of the segment.
|
||||
\pre (The segment is non-vertical)
|
||||
*/
|
||||
/*! returns the arc number of the segment.
|
||||
* \pre (The segment is non-vertical)
|
||||
*/
|
||||
int arcno () const;
|
||||
|
||||
/*!
|
||||
|
|
@ -395,8 +351,6 @@ Algebraic_real_1 x () const;
|
|||
|
||||
}; /* end Arr_algebraic_segment_traits_2::X_monotone_curve_2 */
|
||||
|
||||
|
||||
|
||||
|
||||
}; /* end Arr_algebraic_segment_traits_2 */
|
||||
|
||||
} /* end namespace CGAL */
|
||||
|
|
|
|||
|
|
@ -1,36 +1,38 @@
|
|||
namespace CGAL {
|
||||
|
||||
/*!
|
||||
\ingroup PkgArrangementOnSurface2PointLocation
|
||||
|
||||
Performs a batched point-location operation on a
|
||||
given arrangement. It accepts a range of query points, and locates each
|
||||
point in the arrangement. The query results are returned through the output
|
||||
iterator. Each query result is given as a pair of the query point and an
|
||||
object representing the arrangement feature that contains it, namely a
|
||||
discriminated union container of the bounded types `Face_const_handle`,
|
||||
`Halfedge_const_handle`, and `Vertex_const_hanlde`. The resulting
|
||||
pairs in the output sequence are sorted in increasing \f$ xy\f$-lexicographical
|
||||
order of the query points. The function returns a past-the-end iterator of
|
||||
the output sequence.
|
||||
|
||||
\cgalHeading{Requirements}
|
||||
|
||||
<UL>
|
||||
<LI>`InputIterator::value_type` must be `Arrangement_2::Point_2`.
|
||||
<LI>`OutputIterator::value_type` must be convertible to
|
||||
`std::pair<Arrangement_2::Point_2, Arr_point_location_result<Arrangement_2>::%Type>`.
|
||||
</UL>
|
||||
|
||||
\sa `CGAL::Arr_point_location_result<Arrangement>`
|
||||
|
||||
*/
|
||||
template<typename Traits, typename Dcel,
|
||||
/*! \ingroup PkgArrangementOnSurface2PointLocation
|
||||
*
|
||||
* performs a batched point-location operation on a given arrangement. It
|
||||
* accepts a collection of query points, locates each point in a given
|
||||
* arrangement, and inserts the query results into an output container given
|
||||
* through an output iterator. Each query result is given as a pair of the query
|
||||
* point and an object representing the arrangement feature that contains it,
|
||||
* namely a discriminated union container of the types `Face_const_handle`,
|
||||
* `Halfedge_const_handle`, and `Vertex_const_hanlde`. The resulting pairs in
|
||||
* the output container are sorted in increasing \f$xy\f$-lexicographical order
|
||||
* of the query points.
|
||||
*
|
||||
* \param arr The arrangement.
|
||||
* \param begin The begin iterator of the container of input points.
|
||||
* \param end The past-the-end iterator of the container of input points.
|
||||
* \param oi The output iterator that points at the output container.
|
||||
* \return The past-the-end iterator of the output container.
|
||||
*
|
||||
* \cgalHeading{Requirements}
|
||||
*
|
||||
* \pre The value type of `InputIterator` must be convertible to
|
||||
* `Arrangement_2::Point_2`.
|
||||
* \pre Dereferencing `oi` must yield an object convertible to
|
||||
* `std::pair<Arrangement_2::Point_2, Arr_point_location_result<Arrangement_2>::%Type>`.
|
||||
*
|
||||
* \sa `CGAL::Arr_point_location_result<Arrangement>`
|
||||
*
|
||||
*/
|
||||
template <typename Traits, typename Dcel,
|
||||
typename InputIterator, typename OutputIterator>
|
||||
OutputIterator locate (const Arrangement_2<Traits,Dcel>& arr,
|
||||
InputIterator points_begin,
|
||||
InputIterator points_end,
|
||||
OutputIterator oi);
|
||||
OutputIterator locate (const Arrangement_2<Traits, Dcel>& arr,
|
||||
InputIterator begin,
|
||||
InputIterator end,
|
||||
OutputIterator oi);
|
||||
|
||||
} /* namespace CGAL */
|
||||
|
||||
|
|
|
|||
|
|
@ -467,20 +467,23 @@ public:
|
|||
*/
|
||||
Approximate_point_2 operator()(const Point_2& p) const;
|
||||
|
||||
/*! Obtain a polyline that approximates an \f$x\f$-monotone curve. The
|
||||
* polyline is defined by a range of approximate points beginning at
|
||||
* `oi`. The type `OutputIterator` must dereference the type
|
||||
* `Approximate_point_2`. The first and last points in the range are always
|
||||
* the endpoints of the given arc `xcv`. The operator returns a
|
||||
* past-the-end iterator of the destination range.
|
||||
* \param oi An output iterator for the resulting polyline.
|
||||
* \param error The error bound of the polyline approximation. This is
|
||||
* the Hausdorff distance between the arc and the polyline
|
||||
* that approximates the arc.
|
||||
/*! approximates a given \f$x\f$-monotone curve. It computes a sequence of
|
||||
* approximate points that represent an approximate polyline, and inserts
|
||||
* them into an output container given through an output iterator. The
|
||||
* first and last points in the sequence are always approximations of the
|
||||
* endpoints of the given arc.
|
||||
*
|
||||
* \param oi An output iterator for the output container.
|
||||
* \param error The error bound of the polyline approximation. This is the
|
||||
* Hausdorff distance between the arc and the polyline that
|
||||
* approximates the arc.
|
||||
* \param xcv The exact \f$x\f$-monotone arc.
|
||||
* \param l2r A Boolean flag that indicates whether the arc direction is
|
||||
* left to right.
|
||||
* \return The past-the-end iterator of the output iterator.
|
||||
* left to right.
|
||||
* \return The past-the-end iterator of the output container.
|
||||
*
|
||||
* \pre Dereferencing `oi` must yield an object of type
|
||||
* `Arr_conic_traits_2::Approximate_point_2`.
|
||||
*/
|
||||
template <typename OutputIterator>
|
||||
OutputIterator operator()(OutputIterator oi, double error,
|
||||
|
|
@ -521,7 +524,7 @@ public:
|
|||
Trim_2 trim_2_object() const;
|
||||
|
||||
/*! Obtain an `Approximate_2` functor. */
|
||||
Trim_2 approximate_2_object() const;
|
||||
Approximate_2 approximate_2_object() const;
|
||||
|
||||
/// @}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,27 +1,28 @@
|
|||
namespace CGAL {
|
||||
|
||||
/*!
|
||||
\ingroup PkgArrangementOnSurface2PointLocation
|
||||
|
||||
A unary metafunction to determine the return type of a point-location
|
||||
or vertical ray-shoot query.
|
||||
|
||||
\tparam Arrangement must be an instance of the `CGAL::Arrangement_2<Traits,Dcel>` class template.
|
||||
|
||||
\sa `ArrangementPointLocation_2`
|
||||
\sa `ArrangementVerticalRayShoot_2`
|
||||
\sa `CGAL::Arr_naive_point_location<Arrangement>`
|
||||
\sa `CGAL::Arr_walk_along_line_point_location<Arrangement>`
|
||||
\sa `CGAL::Arr_landmarks_point_location<Arrangement,Generator>`
|
||||
\sa `CGAL::Arr_trapezoid_ric_point_location<Arrangement>`
|
||||
*/
|
||||
template <class Arrangement>
|
||||
/*! \ingroup PkgArrangementOnSurface2PointLocation
|
||||
*
|
||||
* A unary metafunction to determine the return type of a point-location or
|
||||
* vertical ray-shoot query.
|
||||
*
|
||||
* \tparam Arrangement must be an instance of the
|
||||
* `CGAL::Arrangement_on_surface_2<GeometryTraits,Topology>` class template.
|
||||
*
|
||||
* \sa `ArrangementPointLocation_2`
|
||||
* \sa `ArrangementVerticalRayShoot_2`
|
||||
* \sa `CGAL::Arr_naive_point_location<Arrangement>`
|
||||
* \sa `CGAL::Arr_walk_along_line_point_location<Arrangement>`
|
||||
* \sa `CGAL::Arr_landmarks_point_location<Arrangement,Generator>`
|
||||
* \sa `CGAL::Arr_trapezoid_ric_point_location<Arrangement>`
|
||||
*/
|
||||
template <typename Arrangement>
|
||||
struct Arr_point_location_result
|
||||
{
|
||||
/*! The type of the arrangement feature that is the result of a
|
||||
* point-location query or a vertical ray-shoot query, namely,
|
||||
* `std::variant<Arrangement::Vertex_const_handle, Arrangement::Halfedge_const_handle, Arrangement::Face_const_handle>`
|
||||
* `std::variant<Arrangement_on_surface_2::Vertex_const_handle, Arrangement_on_surface_2::Halfedge_const_handle, Arrangement_on_surface_2::Face_const_handle>`
|
||||
*/
|
||||
typedef unspecified_type Type;
|
||||
}; /* end Arr_point_location_result */
|
||||
|
||||
} /* end namespace CGAL */
|
||||
|
|
|
|||
|
|
@ -238,17 +238,22 @@ namespace CGAL {
|
|||
const Point_2& tgt) const;
|
||||
};
|
||||
|
||||
/*! Subdivide a given subcurve into x-monotone subcurves and insert them
|
||||
* into a given output iterator.
|
||||
/*! Subdivide a given subcurve into \f$x\f$-monotone subcurves and
|
||||
* isolated points, and insert them into an output container. An object in
|
||||
* the output container is represented by a discriminated union container
|
||||
* that holds either a point or an \f$x\f$-monotone curve.
|
||||
*/
|
||||
class Make_x_monotone_2 {
|
||||
public:
|
||||
/*!
|
||||
* \pre if `cv` is not empty then it must be continuous and well-oriented.
|
||||
/*! performs the subdivision.
|
||||
*
|
||||
* \param cv the subcurve.
|
||||
* \param oi an output iterator for the result. Its value type is a variant
|
||||
* that wraps Point_2 or an X_monotone_curve_2 objects.
|
||||
* \return the past-the-end iterator.
|
||||
* \param oi The output iterator that points at the output container.
|
||||
* \return the past-the-end iterator of the output container.
|
||||
*
|
||||
* \pre if `cv` is not empty, then it must be continuous and well-oriented.
|
||||
* \pre Dereferencing `oi` must yield a polymorphic object of type
|
||||
* `std::variant<`\link Arr_polycurve_traits_2::Point_2 `Point_2` \endlink, `X_monotone_curve_2>`.
|
||||
*/
|
||||
template <typename OutputIterator>
|
||||
OutputIterator operator()(const Curve_2& cv, OutputIterator oi) const;
|
||||
|
|
|
|||
|
|
@ -2,51 +2,51 @@ namespace CGAL {
|
|||
|
||||
/*! \ingroup PkgArrangementOnSurface2Funcs
|
||||
*
|
||||
* Produces the symbolic vertical decomposition of a given arrangement,
|
||||
* performing a batched vertical ray-shooting query from all arrangement
|
||||
* vertices, such that every vertex is associated with a pair of objects, one
|
||||
* corresponds to the arrangement feature that lies below it, and the other
|
||||
* corresponds to the feature that lies above it. The output of this function
|
||||
* can be readily used for inserting vertical walls and physically decomposing
|
||||
* the arrangement into pseudo-trapezoids. To do this, it is convenient to
|
||||
* process the vertices in an ascending \f$ xy\f$-lexicographic order. The
|
||||
* visible objects are therefore returned through an output iterator, which
|
||||
* pairs each finite arrangement vertex with the two features it "sees", such
|
||||
* that the vertices are given in ascending \f$ xy\f$-lexicographic order.
|
||||
* produces the symbolic vertical decomposition of a given arrangement. More
|
||||
* precisely, this function performs a batched vertical ray-shooting query from
|
||||
* every arrangement vertex, and pairs each vertex with a pair of polymorphic
|
||||
* objects, one corresponds to the arrangement feature that lies below it, and
|
||||
* the other corresponds to the feature that lies above it.
|
||||
*
|
||||
* Produces the symbolic vertical decomposition of the `arr` arrangement. More
|
||||
* precisely, it performs a batched vertical ray-shooting query from all
|
||||
* arrangement vertices, such that every vertex is associated with a pair of
|
||||
* objects, one corresponding to the arrangement feature that lies below it,
|
||||
* while the other corresponds to the feature that lies above it. The query
|
||||
* results are returned through the output iterator, which pairs each finite
|
||||
* arrangement vertex with a pair of objects, the first represents the feature
|
||||
* below the vertex, and the second represents the feature that lies above
|
||||
* it. Each object is an optional variant that wraps a handle to an arrangement
|
||||
* feature. If the vertex is the top end-vertex of a vertical edge, we say that
|
||||
* The finite arrangement vertices and the features they "see", if exist,
|
||||
* that are, the query results, are inserted in ascending \f$xy\f$-lexicographic
|
||||
* order (of the query vertex) into an output container given through an output
|
||||
* iterator. If the vertex is the top end-vertex of a vertical edge, we say that
|
||||
* there is no feature below it; similarly, if it is the bottom end-vertex of a
|
||||
* vertical edge, we say that there is no feature above it. In these cases the
|
||||
* optional object is set to be empty; otherwise it is set as follows:
|
||||
* vertical edge, we say that there is no feature above it. Each feature, if
|
||||
* exists, is represented by a discriminated union container that holds an
|
||||
* object of one of the following types:
|
||||
*
|
||||
* <UL>
|
||||
* <LI>`Halfedge_const_handle`, if the vertex is located above (or below) an
|
||||
* edge. The given halfedge is always directed from right to left. In case
|
||||
* there is no concrete edge below (or above) the vertex, and the arrangement
|
||||
* is unbounded, then the object returned is a <I>fictitious</I> halfedge.
|
||||
* <LI>`Face_const_handle`, in case there is no edge below (or above)
|
||||
* the vertex, and the arrangement is bounded.
|
||||
* <LI>`Vertex_const_handle`, in case the vertex is located vertically above
|
||||
* (or below) another arrangement vertex.
|
||||
* </UL> The function returns a past-the-end iterator for its output sequence.
|
||||
* <LI> `Arrangement_on_surface_2::Halfedge_const_handle`, if the vertex is
|
||||
* located above (or below) an edge. The given halfedge is always directed
|
||||
* from right to left. In case there is no concrete edge below (or above)
|
||||
* the vertex, and the arrangement is unbounded, then the object returned
|
||||
* is a <I>fictitious</I> halfedge.
|
||||
* <LI> `Arrangement_on_surface_2::Face_const_handle`, in case there is no edge
|
||||
* below (or above) the vertex, and the arrangement is bounded.
|
||||
* <LI> `Arrangement_on_surface_2::Vertex_const_handle`, in case the vertex is
|
||||
* located vertically above (or below) another arrangement vertex.
|
||||
* </UL>
|
||||
*
|
||||
* The output of this function can be readily used for inserting vertical walls
|
||||
* and physically decomposing the arrangement into pseudo-trapezoids.
|
||||
*
|
||||
* \param arr The arrangement.
|
||||
* \param oi The output iterator that points at the output container.
|
||||
* \return The past-the-end iterator of the output container.
|
||||
*
|
||||
* \cgalHeading{Requirements}
|
||||
*
|
||||
* `OutputIterator::value_type` must be
|
||||
* `pair<Arrangement_2::Vertex_const_handle, pair<Object, Object> >`.
|
||||
*
|
||||
* \pre Dereferencing `oi` must yield an object of type
|
||||
* `std::pair<Arrangement_on_surface_2::Vertex_const_handle,
|
||||
* std::pair<std::optional<Type,std::optional<Type>>>`,
|
||||
* where `Type` is
|
||||
* `std::variant<Arrangement_on_surface_2::Vertex_const_handle, Arrangement_on_surface_2::Halfedge_const_handle, Arrangement_on_surface_2::Face_const_handle>`.
|
||||
*/
|
||||
template<typename Traits, typename Dcel,
|
||||
typename OutputIterator>
|
||||
OutputIterator decompose (const Arrangement_2<Traits,Dcel>& arr,
|
||||
OutputIterator oi);
|
||||
template <typename Traits, typename TopologyTraits, typename OutputIterator>
|
||||
OutputIterator
|
||||
decompose(const Arrangement_on_surface_2<GeometryTraits,TopologyTraits>& arr,
|
||||
OutputIterator oi);
|
||||
|
||||
} /* namespace CGAL */
|
||||
|
|
|
|||
|
|
@ -160,12 +160,12 @@ public:
|
|||
|
||||
namespace CGAL {
|
||||
|
||||
/*! \ingroup PkgArrangementOnSurface2Insert insert The function `%insert`
|
||||
* inserts one or more curves or \f$ x\f$-monotone curves into a given
|
||||
* arrangement, where no restrictions are imposed on the inserted curves. If an
|
||||
* inserted curve is not \f$ x\f$-monotone curve, it is subdivided into \f$
|
||||
* x\f$-monotone subcurves (and perhaps isolated points), which are inserted
|
||||
* into the arrangement.
|
||||
/*! \ingroup PkgArrangementOnSurface2Insert
|
||||
* The function `%insert` inserts one or more curves or \f$ x\f$-monotone curves
|
||||
* into a given arrangement, where no restrictions are imposed on the inserted
|
||||
* curves. If an inserted curve is not \f$ x\f$-monotone curve, it is subdivided
|
||||
* into \f$ x\f$-monotone subcurves (and perhaps isolated points), which are
|
||||
* inserted into the arrangement.
|
||||
*
|
||||
* \cgalHeading{Requirements}
|
||||
*
|
||||
|
|
@ -379,37 +379,4 @@ template <typename Traits, typename Dcel>
|
|||
bool remove_vertex(Arrangement_2<Traits,Dcel>& arr,
|
||||
typename Arrangement_2<Traits,Dcel>::Vertex_handle v);
|
||||
|
||||
/*! \ingroup PkgArrangementOnSurface2Funcs
|
||||
*
|
||||
* Compute the zone of the given \f$ x\f$-monotone curve in the existing
|
||||
* arrangement. Meaning, it output the arrangement's vertices, edges and faces
|
||||
* that the \f$ x\f$-monotone curve intersects. The order of the objects is the
|
||||
* order that they are discovered when traversing the \f$ x\f$-monotone curve
|
||||
* from left to right.
|
||||
*
|
||||
* A given point-location object is used for answering point-location queries
|
||||
* during the insertion process. By default, the function uses the "walk along
|
||||
* line" point-location strategy - namely an instance of the class
|
||||
* `Arr_walk_along_line_point_location<Arrangement_2<Traits,Dcel> >`.
|
||||
*
|
||||
* Compute the zone of the given \f$ x\f$-monotone curve `c` in the arrangement
|
||||
* `arr`.
|
||||
*
|
||||
* \pre If provided, `pl` must be attached to the given arrangement `arr`.
|
||||
*
|
||||
* \cgalHeading{Requirements}
|
||||
*
|
||||
* <UL>
|
||||
* <LI>The instantiated `GeomTraits` class must model the
|
||||
* `ArrangementXMonotoneTraits_2` concept.
|
||||
* <LI>The point-location object `pl`, must model the
|
||||
* `ArrangementPointLocation_2` concept.
|
||||
* </UL>
|
||||
*/
|
||||
template <typename Traits, typename Dcel,
|
||||
typename OutputIterator, typename PointLocation>
|
||||
OutputIterator zone(Arrangement_2<Traits, Dcel>& arr,
|
||||
const typename Traits::X_monotone_curve_2& c,
|
||||
OutputIterator oi, const PointLocation& pl);
|
||||
|
||||
} /* namespace CGAL */
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@ namespace CGAL {
|
|||
* \sa `Arr_default_dcel<Traits>`
|
||||
* \sa `ArrangementBasicTraits_2`
|
||||
* \sa `CGAL::overlay()`
|
||||
* \sa `CGAL::is_valid()`
|
||||
|
||||
* Insertion Functions
|
||||
|
||||
|
|
@ -1014,7 +1013,7 @@ public:
|
|||
|
||||
namespace CGAL {
|
||||
|
||||
/*! \ingroup PkgArrangementOnSurface2Insert insert
|
||||
/*! \ingroup PkgArrangementOnSurface2Insert
|
||||
* The function `%insert` inserts one or more curves or \f$ x\f$-monotone
|
||||
* curves into a given arrangement, where no restrictions are imposed on the
|
||||
* inserted curves. If an inserted curve is not \f$ x\f$-monotone curve, it is
|
||||
|
|
@ -1295,38 +1294,43 @@ bool remove_vertex
|
|||
|
||||
/*! \ingroup PkgArrangementOnSurface2Funcs
|
||||
*
|
||||
* Compute the zone of the given \f$ x\f$-monotone curve in the existing
|
||||
* arrangement. Meaning, it output the arrangement's vertices, edges and faces
|
||||
* that the \f$ x\f$-monotone curve intersects. The order of the objects is the
|
||||
* order that they are discovered when traversing the \f$ x\f$-monotone curve
|
||||
* from left to right.
|
||||
* computes the zone of the given \f$x\f$-monotone curve in a given
|
||||
* arrangement. More precisely, this function finds the arrangement vertices,
|
||||
* edges ,and faces that the given \f$x\f$-monotone curve intersects, and
|
||||
* inserts them in the order they are discovered when traversing the
|
||||
* \f$x\f$-monotone curve from left to right into an output contaiuner given
|
||||
* through an output iterator. An object in the resulting zone is represented by
|
||||
* a discriminated union container that holds a vertex handle, halfedge handle,
|
||||
* or a face handle.
|
||||
*
|
||||
* A given point-location object is used for answering point-location queries
|
||||
* during the insertion process. By default, the function uses the "walk along
|
||||
* line" point-location strategy - namely an instance of the class
|
||||
* line" point-location strategy, namely, an instance of the class
|
||||
* `Arr_walk_along_line_point_location<Arrangement_on_surface_2<GeometryTraits,
|
||||
* TopologyTraits> >`.
|
||||
* TopologyTraits>>`.
|
||||
*
|
||||
* Compute the zone of the given \f$ x\f$-monotone curve `c` in the arrangement
|
||||
* `arr`.
|
||||
* \param arr The given arrangement.
|
||||
* \param c The \f$x\f$-monotone curve.
|
||||
* \param oi The output iterator that points at the output container.
|
||||
* \param pl The point-location object.
|
||||
* \return The past-the-end iterator of the output container.
|
||||
*
|
||||
* \pre If provided, `pl` must be attached to the given arrangement `arr`.
|
||||
* \pre The instantiated `GeometryTraits` class must model the
|
||||
* `ArrangementXMonotoneTraits_2` concept.
|
||||
* \pre The point-location object `pl`, must model the
|
||||
* `ArrangementPointLocation_2` concept.
|
||||
* \pre Dereferencing `oi` must yield a polymorphic object of type
|
||||
* `std::variant<Arrangement_on_surface_2::Vertex_handle, Arrangement_on_surface_2::Halfedge_handle, Arrangement_on_surface_2::Face_handle>`.
|
||||
*
|
||||
* \cgalHeading{Requirements}
|
||||
*
|
||||
* <UL>
|
||||
* <LI>The instantiated `GeometryTraits` class must model the
|
||||
* `ArrangementXMonotoneTraits_2` concept.
|
||||
* <LI>The point-location object `pl`, must model the
|
||||
* `ArrangementPointLocation_2` concept.
|
||||
* </UL>
|
||||
*/
|
||||
template <typename GeometryTraits, typename TopologyTraits,
|
||||
typename OutputIterator, typename PointLocation>
|
||||
OutputIterator zone
|
||||
(Arrangement_on_surface_2<GeometryTraits, TopologyTraits>& arr,
|
||||
const typename GeometryTraits::X_monotone_curve_2& c,
|
||||
OutputIterator oi,
|
||||
const PointLocation& pl);
|
||||
OutputIterator
|
||||
zone(Arrangement_on_surface_2<GeometryTraits, TopologyTraits>& arr,
|
||||
const typename GeometryTraits::X_monotone_curve_2& c,
|
||||
OutputIterator oi,
|
||||
const PointLocation& pl);
|
||||
|
||||
} /* namespace CGAL */
|
||||
|
|
|
|||
|
|
@ -0,0 +1,246 @@
|
|||
namespace CGAL {
|
||||
|
||||
/*! \ingroup PkgArrangementOnSurface2TraitsClasses
|
||||
*
|
||||
* `CORE_algebraic_number_traits` is a traits class for CORE's algebraic
|
||||
* number types.
|
||||
*
|
||||
* \sa `Arr_conic_traits_2<RatKernel, AlgKernel, NtTraits>`
|
||||
*/
|
||||
class CORE_algebraic_number_traits {
|
||||
public:
|
||||
/// \name Types
|
||||
/// @{
|
||||
|
||||
//! The integer number type.
|
||||
typedef CORE::BigInt Integer;
|
||||
|
||||
//! The rational number type.
|
||||
typedef CORE::BigRat Rational;
|
||||
|
||||
//! The polynomial type.
|
||||
typedef CORE::Polynomial<Integer> Polynomial;
|
||||
|
||||
//! The algebraic number type.
|
||||
typedef CORE::Expr Algebraic;
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Utility Functions
|
||||
/// @{
|
||||
|
||||
/*! obtains the numerator of a rational number.
|
||||
*
|
||||
* \param q The rational number.
|
||||
* \return The numerator of `q`.
|
||||
*/
|
||||
Integer numerator(const Rational& q) const;
|
||||
|
||||
/*! obtains the denominator of a rational number.
|
||||
*
|
||||
* \param q The rational number.
|
||||
* \return The denominator of `q`.
|
||||
*/
|
||||
Integer denominator(const Rational& q) const;
|
||||
|
||||
/*! converts an integer to an algebraic number.
|
||||
*
|
||||
* \param z The integer.
|
||||
* \return The algebraic number equivalent to `z`.
|
||||
*/
|
||||
Algebraic convert(const Integer& z) const;
|
||||
|
||||
/*! converts a rational number to an algebraic number.
|
||||
*
|
||||
* \param q A rational number.
|
||||
* \return The algebraic number equivalent to `q`.
|
||||
*/
|
||||
Algebraic convert(const Rational& q) const;
|
||||
|
||||
/*! constructs a rational number that lies strictly between two algebraic
|
||||
* values.
|
||||
*
|
||||
* \param x1 The first algebraic value.
|
||||
* \param x2 The second algebraic value.
|
||||
* \pre The two values are not equal.
|
||||
* \return The rational number that lies in the open interval (`x1`, `x2`).
|
||||
*/
|
||||
Rational rational_in_interval(const Algebraic& x1, const Algebraic& x2) const;
|
||||
|
||||
/*! obtains a range of double-precision floats that contains the given
|
||||
* algebraic number.
|
||||
*
|
||||
* \param x The given number.
|
||||
* \return The range of double-precision floats that contain `x`.
|
||||
*/
|
||||
std::pair<double, double> double_interval(const Algebraic& x) const;
|
||||
|
||||
/*! converts a sequence of rational coefficients to an equivalent sequence
|
||||
* of integer coefficients. If the input coefficients are
|
||||
* \f$q(1),\ldots,q(k)\f$, where \f$q(i) = n(i)/d(i)\f$, then the output
|
||||
* coefficients will be of the form:
|
||||
* \f$a(i) = \frac{n(i) \cdot \mathrm{lcm}(d(1),\ldots,d(k))}{d(i) \cdot \mathrm{gcd}(n(1),\ldots, n(k))}\f$.
|
||||
* It inserts the output sequence into an output container given through an
|
||||
* output iterator.
|
||||
*
|
||||
* \param begin The begin iterator of the rational coefficients input
|
||||
* container.
|
||||
* \param end The past-the-end iterator of the rational coefficients input
|
||||
* container.
|
||||
* \param oi The output iterator of the integer coefficients output container.
|
||||
* \return The past-the-end iterator of the output container.
|
||||
*
|
||||
* \pre The value type of `InputIterator` is `Rational`.
|
||||
* \pre Dereferencing `oi` must yield an object convertible to `Integer`.
|
||||
*/
|
||||
template <typename InputIterator, typename OutputIterator>
|
||||
OutputIterator convert_coefficients(InputIterator begin,
|
||||
InputIterator end,
|
||||
OutputIterator oi) const;
|
||||
|
||||
/*! computes the square root of an algebraic number.
|
||||
*
|
||||
* \param x The number.
|
||||
* \return The square root of `x`.
|
||||
* \pre `x` is non-negative.
|
||||
*/
|
||||
Algebraic sqrt(const Algebraic& x) const;
|
||||
|
||||
/*! computes the roots of a quadratic equations \f$a*x^2+ b*x + c = 0\f$
|
||||
* with integer coefficients, and inserts them into an output container given
|
||||
* through an output iterator.
|
||||
*
|
||||
* \param a The coefficient of \f$x^2\f$
|
||||
* \param b The coefficient of \f$x\f$
|
||||
* \param c The free term.
|
||||
* \param oi The output iterator of the output container of real-valued
|
||||
* solutions of the quadratic equation.
|
||||
* \return The past-the-end iterator of the output container.
|
||||
*
|
||||
* \pre Dereferencing `oi` must yield an object convertible to `Algebraic`.
|
||||
*/
|
||||
template <typename NT, typename OutputIterator>
|
||||
OutputIterator solve_quadratic_equation(const NT& a, const NT& b, const NT& c,
|
||||
OutputIterator oi) const;
|
||||
|
||||
/*! constructs a polynomial with integer coefficients.
|
||||
*
|
||||
* \param coeffs The coefficients of the input polynomial.
|
||||
* \param degree The degree of the input polynomial.
|
||||
* \return The polynomial.
|
||||
*/
|
||||
Polynomial construct_polynomial(const Integer* coeffs,
|
||||
unsigned int degree) const;
|
||||
|
||||
/*! constructs a polynomial with integer coefficients given rational
|
||||
* coefficients.
|
||||
*
|
||||
* \param coeffs The coefficients of the input polynomial.
|
||||
* \param degree The degree of the input polynomial.
|
||||
* \param poly Output: The resulting polynomial with integer coefficients.
|
||||
* \param poly_denom Output: The denominator for the polynomial.
|
||||
* \return Whether this polynomial is non-zero (false if the polynomial is
|
||||
* zero).
|
||||
*/
|
||||
bool construct_polynomial(const Rational *coeffs,
|
||||
unsigned int degree,
|
||||
Polynomial& poly, Integer& poly_denom) const;
|
||||
|
||||
/*! constructs two polynomials with integer coefficients such that
|
||||
* \f$P(x)/Q(x)\f$ is a rational function equivalent to the one represented
|
||||
* by the two given vectors of rational coefficients. It is guaranteed that
|
||||
* the GCD of \f$P(x)\f$ and \f$Q(x)\f$ is trivial.
|
||||
*
|
||||
* \param p_coeffs The coefficients of the input numerator polynomial.
|
||||
* \param p_degree The degree of the input numerator polynomial.
|
||||
* \param q_coeffs The coefficients of the input denominator polynomial.
|
||||
* \param q_degree The degree of the input denominator polynomial.
|
||||
* \param p_poly Output: The resulting numerator polynomial with integer
|
||||
* coefficients.
|
||||
* \param q_poly Output: The resulting denominator polynomial with integer
|
||||
* coefficients.
|
||||
* \return `true` on success; `false` if the denominator is 0.
|
||||
*/
|
||||
bool construct_polynomials(const Rational* p_coeffs,
|
||||
unsigned int p_degree,
|
||||
const Rational* q_coeffs,
|
||||
unsigned int q_degree,
|
||||
Polynomial& p_poly, Polynomial& q_poly) const;
|
||||
|
||||
/*! Compute the degree of a polynomial.
|
||||
*/
|
||||
int degree(const Polynomial& poly) const;
|
||||
|
||||
/*! evaluates a polynomial at a given \f$x\f$-value.
|
||||
*
|
||||
* \param poly The polynomial.
|
||||
* \param x The value to evaluate at.
|
||||
* \return The value of the polynomial at `x`.
|
||||
*/
|
||||
template <typename NT>
|
||||
NT evaluate_at(const Polynomial& poly, NT& x) const;
|
||||
|
||||
/*! computes the derivative of the given polynomial.
|
||||
*
|
||||
* \param poly The polynomial \f$p(x)\f$.
|
||||
* \return The derivative \f$p'(x)\f$.
|
||||
*/
|
||||
Polynomial derive(const Polynomial& poly) const;
|
||||
|
||||
/*! multiplies a polynomial by some scalar coefficient.
|
||||
*
|
||||
* \param poly The polynomial \f$P(x)\f$.
|
||||
* \param a The scalar value.
|
||||
* \return The scalar multiplication \f$a \cdot P(x)\f$.
|
||||
*/
|
||||
Polynomial scale(const Polynomial& poly, const Integer& a) const;
|
||||
|
||||
/*! performs "long division" of two polynomials: Given \f$A(x)\f$ and
|
||||
* \f$B(x)\f$ compute two polynomials \f$Q(x)\f$ and \f$R(x)\f$ such that:
|
||||
* \f$A(x) = Q(x) \cdot B(x) + R(x)\f$ and \f$R(x)\f$ has minimal degree.
|
||||
*
|
||||
* \param poly_a The first polynomial \f$A(x)\f$.
|
||||
* \param poly_b The second polynomial \f$A(x)\f$.
|
||||
* \param rem Output: The remainder polynomial \f$R(x)\f$.
|
||||
* \return The quontient polynomial \f$Q(x)\f$.
|
||||
*/
|
||||
Polynomial divide(const Polynomial& poly_a,
|
||||
const Polynomial& poly_b,
|
||||
Polynomial& rem) const;
|
||||
|
||||
/*! computes the real-valued roots of a polynomial with integer coefficients,
|
||||
* and inserts them in ascending order into an output container given through
|
||||
* an output iterator.
|
||||
*
|
||||
* \param poly The input polynomial.
|
||||
* \param oi The output iterator of the output container of real-valued root
|
||||
* of the polynomial.
|
||||
* \return The past-the-end iterator of the output container.
|
||||
*
|
||||
* \pre Dereferencing `oi` must yield an object convertible to `Algebraic`.
|
||||
*/
|
||||
template <typename OutputIterator>
|
||||
OutputIterator compute_polynomial_roots(const Polynomial& poly,
|
||||
OutputIterator oi) const;
|
||||
|
||||
/*! computes the real-valued roots of a polynomial with integer coefficients
|
||||
* within a given interval, and inserts them in ascending order into an output
|
||||
* container given through an output iterator.
|
||||
*
|
||||
* \param poly The input polynomial.
|
||||
* \param x_min The left bound of the interval.
|
||||
* \param x_max The right bound of the interval.
|
||||
* \param oi The output iterator of the output container of the real-valued
|
||||
* root of the polynomial.
|
||||
* \return The past-the-end iterator of the output container.
|
||||
*
|
||||
* \pre Dereferencing `oi` must yield an object convertible to `Algebraic`.
|
||||
*/
|
||||
template <typename OutputIterator>
|
||||
OutputIterator compute_polynomial_roots(const Polynomial& poly,
|
||||
double x_min, double x_max,
|
||||
OutputIterator oi) const;
|
||||
/// @}
|
||||
};
|
||||
|
||||
} /* end namespace CGAL */
|
||||
|
|
@ -16,26 +16,33 @@ public:
|
|||
/// A model of this concept must provide:
|
||||
/// @{
|
||||
|
||||
/*! computes the intersections of `xc1` and `xc2` and writes them <I>in an
|
||||
* ascending lexicographic \f$xy\f$-order</I> into a range beginning at
|
||||
* `oi`. The type `OutputIterator` must dereference a polymorphic object of
|
||||
* type `std::variant` that wraps objects of type either type
|
||||
* `pair<ArrTraits::Point_2, ArrTraits::Multiplicity>` or
|
||||
* `ArrTraits::X_monotone_curve_2`. An object of the former type represents an
|
||||
* intersection point with its multiplicity (in case the multiplicity is
|
||||
* undefined or unknown, it should be set to \f$0\f$). An object of the latter
|
||||
* type represents an overlapping subcurve of `xc1` and `xc2`. The operator
|
||||
* returns a past-the-end iterator of the destination range.
|
||||
/*! computes the intersections of two \f$x\f$-monotone curves and inserts the
|
||||
* result in ascending \f$xy\f$-lexicographic order into an output container
|
||||
* given through an output iterator. An intersection, if exists, is
|
||||
* represented by a discriminated union container that holds either an
|
||||
* intersection point along with its multiplicity or an overlapping
|
||||
* \f$x\f$-monotone subcurve. If the multiplicity is undefined or unknown, it
|
||||
* should be set to \f$0\f$.
|
||||
*
|
||||
* A special case may occur when the parameter space of the surface, the
|
||||
* arrangement is embedded on, is identified on the left and right sides of
|
||||
* the boundary. An intersection point that lies on the identification curve,
|
||||
* \param xc1 The first \f$x\f$-monotone curve.
|
||||
* \param xc2 The second \f$x\f$-monotone curve.
|
||||
* \param oi The output iterator that points at the output container.
|
||||
* \return The past-the-end iterator of the output container.
|
||||
*
|
||||
* A special case may occur when the left and right sides of the boundary of
|
||||
* the parameter space of the surface, the arrangement is embedded on, are
|
||||
* identified. An intersection point that lies on the identification curve,
|
||||
* between two \f$x\f$-monotone curves that intersect at their left and right
|
||||
* ends must be ignored. Consider two \f$x\f$-monotone curves that intersect
|
||||
* at their left and right ends, respectively, at a point \f$p\f$ that lies on
|
||||
* the identification curve. If, for example, the number of intersections
|
||||
* between these two curves is greater than 1, the order of intersections is
|
||||
* non-deterministic.
|
||||
* nondeterministic.
|
||||
*
|
||||
* \pre Dereferencing `oi` must yield an object of type
|
||||
* `std::optional<std::variant<std::pair<%Point_2,ArrangementXMonotoneTraits_2::Multiplicity,X_monotone_curve_2>>`,
|
||||
* where `%Point_2` is a model of `ArrTraits::Point_2` and
|
||||
* `X_monotone_curve_2` is a model of `ArrTraits::XMonotoneCurve_2`.
|
||||
*/
|
||||
template <typename OutputIterator>
|
||||
OutputIterator operator()(ArrTraits::X_monotone_curve_2 xc1,
|
||||
|
|
|
|||
|
|
@ -15,12 +15,20 @@ public:
|
|||
/// A model of this concept must provide:
|
||||
/// @{
|
||||
|
||||
/*! subdivides the input curve `c` into \f$x\f$-monotone subcurves and
|
||||
* isolated points, and inserts the results into a range beginning at the given
|
||||
* output iterator `oi`. The type `OutputIterator` dereferences a
|
||||
* `std::variant` that wraps either an `ArrTraits::Point_2` object or an
|
||||
* `ArrTraits::X_monotone_curve_2` object. The operator returns a past-the-end
|
||||
* iterator for the output sequence.
|
||||
/*! subdivides an input curve into \f$x\f$-monotone subcurves and isolated
|
||||
* points, and inserts the results into an output container given through an
|
||||
* output iterator. An object in the output container is represented by a
|
||||
* discriminated union container that holds either a point or an
|
||||
* \f$x\f$-monotone curve.
|
||||
*
|
||||
* \param c The input curve.
|
||||
* \param oi The output iterator that points at the output container.
|
||||
* \return The past-the-end iterator of the output container.
|
||||
*
|
||||
* \pre Dereferencing `oi` must yield a polymorphic object of type
|
||||
* `std::variant<%Point_2, X_monotone_curve_2>`, where `%Point_2` is a model
|
||||
* of `ArrTraits::Point_2` and `X_monotone_curve_2` is a model of
|
||||
* `ArrTraits::XMonotoneCurve_2`.
|
||||
*/
|
||||
template <typename OutputIterator>
|
||||
OutputIterator operator()(ArrTraits::Curve_2 c, OutputIterator oi);
|
||||
|
|
|
|||
|
|
@ -236,6 +236,7 @@ implemented as peripheral classes or as free (global) functions.
|
|||
- `CGAL::Arr_bounded_planar_topology_traits_2<GeometryTraits_2,Dcel>`
|
||||
- `CGAL::Arr_unb_planar_topology_traits_2<GeometryTraits_2,Dcel>`
|
||||
- `CGAL::Arr_spherical_topology_traits_2<GeometryTraits_2,Dcel>`
|
||||
- `CGAL::CORE_algebraic_number_traits`
|
||||
|
||||
\cgalCRPSection{Functions}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ int main() {
|
|||
Point(1, 4), Point(4, 3), Point(6, 3), Point(3, 2), Point(5, 2), Point(1, 0)
|
||||
};
|
||||
std::list<Query_result> results;
|
||||
locate(arr, points.begin(), points.end(), std::back_inserter(results));
|
||||
CGAL::locate(arr, points.begin(), points.end(), std::back_inserter(results));
|
||||
|
||||
// Print the results.
|
||||
for (auto it = results.begin(); it != results.end(); ++it)
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -28,8 +28,7 @@ namespace CGAL {
|
|||
//
|
||||
template <typename Arrangement, typename ZoneVisitor>
|
||||
void Arrangement_zone_2<Arrangement, ZoneVisitor>::
|
||||
init_with_hint(const X_monotone_curve_2& cv, Pl_result_type obj)
|
||||
{
|
||||
init_with_hint(const X_monotone_curve_2& cv, Pl_result_type obj) {
|
||||
#if defined(ARR_ZONE_VERBOSE)
|
||||
std::cout << "init_with_hint()" << std::endl;
|
||||
#endif
|
||||
|
|
@ -80,8 +79,7 @@ init_with_hint(const X_monotone_curve_2& cv, Pl_result_type obj)
|
|||
// notifications for the visitor.
|
||||
//
|
||||
template <typename Arrangement, typename ZoneVisitor>
|
||||
void Arrangement_zone_2<Arrangement, ZoneVisitor>::compute_zone()
|
||||
{
|
||||
void Arrangement_zone_2<Arrangement, ZoneVisitor>::compute_zone() {
|
||||
#if defined(ARR_ZONE_VERBOSE)
|
||||
std::cout << "compute_zone()" << std::endl;
|
||||
#endif
|
||||
|
|
@ -137,7 +135,7 @@ void Arrangement_zone_2<Arrangement, ZoneVisitor>::compute_zone()
|
|||
if (m_found_overlap) {
|
||||
// In this case m_cv overlaps the curve associated with m_intersect_he.
|
||||
// Compute the overlapping subcurve.
|
||||
bool dummy;
|
||||
Arr_parameter_space dummy;
|
||||
auto obj = _compute_next_intersection(m_intersect_he, false, dummy);
|
||||
m_overlap_cv = std::get<X_monotone_curve_2>(*obj);
|
||||
|
||||
|
|
@ -153,7 +151,7 @@ void Arrangement_zone_2<Arrangement, ZoneVisitor>::compute_zone()
|
|||
// overlaps the curve associated with this edge.
|
||||
m_intersect_he = m_arr.non_const_handle(*hh);
|
||||
|
||||
bool dummy;
|
||||
Arr_parameter_space dummy;
|
||||
auto obj = _compute_next_intersection(m_intersect_he, false, dummy);
|
||||
m_overlap_cv = std::get<X_monotone_curve_2>(*obj);
|
||||
|
||||
|
|
@ -211,7 +209,7 @@ void Arrangement_zone_2<Arrangement, ZoneVisitor>::compute_zone()
|
|||
if (m_found_overlap) {
|
||||
// In this case m_cv overlaps the curve associated with m_intersect_he.
|
||||
// Compute the overlapping subcurve to the right of curr_v.
|
||||
bool dummy;
|
||||
Arr_parameter_space dummy;
|
||||
auto obj = _compute_next_intersection(m_intersect_he, false, dummy);
|
||||
m_overlap_cv = std::get<X_monotone_curve_2>(*obj);
|
||||
|
||||
|
|
@ -253,8 +251,7 @@ template <typename Arrangement, typename ZoneVisitor>
|
|||
bool Arrangement_zone_2<Arrangement, ZoneVisitor>::
|
||||
do_overlap_impl(const X_monotone_curve_2& cv1,
|
||||
const X_monotone_curve_2& cv2,
|
||||
const Point_2& p, Arr_not_all_sides_oblivious_tag) const
|
||||
{
|
||||
const Point_2& p, Arr_not_all_sides_oblivious_tag) const {
|
||||
typename Traits_adaptor_2::Compare_y_at_x_right_2 cmp_right =
|
||||
m_geom_traits->compare_y_at_x_right_2_object();
|
||||
|
||||
|
|
@ -307,8 +304,7 @@ do_overlap_impl(const X_monotone_curve_2& cv1,
|
|||
//
|
||||
template <typename Arrangement, typename ZoneVisitor>
|
||||
bool Arrangement_zone_2<Arrangement, ZoneVisitor>::
|
||||
_find_prev_around_vertex(Vertex_handle v, Halfedge_handle& he)
|
||||
{
|
||||
_find_prev_around_vertex(Vertex_handle v, Halfedge_handle& he) {
|
||||
#if defined(ARR_ZONE_VERBOSE)
|
||||
std::cout << "_find_prev_around_vertex(" << v->point() << ")" << std::endl;
|
||||
#endif
|
||||
|
|
@ -393,8 +389,7 @@ typename Arrangement_zone_2<Arrangement, ZoneVisitor>::Halfedge_handle
|
|||
Arrangement_zone_2<Arrangement, ZoneVisitor>::
|
||||
_direct_intersecting_edge_to_right(const X_monotone_curve_2& cv_ins,
|
||||
const Point_2& cv_left_pt,
|
||||
Halfedge_handle query_he)
|
||||
{
|
||||
Halfedge_handle query_he) {
|
||||
#if defined(ARR_ZONE_VERBOSE)
|
||||
std::cout << "_direct_intersecting_edge_to_right() " << cv_left_pt
|
||||
<< std::endl;
|
||||
|
|
@ -446,8 +441,7 @@ template <typename Arrangement, typename ZoneVisitor>
|
|||
typename Arrangement_zone_2<Arrangement, ZoneVisitor>::Halfedge_handle
|
||||
Arrangement_zone_2<Arrangement, ZoneVisitor>::
|
||||
_direct_intersecting_edge_to_left(const X_monotone_curve_2& cv_ins,
|
||||
Halfedge_handle query_he)
|
||||
{
|
||||
Halfedge_handle query_he) {
|
||||
#if defined(ARR_ZONE_VERBOSE)
|
||||
std::cout << "_direct_intersecting_edge_to_left()" << std::endl;
|
||||
#endif
|
||||
|
|
@ -505,6 +499,74 @@ _direct_intersecting_edge_to_left(const X_monotone_curve_2& cv_ins,
|
|||
}
|
||||
}
|
||||
|
||||
//! Implementation for no boundary conditions.
|
||||
template <typename Arrangement, typename ZoneVisitor>
|
||||
bool Arrangement_zone_2<Arrangement, ZoneVisitor>::
|
||||
is_intersection_valid_impl(const Point_2& ip,
|
||||
Arr_parameter_space& /* intersection_location */,
|
||||
Arr_all_sides_oblivious_tag) const
|
||||
{ return (m_geom_traits->compare_xy_2_object()(ip, m_left_pt) == LARGER); }
|
||||
|
||||
//! Implementation for left and right identified boundaries.
|
||||
template <typename Arrangement, typename ZoneVisitor>
|
||||
bool Arrangement_zone_2<Arrangement, ZoneVisitor>::
|
||||
is_intersection_valid_impl(const Point_2& ip,
|
||||
Arr_parameter_space& intersection_location,
|
||||
Arr_has_identified_side_tag) const {
|
||||
auto equal = m_geom_traits->equal_2_object();
|
||||
auto is_on_y_ident = m_geom_traits->is_on_y_identification_2_object();
|
||||
// Case 1: the curve lies on the y-identification
|
||||
if (is_on_y_ident(m_cv)) {
|
||||
if (equal(ip, m_left_pt)) return false;
|
||||
// We set the location to be on the left as a convention
|
||||
intersection_location = ARR_LEFT_BOUNDARY;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Case 2: The left-end lies on the left boundary
|
||||
// (It cannot lie on the right boundary)
|
||||
// If the intersection point is not equal to the left-end, it must lie to
|
||||
// its right; thus valid.
|
||||
if (m_left_on_boundary) return ! equal(ip, m_left_pt);
|
||||
|
||||
// Case 3: The right-end lies on the right boundary
|
||||
if (m_right_on_boundary && equal(ip, m_right_pt)) {
|
||||
intersection_location = ARR_RIGHT_BOUNDARY;
|
||||
return true;
|
||||
}
|
||||
|
||||
// We have a simple intersection point;
|
||||
// make sure it lies to the right of m_left_pt.
|
||||
return (m_geom_traits->compare_xy_2_object()(ip, m_left_pt) == LARGER);
|
||||
}
|
||||
|
||||
/*! Implementation for all the rest.
|
||||
* It would be better to split into the various cases, which is the cartesian
|
||||
* product of (contructed, closed, open) X (contructed, closed, open)
|
||||
*/
|
||||
template <typename Arrangement, typename ZoneVisitor>
|
||||
bool Arrangement_zone_2<Arrangement, ZoneVisitor>::
|
||||
is_intersection_valid_impl(const Point_2& ip,
|
||||
Arr_parameter_space& intersection_location,
|
||||
Arr_boundary_cond_tag) const {
|
||||
auto equal = m_geom_traits->equal_2_object();
|
||||
if (m_left_on_boundary) {
|
||||
// The left-end lies on the left boundary. If the intersection point is not
|
||||
// equal to the left-end, the intersection is valid, because it must lie to
|
||||
// its right.
|
||||
if (m_has_left_pt) return ! equal(ip, m_left_pt);
|
||||
else return true;
|
||||
}
|
||||
if (m_has_right_pt && m_right_on_boundary && equal(ip, m_right_pt)) {
|
||||
intersection_location = ARR_RIGHT_BOUNDARY;
|
||||
return true;
|
||||
}
|
||||
|
||||
// We have a simple intersection point;
|
||||
// make sure it lies to the right of m_left_pt.
|
||||
return (m_geom_traits->compare_xy_2_object()(ip, m_left_pt) == LARGER);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Get the next intersection of cv with the given halfedge.
|
||||
//
|
||||
|
|
@ -513,14 +575,12 @@ typename Arrangement_zone_2<Arrangement, ZoneVisitor>::Optional_intersection
|
|||
Arrangement_zone_2<Arrangement, ZoneVisitor>::
|
||||
_compute_next_intersection(Halfedge_handle he,
|
||||
bool skip_first_point,
|
||||
bool& intersection_on_right_boundary)
|
||||
{
|
||||
Arr_parameter_space& intersection_location) {
|
||||
#if defined(ARR_ZONE_VERBOSE)
|
||||
std::cout << "_compute_next_intersection(" << he->curve() << ", "
|
||||
<< skip_first_point << ")" << std::endl;
|
||||
#endif
|
||||
|
||||
auto equal = m_geom_traits->equal_2_object();
|
||||
auto compare_xy = m_geom_traits->compare_xy_2_object();
|
||||
auto ctr_min = m_geom_traits->construct_min_vertex_2_object();
|
||||
auto is_closed = m_geom_traits->is_closed_2_object();
|
||||
|
|
@ -529,12 +589,12 @@ _compute_next_intersection(Halfedge_handle he,
|
|||
const X_monotone_curve_2* p_curve = &(he->curve());
|
||||
|
||||
// Try to locate the intersections with this curve in the intersections map.
|
||||
Intersect_map_iterator iter = m_inter_map.find(p_curve);
|
||||
auto iter = m_inter_map.find(p_curve);
|
||||
const Intersection_point* ip;
|
||||
const X_monotone_curve_2* icv;
|
||||
bool valid_intersection;
|
||||
|
||||
intersection_on_right_boundary = false;
|
||||
intersection_location = ARR_INTERIOR;
|
||||
if (iter != m_inter_map.end()) {
|
||||
// The intersections with the curve have already been computed.
|
||||
// Retrieve the intersections list from the map.
|
||||
|
|
@ -548,25 +608,9 @@ _compute_next_intersection(Halfedge_handle he,
|
|||
// Compare that current object with m_left_pt (if exists).
|
||||
ip = std::get_if<Intersection_point>(&(inter_list.front()));
|
||||
if (ip != nullptr) {
|
||||
// We have an intersection point
|
||||
if (m_left_on_boundary) {
|
||||
// The left-end lies on the left boundary. If the intersection point
|
||||
// is not equal to the left-end, the intersection is valid, because
|
||||
// it must lie to its right.
|
||||
if (m_has_left_pt) valid_intersection = ! equal(ip->first, m_left_pt);
|
||||
else valid_intersection = true;
|
||||
}
|
||||
else if (m_has_right_pt && m_right_on_boundary &&
|
||||
equal(ip->first, m_right_pt))
|
||||
{
|
||||
valid_intersection = true;
|
||||
intersection_on_right_boundary = true;
|
||||
}
|
||||
else {
|
||||
// We have a simple intersection point - make sure it lies to the
|
||||
// right of m_left_pt.
|
||||
valid_intersection = (compare_xy(ip->first, m_left_pt) == LARGER);
|
||||
}
|
||||
// We have an intersection point -
|
||||
valid_intersection =
|
||||
is_intersection_valid(ip->first, intersection_location);
|
||||
}
|
||||
else {
|
||||
// We have an overlapping subcurve.
|
||||
|
|
@ -576,7 +620,8 @@ _compute_next_intersection(Halfedge_handle he,
|
|||
if (is_closed(*icv, ARR_MIN_END)) {
|
||||
// The curve has a valid left point - make sure it lies to the
|
||||
// right of m_left_pt.
|
||||
valid_intersection = (compare_xy(ctr_min(*icv), m_left_pt) != SMALLER);
|
||||
valid_intersection =
|
||||
(compare_xy(ctr_min(*icv), m_left_pt) != SMALLER);
|
||||
}
|
||||
// In this case the overlap is not valid.
|
||||
else valid_intersection = false;
|
||||
|
|
@ -613,23 +658,8 @@ _compute_next_intersection(Halfedge_handle he,
|
|||
if (ip != nullptr) {
|
||||
// We have an intersection point -
|
||||
// Check whether we need to skip the first intersection
|
||||
if (is_first && skip_first_point) valid_intersection = false;
|
||||
else if (m_left_on_boundary) {
|
||||
// The left-end lies on the left boundary. If the intersection point
|
||||
// is not equal to the left-end, the intersection is valid, because
|
||||
// it must lie to its right.
|
||||
if (m_has_left_pt) valid_intersection = ! equal(ip->first, m_left_pt);
|
||||
else valid_intersection = true;
|
||||
}
|
||||
else if (m_right_on_boundary && m_has_right_pt &&
|
||||
equal(ip->first, m_right_pt))
|
||||
{
|
||||
valid_intersection = true;
|
||||
intersection_on_right_boundary = true;
|
||||
}
|
||||
else {
|
||||
valid_intersection = (compare_xy(ip->first, m_left_pt) == LARGER);
|
||||
}
|
||||
valid_intersection = (is_first && skip_first_point) ? false :
|
||||
is_intersection_valid(ip->first, intersection_location);
|
||||
}
|
||||
else if (m_left_on_boundary) {
|
||||
// The left end is on the boundary, so all overlapping curves are valid,
|
||||
|
|
@ -671,13 +701,12 @@ _compute_next_intersection(Halfedge_handle he,
|
|||
//
|
||||
template <typename Arrangement, typename ZoneVisitor>
|
||||
void Arrangement_zone_2<Arrangement, ZoneVisitor>::
|
||||
_remove_next_intersection(Halfedge_handle he)
|
||||
{
|
||||
_remove_next_intersection(Halfedge_handle he) {
|
||||
// Get a pointer to the curve associated with the halfedge.
|
||||
const X_monotone_curve_2* p_curve = &(he->curve());
|
||||
|
||||
// Locate the intersections with this curve in the intersections map.
|
||||
Intersect_map_iterator iter = m_inter_map.find(p_curve);
|
||||
auto iter = m_inter_map.find(p_curve);
|
||||
|
||||
CGAL_assertion(iter != m_inter_map.end());
|
||||
CGAL_assertion(! iter->second.empty());
|
||||
|
|
@ -692,8 +721,7 @@ _remove_next_intersection(Halfedge_handle he)
|
|||
template <typename Arrangement, typename ZoneVisitor>
|
||||
bool Arrangement_zone_2<Arrangement, ZoneVisitor>::
|
||||
_is_to_left_impl(const Point_2& p, Halfedge_handle he,
|
||||
Arr_not_all_sides_oblivious_tag) const
|
||||
{
|
||||
Arr_not_all_sides_oblivious_tag) const {
|
||||
#if defined(ARR_ZONE_VERBOSE)
|
||||
std::cout << "_is_to_left_impl(" << p << "," << he->curve() << ")"
|
||||
<< std::endl;
|
||||
|
|
@ -708,12 +736,12 @@ _is_to_left_impl(const Point_2& p, Halfedge_handle he,
|
|||
if (ps_x_min == ARR_LEFT_BOUNDARY) return false;
|
||||
|
||||
auto ps_in_y = m_geom_traits->parameter_space_in_y_2_object();
|
||||
auto ps_y = ps_in_y(he->curve(), ARR_MIN_END);
|
||||
if (ps_y != ARR_INTERIOR) {
|
||||
auto ps_y_min = ps_in_y(he->curve(), ARR_MIN_END);
|
||||
if (ps_y_min != ARR_INTERIOR) {
|
||||
// Check if p is to the left of the minimal curve-end:
|
||||
auto cmp_x = m_geom_traits->compare_x_point_curve_end_2_object();
|
||||
const auto res = cmp_x(p, he->curve(), ARR_MIN_END);
|
||||
return ((res == SMALLER) || (res == EQUAL && ps_y == ARR_TOP_BOUNDARY));
|
||||
return ((res == SMALLER) || (res == EQUAL && ps_y_min == ARR_TOP_BOUNDARY));
|
||||
}
|
||||
|
||||
// In case the minimal curve-end does not have boundary conditions, simply
|
||||
|
|
@ -724,13 +752,13 @@ _is_to_left_impl(const Point_2& p, Halfedge_handle he,
|
|||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Determine whether a given point lies completely to the right of a given curve.
|
||||
// Determine whether a given point lies completely to the right of a given
|
||||
// curve.
|
||||
//
|
||||
template <typename Arrangement, typename ZoneVisitor>
|
||||
bool Arrangement_zone_2<Arrangement, ZoneVisitor>::
|
||||
_is_to_right_impl(const Point_2& p, Halfedge_handle he,
|
||||
Arr_not_all_sides_oblivious_tag) const
|
||||
{
|
||||
Arr_not_all_sides_oblivious_tag) const {
|
||||
#if defined(ARR_ZONE_VERBOSE)
|
||||
std::cout << "_is_to_right_impl(" << p << "," << he->curve() << ")"
|
||||
<< std::endl;
|
||||
|
|
@ -747,12 +775,12 @@ _is_to_right_impl(const Point_2& p, Halfedge_handle he,
|
|||
if (ps_x_max == ARR_LEFT_BOUNDARY) return true;
|
||||
|
||||
auto ps_in_y = m_geom_traits->parameter_space_in_y_2_object();
|
||||
auto ps_y = ps_in_y(he->curve(), ARR_MAX_END);
|
||||
if (ps_y != ARR_INTERIOR) {
|
||||
auto ps_y_max = ps_in_y(he->curve(), ARR_MAX_END);
|
||||
if (ps_y_max != ARR_INTERIOR) {
|
||||
// Check if p is to the right of the maximal curve-end:
|
||||
auto cmp_x = m_geom_traits->compare_x_point_curve_end_2_object();
|
||||
auto res = cmp_x(p, he->curve(), ARR_MAX_END);
|
||||
return ((res == LARGER) || (res == EQUAL && ps_y == ARR_BOTTOM_BOUNDARY));
|
||||
return ((res == LARGER) || (res == EQUAL && ps_y_max == ARR_BOTTOM_BOUNDARY));
|
||||
}
|
||||
|
||||
// In case the maximal curve-end does not have boundary conditions, simply
|
||||
|
|
@ -768,8 +796,7 @@ _is_to_right_impl(const Point_2& p, Halfedge_handle he,
|
|||
template <typename Arrangement, typename ZoneVisitor>
|
||||
void Arrangement_zone_2<Arrangement, ZoneVisitor>::
|
||||
_leftmost_intersection(Ccb_halfedge_circulator he_curr, bool on_boundary,
|
||||
bool& leftmost_on_right_boundary)
|
||||
{
|
||||
Arr_parameter_space& leftmost_location) {
|
||||
#if defined(ARR_ZONE_VERBOSE)
|
||||
std::cout << "_leftmost_intersection(" << he_curr->curve() << ", "
|
||||
<< on_boundary << ")" << std::endl;
|
||||
|
|
@ -793,7 +820,7 @@ _leftmost_intersection(Ccb_halfedge_circulator he_curr, bool on_boundary,
|
|||
// entirely to the right of m_intersect_p, its intersection with m_cv (if any)
|
||||
// cannot lie to the left of this point. We therefore do not need to compute
|
||||
// this intersection.
|
||||
if (m_found_intersect && ! leftmost_on_right_boundary &&
|
||||
if (m_found_intersect && (leftmost_location == ARR_INTERIOR) &&
|
||||
_is_to_left(m_intersect_p, he_curr))
|
||||
return;
|
||||
|
||||
|
|
@ -821,13 +848,14 @@ _leftmost_intersection(Ccb_halfedge_circulator he_curr, bool on_boundary,
|
|||
// do not intersect.
|
||||
if (! left_equals_curr_endpoint &&
|
||||
((! m_left_on_boundary && _is_to_right(m_left_pt, he_curr)) ||
|
||||
! is_in_x_range(m_cv, he_curr->curve())))
|
||||
! is_in_x_range(m_cv, he_curr->curve()))) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Compute the next intersection of m_cv and the current halfedge.
|
||||
bool intersection_on_right_boundary;
|
||||
Arr_parameter_space intersection_location;
|
||||
auto iobj = _compute_next_intersection(he_curr, left_equals_curr_endpoint,
|
||||
intersection_on_right_boundary);
|
||||
intersection_location);
|
||||
|
||||
if (iobj) {
|
||||
// We have found an intersection (either a simple point or an
|
||||
|
|
@ -839,8 +867,8 @@ _leftmost_intersection(Ccb_halfedge_circulator he_curr, bool on_boundary,
|
|||
// Found a simple intersection point. Check if it is the leftmost
|
||||
// intersection point so far.
|
||||
if (! m_found_intersect ||
|
||||
(! intersection_on_right_boundary &&
|
||||
(leftmost_on_right_boundary ||
|
||||
((intersection_location != ARR_RIGHT_BOUNDARY) &&
|
||||
((leftmost_location == ARR_RIGHT_BOUNDARY) ||
|
||||
compare_xy(ip, m_intersect_p) == SMALLER)))
|
||||
{
|
||||
// Store the leftmost intersection point and the halfedge handle.
|
||||
|
|
@ -848,7 +876,7 @@ _leftmost_intersection(Ccb_halfedge_circulator he_curr, bool on_boundary,
|
|||
m_ip_multiplicity = int_p->second;
|
||||
m_intersect_he = he_curr;
|
||||
m_found_overlap = false;
|
||||
leftmost_on_right_boundary = intersection_on_right_boundary;
|
||||
leftmost_location = intersection_location;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
@ -880,8 +908,7 @@ _leftmost_intersection(Ccb_halfedge_circulator he_curr, bool on_boundary,
|
|||
//
|
||||
template <typename Arrangement, typename ZoneVisitor>
|
||||
void Arrangement_zone_2<Arrangement, ZoneVisitor>::
|
||||
_leftmost_intersection_with_face_boundary(Face_handle face, bool on_boundary)
|
||||
{
|
||||
_leftmost_intersection_with_face_boundary(Face_handle face, bool on_boundary) {
|
||||
#if defined(ARR_ZONE_VERBOSE)
|
||||
std::cout << "_leftmost_intersection_with_face_boundary(" << on_boundary
|
||||
<< ")" << std::endl;
|
||||
|
|
@ -895,25 +922,23 @@ _leftmost_intersection_with_face_boundary(Face_handle face, bool on_boundary)
|
|||
auto compare_xy = m_geom_traits->compare_xy_2_object();
|
||||
auto is_in_x_range = m_geom_traits->is_in_x_range_2_object();
|
||||
|
||||
bool leftmost_on_right_boundary = false;
|
||||
Arr_parameter_space leftmost_location = ARR_INTERIOR;
|
||||
|
||||
// Traverse the face outer-boundaries; iterate through all outer CCBs.
|
||||
for (auto occb_it = face->outer_ccbs_begin();
|
||||
occb_it != face->outer_ccbs_end(); ++occb_it)
|
||||
{
|
||||
occb_it != face->outer_ccbs_end(); ++occb_it) {
|
||||
Ccb_halfedge_circulator he_first = *occb_it;
|
||||
Ccb_halfedge_circulator he_curr = he_first;
|
||||
do _leftmost_intersection(he_curr, on_boundary, leftmost_on_right_boundary);
|
||||
do _leftmost_intersection(he_curr, on_boundary, leftmost_location);
|
||||
while (++he_curr != he_first);
|
||||
}
|
||||
|
||||
// Traverse the face inner-boundaries; iterate through all inner CCBs (holes).
|
||||
for (auto iccb_it = face->inner_ccbs_begin();
|
||||
iccb_it != face->inner_ccbs_end(); ++iccb_it)
|
||||
{
|
||||
iccb_it != face->inner_ccbs_end(); ++iccb_it) {
|
||||
Ccb_halfedge_circulator he_first = *iccb_it;
|
||||
Ccb_halfedge_circulator he_curr = he_first;
|
||||
do _leftmost_intersection(he_curr, on_boundary, leftmost_on_right_boundary);
|
||||
do _leftmost_intersection(he_curr, on_boundary, leftmost_location);
|
||||
while (++he_curr != he_first);
|
||||
}
|
||||
|
||||
|
|
@ -921,17 +946,17 @@ _leftmost_intersection_with_face_boundary(Face_handle face, bool on_boundary)
|
|||
|
||||
// Traverse the isolated vertices inside the face (if there exist any), and
|
||||
// check whether an isolated vertex lies on the curve.
|
||||
typedef typename Arrangement_2::Isolated_vertex_iterator
|
||||
Isolated_vertex_iterator;
|
||||
for (Isolated_vertex_iterator iv_it = face->isolated_vertices_begin();
|
||||
iv_it != face->isolated_vertices_end(); ++iv_it)
|
||||
{
|
||||
// MSVC17 requires an explicit (non-const) type for the iterator.
|
||||
typename Arrangement_2::Isolated_vertex_iterator iv_it;
|
||||
for (iv_it = face->isolated_vertices_begin();
|
||||
iv_it != face->isolated_vertices_end(); ++iv_it) {
|
||||
// If the isolated vertex is not in the x-range of our curve, disregard it.
|
||||
if (! is_in_x_range(m_cv, iv_it->point())) continue;
|
||||
|
||||
// If we already have an intersection point, compare it to the current
|
||||
// isolated vertex, in order to filter unnecessary computations.
|
||||
if (m_found_intersect && compare_xy(iv_it->point(), m_intersect_p) == LARGER)
|
||||
if (m_found_intersect &&
|
||||
(compare_xy(iv_it->point(), m_intersect_p) == LARGER))
|
||||
continue;
|
||||
|
||||
// In case the isolated vertex lies on the curve, update the intersection
|
||||
|
|
@ -960,8 +985,7 @@ _leftmost_intersection_with_face_boundary(Face_handle face, bool on_boundary)
|
|||
//
|
||||
template <typename Arrangement, typename ZoneVisitor>
|
||||
bool Arrangement_zone_2<Arrangement, ZoneVisitor>::
|
||||
_zone_in_face(Face_handle face, bool on_boundary)
|
||||
{
|
||||
_zone_in_face(Face_handle face, bool on_boundary) {
|
||||
#if defined(ARR_ZONE_VERBOSE)
|
||||
std::cout << "_zone_in_face(" << on_boundary << ")" << std::endl;
|
||||
#endif
|
||||
|
|
@ -1095,7 +1119,7 @@ _zone_in_face(Face_handle face, bool on_boundary)
|
|||
// Associate the intersection list of the original curve with the
|
||||
// right subcurve, while we can associate an empty list with the
|
||||
// left subcurve, as we are now done with it.
|
||||
Intersect_map_iterator iter = m_inter_map.find(p_orig_curve);
|
||||
auto iter = m_inter_map.find(p_orig_curve);
|
||||
Intersect_list empty_inter_list;
|
||||
|
||||
m_inter_map[p_right_subcurve] = iter->second;
|
||||
|
|
@ -1190,8 +1214,7 @@ _zone_in_face(Face_handle face, bool on_boundary)
|
|||
// curve currently associated with m_intersect_he.
|
||||
//
|
||||
template <typename Arrangement, typename ZoneVisitor>
|
||||
bool Arrangement_zone_2<Arrangement, ZoneVisitor>::_zone_in_overlap()
|
||||
{
|
||||
bool Arrangement_zone_2<Arrangement, ZoneVisitor>::_zone_in_overlap() {
|
||||
#if defined(ARR_ZONE_VERBOSE)
|
||||
std::cout << "_zone_in_overlap()" << std::endl;
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -55,65 +55,68 @@ namespace CGAL {
|
|||
template <typename Arrangement_, typename ZoneVisitor_>
|
||||
class Arrangement_zone_2 {
|
||||
public:
|
||||
typedef Arrangement_ Arrangement_2;
|
||||
typedef typename Arrangement_2::Geometry_traits_2 Geometry_traits_2;
|
||||
typedef typename Arrangement_2::Topology_traits Topology_traits;
|
||||
using Arrangement_2 = Arrangement_;
|
||||
using Geometry_traits_2 = typename Arrangement_2::Geometry_traits_2;
|
||||
using Topology_traits = typename Arrangement_2::Topology_traits;
|
||||
|
||||
protected:
|
||||
typedef Arr_traits_adaptor_2<Geometry_traits_2> Traits_adaptor_2;
|
||||
using Traits_adaptor_2 = Arr_traits_adaptor_2<Geometry_traits_2>;
|
||||
|
||||
typedef typename Traits_adaptor_2::Left_side_category Left_side_category;
|
||||
typedef typename Traits_adaptor_2::Bottom_side_category Bottom_side_category;
|
||||
typedef typename Traits_adaptor_2::Top_side_category Top_side_category;
|
||||
typedef typename Traits_adaptor_2::Right_side_category Right_side_category;
|
||||
using Left_side_category = typename Traits_adaptor_2::Left_side_category;
|
||||
using Bottom_side_category = typename Traits_adaptor_2::Bottom_side_category;
|
||||
using Top_side_category = typename Traits_adaptor_2::Top_side_category;
|
||||
using Right_side_category = typename Traits_adaptor_2::Right_side_category;
|
||||
|
||||
static_assert(Arr_sane_identified_tagging<Left_side_category,
|
||||
Bottom_side_category,
|
||||
Bottom_side_category,
|
||||
Top_side_category,
|
||||
Right_side_category>::value);
|
||||
// Categories for dispatching
|
||||
using Are_all_sides_oblivious_category =
|
||||
typename Arr_all_sides_oblivious_category<Left_side_category,
|
||||
Bottom_side_category,
|
||||
Top_side_category,
|
||||
Right_side_category>::result;
|
||||
|
||||
using Left_or_right_sides_category =
|
||||
typename Arr_two_sides_category<Left_side_category,
|
||||
Right_side_category>::result;
|
||||
|
||||
public:
|
||||
typedef ZoneVisitor_ Visitor;
|
||||
using Visitor = ZoneVisitor_;
|
||||
|
||||
typedef typename Arrangement_2::Vertex_handle Vertex_handle;
|
||||
typedef typename Arrangement_2::Halfedge_handle Halfedge_handle;
|
||||
typedef typename Arrangement_2::Face_handle Face_handle;
|
||||
using Vertex_handle = typename Arrangement_2::Vertex_handle;
|
||||
using Halfedge_handle = typename Arrangement_2::Halfedge_handle;
|
||||
using Face_handle = typename Arrangement_2::Face_handle;
|
||||
|
||||
typedef std::pair<Halfedge_handle, bool> Visitor_result;
|
||||
using Visitor_result = std::pair<Halfedge_handle, bool>;
|
||||
|
||||
typedef typename Geometry_traits_2::Point_2 Point_2;
|
||||
typedef typename Geometry_traits_2::X_monotone_curve_2 X_monotone_curve_2;
|
||||
typedef typename Geometry_traits_2::Multiplicity Multiplicity;
|
||||
using Point_2 = typename Geometry_traits_2::Point_2;
|
||||
using X_monotone_curve_2 = typename Geometry_traits_2::X_monotone_curve_2;
|
||||
using Multiplicity = typename Geometry_traits_2::Multiplicity;
|
||||
|
||||
protected:
|
||||
typedef typename Arr_all_sides_oblivious_category<Left_side_category,
|
||||
Bottom_side_category,
|
||||
Top_side_category,
|
||||
Right_side_category>::result
|
||||
Are_all_sides_oblivious_category;
|
||||
// General types
|
||||
using Vertex_const_handle = typename Arrangement_2::Vertex_const_handle;
|
||||
using Halfedge_const_handle = typename Arrangement_2::Halfedge_const_handle;
|
||||
using Face_const_handle = typename Arrangement_2::Face_const_handle;
|
||||
|
||||
typedef typename Arrangement_2::Vertex_const_handle Vertex_const_handle;
|
||||
typedef typename Arrangement_2::Halfedge_const_handle Halfedge_const_handle;
|
||||
typedef typename Arrangement_2::Face_const_handle Face_const_handle;
|
||||
|
||||
typedef typename Arrangement_2::Ccb_halfedge_circulator
|
||||
Ccb_halfedge_circulator;
|
||||
using Ccb_halfedge_circulator =
|
||||
typename Arrangement_2::Ccb_halfedge_circulator;
|
||||
|
||||
// Types used for caching intersection points:
|
||||
typedef std::pair<Point_2, Multiplicity> Intersection_point;
|
||||
typedef std::variant<Intersection_point, X_monotone_curve_2>
|
||||
Intersection_result;
|
||||
typedef std::optional<Intersection_result> Optional_intersection;
|
||||
typedef std::list<Intersection_result> Intersect_list;
|
||||
typedef std::map<const X_monotone_curve_2*, Intersect_list>
|
||||
Intersect_map;
|
||||
typedef typename Intersect_map::iterator Intersect_map_iterator;
|
||||
using Intersection_point = std::pair<Point_2, Multiplicity>;
|
||||
using Intersection_result =
|
||||
std::variant<Intersection_point, X_monotone_curve_2>;
|
||||
using Optional_intersection = std::optional<Intersection_result>;
|
||||
using Intersect_list = std::list<Intersection_result>;
|
||||
using Intersect_map = std::map<const X_monotone_curve_2*, Intersect_list>;
|
||||
|
||||
typedef std::set<const X_monotone_curve_2*> Curves_set;
|
||||
typedef typename Curves_set::iterator Curves_set_iterator;
|
||||
using Curves_set = std::set<const X_monotone_curve_2*>;
|
||||
using Curves_set_iterator = typename Curves_set::iterator;
|
||||
|
||||
typedef Arr_point_location_result<Arrangement_2> Pl_result;
|
||||
typedef typename Pl_result::Type Pl_result_type;
|
||||
using Pl_result = Arr_point_location_result<Arrangement_2>;
|
||||
using Pl_result_type = typename Pl_result::Type;
|
||||
|
||||
// Data members:
|
||||
Arrangement_2& m_arr; // The associated arrangement.
|
||||
|
|
@ -193,8 +196,7 @@ public:
|
|||
* \param pl A point-location object associated with the arrangement.
|
||||
*/
|
||||
template <typename PointLocation>
|
||||
void init(const X_monotone_curve_2& cv, const PointLocation& pl)
|
||||
{
|
||||
void init(const X_monotone_curve_2& cv, const PointLocation& pl) {
|
||||
// Set the curve and check whether its left end has boundary conditions.
|
||||
m_cv = cv;
|
||||
|
||||
|
|
@ -267,8 +269,7 @@ private:
|
|||
*/
|
||||
bool do_overlap_impl(const X_monotone_curve_2& cv1,
|
||||
const X_monotone_curve_2& cv2,
|
||||
const Point_2& p, Arr_all_sides_oblivious_tag) const
|
||||
{
|
||||
const Point_2& p, Arr_all_sides_oblivious_tag) const {
|
||||
return m_geom_traits->compare_y_at_x_right_2_object()(cv1, cv2, p) == EQUAL;
|
||||
}
|
||||
|
||||
|
|
@ -336,7 +337,7 @@ private:
|
|||
Optional_intersection
|
||||
_compute_next_intersection(Halfedge_handle he,
|
||||
bool skip_first_point,
|
||||
bool& intersect_on_right_boundary);
|
||||
Arr_parameter_space& intersection_location);
|
||||
|
||||
/*! Remove the next intersection of m_cv with the given halfedge from the map.
|
||||
* \param he A handle to the halfedge.
|
||||
|
|
@ -381,8 +382,7 @@ private:
|
|||
{ return (_is_to_right_impl(p, he, Are_all_sides_oblivious_category())); }
|
||||
|
||||
bool _is_to_right_impl(const Point_2& p, Halfedge_handle he,
|
||||
Arr_all_sides_oblivious_tag) const
|
||||
{
|
||||
Arr_all_sides_oblivious_tag) const {
|
||||
return (((he->direction() == ARR_LEFT_TO_RIGHT) &&
|
||||
m_geom_traits->compare_xy_2_object()(p, he->target()->point()) ==
|
||||
LARGER) ||
|
||||
|
|
@ -394,12 +394,33 @@ private:
|
|||
bool _is_to_right_impl(const Point_2& p, Halfedge_handle he,
|
||||
Arr_not_all_sides_oblivious_tag) const;
|
||||
|
||||
/*! Check whether an intersection point is valid. A valid intersection point
|
||||
* must be to the left of the left end of the curve involved.
|
||||
*/
|
||||
bool is_intersection_valid(const Point_2& ip,
|
||||
Arr_parameter_space& intersection_location) const {
|
||||
return is_intersection_valid_impl(ip, intersection_location,
|
||||
Left_or_right_sides_category());
|
||||
}
|
||||
|
||||
bool is_intersection_valid_impl(const Point_2& ip,
|
||||
Arr_parameter_space& intersection_location,
|
||||
Arr_all_sides_oblivious_tag) const;
|
||||
|
||||
bool is_intersection_valid_impl(const Point_2& ip,
|
||||
Arr_parameter_space& intersection_location,
|
||||
Arr_has_identified_side_tag) const;
|
||||
|
||||
bool is_intersection_valid_impl(const Point_2& ip,
|
||||
Arr_parameter_space& intersection_location,
|
||||
Arr_boundary_cond_tag) const;
|
||||
|
||||
/*! Compute the (lexicographically) leftmost intersection of the query
|
||||
* curve with a given halfedge on the boundary of a face in the arrangement.
|
||||
*/
|
||||
void
|
||||
_leftmost_intersection(Ccb_halfedge_circulator he_curr, bool on_boundary,
|
||||
bool& leftmost_on_right_boundary);
|
||||
Arr_parameter_space& leftmost_location);
|
||||
|
||||
/*! Compute the (lexicographically) leftmost intersection of the query
|
||||
* curve with the boundary of a given face in the arrangement.
|
||||
|
|
|
|||
|
|
@ -29,7 +29,9 @@
|
|||
|
||||
#include <type_traits>
|
||||
#include <CGAL/Qt/init_ogl_context.h>
|
||||
#include <CGAL/Arrangement_on_surface_2.h>
|
||||
#include <CGAL/Arrangement_2.h>
|
||||
#include <CGAL/Arr_geodesic_arc_on_sphere_traits_2.h>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
|
|
@ -46,32 +48,32 @@ struct Default_color_generator {
|
|||
};
|
||||
|
||||
// Viewer class for`< Polygon_2
|
||||
template <typename Arrangement_2_,
|
||||
template <typename ArrangementOnSurface_2,
|
||||
typename ColorGenerator = Default_color_generator>
|
||||
class Arr_2_basic_viewer_qt : public Basic_viewer_qt {
|
||||
using Arr = Arrangement_2_;
|
||||
class Aos_2_basic_viewer_qt : public Basic_viewer_qt {
|
||||
using Aos = ArrangementOnSurface_2;
|
||||
using Color_generator = ColorGenerator;
|
||||
using Base = Basic_viewer_qt;
|
||||
using Gt = typename Arr::Geometry_traits_2;
|
||||
using Point = typename Arr::Point_2;
|
||||
using X_monotone_curve = typename Arr::X_monotone_curve_2;
|
||||
using Vertex_const_handle = typename Arr::Vertex_const_handle;
|
||||
using Halfedge_const_handle = typename Arr::Halfedge_const_handle;
|
||||
using Face_const_handle = typename Arr::Face_const_handle;
|
||||
using Gt = typename Aos::Geometry_traits_2;
|
||||
using Point = typename Aos::Point_2;
|
||||
using X_monotone_curve = typename Aos::X_monotone_curve_2;
|
||||
using Vertex_const_handle = typename Aos::Vertex_const_handle;
|
||||
using Halfedge_const_handle = typename Aos::Halfedge_const_handle;
|
||||
using Face_const_handle = typename Aos::Face_const_handle;
|
||||
using Ccb_halfedge_const_circulator =
|
||||
typename Arr::Ccb_halfedge_const_circulator;
|
||||
typename Aos::Ccb_halfedge_const_circulator;
|
||||
|
||||
public:
|
||||
/// Construct the viewer.
|
||||
/// @param arr the arrangement to view
|
||||
/// @param title the title of the window
|
||||
Arr_2_basic_viewer_qt(QWidget* parent, const Arr& arr,
|
||||
Aos_2_basic_viewer_qt(QWidget* parent, const Aos& aos,
|
||||
Color_generator color_generator,
|
||||
const char* title = "2D Arrangement Basic Viewer",
|
||||
bool draw_vertices = false) :
|
||||
// First draw: vertices; edges, faces; multi-color; no inverse normal
|
||||
Base(parent, title, draw_vertices, true, true, false, false),
|
||||
m_arr(arr),
|
||||
m_aos(aos),
|
||||
m_color_generator(color_generator)
|
||||
{
|
||||
// mimic the computation of Camera::pixelGLRatio()
|
||||
|
|
@ -154,32 +156,47 @@ public:
|
|||
*/
|
||||
CGAL::Bbox_2 bounding_box() {
|
||||
CGAL::Bbox_2 bbox;
|
||||
const auto* traits = this->m_arr.geometry_traits();
|
||||
const auto* traits = this->m_aos.geometry_traits();
|
||||
// At this point we assume that the arrangement is not open, and thus the
|
||||
// bounding box is defined by the vertices.
|
||||
for (auto it = m_arr.vertices_begin(); it != m_arr.vertices_end(); ++it)
|
||||
for (auto it = m_aos.vertices_begin(); it != m_aos.vertices_end(); ++it)
|
||||
bounding_box_impl1(bbox, it->point(), *traits, 0);
|
||||
return bbox;
|
||||
}
|
||||
|
||||
/*! Add all faces.
|
||||
*/
|
||||
template <typename Traits>
|
||||
void add_faces(const Traits&) {
|
||||
for (auto it = m_aos.unbounded_faces_begin();
|
||||
it != m_aos.unbounded_faces_end(); ++it)
|
||||
add_face(it);
|
||||
}
|
||||
|
||||
/*! Add all faces.
|
||||
*/
|
||||
template <typename Kernel_, int AtanX, int AtanY>
|
||||
void
|
||||
add_faces(Arr_geodesic_arc_on_sphere_traits_2<Kernel_, AtanX, AtanY> const&)
|
||||
{ add_face(m_aos.faces_begin()); }
|
||||
|
||||
/*! Add all elements to be drawn.
|
||||
*/
|
||||
void add_elements() {
|
||||
// std::cout << "add_elements()\n";
|
||||
// std::cout << "ratio: " << this->pixel_ratio() << std::endl;
|
||||
clear();
|
||||
m_visited.clear();
|
||||
|
||||
if (m_arr.is_empty()) return;
|
||||
for (auto it = m_arr.unbounded_faces_begin();
|
||||
it != m_arr.unbounded_faces_end(); ++it)
|
||||
add_face(it);
|
||||
if (m_aos.is_empty()) return;
|
||||
add_faces(*(this->m_aos.geometry_traits()));
|
||||
|
||||
// Add edges that do not separe faces.
|
||||
for (auto it = m_arr.edges_begin(); it != m_arr.edges_end(); ++it)
|
||||
// Add edges that do not separate faces.
|
||||
for (auto it = m_aos.edges_begin(); it != m_aos.edges_end(); ++it)
|
||||
if (it->face() == it->twin()->face()) draw_curve(it->curve());
|
||||
|
||||
// Add all points
|
||||
for (auto it = m_arr.vertices_begin(); it != m_arr.vertices_end(); ++it)
|
||||
for (auto it = m_aos.vertices_begin(); it != m_aos.vertices_end(); ++it)
|
||||
draw_point(it->point());
|
||||
|
||||
m_visited.clear();
|
||||
|
|
@ -190,11 +207,20 @@ public:
|
|||
double pixel_ratio() const { return m_pixel_ratio; }
|
||||
|
||||
protected:
|
||||
template <typename Kernel, int AtanX, int AtanY>
|
||||
Halfedge_const_handle
|
||||
find_smallest(Ccb_halfedge_const_circulator circ,
|
||||
Arr_geodesic_arc_on_sphere_traits_2<Kernel, AtanX, AtanY> const&)
|
||||
{ return circ; }
|
||||
|
||||
/*! Find the halfedge incident to the lexicographically smallest vertex
|
||||
* along the CCB, such that there is no other halfedge underneath.
|
||||
*/
|
||||
Halfedge_const_handle find_smallest(Ccb_halfedge_const_circulator circ) {
|
||||
const auto* traits = this->m_arr.geometry_traits();
|
||||
template <typename Traits>
|
||||
Halfedge_const_handle find_smallest(Ccb_halfedge_const_circulator circ,
|
||||
const Traits&) {
|
||||
// std::cout << "find_smallest()\n";
|
||||
const auto* traits = this->m_aos.geometry_traits();
|
||||
auto cmp_xy = traits->compare_xy_2_object();
|
||||
auto cmp_y = traits->compare_y_at_x_right_2_object();
|
||||
|
||||
|
|
@ -241,6 +267,7 @@ protected:
|
|||
template <typename Approximate>
|
||||
void draw_approximate_region(Halfedge_const_handle curr,
|
||||
const Approximate& approx) {
|
||||
// std::cout << "draw_approximate_region()\n";
|
||||
std::vector<typename Gt::Approximate_point_2> polyline;
|
||||
double error(this->pixel_ratio());
|
||||
bool l2r = curr->direction() == ARR_LEFT_TO_RIGHT;
|
||||
|
|
@ -258,7 +285,7 @@ protected:
|
|||
*/
|
||||
template <typename XMonotoneCurve>
|
||||
void draw_exact_curve(const XMonotoneCurve& curve) {
|
||||
const auto* traits = this->m_arr.geometry_traits();
|
||||
const auto* traits = this->m_aos.geometry_traits();
|
||||
auto ctr_min = traits->construct_min_vertex_2_object();
|
||||
auto ctr_max = traits->construct_max_vertex_2_object();
|
||||
this->add_segment(ctr_min(curve), ctr_max(curve));
|
||||
|
|
@ -267,7 +294,7 @@ protected:
|
|||
/*! Draw an exact region.
|
||||
*/
|
||||
void draw_exact_region(Halfedge_const_handle curr) {
|
||||
this->add_point_in_face(curr->source()->point());
|
||||
// this->add_point_in_face(curr->source()->point());
|
||||
draw_exact_curve(curr->curve());
|
||||
}
|
||||
|
||||
|
|
@ -300,9 +327,46 @@ protected:
|
|||
{ draw_approximate_region(curr, traits.approximate_2_object()); }
|
||||
#endif
|
||||
|
||||
template <typename Kernel_, int AtanX, int AtanY>
|
||||
void draw_region_impl1
|
||||
(Halfedge_const_handle curr,
|
||||
Arr_geodesic_arc_on_sphere_traits_2<Kernel_, AtanX, AtanY> const& traits,
|
||||
int) {
|
||||
// std::cout << "draw_region_impl1()\n";
|
||||
auto approx = traits.approximate_2_object();
|
||||
using Kernel = Kernel_;
|
||||
using Traits = Arr_geodesic_arc_on_sphere_traits_2<Kernel, AtanX, AtanY>;
|
||||
using Ak = typename Traits::Approximate_kernel;
|
||||
using Ap = typename Traits::Approximate_point_2;
|
||||
using Approx_point_3 = typename Ak::Point_3;
|
||||
|
||||
std::vector<Ap> polyline;
|
||||
double error(0.01);
|
||||
bool l2r = curr->direction() == ARR_LEFT_TO_RIGHT;
|
||||
approx(curr->curve(), error, std::back_inserter(polyline), l2r);
|
||||
if (polyline.empty()) return;
|
||||
auto it = polyline.begin();
|
||||
auto x = it->dx();
|
||||
auto y = it->dy();
|
||||
auto z = it->dz();
|
||||
auto l = std::sqrt(x*x + y*y + z*z);
|
||||
Approx_point_3 prev(x/l, y/l, z/l);
|
||||
for (++it; it != polyline.end(); ++it) {
|
||||
auto x = it->dx();
|
||||
auto y = it->dy();
|
||||
auto z = it->dz();
|
||||
auto l = std::sqrt(x*x + y*y + z*z);
|
||||
Approx_point_3 next(x/l, y/l, z/l);
|
||||
this->add_segment(prev, next);
|
||||
prev = next;
|
||||
// this->add_point_in_face(*prev);
|
||||
}
|
||||
}
|
||||
|
||||
/*! Draw a region.
|
||||
*/
|
||||
void draw_region(Ccb_halfedge_const_circulator circ) {
|
||||
// std::cout << "draw_region()\n";
|
||||
/* Check whether the traits has a member function called
|
||||
* approximate_2_object() and if so check whether the return type, namely
|
||||
* `Approximate_2` has an appropriate operator.
|
||||
|
|
@ -321,8 +385,8 @@ protected:
|
|||
auto color = m_color_generator(circ->face());
|
||||
this->face_begin(color);
|
||||
|
||||
const auto* traits = this->m_arr.geometry_traits();
|
||||
auto ext = find_smallest(circ);
|
||||
const auto* traits = this->m_aos.geometry_traits();
|
||||
auto ext = find_smallest(circ, *traits);
|
||||
auto curr = ext;
|
||||
|
||||
do {
|
||||
|
|
@ -382,6 +446,37 @@ protected:
|
|||
{ draw_approximate_curve(xcv, traits.approximate_2_object()); }
|
||||
#endif
|
||||
|
||||
template <typename Kernel_, int AtanX, int AtanY>
|
||||
void draw_curve_impl1
|
||||
(const X_monotone_curve& xcv,
|
||||
Arr_geodesic_arc_on_sphere_traits_2<Kernel_, AtanX, AtanY> const& traits,
|
||||
int) {
|
||||
auto approx = traits.approximate_2_object();
|
||||
using Kernel = Kernel_;
|
||||
using Traits = Arr_geodesic_arc_on_sphere_traits_2<Kernel, AtanX, AtanY>;
|
||||
using Ak = typename Traits::Approximate_kernel;
|
||||
using Ap = typename Traits::Approximate_point_2;
|
||||
using Approx_point_3 = typename Ak::Point_3;
|
||||
std::vector<Ap> apoints;
|
||||
double error(0.01);
|
||||
approx(xcv, error, std::back_inserter(apoints));
|
||||
auto it = apoints.begin();
|
||||
auto x = it->dx();
|
||||
auto y = it->dy();
|
||||
auto z = it->dz();
|
||||
auto l = std::sqrt(x*x + y*y + z*z);
|
||||
Approx_point_3 prev(x/l, y/l, z/l);
|
||||
for (++it; it != apoints.end(); ++it) {
|
||||
auto x = it->dx();
|
||||
auto y = it->dy();
|
||||
auto z = it->dz();
|
||||
auto l = std::sqrt(x*x + y*y + z*z);
|
||||
Approx_point_3 next(x/l, y/l, z/l);
|
||||
this->add_segment(prev, next);
|
||||
prev = next;
|
||||
}
|
||||
}
|
||||
|
||||
/*! Draw a curve.
|
||||
*/
|
||||
template <typename XMonotoneCurve>
|
||||
|
|
@ -404,14 +499,14 @@ protected:
|
|||
#if 0
|
||||
if constexpr (std::experimental::is_detected_v<approximate_2_object_t, Gt>)
|
||||
{
|
||||
const auto* traits = this->m_arr.geometry_traits();
|
||||
const auto* traits = this->m_aos.geometry_traits();
|
||||
auto approx = traits->approximate_2_object();
|
||||
draw_approximate_curve(curve, approx);
|
||||
return;
|
||||
}
|
||||
draw_exact_curve(curve);
|
||||
#else
|
||||
const auto* traits = this->m_arr.geometry_traits();
|
||||
const auto* traits = this->m_aos.geometry_traits();
|
||||
draw_curve_impl1(curve, *traits, 0);
|
||||
#endif
|
||||
}
|
||||
|
|
@ -442,16 +537,35 @@ protected:
|
|||
{ add_point(traits.approximate_2_object()(p)); }
|
||||
#endif
|
||||
|
||||
template <typename Kernel_, int AtanX, int AtanY>
|
||||
void draw_point_impl1
|
||||
(const Point& p,
|
||||
Arr_geodesic_arc_on_sphere_traits_2<Kernel_, AtanX, AtanY> const& traits,
|
||||
int) {
|
||||
auto approx = traits.approximate_2_object();
|
||||
using Traits = Arr_geodesic_arc_on_sphere_traits_2<Kernel_, AtanX, AtanY>;
|
||||
using Ak = typename Traits::Approximate_kernel;
|
||||
using Approx_point_3 = typename Ak::Point_3;
|
||||
auto ap = approx(p);
|
||||
auto x = ap.dx();
|
||||
auto y = ap.dy();
|
||||
auto z = ap.dz();
|
||||
auto l = std::sqrt(x*x + y*y + z*z);
|
||||
Approx_point_3 p3(x/l, y/l, z/l);
|
||||
add_point(p3);
|
||||
}
|
||||
|
||||
/*! Draw a point.
|
||||
*/
|
||||
void draw_point(const Point& p) {
|
||||
const auto* traits = m_arr.geometry_traits();
|
||||
const auto* traits = m_aos.geometry_traits();
|
||||
draw_point_impl1(p, *traits, 0);
|
||||
}
|
||||
|
||||
/*! Add a Connected Component of the Boundary.
|
||||
*/
|
||||
void add_ccb(Ccb_halfedge_const_circulator circ) {
|
||||
// std::cout << "add_ccb()\n";
|
||||
auto curr = circ;
|
||||
do {
|
||||
auto new_face = curr->twin()->face();
|
||||
|
|
@ -464,8 +578,9 @@ protected:
|
|||
/*! Add a face.
|
||||
*/
|
||||
void add_face(Face_const_handle face) {
|
||||
using Inner_ccb_const_iterator = typename Arr::Inner_ccb_const_iterator;
|
||||
using Outer_ccb_const_iterator = typename Arr::Outer_ccb_const_iterator;
|
||||
// std::cout << "add_face()\n";
|
||||
using Inner_ccb_const_iterator = typename Aos::Inner_ccb_const_iterator;
|
||||
using Outer_ccb_const_iterator = typename Aos::Outer_ccb_const_iterator;
|
||||
|
||||
for (Inner_ccb_const_iterator it = face->inner_ccbs_begin();
|
||||
it != face->inner_ccbs_end(); ++it)
|
||||
|
|
@ -505,7 +620,7 @@ protected:
|
|||
double m_pixel_ratio = 1;
|
||||
|
||||
//! The arrangement to draw.
|
||||
const Arr& m_arr;
|
||||
const Aos& m_aos;
|
||||
|
||||
//! The color generator.
|
||||
Color_generator m_color_generator;
|
||||
|
|
@ -514,32 +629,63 @@ protected:
|
|||
};
|
||||
|
||||
//! Basic viewer of a 2D arrangement.
|
||||
template <typename Arrangement_2_,
|
||||
template <typename ArrangementOnSurface_2,
|
||||
typename ColorGenerator = Default_color_generator>
|
||||
class Arr_2_viewer_qt : public Arr_2_basic_viewer_qt<Arrangement_2_,
|
||||
class Aos_2_viewer_qt : public Aos_2_basic_viewer_qt<ArrangementOnSurface_2,
|
||||
ColorGenerator> {
|
||||
public:
|
||||
using Arr = Arrangement_2_;
|
||||
using Aos = ArrangementOnSurface_2;
|
||||
using Color_generator = ColorGenerator;
|
||||
using Base = Arr_2_basic_viewer_qt<Arr, Color_generator>;
|
||||
using Point = typename Arr::Point_2;
|
||||
using X_monotone_curve = typename Arr::X_monotone_curve_2;
|
||||
using Halfedge_const_handle = typename Arr::Halfedge_const_handle;
|
||||
using Face_const_handle = typename Arr::Face_const_handle;
|
||||
using Base = Aos_2_basic_viewer_qt<Aos, Color_generator>;
|
||||
using Point = typename Aos::Point_2;
|
||||
using X_monotone_curve = typename Aos::X_monotone_curve_2;
|
||||
using Halfedge_const_handle = typename Aos::Halfedge_const_handle;
|
||||
using Face_const_handle = typename Aos::Face_const_handle;
|
||||
using Ccb_halfedge_const_circulator =
|
||||
typename Arr::Ccb_halfedge_const_circulator;
|
||||
typename Aos::Ccb_halfedge_const_circulator;
|
||||
|
||||
/// Construct the viewer.
|
||||
/// @param arr the arrangement to view
|
||||
/// @param title the title of the window
|
||||
Arr_2_viewer_qt(QWidget* parent, const Arr& arr,
|
||||
Aos_2_viewer_qt(QWidget* parent, const Aos& aos,
|
||||
Color_generator color_generator,
|
||||
const char* title = "2D Arrangement Basic Viewer",
|
||||
const char* title = "2D Arrangement on Surface Basic Viewer",
|
||||
bool draw_vertices = false) :
|
||||
Base(parent, arr, color_generator, title, draw_vertices)
|
||||
Base(parent, aos, color_generator, title, draw_vertices)
|
||||
{}
|
||||
};
|
||||
|
||||
/*! Draw an arrangement on surface.
|
||||
*/
|
||||
template <typename GeometryTraits_2, typename TopologyTraits>
|
||||
void draw(const Arrangement_on_surface_2<GeometryTraits_2, TopologyTraits>& aos,
|
||||
const char* title = "2D Arrangement on Surface Basic Viewer",
|
||||
bool draw_vertices = false) {
|
||||
#if defined(CGAL_TEST_SUITE)
|
||||
bool cgal_test_suite=true;
|
||||
#else
|
||||
bool cgal_test_suite = qEnvironmentVariableIsSet("CGAL_TEST_SUITE");
|
||||
#endif
|
||||
|
||||
if (cgal_test_suite) return;
|
||||
using Gt = GeometryTraits_2;
|
||||
using Tt = TopologyTraits;
|
||||
using Aos = CGAL::Arrangement_on_surface_2<Gt, Tt>;
|
||||
using Viewer = Aos_2_viewer_qt<Aos, Default_color_generator>;
|
||||
|
||||
CGAL::Qt::init_ogl_context(4,3);
|
||||
|
||||
int argc = 1;
|
||||
const char* argv[2] = {"t2_viewer", nullptr};
|
||||
QApplication app(argc, const_cast<char**>(argv));
|
||||
Default_color_generator color_generator;
|
||||
Viewer mainwindow(app.activeWindow(), aos, color_generator, title,
|
||||
draw_vertices);
|
||||
mainwindow.add_elements();
|
||||
mainwindow.show();
|
||||
app.exec();
|
||||
}
|
||||
|
||||
/*! Draw an arrangement.
|
||||
*/
|
||||
template <typename GeometryTraits_2, typename Dcel>
|
||||
|
|
@ -555,7 +701,7 @@ void draw(const Arrangement_2<GeometryTraits_2, Dcel>& arr,
|
|||
if (cgal_test_suite) return;
|
||||
using Gt = GeometryTraits_2;
|
||||
using Arr = CGAL::Arrangement_2<Gt, Dcel>;
|
||||
using Viewer = Arr_2_viewer_qt<Arr, Default_color_generator>;
|
||||
using Viewer = Aos_2_viewer_qt<Arr, Default_color_generator>;
|
||||
|
||||
CGAL::Qt::init_ogl_context(4,3);
|
||||
|
||||
|
|
@ -589,7 +735,7 @@ void draw(const Arrangement_2<GeometryTraits_2, Dcel>& arr,
|
|||
using Color_generator = ColorGenerator;
|
||||
using Gt = GeometryTraits_2;
|
||||
using Arr = CGAL::Arrangement_2<Gt, Dcel>;
|
||||
using Viewer = Arr_2_viewer_qt<Arr, Color_generator>;
|
||||
using Viewer = Aos_2_viewer_qt<Arr, Color_generator>;
|
||||
|
||||
CGAL::Qt::init_ogl_context(4,3);
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
5
|
||||
0 -1 0 0 0 -1 0
|
||||
0 0 -1 0 0 0 -1
|
||||
0 0 0 -1 0 1 0
|
||||
0 0 1 0 -1 0 0
|
||||
0 0 0 -1 -1 0 0
|
||||
0
|
||||
4 5 3
|
||||
0 0 -1
|
||||
-1 0 0
|
||||
0 -1 0
|
||||
0 1 0
|
||||
0 0 0 -1 -1 0 0 1
|
||||
0 -1 0 0 0 -1 0 1
|
||||
0 0 -1 0 0 0 -1 1
|
||||
0 0 0 -1 0 1 0 1
|
||||
0 0 1 0 -1 0 0 1
|
||||
|
|
@ -37,3 +37,4 @@ data/test_construction/geodesic_arcs_on_sphere/test36.txt
|
|||
data/test_construction/geodesic_arcs_on_sphere/test37.txt
|
||||
data/test_construction/geodesic_arcs_on_sphere/test38.txt
|
||||
data/test_construction/geodesic_arcs_on_sphere/test39.txt
|
||||
data/test_construction/geodesic_arcs_on_sphere/test40.txt
|
||||
|
|
|
|||
|
|
@ -216,7 +216,7 @@ boxes and approximated geometry, which is the case here. It saves us
|
|||
the extra space that was needed for the explicit `id`-number in
|
||||
the previous example.
|
||||
|
||||
We run the self intersection algorithm with the `report_inters`
|
||||
We run the self intersection algorithm with the `report_inters()`
|
||||
function as callback. This callback reports the intersecting boxes. It
|
||||
uses the `handle` and the global `triangles` vector to
|
||||
calculate the triangle numbers. Then it checks the triangles
|
||||
|
|
@ -480,4 +480,3 @@ however, we learned too late about this implementation.
|
|||
|
||||
*/
|
||||
} /* namespace CGAL */
|
||||
|
||||
|
|
|
|||
|
|
@ -47,12 +47,12 @@ Box_traits_d();
|
|||
|
||||
|
||||
/*!
|
||||
\ingroup PkgBoxIntersectionDFunctions
|
||||
\ingroup PkgBoxIntersectionDEnums
|
||||
*/
|
||||
enum Setting { COMPLETE, BIPARTITE };
|
||||
|
||||
/*!
|
||||
\ingroup PkgBoxIntersectionDFunctions
|
||||
\ingroup PkgBoxIntersectionDEnums
|
||||
*/
|
||||
enum Topology { HALF_OPEN, CLOSED };
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,9 @@
|
|||
/// \defgroup PkgBoxIntersectionDConcepts Concepts
|
||||
/// \ingroup PkgBoxIntersectionDRef
|
||||
|
||||
/// \defgroup PkgBoxIntersectionDEnums Enumerations
|
||||
/// \ingroup PkgBoxIntersectionDRef
|
||||
|
||||
/// \defgroup PkgBoxIntersectionDClasses Classes
|
||||
/// \ingroup PkgBoxIntersectionDRef
|
||||
|
||||
|
|
@ -43,6 +46,10 @@
|
|||
- `BoxIntersectionBox_d`
|
||||
- `BoxIntersectionTraits_d`
|
||||
|
||||
\cgalCRPSection{Enumerations}
|
||||
- `CGAL::Box_intersection_d::Setting`
|
||||
- `CGAL::Box_intersection_d::Topology`
|
||||
|
||||
\cgalCRPSection{Classes}
|
||||
- `CGAL::Box_intersection_d::Box_d<NT,int D,IdPolicy>`
|
||||
- `CGAL::Box_intersection_d::Box_with_handle_d<NT, int D, Handle, IdPolicy>`
|
||||
|
|
@ -56,4 +63,3 @@
|
|||
- `CGAL::box_self_intersection_all_pairs_d`
|
||||
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -4,3 +4,4 @@ STL_Extension
|
|||
Algebraic_foundations
|
||||
Circulator
|
||||
Stream_support
|
||||
Polyhedron
|
||||
|
|
|
|||
|
|
@ -34,11 +34,7 @@
|
|||
#include <boost/bind/bind.hpp>
|
||||
#include <boost/ptr_container/ptr_vector.hpp>
|
||||
#include <boost/random/mersenne_twister.hpp>
|
||||
#if BOOST_VERSION >= 104700
|
||||
# include <boost/random/uniform_int_distribution.hpp>
|
||||
#else
|
||||
# include <boost/random/uniform_int.hpp>
|
||||
#endif
|
||||
#include <boost/random/uniform_int_distribution.hpp>
|
||||
#include <boost/random/uniform_01.hpp>
|
||||
#include <boost/random/normal_distribution.hpp>
|
||||
#if defined(CGAL_LINKED_WITH_BOOST_IOSTREAMS) && defined(CGAL_LINKED_WITH_BOOST_SERIALIZATION)
|
||||
|
|
@ -65,17 +61,10 @@ inline void init_feature_class_data(FeatureClassDataFloat& /*data*/, int /*n_cla
|
|||
}
|
||||
typedef std::unordered_set<int> FeatureSet;
|
||||
|
||||
#if BOOST_VERSION >= 104700
|
||||
typedef boost::random::uniform_int_distribution<> UniformIntDist;
|
||||
typedef boost::random::normal_distribution<> NormalDist;
|
||||
typedef boost::random::mt19937 RandomGen;
|
||||
typedef boost::random::uniform_01<> UnitDist;
|
||||
#else
|
||||
typedef boost::uniform_int<> UniformIntDist;
|
||||
typedef boost::normal_distribution<> NormalDist;
|
||||
typedef boost::uniform_01<> UnitDist;
|
||||
typedef boost::mt19937 RandomGen;
|
||||
#endif
|
||||
|
||||
struct ForestParams {
|
||||
size_t n_classes;
|
||||
|
|
|
|||
|
|
@ -562,7 +562,7 @@ Let <I>d0</I>\f$ \in \f$ <I>D</I> be a dart. Given <I>i</I>, 1 \f$ \leq \f$ <I>i
|
|||
|
||||
\section Combinatorial_mapDesign Design and Implementation History
|
||||
|
||||
The code of this package is inspired by Moka, a 3D topological modeler mainly developed by Frédéric Vidil and Guillaume Damiand (<A HREF="https://moka-modeller.sourceforge.net/">https://moka-modeller.sourceforge.net/</A>). However, Moka was based on Generalized maps (and not Combinatorial maps), and the design was not \cgal "compatible". Thus, Guillaume Damiand started to develop a totally new package by mixing ideas taken from Moka with the design of the Halfedge data structure package of \cgal. Andreas Fabri and Sébastien Loriot contributed to the design, the coding, and to the documentation of the package, and Laurent Rineau helped for the design. Emma Michel contributed to the manual. Monique Teillaud and Bernd Gärtner contributed to the manual by giving useful remarks, really numerous and detailed for Monique. Ken Arroyo Ohori contributed to the two reverse orientation functions.
|
||||
The code of this package is inspired by Moka, a 3D topological modeler mainly developed by Frédéric Vidil and Guillaume Damiand (see https://projet.liris.cnrs.fr/moka/index.php and https://github.com/gdamiand/moka). However, Moka was based on Generalized maps (and not Combinatorial maps), and the design was not \cgal "compatible". Thus, Guillaume Damiand started to develop a totally new package by mixing ideas taken from Moka with the design of the Halfedge data structure package of \cgal. Andreas Fabri and Sébastien Loriot contributed to the design, the coding, and to the documentation of the package, and Laurent Rineau helped for the design. Emma Michel contributed to the manual. Monique Teillaud and Bernd Gärtner contributed to the manual by giving useful remarks, really numerous and detailed for Monique. Ken Arroyo Ohori contributed to the two reverse orientation functions.
|
||||
|
||||
*/
|
||||
} /* namespace CGAL */
|
||||
|
|
|
|||
|
|
@ -148,6 +148,10 @@ namespace CGAL {
|
|||
{ return mmap.mdarts.is_used(i); }
|
||||
bool owns(size_type i) const
|
||||
{ return mmap.mdarts.owns(i); }
|
||||
size_type capacity() const
|
||||
{ return mmap.mdarts.capacity(); }
|
||||
size_type upper_bound() const
|
||||
{ return mmap.mdarts.upper_bound(); }
|
||||
private:
|
||||
Self & mmap;
|
||||
};
|
||||
|
|
@ -444,7 +448,7 @@ namespace CGAL {
|
|||
(mattribute_containers).upper_bound();
|
||||
}
|
||||
|
||||
protected:
|
||||
protected:
|
||||
// Set the handle on the i th attribute
|
||||
template<unsigned int i>
|
||||
void basic_set_dart_attribute(Dart_descriptor dh,
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ then the default traits class of `::convex_hull_3()` is `Convex_hull_traits_3<R>
|
|||
\cgalHeading{Implementation}
|
||||
|
||||
The algorithm implemented by these functions is the quickhull algorithm of
|
||||
Barnard <I>et al.</I> \cgalCite{bdh-qach-96}.
|
||||
Barber <I>et al.</I> \cgalCite{bdh-qach-96}.
|
||||
|
||||
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -238,9 +238,10 @@ in \cgal programs, the executables should be linked with the CMake
|
|||
imported target `CGAL::LASLIB_support` provided in
|
||||
`CGAL_LASLIB_support.cmake`.
|
||||
|
||||
The \laslib web site is <a
|
||||
href="https://rapidlasso.com/lastools/">`https://rapidlasso.com/lastools/`</a>. \laslib
|
||||
is usually distributed along with LAStools: for simplicity, \cgal
|
||||
\laslib information can be obtained from
|
||||
<a href="https://lastools.github.io/">https://lastools.github.io/</a> and
|
||||
<a href="https://rapidlasso.de/product-overview/">https://rapidlasso.de/product-overview/</a>.
|
||||
\laslib is usually distributed along with LAStools: for simplicity, \cgal
|
||||
provides <a href="https://github.com/CGAL/LAStools">a fork with a
|
||||
CMake based install procedure</a>.
|
||||
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ seems that the points are collinear, or perform a right turn.
|
|||
|
||||
If you must ensure that your numbers get interpreted at their full precision
|
||||
you can use a \cgal kernel that performs exact predicates and
|
||||
extract constructions.
|
||||
exact constructions.
|
||||
|
||||
\cgalExample{Kernel_23/exact.cpp}
|
||||
|
||||
|
|
|
|||
|
|
@ -275,8 +275,8 @@ dependencies.
|
|||
\section sec-win-demo Trying CGAL algorithms using a Precompiled Demo
|
||||
\cgal provides a few demos offering a graphical user interface for some \cgal algorithms.
|
||||
All precompiled demos are available for download on the \ref packages page.
|
||||
Two links are provided in the column on the right: the demo itself (under **Windows Demo**) and a set of dlls (under **Common Demo Dlls**)
|
||||
that contains dlls files that must be placed in the same directory as the `.exe` of the demo.
|
||||
A link is provided in the column on the right, to download an archive. It contains the demo executable itself,
|
||||
and a set of dll files that must remain in the same directory as the `.exe` of the demo.
|
||||
See for example the \ref PkgConvexHull3 package.
|
||||
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@
|
|||
, pages = "617--625"
|
||||
, note = "SIGGRAPH '2005 Conference Proceedings"
|
||||
, volume = 24
|
||||
, url = "https://hal.inria.fr/inria-00226418"
|
||||
, url = "https://inria.hal.science/inria-00226418"
|
||||
, geombib = "not yet"
|
||||
}
|
||||
|
||||
|
|
@ -157,7 +157,7 @@ Pion and Monique Teillaud and Mariette Yvinec"
|
|||
@ARTICLE{cgal:bdt-hdcvd-14,
|
||||
AUTHOR = {Mikhail Bogdanov and Olivier Devillers and Monique Teillaud},
|
||||
JOURNAL = {Journal of Computational Geometry},
|
||||
NOTE = {https://hal.inria.fr/hal-00961390},
|
||||
NOTE = {https://inria.hal.science/hal-00961390},
|
||||
PAGES = {56--85},
|
||||
TITLE = {Hyperbolic {Delaunay} complexes and {Voronoi} diagrams made practical},
|
||||
VOLUME = {5},
|
||||
|
|
@ -243,7 +243,7 @@ Pion and Monique Teillaud and Mariette Yvinec"
|
|||
Boissonnat}
|
||||
, title = {Mesh Generation from 3D Multi-material Images}
|
||||
, pages = {283--290}
|
||||
, url = "https://hal.inria.fr/inria-00420228"
|
||||
, url = "https://inria.hal.science/inria-00420228"
|
||||
, x-international-audience = "yes"
|
||||
, x-proceedings = "yes"
|
||||
}
|
||||
|
|
@ -257,7 +257,7 @@ Boissonnat}
|
|||
, pages = "1455-14645"
|
||||
, volume = 28
|
||||
, year = 2009
|
||||
, url = "https://hal.inria.fr/inria-00413248"
|
||||
, url = "https://inria.hal.science/inria-00413248"
|
||||
, x-international-audience = "yes"
|
||||
, x-editorial-board = "yes"
|
||||
}
|
||||
|
|
@ -338,7 +338,7 @@ Boissonnat}
|
|||
,title = "{PLY} - Polygon File Format"
|
||||
,howpublished = {Paul Bourke}
|
||||
,year = 2011
|
||||
,url = "http://paulbourke.net/dataformats/ply/"
|
||||
,url = "https://paulbourke.net/dataformats/ply/"
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -361,7 +361,7 @@ Boissonnat}
|
|||
TITLE = {Delaunay triangulations on orientable surfaces of low genus},
|
||||
YEAR = {2016},
|
||||
DOI = {10.4230/LIPIcs.SoCG.2016.20},
|
||||
URL = {https://hal.inria.fr/hal-01276386}
|
||||
URL = {https://inria.hal.science/hal-01276386}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -402,7 +402,7 @@ Boissonnat}
|
|||
,school = "Universit\'e de {Nice-Sophia Antipolis}"
|
||||
,address = "France"
|
||||
,year = 2010
|
||||
,url = "https://tel.archives-ouvertes.fr/tel-00552215/"
|
||||
,url = "https://theses.hal.science/tel-00552215/"
|
||||
}
|
||||
|
||||
@inproceedings{cgal:ccplr-redtp-10,
|
||||
|
|
@ -539,13 +539,13 @@ note="Conference version: Symp. on Geometry Processing 2003"
|
|||
@inproceedings{ cgal:ct-c3pt-09
|
||||
, title = "Computing {3D} Periodic Triangulations"
|
||||
, author = "Manuel Caroli and Monique Teillaud"
|
||||
, booktitle = "Proceedings 17th European Symposium on Algorithms"
|
||||
, nickname = "ESA'09"
|
||||
, booktitle = "Proceedings 17th European Symposium on Algorithms"
|
||||
, nickname = "ESA'09"
|
||||
, series = "Lecture Notes in Computer Science"
|
||||
, year = 2009
|
||||
, volume = 5757
|
||||
, pages = "37--48"
|
||||
, note = "Full version available as INRIA Research Report 6823 \url{https://hal.inria.fr/inria-00356871}"
|
||||
, note = "Full version available as INRIA Research Report 6823 \url{https://inria.hal.science/inria-00356871}"
|
||||
}
|
||||
|
||||
@inproceedings{cgal:pt-rs-14,
|
||||
|
|
@ -729,7 +729,7 @@ Mourrain and Monique Teillaud"
|
|||
|
||||
@article{cgal:dmsl-ssmrp-11,
|
||||
author = {Digne, Julie and Morel, Jean-Michel and Souzani, Charyar-Mehdi and
|
||||
Lartigue, Claire},
|
||||
Lartigue, Claire},
|
||||
title = {Scale Space Meshing of Raw Data Point Sets},
|
||||
journal = {Computer Graphics Forum},
|
||||
year = {2011},
|
||||
|
|
@ -741,13 +741,13 @@ Mourrain and Monique Teillaud"
|
|||
}
|
||||
|
||||
@inproceedings{ cgal:dp-eegpd-03
|
||||
, author = "Olivier Devillers and Sylvain Pion"
|
||||
, title = "Efficient Exact Geometric Predicates for {Delaunay} Triangulations"
|
||||
, booktitle = "Proc. 5th Workshop Algorithm Eng. Exper."
|
||||
, nickname = "ALENEX '03"
|
||||
, year = 2003
|
||||
, pages = "37--44"
|
||||
, url = "https://hal.inria.fr/inria-00344517/"
|
||||
, author = "Olivier Devillers and Sylvain Pion"
|
||||
, title = "Efficient Exact Geometric Predicates for {Delaunay} Triangulations"
|
||||
, booktitle = "Proc. 5th Workshop Algorithm Eng. Exper."
|
||||
, nickname = "ALENEX '03"
|
||||
, year = 2003
|
||||
, pages = "37--44"
|
||||
, url = "https://inria.hal.science/inria-00344517/"
|
||||
}
|
||||
|
||||
@article{ cgal:dpt-wt-02
|
||||
|
|
@ -766,7 +766,7 @@ Teillaud"
|
|||
, author = "Olivier Devillers and Monique Teillaud"
|
||||
, title = "Perturbations and Vertex Removal in a {3D Delaunay} Triangulation"
|
||||
, booktitle = "Proc. 14th ACM-SIAM Sympos. Discrete Algorithms (SODA)"
|
||||
, url = "https://hal.inria.fr/inria-00166710/"
|
||||
, url = "https://inria.hal.science/inria-00166710/"
|
||||
, year = 2003
|
||||
, pages = "313-319"
|
||||
}
|
||||
|
|
@ -778,7 +778,7 @@ Teillaud"
|
|||
, volume = 44
|
||||
, year = 2011
|
||||
, pages = "160--168"
|
||||
, url = "https://hal.archives-ouvertes.fr/inria-00560388/"
|
||||
, url = "https://theses.hal.science/inria-00560388/"
|
||||
, doi = "10.1016/j.comgeo.2010.09.010"
|
||||
}
|
||||
|
||||
|
|
@ -845,7 +845,7 @@ Teillaud"
|
|||
,school = "Universit\'e de {Nice-Sophia Antipolis}"
|
||||
,address = "France"
|
||||
,year = 2003
|
||||
,url = "https://tel.archives-ouvertes.fr/tel-00832487/"
|
||||
,url = "https://theses.hal.science/tel-00832487/"
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1230,7 +1230,7 @@ Teillaud"
|
|||
TITLE = {{Implementing Delaunay triangulations of the Bolza surface}},
|
||||
YEAR = {2017},
|
||||
DOI = {10.4230/LIPIcs.SoCG.2017.44},
|
||||
URL = {https://hal.inria.fr/hal-01568002},
|
||||
URL = {https://inria.hal.science/hal-01568002},
|
||||
}
|
||||
|
||||
@inproceedings{cgal:j-lrsspp-19,
|
||||
|
|
@ -1261,13 +1261,13 @@ Teillaud"
|
|||
|
||||
|
||||
@InProceedings{ cgal:k-reisv-04,
|
||||
author = {Menelaos I. Karavelas},
|
||||
title = {A robust and efficient implementation for the segment
|
||||
author = {Menelaos I. Karavelas},
|
||||
title = {A robust and efficient implementation for the segment
|
||||
{V}oronoi diagram},
|
||||
booktitle = {Proc. Internat. Symp. on Voronoi diagrams in Science
|
||||
and Engineering (VD2004)},
|
||||
pages = {51--62},
|
||||
year = {2004}
|
||||
pages = {51--62},
|
||||
year = {2004}
|
||||
}
|
||||
|
||||
@article{ cgal:k-rprnm-96
|
||||
|
|
@ -1599,12 +1599,12 @@ ABSTRACT = {We present the first complete, exact and efficient C++ implementatio
|
|||
}
|
||||
|
||||
@article{cgal:ml-cfsg-00
|
||||
, author = "G. Medioni and M. Lee and C. Tang"
|
||||
, title = "A Computational Framework for Segmentation and Grouping"
|
||||
, journal = "Elsevier Science"
|
||||
, year = 2000
|
||||
, pages = ""
|
||||
, update = "12.13 afabri"
|
||||
, author = "G. Medioni and M. Lee and C. Tang"
|
||||
, title = "A Computational Framework for Segmentation and Grouping"
|
||||
, journal = "Elsevier Science"
|
||||
, year = 2000
|
||||
, pages = ""
|
||||
, update = "12.13 afabri"
|
||||
}
|
||||
|
||||
@book{ cgal:m-cst-93
|
||||
|
|
@ -1887,28 +1887,28 @@ ABSTRACT = {We present the first complete, exact and efficient C++ implementatio
|
|||
@article{cgal:btsag-asosr-16,
|
||||
TITLE = {{A Survey of Surface Reconstruction from Point Clouds}},
|
||||
AUTHOR = {Berger, Matthew and Tagliasacchi, Andrea and Seversky, Lee and Alliez, Pierre and Guennebaud, Gael and Levine, Joshua and Sharf, Andrei and Silva, Claudio},
|
||||
URL = {https://hal.inria.fr/hal-01348404},
|
||||
URL = {https://inria.hal.science/hal-01348404},
|
||||
JOURNAL = {{Computer Graphics Forum}},
|
||||
PUBLISHER = {{Wiley}},
|
||||
PAGES = {27},
|
||||
YEAR = {2016},
|
||||
DOI = {10.1111/cgf.12802},
|
||||
PDF = {https://hal.inria.fr/hal-01348404/file/survey-author.pdf},
|
||||
PDF = {https://inria.hal.science/hal-01348404/file/survey-author.pdf},
|
||||
HAL_ID = {hal-01348404},
|
||||
HAL_VERSION = {v2}
|
||||
}
|
||||
|
||||
|
||||
@TechReport{ cgal:pabl-cco-07,
|
||||
author = {Poudret, M. and Arnould, A. and Bertrand, Y. and Lienhardt, P.},
|
||||
title = {Cartes Combinatoires Ouvertes.},
|
||||
institution = {Laboratoire SIC E.A. 4103},
|
||||
number = {2007-1},
|
||||
month = {October},
|
||||
year = {2007},
|
||||
address = {F-86962 Futuroscope Cedex, France},
|
||||
type = {Research Notes},
|
||||
keywords = {cartes combinatoires, demi-ar{\^e}te, ar{\^e}te radiale},
|
||||
author = {Poudret, M. and Arnould, A. and Bertrand, Y. and Lienhardt, P.},
|
||||
title = {Cartes Combinatoires Ouvertes.},
|
||||
institution = {Laboratoire SIC E.A. 4103},
|
||||
number = {2007-1},
|
||||
month = {October},
|
||||
year = {2007},
|
||||
address = {F-86962 Futuroscope Cedex, France},
|
||||
type = {Research Notes},
|
||||
keywords = {cartes combinatoires, demi-ar{\^e}te, ar{\^e}te radiale},
|
||||
}
|
||||
|
||||
@article{ cgal:pc-rdp-86
|
||||
|
|
@ -2293,7 +2293,7 @@ location = {Salt Lake City, Utah, USA}
|
|||
, pages = "75:1-75:9"
|
||||
, note = "SIGGRAPH '2009 Conference Proceedings"
|
||||
, volume = "28(3)"
|
||||
, url = "https://hal.inria.fr/inria-00359288"
|
||||
, url = "https://inria.hal.science/inria-00359288"
|
||||
, geombib = "not yet"
|
||||
, x-editorial-board = {yes}
|
||||
, x-proceedings = {yes}
|
||||
|
|
@ -2332,7 +2332,7 @@ location = {Salt Lake City, Utah, USA}
|
|||
,month = jun
|
||||
,pages = {26--31}
|
||||
,annote = {Inlining vector expressions and parameter passing
|
||||
of expressions at compile time. Template Metaprograms.}
|
||||
of expressions at compile time. Template Metaprograms.}
|
||||
,update = "98.01 kettner"
|
||||
}
|
||||
|
||||
|
|
@ -2354,7 +2354,7 @@ location = {Salt Lake City, Utah, USA}
|
|||
,month = may
|
||||
,pages = {36--43}
|
||||
,annote = {Prime numbers at compiler time, C++ programs at
|
||||
compile time, control structures, local variables.}
|
||||
compile time, control structures, local variables.}
|
||||
,update = "98.01 kettner"
|
||||
}
|
||||
|
||||
|
|
@ -2422,7 +2422,7 @@ location = {Salt Lake City, Utah, USA}
|
|||
@book{ cgal:w-impoo-94
|
||||
,author = {Josie Wernicke}
|
||||
,title = {The Inventor Mentor: Programming Object-Oriented
|
||||
3D Graphics with Open Inventor, Release 2}
|
||||
3D Graphics with Open Inventor, Release 2}
|
||||
,publisher = {Addison-Wesley}
|
||||
,year = 1994
|
||||
,update = "97.04 kettner"
|
||||
|
|
@ -2549,12 +2549,12 @@ url = "https://wscg.zcu.cz/wscg2003/Papers_2003/G67.pdf"
|
|||
}
|
||||
|
||||
@InProceedings{cgal:k-vdc-06,
|
||||
author = {Menelaos I. Karavelas},
|
||||
title = {Voronoi diagrams in {\sc Cgal}},
|
||||
author = {Menelaos I. Karavelas},
|
||||
title = {Voronoi diagrams in {\sc Cgal}},
|
||||
booktitle = {22nd European Symposium on Computational Geometry},
|
||||
pages = {229--232},
|
||||
year = {2006},
|
||||
address = {Delphi, Greece},
|
||||
pages = {229--232},
|
||||
year = {2006},
|
||||
address = {Delphi, Greece},
|
||||
}
|
||||
|
||||
@incollection{cgal:fhktww-a-07,
|
||||
|
|
@ -2607,27 +2607,27 @@ url = "https://www.boost.org/community/exception_safety.html"
|
|||
}
|
||||
|
||||
@article{cgal:as-solri-92
|
||||
, author = "F. Aurenhammer and O. Schwarzkopf"
|
||||
, title = "A simple on-line randomized incremental algorithm for computing higher order {Voronoi} diagrams"
|
||||
, journal = "Internat. J. Comput. Geom. Appl."
|
||||
, volume = 2
|
||||
, year = 1992
|
||||
, pages = "363--381"
|
||||
, keywords = "Voronoi diagrams, geometric transforms, dynamization"
|
||||
, succeeds = "as-solri-91"
|
||||
, update = "93.09 aurenhammer, 93.05 schwarzkopf"
|
||||
, author = "F. Aurenhammer and O. Schwarzkopf"
|
||||
, title = "A simple on-line randomized incremental algorithm for computing higher order {Voronoi} diagrams"
|
||||
, journal = "Internat. J. Comput. Geom. Appl."
|
||||
, volume = 2
|
||||
, year = 1992
|
||||
, pages = "363--381"
|
||||
, keywords = "Voronoi diagrams, geometric transforms, dynamization"
|
||||
, succeeds = "as-solri-91"
|
||||
, update = "93.09 aurenhammer, 93.05 schwarzkopf"
|
||||
}
|
||||
|
||||
@inproceedings{cgal:fy-okvd-01
|
||||
, author = "Julia Fl{\"o}totto and Mariette Yvinec"
|
||||
, title = "Order-$k$ {Voronoi} Diagrams"
|
||||
, booktitle = "Abstracts 17th European Workshop Comput. Geom."
|
||||
, nickname = "CG 2001"
|
||||
, site = "Berlin"
|
||||
, publisher = "Freie Universit{\"a}t Berlin"
|
||||
, year = 2001
|
||||
, pages = "109--112"
|
||||
, update = "01.04 icking"
|
||||
, author = "Julia Fl{\"o}totto and Mariette Yvinec"
|
||||
, title = "Order-$k$ {Voronoi} Diagrams"
|
||||
, booktitle = "Abstracts 17th European Workshop Comput. Geom."
|
||||
, nickname = "CG 2001"
|
||||
, site = "Berlin"
|
||||
, publisher = "Freie Universit{\"a}t Berlin"
|
||||
, year = 2001
|
||||
, pages = "109--112"
|
||||
, update = "01.04 icking"
|
||||
}
|
||||
|
||||
@proceedings{cgal:jlm-isgp-98,
|
||||
|
|
@ -2768,7 +2768,7 @@ author = "Pedro M.M. de Castro and Frederic Cazals and Sebastien Loriot and Moni
|
|||
, volume = "40"
|
||||
, number = "1"
|
||||
, pages = "61-78"
|
||||
, url = "https://hal.inria.fr/inria-00344310/"
|
||||
, url = "https://inria.hal.science/inria-00344310/"
|
||||
, doi = "10.1016/j.comgeo.2007.06.003"
|
||||
, x-international-audience = "yes"
|
||||
, x-editorial-board = "yes"
|
||||
|
|
@ -2788,7 +2788,7 @@ author = "Pedro M.M. de Castro and Frederic Cazals and Sebastien Loriot and Moni
|
|||
, title = "Complexity of {Delaunay} triangulation for points on lower-dimensional polyhedra"
|
||||
, booktitle = "Proc. 18th ACM-SIAM Sympos. Discrete Algorithms"
|
||||
, nickname = "SODA"
|
||||
, url = "https://hal.inria.fr/inria-00182835/"
|
||||
, url = "https://inria.hal.science/inria-00182835/"
|
||||
, year = 2007
|
||||
, pages = "1106--1113"
|
||||
}
|
||||
|
|
@ -2856,14 +2856,14 @@ ADDRESS = "Saarbr{\"u}cken, Germany"
|
|||
}
|
||||
|
||||
@InCollection{grlr-sturm-habicht-98,
|
||||
author = {L.~Gonzalez-Vega and T.~Recio and H.~Lombardi and M.-F.~Roy},
|
||||
title = {Sturm-Habicht Sequences, Determinants and Real Roots of Univariate Polynomials},
|
||||
booktitle = {Quantifier Elimination and Cylindrical Algebraic Decomposition},
|
||||
pages = {300--316},
|
||||
publisher = {Springer},
|
||||
year = 1998,
|
||||
editor = {B.F.~Caviness and J.R.~Johnson},
|
||||
series = {Texts and Monographs in Symbolic Computation}
|
||||
author = {L.~Gonzalez-Vega and T.~Recio and H.~Lombardi and M.-F.~Roy},
|
||||
title = {Sturm-Habicht Sequences, Determinants and Real Roots of Univariate Polynomials},
|
||||
booktitle = {Quantifier Elimination and Cylindrical Algebraic Decomposition},
|
||||
pages = {300--316},
|
||||
publisher = {Springer},
|
||||
year = 1998,
|
||||
editor = {B.F.~Caviness and J.R.~Johnson},
|
||||
series = {Texts and Monographs in Symbolic Computation}
|
||||
}
|
||||
|
||||
@inproceedings{Sorkine2007AsRigidAs,
|
||||
|
|
@ -3213,14 +3213,14 @@ pages = "207--221"
|
|||
@techreport{frey:inria-00069921,
|
||||
TITLE = {{MEDIT : An interactive Mesh visualization Software}},
|
||||
AUTHOR = {Frey, Pascal},
|
||||
URL = {https://hal.inria.fr/inria-00069921},
|
||||
URL = {https://inria.hal.science/inria-00069921},
|
||||
NUMBER = {RT-0253},
|
||||
PAGES = {41},
|
||||
INSTITUTION = {{INRIA}},
|
||||
YEAR = {2001},
|
||||
MONTH = Dec,
|
||||
KEYWORDS = {MESH ; VISUALIZATION ; POST-PROCESSING},
|
||||
PDF = {https://hal.inria.fr/inria-00069921/file/RT-0253.pdf},
|
||||
PDF = {https://inria.hal.science/inria-00069921/file/RT-0253.pdf},
|
||||
HAL_ID = {inria-00069921},
|
||||
HAL_VERSION = {v1}
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -172,9 +172,9 @@ ALIASES = "cgal=%CGAL" \
|
|||
"cgalPkgSince{1}=<B>Introduced in:</B> \cgal \1<BR>" \
|
||||
"cgalPkgDependsOn{1}=<B>Depends on:</B> \1 <BR>" \
|
||||
"cgalPkgLicense{1}=<B>License:</B> \1 <BR>" \
|
||||
"cgalPkgDemo{2}=<B>Windows demo:</B> <a href=\"https://www.cgal.org/demo/${CGAL_CREATED_VERSION_NUM}/\2\">\1</a><BR><B>Common demo dlls:</B> <a href=\"https://www.cgal.org/demo/${CGAL_CREATED_VERSION_NUM}/CGAL-demoDLLs.zip\">dlls</a><BR>" \
|
||||
"cgalPkgDemo{4}=<B>Windows demos:</B> <a href=\"https://www.cgal.org/demo/${CGAL_CREATED_VERSION_NUM}/\2\">\1</a>, <a href=\"https://www.cgal.org/demo/${CGAL_CREATED_VERSION_NUM}/\4\">\3</a><BR><B>Common demo dlls:</B> <a href=\"https://www.cgal.org/demo/${CGAL_CREATED_VERSION_NUM}/CGAL-demoDLLs.zip\">dlls</a><BR>" \
|
||||
"cgalPkgDemo{6}=<B>Windows demos:</B> <a href=\"https://www.cgal.org/demo/${CGAL_CREATED_VERSION_NUM}/\2\">\1</a>, <a href=\"https://www.cgal.org/demo/${CGAL_CREATED_VERSION_NUM}/\4\">\3</a>, <a href=\"https://www.cgal.org/demo/${CGAL_CREATED_VERSION_NUM}/\6\">\5</a><BR><B>Common demo dlls:</B> <a href=\"https://www.cgal.org/demo/${CGAL_CREATED_VERSION_NUM}/CGAL-demoDLLs.zip\">dlls</a><BR>" \
|
||||
"cgalPkgDemo{2}=<B>Windows Demo:</B> <a href=\"https://www.cgal.org/demo/${CGAL_CREATED_VERSION_NUM}/\2\">\1</a><BR>" \
|
||||
"cgalPkgDemo{4}=<B>Windows Demos:</B> <a href=\"https://www.cgal.org/demo/${CGAL_CREATED_VERSION_NUM}/\2\">\1</a>, <a href=\"https://www.cgal.org/demo/${CGAL_CREATED_VERSION_NUM}/\4\">\3</a><BR>" \
|
||||
"cgalPkgDemo{6}=<B>Windows Demos:</B> <a href=\"https://www.cgal.org/demo/${CGAL_CREATED_VERSION_NUM}/\2\">\1</a>, <a href=\"https://www.cgal.org/demo/${CGAL_CREATED_VERSION_NUM}/\4\">\3</a>, <a href=\"https://www.cgal.org/demo/${CGAL_CREATED_VERSION_NUM}/\6\">\5</a><BR>" \
|
||||
"cgalPkgDescriptionEnd=" \
|
||||
"cgalModifBegin=\htmlonly <div class=\"CGALModification\"> \endhtmlonly \xrefitem Modification \"Modifications\" \"MODIFICATIONS\" " \
|
||||
"cgalModifEnd=\htmlonly </div> \endhtmlonly \latexonly END MODIFICATIONS \endlatexonly" \
|
||||
|
|
|
|||
|
|
@ -181,9 +181,9 @@ ALIASES = "cgal=%CGAL" \
|
|||
"cgalPkgSince{1}=<B>Introduced in:</B> \cgal \1<BR>" \
|
||||
"cgalPkgDependsOn{1}=<B>Depends on:</B> \1 <BR>" \
|
||||
"cgalPkgLicense{1}=<B>License:</B> \1 <BR>" \
|
||||
"cgalPkgDemo{2}=<B>Windows demo:</B> <a href=\"https://www.cgal.org/demo/${CGAL_CREATED_VERSION_NUM}/\2\">\1</a><BR><B>Common demo dlls:</B> <a href=\"https://www.cgal.org/demo/${CGAL_CREATED_VERSION_NUM}/CGAL-demoDLLs.zip\">dlls</a><BR>" \
|
||||
"cgalPkgDemo{4}=<B>Windows demos:</B> <a href=\"https://www.cgal.org/demo/${CGAL_CREATED_VERSION_NUM}/\2\">\1</a>, <a href=\"https://www.cgal.org/demo/${CGAL_CREATED_VERSION_NUM}/\4\">\3</a><BR><B>Common demo dlls:</B> <a href=\"https://www.cgal.org/demo/${CGAL_CREATED_VERSION_NUM}/CGAL-demoDLLs.zip\">dlls</a><BR>" \
|
||||
"cgalPkgDemo{6}=<B>Windows demos:</B> <a href=\"https://www.cgal.org/demo/${CGAL_CREATED_VERSION_NUM}/\2\">\1</a>, <a href=\"https://www.cgal.org/demo/${CGAL_CREATED_VERSION_NUM}/\4\">\3</a>, <a href=\"https://www.cgal.org/demo/${CGAL_CREATED_VERSION_NUM}/\6\">\5</a><BR><B>Common demo dlls:</B> <a href=\"https://www.cgal.org/demo/${CGAL_CREATED_VERSION_NUM}/CGAL-demoDLLs.zip\">dlls</a><BR>" \
|
||||
"cgalPkgDemo{2}=<B>Windows Demo:</B> <a href=\"https://www.cgal.org/demo/${CGAL_CREATED_VERSION_NUM}/\2\">\1</a><BR>" \
|
||||
"cgalPkgDemo{4}=<B>Windows Demos:</B> <a href=\"https://www.cgal.org/demo/${CGAL_CREATED_VERSION_NUM}/\2\">\1</a>, <a href=\"https://www.cgal.org/demo/${CGAL_CREATED_VERSION_NUM}/\4\">\3</a><BR>" \
|
||||
"cgalPkgDemo{6}=<B>Windows Demos:</B> <a href=\"https://www.cgal.org/demo/${CGAL_CREATED_VERSION_NUM}/\2\">\1</a>, <a href=\"https://www.cgal.org/demo/${CGAL_CREATED_VERSION_NUM}/\4\">\3</a>, <a href=\"https://www.cgal.org/demo/${CGAL_CREATED_VERSION_NUM}/\6\">\5</a><BR>" \
|
||||
"cgalPkgDescriptionEnd=" \
|
||||
"cgalModifBegin=\htmlonly <div class=\"CGALModification\"> \endhtmlonly \xrefitem Modification \"Modifications\" \"MODIFICATIONS\"" \
|
||||
"cgalModifEnd=\htmlonly </div> \endhtmlonly \latexonly END MODIFICATIONS \endlatexonly" \
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ pre_html=r"""<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "htt
|
|||
<link rel="icon" type="image/png" href="../Manual/g-196x196-doc.png"/>
|
||||
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
|
||||
<link href="stylesheet.css" rel="stylesheet" type="text/css" />
|
||||
<link href="cgal_stylesheet.css" rel="stylesheet" type="text/css" />
|
||||
<title>CGAL ${CGAL_CREATED_VERSION_NUM} - Manual: Acknowledging CGAL</title>
|
||||
</head>
|
||||
<body>
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ def clean_doc():
|
|||
duplicate_files=list(package_glob('./*/jquery.js'))
|
||||
duplicate_files.extend(package_glob('./*/dynsections.js'))
|
||||
duplicate_files.extend(package_glob('./*/resize.js'))
|
||||
duplicate_files.extend(package_glob('./*/stylesheet.css'))
|
||||
duplicate_files.extend(package_glob('./*/cgal_stylesheet.css'))
|
||||
# kill _all_, including the one in CGAL tabs.css files
|
||||
duplicate_files.extend(glob.glob('./*/tabs.css'))
|
||||
# left-over by doxygen?
|
||||
|
|
|
|||
|
|
@ -571,7 +571,7 @@ Let <I>d0</I> \f$ \in \f$ <I>D</I> be a dart. Given <I>i</I>, 0 \f$ \leq \f$ <I>
|
|||
|
||||
\section Generalized_mapDesign Design and Implementation History
|
||||
|
||||
The code of this package followed the code of Combinatorial maps and was inspired by Moka, a 3D topological modeler that uses 3D generalized maps (<A HREF="https://moka-modeller.sourceforge.net/">https://moka-modeller.sourceforge.net/</A>).
|
||||
The code of this package followed the code of Combinatorial maps and was inspired by Moka, a 3D topological modeler that uses 3D generalized maps (see https://projet.liris.cnrs.fr/moka/index.php and https://github.com/gdamiand/moka).
|
||||
|
||||
*/
|
||||
} /* namespace CGAL */
|
||||
|
|
|
|||
|
|
@ -7,6 +7,15 @@ project(Bounding_volumes_Demo)
|
|||
find_package(CGAL REQUIRED OPTIONAL_COMPONENTS Qt6)
|
||||
|
||||
find_package(Qt6 QUIET COMPONENTS Widgets)
|
||||
|
||||
find_package(Eigen3 3.1.91 QUIET) #(requires 3.1.91 or greater)
|
||||
include(CGAL_Eigen3_support)
|
||||
|
||||
if(NOT TARGET CGAL::Eigen3_support)
|
||||
message("NOTICE: This demo requires CGAL and Eigen, and will not be compiled.")
|
||||
return()
|
||||
endif()
|
||||
|
||||
if(CGAL_Qt6_FOUND AND Qt6_FOUND)
|
||||
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
|
|
@ -21,7 +30,8 @@ if(CGAL_Qt6_FOUND AND Qt6_FOUND)
|
|||
add_to_cached_list(CGAL_EXECUTABLE_TARGETS Bounding_volumes)
|
||||
|
||||
target_link_libraries(Bounding_volumes PRIVATE CGAL::CGAL CGAL::CGAL_Qt6
|
||||
Qt6::Widgets)
|
||||
Qt6::Widgets
|
||||
CGAL::Eigen3_support)
|
||||
|
||||
include(${CGAL_MODULES_DIR}/CGAL_add_test.cmake)
|
||||
cgal_add_compilation_test(Bounding_volumes)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
#ifndef ELLIPSE_H
|
||||
#define ELLIPSE_H
|
||||
|
||||
#include <Eigen/Dense>
|
||||
#include <Eigen/Eigenvalues>
|
||||
|
||||
template <class R>
|
||||
class Ellipse_2 {
|
||||
|
||||
|
|
@ -20,50 +23,51 @@ template <class R>
|
|||
CGAL::Simple_cartesian<double>::Conic_2 co;
|
||||
me.ellipse().double_conic(co);
|
||||
|
||||
double a11 = co.r();
|
||||
double a12 = co.t()/2.0;
|
||||
double a22 = co.s();
|
||||
double b1 = co.u();
|
||||
double b2 = co.v();
|
||||
double c = co.w();
|
||||
// https://en.wikipedia.org/wiki/Matrix_representation_of_conic_sections
|
||||
double A = co.r();
|
||||
double B = co.t();
|
||||
double C = co.s();
|
||||
double D = co.u();
|
||||
double E = co.v();
|
||||
double F = co.w();
|
||||
|
||||
assert(a11*a22-a12*a12 >= 0);
|
||||
assert(A * C - B*B/4 >= 0);
|
||||
|
||||
double delta = (a11>a22)? a11-a22 : a22-a11;
|
||||
if( (delta < 0.00000000001) && (a12 == 0)){
|
||||
ce = Point_2(-b1/(2*a11), -b2/(2*a11));
|
||||
a_ = b_ = std::sqrt(b1*b1+b2*b2-4*a11*c)/(2*a11);
|
||||
va_ = Vector_2(a_, 0);
|
||||
vb_ = Vector_2(0, b_);
|
||||
return;
|
||||
}
|
||||
Eigen::Matrix2d A33, A33i;
|
||||
A33 << A, B/2, B/2, C;
|
||||
A33i = A33.inverse();
|
||||
|
||||
double kden = 2.0*(a12*a12 - a11*a22);
|
||||
double k1 = (a22*b1 - a12*b2)/kden;
|
||||
double k2 = (a11*b2 - a12*b1)/kden;
|
||||
ce = Point_2(k1,k2);
|
||||
double mu = 1/(a11*k1*k1 + 2.0*a12*k1*k2 + a22*k2*k2 - c);
|
||||
double m11 = mu*a11;
|
||||
double m12 = mu*a12;
|
||||
double m22 = mu*a22;
|
||||
Eigen::Vector2d v;
|
||||
v << -D/2 , -E/2;
|
||||
|
||||
double r = std::sqrt((m11-m22)*(m11-m22) + 4.0*m12*m12);
|
||||
double lambda1 = ((m11+m22) + r)/2.0;
|
||||
double lambda2 = ((m11+m22) - r)/2.0;
|
||||
v = A33i * v;
|
||||
|
||||
b_ = 1.0/sqrt(lambda1);
|
||||
a_ = 1.0/sqrt(lambda2);
|
||||
double omega = 1.0/
|
||||
std::sqrt((lambda1-m22)*(lambda1-m22) + m12*m12);
|
||||
ce = Point_2(v[0],v[1]);
|
||||
|
||||
double u1x = - a_ * omega*m12;
|
||||
double u1y = a_ * omega * (lambda1-m22);
|
||||
Eigen::EigenSolver<Eigen::Matrix2d> es(A33);
|
||||
|
||||
double u2x = b_* omega * (lambda1-m22);
|
||||
double u2y = b_* omega*m12;
|
||||
Eigen::Matrix2cd ev;
|
||||
ev = es.eigenvectors();
|
||||
double x0 = ev.col(0)[0].real();
|
||||
double y0 = ev.col(0)[1].real();
|
||||
double x1 = ev.col(1)[0].real();
|
||||
double y1 = ev.col(1)[1].real();
|
||||
|
||||
va_ = Vector_2(u1x,u1y);
|
||||
vb_ = Vector_2(u2x,u2y);
|
||||
double lambda1 = es.eigenvalues()[0].real();
|
||||
double lambda2 = es.eigenvalues()[1].real();
|
||||
|
||||
Eigen::Matrix3d AQ;
|
||||
AQ << A, B/2, D/2,
|
||||
B/2, C, E/2,
|
||||
D/2, E/2, F;
|
||||
|
||||
double K = AQ.determinant() / A33.determinant();
|
||||
|
||||
a_ = sqrt(-K/lambda1);
|
||||
b_ = sqrt(-K/lambda2);
|
||||
|
||||
va_ = a_ * Vector_2(x0,y0);
|
||||
vb_ = b_ * Vector_2(x1,y1);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
0 2
|
||||
2 1
|
||||
0 0
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
-2 1
|
||||
-2 -1
|
||||
2 1
|
||||
2 -1
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
-2 -1
|
||||
-1 -2
|
||||
1 2
|
||||
2 1
|
||||
|
|
@ -746,17 +746,23 @@ protected:
|
|||
fit->info().is_process = false;
|
||||
}
|
||||
// (2.2) We check if the facet is external or internal
|
||||
std::queue<typename CDT::Face_handle> face_queue;
|
||||
typename CDT::Face_handle face_internal = nullptr;
|
||||
std::queue<typename CDT::Face_handle> face_queue, faces_internal;
|
||||
if (cdt.infinite_vertex()->face()!=nullptr)
|
||||
{ face_queue.push(cdt.infinite_vertex()->face()); }
|
||||
{
|
||||
typename CDT::Face_circulator
|
||||
incident_faces(cdt.infinite_vertex()), end_incident_faces(incident_faces);
|
||||
do
|
||||
{ face_queue.push(incident_faces); }
|
||||
while(++incident_faces!=end_incident_faces);
|
||||
}
|
||||
// std::cout<<"# faces PUSHED "<<face_queue.size()<<std::endl;
|
||||
while(!face_queue.empty())
|
||||
{
|
||||
typename CDT::Face_handle fh = face_queue.front();
|
||||
typename CDT::Face_handle fh=face_queue.front();
|
||||
face_queue.pop();
|
||||
if(!fh->info().is_process)
|
||||
{
|
||||
fh->info().is_process = true;
|
||||
fh->info().is_process=true;
|
||||
for(int i=0; i<3; ++i)
|
||||
{
|
||||
if(!cdt.is_constrained(std::make_pair(fh, i)))
|
||||
|
|
@ -764,21 +770,16 @@ protected:
|
|||
if (fh->neighbor(i)!=nullptr)
|
||||
{ face_queue.push(fh->neighbor(i)); }
|
||||
}
|
||||
else if (face_internal==nullptr)
|
||||
{
|
||||
face_internal = fh->neighbor(i);
|
||||
}
|
||||
else
|
||||
{ faces_internal.push(fh->neighbor(i)); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( face_internal!=nullptr )
|
||||
{ face_queue.push(face_internal); }
|
||||
|
||||
while(!face_queue.empty())
|
||||
while(!faces_internal.empty())
|
||||
{
|
||||
typename CDT::Face_handle fh = face_queue.front();
|
||||
face_queue.pop();
|
||||
typename CDT::Face_handle fh=faces_internal.front();
|
||||
faces_internal.pop();
|
||||
if(!fh->info().is_process)
|
||||
{
|
||||
fh->info().is_process = true;
|
||||
|
|
@ -788,7 +789,7 @@ protected:
|
|||
if(!cdt.is_constrained(std::make_pair(fh, i)))
|
||||
{
|
||||
if (fh->neighbor(i)!=nullptr)
|
||||
{ face_queue.push(fh->neighbor(i)); }
|
||||
{ faces_internal.push(fh->neighbor(i)); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,5 +8,5 @@ is available in:
|
|||
Mikhail Bogdanov, Olivier Devillers, and Monique Teillaud. Hyperbolic
|
||||
Delaunay complexes and Voronoi diagrams made practical. Journal of
|
||||
Computational Geometry, 5(1):56–85, 2014.
|
||||
URL: https://hal.inria.fr/hal-00961390,
|
||||
doi:10.20382/jocg.v5i1a4.
|
||||
URL: https://inria.hal.science/hal-00961390,
|
||||
doi:10.20382/jocg.v5i1a4.
|
||||
|
|
|
|||
|
|
@ -37,6 +37,10 @@ Release date: October 2023
|
|||
- Removed the class templates `Gray_image_mesh_domain_3`, `Implicit_mesh_domain_3`, and `Labeled_image_mesh_domain_3`
|
||||
which are deprecated since CGAL-4.13.
|
||||
|
||||
### [2D Arrangements](https://doc.cgal.org/6.0/Manual/packages.html#PkgArrangementOnSurface2)
|
||||
- Fixed a bug in the zone construction code applied to arrangements of geodesic arcs on a sphere,
|
||||
when inserting an arc that lies on the identification curve.
|
||||
|
||||
### [Tetrahedral Remeshing](https://doc.cgal.org/6.0/Manual/packages.html#PkgTetrahedralRemeshing)
|
||||
- **Breaking change**: The template parameters of
|
||||
`CGAL::Tetrahedral_remeshing::Remeshing_cell_base_3`
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
namespace CGAL {
|
||||
|
||||
/*!
|
||||
\ingroup kernel_affine
|
||||
\ingroup kernel_classes2
|
||||
|
||||
The class `Aff_transformation_2` represents two-dimensional affine transformations.
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ namespace CGAL {
|
|||
|
||||
/*!
|
||||
\ingroup kernel_classes3
|
||||
\ingroup kernel_affine
|
||||
|
||||
The class `Aff_transformation_3` represents three-dimensional affine transformations.
|
||||
The general form of an affine transformation is based on a homogeneous
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
namespace CGAL {
|
||||
|
||||
/*!
|
||||
\ingroup kernel_affine
|
||||
\ingroup PkgKernel23Ref
|
||||
|
||||
Tag class for affine transformations.
|
||||
|
||||
|
|
@ -24,7 +24,7 @@ public:
|
|||
namespace CGAL {
|
||||
|
||||
/*!
|
||||
\ingroup kernel_affine
|
||||
\ingroup PkgKernel23Ref
|
||||
|
||||
Tag class for affine transformations.
|
||||
|
||||
|
|
@ -46,7 +46,7 @@ public:
|
|||
namespace CGAL {
|
||||
|
||||
/*!
|
||||
\ingroup kernel_affine
|
||||
\ingroup PkgKernel23Ref
|
||||
|
||||
Tag class for affine transformations.
|
||||
|
||||
|
|
@ -68,7 +68,7 @@ public:
|
|||
namespace CGAL {
|
||||
|
||||
/*!
|
||||
\ingroup kernel_affine
|
||||
\ingroup PkgKernel23Ref
|
||||
|
||||
Tag class for affine transformations.
|
||||
|
||||
|
|
@ -90,7 +90,7 @@ public:
|
|||
namespace CGAL {
|
||||
|
||||
/*!
|
||||
\ingroup kernel_affine
|
||||
\ingroup PkgKernel23Ref
|
||||
|
||||
Tag class for affine transformations.
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ function are available.
|
|||
|
||||
/*!
|
||||
\addtogroup do_intersect_linear_grp
|
||||
\ingroup do_intersect
|
||||
\ingroup do_intersect_grp
|
||||
|
||||
\sa `do_intersect_circular_grp`
|
||||
\sa `do_intersect_spherical_grp`
|
||||
|
|
@ -79,7 +79,7 @@ function are available.
|
|||
|
||||
/*!
|
||||
\addtogroup intersection_linear_grp
|
||||
\ingroup intersection
|
||||
\ingroup intersection_grp
|
||||
|
||||
*/
|
||||
/// @{
|
||||
|
|
|
|||
|
|
@ -99,14 +99,14 @@ namespace CGAL {
|
|||
{};
|
||||
template<int i>
|
||||
struct Attribute_const_descriptor:
|
||||
public Helper::template Attribute_const_descriptor<i>
|
||||
public Helper::template Attribute_const_descriptor<i>
|
||||
{};
|
||||
template<int i>
|
||||
struct Attribute_range: public Helper::template Attribute_range<i>
|
||||
{};
|
||||
template<int i>
|
||||
struct Attribute_const_range:
|
||||
public Helper::template Attribute_const_range<i>
|
||||
public Helper::template Attribute_const_range<i>
|
||||
{};
|
||||
|
||||
typedef typename Attribute_type<0>::type Vertex_attribute;
|
||||
|
|
@ -169,6 +169,10 @@ namespace CGAL {
|
|||
{ return mmap.mdarts.is_used(i); }
|
||||
bool owns(size_type i) const
|
||||
{ return mmap.mdarts.owns(i); }
|
||||
size_type capacity() const
|
||||
{ return mmap.mdarts.capacity(); }
|
||||
size_type upper_bound() const
|
||||
{ return mmap.mdarts.upper_bound(); }
|
||||
private:
|
||||
Self & mmap;
|
||||
};
|
||||
|
|
@ -202,7 +206,7 @@ namespace CGAL {
|
|||
* @return true iff the map is empty.
|
||||
*/
|
||||
bool is_empty() const
|
||||
{ return darts().empty(); }
|
||||
{ return darts().empty(); }
|
||||
|
||||
/// @return the number of darts.
|
||||
size_type number_of_darts() const
|
||||
|
|
@ -288,18 +292,18 @@ namespace CGAL {
|
|||
typename Attribute_descriptor<i>::type attribute(Dart_descriptor ADart)
|
||||
{
|
||||
static_assert(Helper::template Dimension_index<i>::value>=0,
|
||||
"attribute<i> called but i-attributes are disabled.");
|
||||
"attribute<i> called but i-attributes are disabled.");
|
||||
return std::get<Helper::template Dimension_index<i>::value>
|
||||
(mdarts[ADart].mattribute_descriptors);
|
||||
(mdarts[ADart].mattribute_descriptors);
|
||||
}
|
||||
template<unsigned int i>
|
||||
typename Attribute_const_descriptor<i>::type
|
||||
attribute(Dart_const_descriptor ADart) const
|
||||
{
|
||||
static_assert(Helper::template Dimension_index<i>::value>=0,
|
||||
"attribute<i> called but i-attributes are disabled.");
|
||||
"attribute<i> called but i-attributes are disabled.");
|
||||
return std::get<Helper::template Dimension_index<i>::value>
|
||||
(mdarts[ADart].mattribute_descriptors);
|
||||
(mdarts[ADart].mattribute_descriptors);
|
||||
}
|
||||
|
||||
// Copy a given attribute
|
||||
|
|
@ -360,7 +364,7 @@ namespace CGAL {
|
|||
{
|
||||
CGAL_assertion( ah!=null_descriptor );
|
||||
return std::get<Helper::template Dimension_index<i>::value>
|
||||
(mattribute_containers)[ah];
|
||||
(mattribute_containers)[ah];
|
||||
}
|
||||
template<unsigned int i>
|
||||
const typename Attribute_type<i>::type&
|
||||
|
|
@ -368,7 +372,7 @@ namespace CGAL {
|
|||
{
|
||||
CGAL_assertion( ah!=null_descriptor );
|
||||
return std::get<Helper::template Dimension_index<i>::value>
|
||||
(mattribute_containers)[ah];
|
||||
(mattribute_containers)[ah];
|
||||
}
|
||||
|
||||
// Get the dart of the given attribute
|
||||
|
|
@ -486,14 +490,14 @@ namespace CGAL {
|
|||
typename Attribute_descriptor<i>::type ah)
|
||||
{
|
||||
std::get<Helper::template Dimension_index<i>::value>
|
||||
(mdarts[dh].mattribute_descriptors) = ah;
|
||||
(mdarts[dh].mattribute_descriptors) = ah;
|
||||
}
|
||||
|
||||
/** Link a dart with a given dart for a given dimension.
|
||||
* @param adart the dart to link.
|
||||
* @param adart2 the dart to link with.
|
||||
* @param i the dimension.
|
||||
*/
|
||||
* @param adart the dart to link.
|
||||
* @param adart2 the dart to link with.
|
||||
* @param i the dimension.
|
||||
*/
|
||||
template<unsigned int i>
|
||||
void dart_link_beta(Dart_descriptor adart, Dart_descriptor adart2)
|
||||
{
|
||||
|
|
@ -509,9 +513,9 @@ namespace CGAL {
|
|||
}
|
||||
|
||||
/** Unlink a dart for a given dimension.
|
||||
* @param adart a dart.
|
||||
* @param i the dimension.
|
||||
*/
|
||||
* @param adart a dart.
|
||||
* @param i the dimension.
|
||||
*/
|
||||
template<unsigned int i>
|
||||
void dart_unlink_beta(Dart_descriptor adart)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ read_triangle_poly_file(CDT& t, std::istream &f,
|
|||
{
|
||||
unsigned int j;
|
||||
double x, y;
|
||||
f >> j >> iformat(x) >> iformat(y);
|
||||
f >> j >> IO::iformat(x) >> IO::iformat(y);
|
||||
Point p(x, y);
|
||||
skip_until_EOL(f); skip_comment_OFF(f);
|
||||
vertices[--j] = t.insert(p);
|
||||
|
|
|
|||
|
|
@ -1,60 +0,0 @@
|
|||
namespace CGAL {
|
||||
|
||||
/*!
|
||||
\ingroup PkgMesh3Domains
|
||||
|
||||
The class `Polyhedral_mesh_domain_3` implements
|
||||
a domain defined by a simplicial polyhedral surface.
|
||||
|
||||
The input polyhedral surface must be free of intersection.
|
||||
It must include (at least) one closed connected component
|
||||
that defines the boundary of the domain to be meshed.
|
||||
Inside this bounding component,
|
||||
the input polyhedral surface may contain
|
||||
several other components (closed or not)
|
||||
that will be represented in the final mesh.
|
||||
This class is a model of the concept `MeshDomain_3`.
|
||||
|
||||
\tparam Polyhedron stands for the type of the input polyhedral surface(s),
|
||||
model of `FaceListGraph`.
|
||||
|
||||
\tparam IGT stands for a geometric traits class
|
||||
providing the types and functors required to implement
|
||||
the intersection tests and intersection computations
|
||||
for polyhedral boundary surfaces. This parameter has to be instantiated
|
||||
with a model of the concept `IntersectionGeometricTraits_3`.
|
||||
|
||||
\cgalModels{MeshDomain_3}
|
||||
|
||||
\sa `IntersectionGeometricTraits_3`
|
||||
\sa `CGAL::make_mesh_3()`.
|
||||
|
||||
*/
|
||||
template< typename Polyhedron, typename IGT, typename TriangleAccessor >
|
||||
class Polyhedral_mesh_domain_3
|
||||
{
|
||||
public:
|
||||
|
||||
/// \name Creation
|
||||
/// @{
|
||||
|
||||
/*!
|
||||
Construction from a bounding polyhedral surface which must be closed, and free of intersections.
|
||||
The inside of `bounding_polyhedron` will be meshed.
|
||||
*/
|
||||
Polyhedral_mesh_domain_3(const Polyhedron& bounding_polyhedron);
|
||||
|
||||
/*!
|
||||
Construction from a polyhedral surface, and a bounding polyhedral surface,.
|
||||
The first polyhedron must be entirely included inside `bounding_polyhedron`, which must be closed
|
||||
and free of intersections.
|
||||
Using this constructor allows to mesh a polyhedral surface which is not closed, or has holes.
|
||||
The inside of `bounding_polyhedron` will be meshed.
|
||||
*/
|
||||
Polyhedral_mesh_domain_3(const Polyhedron& polyhedron,
|
||||
const Polyhedron& bounding_polyhedron);
|
||||
|
||||
/// @}
|
||||
|
||||
}; /* end Polyhedral_mesh_domain_3 */
|
||||
} /* end namespace CGAL */
|
||||
|
|
@ -1,105 +0,0 @@
|
|||
namespace CGAL {
|
||||
|
||||
/*!
|
||||
\ingroup PkgMesh3Domains
|
||||
|
||||
The class `Polyhedral_mesh_domain_with_features_3` implements a domain whose
|
||||
boundary is a simplicial polyhedral surface.
|
||||
This surface must be free of intersection.
|
||||
It can either be closed,
|
||||
included inside another polyhedral surface which is closed and free of intersection,
|
||||
or open. In the latter case, the meshing process will only take care of the quality
|
||||
of the 1D (features and boundaries) and 2D (surfaces) components of the mesh.
|
||||
|
||||
It is a model of the concept `MeshDomainWithFeatures_3`. It also
|
||||
provides a member function to automatically detect sharp features and boundaries from
|
||||
the input polyhedral surface(s).
|
||||
|
||||
\tparam IGT stands for a geometric traits class providing the types
|
||||
and functors required to implement the intersection tests and intersection computations
|
||||
for polyhedral boundary surfaces. This parameter has to be
|
||||
instantiated with a model of the concept `IntersectionGeometricTraits_3`.
|
||||
|
||||
\cgalModels{MeshDomainWithFeatures_3}
|
||||
|
||||
\sa `CGAL::Mesh_domain_with_polyline_features_3<MD>`
|
||||
\sa `CGAL::Polyhedral_mesh_domain_3<Polyhedron,IGT,TriangleAccessor>`
|
||||
\sa `CGAL::Mesh_polyhedron_3<IGT>`
|
||||
*/
|
||||
template< typename IGT >
|
||||
class Polyhedral_mesh_domain_with_features_3
|
||||
: public CGAL::Mesh_domain_with_polyline_features_3<
|
||||
CGAL::Polyhedral_mesh_domain_3< CGAL::Mesh_polyhedron_3<IGT>::type, IGT> >
|
||||
{
|
||||
public:
|
||||
|
||||
/// \name Types
|
||||
/// @{
|
||||
|
||||
/*!
|
||||
Numerical type.
|
||||
*/
|
||||
typedef unspecified_type FT;
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Creation
|
||||
/// @{
|
||||
|
||||
/*!
|
||||
Constructs a `Polyhedral_mesh_domain_with_features_3` from a polyhedral surface of type `Polyhedron`.
|
||||
The only requirement on type `Polyhedron` is that `CGAL::Mesh_polyhedron_3<IGT>::%type` should
|
||||
be constructible from `Polyhedron`.
|
||||
No feature detection is done at this level. Note that a copy of `bounding_polyhedron` will be done.
|
||||
The polyhedron `bounding_polyhedron` has to be closed and free of intersections.
|
||||
Its interior of `bounding_polyhedron` will be meshed.
|
||||
*/
|
||||
template <typename Polyhedron>
|
||||
Polyhedral_mesh_domain_with_features_3(const Polyhedron& bounding_polyhedron);
|
||||
|
||||
|
||||
/*!
|
||||
Constructs a `Polyhedral_mesh_domain_with_features_3` from a polyhedral surface, and a bounding polyhedral surface.
|
||||
`CGAL::Mesh_polyhedron_3<IGT>::%type` should be constructible from `Polyhedron`.
|
||||
The first polyhedron should be entirely included inside `bounding_polyhedron`, which has to be closed
|
||||
and free of intersections.
|
||||
Using this constructor allows to mesh a polyhedral surface which is not closed, or has holes.
|
||||
The inside of `bounding_polyhedron` will be meshed.
|
||||
*/
|
||||
template <typename Polyhedron>
|
||||
Polyhedral_mesh_domain_with_features_3(const Polyhedron& polyhedron,
|
||||
const Polyhedron& bounding_polyhedron);
|
||||
|
||||
/*!
|
||||
\deprecated Constructs a `Polyhedral_mesh_domain_with_features_3` from an off file. No feature
|
||||
detection is done at this level. Users must read the file into a `Polyhedron_3` and call the
|
||||
constructor above.
|
||||
*/
|
||||
Polyhedral_mesh_domain_with_features_3(const std::string& filename);
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Operations
|
||||
/// @{
|
||||
|
||||
/*!
|
||||
Detects sharp features and boundaries of the internal bounding polyhedron (and the potential internal polyhedron)
|
||||
and inserts them as features of the domain. `angle_bound` gives the maximum
|
||||
angle (in degrees) between the two normal vectors of adjacent triangles.
|
||||
For an edge of the polyhedron, if the angle between the two normal vectors of its
|
||||
incident facets is bigger than the given bound, then the edge is considered as
|
||||
a feature edge.
|
||||
*/
|
||||
void detect_features(FT angle_bound=60);
|
||||
|
||||
|
||||
/*!
|
||||
Detects border edges of the bounding polyhedron and inserts them as features of the domain.
|
||||
This function should be called alone only, and not before or after `detect_features()`.
|
||||
*/
|
||||
void detect_borders();
|
||||
|
||||
/// @}
|
||||
|
||||
}; /* end Polyhedral_mesh_domain_with_features_3 */
|
||||
} /* end namespace CGAL */
|
||||
|
|
@ -197,6 +197,7 @@ if(CGAL_ACTIVATE_CONCURRENT_MESH_3 AND TARGET CGAL::TBB_support)
|
|||
target
|
||||
mesh_3D_image
|
||||
mesh_3D_weighted_image
|
||||
mesh_3D_weighted_image_with_detection_of_features
|
||||
mesh_3D_image_variable_size
|
||||
mesh_3D_image_with_custom_initialization
|
||||
mesh_3D_gray_image_with_custom_initialization
|
||||
|
|
|
|||
|
|
@ -1148,9 +1148,9 @@ number_of_bad_elements_impl()
|
|||
const Subdomain mc_subdomain = this->r_oracle_.is_in_domain_object()(this->r_tr_.dual(mc));
|
||||
|
||||
std::cerr << "*** Is in complex? c is marked in domain: " << this->r_c3t3_.is_in_complex(c)
|
||||
<< " / c is really in subdomain: " << oformat(c_subdomain)
|
||||
<< " / c is really in subdomain: " << IO::oformat(c_subdomain)
|
||||
<< " / mc is marked in domain: " << this->r_c3t3_.is_in_complex(mc)
|
||||
<< " / mc is really in subdomain: " << oformat(mc_subdomain)
|
||||
<< " / mc is really in subdomain: " << IO::oformat(mc_subdomain)
|
||||
<< std::endl;
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ public:
|
|||
namespace CGAL {
|
||||
|
||||
/*!
|
||||
\ingroup PkgMinkowskiSum2Classes
|
||||
\ingroup PkgMinkowskiSum2Ref
|
||||
|
||||
The `Hertel_Mehlhorn_convex_decomposition_2` class implements the approximation algorithm of Hertel
|
||||
and Mehlhorn for decomposing a polygon into convex
|
||||
|
|
|
|||
|
|
@ -18,9 +18,6 @@
|
|||
/// \defgroup nt_cgal CGAL Number Types
|
||||
/// \ingroup PkgNumberTypesRef
|
||||
|
||||
/// \defgroup nt_cgal CGAL Number Types
|
||||
/// \ingroup PkgNumberTypesRef
|
||||
|
||||
/// \defgroup nt_rrational Relates Rational
|
||||
/// \ingroup PkgNumberTypesRef
|
||||
|
||||
|
|
|
|||
|
|
@ -8,15 +8,4 @@
|
|||
<enableAddressBar>false</enableAddressBar>
|
||||
<enableFilterFunctionality>false</enableFilterFunctionality>
|
||||
</assistant>
|
||||
<docFiles>
|
||||
<generate>
|
||||
<file>
|
||||
<input>Periodic_3_triangulation_3.qhp</input>
|
||||
<output>Periodic_3_triangulation_3.qch</output>
|
||||
</file>
|
||||
</generate>
|
||||
<register>
|
||||
<file>Periodic_3_triangulation_3.qch</file>
|
||||
</register>
|
||||
</docFiles>
|
||||
</QHelpCollectionProject>
|
||||
|
|
|
|||
|
|
@ -8,15 +8,4 @@
|
|||
<enableAddressBar>false</enableAddressBar>
|
||||
<enableFilterFunctionality>false</enableFilterFunctionality>
|
||||
</assistant>
|
||||
<docFiles>
|
||||
<generate>
|
||||
<file>
|
||||
<input>Periodic_Lloyd_3.qhp</input>
|
||||
<output>Periodic_Lloyd_3.qch</output>
|
||||
</file>
|
||||
</generate>
|
||||
<register>
|
||||
<file>Periodic_Lloyd_3.qch</file>
|
||||
</register>
|
||||
</docFiles>
|
||||
</QHelpCollectionProject>
|
||||
|
|
|
|||
|
|
@ -134,15 +134,15 @@ bool read_XYZ(std::istream& is,
|
|||
{
|
||||
iss.clear();
|
||||
iss.str(line);
|
||||
if (iss >> iformat(x) >> iformat(y) >> iformat(z))
|
||||
if (iss >> IO::iformat(x) >> IO::iformat(y) >> IO::iformat(z))
|
||||
{
|
||||
Point point(x,y,z);
|
||||
Vector normal = CGAL::NULL_VECTOR;
|
||||
// ... + normal...
|
||||
if (iss >> iformat(nx))
|
||||
if (iss >> IO::iformat(nx))
|
||||
{
|
||||
// In case we could read one number, we expect that there are two more
|
||||
if(iss >> iformat(ny) >> iformat(nz)){
|
||||
if(iss >> IO::iformat(ny) >> IO::iformat(nz)){
|
||||
normal = Vector(nx,ny,nz);
|
||||
} else {
|
||||
std::cerr << "Error line " << lineNumber << " of file (incomplete normal coordinates)" << std::endl;
|
||||
|
|
|
|||
|
|
@ -553,9 +553,6 @@ create_mst_graph(
|
|||
For this reason it should not be called on sorted containers.
|
||||
It is based on \cgalCite{cgal:hddms-srup-92}.
|
||||
|
||||
\warning This function may fail when Boost version 1.54 is used,
|
||||
because of the following bug: https://svn.boost.org/trac/boost/ticket/9012
|
||||
|
||||
\pre Normals must be unit vectors
|
||||
\pre `k >= 2`
|
||||
|
||||
|
|
|
|||
|
|
@ -1150,6 +1150,9 @@ bool adapt_patch(std::vector<std::vector<Point> >& point_patch,
|
|||
put(local_vpm, v, projector(get(local_vpm, v)));
|
||||
|
||||
// The projector can create degenerate faces
|
||||
for (halfedge_descriptor h : border_hedges)
|
||||
if (is_degenerate_triangle_face(face(opposite(h, local_mesh), local_mesh), local_mesh))
|
||||
return !has_SI;
|
||||
if(!remove_degenerate_faces(local_mesh))
|
||||
return !has_SI;
|
||||
|
||||
|
|
@ -2031,7 +2034,7 @@ remove_self_intersections_one_step(std::set<typename boost::graph_traits<Triangl
|
|||
|
||||
#ifdef CGAL_PMP_REMOVE_SELF_INTERSECTION_OUTPUT_INTERMEDIATE_FULL_MESH
|
||||
fname = "results/mesh_at_step_"+std::to_string(step)+"_CC_"+std::to_string(cc_id)+".off";
|
||||
CGAL::IO::write_polygon_mesh(fname, tmesh, CGAL::parameters::stream_precision);
|
||||
CGAL::IO::write_polygon_mesh(fname, tmesh, CGAL::parameters::stream_precision(17));
|
||||
#endif
|
||||
|
||||
// expand the region to be filled
|
||||
|
|
|
|||
|
|
@ -49,21 +49,3 @@
|
|||
#include <CGAL/Polygon_mesh_processing/smooth_mesh.h>
|
||||
#include <CGAL/Polygon_mesh_processing/smooth_shape.h>
|
||||
#include <CGAL/Polygon_mesh_processing/manifoldness.h>
|
||||
|
||||
// the named parameter header being not documented the doc is put here for now
|
||||
#ifdef DOXYGEN_RUNNING
|
||||
namespace CGAL {
|
||||
namespace Polygon_mesh_processing {
|
||||
namespace parameters {
|
||||
|
||||
/*! \ingroup namedparameters
|
||||
\deprecated This function is deprecated and `default_values()` should be used instead.
|
||||
This function can be used to indicate that all optional named parameters
|
||||
to be used are the default ones. This is particularly useful when a function
|
||||
requires more than one sequence of named parameters and default values is
|
||||
fine only for some of them.
|
||||
*/
|
||||
unspecified_type all_default();
|
||||
|
||||
} } } // end of namespace CGAL::Polygon_mesh_processing::parameters
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -18,6 +18,10 @@
|
|||
#include <CGAL/Polygonal_surface_reconstruction/internal/hypothesis.h>
|
||||
#include <CGAL/Polygonal_surface_reconstruction/internal/compute_confidences.h>
|
||||
#include <CGAL/Polygonal_surface_reconstruction/internal/point_set_with_planes.h>
|
||||
#include <CGAL/Polygon_mesh_processing/orient_polygon_soup.h>
|
||||
#include <CGAL/Polygon_mesh_processing/polygon_soup_to_polygon_mesh.h>
|
||||
#include <CGAL/Polygon_mesh_processing/polygon_mesh_to_polygon_soup.h>
|
||||
#include <CGAL/Polygon_mesh_processing/repair_polygon_soup.h>
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
|
|
@ -28,7 +32,7 @@
|
|||
namespace CGAL {
|
||||
|
||||
/*!
|
||||
\ingroup PkgPolygonalSurfaceReconstruction
|
||||
\ingroup PkgPolygonalSurfaceReconstructionRef
|
||||
|
||||
\brief
|
||||
|
||||
|
|
@ -455,7 +459,12 @@ namespace CGAL {
|
|||
|
||||
// Converts from internal data structure to the required `PolygonMesh`.
|
||||
output_mesh.clear(); // make sure it is empty.
|
||||
CGAL::copy_face_graph(target_mesh, output_mesh);
|
||||
std::vector<Point> points;
|
||||
std::vector<std::vector<std::size_t> > polygons;
|
||||
CGAL::Polygon_mesh_processing::polygon_mesh_to_polygon_soup(target_mesh, points, polygons);
|
||||
CGAL::Polygon_mesh_processing::merge_duplicate_points_in_polygon_soup(points, polygons);
|
||||
CGAL::Polygon_mesh_processing::orient_polygon_soup(points, polygons);
|
||||
CGAL::Polygon_mesh_processing::polygon_soup_to_polygon_mesh(points, polygons, output_mesh);
|
||||
}
|
||||
else {
|
||||
error_message_ = "solving the binary program failed";
|
||||
|
|
|
|||
|
|
@ -67,6 +67,18 @@ namespace CGAL {
|
|||
delete supporting_plane_;
|
||||
supporting_plane_ = new Plane;
|
||||
CGAL::linear_least_squares_fitting_3(pts.begin(), pts.end(), *supporting_plane_, CGAL::Dimension_tag<0>());
|
||||
|
||||
// Check orientation
|
||||
int vote_for_opposite = 0;
|
||||
for (std::size_t i = 0; i < size(); i++)
|
||||
if (supporting_plane_->orthogonal_vector() * point_set_->normal_map()[at(i)] < 0)
|
||||
vote_for_opposite++;
|
||||
else
|
||||
vote_for_opposite--;
|
||||
|
||||
if (vote_for_opposite > 0)
|
||||
*supporting_plane_ = supporting_plane_->opposite();
|
||||
|
||||
return supporting_plane_;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ Point_set_3
|
|||
Point_set_processing_3
|
||||
Polygon
|
||||
Polygonal_surface_reconstruction
|
||||
Polygon_mesh_processing
|
||||
Principal_component_analysis
|
||||
Principal_component_analysis_LGPL
|
||||
Profiling_tools
|
||||
|
|
|
|||
|
|
@ -228,7 +228,7 @@ if(CGAL_Qt6_FOUND AND Qt6_FOUND)
|
|||
endmacro(add_item)
|
||||
|
||||
add_item(scene_triangulation_3_item Scene_triangulation_3_item.cpp)
|
||||
target_link_libraries(scene_triangulation_3_item PUBLIC scene_basic_objects)
|
||||
target_link_libraries(scene_triangulation_3_item PUBLIC scene_basic_objects scene_edit_box_item)
|
||||
|
||||
add_item(scene_c3t3_item Scene_c3t3_item.cpp)
|
||||
target_link_libraries(
|
||||
|
|
|
|||
|
|
@ -153,13 +153,13 @@ public:
|
|||
for(auto fit=wrapper.triangulation().finite_facets_begin(), fend=wrapper.triangulation().finite_facets_end(); fit!=fend; ++fit)
|
||||
{
|
||||
Facet f = *fit;
|
||||
if(!f.first->info().is_outside)
|
||||
if(!f.first->is_outside())
|
||||
f = wrapper.triangulation().mirror_facet(f);
|
||||
|
||||
const Cell_handle c = f.first;
|
||||
const int s = f.second;
|
||||
const Cell_handle nh = c->neighbor(s);
|
||||
if(c->info().is_outside == nh->info().is_outside)
|
||||
if(c->is_outside() == nh->is_outside())
|
||||
continue;
|
||||
|
||||
std::array<std::size_t, 3> ids;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,6 @@
|
|||
include(polyhedron_demo_macros)
|
||||
|
||||
polyhedron_demo_plugin(isosurface_3_plugin Isosurface_3_plugin KEYWORDS
|
||||
Isosurface_3)
|
||||
target_link_libraries(
|
||||
isosurface_3_plugin PUBLIC scene_polygon_soup_item scene_image_item )
|
||||
|
|
@ -0,0 +1,370 @@
|
|||
#include <QElapsedTimer>
|
||||
#include <QApplication>
|
||||
#include <QAction>
|
||||
#include <QMainWindow>
|
||||
#include "Scene_polygon_soup_item.h"
|
||||
#include "Scene_image_item.h"
|
||||
#include "SMesh_type.h"
|
||||
#include "Image_type.h"
|
||||
|
||||
#include <CGAL/Three/Polyhedron_demo_plugin_interface.h>
|
||||
#include <CGAL/Polygon_mesh_processing/polygon_soup_to_polygon_mesh.h>
|
||||
#include <CGAL/Polygon_mesh_processing/orient_polygon_soup.h>
|
||||
|
||||
using namespace CGAL::Three;
|
||||
class Polyhedron_demo_isosurface_3_plugin :
|
||||
public QObject,
|
||||
public Polyhedron_demo_plugin_interface
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(CGAL::Three::Polyhedron_demo_plugin_interface)
|
||||
Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.PluginInterface/1.0")
|
||||
public:
|
||||
void init(QMainWindow*mw,
|
||||
Scene_interface* scene_interface,
|
||||
Messages_interface*)
|
||||
{
|
||||
scene = scene_interface;
|
||||
this->mw = mw;
|
||||
QAction *actionDualLabel = new QAction("Dual contour label image", mw);
|
||||
actionDualLabel->setProperty("subMenuName","Isosurface");
|
||||
connect(actionDualLabel, SIGNAL(triggered()), this, SLOT(on_actionDualLabel_triggered()));
|
||||
_actions << actionDualLabel;
|
||||
}
|
||||
|
||||
QList<QAction*> actions()const {return _actions;}
|
||||
|
||||
bool applicable(QAction*) const {
|
||||
return
|
||||
qobject_cast<Scene_image_item*>(scene->item(scene->mainSelectionIndex()));
|
||||
}
|
||||
|
||||
public Q_SLOTS:
|
||||
void on_actionDualLabel_triggered();
|
||||
private:
|
||||
QList<QAction*> _actions;
|
||||
Scene_interface* scene;
|
||||
QMainWindow* mw;
|
||||
}; // end Polyhedron_demo_convex_hull_plugin
|
||||
|
||||
class Polyhedron_demo_isosurface_3_plugin_helper {
|
||||
typedef float Word_type;
|
||||
typedef std::size_t vertex_descriptor;
|
||||
typedef std::pair<Word_type, Word_type> surface_descriptor;
|
||||
|
||||
struct Mesh_quad {
|
||||
typedef vertex_descriptor* iterator;
|
||||
typedef const vertex_descriptor* const_iterator;
|
||||
|
||||
vertex_descriptor t[4];
|
||||
surface_descriptor surface;
|
||||
|
||||
Mesh_quad() {}
|
||||
|
||||
Mesh_quad(const Mesh_quad & other) {
|
||||
t[0] = other.t[0];
|
||||
t[1] = other.t[1];
|
||||
t[2] = other.t[2];
|
||||
t[3] = other.t[3];
|
||||
surface = other.surface;
|
||||
}
|
||||
|
||||
Mesh_quad(vertex_descriptor v0, vertex_descriptor v1, vertex_descriptor v2, vertex_descriptor v3, Word_type val1, Word_type val2) {
|
||||
if (val1 < val2) {
|
||||
t[0] = v3;
|
||||
t[1] = v2;
|
||||
t[2] = v1;
|
||||
t[3] = v0;
|
||||
surface = std::make_pair(val1, val2);
|
||||
}
|
||||
else {
|
||||
t[0] = v0;
|
||||
t[1] = v1;
|
||||
t[2] = v2;
|
||||
t[3] = v3;
|
||||
surface = std::make_pair(val2, val1);
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t size() const {
|
||||
return 4;
|
||||
}
|
||||
|
||||
vertex_descriptor operator[](int i) const { return t[i]; }
|
||||
|
||||
iterator begin() { return &t[0]; }
|
||||
const_iterator begin() const { return &t[0]; }
|
||||
iterator end() { return &t[4]; }
|
||||
const_iterator end() const { return &t[4]; }
|
||||
};
|
||||
|
||||
struct Mesh
|
||||
{
|
||||
using Polygon = Mesh_quad;
|
||||
|
||||
std::vector<Point_3> vertices;
|
||||
std::vector<Polygon> polygons;
|
||||
|
||||
vertex_descriptor add_vertex(EPICK::Point_3 p) {
|
||||
vertices.push_back(p);
|
||||
return vertices.size()-1;
|
||||
}
|
||||
|
||||
void add_face(const Polygon & poly) {
|
||||
polygons.push_back(Polygon(poly));
|
||||
}
|
||||
|
||||
void add_face(vertex_descriptor v0, vertex_descriptor v1, vertex_descriptor v2, vertex_descriptor v3, Word_type val1, Word_type val2)
|
||||
{
|
||||
polygons.push_back(Polygon(v0, v1, v2, v3, val1, val2));
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
Polyhedron_demo_isosurface_3_plugin_helper(const Image* image)
|
||||
{
|
||||
image_ = image;
|
||||
}
|
||||
|
||||
void dual_contouring_label_image()
|
||||
{
|
||||
int i,j,k;
|
||||
|
||||
const int dx_ = 1;
|
||||
const int dy_ = 1;
|
||||
const int dz_ = 1;
|
||||
double vx_ = image_->vx();
|
||||
double vy_ = image_->vy();
|
||||
double vz_ = image_->vz();
|
||||
double tx_ = image_->tx();
|
||||
double ty_ = image_->ty();
|
||||
double tz_ = image_->tz();
|
||||
|
||||
int xdim_ = static_cast<int>(image_->xdim());
|
||||
int ydim_ = static_cast<int>(image_->ydim());
|
||||
int zdim_ = static_cast<int>(image_->zdim());
|
||||
int xdim_p = xdim_+dx_;
|
||||
int ydim_p = ydim_+dy_;
|
||||
int xydim_p = ydim_p*xdim_p;
|
||||
|
||||
std::map<std::size_t, vertex_descriptor> vertices;
|
||||
|
||||
for ( k = -dz_ ; k < zdim_ ; k+=dz_ )
|
||||
{
|
||||
for ( j = -dy_ ; j < ydim_ ; j+=dy_ )
|
||||
{
|
||||
for ( i = -dx_ ; i < xdim_ ; i+=dx_ )
|
||||
{
|
||||
const Word_type & v0 = image_data(i, j, k);
|
||||
|
||||
const Word_type & v1 = image_data(i+dx_, j, k);
|
||||
const Word_type & v2 = image_data(i, j+dy_, k);
|
||||
const Word_type & v3 = image_data(i, j, k+dz_);
|
||||
|
||||
const Word_type & v4 = image_data(i+dx_, j+dy_, k);
|
||||
const Word_type & v5 = image_data(i, j+dy_, k+dz_);
|
||||
const Word_type & v6 = image_data(i+dx_, j, k+dz_);
|
||||
|
||||
const Word_type & v7 = image_data(i+dx_, j+dy_, k+dz_);
|
||||
|
||||
// if one is different
|
||||
if (v0 != v1 || v0 != v2 || v0 != v3 || v0 != v4 || v0 != v5 || v0 != v6 || v0 != v7) {
|
||||
unsigned int ip = i+dx_;
|
||||
unsigned int jp = j+dy_;
|
||||
unsigned int kp = k+dz_;
|
||||
unsigned int index = kp*xydim_p + jp*xdim_p + ip;
|
||||
double di = i+0.5*dx_;
|
||||
double dj = j+0.5*dy_;
|
||||
double dk = k+0.5*dz_;
|
||||
if (di < 0)
|
||||
di = 0.0;
|
||||
if (dj < 0)
|
||||
dj = 0.0;
|
||||
if (dk < 0)
|
||||
dk = 0.0;
|
||||
if (di > xdim_-dx_)
|
||||
di = xdim_-1;
|
||||
if (dj > ydim_-dy_)
|
||||
dj = ydim_-1;
|
||||
if (dk > zdim_-dz_)
|
||||
dk = zdim_-1;
|
||||
di = di * vx_ + tx_;
|
||||
dj = dj * vy_ + ty_;
|
||||
dk = dk * vz_ + tz_;
|
||||
|
||||
vertex_descriptor vertex_0 = mesh_.add_vertex(Point_3(di, dj, dk));
|
||||
vertices.insert(std::make_pair(index, vertex_0));
|
||||
|
||||
// check x direction
|
||||
if (v0 != v1)
|
||||
{
|
||||
vertex_descriptor vertex_1 = vertices.find(kp*xydim_p + j *xdim_p + ip)->second;
|
||||
vertex_descriptor vertex_2 = vertices.find(k *xydim_p + j *xdim_p + ip)->second;
|
||||
vertex_descriptor vertex_3 = vertices.find(k *xydim_p + jp*xdim_p + ip)->second;
|
||||
mesh_.add_face(vertex_0, vertex_1, vertex_2, vertex_3, v0, v1);
|
||||
}
|
||||
// check y direction
|
||||
if (v0 != v2)
|
||||
{
|
||||
vertex_descriptor vertex_1 = vertices.find(k *xydim_p + jp*xdim_p + ip)->second;
|
||||
vertex_descriptor vertex_2 = vertices.find(k *xydim_p + jp*xdim_p + i )->second;
|
||||
vertex_descriptor vertex_3 = vertices.find(kp*xydim_p + jp*xdim_p + i )->second;
|
||||
mesh_.add_face(vertex_0, vertex_1, vertex_2, vertex_3, v0, v2);
|
||||
}
|
||||
// check z direction
|
||||
if (v0 != v3)
|
||||
{
|
||||
vertex_descriptor vertex_1 = vertices.find(kp*xydim_p + jp*xdim_p + i )->second;
|
||||
vertex_descriptor vertex_2 = vertices.find(kp*xydim_p + j *xdim_p + i )->second;
|
||||
vertex_descriptor vertex_3 = vertices.find(kp*xydim_p + j *xdim_p + ip)->second;
|
||||
mesh_.add_face(vertex_0, vertex_1, vertex_2, vertex_3, v0, v3);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void generate_polygon_soup(std::vector<Point_3> & vertices,
|
||||
std::vector<std::vector<std::size_t>> & polygons,
|
||||
std::vector<CGAL::IO::Color> & fcolors,
|
||||
std::vector<CGAL::IO::Color> & vcolors,
|
||||
const QColor & c)
|
||||
{
|
||||
vertices.clear();
|
||||
polygons.clear();
|
||||
fcolors.clear();
|
||||
vcolors.clear();
|
||||
|
||||
const std::vector<Point_3> & m_vertices = mesh_.vertices;
|
||||
const std::vector<Mesh_quad> & m_polygons = mesh_.polygons;
|
||||
std::size_t polygon_size = m_polygons.size();
|
||||
|
||||
vertices.insert(vertices.begin(), m_vertices.begin(), m_vertices.end());
|
||||
|
||||
std::map<surface_descriptor, QColor> surface_color_map;
|
||||
compute_color_map(surface_color_map, c);
|
||||
|
||||
fcolors.resize(polygon_size);
|
||||
polygons.resize(polygon_size);
|
||||
for (std::size_t i = 0; i < polygon_size; i++)
|
||||
{
|
||||
const Mesh_quad & quad = m_polygons[i];
|
||||
|
||||
std::vector<std::size_t> polygon;
|
||||
polygon.resize(4);
|
||||
polygon[0] = quad.t[0];
|
||||
polygon[1] = quad.t[1];
|
||||
polygon[2] = quad.t[2];
|
||||
polygon[3] = quad.t[3];
|
||||
polygons[i] = polygon;
|
||||
|
||||
const QColor & color = surface_color_map[quad.surface];
|
||||
fcolors[i] = CGAL::IO::Color(color.red(), color.green(), color.blue());
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
Mesh mesh_;
|
||||
const Image* image_;
|
||||
|
||||
Word_type image_data(int i, int j, int k)
|
||||
{
|
||||
if ( i>=0 && static_cast<std::size_t>(i)<image_->xdim() &&
|
||||
j>=0 && static_cast<std::size_t>(j)<image_->ydim() &&
|
||||
k>=0 && static_cast<std::size_t>(k)<image_->zdim() )
|
||||
return image_->value(i, j, k);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void compute_color_map(std::map<surface_descriptor, QColor> & surface_color_map, const QColor & c)
|
||||
{
|
||||
// obtain and order all subdomains and surfaces
|
||||
std::map<Word_type, QColor> subdomain_color_map;
|
||||
for (const Mesh_quad& quad : mesh_.polygons) {
|
||||
const surface_descriptor & surface = quad.surface;
|
||||
subdomain_color_map[surface.first] = QColor();
|
||||
subdomain_color_map[surface.second] = QColor();
|
||||
surface_color_map[surface] = QColor();
|
||||
}
|
||||
|
||||
// assign default color to each subdomains (same colors as images)
|
||||
double nb_domains = subdomain_color_map.size();
|
||||
double i = 0;
|
||||
for (std::map<Word_type, QColor>::iterator it = subdomain_color_map.begin(),
|
||||
end = subdomain_color_map.end(); it != end; ++it, i += 1.)
|
||||
{
|
||||
double hue = c.hueF() + 1. / nb_domains * i;
|
||||
if (hue > 1) { hue -= 1.; }
|
||||
it->second = QColor::fromHsvF(hue, c.saturationF(), c.valueF());
|
||||
}
|
||||
|
||||
// assign color for each surfaces (use subdomain color if the surface is in contact with background)
|
||||
nb_domains = surface_color_map.size();
|
||||
i = 0;
|
||||
double patch_hsv_value = fmod(c.valueF() + .5, 1.);
|
||||
for (std::map<surface_descriptor, QColor>::iterator it = surface_color_map.begin(),
|
||||
end = surface_color_map.end(); it != end; ++it, i += 1.)
|
||||
{
|
||||
QColor surface_color;
|
||||
if (it->first.first == 0) {
|
||||
surface_color = subdomain_color_map[it->first.second];
|
||||
}
|
||||
else {
|
||||
double hue = c.hueF() + 1. / nb_domains * i;
|
||||
if (hue > 1) { hue -= 1.; }
|
||||
surface_color = QColor::fromHsvF(hue, c.saturationF(), patch_hsv_value);
|
||||
}
|
||||
|
||||
it->second = surface_color;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void Polyhedron_demo_isosurface_3_plugin::on_actionDualLabel_triggered()
|
||||
{
|
||||
const CGAL::Three::Scene_interface::Item_id index = scene->mainSelectionIndex();
|
||||
|
||||
Scene_image_item* img_item =
|
||||
qobject_cast<Scene_image_item*>(scene->item(index));
|
||||
|
||||
if( img_item )
|
||||
{
|
||||
// wait cursor
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
|
||||
QElapsedTimer time;
|
||||
time.start();
|
||||
QElapsedTimer time_per_op;
|
||||
time_per_op.start();
|
||||
std::cout << "Dual contour label image...";
|
||||
|
||||
Polyhedron_demo_isosurface_3_plugin_helper helper(img_item->image());
|
||||
helper.dual_contouring_label_image();
|
||||
|
||||
std::vector<Point_3> vertices;
|
||||
std::vector<std::vector<std::size_t>> polygons;
|
||||
std::vector<CGAL::IO::Color> fcolors;
|
||||
std::vector<CGAL::IO::Color> vcolors;
|
||||
|
||||
helper.generate_polygon_soup(vertices, polygons, fcolors, vcolors, img_item->color());
|
||||
|
||||
std::cout << "ok (" << time.elapsed() << " ms)" << std::endl;
|
||||
|
||||
Scene_polygon_soup_item* new_item = new Scene_polygon_soup_item();
|
||||
new_item->load(vertices, polygons, fcolors, vcolors);
|
||||
new_item->setName(tr("%1 (surface)").arg(scene->item(index)->name()));
|
||||
new_item->setColor(img_item->color());
|
||||
new_item->setRenderingMode(FlatPlusEdges);
|
||||
scene->addItem(new_item);
|
||||
|
||||
|
||||
img_item->setVisible(false);
|
||||
|
||||
// default cursor
|
||||
QApplication::restoreOverrideCursor();
|
||||
}
|
||||
}
|
||||
|
||||
#include "Isosurface_3_plugin.moc"
|
||||
|
|
@ -34,14 +34,14 @@ if(ITK_FOUND)
|
|||
target_link_libraries(mesh_3_plugin PUBLIC CGAL::ITK_support)
|
||||
endif(ITK_FOUND)
|
||||
|
||||
find_package(VTK QUIET COMPONENTS vtkImagingGeneral vtkIOImage NO_MODULE)
|
||||
find_package(VTK QUIET COMPONENTS vtkImagingGeneral vtkIOImage vtkIOXML NO_MODULE)
|
||||
if(VTK_FOUND)
|
||||
if(VTK_USE_FILE)
|
||||
include(${VTK_USE_FILE})
|
||||
endif()
|
||||
if("${VTK_VERSION_MAJOR}" GREATER "5" OR VTK_VERSION VERSION_GREATER 5)
|
||||
if(TARGET VTK::IOImage)
|
||||
set(VTK_LIBRARIES VTK::IOImage VTK::ImagingGeneral)
|
||||
set(VTK_LIBRARIES VTK::IOImage VTK::ImagingGeneral VTK::IOXML)
|
||||
endif()
|
||||
if(NOT VTK_LIBRARIES)
|
||||
message(STATUS "NOTICE: DICOM files (.dcm) require the VTK libraries, and will not be readable.")
|
||||
|
|
|
|||
|
|
@ -54,8 +54,10 @@
|
|||
#include <CGAL/IO/read_vtk_image_data.h>
|
||||
|
||||
#include <vtkNew.h>
|
||||
#include <vtkSmartPointer.h>
|
||||
#include <vtkStringArray.h>
|
||||
#include <vtkImageData.h>
|
||||
#include <vtkXMLImageDataReader.h>
|
||||
#include <vtkDICOMImageReader.h>
|
||||
#include <vtkBMPReader.h>
|
||||
#include <vtkNIFTIImageReader.h>
|
||||
|
|
@ -77,6 +79,23 @@
|
|||
#include <iostream>
|
||||
#include <locale>
|
||||
|
||||
template <class vtkReader>
|
||||
bool
|
||||
load_vtk_file(QFileInfo fileinfo, Image* image)
|
||||
{
|
||||
#ifdef CGAL_USE_VTK
|
||||
vtkNew<vtkReader> reader;
|
||||
reader->SetFileName(fileinfo.filePath().toUtf8());
|
||||
reader->Update();
|
||||
auto vtk_image = reader->GetOutput();
|
||||
vtk_image->Print(std::cerr);
|
||||
*image = CGAL::IO::read_vtk_image_data(vtk_image); // copy the image data
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Covariant return types don't work for scalar types and we cannot
|
||||
// have templates here, hence this unfortunate hack.
|
||||
|
||||
|
|
@ -1089,6 +1108,7 @@ QString Io_image_plugin::nameFilters() const
|
|||
return QString("Inrimage files (*.inr *.inr.gz) ;; "
|
||||
"Analyze files (*.hdr *.img *.img.gz) ;; "
|
||||
"Stanford Exploration Project files (*.H *.HH) ;; "
|
||||
"VTK image files (*.vti) ;; "
|
||||
"NRRD image files (*.nrrd) ;; "
|
||||
"NIFTI image files (*.nii *.nii.gz)");
|
||||
}
|
||||
|
|
@ -1121,6 +1141,7 @@ void convert(Image* image)
|
|||
image->image()->wordKind = WK_FLOAT;
|
||||
}
|
||||
|
||||
|
||||
QList<Scene_item*>
|
||||
Io_image_plugin::load(QFileInfo fileinfo, bool& ok, bool add_to_scene)
|
||||
{
|
||||
|
|
@ -1128,39 +1149,39 @@ Io_image_plugin::load(QFileInfo fileinfo, bool& ok, bool add_to_scene)
|
|||
QApplication::restoreOverrideCursor();
|
||||
Image* image = new Image;
|
||||
|
||||
// read a nrrd file
|
||||
if(fileinfo.suffix() == "nrrd")
|
||||
QString warningMessage;
|
||||
// read a vti file
|
||||
if(fileinfo.suffix() == "vti")
|
||||
{
|
||||
#ifdef CGAL_USE_VTK
|
||||
vtkNew<vtkNrrdReader> reader;
|
||||
reader->SetFileName(fileinfo.filePath().toUtf8());
|
||||
reader->Update();
|
||||
auto vtk_image = reader->GetOutput();
|
||||
vtk_image->Print(std::cerr);
|
||||
*image = CGAL::IO::read_vtk_image_data(vtk_image); // copy the image data
|
||||
ok = load_vtk_file<vtkXMLImageDataReader>(fileinfo, image);
|
||||
#else
|
||||
CGAL::Three::Three::warning("VTK is required to read NRRD files");
|
||||
delete image;
|
||||
return QList<Scene_item*>();
|
||||
ok = false;
|
||||
warningMessage = "VTK is required to read VTI files";
|
||||
#endif
|
||||
}
|
||||
|
||||
// read a nrrd file
|
||||
else if(fileinfo.suffix() == "nrrd")
|
||||
{
|
||||
#ifdef CGAL_USE_VTK
|
||||
ok = load_vtk_file<vtkNrrdReader>(fileinfo, image);
|
||||
#else
|
||||
ok = false;
|
||||
warningMessage = "VTK is required to read NRRD files";
|
||||
#endif
|
||||
}
|
||||
|
||||
// read a NIFTI file
|
||||
if(fileinfo.suffix() == "nii"
|
||||
else if(fileinfo.suffix() == "nii"
|
||||
|| ( fileinfo.suffix() == "gz"
|
||||
&& fileinfo.fileName().endsWith(QString(".nii.gz"), Qt::CaseInsensitive)))
|
||||
{
|
||||
#ifdef CGAL_USE_VTK
|
||||
vtkNew<vtkNIFTIImageReader> reader;
|
||||
reader->SetFileName(fileinfo.filePath().toUtf8());
|
||||
reader->Update();
|
||||
auto vtk_image = reader->GetOutput();
|
||||
vtk_image->Print(std::cerr);
|
||||
*image = CGAL::IO::read_vtk_image_data(vtk_image); // copy the image data
|
||||
ok = load_vtk_file<vtkNIFTIImageReader>(fileinfo, image);
|
||||
#else
|
||||
CGAL::Three::Three::warning("VTK is required to read NIfTI files");
|
||||
delete image;
|
||||
return QList<Scene_item*>();
|
||||
ok = false;
|
||||
warningMessage = "VTK is required to read NifTI files";
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -1267,11 +1288,16 @@ Io_image_plugin::load(QFileInfo fileinfo, bool& ok, bool add_to_scene)
|
|||
if(!success)
|
||||
{
|
||||
ok = false;
|
||||
delete image;
|
||||
return QList<Scene_item*>();
|
||||
}
|
||||
}
|
||||
|
||||
if (!ok) {
|
||||
if (warningMessage.length() > 0)
|
||||
CGAL::Three::Three::warning(warningMessage);
|
||||
delete image;
|
||||
return QList<Scene_item*>();
|
||||
}
|
||||
|
||||
// Get display precision
|
||||
QDialog dialog;
|
||||
ui.setupUi(&dialog);
|
||||
|
|
|
|||
|
|
@ -368,9 +368,9 @@ std::optional<QString> Mesh_3_plugin::get_items_or_return_error_string() const
|
|||
{
|
||||
auto poly_items_ptr = std::get_if<Polyhedral_mesh_items>(&items.value());
|
||||
auto image_items_ptr = std::get_if<Image_mesh_items>(&items.value());
|
||||
if(poly_items_ptr && poly_items_ptr == nullptr)
|
||||
if(poly_items_ptr != nullptr)
|
||||
poly_items_ptr->polylines_item = polylines_item;
|
||||
else if(image_items_ptr && image_items_ptr == nullptr)
|
||||
else if(image_items_ptr != nullptr )
|
||||
image_items_ptr->polylines_item = polylines_item;
|
||||
}
|
||||
|
||||
|
|
@ -663,6 +663,8 @@ void Mesh_3_plugin::mesh_3(const Mesh_type mesh_type,
|
|||
ui.protectEdges->addItem(boundary_only.first, v(boundary_only.second));
|
||||
} else
|
||||
ui.protectEdges->addItem(sharp_edges.first, v(sharp_edges.second));
|
||||
if (polylines_item != nullptr)
|
||||
ui.protectEdges->addItem(input_polylines.first, v(input_polylines.second));
|
||||
} else if (items->index() == IMAGE_MESH_ITEMS) {
|
||||
if (polylines_item != nullptr) {
|
||||
ui.protectEdges->addItem(input_polylines.first, QVariant::fromValue(input_polylines.second));
|
||||
|
|
@ -729,6 +731,7 @@ void Mesh_3_plugin::mesh_3(const Mesh_type mesh_type,
|
|||
const auto pe_flags = ui.protectEdges->currentData().value<Protection_flags>();
|
||||
protect_borders = ui.protect->isChecked() && pe_flags.testFlag(BORDERS);
|
||||
protect_features = ui.protect->isChecked() && pe_flags.testFlag(FEATURES);
|
||||
const bool protect_polylines = ui.protect->isChecked() && polylines_item != nullptr;
|
||||
|
||||
const bool detect_connected_components = ui.detectComponents->isChecked();
|
||||
const int manifold = (ui.manifoldCheckBox->isChecked() ? 1 : 0) +
|
||||
|
|
@ -775,7 +778,7 @@ void Mesh_3_plugin::mesh_3(const Mesh_type mesh_type,
|
|||
sm_items.removeAll(make_not_null(bounding_sm_item));
|
||||
}
|
||||
|
||||
Scene_polylines_item::Polylines_container plc;
|
||||
Scene_polylines_item::Polylines_container polylines_empty_container;
|
||||
SMesh* bounding_polyhedron = (bounding_sm_item == nullptr)
|
||||
? nullptr
|
||||
: bounding_sm_item->polyhedron();
|
||||
|
|
@ -811,7 +814,7 @@ void Mesh_3_plugin::mesh_3(const Mesh_type mesh_type,
|
|||
{
|
||||
thread = cgal_code_mesh_3(
|
||||
polyhedrons,
|
||||
(polylines_item == nullptr) ? plc : polylines_item->polylines,
|
||||
protect_polylines ? polylines_item->polylines : polylines_empty_container,
|
||||
bounding_polyhedron,
|
||||
item_name,
|
||||
angle,
|
||||
|
|
@ -878,11 +881,11 @@ void Mesh_3_plugin::mesh_3(const Mesh_type mesh_type,
|
|||
? image_item->image_weights()
|
||||
: nullptr;
|
||||
|
||||
Scene_polylines_item::Polylines_container plc;
|
||||
Scene_polylines_item::Polylines_container polylines_empty_container;
|
||||
|
||||
thread = cgal_code_mesh_3(
|
||||
pImage,
|
||||
(img_polylines_item == nullptr) ? plc : img_polylines_item->polylines,
|
||||
(img_polylines_item == nullptr) ? polylines_empty_container : img_polylines_item->polylines,
|
||||
angle,
|
||||
facets_sizing,
|
||||
facets_min_sizing,
|
||||
|
|
@ -1035,7 +1038,7 @@ treat_result(Scene_item& source_item,
|
|||
float((bbox.ymin() + bbox.ymax())/2.f),
|
||||
float((bbox.zmin() + bbox.zmax())/2.f));
|
||||
|
||||
result_item->setColor(default_mesh_color);
|
||||
result_item->setColor(source_item.color());
|
||||
result_item->setRenderingMode(source_item.renderingMode());
|
||||
result_item->set_data_item(&source_item);
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
#include <CGAL/double.h>
|
||||
|
||||
#include "Scene_c3t3_item.h"
|
||||
#include "Scene_triangulation_3_item.h"
|
||||
#include "Scene_tetrahedra_item.h"
|
||||
#include "Messages_interface.h"
|
||||
#include "CGAL_double_edit.h"
|
||||
|
|
@ -58,6 +59,10 @@ public :
|
|||
addDockWidget(dock_widget);
|
||||
|
||||
connect(dock_widget->resetButton, &QPushButton::clicked, [this](){
|
||||
if(!tet_item)
|
||||
return;
|
||||
tet_item->c3t3_item()->resetVisibleSubdomain();
|
||||
tet_item->c3t3_item()->computeIntersection();
|
||||
filter();
|
||||
});
|
||||
}
|
||||
|
|
@ -129,6 +134,7 @@ public Q_SLOTS:
|
|||
connect(dock_widget->minEdit, &DoubleEdit::editingFinished, tet_item, QOverload<>::of(&Scene_tetrahedra_item::setMinThreshold));
|
||||
connect(dock_widget->maxEdit, &DoubleEdit::editingFinished, tet_item, QOverload<>::of(&Scene_tetrahedra_item::setMaxThreshold));
|
||||
|
||||
onFilterIndexChanged(dock_widget->filterBox->currentIndex());
|
||||
dock_widget->show();
|
||||
}
|
||||
|
||||
|
|
@ -150,14 +156,25 @@ public Q_SLOTS:
|
|||
if(!tet_item)
|
||||
return;
|
||||
Scene_c3t3_item* c3t3_item = tet_item->c3t3_item();
|
||||
if(c3t3_item->subdomain_indices().size() > 96)
|
||||
unsigned int max_number_of_item = 32*Scene_triangulation_3_item::number_of_bitset-1;
|
||||
if(c3t3_item->subdomain_indices().size() >= max_number_of_item)
|
||||
{
|
||||
QMessageBox::warning(nullptr, "Warning", tr("The filtering is only available for items with less than 96 subdomains, and this one has %1").arg(c3t3_item->subdomain_indices().size()));
|
||||
QString message = tr("The filtering is only available for items with less than %1 subdomains, and this one has %2")
|
||||
.arg(max_number_of_item)
|
||||
.arg(c3t3_item->subdomain_indices().size());
|
||||
QMessageBox::warning(nullptr, "Warning", message);
|
||||
return;
|
||||
}
|
||||
int counter = 0;
|
||||
int limit = static_cast<int>(std::ceil(CGAL::approximate_sqrt(EPICK::FT(c3t3_item->subdomain_indices().size()))));
|
||||
QGridLayout *layout = dock_widget->gridLayout;
|
||||
//delete all items (see https://stackoverflow.com/questions/4272196/qt-remove-all-widgets-from-layout)
|
||||
QLayoutItem* item;
|
||||
while ((item = layout->takeAt(0)))
|
||||
{
|
||||
delete item->widget();
|
||||
delete item;
|
||||
}
|
||||
for (std::set<int>::iterator it = c3t3_item->subdomain_indices().begin(),
|
||||
end = c3t3_item->subdomain_indices().end(); it != end; ++it)
|
||||
{
|
||||
|
|
@ -165,7 +182,7 @@ public Q_SLOTS:
|
|||
QPushButton* button = new QPushButton(tr("%1").arg(index));
|
||||
buttons.push_back(button);
|
||||
button->setCheckable(true);
|
||||
button->setChecked(true);
|
||||
button->setChecked(c3t3_item->isVisibleSubdomain(index));
|
||||
QColor color = c3t3_item->getSubdomainIndexColor(index);
|
||||
QString s("QPushButton { font-weight: bold; background: #"
|
||||
+ QString::number(90,16)
|
||||
|
|
|
|||
|
|
@ -64,10 +64,14 @@ public Q_SLOTS:
|
|||
void tab_change();
|
||||
private:
|
||||
bool eventFilter(QObject *, QEvent *);
|
||||
bool process_event_clip_box(QEvent *);
|
||||
bool process_event_clip_orthographic(QEvent *);
|
||||
void do_clip(bool);
|
||||
QAction* actionClipbox;
|
||||
ClipWidget* dock_widget;
|
||||
Scene_edit_box_item* item;
|
||||
bool shift_pressing;
|
||||
bool clipping;
|
||||
Selection_visualizer* visualizer;
|
||||
}; // end Clipping_box_plugin
|
||||
|
||||
|
|
@ -96,6 +100,7 @@ void Clipping_box_plugin::init(QMainWindow* mainWindow, CGAL::Three::Scene_inter
|
|||
this, SLOT(connectNewViewer(QObject*)));
|
||||
visualizer = nullptr;
|
||||
shift_pressing = false;
|
||||
clipping = false;
|
||||
}
|
||||
|
||||
void Clipping_box_plugin::clipbox()
|
||||
|
|
@ -130,6 +135,12 @@ void Clipping_box_plugin::clipbox()
|
|||
});
|
||||
connect(dock_widget->tabWidget, &QTabWidget::currentChanged,
|
||||
this, &Clipping_box_plugin::tab_change);
|
||||
connect(dock_widget->resetButton, &QPushButton::clicked,
|
||||
this, [this]()
|
||||
{
|
||||
item->reset();
|
||||
do_clip(true);
|
||||
});
|
||||
item->setName("Clipping box");
|
||||
item->setRenderingMode(FlatPlusEdges);
|
||||
|
||||
|
|
@ -148,6 +159,25 @@ void Clipping_box_plugin::enableAction() {
|
|||
}
|
||||
|
||||
void Clipping_box_plugin::clip(bool b)
|
||||
{
|
||||
clipping = b;
|
||||
if (b)
|
||||
{
|
||||
for(CGAL::QGLViewer* v : CGAL::QGLViewer::QGLViewerPool())
|
||||
{
|
||||
v->installEventFilter(this);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for(CGAL::QGLViewer* v : CGAL::QGLViewer::QGLViewerPool())
|
||||
{
|
||||
v->removeEventFilter(this);
|
||||
}
|
||||
}
|
||||
do_clip(b);
|
||||
}
|
||||
|
||||
void Clipping_box_plugin::do_clip(bool b)
|
||||
{
|
||||
typedef CGAL::Epick Kernel;
|
||||
typedef CGAL::Polyhedron_3<Kernel> Mesh;
|
||||
|
|
@ -231,12 +261,20 @@ void Clipping_box_plugin::tab_change()
|
|||
|
||||
}
|
||||
|
||||
bool Clipping_box_plugin::eventFilter(QObject *, QEvent *event) {
|
||||
static QImage background;
|
||||
if (dock_widget->isHidden() || !(dock_widget->isActiveWindow()) || dock_widget->tabWidget->currentIndex() != 1
|
||||
|| (dock_widget->tabWidget->currentIndex() == 1 && !dock_widget->clipButton->isChecked()))
|
||||
bool Clipping_box_plugin::process_event_clip_box(QEvent *event)
|
||||
{
|
||||
if (event->type() == QEvent::MouseButtonRelease)
|
||||
{
|
||||
// item->itemChanged();
|
||||
do_clip(clipping);
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Clipping_box_plugin::process_event_clip_orthographic(QEvent *event)
|
||||
{
|
||||
static QImage background;
|
||||
if(event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease)
|
||||
{
|
||||
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
|
||||
|
|
@ -359,4 +397,16 @@ bool Clipping_box_plugin::eventFilter(QObject *, QEvent *event) {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Clipping_box_plugin::eventFilter(QObject *, QEvent *event) {
|
||||
if (dock_widget->isHidden() || !dock_widget->isActiveWindow())
|
||||
return false;
|
||||
if (dock_widget->tabWidget->currentIndex() == 0 && dock_widget->pushButton->isChecked())
|
||||
return process_event_clip_box(event);
|
||||
else if (dock_widget->tabWidget->currentIndex() == 1 && dock_widget->clipButton->isChecked())
|
||||
return process_event_clip_orthographic(event);
|
||||
else
|
||||
return false;
|
||||
|
||||
}
|
||||
#include "Clipping_box_plugin.moc"
|
||||
|
|
|
|||
|
|
@ -65,6 +65,43 @@
|
|||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_6">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_6">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="resetButton">
|
||||
<property name="text">
|
||||
<string>Reset</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_7">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
|
|
|
|||
|
|
@ -99,9 +99,10 @@ struct Scene_edit_box_item_priv{
|
|||
constraint.setRotationConstraintDirection(CGAL::qglviewer::Vec(.0,.0,.1));
|
||||
frame->setConstraint(&constraint);
|
||||
//create the sphere model
|
||||
pool[0] = bb.xmin(); pool[3] = bb.xmax();
|
||||
pool[1] = bb.ymin(); pool[4] = bb.ymax();
|
||||
pool[2] = bb.zmin(); pool[5] = bb.zmax();
|
||||
double eps = 1.e-3;
|
||||
pool[0] = bb.xmin()-eps; pool[3] = bb.xmax()+eps;
|
||||
pool[1] = bb.ymin()-eps; pool[4] = bb.ymax()+eps;
|
||||
pool[2] = bb.zmin()-eps; pool[5] = bb.zmax()+eps;
|
||||
|
||||
vertex_spheres.resize(0);
|
||||
normal_spheres.resize(0);
|
||||
|
|
@ -251,6 +252,22 @@ struct Scene_edit_box_item_priv{
|
|||
double applyX(int id, double x, double dirx);
|
||||
double applyY(int id, double y, double diry);
|
||||
double applyZ(int id, double z, double dirz);
|
||||
void reset_vertices()
|
||||
{
|
||||
Scene_item::Bbox bb = scene->bbox();
|
||||
double eps = 1.e-3;
|
||||
pool[0] = bb.xmin()-eps; pool[3] = bb.xmax()+eps;
|
||||
pool[1] = bb.ymin()-eps; pool[4] = bb.ymax()+eps;
|
||||
pool[2] = bb.zmin()-eps; pool[5] = bb.zmax()+eps;
|
||||
double x=(bb.xmin()+bb.xmax())/2;
|
||||
double y=(bb.ymin()+bb.ymax())/2;
|
||||
double z=(bb.zmin()+bb.zmax())/2;
|
||||
center_ = CGAL::qglviewer::Vec(x,y,z);
|
||||
relative_center_ = CGAL::qglviewer::Vec(0,0,0);
|
||||
const CGAL::qglviewer::Vec offset = static_cast<CGAL::Three::Viewer_interface*>(CGAL::QGLViewer::QGLViewerPool().first())->offset();
|
||||
frame->setPosition(center_+offset);
|
||||
item->invalidateOpenGLBuffers();
|
||||
}
|
||||
const Scene_interface* scene;
|
||||
Scene_edit_box_item* item;
|
||||
QPoint picked_pixel;
|
||||
|
|
@ -264,6 +281,7 @@ struct Scene_edit_box_item_priv{
|
|||
Scene_edit_box_item::Scene_edit_box_item()
|
||||
{
|
||||
d = nullptr;
|
||||
contextMenu();
|
||||
}
|
||||
Scene_edit_box_item::Scene_edit_box_item(const Scene_interface *scene_interface)
|
||||
{
|
||||
|
|
@ -294,12 +312,26 @@ Scene_edit_box_item::Scene_edit_box_item(const Scene_interface *scene_interface)
|
|||
: Vi::PROGRAM_NO_SELECTION,
|
||||
false));
|
||||
}
|
||||
contextMenu();
|
||||
}
|
||||
QString Scene_edit_box_item::toolTip() const {
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
|
||||
QMenu* Scene_edit_box_item::contextMenu()
|
||||
{
|
||||
// diasable "Alpha slider" in menu
|
||||
QMenu* resMenu = Scene_item::contextMenu();
|
||||
bool prop = property("menu_changed").toBool();
|
||||
if(!prop)
|
||||
{
|
||||
setProperty("menu_changed", true);
|
||||
}
|
||||
return resMenu;
|
||||
}
|
||||
|
||||
void Scene_edit_box_item::drawSpheres(Viewer_interface *viewer, const QMatrix4x4 f_matrix ) const
|
||||
{
|
||||
GLdouble d_mat[16];
|
||||
|
|
@ -941,7 +973,7 @@ void Scene_edit_box_item_priv::remodel_box(const QVector3D &dir)
|
|||
for(Scene_edit_box_item::vertex* selected_vertex: selected_vertices )
|
||||
{
|
||||
int id = selected_vertex->id;
|
||||
CGAL_assume(id<8);
|
||||
CGAL_assume(id<8 && id >=0);
|
||||
*selected_vertex->x = applyX(id, last_pool[id][0], dir.x());
|
||||
*selected_vertex->y = applyY(id, last_pool[id][1], dir.y());
|
||||
*selected_vertex->z = applyZ(id, last_pool[id][2], dir.z());
|
||||
|
|
@ -1307,3 +1339,8 @@ void Scene_edit_box_item::connectNewViewer(QObject *o)
|
|||
return;
|
||||
viewer->setMouseTracking(true);
|
||||
}
|
||||
|
||||
void Scene_edit_box_item::reset()
|
||||
{
|
||||
d->reset_vertices();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ class SCENE_EDIT_BOX_ITEM_EXPORT Scene_edit_box_item:
|
|||
}
|
||||
|
||||
QString toolTip() const;
|
||||
QMenu* contextMenu();
|
||||
|
||||
bool eventFilter(QObject *, QEvent *);
|
||||
// Indicate if rendering mode is supported
|
||||
|
|
@ -59,6 +60,7 @@ public Q_SLOTS:
|
|||
void highlight(CGAL::Three::Viewer_interface* viewer);
|
||||
void clearHL();
|
||||
void connectNewViewer(QObject* o);
|
||||
void reset();
|
||||
protected:
|
||||
friend struct Scene_edit_box_item_priv;
|
||||
Scene_edit_box_item_priv* d;
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ template <typename Word_type>
|
|||
class Image_accessor
|
||||
{
|
||||
public:
|
||||
Image_accessor(const Image& im, int dx=1, int dy=1, int dz=1);
|
||||
Image_accessor(const Image& im, int dx=1, int dy=1, int dz=1, const QColor& default_color = QColor());
|
||||
|
||||
bool is_vertex_active(std::size_t i, std::size_t j, std::size_t k) const;
|
||||
const QColor& vertex_color(std::size_t i, std::size_t j, std::size_t k) const;
|
||||
|
|
@ -64,12 +64,12 @@ private:
|
|||
};
|
||||
|
||||
template <typename Word_type>
|
||||
Image_accessor<Word_type>::Image_accessor(const Image& im, int dx, int dy, int dz)
|
||||
Image_accessor<Word_type>::Image_accessor(const Image& im, int dx, int dy, int dz, const QColor& default_color)
|
||||
: im_(&im)
|
||||
, dx_(dx)
|
||||
, dy_(dy)
|
||||
, dz_(dz)
|
||||
, default_color_()
|
||||
, default_color_(default_color)
|
||||
, colors_()
|
||||
{
|
||||
const std::size_t xdim = im_->xdim();
|
||||
|
|
@ -88,14 +88,15 @@ Image_accessor<Word_type>::Image_accessor(const Image& im, int dx, int dy, int d
|
|||
}
|
||||
}
|
||||
|
||||
double i=0;
|
||||
const double starting_hue = 45./360.; // magenta
|
||||
const double nb_Colors = colors_.size()+1;
|
||||
double i=1;
|
||||
const double starting_hue = default_color.hueF();
|
||||
for ( auto it = colors_.begin(),
|
||||
end = colors_.end() ; it != end ; ++it, i += 1.)
|
||||
{
|
||||
double hue = starting_hue + 1./double(colors_.size()) * i;
|
||||
double hue = starting_hue + 1./nb_Colors * i;
|
||||
if ( hue > 1. ) { hue -= 1.; }
|
||||
it->second = QColor::fromHsvF(hue, .75, .75);
|
||||
it->second = QColor::fromHsvF(hue, default_color.saturationF(), default_color.valueF());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -113,15 +114,7 @@ is_vertex_active(std::size_t i, std::size_t j, std::size_t k) const
|
|||
Word_type v7 = image_data(i , j , k-dz_);
|
||||
Word_type v8 = image_data(i , j , k );
|
||||
|
||||
// don't draw interior vertices
|
||||
if ( v1 != 0 && v2 != 0 && v3 != 0 && v4 != 0 &&
|
||||
v5 != 0 && v6 != 0 && v7 != 0 && v8 != 0 )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return ( v1 != 0 || v2 != 0 || v3 != 0 || v4 != 0 ||
|
||||
v5 != 0 || v6 != 0 || v7 != 0 || v8 != 0 );
|
||||
return v1 != v2 || v1 != v3 || v1 != v4 || v1 != v5 || v1 != v6 || v1 != v7 || v1 != v8;
|
||||
}
|
||||
template <typename Word_type>
|
||||
const QColor&
|
||||
|
|
@ -755,6 +748,7 @@ void Scene_image_item::drawEdges(Viewer_interface *viewer) const
|
|||
getEdgeContainer(0)->setWidth(3.0f);
|
||||
}
|
||||
getEdgeContainer(0)->setColor(QColor(Qt::black));
|
||||
getEdgeContainer(0)->setClipping(false);
|
||||
viewer->glDepthRangef(0.00001f, 0.99999f);
|
||||
getEdgeContainer(0)->draw(viewer, true);
|
||||
viewer->glDepthRangef(0.0f, 1.0f);
|
||||
|
|
@ -762,6 +756,11 @@ void Scene_image_item::drawEdges(Viewer_interface *viewer) const
|
|||
|
||||
bool Scene_image_item::isGray() { return d->is_hidden;}
|
||||
|
||||
void Scene_image_item::setColor(QColor c) {
|
||||
color_ = c;
|
||||
invalidateOpenGLBuffers();
|
||||
}
|
||||
|
||||
void Scene_image_item::invalidateOpenGLBuffers()
|
||||
{
|
||||
setBuffersFilled(false);
|
||||
|
|
@ -788,9 +787,9 @@ void Scene_image_item::initializeBuffers(Viewer_interface *v) const
|
|||
|
||||
template <typename Word_type>
|
||||
internal::Vertex_buffer_helper*
|
||||
init_helper(const Image &im, int dx, int dy, int dz, bool is_ogl_4_3)
|
||||
init_helper(const Image &im, int dx, int dy, int dz, bool is_ogl_4_3, const QColor& default_color = QColor())
|
||||
{
|
||||
internal::Image_accessor<Word_type> image_data_accessor(im, dx, dy, dz);
|
||||
internal::Image_accessor<Word_type> image_data_accessor(im, dx, dy, dz, default_color);
|
||||
return new internal::Vertex_buffer_helper_impl<Word_type>(std::move(image_data_accessor),
|
||||
is_ogl_4_3);
|
||||
}
|
||||
|
|
@ -809,7 +808,8 @@ void Scene_image_item::computeElements() const
|
|||
CGAL_IMAGE_IO_CASE(m_image->image(),
|
||||
d->helper = init_helper<Word>(*m_image,
|
||||
d->m_voxel_scale, d->m_voxel_scale, d->m_voxel_scale,
|
||||
d->is_ogl_4_3));
|
||||
d->is_ogl_4_3,
|
||||
color_));
|
||||
d->helper->fill_buffer_data();
|
||||
getTriangleContainer(0)->allocate(
|
||||
Tc::Smooth_vertices,
|
||||
|
|
|
|||
|
|
@ -50,6 +50,8 @@ public:
|
|||
float sigma_weights() const;
|
||||
float default_sigma_weights() const;
|
||||
|
||||
void setColor(QColor c);
|
||||
|
||||
void invalidateOpenGLBuffers();
|
||||
void initializeBuffers(Viewer_interface *) const;
|
||||
void computeElements() const;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
#include "Scene.h"
|
||||
#include "config.h"
|
||||
#include "Scene_triangulation_3_item.h"
|
||||
#include "Scene_surface_mesh_item.h"
|
||||
#include "Scene_spheres_item.h"
|
||||
#include "Plugins/PCA/Scene_edit_box_item.h"
|
||||
|
||||
#include <QVector>
|
||||
#include <QColor>
|
||||
|
|
@ -20,6 +22,7 @@
|
|||
#include <unordered_map>
|
||||
#include <bitset>
|
||||
|
||||
#include <CGAL/Three/Scene_item.h>
|
||||
#include <CGAL/Three/Scene_interface.h>
|
||||
#include <CGAL/Three/Triangle_container.h>
|
||||
#include <CGAL/Three/Edge_container.h>
|
||||
|
|
@ -179,7 +182,15 @@ public :
|
|||
QVector4D cp = cgal_plane_to_vector4d(plane);
|
||||
getEdgeContainer(0)->setPlane(cp);
|
||||
getEdgeContainer(0)->setColor(QColor(Qt::black));
|
||||
getEdgeContainer(0)->draw(viewer, true);
|
||||
if (!cut_edges) {
|
||||
bool clipping = getEdgeContainer(0)->getClipping();
|
||||
getEdgeContainer(0)->setClipping(false);
|
||||
getEdgeContainer(0)->draw(viewer, true);
|
||||
getEdgeContainer(0)->setClipping(clipping);
|
||||
}
|
||||
else {
|
||||
getEdgeContainer(0)->draw(viewer, true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -278,6 +289,10 @@ public :
|
|||
m_alpha = a / 255.0f;
|
||||
redraw();
|
||||
}
|
||||
void setCutEdges(bool b)
|
||||
{
|
||||
cut_edges = b;
|
||||
}
|
||||
private:
|
||||
|
||||
//contains the data
|
||||
|
|
@ -290,6 +305,8 @@ private:
|
|||
mutable bool is_fast;
|
||||
mutable QSlider* alphaSlider;
|
||||
mutable float m_alpha ;
|
||||
|
||||
bool cut_edges;
|
||||
}; //end of class Scene_triangle_item
|
||||
|
||||
|
||||
|
|
@ -353,6 +370,7 @@ struct Scene_triangulation_3_item_priv {
|
|||
is_aabb_tree_built = false;
|
||||
alphaSlider = NULL;
|
||||
is_filterable = true;
|
||||
visible_bitset.fill(0xFFFFFFFF);
|
||||
}
|
||||
void computeIntersection(const Primitive& facet);
|
||||
void fill_aabb_tree() {
|
||||
|
|
@ -436,12 +454,30 @@ struct Scene_triangulation_3_item_priv {
|
|||
Scene_spheres_item *spheres;
|
||||
std::vector<Tr::Vertex> tr_vertices;
|
||||
Scene_intersection_item *intersection;
|
||||
void set_intersection_enabled(bool b)
|
||||
{
|
||||
if (intersection)
|
||||
intersection->setVisible(b);
|
||||
cut_plane_enabled = b;
|
||||
}
|
||||
bool is_intersection_enabled()
|
||||
{
|
||||
return cut_plane_enabled;
|
||||
}
|
||||
bool is_item_clip_box(int id)
|
||||
{
|
||||
if(dynamic_cast<Scene_edit_box_item*>(CGAL::Three::Three::scene()->item(id)))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
bool spheres_are_shown;
|
||||
const Scene_item* data_item_;
|
||||
QPixmap histogram_;
|
||||
typedef std::set<int> Indices;
|
||||
Indices surface_patch_indices_;
|
||||
Indices subdomain_indices_;
|
||||
std::unordered_map<int, int> visible_surface_patch_to_subdomain;
|
||||
std::unordered_map<int, int> id_to_compact;
|
||||
QSlider* tet_Slider;
|
||||
bool is_filterable;
|
||||
|
|
@ -492,10 +528,12 @@ struct Scene_triangulation_3_item_priv {
|
|||
QVector<QColor> colors;
|
||||
QVector<QColor> colors_subdomains;
|
||||
boost::dynamic_bitset<> visible_subdomain;
|
||||
std::bitset<24> bs[4] = {16777215, 16777215, 16777215, 16777215};
|
||||
std::array<std::bitset<32>, Scene_triangulation_3_item::number_of_bitset> visible_bitset;
|
||||
bool show_tetrahedra;
|
||||
bool cut_plane_enabled;
|
||||
bool is_aabb_tree_built;
|
||||
bool last_intersection;
|
||||
bool cut_edges;
|
||||
|
||||
void push_normal(std::vector<float>& normals, const EPICK::Vector_3& n) const
|
||||
{
|
||||
|
|
@ -539,6 +577,7 @@ void Scene_triangulation_3_item::common_constructor(bool display_elements)
|
|||
|
||||
d->is_grid_shown = display_elements;
|
||||
d->show_tetrahedra = display_elements;
|
||||
d->cut_plane_enabled = display_elements;
|
||||
d->last_intersection = !d->show_tetrahedra;
|
||||
|
||||
setTriangleContainer(T3_faces, new Tc(Vi::PROGRAM_C3T3, false));
|
||||
|
|
@ -549,6 +588,14 @@ void Scene_triangulation_3_item::common_constructor(bool display_elements)
|
|||
{
|
||||
v->installEventFilter(this);
|
||||
}
|
||||
for(int i = 0, end = scene->numberOfEntries();
|
||||
i < end; ++i)
|
||||
{
|
||||
if (d->is_item_clip_box(i))
|
||||
d->set_intersection_enabled(false);
|
||||
}
|
||||
connect(static_cast<Scene*>(CGAL::Three::Three::scene()), SIGNAL(newItem(int)), this, SLOT(check_new_item(int)));
|
||||
connect(static_cast<Scene*>(CGAL::Three::Three::scene()), SIGNAL(indexErased(Scene_interface::Item_id)), this, SLOT(check_deleted_item(Scene_interface::Item_id)));
|
||||
}
|
||||
Scene_triangulation_3_item::Scene_triangulation_3_item(bool display_elements)
|
||||
: Scene_group_item("unnamed")
|
||||
|
|
@ -601,6 +648,20 @@ Scene_triangulation_3_item::data_item_destroyed()
|
|||
set_data_item(NULL);
|
||||
}
|
||||
|
||||
void
|
||||
Scene_triangulation_3_item::check_new_item(int id)
|
||||
{
|
||||
if (d->is_item_clip_box(id))
|
||||
d->set_intersection_enabled(false);
|
||||
}
|
||||
|
||||
void
|
||||
Scene_triangulation_3_item::check_deleted_item(Scene_interface::Item_id id)
|
||||
{
|
||||
if (d->is_item_clip_box(id))
|
||||
d->set_intersection_enabled(true);
|
||||
}
|
||||
|
||||
const T3&
|
||||
Scene_triangulation_3_item::triangulation() const {
|
||||
return d->triangulation;
|
||||
|
|
@ -643,6 +704,7 @@ Scene_triangulation_3_item::triangulation_changed()
|
|||
// Fill indices map and get max subdomain value
|
||||
d->surface_patch_indices_.clear();
|
||||
d->subdomain_indices_.clear();
|
||||
d->visible_surface_patch_to_subdomain.clear();
|
||||
d->visible_subdomain.clear();
|
||||
d->id_to_compact.clear();
|
||||
|
||||
|
|
@ -659,12 +721,23 @@ Scene_triangulation_3_item::triangulation_changed()
|
|||
}
|
||||
const int max_subdomain_index = max;
|
||||
d->visible_subdomain.resize(max_subdomain_index+1, true);
|
||||
d->is_filterable &=( d->subdomain_ids.size() < 96);
|
||||
d->is_filterable &=( d->subdomain_indices_.size() < 32*number_of_bitset-1);
|
||||
for (Tr::Finite_facets_iterator fit = triangulation().finite_facets_begin(),
|
||||
end = triangulation().finite_facets_end(); fit != end; ++fit)
|
||||
{
|
||||
max = (std::max)(max, fit->first->surface_patch_index(fit->second));
|
||||
d->surface_patch_indices_.insert(fit->first->surface_patch_index(fit->second));
|
||||
int index = fit->first->surface_patch_index(fit->second);
|
||||
d->surface_patch_indices_.insert(index);
|
||||
int dom0 = fit->first->subdomain_index();
|
||||
int dom1 = fit->first->neighbor(fit->second)->subdomain_index();
|
||||
if (dom0 == 0) // if cell is not in complex
|
||||
{
|
||||
d->visible_surface_patch_to_subdomain[index] = dom1;
|
||||
}
|
||||
else if (dom1 == 0) // if opposite cell is not in complex
|
||||
{
|
||||
d->visible_surface_patch_to_subdomain[index] = dom0;
|
||||
}
|
||||
}
|
||||
|
||||
d->colors.resize(max + 1);
|
||||
|
|
@ -882,17 +955,26 @@ Scene_triangulation_3_item_priv::compute_color_map(const QColor& c)
|
|||
}
|
||||
const size_type nb_patch_indices = surface_patch_indices_.size();
|
||||
i = 0;
|
||||
double patch_hsv_value = fmod(c.valueF() + .5, 1.);
|
||||
for (Indices::iterator it = surface_patch_indices_.begin(),
|
||||
end = surface_patch_indices_.end(); it != end; ++it, i += 1.)
|
||||
{
|
||||
double hue = c.hueF() + 1. / double(nb_patch_indices) * i;
|
||||
if (hue > 1) { hue -= 1.; }
|
||||
colors[*it] = QColor::fromHsvF(hue, c.saturationF(), c.valueF());
|
||||
colors[*it] = QColor::fromHsvF(hue, c.saturationF(), patch_hsv_value);
|
||||
}
|
||||
|
||||
for (std::unordered_map<int, int>::iterator it = visible_surface_patch_to_subdomain.begin(),
|
||||
end = visible_surface_patch_to_subdomain.end(); it != end; ++it)
|
||||
{
|
||||
colors[it->first] = colors_subdomains[it->second];
|
||||
}
|
||||
}
|
||||
|
||||
Geom_traits::Plane_3 Scene_triangulation_3_item::plane(CGAL::qglviewer::Vec offset) const
|
||||
{
|
||||
if (!d->is_intersection_enabled())
|
||||
return Geom_traits::Plane_3(1.0, 0.0, 0.0, std::numeric_limits<float>::max());
|
||||
const CGAL::qglviewer::Vec& pos = d->frame->position() - offset;
|
||||
const CGAL::qglviewer::Vec& n =
|
||||
d->frame->inverseTransformOf(CGAL::qglviewer::Vec(0.f, 0.f, 1.f));
|
||||
|
|
@ -972,8 +1054,11 @@ void Scene_triangulation_3_item::draw(CGAL::Three::Viewer_interface* viewer) con
|
|||
program->bind();
|
||||
if(d->is_filterable)
|
||||
{
|
||||
QVector4D visible_bitset(d->bs[0].to_ulong(),d->bs[1].to_ulong(),d->bs[2].to_ulong(),d->bs[3].to_ulong());
|
||||
program->setUniformValue("is_visible_bitset", visible_bitset);
|
||||
std::array<GLuint, number_of_bitset> visible_bitset_ulong;
|
||||
std::transform(d->visible_bitset.cbegin(), d->visible_bitset.cend(), visible_bitset_ulong.begin(),
|
||||
[](const std::bitset<32>& bitset) { return bitset.to_ulong(); }
|
||||
);
|
||||
program->setUniformValueArray("is_visible_bitset", visible_bitset_ulong.data(), number_of_bitset);
|
||||
}
|
||||
program->setUniformValue("is_filterable", d->is_filterable);
|
||||
program->release();
|
||||
|
|
@ -998,7 +1083,7 @@ void Scene_triangulation_3_item::draw(CGAL::Three::Viewer_interface* viewer) con
|
|||
d->spheres->setPlane(this->plane());
|
||||
}
|
||||
}
|
||||
if(d->is_grid_shown)
|
||||
if(d->is_grid_shown && d->is_intersection_enabled())
|
||||
{
|
||||
|
||||
getEdgeContainer(Grid_edges)->setColor(QColor(Qt::black));
|
||||
|
|
@ -1006,7 +1091,11 @@ void Scene_triangulation_3_item::draw(CGAL::Three::Viewer_interface* viewer) con
|
|||
for (int i = 0; i<16; i++)
|
||||
f_mat.data()[i] = static_cast<float>(d->frame->matrix()[i]);
|
||||
getEdgeContainer(Grid_edges)->setFrameMatrix(f_mat);
|
||||
// always draw plane (disable clipping)
|
||||
bool clipping = getEdgeContainer(Grid_edges)->getClipping();
|
||||
getEdgeContainer(Grid_edges)->setClipping(false);
|
||||
getEdgeContainer(Grid_edges)->draw(viewer, true);
|
||||
getEdgeContainer(Grid_edges)->setClipping(clipping);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1036,14 +1125,18 @@ void Scene_triangulation_3_item::drawEdges(CGAL::Three::Viewer_interface* viewer
|
|||
computeElements();
|
||||
initializeBuffers(viewer);
|
||||
}
|
||||
if(renderingMode() == Wireframe && d->is_grid_shown)
|
||||
if(renderingMode() == Wireframe && d->is_grid_shown && d->is_intersection_enabled())
|
||||
{
|
||||
getEdgeContainer(Grid_edges)->setColor(QColor(Qt::black));
|
||||
QMatrix4x4 f_mat;
|
||||
for (int i = 0; i<16; i++)
|
||||
f_mat.data()[i] = static_cast<float>(d->frame->matrix()[i]);
|
||||
getEdgeContainer(Grid_edges)->setFrameMatrix(f_mat);
|
||||
// always draw plane (disable clipping)
|
||||
bool clipping = getEdgeContainer(Grid_edges)->getClipping();
|
||||
getEdgeContainer(Grid_edges)->setClipping(false);
|
||||
getEdgeContainer(Grid_edges)->draw(viewer, true);
|
||||
getEdgeContainer(Grid_edges)->setClipping(clipping);
|
||||
}
|
||||
|
||||
QVector4D cp = cgal_plane_to_vector4d(this->plane());
|
||||
|
|
@ -1051,15 +1144,26 @@ void Scene_triangulation_3_item::drawEdges(CGAL::Three::Viewer_interface* viewer
|
|||
program->bind();
|
||||
if(d->is_filterable)
|
||||
{
|
||||
QVector4D visible_bitset(d->bs[0].to_ulong(),d->bs[1].to_ulong(),d->bs[2].to_ulong(),d->bs[3].to_ulong());
|
||||
program->setUniformValue("is_visible_bitset", visible_bitset);
|
||||
std::array<GLuint, number_of_bitset> visible_bitset_ulong;
|
||||
std::transform(d->visible_bitset.cbegin(), d->visible_bitset.cend(), visible_bitset_ulong.begin(),
|
||||
[](const std::bitset<32>& bitset) { return bitset.to_ulong(); }
|
||||
);
|
||||
program->setUniformValueArray("is_visible_bitset", visible_bitset_ulong.data(), number_of_bitset);
|
||||
}
|
||||
program->setUniformValue("is_filterable", d->is_filterable);
|
||||
program->release();
|
||||
getEdgeContainer(T3_edges)->setPlane(cp);
|
||||
getEdgeContainer(T3_edges)->setIsSurface(is_surface());
|
||||
getEdgeContainer(T3_edges)->setColor(QColor(Qt::black));
|
||||
getEdgeContainer(T3_edges)->draw(viewer, true);
|
||||
if (!d->cut_edges) {
|
||||
bool clipping = getEdgeContainer(T3_edges)->getClipping();
|
||||
getEdgeContainer(T3_edges)->setClipping(false);
|
||||
getEdgeContainer(T3_edges)->draw(viewer, true);
|
||||
getEdgeContainer(T3_edges)->setClipping(clipping);
|
||||
}
|
||||
else {
|
||||
getEdgeContainer(T3_edges)->draw(viewer, true);
|
||||
}
|
||||
|
||||
if(d->show_tetrahedra){
|
||||
if(!d->frame->isManipulated())
|
||||
|
|
@ -1197,6 +1301,14 @@ QMenu* Scene_triangulation_3_item::contextMenu()
|
|||
this, SLOT(show_spheres(bool)));
|
||||
}
|
||||
|
||||
QAction* actionToggleCutEdges =
|
||||
menu->addAction(tr("Cut &edges"));
|
||||
actionToggleCutEdges->setCheckable(true);
|
||||
actionToggleCutEdges->setChecked(true);
|
||||
actionToggleCutEdges->setObjectName("actionToggleCutEdges");
|
||||
connect(actionToggleCutEdges, SIGNAL(toggled(bool)),
|
||||
this, SLOT(set_cut_edge(bool)));
|
||||
|
||||
menu->setProperty(prop_name, true);
|
||||
}
|
||||
return menu;
|
||||
|
|
@ -2043,6 +2155,12 @@ QColor Scene_triangulation_3_item::getSubdomainIndexColor(int i) const
|
|||
return d->colors_subdomains[i];
|
||||
}
|
||||
|
||||
void Scene_triangulation_3_item::resetVisibleSubdomain()
|
||||
{
|
||||
d->visible_subdomain.set();
|
||||
d->visible_bitset.fill(0xFFFFFFFF);
|
||||
}
|
||||
|
||||
void Scene_triangulation_3_item::switchVisibleSubdomain(int id)
|
||||
{
|
||||
d->visible_subdomain[id] = !d->visible_subdomain[id];
|
||||
|
|
@ -2050,7 +2168,12 @@ void Scene_triangulation_3_item::switchVisibleSubdomain(int id)
|
|||
int i = compact_id/32;
|
||||
int j = compact_id%32;
|
||||
|
||||
d->bs[i][j] = d->visible_subdomain[id];
|
||||
d->visible_bitset[i][j] = d->visible_subdomain[id];
|
||||
}
|
||||
|
||||
bool Scene_triangulation_3_item::isVisibleSubdomain(int id) const
|
||||
{
|
||||
return d->visible_subdomain[id];
|
||||
}
|
||||
|
||||
void Scene_triangulation_3_item::computeIntersection()
|
||||
|
|
@ -2061,5 +2184,12 @@ void Scene_triangulation_3_item::computeIntersection()
|
|||
}
|
||||
}
|
||||
|
||||
void Scene_triangulation_3_item::set_cut_edge(bool b)
|
||||
{
|
||||
d->cut_edges = b;
|
||||
d->intersection->setCutEdges(b);
|
||||
Q_EMIT redraw();
|
||||
}
|
||||
|
||||
#include "Scene_triangulation_3_item.moc"
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ using namespace CGAL::Three;
|
|||
Q_OBJECT
|
||||
public:
|
||||
typedef CGAL::qglviewer::ManipulatedFrame ManipulatedFrame;
|
||||
static const int number_of_bitset = 4; // also defined in "shader_c3t3.frag" and "shader_c3t3_edges.frag"
|
||||
|
||||
Scene_triangulation_3_item(bool display_elements = true);
|
||||
Scene_triangulation_3_item(const T3 t3, bool display_elements = true);
|
||||
|
|
@ -121,6 +122,9 @@ public:
|
|||
|
||||
void data_item_destroyed();
|
||||
|
||||
void check_new_item(int id);
|
||||
void check_deleted_item(Scene_interface::Item_id id);
|
||||
|
||||
void reset_spheres();
|
||||
|
||||
void reset_intersection_item();
|
||||
|
|
@ -128,6 +132,7 @@ public:
|
|||
void show_grid(bool b);
|
||||
void show_spheres(bool b);
|
||||
void computeIntersection();
|
||||
void set_cut_edge(bool b);
|
||||
|
||||
virtual QPixmap graphicalToolTip() const Q_DECL_OVERRIDE;
|
||||
|
||||
|
|
@ -141,7 +146,9 @@ public:
|
|||
|
||||
QColor get_histogram_color(const double v) const;
|
||||
|
||||
void resetVisibleSubdomain();
|
||||
void switchVisibleSubdomain(int);
|
||||
bool isVisibleSubdomain(int) const;
|
||||
|
||||
void itemAboutToBeDestroyed(Scene_item *) Q_DECL_OVERRIDE;
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ in GS_OUT
|
|||
flat vec4 color[4];
|
||||
vec2 uv;
|
||||
flat vec4 prob[4];
|
||||
float dist[6];
|
||||
} fs_in;
|
||||
|
||||
uniform bool is_two_side;
|
||||
|
|
@ -15,11 +16,20 @@ uniform vec4 light_diff;
|
|||
uniform vec4 light_spec;
|
||||
uniform vec4 light_amb;
|
||||
uniform float spec_power ;
|
||||
uniform bool is_clipbox_on;
|
||||
|
||||
out vec4 out_color;
|
||||
|
||||
void main(void)
|
||||
{
|
||||
if(is_clipbox_on)
|
||||
if(fs_in.dist[0]>0.0 ||
|
||||
fs_in.dist[1]>0.0 ||
|
||||
fs_in.dist[2]>0.0 ||
|
||||
fs_in.dist[3]>0.0 ||
|
||||
fs_in.dist[4]>0.0 ||
|
||||
fs_in.dist[5]>0.0)
|
||||
discard;
|
||||
vec4 color;
|
||||
//find base color of pixel
|
||||
vec4 m1 = mix(fs_in.prob[0], fs_in.prob[1], fs_in.uv.y);
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ in VS_OUT
|
|||
vec4 fP;
|
||||
vec3 fN;
|
||||
vec4 out_color;
|
||||
float dist[6];
|
||||
} gs_in[4];
|
||||
|
||||
out GS_OUT
|
||||
|
|
@ -17,6 +18,7 @@ out GS_OUT
|
|||
flat vec4 color[4];
|
||||
vec2 uv;
|
||||
flat vec4 prob[4];
|
||||
float dist[6];
|
||||
} gs_out;
|
||||
|
||||
void main(void)
|
||||
|
|
@ -25,19 +27,21 @@ void main(void)
|
|||
gs_out.fN = gs_in[0].fN;
|
||||
gs_out.fP = gs_in[0].fP;
|
||||
gs_out.uv = vec2(0.0, 0.0);
|
||||
|
||||
gs_out.dist = gs_in[0].dist;
|
||||
EmitVertex();
|
||||
|
||||
gl_Position = gl_in[1].gl_Position;
|
||||
gs_out.fN = gs_in[1].fN;
|
||||
gs_out.fP = gs_in[1].fP;
|
||||
gs_out.uv = vec2(0.0, 1.0);
|
||||
gs_out.dist = gs_in[1].dist;
|
||||
EmitVertex();
|
||||
|
||||
gl_Position = gl_in[3].gl_Position;
|
||||
gs_out.fN = gs_in[3].fN;
|
||||
gs_out.fP = gs_in[3].fP;
|
||||
gs_out.uv = vec2(1.0, 0.0);
|
||||
gs_out.dist = gs_in[3].dist;
|
||||
|
||||
// We're only writing the output color for the last
|
||||
// vertex here because they're flat attributes,
|
||||
|
|
@ -67,18 +71,21 @@ void main(void)
|
|||
gs_out.fN = gs_in[1].fN;
|
||||
gs_out.fP = gs_in[1].fP;
|
||||
gs_out.uv = vec2(0.0, 1.0);
|
||||
gs_out.dist = gs_in[1].dist;
|
||||
EmitVertex();
|
||||
|
||||
gl_Position = gl_in[2].gl_Position;
|
||||
gs_out.fN = gs_in[2].fN;
|
||||
gs_out.fP = gs_in[2].fP;
|
||||
gs_out.uv = vec2(1.0, 1.0);
|
||||
gs_out.dist = gs_in[2].dist;
|
||||
EmitVertex();
|
||||
|
||||
gl_Position = gl_in[3].gl_Position;
|
||||
gs_out.fN = gs_in[3].fN;
|
||||
gs_out.fP = gs_in[3].fP;
|
||||
gs_out.uv = vec2(1.0, 0.0);
|
||||
gs_out.dist = gs_in[3].dist;
|
||||
// Again, only write the output color for the last vertex
|
||||
gs_out.color[0] = gs_in[0].out_color;
|
||||
gs_out.color[1] = gs_in[1].out_color;
|
||||
|
|
|
|||
|
|
@ -9,15 +9,39 @@ out VS_OUT
|
|||
vec4 fP;
|
||||
vec3 fN;
|
||||
vec4 out_color;
|
||||
float dist[6];
|
||||
}vs_out;
|
||||
|
||||
uniform mat4 mvp_matrix;
|
||||
uniform mat4 mv_matrix;
|
||||
uniform mat4 norm_matrix;
|
||||
|
||||
uniform bool is_clipbox_on;
|
||||
uniform mat4 clipbox1;
|
||||
uniform mat4 clipbox2;
|
||||
|
||||
void compute_distances(void)
|
||||
{
|
||||
for(int i=0; i<3; ++i)
|
||||
{
|
||||
vs_out.dist[i]=
|
||||
clipbox1[i][0]*vertex.x+
|
||||
clipbox1[i][1]*vertex.y+
|
||||
clipbox1[i][2]*vertex.z +
|
||||
clipbox1[i][3];
|
||||
vs_out.dist[i+3]=
|
||||
clipbox2[i][0]*vertex.x+
|
||||
clipbox2[i][1]*vertex.y+
|
||||
clipbox2[i][2]*vertex.z +
|
||||
clipbox2[i][3];
|
||||
}
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
vs_out.out_color=colors;
|
||||
if(is_clipbox_on)
|
||||
compute_distances();
|
||||
vs_out.fP = mv_matrix * vertex;
|
||||
vs_out.fN = mat3(norm_matrix)* normals;
|
||||
gl_Position = mvp_matrix * vertex;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,11 @@
|
|||
#version 150
|
||||
|
||||
const int number_of_bitset = 4;
|
||||
|
||||
in vec4 color;
|
||||
in vec4 fP;
|
||||
in vec3 fN;
|
||||
in float dist[6];
|
||||
flat in vec2 subdomain_out;
|
||||
uniform vec4 light_pos;
|
||||
uniform vec4 light_diff;
|
||||
|
|
@ -10,6 +14,7 @@ uniform vec4 light_amb;
|
|||
uniform float spec_power ;
|
||||
uniform int is_two_side;
|
||||
uniform bool is_selected;
|
||||
uniform bool is_clipbox_on;
|
||||
uniform float near;
|
||||
uniform float far;
|
||||
uniform float width;
|
||||
|
|
@ -19,8 +24,8 @@ uniform bool writing;
|
|||
uniform sampler2D sampler;
|
||||
uniform float alpha;
|
||||
uniform bool is_surface;
|
||||
uniform vec4 is_visible_bitset;
|
||||
uniform bool is_filterable;
|
||||
uniform int is_visible_bitset[number_of_bitset];
|
||||
out vec4 out_color;
|
||||
|
||||
float depth(float z)
|
||||
|
|
@ -28,19 +33,38 @@ float depth(float z)
|
|||
return (2 * near) / (far + near - z * (far - near));
|
||||
}
|
||||
|
||||
void main(void) {
|
||||
bool compute_clip_visibility() {
|
||||
if(is_clipbox_on)
|
||||
return dist[0]>0.0 ||
|
||||
dist[1]>0.0 ||
|
||||
dist[2]>0.0 ||
|
||||
dist[3]>0.0 ||
|
||||
dist[4]>0.0 ||
|
||||
dist[5]>0.0;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool compute_filtering_visibility() {
|
||||
if(is_filterable)
|
||||
{
|
||||
uint domain1 = uint(subdomain_out.x);
|
||||
uint domain2 = uint(subdomain_out.y);
|
||||
uint i1 = domain1/25u;
|
||||
uint i2 = domain2/25u;
|
||||
uint i1 = domain1/32u;
|
||||
uint j1 = domain1%32u;
|
||||
uint i2 = domain2/32u;
|
||||
uint j2 = domain2%32u;
|
||||
uint visible1 = uint(is_visible_bitset[i1]);
|
||||
uint visible2 = uint(is_visible_bitset[i2]);
|
||||
if((visible1>>(domain1%25u))%2u == 0u && (visible2>>(domain2%25u))%2u == 0u)
|
||||
{
|
||||
discard;
|
||||
}
|
||||
return ((visible1>>j1)&1u) == 0u && ((visible2>>j2)&1u) == 0u;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void main(void) {
|
||||
if (compute_clip_visibility() || compute_filtering_visibility()) {
|
||||
discard;
|
||||
}
|
||||
float d = depth(gl_FragCoord.z);
|
||||
float test = texture(sampler, vec2(gl_FragCoord.x/width, gl_FragCoord.y/height)).r;
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue