Merge remote-tracking branch 'cgal/master' into CGAL-Qt6-GF

# Conflicts:
#	GraphicsView/demo/Bounding_volumes/CMakeLists.txt
This commit is contained in:
Laurent Rineau 2023-11-01 20:59:44 +01:00
commit 51627e3505
125 changed files with 112022 additions and 110309 deletions

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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")

View File

@ -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>;

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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]);
}
}

View File

@ -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

View File

@ -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

View File

@ -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();

View File

@ -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.

View File

@ -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 */

View File

@ -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 */

View File

@ -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;
/// @}

View File

@ -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 */

View File

@ -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;

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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,

View File

@ -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);

View File

@ -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}

View File

@ -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)

View File

@ -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

View File

@ -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.

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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 */

View File

@ -47,12 +47,12 @@ Box_traits_d();
/*!
\ingroup PkgBoxIntersectionDFunctions
\ingroup PkgBoxIntersectionDEnums
*/
enum Setting { COMPLETE, BIPARTITE };
/*!
\ingroup PkgBoxIntersectionDFunctions
\ingroup PkgBoxIntersectionDEnums
*/
enum Topology { HALF_OPEN, CLOSED };

View File

@ -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`
*/

View File

@ -4,3 +4,4 @@ STL_Extension
Algebraic_foundations
Circulator
Stream_support
Polyhedron

View File

@ -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;

View File

@ -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&eacute;d&eacute;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&eacute;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&auml;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&eacute;d&eacute;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&eacute;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&auml;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 */

View File

@ -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,

View File

@ -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}.
*/

View File

@ -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>.

View File

@ -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}

View File

@ -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.
*/

View File

@ -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

View File

@ -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" \

View File

@ -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" \

View File

@ -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>

View File

@ -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?

View File

@ -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 */

View File

@ -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)

View File

@ -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);
}

View File

@ -0,0 +1,3 @@
0 2
2 1
0 0

View File

@ -0,0 +1,4 @@
-2 1
-2 -1
2 1
2 -1

View File

@ -0,0 +1,4 @@
-2 -1
-1 -2
1 2
2 1

View File

@ -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)); }
}
}
}

View File

@ -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):5685, 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.

View File

@ -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`

View File

@ -1,7 +1,6 @@
namespace CGAL {
/*!
\ingroup kernel_affine
\ingroup kernel_classes2
The class `Aff_transformation_2` represents two-dimensional affine transformations.

View File

@ -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

View File

@ -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.

View File

@ -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
*/
/// @{

View File

@ -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)
{

View File

@ -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);

View File

@ -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 */

View File

@ -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 */

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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>

View File

@ -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>

View File

@ -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;

View File

@ -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`

View File

@ -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

View File

@ -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

View File

@ -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";

View File

@ -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_;
}

View File

@ -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

View File

@ -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(

View File

@ -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;

View File

@ -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 )

View File

@ -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"

View File

@ -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.")

View File

@ -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);

View File

@ -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);

View File

@ -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)

View File

@ -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"

View File

@ -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">

View File

@ -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();
}

View File

@ -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;

View File

@ -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,

View File

@ -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;

View File

@ -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"

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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