mirror of https://github.com/CGAL/cgal
Compare commits
120 Commits
3610981b2c
...
71dcddb981
| Author | SHA1 | Date |
|---|---|---|
|
|
71dcddb981 | |
|
|
dbcace69e6 | |
|
|
bac686d05b | |
|
|
30f63794c3 | |
|
|
d14619c335 | |
|
|
50a187db38 | |
|
|
95a315335f | |
|
|
ff5166fbee | |
|
|
9f2fcb5e28 | |
|
|
85ef57ffa1 | |
|
|
aefbc23955 | |
|
|
da0f634cb2 | |
|
|
7bf5687d5d | |
|
|
1069678f36 | |
|
|
cda931ec46 | |
|
|
e98fa21cc9 | |
|
|
e0a720452d | |
|
|
c856e40662 | |
|
|
ef6f9d8c3c | |
|
|
18e5836373 | |
|
|
3e1a8c110d | |
|
|
5b574bfaae | |
|
|
b804ec9394 | |
|
|
6ec5daa6b9 | |
|
|
e74e5de28a | |
|
|
5c5c48ba16 | |
|
|
9587991deb | |
|
|
b44e132565 | |
|
|
789d4c4f9d | |
|
|
0a6df0877a | |
|
|
1602be1348 | |
|
|
c751ee6bc9 | |
|
|
7e1f685ea3 | |
|
|
f92b41ae0a | |
|
|
e4469c043e | |
|
|
2a5351cc0a | |
|
|
f508d6fe1d | |
|
|
7f4703e248 | |
|
|
e13da7cbd4 | |
|
|
5cc8ec7d71 | |
|
|
b5c3b5f895 | |
|
|
ab9e0ebc8a | |
|
|
6706e0468e | |
|
|
fd21dfb67d | |
|
|
bc42fb4a40 | |
|
|
07e0ea785d | |
|
|
edbc32959d | |
|
|
b068e62ffb | |
|
|
b85035ff87 | |
|
|
c48b4cb6c2 | |
|
|
d34201ed38 | |
|
|
15a155ec30 | |
|
|
e02c1495bf | |
|
|
28d6ac5e49 | |
|
|
7fe0100855 | |
|
|
e7ab5002a3 | |
|
|
940ac3d6e4 | |
|
|
8746a29fa9 | |
|
|
bc770242a5 | |
|
|
61013d5053 | |
|
|
d7faad95dd | |
|
|
bac2c06026 | |
|
|
75c2ac5a68 | |
|
|
b11e42c4a7 | |
|
|
7d9dbdafcd | |
|
|
21df7dad86 | |
|
|
4d3d2f4f03 | |
|
|
626675ea08 | |
|
|
71c2425b6e | |
|
|
c26c013b5a | |
|
|
2bde2295f4 | |
|
|
89393e1b7c | |
|
|
ba10efcbe4 | |
|
|
2a815ff510 | |
|
|
8c150b865c | |
|
|
d309bc89ce | |
|
|
f4aa383177 | |
|
|
2c98528a97 | |
|
|
26130f161d | |
|
|
2d2773e4ed | |
|
|
2e15f13dc4 | |
|
|
93d3356dd9 | |
|
|
389bb11390 | |
|
|
9b3132a2cd | |
|
|
05dd65609d | |
|
|
2e087bc108 | |
|
|
bd6a4ca392 | |
|
|
3988fe2009 | |
|
|
0f2aa39b62 | |
|
|
ba19fbd67d | |
|
|
65c797ab44 | |
|
|
a9e0eeec8f | |
|
|
dc422a7531 | |
|
|
e73cf18c12 | |
|
|
bc29da5ee3 | |
|
|
1d62c37822 | |
|
|
4a6d766d8c | |
|
|
f8c9340c1c | |
|
|
5b6df813f5 | |
|
|
46d0d0799e | |
|
|
b871b81d57 | |
|
|
29715e44a4 | |
|
|
f4a02aeaef | |
|
|
dbcbff15fc | |
|
|
17e3ee7189 | |
|
|
c350da1ac7 | |
|
|
f69ad03ef8 | |
|
|
da2b0edcd1 | |
|
|
a366725c85 | |
|
|
1c45ed834c | |
|
|
375681748d | |
|
|
81bb832333 | |
|
|
a74945062c | |
|
|
e5049d4b03 | |
|
|
1bd923b393 | |
|
|
c677355de2 | |
|
|
0f528545c7 | |
|
|
35721db0b9 | |
|
|
d41efe0330 | |
|
|
bf1bc2fc85 |
|
|
@ -1,35 +1,63 @@
|
|||
---
|
||||
# CGAL clang-format configuration
|
||||
# This file defines the code formatting style for C++ files in the CGAL project.
|
||||
|
||||
Language: Cpp
|
||||
BasedOnStyle: LLVM
|
||||
AccessModifierOffset: -2
|
||||
AllowShortFunctionsOnASingleLine: true
|
||||
BinPackParameters: false
|
||||
BreakConstructorInitializers: BeforeComma
|
||||
|
||||
# Indentation
|
||||
AccessModifierOffset: -2 # Indent public:/private:/protected: 2 spaces to the left
|
||||
|
||||
# Function formatting
|
||||
AllowShortFunctionsOnASingleLine: Inline # Allow short inline/member functions on one line, but not free functions
|
||||
AlwaysBreakAfterReturnType: None # Don't force return type on separate line
|
||||
|
||||
# Parameter and argument formatting
|
||||
BinPackParameters: false # Put each parameter on its own line for better readability
|
||||
|
||||
# Constructor formatting
|
||||
BreakConstructorInitializers: BeforeComma # Put comma before each initializer: `MyClass() \n , member1(val1) \n , member2(val2)`
|
||||
|
||||
# Brace wrapping configuration
|
||||
BreakBeforeBraces: Custom
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: false
|
||||
AfterClass: true
|
||||
AfterControlStatement: MultiLine
|
||||
AfterEnum: false
|
||||
AfterFunction: false
|
||||
AfterNamespace: false
|
||||
AfterObjCDeclaration: false
|
||||
AfterStruct: true
|
||||
AfterUnion: false
|
||||
AfterExternBlock: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
BeforeLambdaBody: false
|
||||
BeforeWhile: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: false
|
||||
SplitEmptyRecord: false
|
||||
SplitEmptyNamespace: false
|
||||
ColumnLimit: 120
|
||||
# Force pointers to the type for C++.
|
||||
AfterCaseLabel: false # Don't put brace on new line after case labels
|
||||
AfterClass: true # Put opening brace on new line after class definition
|
||||
AfterControlStatement: MultiLine # Only break before braces if the control statement spans multiple lines
|
||||
AfterEnum: false # Don't break after enum
|
||||
AfterFunction: false # Don't break after function declaration (keep on same line)
|
||||
AfterNamespace: false # Don't break after namespace
|
||||
AfterObjCDeclaration: false # Objective-C related (not used in CGAL)
|
||||
AfterStruct: true # Put opening brace on new line after struct definition
|
||||
AfterUnion: false # Don't break after union
|
||||
AfterExternBlock: false # Don't break after extern "C" blocks
|
||||
BeforeCatch: false # Don't put catch on new line
|
||||
BeforeElse: false # Don't put else on new line
|
||||
BeforeLambdaBody: false # Don't break before lambda body
|
||||
BeforeWhile: false # Don't put while on new line (do-while loops)
|
||||
IndentBraces: false # Don't indent the braces themselves
|
||||
SplitEmptyFunction: false # Don't split empty functions across lines
|
||||
SplitEmptyRecord: false # Don't split empty classes/structs across lines
|
||||
SplitEmptyNamespace: false # Don't split empty namespaces across lines
|
||||
|
||||
# Line length
|
||||
ColumnLimit: 120 # Maximum line length of 120 characters
|
||||
|
||||
# Pointer and reference alignment
|
||||
# Force pointers and references to align with the type (e.g., `int* ptr` not `int *ptr`)
|
||||
DerivePointerAlignment: false
|
||||
PointerAlignment: Left
|
||||
# Control the spaces around conditionals
|
||||
SpacesInConditionalStatement: false
|
||||
SpaceBeforeParens: false
|
||||
|
||||
# Spacing in control statements
|
||||
SpacesInConditionalStatement: false # No extra spaces inside conditionals: `if(condition)` not `if( condition )`
|
||||
SpaceBeforeParens: false # No space before parentheses: `if(` not `if (`
|
||||
|
||||
# Include directive handling
|
||||
SortIncludes: Never # Preserve the original order of #include statements (don't sort them)
|
||||
|
||||
# Preprocessor directive formatting
|
||||
IndentPPDirectives: None # Don't indent preprocessor directives (#ifdef, #include, etc.)
|
||||
|
||||
# Blank line handling
|
||||
MaxEmptyLinesToKeep: 2 # Keep up to 2 consecutive blank lines
|
||||
...
|
||||
|
|
|
|||
|
|
@ -0,0 +1,236 @@
|
|||
// Copyright (c) 2025 Tel-Aviv University (Israel).
|
||||
// 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): Efi Fogel <efifogel@gmail.com>
|
||||
|
||||
#ifndef CGAL_ARR_DO_INTERSECT_OVERLAY_2_H
|
||||
#define CGAL_ARR_DO_INTERSECT_OVERLAY_2_H
|
||||
|
||||
#include <CGAL/license/Arrangement_on_surface_2.h>
|
||||
|
||||
#include <CGAL/disable_warnings.h>
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* Definition of the global do_intersect_overlay_2() function.
|
||||
*/
|
||||
|
||||
#include <CGAL/Arrangement_on_surface_2.h>
|
||||
#include <CGAL/Surface_sweep_2.h>
|
||||
#include <CGAL/Surface_sweep_2/Arr_default_overlay_traits_base.h>
|
||||
#include <CGAL/Surface_sweep_2/Arr_overlay_traits_2.h>
|
||||
#include <CGAL/Surface_sweep_2/Arr_do_intersect_overlay_ss_visitor.h>
|
||||
#include <CGAL/Surface_sweep_2/Arr_overlay_event.h>
|
||||
#include <CGAL/Surface_sweep_2/Arr_overlay_subcurve.h>
|
||||
#include <CGAL/assertions.h>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
/*! Compute the overlay of two input arrangements.
|
||||
* \tparam GeometryTraitsA_2 the geometry traits of the first arrangement.
|
||||
* \tparam GeometryTraitsB_2 the geometry traits of the second arrangement.
|
||||
* \tparam GeometryTraitsRes_2 the geometry traits of the resulting arrangement.
|
||||
* \tparam TopologyTraitsA the topology traits of the first arrangement.
|
||||
* \tparam TopologyTraitsB the topology traits of the second arrangement.
|
||||
* \tparam TopologyTraitsRes the topology traits of the resulting arrangement.
|
||||
* \tparam OverlayTraits An overlay-traits class. As arr1, arr2 and res can be
|
||||
* templated with different geometry-traits class and
|
||||
* different DCELs (encapsulated in the various topology-traits
|
||||
* classes). The geometry-traits of the result arrangement is
|
||||
* used to construct the result arrangement. This means that all
|
||||
* the types (e.g., Point_2, Curve_2 and X_monotone_2) of both
|
||||
* arr1 and arr2 have to be convertible to the types
|
||||
* in the result geometry-traits.
|
||||
* The overlay-traits class defines the various
|
||||
* overlay operations of pairs of DCEL features from
|
||||
* TopologyTraitsA and TopologyTraitsB to the resulting ResDcel.
|
||||
*/
|
||||
template <typename GeometryTraitsA_2,
|
||||
typename GeometryTraitsB_2,
|
||||
typename GeometryTraitsRes_2,
|
||||
typename TopologyTraitsA,
|
||||
typename TopologyTraitsB,
|
||||
typename TopologyTraitsRes,
|
||||
typename OverlayTraits>
|
||||
bool do_intersect_overlay(const Arrangement_on_surface_2<GeometryTraitsA_2, TopologyTraitsA>& arr1,
|
||||
const Arrangement_on_surface_2<GeometryTraitsB_2, TopologyTraitsB>& arr2,
|
||||
Arrangement_on_surface_2<GeometryTraitsRes_2, TopologyTraitsRes>& arr,
|
||||
OverlayTraits& ovl_tr,
|
||||
bool ignore_isolated_vertices = true) {
|
||||
using Agt2 = GeometryTraitsA_2;
|
||||
using Bgt2 = GeometryTraitsB_2;
|
||||
using Rgt2 = GeometryTraitsRes_2;
|
||||
using Att = TopologyTraitsA;
|
||||
using Btt = TopologyTraitsB;
|
||||
using Rtt = TopologyTraitsRes;
|
||||
using Overlay_traits = OverlayTraits;
|
||||
|
||||
using Arr_a = Arrangement_on_surface_2<Agt2, Att>;
|
||||
using Arr_b = Arrangement_on_surface_2<Bgt2, Btt>;
|
||||
using Arr_res = Arrangement_on_surface_2<Rgt2, Rtt>;
|
||||
using Allocator = typename Arr_res::Allocator;
|
||||
|
||||
// some type assertions (not all, but better than nothing).
|
||||
using A_point = typename Agt2::Point_2;
|
||||
using B_point = typename Bgt2::Point_2;
|
||||
using Res_point = typename Rgt2::Point_2;
|
||||
static_assert(std::is_convertible<A_point, Res_point>::value);
|
||||
static_assert(std::is_convertible<B_point, Res_point>::value);
|
||||
|
||||
using A_xcv = typename Agt2::X_monotone_curve_2;
|
||||
using B_xcv = typename Bgt2::X_monotone_curve_2;
|
||||
using Res_xcv = typename Rgt2::X_monotone_curve_2;
|
||||
static_assert(std::is_convertible<A_xcv, Res_xcv>::value);
|
||||
static_assert(std::is_convertible<B_xcv, Res_xcv>::value);
|
||||
|
||||
using Gt_adaptor_2 = Arr_traits_basic_adaptor_2<Rgt2>;
|
||||
using Ovl_gt2 = Arr_overlay_traits_2<Gt_adaptor_2, Arr_a, Arr_b>;
|
||||
using Ovl_event = Arr_overlay_event<Ovl_gt2, Arr_res, Allocator>;
|
||||
using Ovl_curve = Arr_overlay_subcurve<Ovl_gt2, Ovl_event, Allocator>;
|
||||
using Ovl_helper = typename TopologyTraitsRes::template Overlay_helper<Ovl_gt2, Ovl_event, Ovl_curve, Arr_a, Arr_b>;
|
||||
using Diovl_visitor = Arr_do_intersect_overlay_ss_visitor<Ovl_helper, Overlay_traits>;
|
||||
|
||||
using Ovl_x_monotone_curve_2 = typename Ovl_gt2::X_monotone_curve_2;
|
||||
using Ovl_point_2 = typename Ovl_gt2::Point_2;
|
||||
using Cell_handle_red = typename Ovl_gt2::Cell_handle_red;
|
||||
using Optional_cell_red = typename Ovl_gt2::Optional_cell_red;
|
||||
using Cell_handle_blue = typename Ovl_gt2::Cell_handle_blue;
|
||||
using Optional_cell_blue = typename Ovl_gt2::Optional_cell_blue;
|
||||
|
||||
CGAL_USE_TYPE(Optional_cell_red);
|
||||
CGAL_USE_TYPE(Optional_cell_blue);
|
||||
|
||||
// The result arrangement cannot be on of the input arrangements.
|
||||
CGAL_precondition(((void*)(&arr) != (void*)(&arr1)) && ((void*)(&arr) != (void*)(&arr2)));
|
||||
|
||||
// Prepare a vector of extended x-monotone curves that represent all edges
|
||||
// in both input arrangements. Each curve is associated with a halfedge
|
||||
// directed from right to left.
|
||||
typename Arr_a::Halfedge_const_handle invalid_he1;
|
||||
typename Arr_b::Halfedge_const_handle invalid_he2;
|
||||
std::vector<Ovl_x_monotone_curve_2> xcvs(arr1.number_of_edges() + arr2.number_of_edges());
|
||||
std::size_t i = 0;
|
||||
|
||||
for (auto eit1 = arr1.edges_begin(); eit1 != arr1.edges_end(); ++eit1, ++i) {
|
||||
typename Arr_a::Halfedge_const_handle he1 = eit1;
|
||||
if (he1->direction() != ARR_RIGHT_TO_LEFT) he1 = he1->twin();
|
||||
xcvs[i] = Ovl_x_monotone_curve_2(eit1->curve(), he1, invalid_he2);
|
||||
}
|
||||
|
||||
for (auto eit2 = arr2.edges_begin(); eit2 != arr2.edges_end(); ++eit2, ++i) {
|
||||
typename Arr_b::Halfedge_const_handle he2 = eit2;
|
||||
if (he2->direction() != ARR_RIGHT_TO_LEFT) he2 = he2->twin();
|
||||
xcvs[i] = Ovl_x_monotone_curve_2(eit2->curve(), invalid_he1, he2);
|
||||
}
|
||||
|
||||
// Obtain an extended traits-class object and define the sweep-line visitor.
|
||||
const typename Arr_res::Traits_adaptor_2* traits_adaptor = arr.traits_adaptor();
|
||||
|
||||
/* We would like to avoid copy construction of the geometry traits class.
|
||||
* Copy construction is undesired, because it may results with data
|
||||
* duplication or even data loss.
|
||||
*
|
||||
* If the type Ovl_gt2 is the same as the type
|
||||
* GeomTraits, use a reference to GeomTraits to avoid constructing a new one.
|
||||
* Otherwise, instantiate a local variable of the former and provide
|
||||
* the latter as a single parameter to the constructor.
|
||||
*
|
||||
* Use the form 'A a(*b);' and not ''A a = b;' to handle the case where A has
|
||||
* only an implicit constructor, (which takes *b as a parameter).
|
||||
*/
|
||||
std::conditional_t<std::is_same_v<Gt_adaptor_2, Ovl_gt2>, const Ovl_gt2&, Ovl_gt2> ex_traits(*traits_adaptor);
|
||||
|
||||
Diovl_visitor visitor(&arr1, &arr2, &arr, &ovl_tr);
|
||||
Ss2::Surface_sweep_2<Diovl_visitor> surface_sweep(&ex_traits, &visitor);
|
||||
|
||||
// In case both arrangement do not contain isolated vertices, go on and overlay them.
|
||||
if (ignore_isolated_vertices ||
|
||||
((arr1.number_of_isolated_vertices() == 0) && (arr2.number_of_isolated_vertices() == 0))) {
|
||||
// Clear the result arrangement and perform the sweep to construct it.
|
||||
arr.clear();
|
||||
if (std::is_same<typename Agt2::Bottom_side_category, Arr_contracted_side_tag>::value) {
|
||||
surface_sweep.sweep(xcvs.begin(), xcvs.end());
|
||||
xcvs.clear();
|
||||
return visitor.found_intersection();
|
||||
}
|
||||
surface_sweep.indexed_sweep(xcvs, Indexed_sweep_accessor<Arr_a, Arr_b, Ovl_x_monotone_curve_2>(arr1, arr2));
|
||||
xcvs.clear();
|
||||
return visitor.found_intersection();
|
||||
}
|
||||
|
||||
// Prepare a vector of extended points that represent all isolated vertices
|
||||
// in both input arrangements.
|
||||
std::vector<Ovl_point_2> pts_vec(arr1.number_of_isolated_vertices() + arr2.number_of_isolated_vertices());
|
||||
|
||||
i = 0;
|
||||
for (auto vit1 = arr1.vertices_begin(); vit1 != arr1.vertices_end(); ++vit1) {
|
||||
if (vit1->is_isolated()) {
|
||||
typename Arr_a::Vertex_const_handle v1 = vit1;
|
||||
pts_vec[i++] = Ovl_point_2(vit1->point(), std::make_optional(Cell_handle_red(v1)),
|
||||
std::optional<Cell_handle_blue>());
|
||||
}
|
||||
}
|
||||
|
||||
for (auto vit2 = arr2.vertices_begin(); vit2 != arr2.vertices_end(); ++vit2) {
|
||||
if (vit2->is_isolated()) {
|
||||
typename Arr_b::Vertex_const_handle v2 = vit2;
|
||||
pts_vec[i++] = Ovl_point_2(vit2->point(), std::optional<Cell_handle_red>(),
|
||||
std::make_optional(Cell_handle_blue(v2)));
|
||||
}
|
||||
}
|
||||
|
||||
// Clear the result arrangement and perform the sweep to construct it.
|
||||
arr.clear();
|
||||
if (std::is_same<typename Agt2::Bottom_side_category, Arr_contracted_side_tag>::value) {
|
||||
surface_sweep.sweep(xcvs.begin(), xcvs.end(), pts_vec.begin(), pts_vec.end());
|
||||
xcvs.clear();
|
||||
pts_vec.clear();
|
||||
return visitor.found_intersection();
|
||||
}
|
||||
surface_sweep.indexed_sweep(xcvs, Indexed_sweep_accessor<Arr_a, Arr_b, Ovl_x_monotone_curve_2>(arr1, arr2),
|
||||
pts_vec.begin(), pts_vec.end());
|
||||
xcvs.clear();
|
||||
pts_vec.clear();
|
||||
return visitor.found_intersection();
|
||||
}
|
||||
|
||||
/*! Compute the (simple) overlay of two input arrangements.
|
||||
* \param[in] arr1 the first arrangement.
|
||||
* \param[in] arr2 the second arrangement.
|
||||
* \param[out] arr the resulting arrangement.
|
||||
*/
|
||||
template <typename GeometryTraitsA_2,
|
||||
typename GeometryTraitsB_2,
|
||||
typename GeometryTraitsRes_2,
|
||||
typename TopologyTraitsA,
|
||||
typename TopologyTraitsB,
|
||||
typename TopologyTraitsRes>
|
||||
bool do_intersect_overlay(const Arrangement_on_surface_2<GeometryTraitsA_2, TopologyTraitsA>& arr1,
|
||||
const Arrangement_on_surface_2<GeometryTraitsB_2, TopologyTraitsB>& arr2,
|
||||
Arrangement_on_surface_2<GeometryTraitsRes_2, TopologyTraitsRes>& arr) {
|
||||
using Agt2 = GeometryTraitsA_2;
|
||||
using Bgt2 = GeometryTraitsB_2;
|
||||
using Rgt2 = GeometryTraitsRes_2;
|
||||
using Att = TopologyTraitsA;
|
||||
using Btt = TopologyTraitsB;
|
||||
using Rtt = TopologyTraitsRes;
|
||||
using Arr_a = Arrangement_on_surface_2<Agt2, Att>;
|
||||
using Arr_b = Arrangement_on_surface_2<Bgt2, Btt>;
|
||||
using Arr_res = Arrangement_on_surface_2<Rgt2, Rtt>;
|
||||
|
||||
_Arr_default_overlay_traits_base<Arr_a, Arr_b, Arr_res> ovl_traits;
|
||||
return do_intersect_overlay(arr1, arr2, arr, ovl_traits);
|
||||
}
|
||||
|
||||
} // namespace CGAL
|
||||
|
||||
#include <CGAL/enable_warnings.h>
|
||||
|
||||
#endif
|
||||
|
|
@ -8,8 +8,8 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
//
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Efi Fogel <efifogel@gmail.com>
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Efi Fogel <efifogel@gmail.com>
|
||||
|
||||
#ifndef CGAL_ARR_OVERLAY_2_H
|
||||
#define CGAL_ARR_OVERLAY_2_H
|
||||
|
|
@ -40,24 +40,18 @@
|
|||
namespace CGAL {
|
||||
|
||||
template <typename Arr1, typename Arr2, typename Curve>
|
||||
class Indexed_sweep_accessor
|
||||
{
|
||||
const Arr1& arr1;
|
||||
const Arr2& arr2;
|
||||
mutable std::vector<void*> backup_inc;
|
||||
class Indexed_sweep_accessor {
|
||||
private:
|
||||
const Arr1& m_arr1;
|
||||
const Arr2& m_arr2;
|
||||
mutable std::vector<void*> m_backup_inc;
|
||||
|
||||
public:
|
||||
Indexed_sweep_accessor(const Arr1& arr1, const Arr2& arr2) : m_arr1(arr1), m_arr2(arr2) {}
|
||||
|
||||
Indexed_sweep_accessor (const Arr1& arr1, const Arr2& arr2)
|
||||
: arr1(arr1), arr2(arr2) { }
|
||||
std::size_t nb_vertices() const { return m_arr1.number_of_vertices() + m_arr2.number_of_vertices(); }
|
||||
|
||||
std::size_t nb_vertices() const
|
||||
{
|
||||
return arr1.number_of_vertices() + arr2.number_of_vertices();
|
||||
}
|
||||
|
||||
std::size_t min_end_index (const Curve& c) const
|
||||
{
|
||||
std::size_t min_end_index(const Curve& c) const {
|
||||
if (c.red_halfedge_handle() != typename Curve::HH_red())
|
||||
return reinterpret_cast<std::size_t>(c.red_halfedge_handle()->target()->inc());
|
||||
// else
|
||||
|
|
@ -65,8 +59,7 @@ public:
|
|||
return reinterpret_cast<std::size_t>(c.blue_halfedge_handle()->target()->inc());
|
||||
}
|
||||
|
||||
std::size_t max_end_index (const Curve& c) const
|
||||
{
|
||||
std::size_t max_end_index(const Curve& c) const {
|
||||
if (c.red_halfedge_handle() != typename Curve::HH_red())
|
||||
return reinterpret_cast<std::size_t>(c.red_halfedge_handle()->source()->inc());
|
||||
// else
|
||||
|
|
@ -74,52 +67,36 @@ public:
|
|||
return reinterpret_cast<std::size_t>(c.blue_halfedge_handle()->source()->inc());
|
||||
}
|
||||
|
||||
const Curve& curve (const Curve& c) const
|
||||
{
|
||||
return c;
|
||||
}
|
||||
const Curve& curve(const Curve& c) const { return c; }
|
||||
|
||||
// Initializes indices by squatting Vertex::inc();
|
||||
void before_init() const
|
||||
{
|
||||
void before_init() const {
|
||||
std::size_t idx = 0;
|
||||
backup_inc.resize (nb_vertices());
|
||||
for (typename Arr1::Vertex_const_iterator vit = arr1.vertices_begin();
|
||||
vit != arr1.vertices_end(); ++vit, ++idx)
|
||||
{
|
||||
CGAL_assertion (idx < backup_inc.size());
|
||||
backup_inc[idx] = vit->inc();
|
||||
vit->set_inc (reinterpret_cast<void*>(idx));
|
||||
m_backup_inc.resize (nb_vertices());
|
||||
for (auto vit = m_arr1.vertices_begin(); vit != m_arr1.vertices_end(); ++vit, ++idx) {
|
||||
CGAL_assertion(idx < m_backup_inc.size());
|
||||
m_backup_inc[idx] = vit->inc();
|
||||
vit->set_inc(reinterpret_cast<void*>(idx));
|
||||
}
|
||||
for (typename Arr2::Vertex_const_iterator vit = arr2.vertices_begin();
|
||||
vit != arr2.vertices_end(); ++vit, ++idx)
|
||||
{
|
||||
CGAL_assertion (idx < backup_inc.size());
|
||||
backup_inc[idx] = vit->inc();
|
||||
vit->set_inc (reinterpret_cast<void*>(idx));
|
||||
for (auto vit = m_arr2.vertices_begin(); vit != m_arr2.vertices_end(); ++vit, ++idx) {
|
||||
CGAL_assertion(idx < m_backup_inc.size());
|
||||
m_backup_inc[idx] = vit->inc();
|
||||
vit->set_inc(reinterpret_cast<void*>(idx));
|
||||
}
|
||||
}
|
||||
|
||||
// Restores state of arrangements before index squatting
|
||||
void after_init() const
|
||||
{
|
||||
void after_init() const {
|
||||
std::size_t idx = 0;
|
||||
for (typename Arr1::Vertex_const_iterator vit = arr1.vertices_begin();
|
||||
vit != arr1.vertices_end(); ++vit, ++idx)
|
||||
{
|
||||
CGAL_assertion (idx < backup_inc.size());
|
||||
vit->set_inc (backup_inc[idx]);
|
||||
for (auto vit = m_arr1.vertices_begin(); vit != m_arr1.vertices_end(); ++vit, ++idx) {
|
||||
CGAL_assertion(idx < m_backup_inc.size());
|
||||
vit->set_inc(m_backup_inc[idx]);
|
||||
}
|
||||
for (typename Arr2::Vertex_const_iterator vit = arr2.vertices_begin();
|
||||
vit != arr2.vertices_end(); ++vit, ++idx)
|
||||
{
|
||||
CGAL_assertion (idx < backup_inc.size());
|
||||
vit->set_inc (backup_inc[idx]);
|
||||
for (auto vit = m_arr2.vertices_begin(); vit != m_arr2.vertices_end(); ++vit, ++idx) {
|
||||
CGAL_assertion(idx < m_backup_inc.size());
|
||||
vit->set_inc(m_backup_inc[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
/*! Compute the overlay of two input arrangements.
|
||||
|
|
@ -148,64 +125,55 @@ template <typename GeometryTraitsA_2,
|
|||
typename TopologyTraitsB,
|
||||
typename TopologyTraitsRes,
|
||||
typename OverlayTraits>
|
||||
void
|
||||
overlay(const Arrangement_on_surface_2<GeometryTraitsA_2, TopologyTraitsA>& arr1,
|
||||
const Arrangement_on_surface_2<GeometryTraitsB_2, TopologyTraitsB>& arr2,
|
||||
Arrangement_on_surface_2<GeometryTraitsRes_2, TopologyTraitsRes>& arr,
|
||||
OverlayTraits& ovl_tr)
|
||||
{
|
||||
typedef GeometryTraitsA_2 Agt2;
|
||||
typedef GeometryTraitsB_2 Bgt2;
|
||||
typedef GeometryTraitsRes_2 Rgt2;
|
||||
typedef TopologyTraitsA Att;
|
||||
typedef TopologyTraitsB Btt;
|
||||
typedef TopologyTraitsRes Rtt;
|
||||
typedef OverlayTraits Overlay_traits;
|
||||
void overlay(const Arrangement_on_surface_2<GeometryTraitsA_2, TopologyTraitsA>& arr1,
|
||||
const Arrangement_on_surface_2<GeometryTraitsB_2, TopologyTraitsB>& arr2,
|
||||
Arrangement_on_surface_2<GeometryTraitsRes_2, TopologyTraitsRes>& arr,
|
||||
OverlayTraits& ovl_tr) {
|
||||
using Agt2 = GeometryTraitsA_2;
|
||||
using Bgt2 = GeometryTraitsB_2;
|
||||
using Rgt2 = GeometryTraitsRes_2;
|
||||
using Att = TopologyTraitsA;
|
||||
using Btt = TopologyTraitsB;
|
||||
using Rtt = TopologyTraitsRes;
|
||||
using Overlay_traits = OverlayTraits;
|
||||
|
||||
typedef Arrangement_on_surface_2<Agt2, Att> Arr_a;
|
||||
typedef Arrangement_on_surface_2<Bgt2, Btt> Arr_b;
|
||||
typedef Arrangement_on_surface_2<Rgt2, Rtt> Arr_res;
|
||||
typedef typename Arr_res::Allocator Allocator;
|
||||
using Arr_a = Arrangement_on_surface_2<Agt2, Att>;
|
||||
using Arr_b = Arrangement_on_surface_2<Bgt2, Btt>;
|
||||
using Arr_res = Arrangement_on_surface_2<Rgt2, Rtt>;
|
||||
using Allocator = typename Arr_res::Allocator;
|
||||
|
||||
// some type assertions (not all, but better than nothing).
|
||||
typedef typename Agt2::Point_2 A_point;
|
||||
typedef typename Bgt2::Point_2 B_point;
|
||||
typedef typename Rgt2::Point_2 Res_point;
|
||||
using A_point = typename Agt2::Point_2;
|
||||
using B_point = typename Bgt2::Point_2;
|
||||
using Res_point = typename Rgt2::Point_2;
|
||||
static_assert(std::is_convertible<A_point, Res_point>::value);
|
||||
static_assert(std::is_convertible<B_point, Res_point>::value);
|
||||
|
||||
typedef typename Agt2::X_monotone_curve_2 A_xcv;
|
||||
typedef typename Bgt2::X_monotone_curve_2 B_xcv;
|
||||
typedef typename Rgt2::X_monotone_curve_2 Res_xcv;
|
||||
using A_xcv = typename Agt2::X_monotone_curve_2;
|
||||
using B_xcv = typename Bgt2::X_monotone_curve_2;
|
||||
using Res_xcv = typename Rgt2::X_monotone_curve_2;
|
||||
static_assert(std::is_convertible<A_xcv, Res_xcv>::value);
|
||||
static_assert(std::is_convertible<B_xcv, Res_xcv>::value);
|
||||
|
||||
typedef Arr_traits_basic_adaptor_2<Rgt2> Gt_adaptor_2;
|
||||
typedef Arr_overlay_traits_2<Gt_adaptor_2, Arr_a, Arr_b>
|
||||
Ovl_gt2;
|
||||
typedef Arr_overlay_event<Ovl_gt2, Arr_res, Allocator>
|
||||
Ovl_event;
|
||||
typedef Arr_overlay_subcurve<Ovl_gt2, Ovl_event, Allocator>
|
||||
Ovl_curve;
|
||||
typedef typename TopologyTraitsRes::template
|
||||
Overlay_helper<Ovl_gt2, Ovl_event, Ovl_curve, Arr_a, Arr_b>
|
||||
Ovl_helper;
|
||||
typedef Arr_overlay_ss_visitor<Ovl_helper, Overlay_traits>
|
||||
Ovl_visitor;
|
||||
using Gt_adaptor_2 = Arr_traits_basic_adaptor_2<Rgt2>;
|
||||
using Ovl_gt2 = Arr_overlay_traits_2<Gt_adaptor_2, Arr_a, Arr_b>;
|
||||
using Ovl_event = Arr_overlay_event<Ovl_gt2, Arr_res, Allocator>;
|
||||
using Ovl_curve = Arr_overlay_subcurve<Ovl_gt2, Ovl_event, Allocator>;
|
||||
using Ovl_helper = typename TopologyTraitsRes::template Overlay_helper<Ovl_gt2, Ovl_event, Ovl_curve, Arr_a, Arr_b>;
|
||||
using Ovl_visitor = Arr_overlay_ss_visitor<Ovl_helper, Overlay_traits>;
|
||||
|
||||
typedef typename Ovl_gt2::X_monotone_curve_2 Ovl_x_monotone_curve_2;
|
||||
typedef typename Ovl_gt2::Point_2 Ovl_point_2;
|
||||
typedef typename Ovl_gt2::Cell_handle_red Cell_handle_red;
|
||||
typedef typename Ovl_gt2::Optional_cell_red Optional_cell_red;
|
||||
typedef typename Ovl_gt2::Cell_handle_blue Cell_handle_blue;
|
||||
typedef typename Ovl_gt2::Optional_cell_blue Optional_cell_blue;
|
||||
using Ovl_x_monotone_curve_2 = typename Ovl_gt2::X_monotone_curve_2;
|
||||
using Ovl_point_2 = typename Ovl_gt2::Point_2;
|
||||
using Cell_handle_red = typename Ovl_gt2::Cell_handle_red;
|
||||
using Optional_cell_red = typename Ovl_gt2::Optional_cell_red;
|
||||
using Cell_handle_blue = typename Ovl_gt2::Cell_handle_blue;
|
||||
using Optional_cell_blue = typename Ovl_gt2::Optional_cell_blue;
|
||||
|
||||
CGAL_USE_TYPE(Optional_cell_red);
|
||||
CGAL_USE_TYPE(Optional_cell_blue);
|
||||
|
||||
// The result arrangement cannot be on of the input arrangements.
|
||||
CGAL_precondition(((void*)(&arr) != (void*)(&arr1)) &&
|
||||
((void*)(&arr) != (void*)(&arr2)));
|
||||
CGAL_precondition(((void*)(&arr) != (void*)(&arr1)) && ((void*)(&arr) != (void*)(&arr2)));
|
||||
|
||||
// Prepare a vector of extended x-monotone curves that represent all edges
|
||||
// in both input arrangements. Each curve is associated with a halfedge
|
||||
|
|
@ -216,23 +184,20 @@ overlay(const Arrangement_on_surface_2<GeometryTraitsA_2, TopologyTraitsA>& arr1
|
|||
xcvs_vec(arr1.number_of_edges() + arr2.number_of_edges());
|
||||
unsigned int i = 0;
|
||||
|
||||
typename Arr_a::Edge_const_iterator eit1;
|
||||
for (eit1 = arr1.edges_begin(); eit1 != arr1.edges_end(); ++eit1, ++i) {
|
||||
for (auto eit1 = arr1.edges_begin(); eit1 != arr1.edges_end(); ++eit1, ++i) {
|
||||
typename Arr_a::Halfedge_const_handle he1 = eit1;
|
||||
if (he1->direction() != ARR_RIGHT_TO_LEFT) he1 = he1->twin();
|
||||
xcvs_vec[i] = Ovl_x_monotone_curve_2(eit1->curve(), he1, invalid_he2);
|
||||
}
|
||||
|
||||
typename Arr_b::Edge_const_iterator eit2;
|
||||
for (eit2 = arr2.edges_begin(); eit2 != arr2.edges_end(); ++eit2, ++i) {
|
||||
for (auto eit2 = arr2.edges_begin(); eit2 != arr2.edges_end(); ++eit2, ++i) {
|
||||
typename Arr_b::Halfedge_const_handle he2 = eit2;
|
||||
if (he2->direction() != ARR_RIGHT_TO_LEFT) he2 = he2->twin();
|
||||
xcvs_vec[i] = Ovl_x_monotone_curve_2(eit2->curve(), invalid_he1, he2);
|
||||
}
|
||||
|
||||
// Obtain an extended traits-class object and define the sweep-line visitor.
|
||||
const typename Arr_res::Traits_adaptor_2* traits_adaptor =
|
||||
arr.traits_adaptor();
|
||||
const typename Arr_res::Traits_adaptor_2* traits_adaptor = arr.traits_adaptor();
|
||||
|
||||
/* We would like to avoid copy construction of the geometry traits class.
|
||||
* Copy construction is undesired, because it may results with data
|
||||
|
|
@ -246,29 +211,22 @@ overlay(const Arrangement_on_surface_2<GeometryTraitsA_2, TopologyTraitsA>& arr1
|
|||
* Use the form 'A a(*b);' and not ''A a = b;' to handle the case where A has
|
||||
* only an implicit constructor, (which takes *b as a parameter).
|
||||
*/
|
||||
std::conditional_t<std::is_same_v<Gt_adaptor_2, Ovl_gt2>,
|
||||
const Ovl_gt2&, Ovl_gt2>
|
||||
ex_traits(*traits_adaptor);
|
||||
std::conditional_t<std::is_same_v<Gt_adaptor_2, Ovl_gt2>, const Ovl_gt2&, Ovl_gt2> ex_traits(*traits_adaptor);
|
||||
|
||||
Ovl_visitor visitor(&arr1, &arr2, &arr, &ovl_tr);
|
||||
Ss2::Surface_sweep_2<Ovl_visitor> surface_sweep(&ex_traits, &visitor);
|
||||
|
||||
// In case both arrangement do not contain isolated vertices, go on and
|
||||
// overlay them.
|
||||
const std::size_t total_iso_verts =
|
||||
arr1.number_of_isolated_vertices() + arr2.number_of_isolated_vertices();
|
||||
const std::size_t total_iso_verts = arr1.number_of_isolated_vertices() + arr2.number_of_isolated_vertices();
|
||||
|
||||
if (total_iso_verts == 0) {
|
||||
// Clear the result arrangement and perform the sweep to construct it.
|
||||
arr.clear();
|
||||
if (std::is_same<typename Agt2::Bottom_side_category,
|
||||
Arr_contracted_side_tag>::value)
|
||||
surface_sweep.sweep (xcvs_vec.begin(), xcvs_vec.end());
|
||||
if (std::is_same<typename Agt2::Bottom_side_category, Arr_contracted_side_tag>::value)
|
||||
surface_sweep.sweep(xcvs_vec.begin(), xcvs_vec.end());
|
||||
else
|
||||
surface_sweep.indexed_sweep (xcvs_vec,
|
||||
Indexed_sweep_accessor
|
||||
<Arr_a, Arr_b, Ovl_x_monotone_curve_2>
|
||||
(arr1, arr2));
|
||||
surface_sweep.indexed_sweep(xcvs_vec, Indexed_sweep_accessor<Arr_a, Arr_b, Ovl_x_monotone_curve_2>(arr1, arr2));
|
||||
xcvs_vec.clear();
|
||||
return;
|
||||
}
|
||||
|
|
@ -278,38 +236,29 @@ overlay(const Arrangement_on_surface_2<GeometryTraitsA_2, TopologyTraitsA>& arr1
|
|||
std::vector<Ovl_point_2> pts_vec(total_iso_verts);
|
||||
|
||||
i = 0;
|
||||
typename Arr_a::Vertex_const_iterator vit1;
|
||||
for (vit1 = arr1.vertices_begin(); vit1 != arr1.vertices_end(); ++vit1) {
|
||||
for (auto vit1 = arr1.vertices_begin(); vit1 != arr1.vertices_end(); ++vit1) {
|
||||
if (vit1->is_isolated()) {
|
||||
typename Arr_a::Vertex_const_handle v1 = vit1;
|
||||
pts_vec[i++] =
|
||||
Ovl_point_2(vit1->point(), std::make_optional(Cell_handle_red(v1)),
|
||||
std::optional<Cell_handle_blue>());
|
||||
pts_vec[i++] = Ovl_point_2(vit1->point(), std::make_optional(Cell_handle_red(v1)),
|
||||
std::optional<Cell_handle_blue>());
|
||||
}
|
||||
}
|
||||
|
||||
typename Arr_b::Vertex_const_iterator vit2;
|
||||
for (vit2 = arr2.vertices_begin(); vit2 != arr2.vertices_end(); ++vit2) {
|
||||
for (auto vit2 = arr2.vertices_begin(); vit2 != arr2.vertices_end(); ++vit2) {
|
||||
if (vit2->is_isolated()) {
|
||||
typename Arr_b::Vertex_const_handle v2 = vit2;
|
||||
pts_vec[i++] =
|
||||
Ovl_point_2(vit2->point(), std::optional<Cell_handle_red>(),
|
||||
std::make_optional(Cell_handle_blue(v2)));
|
||||
pts_vec[i++] = Ovl_point_2(vit2->point(), std::optional<Cell_handle_red>(),
|
||||
std::make_optional(Cell_handle_blue(v2)));
|
||||
}
|
||||
}
|
||||
|
||||
// Clear the result arrangement and perform the sweep to construct it.
|
||||
arr.clear();
|
||||
if (std::is_same<typename Agt2::Bottom_side_category,
|
||||
Arr_contracted_side_tag>::value)
|
||||
surface_sweep.sweep(xcvs_vec.begin(), xcvs_vec.end(),
|
||||
pts_vec.begin(), pts_vec.end());
|
||||
if (std::is_same<typename Agt2::Bottom_side_category, Arr_contracted_side_tag>::value)
|
||||
surface_sweep.sweep(xcvs_vec.begin(), xcvs_vec.end(), pts_vec.begin(), pts_vec.end());
|
||||
else
|
||||
surface_sweep.indexed_sweep (xcvs_vec,
|
||||
Indexed_sweep_accessor
|
||||
<Arr_a, Arr_b, Ovl_x_monotone_curve_2>
|
||||
(arr1, arr2),
|
||||
pts_vec.begin(), pts_vec.end());
|
||||
surface_sweep.indexed_sweep(xcvs_vec, Indexed_sweep_accessor<Arr_a, Arr_b, Ovl_x_monotone_curve_2>(arr1, arr2),
|
||||
pts_vec.begin(), pts_vec.end());
|
||||
xcvs_vec.clear();
|
||||
pts_vec.clear();
|
||||
}
|
||||
|
|
@ -325,20 +274,18 @@ template <typename GeometryTraitsA_2,
|
|||
typename TopologyTraitsA,
|
||||
typename TopologyTraitsB,
|
||||
typename TopologyTraitsRes>
|
||||
void
|
||||
overlay(const Arrangement_on_surface_2<GeometryTraitsA_2, TopologyTraitsA>& arr1,
|
||||
const Arrangement_on_surface_2<GeometryTraitsB_2, TopologyTraitsB>& arr2,
|
||||
Arrangement_on_surface_2<GeometryTraitsRes_2, TopologyTraitsRes>& arr)
|
||||
{
|
||||
typedef GeometryTraitsA_2 Agt2;
|
||||
typedef GeometryTraitsB_2 Bgt2;
|
||||
typedef GeometryTraitsRes_2 Rgt2;
|
||||
typedef TopologyTraitsA Att;
|
||||
typedef TopologyTraitsB Btt;
|
||||
typedef TopologyTraitsRes Rtt;
|
||||
typedef Arrangement_on_surface_2<Agt2, Att> Arr_a;
|
||||
typedef Arrangement_on_surface_2<Bgt2, Btt> Arr_b;
|
||||
typedef Arrangement_on_surface_2<Rgt2, Rtt> Arr_res;
|
||||
void overlay(const Arrangement_on_surface_2<GeometryTraitsA_2, TopologyTraitsA>& arr1,
|
||||
const Arrangement_on_surface_2<GeometryTraitsB_2, TopologyTraitsB>& arr2,
|
||||
Arrangement_on_surface_2<GeometryTraitsRes_2, TopologyTraitsRes>& arr) {
|
||||
using Agt2 = GeometryTraitsA_2;
|
||||
using Bgt2 = GeometryTraitsB_2;
|
||||
using Rgt2 = GeometryTraitsRes_2;
|
||||
using Att = TopologyTraitsA;
|
||||
using Btt = TopologyTraitsB;
|
||||
using Rtt = TopologyTraitsRes;
|
||||
using Arr_a = Arrangement_on_surface_2<Agt2, Att>;
|
||||
using Arr_b = Arrangement_on_surface_2<Bgt2, Btt>;
|
||||
using Arr_res = Arrangement_on_surface_2<Rgt2, Rtt>;
|
||||
|
||||
_Arr_default_overlay_traits_base<Arr_a, Arr_b, Arr_res> ovl_traits;
|
||||
overlay(arr1, arr2, arr, ovl_traits);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,110 @@
|
|||
// Copyright (c) 2006,2007,2009,2010,2011,2025 Tel-Aviv University (Israel).
|
||||
// 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) : Efi Fogel <efif@post.tau.ac.il>
|
||||
|
||||
#ifndef CGAL_DO_INTERSECT_ARR_OVERLAY_SS_VISITOR_H
|
||||
#define CGAL_DO_INTERSECT_ARR_OVERLAY_SS_VISITOR_H
|
||||
|
||||
#include <CGAL/license/Arrangement_on_surface_2.h>
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* Definition of the Arr_do_intersect_overlay_ss_visitor class-template.
|
||||
*/
|
||||
|
||||
#include <CGAL/Default.h>
|
||||
#include <CGAL/Surface_sweep_2/Arr_overlay_ss_visitor.h>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
/*! \class Arr_do_intersect_overlay_ss_visitor
|
||||
*
|
||||
* A sweep-line visitor for overlaying a "red" arrangement and a "blue"
|
||||
* arrangement as long as the edges do not intersect in their interiors. If
|
||||
* there are no intersections, the overlay arrangement is constructed. All three
|
||||
* arrangements are embedded on the same type of surface and use the same
|
||||
* geometry traits. Otherwise, the process is terminated without any delay (that
|
||||
* is, once an intersection is detected).
|
||||
*/
|
||||
template <typename OverlayHelper, typename OverlayTraits, typename Visitor_ = Default>
|
||||
class Arr_do_intersect_overlay_ss_visitor :
|
||||
public Arr_overlay_ss_visitor<
|
||||
OverlayHelper, OverlayTraits,
|
||||
typename Default::Get<Visitor_,
|
||||
Arr_do_intersect_overlay_ss_visitor<OverlayHelper, OverlayTraits, Visitor_> >::type> {
|
||||
private:
|
||||
using Overlay_helper = OverlayHelper;
|
||||
using Overlay_traits = OverlayTraits;
|
||||
|
||||
using Self = Arr_do_intersect_overlay_ss_visitor<Overlay_helper, Overlay_traits, Visitor_>;
|
||||
using Visitor = typename Default::Get<Visitor_, Self>::type;
|
||||
using Base = Arr_overlay_ss_visitor<Overlay_helper, Overlay_traits, Visitor>;
|
||||
|
||||
protected:
|
||||
bool m_found_x;
|
||||
|
||||
public:
|
||||
using Arrangement_red_2 = typename Base::Arrangement_red_2;
|
||||
using Arrangement_blue_2 = typename Base::Arrangement_blue_2;
|
||||
using Arrangement_2 = typename Base::Arrangement_2;
|
||||
using Event = typename Base::Event;
|
||||
using Subcurve = typename Base::Subcurve;
|
||||
using Status_line_iterator = typename Base::Status_line_iterator;
|
||||
using X_monotone_curve_2 = typename Base::X_monotone_curve_2;
|
||||
using Point_2 = typename Base::Point_2;
|
||||
using Multiplicity = typename Base::Multiplicity;
|
||||
|
||||
/*! Constructor */
|
||||
Arr_do_intersect_overlay_ss_visitor(const Arrangement_red_2* red_arr,
|
||||
const Arrangement_blue_2* blue_arr,
|
||||
Arrangement_2* res_arr,
|
||||
Overlay_traits* overlay_traits) :
|
||||
Base(red_arr, blue_arr, res_arr, overlay_traits),
|
||||
m_found_x(false)
|
||||
{}
|
||||
|
||||
/*! Destructor */
|
||||
virtual ~Arr_do_intersect_overlay_ss_visitor() {}
|
||||
|
||||
/*! Update an event that corresponds to a curve endpoint. */
|
||||
void update_event(Event* e, const Point_2& end_point, const X_monotone_curve_2& cv, Arr_curve_end cv_end, bool is_new)
|
||||
{ return Base::update_event(e, end_point, cv, cv_end, is_new); }
|
||||
|
||||
/*! Update an event that corresponds to a curve endpoint */
|
||||
void update_event(Event* e, const X_monotone_curve_2& cv, Arr_curve_end cv_end, bool is_new )
|
||||
{ return Base::update_event(e, cv, cv_end, is_new); }
|
||||
|
||||
/*! Update an event that corresponds to a curve endpoint */
|
||||
void update_event(Event* e, const Point_2& p, bool is_new)
|
||||
{ return Base::update_event(e, p, is_new); }
|
||||
|
||||
/*! Update an event that corresponds to an intersection */
|
||||
void update_event(Event* e, Subcurve* sc) { return Base::update_event(e, sc); }
|
||||
|
||||
/*! Update an event that corresponds to an intersection between curves */
|
||||
void update_event(Event* e, Subcurve* sc1, Subcurve* sc2, bool is_new, Multiplicity multiplicity) {
|
||||
if ((multiplicity % 2) == 1) m_found_x = true;
|
||||
Base::update_event(e, sc1, sc2, is_new, multiplicity);
|
||||
}
|
||||
|
||||
bool after_handle_event(Event* e, Status_line_iterator iter, bool flag) {
|
||||
auto res = Base::after_handle_event(e, iter, flag);
|
||||
if (m_found_x) this->surface_sweep()->stop_sweep();
|
||||
return res;
|
||||
}
|
||||
|
||||
/*! Getter */
|
||||
bool found_intersection() { return m_found_x; }
|
||||
};
|
||||
|
||||
} // namespace CGAL
|
||||
|
||||
#endif
|
||||
|
|
@ -8,9 +8,9 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
//
|
||||
// Author(s): Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ron Wein <wein@post.tau.ac.il>
|
||||
// Efi Fogel <efif@post.tau.ac.il>
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ron Wein <wein@post.tau.ac.il>
|
||||
// Efi Fogel <efif@post.tau.ac.il>
|
||||
|
||||
#ifndef CGAL_ARR_NO_INTERSECTION_INSERTION_SS_VISITOR_H
|
||||
#define CGAL_ARR_NO_INTERSECTION_INSERTION_SS_VISITOR_H
|
||||
|
|
@ -42,35 +42,33 @@ class Arr_no_intersection_insertion_ss_visitor :
|
|||
public Arr_construction_ss_visitor<
|
||||
Helper_,
|
||||
typename Default::Get<Visitor_, Arr_no_intersection_insertion_ss_visitor<
|
||||
Helper_, Visitor_> >::type>
|
||||
{
|
||||
Helper_, Visitor_> >::type> {
|
||||
public:
|
||||
typedef Helper_ Helper;
|
||||
using Helper = Helper_;
|
||||
|
||||
typedef typename Helper::Geometry_traits_2 Geometry_traits_2;
|
||||
typedef typename Helper::Event Event;
|
||||
typedef typename Helper::Subcurve Subcurve;
|
||||
using Geometry_traits_2 = typename Helper::Geometry_traits_2;
|
||||
using Event = typename Helper::Event;
|
||||
using Subcurve = typename Helper::Subcurve;
|
||||
|
||||
private:
|
||||
typedef Geometry_traits_2 Gt2;
|
||||
typedef Arr_no_intersection_insertion_ss_visitor<Helper, Visitor_>
|
||||
Self;
|
||||
typedef typename Default::Get<Visitor_, Self>::type Visitor;
|
||||
typedef Arr_construction_ss_visitor<Helper, Visitor> Base;
|
||||
using Gt2 = Geometry_traits_2;
|
||||
using Self = Arr_no_intersection_insertion_ss_visitor<Helper, Visitor_>;
|
||||
using Visitor = typename Default::Get<Visitor_, Self>::type;
|
||||
using Base = Arr_construction_ss_visitor<Helper, Visitor>;
|
||||
|
||||
public:
|
||||
typedef typename Gt2::X_monotone_curve_2 X_monotone_curve_2;
|
||||
typedef typename Gt2::Point_2 Point_2;
|
||||
using X_monotone_curve_2 = typename Gt2::X_monotone_curve_2;
|
||||
using Point_2 = typename Gt2::Point_2;
|
||||
using Multiplicity = typename Gt2::Multiplicity;
|
||||
|
||||
protected:
|
||||
typedef typename Subcurve::Status_line_iterator Status_line_iterator;
|
||||
typedef typename Base::Event_subcurve_reverse_iterator
|
||||
Event_subcurve_reverse_iterator;
|
||||
using Status_line_iterator = typename Subcurve::Status_line_iterator;
|
||||
using Event_subcurve_reverse_iterator = typename Base::Event_subcurve_reverse_iterator;
|
||||
|
||||
typedef typename Helper::Arrangement_2 Arrangement_2;
|
||||
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 Arrangement_2 = typename Helper::Arrangement_2;
|
||||
using Vertex_handle = typename Arrangement_2::Vertex_handle;
|
||||
using Halfedge_handle = typename Arrangement_2::Halfedge_handle;
|
||||
using Face_handle = typename Arrangement_2::Face_handle;
|
||||
|
||||
public:
|
||||
/*! Constructor. */
|
||||
|
|
@ -103,13 +101,12 @@ public:
|
|||
{}
|
||||
|
||||
void update_event(Event* /* e */, Subcurve* /* sc1 */, Subcurve* /* sc2 */,
|
||||
bool /* is_new */)
|
||||
bool /* is_new */, Multiplicity /* multiplicity */)
|
||||
{}
|
||||
|
||||
void update_event(Event* /* e */, Subcurve* /* sc1 */) {}
|
||||
|
||||
void update_event(Event* e, const Point_2& pt, bool /* is_new */)
|
||||
{
|
||||
void update_event(Event* e, const Point_2& pt, bool /* is_new */) {
|
||||
Vertex_handle invalid_v;
|
||||
if (e->point().vertex_handle() == invalid_v)
|
||||
e->point().set_vertex_handle(pt.vertex_handle());
|
||||
|
|
@ -241,8 +238,7 @@ void Arr_no_intersection_insertion_ss_visitor<Hlpr, Vis>::before_sweep()
|
|||
//
|
||||
template <typename Hlpr, typename Vis>
|
||||
void Arr_no_intersection_insertion_ss_visitor<Hlpr, Vis>::
|
||||
before_handle_event(Event* event)
|
||||
{
|
||||
before_handle_event(Event* event) {
|
||||
// First we notify the helper class on the event.
|
||||
this->m_helper.before_handle_event(event);
|
||||
|
||||
|
|
@ -330,8 +326,7 @@ before_handle_event(Event* event)
|
|||
//
|
||||
template <typename Hlpr, typename Vis>
|
||||
bool Arr_no_intersection_insertion_ss_visitor<Hlpr, Vis>::
|
||||
add_subcurve_(const X_monotone_curve_2& cv, Subcurve* sc)
|
||||
{
|
||||
add_subcurve_(const X_monotone_curve_2& cv, Subcurve* sc) {
|
||||
const Halfedge_handle invalid_he;
|
||||
if (cv.halfedge_handle() != invalid_he) return false;
|
||||
// Insert the curve into the arrangement
|
||||
|
|
@ -344,8 +339,7 @@ add_subcurve_(const X_monotone_curve_2& cv, Subcurve* sc)
|
|||
//
|
||||
template <typename Hlpr, typename Vis>
|
||||
void Arr_no_intersection_insertion_ss_visitor<Hlpr, Vis>::
|
||||
add_subcurve(const X_monotone_curve_2& cv, Subcurve* sc)
|
||||
{
|
||||
add_subcurve(const X_monotone_curve_2& cv, Subcurve* sc) {
|
||||
if (add_subcurve_(cv, sc)) return;
|
||||
|
||||
Halfedge_handle next_ccw_he =
|
||||
|
|
@ -359,8 +353,7 @@ add_subcurve(const X_monotone_curve_2& cv, Subcurve* sc)
|
|||
template <typename Hlpr, typename Vis>
|
||||
typename Arr_no_intersection_insertion_ss_visitor<Hlpr, Vis>::Halfedge_handle
|
||||
Arr_no_intersection_insertion_ss_visitor<Hlpr, Vis>::
|
||||
insert_in_face_interior(const X_monotone_curve_2& cv, Subcurve* sc)
|
||||
{
|
||||
insert_in_face_interior(const X_monotone_curve_2& cv, Subcurve* sc) {
|
||||
Event* last_event = this->last_event_on_subcurve(sc);
|
||||
Vertex_handle last_v = last_event->point().vertex_handle();
|
||||
Vertex_handle curr_v = this->current_event()->point().vertex_handle();
|
||||
|
|
@ -385,8 +378,7 @@ template <typename Hlpr, typename Vis>
|
|||
typename Arr_no_intersection_insertion_ss_visitor<Hlpr, Vis>::Halfedge_handle
|
||||
Arr_no_intersection_insertion_ss_visitor<Hlpr, Vis>::
|
||||
insert_from_left_vertex(const X_monotone_curve_2& cv, Halfedge_handle he,
|
||||
Subcurve* sc)
|
||||
{
|
||||
Subcurve* sc) {
|
||||
Vertex_handle curr_v = this->current_event()->point().vertex_handle();
|
||||
if (curr_v != Vertex_handle())
|
||||
return (this->m_arr->insert_at_vertices(cv.base(), he, curr_v));
|
||||
|
|
@ -400,8 +392,7 @@ template <typename Hlpr, typename Vis>
|
|||
typename Arr_no_intersection_insertion_ss_visitor<Hlpr, Vis>::Halfedge_handle
|
||||
Arr_no_intersection_insertion_ss_visitor<Hlpr, Vis>::
|
||||
insert_from_right_vertex(const X_monotone_curve_2& cv, Halfedge_handle he,
|
||||
Subcurve* sc)
|
||||
{
|
||||
Subcurve* sc) {
|
||||
Event* last_event = this->last_event_on_subcurve(sc);
|
||||
Vertex_handle last_v = last_event->point().vertex_handle();
|
||||
if (last_v != Vertex_handle())
|
||||
|
|
@ -426,8 +417,7 @@ insert_at_vertices(const X_monotone_curve_2& cv,
|
|||
template <typename Hlpr, typename Vis>
|
||||
typename Arr_no_intersection_insertion_ss_visitor<Hlpr, Vis>::Vertex_handle
|
||||
Arr_no_intersection_insertion_ss_visitor<Hlpr, Vis>::
|
||||
insert_isolated_vertex(const Point_2& pt, Status_line_iterator iter)
|
||||
{
|
||||
insert_isolated_vertex(const Point_2& pt, Status_line_iterator iter) {
|
||||
// If the isolated vertex is already at the arrangement, return:
|
||||
if (pt.vertex_handle() != Vertex_handle()) return Vertex_handle();
|
||||
|
||||
|
|
@ -443,8 +433,7 @@ insert_isolated_vertex(const Point_2& pt, Status_line_iterator iter)
|
|||
template <typename Hlpr, typename Vis>
|
||||
typename Arr_no_intersection_insertion_ss_visitor<Hlpr, Vis>::Halfedge_handle
|
||||
Arr_no_intersection_insertion_ss_visitor<Hlpr, Vis>::
|
||||
_insert_in_face_interior(const X_monotone_curve_2& cv, Subcurve* sc)
|
||||
{
|
||||
_insert_in_face_interior(const X_monotone_curve_2& cv, Subcurve* sc) {
|
||||
// Check if the vertex to be associated with the left end of the curve has
|
||||
// already been created.
|
||||
Event* last_event = this->last_event_on_subcurve(sc);
|
||||
|
|
@ -514,8 +503,7 @@ template <typename Hlpr, typename Vis>
|
|||
typename Arr_no_intersection_insertion_ss_visitor<Hlpr, Vis>::Halfedge_handle
|
||||
Arr_no_intersection_insertion_ss_visitor<Hlpr, Vis>::
|
||||
_insert_from_left_vertex(const X_monotone_curve_2& cv,
|
||||
Halfedge_handle prev, Subcurve* sc)
|
||||
{
|
||||
Halfedge_handle prev, Subcurve* sc) {
|
||||
// Check if the vertex to be associated with the right end of the curve has
|
||||
// already been created.
|
||||
Event* curr_event = this->current_event();
|
||||
|
|
@ -551,8 +539,7 @@ template <typename Hlpr, typename Vis>
|
|||
typename Arr_no_intersection_insertion_ss_visitor<Hlpr, Vis>::Halfedge_handle
|
||||
Arr_no_intersection_insertion_ss_visitor<Hlpr, Vis>::
|
||||
_insert_from_right_vertex(const X_monotone_curve_2& cv, Halfedge_handle prev,
|
||||
Subcurve* sc)
|
||||
{
|
||||
Subcurve* sc) {
|
||||
// Check if the vertex to be associated with the left end of the curve has
|
||||
// already been created.
|
||||
Event* last_event = this->last_event_on_subcurve(sc);
|
||||
|
|
@ -589,8 +576,7 @@ typename Arr_no_intersection_insertion_ss_visitor<Hlpr, Vis>::Halfedge_handle
|
|||
Arr_no_intersection_insertion_ss_visitor<Hlpr, Vis>::
|
||||
_insert_at_vertices(const X_monotone_curve_2& cv,
|
||||
Halfedge_handle prev1, Halfedge_handle prev2,
|
||||
Subcurve* sc, bool& new_face_created)
|
||||
{
|
||||
Subcurve* sc, bool& new_face_created) {
|
||||
// Perform the insertion.
|
||||
new_face_created = false;
|
||||
bool swapped_predecessors = false;
|
||||
|
|
@ -632,8 +618,7 @@ _insert_at_vertices(const X_monotone_curve_2& cv,
|
|||
template <typename Hlpr, typename Vis>
|
||||
typename Arr_no_intersection_insertion_ss_visitor<Hlpr, Vis>::Face_handle
|
||||
Arr_no_intersection_insertion_ss_visitor<Hlpr, Vis>::
|
||||
_ray_shoot_up(Status_line_iterator iter)
|
||||
{
|
||||
_ray_shoot_up(Status_line_iterator iter) {
|
||||
// Go up the status line and try to locate a curve which is associated
|
||||
// with a valid arrangement halfedge.
|
||||
const Halfedge_handle invalid_he;
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
//
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ron Wein <wein@post.tau.ac.il>
|
||||
// Efi Fogel <efif@post.tau.ac.il>
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ron Wein <wein@post.tau.ac.il>
|
||||
// Efi Fogel <efif@post.tau.ac.il>
|
||||
|
||||
#ifndef CGAL_ARR_OVERLAY_SS_VISITOR_H
|
||||
#define CGAL_ARR_OVERLAY_SS_VISITOR_H
|
||||
|
|
@ -40,92 +40,80 @@ namespace CGAL {
|
|||
* arrangement, creating a result arrangement. All three arrangements are
|
||||
* embedded on the same type of surface and use the same geometry traits.
|
||||
*/
|
||||
template <typename OverlayHelper, typename OverlayTraits,
|
||||
typename Visitor_ = Default>
|
||||
template <typename OverlayHelper, typename OverlayTraits, typename Visitor_ = Default>
|
||||
class Arr_overlay_ss_visitor :
|
||||
public Arr_construction_ss_visitor<
|
||||
typename OverlayHelper::Construction_helper,
|
||||
typename Default::Get<Visitor_,
|
||||
Arr_overlay_ss_visitor<OverlayHelper, OverlayTraits,
|
||||
Visitor_> >::type>
|
||||
{
|
||||
Arr_overlay_ss_visitor<OverlayHelper, OverlayTraits, Visitor_> >::type> {
|
||||
public:
|
||||
typedef OverlayHelper Overlay_helper;
|
||||
typedef OverlayTraits Overlay_traits;
|
||||
using Overlay_helper = OverlayHelper;
|
||||
using Overlay_traits = OverlayTraits;
|
||||
|
||||
typedef typename Overlay_helper::Geometry_traits_2 Geometry_traits_2;
|
||||
typedef typename Overlay_helper::Event Event;
|
||||
typedef typename Overlay_helper::Subcurve Subcurve;
|
||||
using Geometry_traits_2 = typename Overlay_helper::Geometry_traits_2;
|
||||
using Event = typename Overlay_helper::Event;
|
||||
using Subcurve = typename Overlay_helper::Subcurve;
|
||||
|
||||
typedef typename Overlay_helper::Arrangement_red_2 Arrangement_red_2;
|
||||
typedef typename Overlay_helper::Arrangement_blue_2 Arrangement_blue_2;
|
||||
|
||||
typedef typename Overlay_helper::Construction_helper Construction_helper;
|
||||
using Arrangement_red_2 = typename Overlay_helper::Arrangement_red_2;
|
||||
using Arrangement_blue_2 = typename Overlay_helper::Arrangement_blue_2;
|
||||
|
||||
using Construction_helper = typename Overlay_helper::Construction_helper;
|
||||
|
||||
private:
|
||||
typedef Geometry_traits_2 Gt2;
|
||||
typedef Arrangement_red_2 Ar2;
|
||||
typedef Arrangement_blue_2 Ab2;
|
||||
using Gt2 = Geometry_traits_2;
|
||||
using Ar2 = Arrangement_red_2;
|
||||
using Ab2 = Arrangement_blue_2;
|
||||
|
||||
typedef Arr_overlay_ss_visitor<Overlay_helper, Overlay_traits, Visitor_>
|
||||
Self;
|
||||
typedef typename Default::Get<Visitor_, Self>::type Visitor;
|
||||
typedef Arr_construction_ss_visitor<Construction_helper, Visitor>
|
||||
Base;
|
||||
using Self = Arr_overlay_ss_visitor<Overlay_helper, Overlay_traits, Visitor_>;
|
||||
using Visitor = typename Default::Get<Visitor_, Self>::type;
|
||||
using Base = Arr_construction_ss_visitor<Construction_helper, Visitor>;
|
||||
|
||||
public:
|
||||
typedef typename Gt2::X_monotone_curve_2 X_monotone_curve_2;
|
||||
typedef typename Gt2::Point_2 Point_2;
|
||||
using X_monotone_curve_2 = typename Gt2::X_monotone_curve_2;
|
||||
using Point_2 = typename Gt2::Point_2;
|
||||
using Multiplicity = typename Gt2::Multiplicity;
|
||||
|
||||
// The input arrangements (the "red" and the "blue" one):
|
||||
typedef typename Ar2::Halfedge_const_handle Halfedge_handle_red;
|
||||
typedef typename Ar2::Face_const_handle Face_handle_red;
|
||||
typedef typename Ar2::Vertex_const_handle Vertex_handle_red;
|
||||
using Halfedge_handle_red = typename Ar2::Halfedge_const_handle;
|
||||
using Face_handle_red = typename Ar2::Face_const_handle;
|
||||
using Vertex_handle_red = typename Ar2::Vertex_const_handle;
|
||||
|
||||
typedef typename Ab2::Halfedge_const_handle Halfedge_handle_blue;
|
||||
typedef typename Ab2::Face_const_handle Face_handle_blue;
|
||||
typedef typename Ab2::Vertex_const_handle Vertex_handle_blue;
|
||||
using Halfedge_handle_blue = typename Ab2::Halfedge_const_handle;
|
||||
using Face_handle_blue = typename Ab2::Face_const_handle;
|
||||
using Vertex_handle_blue = typename Ab2::Vertex_const_handle;
|
||||
|
||||
// The resulting arrangement:
|
||||
typedef typename Overlay_helper::Arrangement_2 Arrangement_2;
|
||||
typedef typename Arrangement_2::Halfedge_handle Halfedge_handle;
|
||||
typedef typename Arrangement_2::Face_handle Face_handle;
|
||||
typedef typename Arrangement_2::Vertex_handle Vertex_handle;
|
||||
typedef typename Arrangement_2::Ccb_halfedge_circulator
|
||||
Ccb_halfedge_circulator;
|
||||
typedef typename Arrangement_2::Outer_ccb_iterator Outer_ccb_iterator;
|
||||
using Arrangement_2 = typename Overlay_helper::Arrangement_2;
|
||||
using Halfedge_handle = typename Arrangement_2::Halfedge_handle;
|
||||
using Face_handle = typename Arrangement_2::Face_handle;
|
||||
using Vertex_handle = typename Arrangement_2::Vertex_handle;
|
||||
using Ccb_halfedge_circulator = typename Arrangement_2::Ccb_halfedge_circulator;
|
||||
using Outer_ccb_iterator = typename Arrangement_2::Outer_ccb_iterator;
|
||||
|
||||
typedef typename Base::Event_subcurve_iterator
|
||||
Event_subcurve_iterator;
|
||||
typedef typename Base::Event_subcurve_reverse_iterator
|
||||
Event_subcurve_reverse_iterator;
|
||||
typedef typename Base::Status_line_iterator Status_line_iterator;
|
||||
using Event_subcurve_iterator = typename Base::Event_subcurve_iterator;
|
||||
using Event_subcurve_reverse_iterator = typename Base::Event_subcurve_reverse_iterator;
|
||||
using Status_line_iterator = typename Base::Status_line_iterator;
|
||||
|
||||
protected:
|
||||
typedef typename Gt2::Cell_handle_red Cell_handle_red;
|
||||
typedef typename Gt2::Optional_cell_red Optional_cell_red;
|
||||
typedef typename Gt2::Cell_handle_blue Cell_handle_blue;
|
||||
typedef typename Gt2::Optional_cell_blue Optional_cell_blue;
|
||||
using Cell_handle_red = typename Gt2::Cell_handle_red;
|
||||
using Optional_cell_red = typename Gt2::Optional_cell_red;
|
||||
using Cell_handle_blue = typename Gt2::Cell_handle_blue;
|
||||
using Optional_cell_blue = typename Gt2::Optional_cell_blue;
|
||||
|
||||
typedef std::pair<Halfedge_handle_red, Halfedge_handle_blue>
|
||||
Halfedge_info;
|
||||
typedef Unique_hash_map<Halfedge_handle, Halfedge_info>
|
||||
Halfedge_map;
|
||||
using Halfedge_info = std::pair<Halfedge_handle_red, Halfedge_handle_blue>;
|
||||
using Halfedge_map = Unique_hash_map<Halfedge_handle, Halfedge_info>;
|
||||
|
||||
typedef std::pair<Cell_handle_red, Cell_handle_blue> Handle_info;
|
||||
typedef std::unordered_map<Vertex_handle, Handle_info, Handle_hash_function>
|
||||
Vertex_map;
|
||||
using Handle_info = std::pair<Cell_handle_red, Cell_handle_blue>;
|
||||
using Vertex_map = std::unordered_map<Vertex_handle, Handle_info, Handle_hash_function>;
|
||||
|
||||
// Side categoties:
|
||||
typedef typename Gt2::Left_side_category Left_side_category;
|
||||
typedef typename Gt2::Bottom_side_category Bottom_side_category;
|
||||
typedef typename Gt2::Top_side_category Top_side_category;
|
||||
typedef typename Gt2::Right_side_category Right_side_category;
|
||||
using Left_side_category = typename Gt2::Left_side_category;
|
||||
using Bottom_side_category = typename Gt2::Bottom_side_category;
|
||||
using Top_side_category = typename Gt2::Top_side_category;
|
||||
using Right_side_category = typename Gt2::Right_side_category;
|
||||
|
||||
typedef typename Arr_has_identified_sides<Left_side_category,
|
||||
Bottom_side_category>::result
|
||||
Has_identified_sides_category;
|
||||
using Has_identified_sides_category =
|
||||
typename Arr_has_identified_sides<Left_side_category, Bottom_side_category>::result;
|
||||
|
||||
// Data members:
|
||||
Overlay_traits* m_overlay_traits; // The overlay traits object.
|
||||
|
|
@ -195,10 +183,9 @@ public:
|
|||
void update_event(Event* /* e */,
|
||||
Subcurve* /* c1 */,
|
||||
Subcurve* /* c2 */,
|
||||
bool CGAL_assertion_code(is_new))
|
||||
{
|
||||
CGAL_assertion(is_new == true);
|
||||
}
|
||||
bool CGAL_assertion_code(is_new),
|
||||
Multiplicity /* multiplicity */)
|
||||
{ CGAL_assertion(is_new == true); }
|
||||
|
||||
/*! Update an event. */
|
||||
void update_event(Event* e, Subcurve* sc);
|
||||
|
|
@ -407,9 +394,8 @@ protected:
|
|||
//-----------------------------------------------------------------------------
|
||||
// A notification issued before the sweep process starts.
|
||||
//
|
||||
template <typename OvlHlpr, typename OvlTr, typename Vis>
|
||||
void Arr_overlay_ss_visitor<OvlHlpr, OvlTr, Vis>::before_sweep()
|
||||
{
|
||||
template <typename OvlHlpr, typename OvlTr, typename Vis>
|
||||
void Arr_overlay_ss_visitor<OvlHlpr, OvlTr, Vis>::before_sweep() {
|
||||
// Initialize the necessary fields in the base construction visitor.
|
||||
// Note that the construction visitor also informs its helper class that
|
||||
// the sweep process is about to start.
|
||||
|
|
@ -425,8 +411,7 @@ protected:
|
|||
//
|
||||
template <typename OvlHlpr, typename OvlTr, typename Vis>
|
||||
void
|
||||
Arr_overlay_ss_visitor<OvlHlpr, OvlTr, Vis>::before_handle_event(Event* event)
|
||||
{
|
||||
Arr_overlay_ss_visitor<OvlHlpr, OvlTr, Vis>::before_handle_event(Event* event) {
|
||||
// Let the base construction visitor do the work (and also inform its helper
|
||||
// class on the event).
|
||||
Base::before_handle_event(event);
|
||||
|
|
@ -441,8 +426,7 @@ Arr_overlay_ss_visitor<OvlHlpr, OvlTr, Vis>::before_handle_event(Event* event)
|
|||
//
|
||||
template <typename OvlHlpr, typename OvlTr, typename Vis>
|
||||
bool Arr_overlay_ss_visitor<OvlHlpr, OvlTr, Vis>::
|
||||
after_handle_event(Event* event, Status_line_iterator iter, bool flag)
|
||||
{
|
||||
after_handle_event(Event* event, Status_line_iterator iter, bool flag) {
|
||||
// Let the base construction visitor handle the event.
|
||||
bool res = Base::after_handle_event(event, iter, flag);
|
||||
|
||||
|
|
@ -497,8 +481,7 @@ update_event(Event* e,
|
|||
const Point_2& end_point,
|
||||
const X_monotone_curve_2& /* cv */,
|
||||
Arr_curve_end /* cv_end */,
|
||||
bool /* is_new */)
|
||||
{
|
||||
bool /* is_new */) {
|
||||
// Nothing to do in case of an event at infinity.
|
||||
CGAL_assertion(e->is_closed());
|
||||
|
||||
|
|
@ -513,8 +496,7 @@ update_event(Event* e,
|
|||
//
|
||||
template <typename OvlHlpr, typename OvlTr, typename Vis>
|
||||
void Arr_overlay_ss_visitor<OvlHlpr, OvlTr, Vis>::update_event(Event* e,
|
||||
Subcurve* sc)
|
||||
{
|
||||
Subcurve* sc) {
|
||||
// Update the red and blue halfedges associated with the point as necessary.
|
||||
Point_2& pt = e->point();
|
||||
|
||||
|
|
@ -538,8 +520,7 @@ template <typename OvlHlpr, typename OvlTr, typename Vis>
|
|||
void
|
||||
Arr_overlay_ss_visitor<OvlHlpr, OvlTr, Vis>::update_event(Event* e,
|
||||
const Point_2& p,
|
||||
bool /* is_new */)
|
||||
{
|
||||
bool /* is_new */) {
|
||||
// Update the red and blue objects associated with the point as necessary.
|
||||
Point_2& pt = e->point();
|
||||
if (pt.is_red_cell_empty()) pt.set_red_cell(p.red_cell());
|
||||
|
|
@ -550,8 +531,7 @@ Arr_overlay_ss_visitor<OvlHlpr, OvlTr, Vis>::update_event(Event* e,
|
|||
// A notification issued when the sweep process has ended.
|
||||
//
|
||||
template <typename OvlHlpr, typename OvlTr, typename Vis>
|
||||
void Arr_overlay_ss_visitor<OvlHlpr, OvlTr, Vis>::after_sweep()
|
||||
{
|
||||
void Arr_overlay_ss_visitor<OvlHlpr, OvlTr, Vis>::after_sweep() {
|
||||
Base::after_sweep();
|
||||
|
||||
// Notify boundary vertices:
|
||||
|
|
@ -580,8 +560,7 @@ void Arr_overlay_ss_visitor<OvlHlpr, OvlTr, Vis>::after_sweep()
|
|||
template <typename OvlHlpr, typename OvlTr, typename Vis>
|
||||
typename Arr_overlay_ss_visitor<OvlHlpr, OvlTr, Vis>::Halfedge_handle
|
||||
Arr_overlay_ss_visitor<OvlHlpr, OvlTr, Vis>::
|
||||
insert_in_face_interior(const X_monotone_curve_2& cv, Subcurve* sc)
|
||||
{
|
||||
insert_in_face_interior(const X_monotone_curve_2& cv, Subcurve* sc) {
|
||||
// Insert the halfedge using the base construction visitor.
|
||||
Halfedge_handle new_he = Base::insert_in_face_interior(cv, sc);
|
||||
_map_halfedge_and_twin(new_he,
|
||||
|
|
@ -615,8 +594,7 @@ typename Arr_overlay_ss_visitor<OvlHlpr, OvlTr, Vis>::Halfedge_handle
|
|||
Arr_overlay_ss_visitor<OvlHlpr, OvlTr, Vis>::
|
||||
insert_from_left_vertex(const X_monotone_curve_2& cv,
|
||||
Halfedge_handle prev,
|
||||
Subcurve* sc)
|
||||
{
|
||||
Subcurve* sc) {
|
||||
_map_boundary_vertices(this->last_event_on_subcurve(sc), prev->target(),
|
||||
Has_identified_sides_category());
|
||||
|
||||
|
|
@ -647,8 +625,7 @@ typename Arr_overlay_ss_visitor<OvlHlpr, OvlTr, Vis>::Halfedge_handle
|
|||
Arr_overlay_ss_visitor<OvlHlpr, OvlTr, Vis>::
|
||||
insert_from_right_vertex(const X_monotone_curve_2& cv,
|
||||
Halfedge_handle prev,
|
||||
Subcurve* sc)
|
||||
{
|
||||
Subcurve* sc) {
|
||||
_map_boundary_vertices(this->current_event(), prev->target(),
|
||||
Has_identified_sides_category());
|
||||
|
||||
|
|
@ -680,8 +657,7 @@ insert_at_vertices(const X_monotone_curve_2& cv,
|
|||
Halfedge_handle prev1,
|
||||
Halfedge_handle prev2,
|
||||
Subcurve* sc,
|
||||
bool& new_face_created)
|
||||
{
|
||||
bool& new_face_created) {
|
||||
// Insert the halfedge using the base construction visitor. Note that the
|
||||
// resulting halfedge is always incident to the new face (if one created).
|
||||
Halfedge_handle new_he =
|
||||
|
|
@ -795,8 +771,7 @@ template <typename OvlHlpr, typename OvlTr, typename Vis>
|
|||
typename Arr_overlay_ss_visitor<OvlHlpr, OvlTr, Vis>::Vertex_handle
|
||||
Arr_overlay_ss_visitor<OvlHlpr, OvlTr, Vis>::
|
||||
insert_isolated_vertex(const Point_2& pt,
|
||||
Status_line_iterator iter)
|
||||
{
|
||||
Status_line_iterator iter) {
|
||||
// Insert the isolated vertex using the base construction visitor.
|
||||
Vertex_handle new_v = Base::insert_isolated_vertex(pt, iter);
|
||||
|
||||
|
|
@ -897,14 +872,13 @@ template <typename OvlHlpr, typename OvlTr, typename Vis>
|
|||
void Arr_overlay_ss_visitor<OvlHlpr, OvlTr, Vis>::
|
||||
_map_halfedge_and_twin(Halfedge_handle he,
|
||||
Halfedge_handle_red red_he,
|
||||
Halfedge_handle_blue blue_he)
|
||||
{
|
||||
Halfedge_handle_blue blue_he) {
|
||||
if (he->direction() == ARR_LEFT_TO_RIGHT) he = he->twin();
|
||||
|
||||
// Obtain the twin red and blue halfedges (if they are valid). Note that
|
||||
// the original halfedges are always directed from right to left.
|
||||
Halfedge_handle_red red_he_twin;
|
||||
Halfedge_handle_blue blue_he_twin;
|
||||
Halfedge_handle_red red_he_twin;
|
||||
Halfedge_handle_blue blue_he_twin;
|
||||
|
||||
if (red_he != Halfedge_handle_red()) red_he_twin = red_he->twin();
|
||||
if (blue_he != Halfedge_handle_blue()) blue_he_twin = blue_he->twin();
|
||||
|
|
@ -922,8 +896,7 @@ _map_halfedge_and_twin(Halfedge_handle he,
|
|||
//
|
||||
template <typename OvlHlpr, typename OvlTr, typename Vis>
|
||||
void Arr_overlay_ss_visitor<OvlHlpr, OvlTr, Vis>::
|
||||
_map_boundary_vertices(Event* event, Vertex_handle v, std::bool_constant<true>)
|
||||
{
|
||||
_map_boundary_vertices(Event* event, Vertex_handle v, std::bool_constant<true>) {
|
||||
// Update the red and blue object if the last event on sc is on the boundary.
|
||||
if ((event->parameter_space_in_x() != ARR_INTERIOR) ||
|
||||
(event->parameter_space_in_y() != ARR_INTERIOR))
|
||||
|
|
@ -938,8 +911,7 @@ _map_boundary_vertices(Event* event, Vertex_handle v, std::bool_constant<true>)
|
|||
if (red_handle_p) info.first = *red_handle_p;
|
||||
|
||||
if (!std::get_if<Face_handle_red>(&(info.first)) &&
|
||||
!std::get_if<Face_handle_blue>(&(info.second)))
|
||||
{
|
||||
!std::get_if<Face_handle_blue>(&(info.second))) {
|
||||
// If both, the red and blue, variants do not represent face handles,
|
||||
// they must represt either vertex or edge handles. In this case it is
|
||||
// safe to apply the call to the overlay traits and erase the record,
|
||||
|
|
@ -974,8 +946,7 @@ void Arr_overlay_ss_visitor<OvlHlpr, OvlTr, Vis>::
|
|||
_create_vertex(Event* event,
|
||||
Vertex_handle new_v,
|
||||
Subcurve* sc,
|
||||
std::bool_constant<true>)
|
||||
{
|
||||
std::bool_constant<true>) {
|
||||
const Point_2& pt = event->point();
|
||||
const Cell_handle_red* red_handle = pt.red_cell_handle();
|
||||
const Cell_handle_blue* blue_handle = pt.blue_cell_handle();
|
||||
|
|
@ -983,8 +954,7 @@ _create_vertex(Event* event,
|
|||
// If the vertex is on the boundary, postpone the notification, but
|
||||
// update the red and objects in case they are empty.
|
||||
if ((event->parameter_space_in_x() != ARR_INTERIOR) ||
|
||||
(event->parameter_space_in_y() != ARR_INTERIOR))
|
||||
{
|
||||
(event->parameter_space_in_y() != ARR_INTERIOR)) {
|
||||
if (!red_handle) {
|
||||
CGAL_assertion(blue_handle != nullptr);
|
||||
// Obtain the red face by looking for a subcurve above.
|
||||
|
|
@ -1020,8 +990,7 @@ void Arr_overlay_ss_visitor<OvlHlpr, OvlTr, Vis>::
|
|||
_create_vertex(Event* event,
|
||||
Vertex_handle new_v,
|
||||
Subcurve* sc,
|
||||
std::bool_constant<false>)
|
||||
{
|
||||
std::bool_constant<false>) {
|
||||
const Point_2& pt = event->point();
|
||||
const Cell_handle_red* red_handle = pt.red_cell_handle();
|
||||
const Cell_handle_blue* blue_handle = pt.blue_cell_handle();
|
||||
|
|
@ -1063,8 +1032,7 @@ _create_vertex(Event* event,
|
|||
template <typename OvlHlpr, typename OvlTr, typename Vis>
|
||||
void Arr_overlay_ss_visitor<OvlHlpr, OvlTr, Vis>::
|
||||
_create_edge(Subcurve* sc,
|
||||
Halfedge_handle new_he)
|
||||
{
|
||||
Halfedge_handle new_he) {
|
||||
// Note that the "red" and "blue" halfedges are always directed from right
|
||||
// to left, so we make sure the overlaid halfedge is also directed from
|
||||
// right to left.
|
||||
|
|
|
|||
|
|
@ -700,15 +700,29 @@ swap its source and target points).
|
|||
The traits classes `Arr_segment_traits_2`,
|
||||
`Arr_non_caching_segment_traits_2`, `Arr_circle_segment_traits_2`,
|
||||
`Arr_conic_traits_2` and `Arr_rational_function_traits_2`, which are
|
||||
bundled in the `Arrangement_2` package and distributed with \cgal,
|
||||
are all models of the refined concept
|
||||
`AosDirectionalXMonotoneTraits_2`.\cgalFootnote{The \cgalFootnoteCode{Arr_polyline_traits_2} class is <I>not</I> a model of the, \cgalFootnoteCode{AosDirectionalXMonotoneTraits_2} concept, as the \f$ x\f$-monotone curve it defines is always directed from left to right. Thus, an opposite curve cannot be constructed. However, it is not very useful to construct a polygon whose edges are polylines, as an ordinary polygon with linear edges can represent the same entity.}
|
||||
bundled in the `Arrangement_2` package and distributed with \cgal, are
|
||||
all models of the refined concept
|
||||
`AosDirectionalXMonotoneTraits_2`.\cgalFootnote{The
|
||||
\cgalFootnoteCode{Arr_polyline_traits_2} class is <I>not</I> a model
|
||||
of the, \cgalFootnoteCode{AosDirectionalXMonotoneTraits_2} concept, as
|
||||
the \f$ x\f$-monotone curve it defines is always directed from left to
|
||||
right. Thus, an opposite curve cannot be constructed. However, it is
|
||||
not very useful to construct a polygon whose edges are polylines, as
|
||||
an ordinary polygon with linear edges can represent the same entity.}
|
||||
|
||||
Just as with the case of computations using models of the
|
||||
`AosXMonotoneTraits_2` concept, operations are robust only
|
||||
when exact arithmetic is used. When inexact arithmetic is used,
|
||||
(nearly) degenerate configurations may result in abnormal termination
|
||||
of the program or even incorrect results.
|
||||
Operations on polygons (or general polygons) are guaranteed to be
|
||||
robust only if the operations of the geometry traits used to carry out
|
||||
the high-level operations are robust. Most operations on polygons use
|
||||
geometry traits constructors, as they generate new polygons; such
|
||||
constructors are guaranteed to be robust only if the kernel in use
|
||||
supports exact constructions, such as the EPEC (Exact Predicate Exact
|
||||
Construction) kernel. The `do_intersect()` overloaded predicates that
|
||||
operate on (linear) polygons are exceptions, as they only use geometry
|
||||
traits predicates; such predicates are guaranteed to be robust only if
|
||||
the kernel in use supports exact predicates, such as the EPIC (Exact
|
||||
Predicate Inexact Construction) kernel. When inexact arithmetic is
|
||||
used, (nearly) degenerate configurations may result in abnormal
|
||||
termination of the program or even incorrect results.
|
||||
|
||||
\subsection bso_sseccirc_seg Operating on Polygons with Circular Arcs
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,10 @@ namespace CGAL {
|
|||
* <tr><td align="right"><b>2.</b></td><td>`void complement(const Type1& pgn, Type2& res, const GpsTraits& traits);`</td></tr>
|
||||
* </table>
|
||||
*
|
||||
* \tparam Kernel a model of the concept `PolygonTraits_2`.
|
||||
* \tparam Container a model of the concept `Container`; defaults to `std::vector<Kernel::Point_2`>.
|
||||
* \tparam ArrTraits a model of the concept `AosDirectionalXMonotoneTraits_2`.
|
||||
* \tparam GpsTraits a model of the concept `GeneralPolygonSetTraits_2`, which must be convertible to `ArrTraits`.
|
||||
* \tparam UsePolylines determines whether the boundary of the input polygon is
|
||||
* treated as a cyclic sequence of single (\f$x\f$-monotone) segments or as a
|
||||
* cyclic sequence of (\f$x\f$-monotone) polylines. If substituted with
|
||||
|
|
@ -28,7 +32,7 @@ namespace CGAL {
|
|||
* to a standard polygon. If substituted with `CGAL::Tag_false`, the input
|
||||
* polygon is used as is. Refer to \ref bso_ssectraits_sel for more information.
|
||||
*
|
||||
* - The types `Type` and `Type2` of the parameters must be convertible to the
|
||||
* - The types `Type1` and `Type2` of the parameters must be convertible to the
|
||||
* types specified in a row in the table below, respectively.
|
||||
* - The types that apply to signature (<b>1.1.</b>) above are restricted to those
|
||||
* listed in rows <b>1</b> and <b>2</b> in the table below.
|
||||
|
|
@ -54,6 +58,8 @@ namespace CGAL {
|
|||
* \sa \link boolean_join `CGAL::join()` \endlink
|
||||
* \sa \link boolean_difference `CGAL::difference()` \endlink
|
||||
* \sa \link boolean_symmetric_difference `CGAL::symmetric_difference()` \endlink
|
||||
* \sa Polygon_2<Kernel, Container>
|
||||
* \sa Polygon_with_holes_2<Kernel, Container>
|
||||
*/
|
||||
|
||||
/// @{
|
||||
|
|
@ -224,6 +230,10 @@ namespace CGAL {
|
|||
* <tr><td align="right"><b>2.</b></td><td>`OutputIterator difference(const Type1& pgn1, const Type2& pgn2, OutputIterator oi, const GpsTraits& traits);`</td></tr>
|
||||
* </table>
|
||||
*
|
||||
* \tparam Kernel a model of the concept `PolygonTraits_2`
|
||||
* \tparam Container a model of the concept `Container`; defaults to `std::vector<Kernel::Point_2`>.
|
||||
* \tparam ArrTraits a model of the concept `AosDirectionalXMonotoneTraits_2`
|
||||
* \tparam GpsTraits a model of the concept `GeneralPolygonSetTraits_2`, which must be convertible to `ArrTraits`.
|
||||
* \tparam UsePolylines determines whether the boundaries of the input polygons
|
||||
* are treated as cyclic sequences of single (\f$x\f$-monotone) segments or as
|
||||
* cyclic sequences of (\f$x\f$-monotone) polylines. If substituted with
|
||||
|
|
@ -264,6 +274,8 @@ namespace CGAL {
|
|||
* \sa \link boolean_intersection `CGAL::intersection()` \endlink
|
||||
* \sa \link boolean_join `CGAL::join()` \endlink
|
||||
* \sa \link boolean_symmetric_difference `CGAL::symmetric_difference()` \endlink
|
||||
* \sa Polygon_2<Kernel, Container>
|
||||
* \sa Polygon_with_holes_2<Kernel, Container>
|
||||
*/
|
||||
|
||||
/// @{
|
||||
|
|
@ -660,48 +672,22 @@ namespace CGAL {
|
|||
* A function template in this group that accepts two input polygons has one of
|
||||
* the following signatures:
|
||||
* <table cellpadding=3 border="0">
|
||||
* <tr><td align="right"><b>1.1.</b></td><td>`bool do_intersect(const Type1& pgn1, const Type2& pgn2, UsePolylines = Tag_true());`</td></tr>
|
||||
* <tr><td align="right"><b>1.2.</b></td><td>`bool do_intersect(const Type1& pgn1, const Type2& pgn2);`</td></tr>
|
||||
* <tr><td align="right"><b> 2.</b></td><td>`bool do_intersect(const Type1& pgn1, const Type2& pgn2, const GpsTraits& traits);`</td></tr>
|
||||
* <tr><td align="right"><b>1.</b></td><td>`bool do_intersect(const Type1& pgn1, const Type2& pgn2);`</td></tr>
|
||||
* <tr><td align="right"><b>2.</b></td><td>`bool do_intersect(const Type1& pgn1, const Type2& pgn2, const GpsTraits& traits);`</td></tr>
|
||||
* </table>
|
||||
*
|
||||
* There are also function templates that accept one or two ranges of input polygons:
|
||||
* <table cellpadding=3 border="0">
|
||||
* <tr><td align="right"><b>3.1.</b></td><td>`bool do_intersect(InputIterator begin, InputIterator end, UsePolylines = Tag_true());`</td></tr>
|
||||
* <tr><td align="right"><b>3.2.</b></td><td>`bool do_intersect(InputIterator begin, InputIterator end);`</td></tr>
|
||||
* <tr><td align="right"><b> 4.</b></td><td>`bool do_intersect(InputIterator begin, InputIterator end, const GpsTraits& traits);`</td></tr>
|
||||
* <tr><td align="right"><b>5.1.</b></td><td>`bool do_intersect(InputIterator1 begin1, InputIterator1 end1, InputIterator2 begin2, InputIterator2 end2, UsePolylines = Tag_true());`</td></tr>
|
||||
* <tr><td align="right"><b>5.2.</b></td><td>`bool do_intersect(InputIterator1 begin1, InputIterator1 end1, InputIterator2 begin2, InputIterator2 end2);`</td></tr>
|
||||
* <tr><td align="right"><b> 6.</b></td><td>`bool do_intersect(InputIterator1 begin1, InputIterator1 end1, InputIterator2 begin2, InputIterator2 end2, const GpsTraits& traits);`</td></tr>
|
||||
* <tr><td align="right"><b>3.</b></td><td>`bool do_intersect(InputIterator begin, InputIterator end);`</td></tr>
|
||||
* <tr><td align="right"><b>4.</b></td><td>`bool do_intersect(InputIterator begin, InputIterator end, const GpsTraits& traits);`</td></tr>
|
||||
* <tr><td align="right"><b>5.</b></td><td>`bool do_intersect(InputIterator1 begin1, InputIterator1 end1, InputIterator2 begin2, InputIterator2 end2);`</td></tr>
|
||||
* <tr><td align="right"><b>6.</b></td><td>`bool do_intersect(InputIterator1 begin1, InputIterator1 end1, InputIterator2 begin2, InputIterator2 end2, const GpsTraits& traits);`</td></tr>
|
||||
* </table>
|
||||
*
|
||||
* \tparam UsePolylines determines whether the boundary of the input polygons
|
||||
* are treated as a cyclic sequence of single (\f$x\f$-monotone) segments or as
|
||||
* a cyclic sequence of (\f$x\f$-monotone) polylines. If substituted with
|
||||
* `CGAL::Tag_true`, which is the default, the input polygons are converted to
|
||||
* general polygons bounded by polylines before the operation is actually
|
||||
* performed. If substituted with `CGAL::Tag_false`, the input polygons are used
|
||||
* as is. Refer to \ref bso_ssectraits_sel for more information.
|
||||
*
|
||||
* - The types `Type1` and `Type2` of the parameters of
|
||||
* `InputIterator1::value_type` and `InputIterator2::value_type` must be
|
||||
* convertible to the types specified in a row in the table below,
|
||||
* respectively.
|
||||
*
|
||||
* - The types that apply to signatures (<b>1.1.</b>) and (<b>5.1.</b>) above
|
||||
* are restricted to those listed in rows <b>1–4</b> in the table
|
||||
* below.
|
||||
*
|
||||
* - The types that apply to signatures (<b>1.2.</b>) and (<b>5.2.</b>) above
|
||||
* are restricted to those listed in rows <b>5–8</b> in the table
|
||||
* below.
|
||||
*
|
||||
* - The type of `InputIterator::value_type` in (<b>3.1.</b>) above
|
||||
* must be convertible to either `Polygon_2` or `Polygon_with_holes_2`.
|
||||
*
|
||||
* - The type of `InputIterator::value_type` in (<b>3.2.</b>) above must be
|
||||
* convertible to either `General_polygon_2` or
|
||||
* `General_polygon_with_holes_2`.
|
||||
* \tparam Kernel a model of the concept `PolygonTraits_2`.
|
||||
* \tparam Container a model of the concept `Container`; defaults to `std::vector<Kernel::Point_2`>.
|
||||
* \tparam ArrTraits a model of the concept `AosDirectionalXMonotoneTraits_2`.
|
||||
* \tparam GpsTraits a model of the concept `GeneralPolygonSetTraits_2`, which must be convertible to `ArrTraits`.
|
||||
*
|
||||
* <div align="left">
|
||||
* <table cellpadding=3 border="1">
|
||||
|
|
@ -728,6 +714,8 @@ namespace CGAL {
|
|||
* \sa \link boolean_join `CGAL::join()` \endlink
|
||||
* \sa \link boolean_difference `CGAL::difference()` \endlink
|
||||
* \sa \link boolean_symmetric_difference `CGAL::symmetric_difference()` \endlink
|
||||
* \sa Polygon_2<Kernel, Container>
|
||||
* \sa Polygon_with_holes_2<Kernel, Container>
|
||||
*/
|
||||
|
||||
/// @{
|
||||
|
|
@ -735,6 +723,11 @@ namespace CGAL {
|
|||
//////// Traits-less
|
||||
|
||||
/*! determines whether two polygons intersect in their interior.
|
||||
*
|
||||
* The kernel used to instantiate the type of the input polygons must support
|
||||
* exact predicates to guarantee correct results; however, inexact constructions
|
||||
* are tolerated.
|
||||
*
|
||||
* \param pgn1 the 1st input polygon.
|
||||
* \param pgn2 the 2nd input polygon.
|
||||
* \return `true` if `pgn1` and `pgn2` intersect in their interior and `false`
|
||||
|
|
@ -745,25 +738,11 @@ bool do_intersect(const Polygon_2<Kernel, Container>& pgn1,
|
|||
const Polygon_2<Kernel, Container>& pgn2);
|
||||
|
||||
/*! determines whether two polygons intersect in their interior.
|
||||
* \tparam UsePolylines determines whether the boundaries of `pgn1` and `pgn2`
|
||||
* are treated as cyclic sequences of single (\f$x\f$-monotone) segments
|
||||
* or as a cyclic sequences of (\f$x\f$-monotone) polylines. If
|
||||
* substituted with `CGAL::Tag_true`, which is the default, `pgn1` and
|
||||
* `pgn2` are converted to general polygons, bounded by polylines
|
||||
* before the operation is actually performed. If substituted with
|
||||
* `CGAL::Tag_false`, `pgn1` and `pgn2` are used as is. Refer to \ref
|
||||
* bso_ssectraits_sel for more information.
|
||||
* \param pgn1 the 1st input polygon.
|
||||
* \param pgn2 the 2nd input polygon.
|
||||
* \return `true` if `pgn1` and `pgn2` intersect in their interior and `false`
|
||||
* otherwise.
|
||||
*/
|
||||
template <typename Kernel, typename Container, typename UsePolylines>
|
||||
bool do_intersect(const Polygon_2<Kernel, Container>& pgn1,
|
||||
const Polygon_2<Kernel, Container>& pgn2,
|
||||
UsePolylines = Tag_true());
|
||||
|
||||
/*! determines whether two polygons intersect in their interior.
|
||||
*
|
||||
* The kernel used to instantiate the type of the input polygons must support
|
||||
* exact predicates to guarantee correct results; however, inexact constructions
|
||||
* are tolerated.
|
||||
*
|
||||
* \param pgn1 the 1st input polygon.
|
||||
* \param pgn2 the 2nd input polygon.
|
||||
* \return `true` if `pgn1` and `pgn2` intersect in their interior and `false`
|
||||
|
|
@ -774,26 +753,11 @@ bool do_intersect(const Polygon_2<Kernel, Container>& pgn1,
|
|||
const Polygon_with_holes_2<Kernel, Container>& pgn2);
|
||||
|
||||
/*! determines whether two polygons intersect in their interior.
|
||||
* \tparam UsePolylines determines whether the boundaries of `pgn1` and `pgn2`
|
||||
* are treated as cyclic sequences of single (\f$x\f$-monotone) segments
|
||||
* or as a cyclic sequences of (\f$x\f$-monotone) polylines. If
|
||||
* substituted with `CGAL::Tag_true`, which is the default, `pgn1` and
|
||||
* `pgn2` are converted to a general polygon and a general polygon
|
||||
* with holes, respectively, bounded by polylines before the operation
|
||||
* is actually performed. If substituted with `CGAL::Tag_false`, `pgn1`
|
||||
* and `pgn2` are used as is. Refer to \ref bso_ssectraits_sel for more
|
||||
* information.
|
||||
* \param pgn1 the 1st input polygon.
|
||||
* \param pgn2 the 2nd input polygon.
|
||||
* \return `true` if `pgn1` and `pgn2` intersect in their interior and `false`
|
||||
* otherwise.
|
||||
*/
|
||||
template <typename Kernel, typename Container, typename UsePolylines>
|
||||
bool do_intersect(const Polygon_2<Kernel, Container>& pgn1,
|
||||
const Polygon_with_holes_2<Kernel, Container>& pgn2,
|
||||
UsePolylines = Tag_true());
|
||||
|
||||
/*! determines whether two polygons intersect in their interior.
|
||||
*
|
||||
* The kernel used to instantiate the type of the input polygons must support
|
||||
* exact predicates to guarantee correct results; however, inexact constructions
|
||||
* are tolerated.
|
||||
*
|
||||
* \param pgn1 the 1st input polygon.
|
||||
* \param pgn2 the 2nd input polygon.
|
||||
* \return `true` if `pgn1` and `pgn2` intersect in their interior and `false`
|
||||
|
|
@ -803,27 +767,12 @@ template <typename Kernel, typename Container>
|
|||
bool do_intersect(const Polygon_with_holes_2<Kernel, Container>& pgn1,
|
||||
const Polygon_2<Kernel, Container>& pgn2);
|
||||
|
||||
/*! determines whether two polygons intersect in their interior.
|
||||
* \tparam UsePolylines determines whether the boundaries of `pgn1` and `pgn2`
|
||||
* are treated as cyclic sequences of single (\f$x\f$-monotone) segments
|
||||
* or as a cyclic sequences of (\f$x\f$-monotone) polylines. If
|
||||
* substituted with `CGAL::Tag_true`, which is the default, `pgn1` and
|
||||
* `pgn2` are converted to a general polygon with holes and a general
|
||||
* polygon, respectively, bounded by polylines before the operation
|
||||
* is actually performed. If substituted with `CGAL::Tag_false`, `pgn1`
|
||||
* and `pgn2` are used as is. Refer to \ref bso_ssectraits_sel for more
|
||||
* information.
|
||||
* \param pgn1 the 1st input polygon.
|
||||
* \param pgn2 the 2nd input polygon.
|
||||
* \return `true` if `pgn1` and `pgn2` intersect in their interior and `false`
|
||||
* otherwise.
|
||||
*/
|
||||
template <typename Kernel, typename Container, typename UsePolylines>
|
||||
bool do_intersect(const Polygon_with_holes_2<Kernel, Container>& pgn1,
|
||||
const Polygon_2<Kernel, Container>& pgn2,
|
||||
UsePolylines = Tag_true());
|
||||
|
||||
/*! determines whether two polygons with holes intersect in their interior.
|
||||
*
|
||||
* The kernel used to instantiate the type of the input polygons must support
|
||||
* exact predicates to guarantee correct results; however, inexact constructions
|
||||
* are tolerated.
|
||||
*
|
||||
* \param pgn1 the 1st input polygon.
|
||||
* \param pgn2 the 2nd input polygon.
|
||||
* \return `true` if `pgn1` and `pgn2` intersect in their interior and `false`
|
||||
|
|
@ -833,25 +782,6 @@ template <typename Kernel, typename Container>
|
|||
bool do_intersect(const Polygon_with_holes_2<Kernel, Container>& pgn1,
|
||||
const Polygon_with_holes_2<Kernel, Container>& pgn2);
|
||||
|
||||
/*! determines whether two polygons with holes intersect in their interior.
|
||||
* \tparam UsePolylines determines whether the boundaries of `pgn1` and `pgn2`
|
||||
* are treated as cyclic sequences of single (\f$x\f$-monotone) segments
|
||||
* or as a cyclic sequences of (\f$x\f$-monotone) polylines. If
|
||||
* substituted with `CGAL::Tag_true`, which is the default, `pgn1` and
|
||||
* `pgn2` are converted to general polygon with holes , bounded by
|
||||
* polylines before the operation is actually performed. If substituted
|
||||
* with `CGAL::Tag_false`, `pgn1` and `pgn2` are used as is. Refer to
|
||||
* \ref bso_ssectraits_sel for more information.
|
||||
* \param pgn1 the 1st input polygon.
|
||||
* \param pgn2 the 2nd input polygon.
|
||||
* \return `true` if `pgn1` and `pgn2` intersect in their interior and `false`
|
||||
* otherwise.
|
||||
*/
|
||||
template <typename Kernel, typename Container, typename UsePolylines>
|
||||
bool do_intersect(const Polygon_with_holes_2<Kernel, Container>& pgn1,
|
||||
const Polygon_with_holes_2<Kernel, Container>& pgn2,
|
||||
UsePolylines = Tag_true());
|
||||
|
||||
/*! determines whether two general polygons intersect in their interior.
|
||||
* \param pgn1 the 1st input polygon.
|
||||
* \param pgn2 the 2nd input polygon.
|
||||
|
|
@ -904,6 +834,13 @@ bool do_intersect(const General_polygon_with_holes_2<Polygon>& pgn1,
|
|||
* of general polygons or a range of general polygons with holes) determines
|
||||
* whether the open polygons (respectively general polygons) in the range have a common
|
||||
* point.
|
||||
*
|
||||
* When the operation is applied to linear polygons (that is, the value type of
|
||||
* the input iterator is either `Polygon_2` or `Polygon_with_holes_2`), the
|
||||
* kernel used to instantiate the type of the input polygons must support exact
|
||||
* predicates to guarantee correct results; however, inexact constructions are
|
||||
* tolerated.
|
||||
*
|
||||
* \param begin the first iterator of the input range. Its value type is
|
||||
* either `Polygon_2` (respectively `General_polygon_2`) or
|
||||
* `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
|
||||
|
|
@ -917,36 +854,16 @@ bool do_intersect(const General_polygon_with_holes_2<Polygon>& pgn1,
|
|||
template <typename InputIterator>
|
||||
bool do_intersect(InputIterator begin, InputIterator end);
|
||||
|
||||
/*! Given a range of polygons or a range of polygons with holes (respectively a range
|
||||
* of general polygons or a range of general polygons with holes) determines
|
||||
* whether the open polygons (respectively general polygons) in the range have a common
|
||||
* point.
|
||||
* \tparam UsePolylines determines whether the boundaries of the polygons in the
|
||||
* input range are treated as cyclic sequences of single
|
||||
* (\f$x\f$-monotone) segments or as a cyclic sequences of
|
||||
* (\f$x\f$-monotone) polylines. If substituted with `CGAL::Tag_true`,
|
||||
* which is the default, the input polygons are converted to general
|
||||
* polygon with holes , bounded by polylines before the operation is
|
||||
* actually performed. If substituted with `CGAL::Tag_false`, `pgn1` and
|
||||
* `pgn2` are used as is. Refer to \ref bso_ssectraits_sel for more
|
||||
* information.
|
||||
* \param begin the first iterator of the input range. Its value type is
|
||||
* either `Polygon_2` (respectively `General_polygon_2`) or
|
||||
* `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
|
||||
* \param end the past-the-end iterator of the input range. Its value type is
|
||||
* either `Polygon_2` (respectively `General_polygon_2`) or
|
||||
* `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
|
||||
* \return `true` if the pairwise intersections of all open polygons or polygons
|
||||
* with holes (respectively general polygons or general polygons with holes) in
|
||||
* the range [*begin,*end) overlap, and `false` otherwise.
|
||||
*/
|
||||
template <typename InputIterator, typename UsePolylines>
|
||||
bool do_intersect(InputIterator begin, InputIterator end,
|
||||
UsePolylines = Tag_true());
|
||||
|
||||
/*! Given a range of polygons (respectively general polygons) and a range of polygons
|
||||
* with holes (respectively general polygons with holes) determines whether the open
|
||||
* polygons (respectively general polygons) in the two ranges have a common point.
|
||||
*
|
||||
* When the operation is applied to linear polygons (that is, the value type of
|
||||
* any input iterator is either `Polygon_2` or `Polygon_with_holes_2`), the
|
||||
* kernel used to instantiate the type of the input polygons must support exact
|
||||
* predicates to guarantee correct results; however, inexact constructions are
|
||||
* tolerated.
|
||||
*
|
||||
* \param begin1 the first iterator of the 1st input range. Its value type is
|
||||
* `Polygon_2` (respectively `General_polygon_2`).
|
||||
* \param end1 the past-the-end iterator of the 1st input range. Its value
|
||||
|
|
@ -964,40 +881,14 @@ template <typename InputIterator1, typename InputIterator2>
|
|||
bool do_intersect(InputIterator1 begin1, InputIterator1 end1,
|
||||
InputIterator2 begin2, InputIterator2 end2);
|
||||
|
||||
/*! Given a range of polygons (respectively general polygons) and a range of polygons
|
||||
* with holes (respectively general polygons with holes) determines whether the open
|
||||
* polygons (respectively general polygons) in the two ranges have a common point.
|
||||
* \tparam UsePolylines determines whether the boundaries of the polygons in the
|
||||
* input ranges are treated as cyclic sequences of single
|
||||
* (\f$x\f$-monotone) segments or as a cyclic sequences of
|
||||
* (\f$x\f$-monotone) polylines. If substituted with `CGAL::Tag_true`,
|
||||
* which is the default, the input polygons are converted to general
|
||||
* polygon with holes , bounded by polylines before the operation is
|
||||
* actually performed. If substituted with `CGAL::Tag_false`, `pgn1` and
|
||||
* `pgn2` are used as is. Refer to \ref bso_ssectraits_sel for more
|
||||
* information.
|
||||
* \param begin1 the first iterator of the 1st input range. Its value type is
|
||||
* `Polygon_2` (respectively `General_polygon_2`).
|
||||
* \param end1 the past-the-end iterator of the 1st input range. Its value
|
||||
* type is `Polygon_2` (respectively `General_polygon_2`).
|
||||
* \param begin2 the first iterator of the 2nd input range. Its value type
|
||||
* is `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
|
||||
* \param end2 the past-the-end iterator of the 2nd input range. Its value
|
||||
* type is `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
|
||||
* \return `true` if the pairwise intersections of all open polygons (respectively
|
||||
* general polygons) and polygons with holes (respectively general polygons with
|
||||
* holes) in the ranges [*begin1,*end1) and [*begin2,*end2),
|
||||
* respectively, overlap, and `false` otherwise.
|
||||
*/
|
||||
template <typename InputIterator1, typename InputIterator2,
|
||||
typename UsePolylines>
|
||||
bool do_intersect(InputIterator1 begin1, InputIterator1 end1,
|
||||
InputIterator2 begin2, InputIterator2 end2,
|
||||
UsePolylines = Tag_true());
|
||||
|
||||
//////// With Traits
|
||||
|
||||
/*! determines whether two polygons intersect in their interior.
|
||||
*
|
||||
* The kernel used to instantiate the type of the input polygons must support
|
||||
* exact predicates to guarantee correct results; however, inexact constructions
|
||||
* are tolerated.
|
||||
*
|
||||
* \param pgn1 the 1st input polygon.
|
||||
* \param pgn2 the 2nd input polygon.
|
||||
* \param traits a traits object.
|
||||
|
|
@ -1011,6 +902,11 @@ bool do_intersect(const Polygon_2<Kernel, Container>& pgn1,
|
|||
const GpsTraits& traits);
|
||||
|
||||
/*! determines whether two polygons intersect in their interior.
|
||||
*
|
||||
* The kernel used to instantiate the type of the input polygons must support
|
||||
* exact predicates to guarantee correct results; however, inexact constructions
|
||||
* are tolerated.
|
||||
*
|
||||
* \param pgn1 the 1st input polygon.
|
||||
* \param pgn2 the 2nd input polygon.
|
||||
* \param traits a traits object.
|
||||
|
|
@ -1021,10 +917,14 @@ bool do_intersect(const Polygon_2<Kernel, Container>& pgn1,
|
|||
template <typename Kernel, typename Container, typename GpsTraits>
|
||||
bool do_intersect(const Polygon_2<Kernel, Container>& pgn1,
|
||||
const Polygon_with_holes_2<Kernel, Container>& pgn2,
|
||||
const GpsTraits& traits,
|
||||
const GpsTraits& traits);
|
||||
|
||||
/*! determines whether two polygons intersect in their interior.
|
||||
*
|
||||
* The kernel used to instantiate the type of the input polygons must support
|
||||
* exact predicates to guarantee correct results; however, inexact constructions
|
||||
* are tolerated.
|
||||
*
|
||||
* \param pgn1 the 1st input polygon.
|
||||
* \param pgn2 the 2nd input polygon.
|
||||
* \param traits a traits object.
|
||||
|
|
@ -1038,6 +938,11 @@ bool do_intersect(const Polygon_with_holes_2<Kernel, Container>& pgn1,
|
|||
const GpsTraits& traits);
|
||||
|
||||
/*! determines whether two polygons with holes intersect in their interior.
|
||||
*
|
||||
* The kernel used to instantiate the type of the input polygons must support
|
||||
* exact predicates to guarantee correct results; however, inexact constructions
|
||||
* are tolerated.
|
||||
*
|
||||
* \param pgn1 the 1st input polygon.
|
||||
* \param pgn2 the 2nd input polygon.
|
||||
* \param traits a traits object.
|
||||
|
|
@ -1116,6 +1021,12 @@ bool do_intersect(const General_polygon_with_holes_2<Polygon>& pgn1,
|
|||
* of general polygons or a range of general polygons with holes) determines
|
||||
* whether the open polygons (respectively general polygons) in the range have a common
|
||||
* point.
|
||||
*
|
||||
* When the operation is applied to linear polygons (that is, the value type of
|
||||
* the input iterator is either `Polygon_2` or `Polygon_with_holes_2`), the
|
||||
* traits parameter `GpsTraits` must support exact predicates to guarantee
|
||||
* correct results; however, inexact constructions are tolerated.
|
||||
*
|
||||
* \param begin the first iterator of the input range. Its value type is
|
||||
* either `Polygon_2` (respectively `General_polygon_2`) or
|
||||
* `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
|
||||
|
|
@ -1135,6 +1046,12 @@ bool do_intersect(InputIterator begin, InputIterator end,
|
|||
/*! Given a range of polygons (respectively general polygons) and a range of polygons
|
||||
* with holes (respectively general polygons with holes) determines whether the open
|
||||
* polygons (respectively general polygons) in the two ranges have a common point.
|
||||
*
|
||||
* When the operation is applied to linear polygons (that is, the value type of
|
||||
* any input iterator is either `Polygon_2` or `Polygon_with_holes_2`), the
|
||||
* traits parameter `GpsTraits` must support exact predicates to guarantee
|
||||
* correct results; however, inexact constructions are tolerated.
|
||||
*
|
||||
* \param begin1 the first iterator of the 1st input range. Its value type is
|
||||
* `Polygon_2` (respectively `General_polygon_2`).
|
||||
* \param end1 the past-the-end iterator of the 1st input range. Its value
|
||||
|
|
@ -1186,6 +1103,10 @@ namespace CGAL {
|
|||
* <tr><td align="right"><b>6.</b></td><td>`OutputIterator intersection(InputIterator1 begin1, InputIterator1 end1, InputIterator2 begin2, InputIterator2 end2, OutputIterator oi, const GpsTraits& traits);`</td></tr>
|
||||
* </table>
|
||||
*
|
||||
* \tparam Kernel a model of the concept `PolygonTraits_2`.
|
||||
* \tparam Container a model of the concept `Container`; defaults to `std::vector<Kernel::Point_2`>.
|
||||
* \tparam ArrTraits a model of the concept `AosDirectionalXMonotoneTraits_2`.
|
||||
* \tparam GpsTraits a model of the concept `GeneralPolygonSetTraits_2`, which must be convertible to `ArrTraits`.
|
||||
* \tparam UsePolylines determines whether the boundaries of the input polygons
|
||||
* are treated as cyclic sequences of single (\f$x\f$-monotone) segments or as
|
||||
* cyclic sequences of (\f$x\f$-monotone) polylines. If substituted with
|
||||
|
|
@ -1244,6 +1165,8 @@ namespace CGAL {
|
|||
* \sa \link boolean_join `CGAL::join()` \endlink
|
||||
* \sa \link boolean_difference `CGAL::difference()` \endlink
|
||||
* \sa \link boolean_symmetric_difference `CGAL::symmetric_difference()` \endlink
|
||||
* \sa Polygon_2<Kernel, Container>
|
||||
* \sa Polygon_with_holes_2<Kernel, Container>
|
||||
*/
|
||||
|
||||
/// @{
|
||||
|
|
@ -1825,6 +1748,10 @@ namespace CGAL {
|
|||
* <tr><td align="right"><b>6.</b></td><td>`OutputIterator join(InputIterator1 begin1, InputIterator1 end1, InputIterator2 begin2, InputIterator2 end2, OutputIterator oi, const GpsTraits& traits);`</td></tr>
|
||||
* </table>
|
||||
*
|
||||
* \tparam Kernel a model of the concept `PolygonTraits_2`.
|
||||
* \tparam Container a model of the concept `Container`; defaults to `std::vector<Kernel::Point_2`>.
|
||||
* \tparam ArrTraits a model of the concept `AosDirectionalXMonotoneTraits_2`.
|
||||
* \tparam GpsTraits a model of the concept `GeneralPolygonSetTraits_2`, which must be convertible to `ArrTraits`.
|
||||
* \tparam UsePolylines determines whether the boundaries of the input polygons
|
||||
* are treated as cyclic sequences of single (\f$x\f$-monotone) segments or as
|
||||
* cyclic sequences of (\f$x\f$-monotone) polylines. If substituted with
|
||||
|
|
@ -1882,6 +1809,8 @@ namespace CGAL {
|
|||
* \sa \link boolean_intersection `CGAL::intersection()` \endlink
|
||||
* \sa \link boolean_difference `CGAL::difference()` \endlink
|
||||
* \sa \link boolean_symmetric_difference `CGAL::symmetric_difference()` \endlink
|
||||
* \sa Polygon_2<Kernel, Container>
|
||||
* \sa Polygon_with_holes_2<Kernel, Container>
|
||||
*/
|
||||
|
||||
/// @{
|
||||
|
|
@ -2407,6 +2336,10 @@ namespace CGAL {
|
|||
* <tr><td align="right"><b> 4.</b></td><td>`Oriented_side oriented_side(const Point_2& p, const Type& pgn, const GpsTraits& traits);`</td></tr>
|
||||
* </table>
|
||||
*
|
||||
* \tparam Kernel a model of the concept `PolygonTraits_2`.
|
||||
* \tparam Container a model of the concept `Container`; defaults to `std::vector<Kernel::Point_2`>.
|
||||
* \tparam ArrTraits a model of the concept `AosDirectionalXMonotoneTraits_2`.
|
||||
* \tparam GpsTraits a model of the concept `GeneralPolygonSetTraits_2`, which must be convertible to `ArrTraits`.
|
||||
* \tparam UsePolylines determines whether the boundaries of the input polygons
|
||||
* are treated as cyclic sequences of single (\f$x\f$-monotone) segments or as
|
||||
* cyclic sequences of (\f$x\f$-monotone) polylines. If substituted with
|
||||
|
|
@ -2446,6 +2379,8 @@ namespace CGAL {
|
|||
* \param traits an optional traits object.
|
||||
*
|
||||
* \sa \link boolean_do_intersect `CGAL::do_intersect()` \endlink
|
||||
* \sa Polygon_2<Kernel, Container>
|
||||
* \sa Polygon_with_holes_2<Kernel, Container>
|
||||
*/
|
||||
|
||||
/// @{
|
||||
|
|
@ -2823,6 +2758,10 @@ namespace CGAL {
|
|||
* <tr><td align="right"><b>6.</b></td><td>`OutputIterator symmetric_difference(InputIterator1 begin1, InputIterator1 end1, InputIterator2 begin2, InputIterator2 end2, OutputIterator oi, const GpsTraits& traits);`</td></tr>
|
||||
* </table>
|
||||
*
|
||||
* \tparam Kernel a model of the concept `PolygonTraits_2`.
|
||||
* \tparam Container a model of the concept `Container`; defaults to `std::vector<Kernel::Point_2`>.
|
||||
* \tparam ArrTraits a model of the concept `AosDirectionalXMonotoneTraits_2`.
|
||||
* \tparam GpsTraits a model of the concept `GeneralPolygonSetTraits_2`, which must be convertible to `ArrTraits`.
|
||||
* \tparam UsePolylines determines whether the boundaries of the input polygons
|
||||
* are treated as cyclic sequences of single (\f$x\f$-monotone) segments or as
|
||||
* cyclic sequences of (\f$x\f$-monotone) polylines. If substituted with
|
||||
|
|
@ -2879,6 +2818,8 @@ namespace CGAL {
|
|||
* \sa \link boolean_intersection `CGAL::intersection()` \endlink
|
||||
* \sa \link boolean_join `CGAL::join()` \endlink
|
||||
* \sa \link boolean_difference `CGAL::difference()` \endlink
|
||||
* \sa Polygon_2<Kernel, Container>
|
||||
* \sa Polygon_with_holes_2<Kernel, Container>
|
||||
*/
|
||||
|
||||
/// @{
|
||||
|
|
|
|||
|
|
@ -5,27 +5,26 @@
|
|||
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
|
||||
#include <CGAL/Boolean_set_operations_2.h>
|
||||
|
||||
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
|
||||
typedef Kernel::Point_2 Point_2;
|
||||
typedef CGAL::Polygon_2<Kernel> Polygon_2;
|
||||
using Kernel = CGAL::Exact_predicates_exact_constructions_kernel;
|
||||
using Point_2 = Kernel::Point_2;
|
||||
using Polygon_2 = CGAL::Polygon_2<Kernel>;
|
||||
|
||||
#include "print_utils.h"
|
||||
|
||||
int main ()
|
||||
{
|
||||
int main() {
|
||||
Polygon_2 P;
|
||||
P.push_back (Point_2 (-1,1));
|
||||
P.push_back (Point_2 (0,-1));
|
||||
P.push_back (Point_2 (1,1));
|
||||
std::cout << "P = "; print_polygon (P);
|
||||
P.push_back(Point_2(-1, 1));
|
||||
P.push_back(Point_2(0, -1));
|
||||
P.push_back(Point_2(1, 1));
|
||||
std::cout << "P = "; print_polygon(P);
|
||||
|
||||
Polygon_2 Q;
|
||||
Q.push_back(Point_2 (-1,-1));
|
||||
Q.push_back(Point_2 (1,-1));
|
||||
Q.push_back(Point_2 (0,1));
|
||||
std::cout << "Q = "; print_polygon (Q);
|
||||
Q.push_back(Point_2(-1, -1));
|
||||
Q.push_back(Point_2(1, -1));
|
||||
Q.push_back(Point_2(0, 1));
|
||||
std::cout << "Q = "; print_polygon(Q);
|
||||
|
||||
if ((CGAL::do_intersect (P, Q)))
|
||||
if ((CGAL::do_intersect(P, Q)))
|
||||
std::cout << "The two polygons intersect in their interior." << std::endl;
|
||||
else
|
||||
std::cout << "The two polygons do not intersect." << std::endl;
|
||||
|
|
|
|||
|
|
@ -8,10 +8,10 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
//
|
||||
// Author(s): Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ron Wein <wein@post.tau.ac.il>
|
||||
// Efi Fogel <efif@post.tau.ac.il>
|
||||
// Simon Giraudot <simon.giraudot@geometryfactory.com>
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ron Wein <wein@post.tau.ac.il>
|
||||
// Efi Fogel <efif@post.tau.ac.il>
|
||||
// Simon Giraudot <simon.giraudot@geometryfactory.com>
|
||||
|
||||
#ifndef CGAL_BSO_INTERNAL_FUNCTIONS_H
|
||||
#define CGAL_BSO_INTERNAL_FUNCTIONS_H
|
||||
|
|
@ -33,7 +33,7 @@ namespace CGAL {
|
|||
|
||||
// Single
|
||||
// With Traits
|
||||
template <typename Pgn1, class Pgn2, typename Traits>
|
||||
template <typename Pgn1, typename Pgn2, typename Traits>
|
||||
inline bool s_do_intersect(const Pgn1& pgn1, const Pgn2& pgn2, Traits& traits) {
|
||||
General_polygon_set_2<Traits> gps(pgn1, traits);
|
||||
return gps.do_intersect(pgn2);
|
||||
|
|
@ -52,7 +52,7 @@ inline bool s_do_intersect(const Pgn1& pgn1, const Pgn2& pgn2) {
|
|||
// With Traits
|
||||
template <typename InputIterator, typename Traits>
|
||||
inline bool r_do_intersect(InputIterator begin, InputIterator end,
|
||||
Traits& traits, unsigned int k=5) {
|
||||
Traits& traits, std::size_t k = 5) {
|
||||
if (begin == end) return false;
|
||||
General_polygon_set_2<Traits> gps(*begin, traits);
|
||||
return gps.do_intersect(std::next(begin), end, k);
|
||||
|
|
@ -61,8 +61,8 @@ inline bool r_do_intersect(InputIterator begin, InputIterator end,
|
|||
// Without Traits
|
||||
template <typename InputIterator>
|
||||
inline bool r_do_intersect(InputIterator begin, InputIterator end,
|
||||
unsigned int k=5) {
|
||||
typedef typename std::iterator_traits<InputIterator>::value_type Pgn;
|
||||
std::size_t k = 5) {
|
||||
using Pgn = typename std::iterator_traits<InputIterator>::value_type;
|
||||
typename Gps_polyline_traits<Pgn>::Traits traits;
|
||||
const typename Gps_polyline_traits<Pgn>::Polyline_traits& ptraits(traits);
|
||||
return r_do_intersect(convert_polygon_iterator(begin, ptraits),
|
||||
|
|
@ -74,7 +74,7 @@ inline bool r_do_intersect(InputIterator begin, InputIterator end,
|
|||
template <typename InputIterator1, typename InputIterator2, typename Traits>
|
||||
inline bool r_do_intersect(InputIterator1 begin1, InputIterator1 end1,
|
||||
InputIterator2 begin2, InputIterator2 end2,
|
||||
Traits& traits, unsigned int k=5) {
|
||||
Traits& traits, std::size_t k = 5) {
|
||||
if (begin1 == end1) return do_intersect(begin2, end2, traits, k);
|
||||
General_polygon_set_2<Traits> gps(*begin1, traits);
|
||||
return gps.do_intersect(std::next(begin1), end1, begin2, end2, k);
|
||||
|
|
@ -84,8 +84,8 @@ inline bool r_do_intersect(InputIterator1 begin1, InputIterator1 end1,
|
|||
template <typename InputIterator1, typename InputIterator2>
|
||||
inline bool r_do_intersect (InputIterator1 begin1, InputIterator1 end1,
|
||||
InputIterator2 begin2, InputIterator2 end2,
|
||||
unsigned int k=5) {
|
||||
typedef typename std::iterator_traits<InputIterator1>::value_type Pgn;
|
||||
std::size_t k = 5) {
|
||||
using Pgn = typename std::iterator_traits<InputIterator1>::value_type;
|
||||
typename Gps_polyline_traits<Pgn>::Traits traits;
|
||||
const typename Gps_polyline_traits<Pgn>::Polyline_traits& ptraits(traits);
|
||||
return r_do_intersect(convert_polygon_iterator(begin1, ptraits),
|
||||
|
|
@ -119,8 +119,7 @@ inline Oriented_side _oriented_side(const Point_2<Kernel>& point,
|
|||
|
||||
// Without Traits (polygon, polygon)
|
||||
template <typename Pgn1, typename Pgn2>
|
||||
inline Oriented_side _oriented_side(const Pgn1& pgn1, const Pgn2& pgn2)
|
||||
{
|
||||
inline Oriented_side _oriented_side(const Pgn1& pgn1, const Pgn2& pgn2) {
|
||||
// Use the first polygon to determine the (default) traits
|
||||
typename Gps_polyline_traits<Pgn1>::Traits traits;
|
||||
const typename Gps_polyline_traits<Pgn1>::Polyline_traits& ptraits(traits);
|
||||
|
|
@ -149,7 +148,7 @@ template <typename Kernel, typename Container,
|
|||
inline OutputIterator s_intersection(const Pgn1& pgn1, const Pgn2& pgn2,
|
||||
OutputIterator oi) {
|
||||
// Use the first polygon to determine the (default) traits
|
||||
typedef typename Gps_polyline_traits<Pgn1>::Polyline_traits Polyline_traits;
|
||||
using Polyline_traits = typename Gps_polyline_traits<Pgn1>::Polyline_traits;
|
||||
|
||||
typename Gps_polyline_traits<Pgn1>::Traits traits;
|
||||
const Polyline_traits& ptraits(traits);
|
||||
|
|
@ -163,7 +162,7 @@ inline OutputIterator s_intersection(const Pgn1& pgn1, const Pgn2& pgn2,
|
|||
template <typename InputIterator, typename OutputIterator, typename Traits>
|
||||
inline OutputIterator r_intersection(InputIterator begin, InputIterator end,
|
||||
OutputIterator oi, Traits& traits,
|
||||
unsigned int k=5) {
|
||||
std::size_t k = 5) {
|
||||
if (begin == end) return (oi);
|
||||
General_polygon_set_2<Traits> gps(*begin, traits);
|
||||
gps.intersection(std::next(begin), end, k);
|
||||
|
|
@ -173,8 +172,8 @@ inline OutputIterator r_intersection(InputIterator begin, InputIterator end,
|
|||
// Without Traits
|
||||
template <typename InputIterator, typename OutputIterator>
|
||||
inline OutputIterator r_intersection(InputIterator begin, InputIterator end,
|
||||
OutputIterator oi, unsigned int k=5) {
|
||||
typedef typename std::iterator_traits<InputIterator>::value_type Pgn;
|
||||
OutputIterator oi, std::size_t k = 5) {
|
||||
using Pgn = typename std::iterator_traits<InputIterator>::value_type;
|
||||
typename Gps_polyline_traits<Pgn>::Traits traits;
|
||||
const typename Gps_polyline_traits<Pgn>::Polyline_traits& ptraits(traits);
|
||||
if (begin == end) return (oi);
|
||||
|
|
@ -190,7 +189,7 @@ template <typename InputIterator1, typename InputIterator2,
|
|||
inline OutputIterator r_intersection(InputIterator1 begin1, InputIterator1 end1,
|
||||
InputIterator2 begin2, InputIterator2 end2,
|
||||
OutputIterator oi, Traits& traits,
|
||||
unsigned int k=5) {
|
||||
std::size_t k = 5) {
|
||||
if (begin1 == end1) return r_intersection(begin2, end2, oi, traits, k);
|
||||
General_polygon_set_2<Traits> gps(*begin1, traits);
|
||||
gps.intersection(std::next(begin1), end1, begin2, end2, k);
|
||||
|
|
@ -203,8 +202,8 @@ template <typename InputIterator1, typename InputIterator2,
|
|||
inline OutputIterator
|
||||
r_intersection(InputIterator1 begin1, InputIterator1 end1,
|
||||
InputIterator2 begin2, InputIterator2 end2,
|
||||
OutputIterator oi, unsigned int k=5) {
|
||||
typedef typename std::iterator_traits<InputIterator1>::value_type Pgn;
|
||||
OutputIterator oi, std::size_t k = 5) {
|
||||
using Pgn = typename std::iterator_traits<InputIterator1>::value_type;
|
||||
typename Gps_polyline_traits<Pgn>::Traits traits;
|
||||
const typename Gps_polyline_traits<Pgn>::Polyline_traits& ptraits(traits);
|
||||
if (begin1 == end1) {
|
||||
|
|
@ -228,7 +227,7 @@ r_intersection(InputIterator1 begin1, InputIterator1 end1,
|
|||
// Polygon_2
|
||||
template <typename Traits>
|
||||
inline bool _is_empty(const typename Traits::Polygon_2& pgn, Traits& traits) {
|
||||
typedef typename Traits::Curve_const_iterator Curve_const_iterator;
|
||||
using Curve_const_iterator = typename Traits::Curve_const_iterator;
|
||||
const std::pair<Curve_const_iterator, Curve_const_iterator>& itr_pair =
|
||||
traits.construct_curves_2_object()(pgn);
|
||||
return (itr_pair.first == itr_pair.second);
|
||||
|
|
@ -268,9 +267,9 @@ template <typename Kernel, typename Container,
|
|||
typename Pgn1, typename Pgn2, typename Pwh>
|
||||
inline bool s_join(const Pgn1& pgn1, const Pgn2& pgn2, Pwh& pwh) {
|
||||
// Use the first polygon to determine the (default) traits
|
||||
typedef typename Gps_polyline_traits<Pgn1>::Polyline_traits Polyline_traits;
|
||||
typedef General_polygon_2<Polyline_traits> General_pgn;
|
||||
typedef General_polygon_with_holes_2<General_pgn> General_pwh;
|
||||
using Polyline_traits = typename Gps_polyline_traits<Pgn1>::Polyline_traits;
|
||||
using General_pgn = General_polygon_2<Polyline_traits>;
|
||||
using General_pwh = General_polygon_with_holes_2<General_pgn>;
|
||||
|
||||
General_pwh general_pwh;
|
||||
typename Gps_polyline_traits<Pgn1>::Traits traits;
|
||||
|
|
@ -287,7 +286,7 @@ inline bool s_join(const Pgn1& pgn1, const Pgn2& pgn2, Pwh& pwh) {
|
|||
template <typename InputIterator, typename OutputIterator, typename Traits>
|
||||
inline OutputIterator r_join(InputIterator begin, InputIterator end,
|
||||
OutputIterator oi, Traits& traits,
|
||||
unsigned int k=5) {
|
||||
std::size_t k = 5) {
|
||||
if (begin == end) return oi;
|
||||
General_polygon_set_2<Traits> gps(*begin, traits);
|
||||
gps.join(std::next(begin), end, k);
|
||||
|
|
@ -297,8 +296,8 @@ inline OutputIterator r_join(InputIterator begin, InputIterator end,
|
|||
// Without traits
|
||||
template <typename InputIterator, typename OutputIterator>
|
||||
inline OutputIterator r_join(InputIterator begin, InputIterator end,
|
||||
OutputIterator oi, unsigned int k=5) {
|
||||
typedef typename std::iterator_traits<InputIterator>::value_type Pgn;
|
||||
OutputIterator oi, std::size_t k = 5) {
|
||||
using Pgn = typename std::iterator_traits<InputIterator>::value_type;
|
||||
typename Gps_polyline_traits<Pgn>::Traits traits;
|
||||
const typename Gps_polyline_traits<Pgn>::Polyline_traits& ptraits(traits);
|
||||
|
||||
|
|
@ -316,7 +315,7 @@ template <typename InputIterator1, typename InputIterator2,
|
|||
inline OutputIterator r_join(InputIterator1 begin1, InputIterator1 end1,
|
||||
InputIterator2 begin2, InputIterator2 end2,
|
||||
OutputIterator oi, Traits& traits,
|
||||
unsigned int k=5) {
|
||||
std::size_t k = 5) {
|
||||
if (begin1 == end1) return r_join(begin2, end2, oi, traits, k);
|
||||
General_polygon_set_2<Traits> gps(*begin1, traits);
|
||||
gps.join(std::next(begin1), end1, begin2, end2, k);
|
||||
|
|
@ -328,8 +327,8 @@ template <typename InputIterator1, typename InputIterator2,
|
|||
typename OutputIterator>
|
||||
inline OutputIterator r_join(InputIterator1 begin1, InputIterator1 end1,
|
||||
InputIterator2 begin2, InputIterator2 end2,
|
||||
OutputIterator oi, unsigned int k=5) {
|
||||
typedef typename std::iterator_traits<InputIterator1>::value_type Pgn;
|
||||
OutputIterator oi, std::size_t k = 5) {
|
||||
using Pgn = typename std::iterator_traits<InputIterator1>::value_type;
|
||||
typename Gps_polyline_traits<Pgn>::Traits traits;
|
||||
const typename Gps_polyline_traits<Pgn>::Polyline_traits& ptraits(traits);
|
||||
if (begin1 == end1) {
|
||||
|
|
@ -361,10 +360,9 @@ inline OutputIterator _difference(const Pgn1& pgn1, const Pgn2& pgn2,
|
|||
template <typename Kernel, typename Container,
|
||||
typename Pgn1, typename Pgn2, typename OutputIterator>
|
||||
inline OutputIterator _difference(const Pgn1& pgn1, const Pgn2& pgn2,
|
||||
OutputIterator oi)
|
||||
{
|
||||
OutputIterator oi) {
|
||||
// Use the first polygon to determine the (default) traits
|
||||
typedef typename Gps_polyline_traits<Pgn1>::Polyline_traits Polyline_traits;
|
||||
using Polyline_traits = typename Gps_polyline_traits<Pgn1>::Polyline_traits;
|
||||
|
||||
typename Gps_polyline_traits<Pgn1>::Traits traits;
|
||||
const Polyline_traits& ptraits(traits);
|
||||
|
|
@ -394,7 +392,7 @@ template <typename Kernel, typename Container,
|
|||
inline OutputIterator s_symmetric_difference(const Pgn1& pgn1, const Pgn2& pgn2,
|
||||
OutputIterator oi) {
|
||||
// Use the first polygon to determine the (default) traits
|
||||
typedef typename Gps_polyline_traits<Pgn1>::Polyline_traits Polyline_traits;
|
||||
using Polyline_traits = typename Gps_polyline_traits<Pgn1>::Polyline_traits;
|
||||
typename Gps_polyline_traits<Pgn1>::Traits traits;
|
||||
const Polyline_traits& ptraits(traits);
|
||||
s_symmetric_difference(convert_polygon(pgn1, ptraits),
|
||||
|
|
@ -409,7 +407,7 @@ template <typename InputIterator, typename OutputIterator, typename Traits>
|
|||
inline
|
||||
OutputIterator r_symmetric_difference(InputIterator begin, InputIterator end,
|
||||
OutputIterator oi, Traits& traits,
|
||||
unsigned int k=5) {
|
||||
std::size_t k = 5) {
|
||||
if (begin == end) return (oi);
|
||||
General_polygon_set_2<Traits> gps(*begin, traits);
|
||||
gps.symmetric_difference(std::next(begin), end, k);
|
||||
|
|
@ -421,9 +419,8 @@ template <typename InputIterator, typename OutputIterator>
|
|||
inline OutputIterator r_symmetric_difference(InputIterator begin,
|
||||
InputIterator end,
|
||||
OutputIterator oi,
|
||||
unsigned int k=5)
|
||||
{
|
||||
typedef typename std::iterator_traits<InputIterator>::value_type Pgn;
|
||||
std::size_t k = 5) {
|
||||
using Pgn = typename std::iterator_traits<InputIterator>::value_type;
|
||||
typename Gps_polyline_traits<Pgn>::Traits traits;
|
||||
const typename Gps_polyline_traits<Pgn>::Polyline_traits& ptraits(traits);
|
||||
if (begin == end) return (oi);
|
||||
|
|
@ -441,8 +438,7 @@ inline OutputIterator r_symmetric_difference(InputIterator1 begin1,
|
|||
InputIterator2 begin2,
|
||||
InputIterator2 end2,
|
||||
OutputIterator oi, Traits& traits,
|
||||
unsigned int k=5)
|
||||
{
|
||||
std::size_t k = 5) {
|
||||
if (begin1 == end1) return r_symmetric_difference(begin2, end2, oi, traits, k);
|
||||
General_polygon_set_2<Traits> gps(*begin1, traits);
|
||||
gps.symmetric_difference(std::next(begin1), end1, begin2, end2, k);
|
||||
|
|
@ -457,8 +453,8 @@ inline OutputIterator r_symmetric_difference(InputIterator1 begin1,
|
|||
InputIterator2 begin2,
|
||||
InputIterator2 end2,
|
||||
OutputIterator oi,
|
||||
unsigned int k=5) {
|
||||
typedef typename std::iterator_traits<InputIterator1>::value_type Pgn;
|
||||
std::size_t k = 5) {
|
||||
using Pgn = typename std::iterator_traits<InputIterator1>::value_type;
|
||||
typename Gps_polyline_traits<Pgn>::Traits traits;
|
||||
const typename Gps_polyline_traits<Pgn>::Polyline_traits& ptraits(traits);
|
||||
if (begin1 == end1){
|
||||
|
|
@ -522,10 +518,10 @@ OutputIterator _complement(const General_polygon_with_holes_2<Pgn>& pgn,
|
|||
template <typename Kernel, typename Container, typename Pwh>
|
||||
void _complement(const Polygon_2<Kernel, Container>& pgn, Pwh& pwh) {
|
||||
// Use the polygon to determine the (default) traits
|
||||
typedef Polygon_2<Kernel, Container> Pgn;
|
||||
typedef typename Gps_polyline_traits<Pgn>::Polyline_traits Polyline_traits;
|
||||
typedef General_polygon_2<Polyline_traits> General_pgn;
|
||||
typedef General_polygon_with_holes_2<General_pgn> General_pwh;
|
||||
using Pgn = Polygon_2<Kernel, Container>;
|
||||
using Polyline_traits = typename Gps_polyline_traits<Pgn>::Polyline_traits;
|
||||
using General_pgn = General_polygon_2<Polyline_traits>;
|
||||
using General_pwh = General_polygon_with_holes_2<General_pgn>;
|
||||
|
||||
General_pwh general_pwh;
|
||||
typename Gps_polyline_traits<Pgn>::Traits traits;
|
||||
|
|
@ -539,8 +535,8 @@ template <typename Kernel, typename Container, typename OutputIterator>
|
|||
OutputIterator _complement(const Polygon_with_holes_2<Kernel, Container>& pgn,
|
||||
OutputIterator oi) {
|
||||
// Use the polygon with holes to determine the (default) traits
|
||||
typedef Polygon_with_holes_2<Kernel, Container> Pgn;
|
||||
typedef typename Gps_polyline_traits<Pgn>::Polyline_traits Polyline_traits;
|
||||
using Pgn = Polygon_with_holes_2<Kernel, Container>;
|
||||
using Polyline_traits = typename Gps_polyline_traits<Pgn>::Polyline_traits;
|
||||
|
||||
typename Gps_polyline_traits<Pgn>::Traits traits;
|
||||
const Polyline_traits& ptraits(traits);
|
||||
|
|
|
|||
|
|
@ -7,12 +7,11 @@
|
|||
// $Id$
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
//
|
||||
// Author(s): Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Efi Fogel <efifogel@gmail.com>
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Efi Fogel <efifogel@gmail.com>
|
||||
|
||||
#ifndef CGAL_BSO_2_GPS_AGG_META_TRAITS_H
|
||||
#define CGAL_BSO_2_GPS_AGG_META_TRAITS_H
|
||||
#ifndef CGAL_GPS_AGG_META_TRAITS_H
|
||||
#define CGAL_GPS_AGG_META_TRAITS_H
|
||||
|
||||
#include <CGAL/license/Boolean_set_operations_2.h>
|
||||
|
||||
|
|
@ -24,18 +23,17 @@
|
|||
namespace CGAL {
|
||||
|
||||
template <typename Arrangement_>
|
||||
class Gps_agg_curve_data : public Curve_with_halfedge<Arrangement_>
|
||||
{
|
||||
class Gps_agg_curve_data : public Curve_with_halfedge<Arrangement_> {
|
||||
protected:
|
||||
typedef Arrangement_ Arrangement;
|
||||
typedef typename Arrangement::Halfedge_handle Halfedge_handle;
|
||||
typedef Curve_with_halfedge<Arrangement_> Base;
|
||||
using Arrangement = Arrangement_;
|
||||
using Halfedge_handle = typename Arrangement::Halfedge_handle;
|
||||
using Base = Curve_with_halfedge<Arrangement_>;
|
||||
|
||||
const Arrangement* m_arr; // pointer to the arrangement containing the edge.
|
||||
unsigned int m_bc; // the boundary counter of the halfedge with the same
|
||||
std::size_t m_bc; // the boundary counter of the halfedge with the same
|
||||
// direction as the curve
|
||||
|
||||
unsigned int m_twin_bc; // the boundary counter of the halfedge with the same
|
||||
std::size_t m_twin_bc; // the boundary counter of the halfedge with the same
|
||||
// direction as the curve
|
||||
|
||||
public:
|
||||
|
|
@ -47,24 +45,24 @@ public:
|
|||
{}
|
||||
|
||||
Gps_agg_curve_data(const Arrangement* arr, Halfedge_handle he,
|
||||
unsigned int bc, unsigned int twin_bc) :
|
||||
std::size_t bc, std::size_t twin_bc) :
|
||||
Base(he),
|
||||
m_arr(arr),
|
||||
m_bc(bc),
|
||||
m_twin_bc(twin_bc)
|
||||
{}
|
||||
|
||||
unsigned int bc() const { return m_bc; }
|
||||
std::size_t bc() const { return m_bc; }
|
||||
|
||||
unsigned int twin_bc() const { return m_twin_bc; }
|
||||
std::size_t twin_bc() const { return m_twin_bc; }
|
||||
|
||||
unsigned int& bc() { return m_bc; }
|
||||
std::size_t& bc() { return m_bc; }
|
||||
|
||||
unsigned int& twin_bc() { return m_twin_bc; }
|
||||
std::size_t& twin_bc() { return m_twin_bc; }
|
||||
|
||||
void set_bc(unsigned int bc) { m_bc = bc; }
|
||||
void set_bc(std::size_t bc) { m_bc = bc; }
|
||||
|
||||
void set_twin_bc(unsigned int twin_bc) { m_twin_bc = twin_bc; }
|
||||
void set_twin_bc(std::size_t twin_bc) { m_twin_bc = twin_bc; }
|
||||
|
||||
const Arrangement* arr() const { return m_arr; }
|
||||
};
|
||||
|
|
@ -73,54 +71,50 @@ template <typename Arrangement_>
|
|||
class Gps_agg_meta_traits :
|
||||
public Gps_traits_decorator<typename Arrangement_::Traits_adaptor_2,
|
||||
Gps_agg_curve_data<Arrangement_>,
|
||||
Point_with_vertex<Arrangement_> >
|
||||
{
|
||||
typedef Arrangement_ Arrangement;
|
||||
typedef Arrangement Arr;
|
||||
Point_with_vertex<Arrangement_>> {
|
||||
using Arrangement = Arrangement_;
|
||||
using Arr = Arrangement;
|
||||
|
||||
typedef typename Arr::Traits_adaptor_2 Traits;
|
||||
typedef Traits Gt2;
|
||||
using Traits = typename Arr::Traits_adaptor_2;
|
||||
using Gt2 = Traits;
|
||||
|
||||
typedef typename Gt2::X_monotone_curve_2 Base_x_monotone_curve_2;
|
||||
typedef typename Gt2::Point_2 Base_point_2;
|
||||
typedef typename Gt2::Construct_min_vertex_2 Base_Construct_min_vertex_2;
|
||||
typedef typename Gt2::Construct_max_vertex_2 Base_Construct_max_vertex_2;
|
||||
typedef typename Gt2::Compare_endpoints_xy_2 Base_Compare_endpoints_xy_2;
|
||||
typedef typename Gt2::Compare_xy_2 Base_Compare_xy_2;
|
||||
typedef typename Gt2::Compare_y_at_x_right_2 Base_Compare_y_at_x_right_2;
|
||||
typedef typename Gt2::Compare_y_at_x_2 Base_Compare_y_at_x_2;
|
||||
typedef typename Gt2::Intersect_2 Base_Intersect_2;
|
||||
typedef typename Gt2::Split_2 Base_Split_2;
|
||||
using Base_x_monotone_curve_2 = typename Gt2::X_monotone_curve_2;
|
||||
using Base_point_2 = typename Gt2::Point_2;
|
||||
using Base_Construct_min_vertex_2 = typename Gt2::Construct_min_vertex_2;
|
||||
using Base_Construct_max_vertex_2 = typename Gt2::Construct_max_vertex_2;
|
||||
using Base_Compare_endpoints_xy_2 = typename Gt2::Compare_endpoints_xy_2;
|
||||
using Base_Compare_xy_2 = typename Gt2::Compare_xy_2;
|
||||
using Base_Compare_y_at_x_right_2 = typename Gt2::Compare_y_at_x_right_2;
|
||||
using Base_Compare_y_at_x_2 = typename Gt2::Compare_y_at_x_2;
|
||||
using Base_Intersect_2 = typename Gt2::Intersect_2;
|
||||
using Base_Split_2 = typename Gt2::Split_2;
|
||||
|
||||
typedef typename Gt2::Parameter_space_in_x_2 Base_Parameter_space_in_x_2;
|
||||
typedef typename Gt2::Compare_y_near_boundary_2
|
||||
Base_Compare_y_near_boundary_2;
|
||||
using Base_Parameter_space_in_x_2 = typename Gt2::Parameter_space_in_x_2;
|
||||
using Base_Compare_y_near_boundary_2 = typename Gt2::Compare_y_near_boundary_2;
|
||||
|
||||
typedef typename Gt2::Parameter_space_in_y_2 Base_Parameter_space_in_y_2;
|
||||
typedef typename Gt2::Compare_x_near_boundary_2
|
||||
Base_Compare_x_near_boundary_2;
|
||||
using Base_Parameter_space_in_y_2 = typename Gt2::Parameter_space_in_y_2;
|
||||
using Base_Compare_x_near_boundary_2 = typename Gt2::Compare_x_near_boundary_2;
|
||||
|
||||
public:
|
||||
typedef typename Gt2::Multiplicity Multiplicity;
|
||||
typedef Gps_agg_curve_data<Arr> Curve_data;
|
||||
typedef Point_with_vertex<Arr> Point_data;
|
||||
using Multiplicity = typename Gt2::Multiplicity;
|
||||
using Curve_data = Gps_agg_curve_data<Arr>;
|
||||
using Point_data = Point_with_vertex<Arr>;
|
||||
|
||||
private:
|
||||
typedef Gps_agg_meta_traits<Arrangement> Self;
|
||||
typedef Gps_traits_decorator<Gt2, Curve_data, Point_data> Base;
|
||||
using Self = Gps_agg_meta_traits<Arrangement>;
|
||||
using Base = Gps_traits_decorator<Gt2, Curve_data, Point_data>;
|
||||
|
||||
public:
|
||||
typedef typename Base::X_monotone_curve_2 X_monotone_curve_2;
|
||||
typedef typename Base::Point_2 Point_2;
|
||||
typedef typename Gt2::Has_left_category Has_left_category;
|
||||
typedef typename Gt2::Has_merge_category Has_merge_category;
|
||||
typedef typename Gt2::Has_do_intersect_category
|
||||
Has_do_intersect_category;
|
||||
using X_monotone_curve_2 = typename Base::X_monotone_curve_2;
|
||||
using Point_2 = typename Base::Point_2;
|
||||
using Has_left_category = typename Gt2::Has_left_category;
|
||||
using Has_merge_category = typename Gt2::Has_merge_category;
|
||||
using Has_do_intersect_category = typename Gt2::Has_do_intersect_category;
|
||||
|
||||
typedef typename Arr::Left_side_category Left_side_category;
|
||||
typedef typename Arr::Bottom_side_category Bottom_side_category;
|
||||
typedef typename Arr::Top_side_category Top_side_category;
|
||||
typedef typename Arr::Right_side_category Right_side_category;
|
||||
using Left_side_category = typename Arr::Left_side_category;
|
||||
using Bottom_side_category = typename Arr::Bottom_side_category;
|
||||
using Top_side_category = typename Arr::Top_side_category;
|
||||
using Right_side_category = typename Arr::Right_side_category;
|
||||
|
||||
// a side is either oblivious or open (unbounded)
|
||||
static_assert(std::is_same<Left_side_category, Arr_oblivious_side_tag>::value ||
|
||||
|
|
@ -132,8 +126,8 @@ public:
|
|||
static_assert(std::is_same<Right_side_category, Arr_oblivious_side_tag>::value ||
|
||||
std::is_same<Right_side_category, Arr_open_side_tag>::value);
|
||||
|
||||
typedef typename Arr::Halfedge_handle Halfedge_handle;
|
||||
typedef typename Arr::Vertex_handle Vertex_handle;
|
||||
using Halfedge_handle = typename Arr::Halfedge_handle;
|
||||
using Vertex_handle = typename Arr::Vertex_handle;
|
||||
|
||||
Gps_agg_meta_traits() {}
|
||||
|
||||
|
|
@ -152,16 +146,13 @@ public:
|
|||
template <typename OutputIterator>
|
||||
OutputIterator operator()(const X_monotone_curve_2& cv1,
|
||||
const X_monotone_curve_2& cv2,
|
||||
OutputIterator oi) const
|
||||
{
|
||||
OutputIterator oi) const {
|
||||
// Check whether the curves are already in the same arrangement, and thus
|
||||
// must be interior-disjoint
|
||||
if (cv1.data().arr() == cv2.data().arr()) return oi;
|
||||
|
||||
typedef const std::pair<Base_point_2, Multiplicity>
|
||||
Intersection_base_point;
|
||||
typedef std::variant<Intersection_base_point, Base_x_monotone_curve_2>
|
||||
Intersection_base_result;
|
||||
using Intersection_base_point = const std::pair<Base_point_2, Multiplicity>;
|
||||
using Intersection_base_result = std::variant<Intersection_base_point, Base_x_monotone_curve_2>;
|
||||
|
||||
const auto* base_traits = m_traits.m_base_traits;
|
||||
auto base_cmp_xy = base_traits->compare_xy_2_object();
|
||||
|
|
@ -191,8 +182,8 @@ public:
|
|||
const Base_x_monotone_curve_2* overlap_cv =
|
||||
std::get_if<Base_x_monotone_curve_2>(&xection);
|
||||
CGAL_assertion(overlap_cv != nullptr);
|
||||
unsigned int ov_bc;
|
||||
unsigned int ov_twin_bc;
|
||||
std::size_t ov_bc;
|
||||
std::size_t ov_twin_bc;
|
||||
if (base_cmp_endpoints(cv1) == base_cmp_endpoints(cv2)) {
|
||||
// cv1 and cv2 have the same directions
|
||||
ov_bc = cv1.data().bc() + cv2.data().bc();
|
||||
|
|
@ -230,8 +221,7 @@ public:
|
|||
Split_2(const Base_Split_2& base) : m_base_split(base) {}
|
||||
|
||||
void operator()(const X_monotone_curve_2& cv, const Point_2 & p,
|
||||
X_monotone_curve_2& c1, X_monotone_curve_2& c2) const
|
||||
{
|
||||
X_monotone_curve_2& c1, X_monotone_curve_2& c2) const {
|
||||
m_base_split(cv.base(), p.base(), c1.base(), c2.base());
|
||||
const Curve_data& cv_data = cv.data();
|
||||
c1.set_data(Curve_data(cv_data.arr(), Halfedge_handle(), cv_data.bc(),
|
||||
|
|
@ -259,8 +249,7 @@ public:
|
|||
* \param cv The curve.
|
||||
* \return The left endpoint.
|
||||
*/
|
||||
Point_2 operator()(const X_monotone_curve_2 & cv) const
|
||||
{
|
||||
Point_2 operator()(const X_monotone_curve_2 & cv) const {
|
||||
if (cv.data().halfedge() == Halfedge_handle())
|
||||
return (Point_2(m_base(cv.base())));
|
||||
|
||||
|
|
@ -272,8 +261,7 @@ public:
|
|||
};
|
||||
|
||||
/*! Get a Construct_min_vertex_2 functor object. */
|
||||
Construct_min_vertex_2 construct_min_vertex_2_object() const
|
||||
{
|
||||
Construct_min_vertex_2 construct_min_vertex_2_object() const {
|
||||
return Construct_min_vertex_2(this->m_base_traits->
|
||||
construct_min_vertex_2_object());
|
||||
}
|
||||
|
|
@ -285,15 +273,14 @@ public:
|
|||
|
||||
public:
|
||||
Construct_max_vertex_2(const Base_Construct_max_vertex_2& base) :
|
||||
m_base(base)
|
||||
m_base(base)
|
||||
{}
|
||||
|
||||
/*! Obtain the right endpoint of the x-monotone curve (segment).
|
||||
* \param cv The curve.
|
||||
* \return The right endpoint.
|
||||
*/
|
||||
Point_2 operator()(const X_monotone_curve_2& cv) const
|
||||
{
|
||||
Point_2 operator()(const X_monotone_curve_2& cv) const {
|
||||
if (cv.data().halfedge() == Halfedge_handle())
|
||||
return (Point_2(m_base(cv.base())));
|
||||
|
||||
|
|
@ -304,8 +291,7 @@ public:
|
|||
};
|
||||
|
||||
/*! Get a Construct_min_vertex_2 functor object. */
|
||||
Construct_max_vertex_2 construct_max_vertex_2_object() const
|
||||
{
|
||||
Construct_max_vertex_2 construct_max_vertex_2_object() const {
|
||||
return Construct_max_vertex_2(this->m_base_traits->
|
||||
construct_max_vertex_2_object());
|
||||
}
|
||||
|
|
@ -321,8 +307,7 @@ public:
|
|||
* \param cv The curve.
|
||||
* \return The left endpoint.
|
||||
*/
|
||||
Comparison_result operator()(const Point_2& p1, const Point_2& p2) const
|
||||
{
|
||||
Comparison_result operator()(const Point_2& p1, const Point_2& p2) const {
|
||||
const Point_data& inf1 = p1.data();
|
||||
const Point_data& inf2 = p2.data();
|
||||
|
||||
|
|
@ -390,8 +375,7 @@ public:
|
|||
};
|
||||
|
||||
/*! Obtain a Construct_min_vertex_2 functor object. */
|
||||
Compare_y_near_boundary_2 compare_y_near_boundary_2_object() const
|
||||
{
|
||||
Compare_y_near_boundary_2 compare_y_near_boundary_2_object() const {
|
||||
return Compare_y_near_boundary_2(this->m_base_traits->
|
||||
compare_y_near_boundary_2_object()
|
||||
);
|
||||
|
|
@ -429,8 +413,7 @@ public:
|
|||
};
|
||||
|
||||
/*! Obtain a Construct_min_vertex_2 functor object. */
|
||||
Parameter_space_in_y_2 parameter_space_in_y_2_object() const
|
||||
{
|
||||
Parameter_space_in_y_2 parameter_space_in_y_2_object() const {
|
||||
return Parameter_space_in_y_2(this->m_base_traits->
|
||||
parameter_space_in_y_2_object());
|
||||
}
|
||||
|
|
@ -462,8 +445,7 @@ public:
|
|||
};
|
||||
|
||||
/*! Obtain a Construct_min_vertex_2 functor object. */
|
||||
Compare_x_near_boundary_2 compare_x_near_boundary_2_object() const
|
||||
{
|
||||
Compare_x_near_boundary_2 compare_x_near_boundary_2_object() const {
|
||||
return Compare_x_near_boundary_2(this->m_base_traits->
|
||||
compare_x_near_boundary_2_object());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,11 +7,12 @@
|
|||
// $Id$
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ophir Setter <ophir.setter@cs.tau.ac.il>
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ophir Setter <ophir.setter@cs.tau.ac.il>
|
||||
// Efi Fogel <efifogel@gmail.com>
|
||||
|
||||
#ifndef CGAL_BSO_2_GPS_AGG_OP_H
|
||||
#define CGAL_BSO_2_GPS_AGG_OP_H
|
||||
#ifndef CGAL_GPS_AGG_OP_H
|
||||
#define CGAL_GPS_AGG_OP_H
|
||||
|
||||
#include <CGAL/license/Boolean_set_operations_2.h>
|
||||
|
||||
|
|
@ -19,8 +20,8 @@
|
|||
*
|
||||
* The class Gps_agg_op is responsible for aggregated Boolean set operations
|
||||
* depending on a visitor template parameter. It uses the surface-sweep
|
||||
* algorithm from the arrangement packages to overlay all the polygon sets, and
|
||||
* then it uses a BFS that determines which of the faces is contained in the
|
||||
* algorithm from the surface-sweep package to overlay all the polygon sets, and
|
||||
* then it uses a BFS that determines which of the faces are contained in the
|
||||
* result using the visitor.
|
||||
*/
|
||||
|
||||
|
|
@ -37,31 +38,31 @@
|
|||
|
||||
namespace CGAL {
|
||||
|
||||
template <typename Arrangement_, typename BfsVisitor>
|
||||
template <typename Arrangement_, typename BfsVisitor, template <typename, typename, typename> class SweepVisitor>
|
||||
class Gps_agg_op {
|
||||
typedef Arrangement_ Arrangement_2;
|
||||
typedef BfsVisitor Bfs_visitor;
|
||||
using Arrangement_2 = Arrangement_;
|
||||
using Bfs_visitor = BfsVisitor;
|
||||
|
||||
typedef typename Arrangement_2::Traits_adaptor_2 Geometry_traits_2;
|
||||
typedef typename Arrangement_2::Topology_traits Topology_traits;
|
||||
using Geometry_traits_2 = typename Arrangement_2::Traits_adaptor_2;
|
||||
using Topology_traits = typename Arrangement_2::Topology_traits;
|
||||
|
||||
typedef Arrangement_2 Arr;
|
||||
typedef Geometry_traits_2 Gt2;
|
||||
typedef Topology_traits Tt;
|
||||
using Arr = Arrangement_2;
|
||||
using Gt2 = Geometry_traits_2;
|
||||
using Tt = Topology_traits;
|
||||
|
||||
typedef typename Gt2::Curve_const_iterator Curve_const_iterator;
|
||||
typedef Gps_agg_meta_traits<Arr> Mgt2;
|
||||
typedef typename Mgt2::Curve_data Curve_data;
|
||||
typedef typename Mgt2::X_monotone_curve_2 Meta_X_monotone_curve_2;
|
||||
using Curve_const_iterator = typename Gt2::Curve_const_iterator;
|
||||
using Mgt2 = Gps_agg_meta_traits<Arr>;
|
||||
using Curve_data = typename Mgt2::Curve_data;
|
||||
using Meta_X_monotone_curve_2 = typename Mgt2::X_monotone_curve_2;
|
||||
|
||||
typedef typename Arr::Halfedge_handle Halfedge_handle;
|
||||
typedef typename Arr::Halfedge_iterator Halfedge_iterator;
|
||||
typedef typename Arr::Face_handle Face_handle;
|
||||
typedef typename Arr::Edge_iterator Edge_iterator;
|
||||
typedef typename Arr::Vertex_handle Vertex_handle;
|
||||
typedef typename Arr::Allocator Allocator;
|
||||
using Halfedge_handle = typename Arr::Halfedge_handle;
|
||||
using Halfedge_iterator = typename Arr::Halfedge_iterator;
|
||||
using Face_handle = typename Arr::Face_handle;
|
||||
using Edge_iterator = typename Arr::Edge_iterator;
|
||||
using Vertex_handle = typename Arr::Vertex_handle;
|
||||
using Allocator = typename Arr::Allocator;
|
||||
|
||||
typedef std::pair<Arr*, std::vector<Vertex_handle> *> Arr_entry;
|
||||
using Arr_entry = std::pair<Arr*, std::vector<Vertex_handle> *>;
|
||||
|
||||
// We obtain a proper helper type from the topology traits of the arrangement.
|
||||
// However, the arrangement is parametrized with the Gt2 geometry traits,
|
||||
|
|
@ -70,21 +71,16 @@ class Gps_agg_op {
|
|||
// We cannot parameterized the arrangement with the Mgt2 geometry
|
||||
// traits to start with, because it extends the curve type with arrangement
|
||||
// dependent types. (It is parameterized with the arrangement type.)
|
||||
typedef Indexed_event<Mgt2, Arr, Allocator> Event;
|
||||
typedef Arr_construction_subcurve<Mgt2, Event, Allocator>
|
||||
Subcurve;
|
||||
typedef typename Tt::template Construction_helper<Event, Subcurve>
|
||||
Helper_tmp;
|
||||
typedef typename Helper_tmp::template rebind<Mgt2, Arr, Event, Subcurve>::other
|
||||
Helper;
|
||||
typedef Gps_agg_op_visitor<Helper, Arr> Visitor;
|
||||
typedef Gps_agg_op_surface_sweep_2<Arr, Visitor> Surface_sweep_2;
|
||||
using Event = Indexed_event<Mgt2, Arr, Allocator>;
|
||||
using Subcurve = Arr_construction_subcurve<Mgt2, Event, Allocator>;
|
||||
using Helper_tmp = typename Tt::template Construction_helper<Event, Subcurve>;
|
||||
using Helper = typename Helper_tmp::template rebind<Mgt2, Arr, Event, Subcurve>::other;
|
||||
using Visitor = SweepVisitor<Helper, Arr, Default>;
|
||||
using Surface_sweep_2 = Gps_agg_op_surface_sweep_2<Arr, Visitor>;
|
||||
|
||||
typedef Unique_hash_map<Halfedge_handle, unsigned int>
|
||||
Edges_hash;
|
||||
|
||||
typedef Unique_hash_map<Face_handle, unsigned int> Faces_hash;
|
||||
typedef Gps_bfs_scanner<Arr, Bfs_visitor> Bfs_scanner;
|
||||
using Edges_hash = Unique_hash_map<Halfedge_handle, std::size_t>;
|
||||
using Faces_hash = Unique_hash_map<Face_handle, std::size_t>;
|
||||
using Bfs_scanner = Gps_bfs_scanner<Arr, Bfs_visitor>;
|
||||
|
||||
protected:
|
||||
Arr* m_arr;
|
||||
|
|
@ -95,7 +91,7 @@ protected:
|
|||
Faces_hash m_faces_hash; // maps face to its IC (inside count)
|
||||
|
||||
public:
|
||||
/*! Constructor. */
|
||||
/*! constructs. */
|
||||
Gps_agg_op(Arr& arr, std::vector<Vertex_handle>& vert_vec, const Gt2& tr) :
|
||||
m_arr(&arr),
|
||||
m_traits(new Mgt2(tr)),
|
||||
|
|
@ -103,40 +99,40 @@ public:
|
|||
m_surface_sweep(m_traits, &m_visitor)
|
||||
{}
|
||||
|
||||
void sweep_arrangements(unsigned int lower, unsigned int upper,
|
||||
unsigned int jump, std::vector<Arr_entry>& arr_vec)
|
||||
{
|
||||
std::list<Meta_X_monotone_curve_2> curves_list;
|
||||
|
||||
unsigned int n_inf_pgn = 0; // number of infinite polygons (arrangement
|
||||
std::pair<std::size_t, std::size_t>
|
||||
prepare(std::size_t lower, std::size_t upper, std::size_t jump,
|
||||
std::vector<Arr_entry>& arr_vec, std::list<Meta_X_monotone_curve_2>& curves_list) {
|
||||
std::size_t n_inf_pgn = 0; // number of infinite polygons (arrangement
|
||||
// with a contained unbounded face
|
||||
unsigned int n_pgn = 0; // number of polygons (arrangements)
|
||||
unsigned int i;
|
||||
|
||||
for (i = lower; i <= upper; i += jump, ++n_pgn) {
|
||||
std::size_t n_pgn = 0; // number of polygons (arrangements)
|
||||
for (auto i = lower; i <= upper; i += jump, ++n_pgn) {
|
||||
// The BFS scan (after the loop) starts in the reference face,
|
||||
// so we count the number of polygons that contain the reference face.
|
||||
Arr* arr = (arr_vec[i]).first;
|
||||
if (arr->reference_face()->contained()) ++n_inf_pgn;
|
||||
|
||||
Edge_iterator itr = arr->edges_begin();
|
||||
for(; itr != arr->edges_end(); ++itr) {
|
||||
for (auto itr = arr->edges_begin(); itr != arr->edges_end(); ++itr) {
|
||||
// take only relevant edges (which separate between contained and
|
||||
// non-contained faces.
|
||||
Halfedge_iterator he = itr;
|
||||
if(he->face()->contained() == he->twin()->face()->contained())
|
||||
continue;
|
||||
if ((Arr_halfedge_direction)he->direction() == ARR_RIGHT_TO_LEFT)
|
||||
he = he->twin();
|
||||
Halfedge_handle he = itr;
|
||||
if (he->face()->contained() == he->twin()->face()->contained()) continue;
|
||||
if ((Arr_halfedge_direction)he->direction() == ARR_RIGHT_TO_LEFT) he = he->twin();
|
||||
|
||||
Curve_data cv_data(arr, he, 1, 0);
|
||||
curves_list.push_back(Meta_X_monotone_curve_2(he->curve(), cv_data));
|
||||
}
|
||||
}
|
||||
return std::make_pair(n_inf_pgn, n_pgn);
|
||||
}
|
||||
|
||||
m_surface_sweep.sweep(curves_list.begin(), curves_list.end(),
|
||||
lower, upper, jump, arr_vec);
|
||||
|
||||
/*! sweeps the plane without interceptions.
|
||||
*/
|
||||
void sweep_arrangements(std::size_t lower, std::size_t upper, std::size_t jump,
|
||||
std::vector<Arr_entry>& arr_vec) {
|
||||
std::size_t n_inf_pgn, n_pgn;
|
||||
std::list<Meta_X_monotone_curve_2> curves_list;
|
||||
std::tie(n_inf_pgn, n_pgn) = prepare(lower, upper, jump, arr_vec, curves_list);
|
||||
m_surface_sweep.sweep(curves_list.begin(), curves_list.end(), lower, upper, jump, arr_vec);
|
||||
m_faces_hash[m_arr->reference_face()] = n_inf_pgn;
|
||||
Bfs_visitor visitor(&m_edges_hash, &m_faces_hash, n_pgn);
|
||||
visitor.visit_ubf(m_arr->faces_begin(), n_inf_pgn);
|
||||
|
|
@ -145,7 +141,69 @@ public:
|
|||
visitor.after_scan(*m_arr);
|
||||
}
|
||||
|
||||
/*! Destruct.
|
||||
/*! sweeps the plane without interceptions, but stop when an intersection occurs.
|
||||
*/
|
||||
bool sweep_intercept_arrangements(std::size_t lower, std::size_t upper, std::size_t jump,
|
||||
std::vector<Arr_entry>& arr_vec) {
|
||||
std::size_t n_inf_pgn, n_pgn;
|
||||
std::list<Meta_X_monotone_curve_2> curves_list;
|
||||
std::tie(n_inf_pgn, n_pgn) = prepare(lower, upper, jump, arr_vec, curves_list);
|
||||
auto res = m_surface_sweep.sweep_intercept(curves_list.begin(), curves_list.end(), lower, upper, jump, arr_vec);
|
||||
if (res) return true;
|
||||
|
||||
m_faces_hash[m_arr->reference_face()] = n_inf_pgn;
|
||||
Bfs_visitor visitor(&m_edges_hash, &m_faces_hash, n_pgn);
|
||||
visitor.visit_ubf(m_arr->faces_begin(), n_inf_pgn);
|
||||
Bfs_scanner scanner(visitor);
|
||||
scanner.scan(*m_arr);
|
||||
visitor.after_scan(*m_arr);
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename InputIterator>
|
||||
std::size_t prepare2(InputIterator begin, InputIterator end, std::list<Meta_X_monotone_curve_2>& curves_list) {
|
||||
std::size_t n_inf_pgn = 0; // number of infinite polygons (arrangement
|
||||
// with a contained unbounded face
|
||||
for (auto it = begin; it != end; ++it) {
|
||||
// The BFS scan (after the loop) starts in the reference face,
|
||||
// so we count the number of polygons that contain the reference face.
|
||||
Arr* arr = it->first;
|
||||
if (arr->reference_face()->contained()) ++n_inf_pgn;
|
||||
|
||||
for (auto ite = arr->edges_begin(); ite != arr->edges_end(); ++ite) {
|
||||
// take only relevant edges (which separate between contained and
|
||||
// non-contained faces.
|
||||
Halfedge_handle he = ite;
|
||||
if (he->face()->contained() == he->twin()->face()->contained()) continue;
|
||||
if ((Arr_halfedge_direction)he->direction() == ARR_RIGHT_TO_LEFT) he = he->twin();
|
||||
|
||||
Curve_data cv_data(arr, he, 1, 0);
|
||||
curves_list.push_back(Meta_X_monotone_curve_2(he->curve(), cv_data));
|
||||
}
|
||||
}
|
||||
return n_inf_pgn;
|
||||
}
|
||||
|
||||
/*! sweeps the plane without interceptions, but stop when an intersection occurs.
|
||||
*/
|
||||
template <typename InputIterator>
|
||||
bool sweep_intercept_arrangements2(InputIterator begin, InputIterator end) {
|
||||
std::list<Meta_X_monotone_curve_2> curves_list;
|
||||
auto n_inf_pgn = prepare2(begin, end, curves_list);
|
||||
auto res = m_surface_sweep.sweep_intercept2(curves_list.begin(), curves_list.end(), begin, end);
|
||||
if (res) return true;
|
||||
|
||||
m_faces_hash[m_arr->reference_face()] = n_inf_pgn;
|
||||
std::size_t n_pgn = std::distance(begin, end); // number of polygons (arrangements)
|
||||
Bfs_visitor visitor(&m_edges_hash, &m_faces_hash, n_pgn);
|
||||
visitor.visit_ubf(m_arr->faces_begin(), n_inf_pgn);
|
||||
Bfs_scanner scanner(visitor);
|
||||
scanner.scan(*m_arr);
|
||||
visitor.after_scan(*m_arr);
|
||||
return false;
|
||||
}
|
||||
|
||||
/*! destructs.
|
||||
*/
|
||||
~Gps_agg_op() { delete m_traits; }
|
||||
};
|
||||
|
|
|
|||
|
|
@ -7,11 +7,12 @@
|
|||
// $Id$
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ron Wein <wein@post.tau.ac.il>
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ron Wein <wein@post.tau.ac.il>
|
||||
// Efi Fogel <efifogel@gmail.com>
|
||||
|
||||
#ifndef CGAL_BSO_2_GSP_AGG_OP_SURFACE_SWEEP_2_H
|
||||
#define CGAL_BSO_2_GSP_AGG_OP_SURFACE_SWEEP_2_H
|
||||
#ifndef CGAL_GSP_AGG_OP_SURFACE_SWEEP_2_H
|
||||
#define CGAL_GSP_AGG_OP_SURFACE_SWEEP_2_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
|
@ -27,34 +28,34 @@ namespace Ss2 = Surface_sweep_2;
|
|||
template <typename Arrangement_, typename Visitor_>
|
||||
class Gps_agg_op_surface_sweep_2 : public Ss2::Surface_sweep_2<Visitor_> {
|
||||
public:
|
||||
typedef Arrangement_ Arrangement_2;
|
||||
typedef Visitor_ Visitor;
|
||||
using Arrangement_2 = Arrangement_;
|
||||
using Visitor = Visitor_;
|
||||
|
||||
typedef typename Visitor::Geometry_traits_2 Geometry_traits_2;
|
||||
using Geometry_traits_2 = typename Visitor::Geometry_traits_2;
|
||||
|
||||
typedef Arrangement_2 Arr;
|
||||
typedef Geometry_traits_2 Gt2;
|
||||
using Arr = Arrangement_2;
|
||||
using Gt2 = Geometry_traits_2;
|
||||
|
||||
typedef typename Gt2::Point_2 Point_2;
|
||||
typedef typename Gt2::X_monotone_curve_2 X_monotone_curve_2;
|
||||
using Point_2 = typename Gt2::Point_2;
|
||||
using X_monotone_curve_2 = typename Gt2::X_monotone_curve_2;
|
||||
|
||||
typedef typename Arr::Vertex_handle Vertex_handle;
|
||||
typedef typename Arr::Halfedge_handle Halfedge_handle;
|
||||
using Vertex_handle = typename Arr::Vertex_handle;
|
||||
using Halfedge_handle = typename Arr::Halfedge_handle;
|
||||
|
||||
typedef std::pair<Arr*, std::vector<Vertex_handle> *> Arr_entry;
|
||||
using Arr_entry = std::pair<Arr*, std::vector<Vertex_handle> *>;
|
||||
|
||||
typedef Ss2::Surface_sweep_2<Visitor> Base;
|
||||
using Base = Ss2::Surface_sweep_2<Visitor>;
|
||||
|
||||
typedef typename Visitor::Event Event;
|
||||
typedef typename Visitor::Subcurve Subcurve;
|
||||
using Event = typename Visitor::Event;
|
||||
using Subcurve = typename Visitor::Subcurve;
|
||||
|
||||
typedef typename Base::Event_queue_iterator EventQueueIter;
|
||||
typedef typename Event::Subcurve_iterator EventCurveIter;
|
||||
using EventQueueIter = typename Base::Event_queue_iterator;
|
||||
using EventCurveIter = typename Event::Subcurve_iterator;
|
||||
|
||||
typedef typename Event::Attribute Attribute;
|
||||
using Attribute = typename Event::Attribute;
|
||||
|
||||
typedef std::list<Subcurve*> SubCurveList;
|
||||
typedef typename SubCurveList::iterator SubCurveListIter;
|
||||
using SubCurveList = std::list<Subcurve*>;
|
||||
using SubCurveListIter = typename SubCurveList::iterator;
|
||||
|
||||
public:
|
||||
/*! Constructor.
|
||||
|
|
@ -70,21 +71,17 @@ public:
|
|||
Base(traits, visitor)
|
||||
{}
|
||||
|
||||
/*! Perform the sweep. */
|
||||
template <class CurveInputIterator>
|
||||
void sweep(CurveInputIterator curves_begin, CurveInputIterator curves_end,
|
||||
unsigned int lower, unsigned int upper, unsigned int jump,
|
||||
std::vector<Arr_entry>& arr_vec)
|
||||
{
|
||||
template <typename CurveInputIterator>
|
||||
void pre_process(CurveInputIterator curves_begin, CurveInputIterator curves_end,
|
||||
std::size_t lower, std::size_t upper, std::size_t jump,
|
||||
std::vector<Arr_entry>& arr_vec) {
|
||||
CGAL_assertion(this->m_queue->empty() && this->m_statusLine.size() == 0);
|
||||
|
||||
typedef Unique_hash_map<Vertex_handle, Event*> Vertices_map;
|
||||
typedef typename Gt2::Compare_xy_2 Compare_xy_2;
|
||||
using Vertices_map = Unique_hash_map<Vertex_handle, Event*>;
|
||||
using Compare_xy_2 = typename Gt2::Compare_xy_2;
|
||||
|
||||
this->m_visitor->before_sweep();
|
||||
// Allocate all of the Subcurve objects as one block.
|
||||
this->m_num_of_subCurves =
|
||||
static_cast<unsigned int>(std::distance(curves_begin, curves_end));
|
||||
this->m_num_of_subCurves = static_cast<unsigned int>(std::distance(curves_begin, curves_end));
|
||||
if (this->m_num_of_subCurves > 0)
|
||||
this->m_subCurves =
|
||||
this->m_subCurveAlloc.allocate(this->m_num_of_subCurves);
|
||||
|
|
@ -95,9 +92,9 @@ public:
|
|||
Vertices_map vert_map;
|
||||
Vertex_handle vh;
|
||||
Vertex_handle invalid_v;
|
||||
unsigned int i = lower;
|
||||
unsigned int n = static_cast<unsigned int>((arr_vec[i].second)->size());
|
||||
unsigned int j;
|
||||
std::size_t i = lower;
|
||||
auto n = (arr_vec[i].second)->size();
|
||||
std::size_t j;
|
||||
EventQueueIter q_iter;
|
||||
bool first = true;
|
||||
Attribute event_type;
|
||||
|
|
@ -135,7 +132,7 @@ public:
|
|||
for (i += jump; i <= upper; i += jump) {
|
||||
// Merge the vertices of the other vectors into the existing queue.
|
||||
q_iter = this->m_queue->begin();
|
||||
n = static_cast<unsigned int>((arr_vec[i].second)->size());
|
||||
n = (arr_vec[i].second)->size();
|
||||
|
||||
for (j = 0; j < n && (vh = (*(arr_vec[i].second))[j]) != invalid_v; j++) {
|
||||
event_type = _type_of_vertex(vh);
|
||||
|
|
@ -170,7 +167,7 @@ public:
|
|||
|
||||
// Go over all curves (which are associated with halfedges) and associate
|
||||
// them with the events we have just created.
|
||||
unsigned int index = 0;
|
||||
std::size_t index = 0;
|
||||
CurveInputIterator iter;
|
||||
Halfedge_handle he;
|
||||
Event* e_left;
|
||||
|
|
@ -194,9 +191,10 @@ public:
|
|||
}
|
||||
|
||||
// Create the subcurve object.
|
||||
typedef decltype(this->m_subCurveAlloc) Subcurve_alloc;
|
||||
std::allocator_traits<Subcurve_alloc>::construct(this->m_subCurveAlloc, this->m_subCurves + index,
|
||||
this->m_masterSubcurve);
|
||||
using Subcurve_alloc = decltype(this->m_subCurveAlloc);
|
||||
std::allocator_traits<Subcurve_alloc>::construct(this->m_subCurveAlloc,
|
||||
this->m_subCurves + index,
|
||||
this->m_masterSubcurve);
|
||||
(this->m_subCurves + index)->init(*iter);
|
||||
(this->m_subCurves + index)->set_left_event(e_left);
|
||||
(this->m_subCurves + index)->set_right_event(e_right);
|
||||
|
|
@ -204,13 +202,174 @@ public:
|
|||
e_right->add_curve_to_left(this->m_subCurves + index);
|
||||
this->_add_curve_to_right(e_left, this->m_subCurves + index);
|
||||
}
|
||||
}
|
||||
|
||||
// Perform the sweep:
|
||||
template <typename CurveInputIterator, typename InputIterator>
|
||||
void pre_process2(CurveInputIterator curves_begin, CurveInputIterator curves_end,
|
||||
InputIterator begin, InputIterator end) {
|
||||
CGAL_assertion(this->m_queue->empty() && this->m_statusLine.size() == 0);
|
||||
|
||||
using Vertices_map = Unique_hash_map<Vertex_handle, Event*>;
|
||||
using Compare_xy_2 = typename Gt2::Compare_xy_2;
|
||||
|
||||
// Allocate all of the Subcurve objects as one block.
|
||||
this->m_num_of_subCurves = std::distance(curves_begin, curves_end);
|
||||
if (this->m_num_of_subCurves > 0)
|
||||
this->m_subCurves =
|
||||
this->m_subCurveAlloc.allocate(this->m_num_of_subCurves);
|
||||
|
||||
|
||||
// Initialize the event queue using the vertices vectors. Note that these
|
||||
// vertices are already sorted, we simply have to merge them
|
||||
Vertices_map vert_map;
|
||||
Vertex_handle vh;
|
||||
Vertex_handle invalid_v;
|
||||
// std::size_t i = lower;
|
||||
auto it = begin;
|
||||
auto n = it->second->size();
|
||||
std::size_t j;
|
||||
EventQueueIter q_iter;
|
||||
bool first = true;
|
||||
Attribute event_type;
|
||||
Event* event;
|
||||
|
||||
for (j = 0; j < n && (vh = (*(it->second))[j]) != invalid_v; j++) {
|
||||
// Insert the vertices of the first vector one after the other.
|
||||
event_type = _type_of_vertex(vh);
|
||||
if (event_type == Event::DEFAULT) continue;
|
||||
|
||||
event = this->_allocate_event(vh->point(), event_type,
|
||||
ARR_INTERIOR, ARR_INTERIOR);
|
||||
// \todo When the boolean set operations are extended to support
|
||||
// unbounded curves, we will need here a special treatment.
|
||||
|
||||
#ifndef CGAL_ARRANGEMENT_ON_SURFACE_2_H
|
||||
event->set_finite();
|
||||
#endif
|
||||
|
||||
if (! first) {
|
||||
q_iter = this->m_queue->insert_after(q_iter, event);
|
||||
}
|
||||
else {
|
||||
q_iter = this->m_queue->insert(event);
|
||||
first = false;
|
||||
}
|
||||
|
||||
vert_map[vh] = event;
|
||||
}
|
||||
|
||||
Comparison_result res = LARGER;
|
||||
Compare_xy_2 comp_xy = this->m_traits->compare_xy_2_object();
|
||||
EventQueueIter q_end = this->m_queue->end();
|
||||
|
||||
for (++it; it != end; ++it) {
|
||||
// Merge the vertices of the other vectors into the existing queue.
|
||||
q_iter = this->m_queue->begin();
|
||||
n = it->second->size();
|
||||
|
||||
for (j = 0; j < n && (vh = (*(it->second))[j]) != invalid_v; j++) {
|
||||
event_type = _type_of_vertex(vh);
|
||||
if (event_type == Event::DEFAULT) continue;
|
||||
|
||||
while ((q_iter != q_end) &&
|
||||
(res = comp_xy(vh->point(), (*q_iter)->point())) == LARGER)
|
||||
{
|
||||
++q_iter;
|
||||
}
|
||||
|
||||
if (res == SMALLER || q_iter == q_end) {
|
||||
event = this->_allocate_event(vh->point(), event_type,
|
||||
ARR_INTERIOR, ARR_INTERIOR);
|
||||
// \todo When the boolean set operations are extended to support
|
||||
// unbounded curves, we will need here a special treatment.
|
||||
|
||||
#ifndef CGAL_ARRANGEMENT_ON_SURFACE_2_H
|
||||
event->set_finite();
|
||||
#endif
|
||||
|
||||
this->m_queue->insert_before(q_iter, event);
|
||||
vert_map[vh] = event;
|
||||
}
|
||||
else if (res == EQUAL) {
|
||||
// In this case q_iter points to an event already associated with
|
||||
// the vertex, so we just update the map:
|
||||
vert_map[vh] = *q_iter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Go over all curves (which are associated with halfedges) and associate
|
||||
// them with the events we have just created.
|
||||
std::size_t index = 0;
|
||||
CurveInputIterator iter;
|
||||
Halfedge_handle he;
|
||||
Event* e_left;
|
||||
Event* e_right;
|
||||
|
||||
for (iter = curves_begin; iter != curves_end; ++iter, index++) {
|
||||
// Get the events associated with the end-vertices of the current
|
||||
// halfedge.
|
||||
he = iter->data().halfedge();
|
||||
|
||||
CGAL_assertion(vert_map.is_defined(he->source()));
|
||||
CGAL_assertion(vert_map.is_defined(he->target()));
|
||||
|
||||
if ((Arr_halfedge_direction)he->direction() == ARR_LEFT_TO_RIGHT) {
|
||||
e_left = vert_map[he->source()];
|
||||
e_right = vert_map[he->target()];
|
||||
}
|
||||
else {
|
||||
e_left = vert_map[he->target()];
|
||||
e_right = vert_map[he->source()];
|
||||
}
|
||||
|
||||
// Create the subcurve object.
|
||||
using Subcurve_alloc = decltype(this->m_subCurveAlloc);
|
||||
std::allocator_traits<Subcurve_alloc>::construct(this->m_subCurveAlloc,
|
||||
this->m_subCurves + index,
|
||||
this->m_masterSubcurve);
|
||||
(this->m_subCurves + index)->init(*iter);
|
||||
(this->m_subCurves + index)->set_left_event(e_left);
|
||||
(this->m_subCurves + index)->set_right_event(e_right);
|
||||
|
||||
e_right->add_curve_to_left(this->m_subCurves + index);
|
||||
this->_add_curve_to_right(e_left, this->m_subCurves + index);
|
||||
}
|
||||
}
|
||||
|
||||
/*! Perform the sweep. */
|
||||
template <typename CurveInputIterator>
|
||||
void sweep(CurveInputIterator curves_begin, CurveInputIterator curves_end,
|
||||
std::size_t lower, std::size_t upper, std::size_t jump, std::vector<Arr_entry>& arr_vec) {
|
||||
this->m_visitor->before_sweep();
|
||||
pre_process(curves_begin, curves_end,lower, upper, jump, arr_vec);
|
||||
this->_sweep();
|
||||
this->_complete_sweep();
|
||||
this->m_visitor->after_sweep();
|
||||
}
|
||||
|
||||
return;
|
||||
/*! Perform the sweep. */
|
||||
template <typename CurveInputIterator>
|
||||
bool sweep_intercept(CurveInputIterator curves_begin, CurveInputIterator curves_end,
|
||||
std::size_t lower, std::size_t upper, std::size_t jump, std::vector<Arr_entry>& arr_vec) {
|
||||
this->m_visitor->before_sweep();
|
||||
pre_process(curves_begin, curves_end,lower, upper, jump, arr_vec);
|
||||
this->_sweep();
|
||||
this->_complete_sweep();
|
||||
this->m_visitor->after_sweep();
|
||||
return this->m_visitor->found_intersection();
|
||||
}
|
||||
|
||||
/*! Perform the sweep. */
|
||||
template <typename CurveInputIterator, typename InputIterator>
|
||||
bool sweep_intercept2(CurveInputIterator curves_begin, CurveInputIterator curves_end,
|
||||
InputIterator begin, InputIterator end) {
|
||||
this->m_visitor->before_sweep();
|
||||
pre_process2(curves_begin, curves_end, begin, end);
|
||||
this->_sweep();
|
||||
this->_complete_sweep();
|
||||
this->m_visitor->after_sweep();
|
||||
return this->m_visitor->found_intersection();
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
@ -218,8 +377,7 @@ private:
|
|||
* Check if the given vertex is an endpoint of an edge we are going
|
||||
* to use in the sweep.
|
||||
*/
|
||||
Attribute _type_of_vertex(Vertex_handle v)
|
||||
{
|
||||
Attribute _type_of_vertex(Vertex_handle v) {
|
||||
typename Arr::Halfedge_around_vertex_circulator first, circ;
|
||||
|
||||
circ = first = v->incident_halfedges();
|
||||
|
|
@ -232,7 +390,6 @@ private:
|
|||
else return (Event::LEFT_END);
|
||||
}
|
||||
++circ;
|
||||
|
||||
} while (circ != first);
|
||||
|
||||
// If we reached here, we should not keep this vertex.
|
||||
|
|
|
|||
|
|
@ -7,12 +7,12 @@
|
|||
// $Id$
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
//
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ron Wein <wein@post.tau.ac.il>
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ron Wein <wein@post.tau.ac.il>
|
||||
// Efi Fogel <efifogel@gmail.com>
|
||||
|
||||
#ifndef CGAL_BSO_2_GSP_AGG_OP_VISITOR_H
|
||||
#define CGAL_BSO_2_GSP_AGG_OP_VISITOR_H
|
||||
#ifndef CGAL_GSP_AGG_OP_VISITOR_H
|
||||
#define CGAL_GSP_AGG_OP_VISITOR_H
|
||||
|
||||
#include <CGAL/license/Boolean_set_operations_2.h>
|
||||
|
||||
|
|
@ -31,33 +31,29 @@ class Gps_agg_op_base_visitor :
|
|||
Helper_,
|
||||
typename Default::Get<Visitor_, Gps_agg_op_base_visitor<Helper_,
|
||||
Arrangement_,
|
||||
Visitor_> >::type>
|
||||
{
|
||||
Visitor_>>::type> {
|
||||
public:
|
||||
typedef Helper_ Helper;
|
||||
typedef Arrangement_ Arrangement_2;
|
||||
using Helper = Helper_;
|
||||
using Arrangement_2 = Arrangement_;
|
||||
|
||||
typedef typename Helper::Geometry_traits_2 Geometry_traits_2;
|
||||
typedef typename Helper::Event Event;
|
||||
typedef typename Helper::Subcurve Subcurve;
|
||||
using Geometry_traits_2 = typename Helper::Geometry_traits_2;
|
||||
using Event = typename Helper::Event;
|
||||
using Subcurve = typename Helper::Subcurve;
|
||||
|
||||
private:
|
||||
typedef Geometry_traits_2 Gt2;
|
||||
typedef Arrangement_2 Arr;
|
||||
|
||||
typedef Gps_agg_op_base_visitor<Helper, Arr, Visitor_>
|
||||
Self;
|
||||
typedef typename Default::Get<Visitor_, Self>::type Visitor;
|
||||
typedef Arr_construction_ss_visitor<Helper, Visitor> Base;
|
||||
using Gt2 = Geometry_traits_2;
|
||||
using Arr = Arrangement_2;
|
||||
using Self = Gps_agg_op_base_visitor<Helper, Arr, Visitor_>;
|
||||
using Visitor = typename Default::Get<Visitor_, Self>::type;
|
||||
using Base = Arr_construction_ss_visitor<Helper, Visitor>;
|
||||
|
||||
public:
|
||||
typedef typename Arr::Halfedge_handle Halfedge_handle;
|
||||
typedef typename Arr::Vertex_handle Vertex_handle;
|
||||
typedef typename Gt2::X_monotone_curve_2 X_monotone_curve_2;
|
||||
typedef typename Gt2::Point_2 Point_2;
|
||||
using Halfedge_handle = typename Arr::Halfedge_handle;
|
||||
using Vertex_handle = typename Arr::Vertex_handle;
|
||||
using X_monotone_curve_2 = typename Gt2::X_monotone_curve_2;
|
||||
using Point_2 = typename Gt2::Point_2;
|
||||
|
||||
typedef Unique_hash_map<Halfedge_handle, unsigned int>
|
||||
Edges_hash;
|
||||
using Edges_hash = Unique_hash_map<Halfedge_handle, std::size_t>;
|
||||
|
||||
protected:
|
||||
Edges_hash* m_edges_hash; // maps halfedges to their BC (coundary counter)
|
||||
|
|
@ -72,8 +68,7 @@ public:
|
|||
// TODO add mpl-warning
|
||||
|
||||
virtual Halfedge_handle insert_in_face_interior(const X_monotone_curve_2& cv,
|
||||
Subcurve* sc)
|
||||
{
|
||||
Subcurve* sc) {
|
||||
Halfedge_handle he = Base::insert_in_face_interior(cv, sc);
|
||||
insert_edge_to_hash(he, cv);
|
||||
return he;
|
||||
|
|
@ -83,8 +78,7 @@ public:
|
|||
Halfedge_handle hhandle,
|
||||
Halfedge_handle prev,
|
||||
Subcurve* sc,
|
||||
bool& new_face_created)
|
||||
{
|
||||
bool& new_face_created) {
|
||||
Halfedge_handle res_he =
|
||||
Base::insert_at_vertices(cv, hhandle, prev, sc, new_face_created);
|
||||
insert_edge_to_hash(res_he, cv);
|
||||
|
|
@ -93,8 +87,7 @@ public:
|
|||
|
||||
virtual Halfedge_handle insert_from_right_vertex(const X_monotone_curve_2& cv,
|
||||
Halfedge_handle he,
|
||||
Subcurve* sc)
|
||||
{
|
||||
Subcurve* sc) {
|
||||
Halfedge_handle res_he = Base::insert_from_right_vertex(cv, he, sc);
|
||||
insert_edge_to_hash(res_he, cv);
|
||||
return res_he;
|
||||
|
|
@ -102,16 +95,14 @@ public:
|
|||
|
||||
virtual Halfedge_handle insert_from_left_vertex(const X_monotone_curve_2& cv,
|
||||
Halfedge_handle he,
|
||||
Subcurve* sc)
|
||||
{
|
||||
Subcurve* sc) {
|
||||
Halfedge_handle res_he = Base::insert_from_left_vertex(cv, he, sc);
|
||||
insert_edge_to_hash(res_he, cv);
|
||||
return res_he;
|
||||
}
|
||||
|
||||
private:
|
||||
void insert_edge_to_hash(Halfedge_handle he, const X_monotone_curve_2& cv)
|
||||
{
|
||||
void insert_edge_to_hash(Halfedge_handle he, const X_monotone_curve_2& cv) {
|
||||
const Comparison_result he_dir =
|
||||
((Arr_halfedge_direction)he->direction() == ARR_LEFT_TO_RIGHT) ?
|
||||
SMALLER : LARGER;
|
||||
|
|
@ -133,54 +124,53 @@ private:
|
|||
|
||||
template <typename Helper_, typename Arrangement_, typename Visitor_ = Default>
|
||||
class Gps_agg_op_visitor :
|
||||
public Gps_agg_op_base_visitor<Helper_, Arrangement_,
|
||||
Gps_agg_op_visitor<Helper_, Arrangement_,
|
||||
Visitor_> >
|
||||
{
|
||||
public Gps_agg_op_base_visitor<
|
||||
Helper_, Arrangement_,
|
||||
typename Default::Get<Visitor_,
|
||||
Gps_agg_op_visitor<Helper_, Arrangement_, Visitor_>>::type> {
|
||||
public:
|
||||
typedef Helper_ Helper;
|
||||
typedef Arrangement_ Arrangement_2;
|
||||
using Helper = Helper_;
|
||||
using Arrangement_2 = Arrangement_;
|
||||
|
||||
typedef typename Helper::Geometry_traits_2 Geometry_traits_2;
|
||||
typedef typename Helper::Event Event;
|
||||
typedef typename Helper::Subcurve Subcurve;
|
||||
using Geometry_traits_2 = typename Helper::Geometry_traits_2;
|
||||
using Event = typename Helper::Event;
|
||||
using Subcurve = typename Helper::Subcurve;
|
||||
|
||||
private:
|
||||
typedef Geometry_traits_2 Gt2;
|
||||
typedef Arrangement_2 Arr;
|
||||
using Gt2 = Geometry_traits_2;
|
||||
using Arr = Arrangement_2;
|
||||
|
||||
typedef Gps_agg_op_visitor<Helper, Arr, Visitor_> Self;
|
||||
typedef typename Default::Get<Visitor_, Self>::type Visitor;
|
||||
typedef Gps_agg_op_base_visitor<Helper, Arr, Visitor> Base;
|
||||
using Self = Gps_agg_op_visitor<Helper, Arr, Visitor_>;
|
||||
using Visitor = typename Default::Get<Visitor_, Self>::type;
|
||||
using Base = Gps_agg_op_base_visitor<Helper, Arr, Visitor>;
|
||||
|
||||
public:
|
||||
typedef typename Base::Halfedge_handle Halfedge_handle;
|
||||
typedef typename Base::Vertex_handle Vertex_handle;
|
||||
typedef typename Gt2::X_monotone_curve_2 X_monotone_curve_2;
|
||||
typedef typename Gt2::Point_2 Point_2;
|
||||
using Edges_hash = typename Base::Edges_hash;
|
||||
using Halfedge_handle = typename Base::Halfedge_handle;
|
||||
using Vertex_handle = typename Base::Vertex_handle;
|
||||
using X_monotone_curve_2 = typename Gt2::X_monotone_curve_2;
|
||||
using Point_2 = typename Gt2::Point_2;
|
||||
|
||||
protected:
|
||||
unsigned int m_event_count; // The number of events so far.
|
||||
std::size_t m_event_count; // The number of events so far.
|
||||
std::vector<Vertex_handle>* m_vertices_vec; // The vertices, sorted in
|
||||
// ascending order.
|
||||
|
||||
public:
|
||||
Gps_agg_op_visitor(Arr* arr, typename Base::Edges_hash* hash,
|
||||
Gps_agg_op_visitor(Arr* arr, Edges_hash* hash,
|
||||
std::vector<Vertex_handle>* vertices_vec) :
|
||||
Base(arr, hash),
|
||||
m_event_count(0),
|
||||
m_vertices_vec(vertices_vec)
|
||||
{}
|
||||
|
||||
void before_handle_event(Event* event)
|
||||
{
|
||||
void before_handle_event(Event* event) {
|
||||
event->set_index(m_event_count);
|
||||
m_event_count++;
|
||||
}
|
||||
|
||||
virtual Halfedge_handle
|
||||
insert_in_face_interior(const X_monotone_curve_2& cv, Subcurve* sc)
|
||||
{
|
||||
insert_in_face_interior(const X_monotone_curve_2& cv, Subcurve* sc) {
|
||||
Halfedge_handle res_he = Base::insert_in_face_interior(cv, sc);
|
||||
|
||||
// We now have a halfedge whose source vertex is associated with the
|
||||
|
|
@ -198,8 +188,7 @@ public:
|
|||
|
||||
virtual Halfedge_handle insert_from_right_vertex(const X_monotone_curve_2& cv,
|
||||
Halfedge_handle he,
|
||||
Subcurve* sc)
|
||||
{
|
||||
Subcurve* sc) {
|
||||
Halfedge_handle res_he = Base::insert_from_right_vertex(cv, he, sc);
|
||||
|
||||
// We now have a halfedge whose target vertex is associated with the
|
||||
|
|
@ -213,9 +202,8 @@ public:
|
|||
|
||||
virtual Halfedge_handle insert_from_left_vertex(const X_monotone_curve_2& cv,
|
||||
Halfedge_handle he,
|
||||
Subcurve* sc)
|
||||
{
|
||||
Halfedge_handle res_he = Base::insert_from_left_vertex(cv, he, sc);
|
||||
Subcurve* sc) {
|
||||
Halfedge_handle res_he = Base::insert_from_left_vertex(cv, he, sc);
|
||||
|
||||
// We now have a halfedge whose target vertex is associated with the
|
||||
// current event(we have already dealt with its source vertex).
|
||||
|
|
@ -223,18 +211,16 @@ public:
|
|||
|
||||
CGAL_assertion((Arr_halfedge_direction)res_he->direction() ==
|
||||
ARR_LEFT_TO_RIGHT);
|
||||
_insert_vertex (curr_event, res_he->target());
|
||||
_insert_vertex(curr_event, res_he->target());
|
||||
return res_he;
|
||||
}
|
||||
|
||||
private:
|
||||
void _insert_vertex(const Event* event, Vertex_handle v)
|
||||
{
|
||||
const unsigned int index = event->index();
|
||||
void _insert_vertex(const Event* event, Vertex_handle v) {
|
||||
const auto index = event->index();
|
||||
if (index >= m_vertices_vec->size()) m_vertices_vec->resize(2 * (index + 1));
|
||||
(*m_vertices_vec)[index] = v;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // namespace CGAL
|
||||
|
|
|
|||
|
|
@ -8,90 +8,83 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
//
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ophir Setter <ophir.setter@cs.tau.ac.il>
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ophir Setter <ophir.setter@cs.tau.ac.il>
|
||||
|
||||
#ifndef CGAL_GPS_BPS_BASE_VISITOR_H
|
||||
#define CGAL_GPS_BPS_BASE_VISITOR_H
|
||||
|
||||
#include <CGAL/license/Boolean_set_operations_2.h>
|
||||
|
||||
|
||||
#include <CGAL/Unique_hash_map.h>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
//! Gps_bfs_base_visitor
|
||||
/*! This is a base class for all visitors that are responsible for merging
|
||||
polygon sets.
|
||||
We use DerivedVisitor for static polymorphism for using contained_criteria
|
||||
which determines if we should mark the face as contained given the inside
|
||||
count of the face.
|
||||
*/
|
||||
template <class Arrangement_, class DerivedVisitor>
|
||||
class Gps_bfs_base_visitor
|
||||
{
|
||||
typedef Arrangement_ Arrangement;
|
||||
typedef typename Arrangement::Face_iterator Face_iterator;
|
||||
typedef typename Arrangement::Halfedge_iterator Halfedge_iterator;
|
||||
* polygon sets.
|
||||
* We use DerivedVisitor for static polymorphism for using contained_criteria
|
||||
* which determines if we should mark the face as contained given the inside
|
||||
* count of the face.
|
||||
*/
|
||||
template <typename Arrangement_, typename DerivedVisitor>
|
||||
class Gps_bfs_base_visitor {
|
||||
using Arrangement = Arrangement_;
|
||||
using Face_iterator = typename Arrangement::Face_iterator;
|
||||
using Halfedge_iterator = typename Arrangement::Halfedge_iterator;
|
||||
|
||||
public:
|
||||
typedef Unique_hash_map<Halfedge_iterator, unsigned int> Edges_hash;
|
||||
typedef Unique_hash_map<Face_iterator, unsigned int> Faces_hash;
|
||||
using Edges_hash = Unique_hash_map<Halfedge_iterator, std::size_t>;
|
||||
using Faces_hash = Unique_hash_map<Face_iterator, std::size_t>;
|
||||
|
||||
protected:
|
||||
Edges_hash* m_edges_hash;
|
||||
Faces_hash* m_faces_hash;
|
||||
unsigned int m_num_of_polygons; // number of polygons
|
||||
Edges_hash* m_edges_hash;
|
||||
Faces_hash* m_faces_hash;
|
||||
std::size_t m_num_of_polygons; // number of polygons
|
||||
|
||||
public:
|
||||
|
||||
Gps_bfs_base_visitor(Edges_hash* edges_hash,
|
||||
Faces_hash* faces_hash,
|
||||
unsigned int n_pgn):
|
||||
std::size_t n_pgn):
|
||||
m_edges_hash(edges_hash),
|
||||
m_faces_hash(faces_hash),
|
||||
m_num_of_polygons(n_pgn)
|
||||
{}
|
||||
|
||||
|
||||
//! discovered_face
|
||||
/*! discovered_face is called by Gps_bfs_scanner when it reveals a new face
|
||||
during a BFS scan. In the BFS traversal we are going from old_face to
|
||||
new_face through the half-edge he.
|
||||
\param old_face The face that was already revealed
|
||||
\param new_face The face that we have just now revealed
|
||||
\param he The half-edge that is used to traverse between them.
|
||||
*/
|
||||
//! discovered_face
|
||||
/*! discovered_face is called by Gps_bfs_scanner when it reveals a new face
|
||||
* during a BFS scan. In the BFS traversal we are going from old_face to
|
||||
* new_face through the half-edge he.
|
||||
* \param old_face The face that was already revealed
|
||||
* \param new_face The face that we have just now revealed
|
||||
* \param he The half-edge that is used to traverse between them.
|
||||
*/
|
||||
void discovered_face(Face_iterator old_face,
|
||||
Face_iterator new_face,
|
||||
Halfedge_iterator he)
|
||||
{
|
||||
unsigned int ic = compute_ic(old_face, new_face, he);
|
||||
Halfedge_iterator he) {
|
||||
std::size_t ic = compute_ic(old_face, new_face, he);
|
||||
|
||||
if (static_cast<DerivedVisitor*>(this)->contained_criteria(ic))
|
||||
new_face->set_contained(true);
|
||||
}
|
||||
|
||||
// mark the unbounded_face (true iff contained)
|
||||
void visit_ubf(Face_iterator ubf, unsigned int ubf_ic)
|
||||
{
|
||||
void visit_ubf(Face_iterator ubf, std::size_t ubf_ic) {
|
||||
CGAL_assertion(ubf->is_unbounded());
|
||||
if(static_cast<DerivedVisitor*>(this)->contained_criteria(ubf_ic))
|
||||
if (static_cast<DerivedVisitor*>(this)->contained_criteria(ubf_ic))
|
||||
ubf->set_contained(true);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
// compute the inside count of a face
|
||||
unsigned int compute_ic(Face_iterator f1,
|
||||
Face_iterator f2,
|
||||
Halfedge_iterator he)
|
||||
{
|
||||
std::size_t compute_ic(Face_iterator f1,
|
||||
Face_iterator f2,
|
||||
Halfedge_iterator he) {
|
||||
CGAL_assertion(m_edges_hash->is_defined(he) &&
|
||||
m_edges_hash->is_defined(he->twin()) &&
|
||||
m_faces_hash->is_defined(f1) &&
|
||||
!m_faces_hash->is_defined(f2));
|
||||
unsigned int ic_f2 =
|
||||
! m_faces_hash->is_defined(f2));
|
||||
std::size_t ic_f2 =
|
||||
(*m_faces_hash)[f1] - (*m_edges_hash)[he] + (*m_edges_hash)[he->twin()];
|
||||
(*m_faces_hash)[f2] = ic_f2;
|
||||
|
||||
|
|
|
|||
|
|
@ -7,59 +7,50 @@
|
|||
// $Id$
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
//
|
||||
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ophir Setter <ophir.setter@cs.tau.ac.il>
|
||||
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ophir Setter <ophir.setter@cs.tau.ac.il>
|
||||
// Efi Fogel <efifogel@gmail.com>
|
||||
|
||||
#ifndef CGAL_GPS_BFS_INTERSECTION_VISITOR_H
|
||||
#define CGAL_GPS_BFS_INTERSECTION_VISITOR_H
|
||||
|
||||
#include <CGAL/license/Boolean_set_operations_2.h>
|
||||
|
||||
|
||||
#include <CGAL/Boolean_set_operations_2/Gps_bfs_base_visitor.h>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
template <class Arrangement_>
|
||||
template <typename Arrangement_>
|
||||
class Gps_bfs_intersection_visitor :
|
||||
public Gps_bfs_base_visitor<Arrangement_, Gps_bfs_intersection_visitor<Arrangement_> >
|
||||
{
|
||||
typedef Arrangement_ Arrangement;
|
||||
typedef typename Arrangement::Face_iterator Face_iterator;
|
||||
typedef typename Arrangement::Halfedge_iterator Halfedge_iterator;
|
||||
typedef Gps_bfs_intersection_visitor<Arrangement> Self;
|
||||
typedef Gps_bfs_base_visitor<Arrangement, Self> Base;
|
||||
typedef typename Base::Edges_hash Edges_hash;
|
||||
typedef typename Base::Faces_hash Faces_hash;
|
||||
|
||||
public Gps_bfs_base_visitor<Arrangement_, Gps_bfs_intersection_visitor<Arrangement_>> {
|
||||
using Arrangement = Arrangement_;
|
||||
using Face_iterator = typename Arrangement::Face_iterator;
|
||||
using Halfedge_iterator = typename Arrangement::Halfedge_iterator;
|
||||
using Self = Gps_bfs_intersection_visitor<Arrangement>;
|
||||
using Base = Gps_bfs_base_visitor<Arrangement, Self>;
|
||||
using Edges_hash = typename Base::Edges_hash;
|
||||
using Faces_hash = typename Base::Faces_hash;
|
||||
|
||||
public:
|
||||
|
||||
Gps_bfs_intersection_visitor(Edges_hash* edges_hash,
|
||||
Faces_hash* faces_hash,
|
||||
unsigned int n_polygons):
|
||||
std::size_t n_polygons):
|
||||
Base(edges_hash, faces_hash, n_polygons)
|
||||
{}
|
||||
|
||||
|
||||
//! contained_criteria
|
||||
/*! contained_criteria is used to the determine if the face which has
|
||||
inside count should be marked as contained.
|
||||
\param ic the inner count of the talked-about face.
|
||||
\return true if the face of ic, otherwise false.
|
||||
*/
|
||||
bool contained_criteria(unsigned int ic)
|
||||
{
|
||||
//! contained_criteria
|
||||
/*! contained_criteria is used to the determine if the face which has
|
||||
* inside count should be marked as contained.
|
||||
* \param ic the inner count of the talked-about face.
|
||||
* \return true if the face of ic, otherwise false.
|
||||
*/
|
||||
bool contained_criteria(std::size_t ic) {
|
||||
// intersection means that all polygons contain the face.
|
||||
CGAL_assertion(ic <= this->m_num_of_polygons);
|
||||
return (ic == this->m_num_of_polygons);
|
||||
}
|
||||
|
||||
void after_scan(Arrangement&)
|
||||
{}
|
||||
void after_scan(Arrangement&) {}
|
||||
};
|
||||
|
||||
} //namespace CGAL
|
||||
|
|
|
|||
|
|
@ -8,52 +8,46 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
//
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ophir Setter <ophir.setter@cs.tau.ac.il>
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ophir Setter <ophir.setter@cs.tau.ac.il>
|
||||
|
||||
#ifndef CGAL_GPS_BFS_JOIN_VISITOR_H
|
||||
#define CGAL_GPS_BFS_JOIN_VISITOR_H
|
||||
|
||||
#include <CGAL/license/Boolean_set_operations_2.h>
|
||||
|
||||
|
||||
#include <CGAL/Boolean_set_operations_2/Gps_bfs_base_visitor.h>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
template <class Arrangement_>
|
||||
template <typename Arrangement_>
|
||||
class Gps_bfs_join_visitor :
|
||||
public Gps_bfs_base_visitor<Arrangement_, Gps_bfs_join_visitor<Arrangement_> >
|
||||
{
|
||||
typedef Arrangement_ Arrangement;
|
||||
typedef typename Arrangement::Face_iterator Face_iterator;
|
||||
typedef typename Arrangement::Halfedge_iterator Halfedge_iterator;
|
||||
typedef Gps_bfs_join_visitor<Arrangement> Self;
|
||||
typedef Gps_bfs_base_visitor<Arrangement, Self> Base;
|
||||
typedef typename Base::Edges_hash Edges_hash;
|
||||
typedef typename Base::Faces_hash Faces_hash;
|
||||
public Gps_bfs_base_visitor<Arrangement_, Gps_bfs_join_visitor<Arrangement_>> {
|
||||
using Arrangement = Arrangement_;
|
||||
using Face_iterator = typename Arrangement::Face_iterator;
|
||||
using Halfedge_iterator = typename Arrangement::Halfedge_iterator;
|
||||
using Self = Gps_bfs_join_visitor<Arrangement>;
|
||||
using Base = Gps_bfs_base_visitor<Arrangement, Self>;
|
||||
using Edges_hash = typename Base::Edges_hash;
|
||||
using Faces_hash = typename Base::Faces_hash;
|
||||
|
||||
public:
|
||||
|
||||
Gps_bfs_join_visitor(Edges_hash* edges_hash, Faces_hash* faces_hash, unsigned int n_pgn):
|
||||
Gps_bfs_join_visitor(Edges_hash* edges_hash, Faces_hash* faces_hash, std::size_t n_pgn):
|
||||
Base(edges_hash, faces_hash, n_pgn)
|
||||
{}
|
||||
|
||||
//! contained_criteria
|
||||
/*! contained_criteria is used to the determine if the face which has
|
||||
inside count should be marked as contained.
|
||||
\param ic the inner count of the talked-about face.
|
||||
\return true if the face of ic, otherwise false.
|
||||
*/
|
||||
bool contained_criteria(unsigned int ic)
|
||||
{
|
||||
//! contained_criteria
|
||||
/*! contained_criteria is used to the determine if the face which has
|
||||
* inside count should be marked as contained.
|
||||
* \param ic the inner count of the talked-about face.
|
||||
* \return true if the face of ic, otherwise false.
|
||||
*/
|
||||
bool contained_criteria(std::size_t ic) {
|
||||
// at least one polygon contains the face.
|
||||
return (ic > 0);
|
||||
}
|
||||
|
||||
void after_scan(Arrangement&)
|
||||
{}
|
||||
|
||||
void after_scan(Arrangement&) {}
|
||||
};
|
||||
|
||||
} //namespace CGAL
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
//
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ophir Setter <ophir.setter@cs.tau.ac.il>
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ophir Setter <ophir.setter@cs.tau.ac.il>
|
||||
|
||||
#ifndef CGAL_GPS_BFS_XOR_VISITOR_H
|
||||
#define CGAL_GPS_BFS_XOR_VISITOR_H
|
||||
|
|
@ -21,73 +21,61 @@
|
|||
|
||||
namespace CGAL {
|
||||
|
||||
template <class Arrangement_>
|
||||
template <typename Arrangement_>
|
||||
class Gps_bfs_xor_visitor :
|
||||
public Gps_bfs_base_visitor<Arrangement_, Gps_bfs_xor_visitor<Arrangement_> >
|
||||
{
|
||||
typedef Arrangement_ Arrangement;
|
||||
typedef typename Arrangement::Face_iterator Face_iterator;
|
||||
typedef typename Arrangement::Halfedge_iterator Halfedge_iterator;
|
||||
typedef Gps_bfs_xor_visitor<Arrangement> Self;
|
||||
typedef Gps_bfs_base_visitor<Arrangement, Self> Base;
|
||||
typedef typename Base::Edges_hash Edges_hash;
|
||||
typedef typename Base::Faces_hash Faces_hash;
|
||||
public Gps_bfs_base_visitor<Arrangement_, Gps_bfs_xor_visitor<Arrangement_>> {
|
||||
using Arrangement = Arrangement_;
|
||||
using Face_iterator = typename Arrangement::Face_iterator;
|
||||
using Halfedge_iterator = typename Arrangement::Halfedge_iterator;
|
||||
using Self = Gps_bfs_xor_visitor<Arrangement>;
|
||||
using Base = Gps_bfs_base_visitor<Arrangement, Self>;
|
||||
using Edges_hash = typename Base::Edges_hash;
|
||||
using Faces_hash = typename Base::Faces_hash;
|
||||
|
||||
public:
|
||||
|
||||
Gps_bfs_xor_visitor(Edges_hash* edges_hash, Faces_hash* faces_hash,
|
||||
unsigned int n_pgn) :
|
||||
std::size_t n_pgn) :
|
||||
Base(edges_hash, faces_hash, n_pgn)
|
||||
{}
|
||||
|
||||
//! contained_criteria
|
||||
//! contained_criteria
|
||||
/*! contained_criteria is used to the determine if the face which has
|
||||
inside count should be marked as contained.
|
||||
\param ic the inner count of the talked-about face.
|
||||
\return true if the face of ic, otherwise false.
|
||||
*/
|
||||
bool contained_criteria(unsigned int ic)
|
||||
{
|
||||
bool contained_criteria(std::size_t ic) {
|
||||
// xor means odd number of polygons.
|
||||
return (ic % 2) == 1;
|
||||
}
|
||||
|
||||
//! after_scan postprocessing after bfs scan.
|
||||
/*! The function fixes some of the curves, to be in the same direction as the
|
||||
half-edges.
|
||||
|
||||
\param arr The given arrangement.
|
||||
*/
|
||||
void after_scan(Arrangement& arr)
|
||||
{
|
||||
typedef typename Arrangement::Geometry_traits_2 Traits;
|
||||
typedef typename Traits::Compare_endpoints_xy_2 Compare_endpoints_xy_2;
|
||||
typedef typename Traits::Construct_opposite_2 Construct_opposite_2;
|
||||
typedef typename Traits::X_monotone_curve_2 X_monotone_curve_2;
|
||||
typedef typename Arrangement::Edge_iterator Edge_iterator;
|
||||
/*! The function fixes some of the curves, to be in the same direction as the
|
||||
* half-edges.
|
||||
*
|
||||
* \param arr The given arrangement.
|
||||
*/
|
||||
void after_scan(Arrangement& arr) {
|
||||
using Traits = typename Arrangement::Geometry_traits_2;
|
||||
using X_monotone_curve_2 = typename Traits::X_monotone_curve_2;
|
||||
|
||||
Traits tr;
|
||||
Compare_endpoints_xy_2 cmp_endpoints =
|
||||
tr.compare_endpoints_xy_2_object();
|
||||
Construct_opposite_2 ctr_opp = tr.construct_opposite_2_object();
|
||||
auto cmp_endpoints = tr.compare_endpoints_xy_2_object();
|
||||
auto ctr_opp = tr.construct_opposite_2_object();
|
||||
|
||||
for(Edge_iterator eit = arr.edges_begin();
|
||||
eit != arr.edges_end();
|
||||
++eit)
|
||||
{
|
||||
Halfedge_iterator he = eit;
|
||||
for (auto eit = arr.edges_begin(); eit != arr.edges_end(); ++eit) {
|
||||
Halfedge_iterator he = eit;
|
||||
const X_monotone_curve_2& cv = he->curve();
|
||||
const bool is_cont = he->face()->contained();
|
||||
const Comparison_result he_res =
|
||||
const bool is_cont = he->face()->contained();
|
||||
const Comparison_result he_res =
|
||||
((Arr_halfedge_direction)he->direction() == ARR_LEFT_TO_RIGHT) ?
|
||||
SMALLER : LARGER;
|
||||
SMALLER : LARGER;
|
||||
const bool has_same_dir = (cmp_endpoints(cv) == he_res);
|
||||
|
||||
if ((is_cont && !has_same_dir) || (!is_cont && has_same_dir))
|
||||
arr.modify_edge(he, ctr_opp(cv));
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} //namespace CGAL
|
||||
|
|
|
|||
|
|
@ -0,0 +1,93 @@
|
|||
// Copyright (c) 2005 Tel-Aviv University (Israel).
|
||||
// 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) : Efi Fogel <efifogel@gmail.com>
|
||||
|
||||
#ifndef CGAL_GSP_DO_INTERSECT_AGG_OP_VISITOR_H
|
||||
#define CGAL_GSP_DO_INTERSECT_AGG_OP_VISITOR_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <CGAL/license/Boolean_set_operations_2.h>
|
||||
#include <CGAL/Boolean_set_operations_2/Gps_agg_op_visitor.h>
|
||||
#include <CGAL/Default.h>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
template <typename Helper_, typename Arrangement_, typename Visitor_ = Default>
|
||||
class Gps_do_intersect_agg_op_visitor :
|
||||
public Gps_agg_op_visitor<
|
||||
Helper_, Arrangement_,
|
||||
typename Default::Get<Visitor_, Gps_do_intersect_agg_op_visitor<Helper_, Arrangement_, Visitor_>>::type> {
|
||||
public:
|
||||
using Helper = Helper_;
|
||||
using Arrangement_2 = Arrangement_;
|
||||
using Geometry_traits_2 = typename Helper::Geometry_traits_2;
|
||||
using Event = typename Helper::Event;
|
||||
using Subcurve = typename Helper::Subcurve;
|
||||
|
||||
private:
|
||||
using Gt2 = Geometry_traits_2;
|
||||
using Arr = Arrangement_2;
|
||||
using Self = Gps_do_intersect_agg_op_visitor<Helper, Arr, Visitor_>;
|
||||
using Visitor = typename Default::Get<Visitor_, Self>::type;
|
||||
using Base = Gps_agg_op_visitor<Helper, Arr, Visitor>;
|
||||
|
||||
protected:
|
||||
bool m_found_x;
|
||||
|
||||
public:
|
||||
using Edges_hash = typename Base::Edges_hash;
|
||||
using Vertex_handle = typename Base::Vertex_handle;
|
||||
using Status_line_iterator = typename Base::Status_line_iterator;
|
||||
using X_monotone_curve_2 = typename Base::X_monotone_curve_2;
|
||||
using Point_2 = typename Base::Point_2;
|
||||
using Multiplicity = typename Base::Multiplicity;
|
||||
|
||||
Gps_do_intersect_agg_op_visitor(Arr* arr, Edges_hash* hash,
|
||||
std::vector<Vertex_handle>* vertices_vec) :
|
||||
Base(arr, hash, vertices_vec),
|
||||
m_found_x(false)
|
||||
{}
|
||||
|
||||
/*! Update an event that corresponds to a curve endpoint. */
|
||||
void update_event(Event* e, const Point_2& end_point, const X_monotone_curve_2& cv, Arr_curve_end cv_end, bool is_new)
|
||||
{ Base::update_event(e, end_point, cv, cv_end, is_new); }
|
||||
|
||||
/*! Update an event that corresponds to a curve endpoint */
|
||||
void update_event(Event* e, const X_monotone_curve_2& cv, Arr_curve_end cv_end, bool is_new )
|
||||
{ Base::update_event(e, cv, cv_end, is_new); }
|
||||
|
||||
/*! Update an event that corresponds to a curve endpoint */
|
||||
void update_event(Event* e, const Point_2& p, bool is_new)
|
||||
{ Base::update_event(e, p, is_new); }
|
||||
|
||||
/*! Update an event that corresponds to an intersection */
|
||||
void update_event(Event* e, Subcurve* sc) { Base::update_event(e, sc); }
|
||||
|
||||
/*! Update an event that corresponds to an intersection between curves */
|
||||
void update_event(Event* e, Subcurve* sc1, Subcurve* sc2, bool is_new, Multiplicity multiplicity) {
|
||||
if ((multiplicity % 2) == 1) m_found_x = true;
|
||||
Base::update_event(e, sc1, sc2, is_new, multiplicity);
|
||||
}
|
||||
|
||||
//!
|
||||
bool after_handle_event(Event* e, Status_line_iterator iter, bool flag) {
|
||||
auto res = Base::after_handle_event(e, iter, flag);
|
||||
if (m_found_x) this->surface_sweep()->stop_sweep();
|
||||
return res;
|
||||
}
|
||||
|
||||
/*! Getter */
|
||||
bool found_intersection() { return m_found_x; }
|
||||
};
|
||||
|
||||
} // namespace CGAL
|
||||
|
||||
#endif
|
||||
|
|
@ -15,112 +15,61 @@
|
|||
|
||||
#include <CGAL/license/Boolean_set_operations_2.h>
|
||||
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
template <class Arrangement_>
|
||||
class Gps_do_intersect_functor
|
||||
{
|
||||
template <typename Arrangement_>
|
||||
class Gps_do_intersect_functor {
|
||||
public:
|
||||
using Arrangement_2 = Arrangement_;
|
||||
|
||||
typedef Arrangement_ Arrangement_2;
|
||||
using Face_const_handle = typename Arrangement_2::Face_const_handle;
|
||||
using Vertex_const_handle = typename Arrangement_2::Vertex_const_handle;
|
||||
using Halfedge_const_handle = typename Arrangement_2::Halfedge_const_handle;
|
||||
|
||||
typedef typename Arrangement_2::Face_const_handle 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_handle Face_handle;
|
||||
typedef typename Arrangement_2::Halfedge_handle Halfedge_handle;
|
||||
typedef typename Arrangement_2::Vertex_handle Vertex_handle;
|
||||
using Face_handle = typename Arrangement_2::Face_handle;
|
||||
using Halfedge_handle = typename Arrangement_2::Halfedge_handle;
|
||||
using Vertex_handle = typename Arrangement_2::Vertex_handle;
|
||||
|
||||
// default constructor
|
||||
Gps_do_intersect_functor() : m_found_reg_intersection(false),
|
||||
m_found_boudary_intersection(false)
|
||||
|
||||
Gps_do_intersect_functor() :
|
||||
m_found_reg_intersection(false),
|
||||
m_found_boudary_intersection(false)
|
||||
{}
|
||||
|
||||
void create_face (Face_const_handle f1,
|
||||
Face_const_handle f2,
|
||||
Face_handle )
|
||||
{
|
||||
if(f1->contained() && f2->contained())
|
||||
// found intersection
|
||||
m_found_reg_intersection = true;
|
||||
}
|
||||
void create_face(Face_const_handle f1, Face_const_handle f2, Face_handle)
|
||||
{ if (f1->contained() && f2->contained()) m_found_reg_intersection = true; }
|
||||
|
||||
void create_vertex(Vertex_const_handle, Vertex_const_handle, Vertex_handle)
|
||||
{ m_found_boudary_intersection = true; }
|
||||
|
||||
void create_vertex(Vertex_const_handle ,
|
||||
Vertex_const_handle ,
|
||||
Vertex_handle )
|
||||
{
|
||||
m_found_boudary_intersection = true;
|
||||
}
|
||||
void create_vertex(Vertex_const_handle, Halfedge_const_handle, Vertex_handle)
|
||||
{ m_found_boudary_intersection = true; }
|
||||
|
||||
void create_vertex(Vertex_const_handle ,
|
||||
Halfedge_const_handle ,
|
||||
Vertex_handle )
|
||||
{
|
||||
m_found_boudary_intersection = true;
|
||||
}
|
||||
void create_vertex(Halfedge_const_handle, Vertex_const_handle, Vertex_handle)
|
||||
{ m_found_boudary_intersection = true; }
|
||||
|
||||
void create_vertex(Halfedge_const_handle ,
|
||||
Vertex_const_handle ,
|
||||
Vertex_handle )
|
||||
{
|
||||
m_found_boudary_intersection = true;
|
||||
}
|
||||
void create_vertex(Halfedge_const_handle, Halfedge_const_handle, Vertex_handle) {}
|
||||
|
||||
void create_vertex(Halfedge_const_handle ,
|
||||
Halfedge_const_handle ,
|
||||
Vertex_handle )
|
||||
{}
|
||||
void create_vertex(Face_const_handle, Vertex_const_handle, Vertex_handle) {}
|
||||
|
||||
void create_vertex(Vertex_const_handle, Face_const_handle, Vertex_handle) {}
|
||||
|
||||
void create_vertex(Face_const_handle ,
|
||||
Vertex_const_handle ,
|
||||
Vertex_handle )
|
||||
{}
|
||||
void create_edge(Halfedge_const_handle, Halfedge_const_handle, Halfedge_handle)
|
||||
{ m_found_boudary_intersection = true; }
|
||||
|
||||
void create_vertex(Vertex_const_handle ,
|
||||
Face_const_handle ,
|
||||
Vertex_handle )
|
||||
{}
|
||||
void create_edge(Halfedge_const_handle, Face_const_handle, Halfedge_handle) {}
|
||||
|
||||
void create_edge(Halfedge_const_handle ,
|
||||
Halfedge_const_handle ,
|
||||
Halfedge_handle )
|
||||
{
|
||||
m_found_boudary_intersection = true;
|
||||
}
|
||||
void create_edge(Face_const_handle, Halfedge_const_handle, Halfedge_handle) {}
|
||||
|
||||
void create_edge(Halfedge_const_handle ,
|
||||
Face_const_handle ,
|
||||
Halfedge_handle )
|
||||
{}
|
||||
bool found_reg_intersection() const { return m_found_reg_intersection; }
|
||||
|
||||
void create_edge(Face_const_handle ,
|
||||
Halfedge_const_handle ,
|
||||
Halfedge_handle )
|
||||
{}
|
||||
bool found_boundary_intersection() const { return m_found_boudary_intersection; }
|
||||
|
||||
|
||||
bool found_reg_intersection() const
|
||||
{
|
||||
return m_found_reg_intersection;
|
||||
}
|
||||
|
||||
bool found_boundary_intersection() const
|
||||
{
|
||||
return m_found_boudary_intersection;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
bool m_found_reg_intersection;
|
||||
bool m_found_boudary_intersection;
|
||||
protected:
|
||||
bool m_found_reg_intersection;
|
||||
bool m_found_boudary_intersection;
|
||||
};
|
||||
|
||||
|
||||
} //namespace CGAL
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -7,15 +7,17 @@
|
|||
// $Id$
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Efi Fogel <efifogel@gmail.com>
|
||||
|
||||
#ifndef CGAL_GPS_MERGE_H
|
||||
#define CGAL_GPS_MERGE_H
|
||||
|
||||
#include <CGAL/license/Boolean_set_operations_2.h>
|
||||
|
||||
|
||||
#include <CGAL/Boolean_set_operations_2/Gps_agg_op.h>
|
||||
#include <CGAL/Boolean_set_operations_2/Gps_agg_op_visitor.h>
|
||||
#include <CGAL/Boolean_set_operations_2/Gps_do_intersect_agg_op_visitor.h>
|
||||
#include <CGAL/Boolean_set_operations_2/Gps_bfs_join_visitor.h>
|
||||
#include <CGAL/Boolean_set_operations_2/Gps_bfs_xor_visitor.h>
|
||||
#include <CGAL/Boolean_set_operations_2/Gps_bfs_intersection_visitor.h>
|
||||
|
|
@ -23,50 +25,40 @@
|
|||
|
||||
namespace CGAL {
|
||||
|
||||
/*!
|
||||
\file Gps_merge.h
|
||||
\brief This file contains classes that are responsible for merging
|
||||
two sets of polygons in the divide-and-conquer algorithm.
|
||||
The file contains 3 mergers: Join_merge, Intersection_merge and
|
||||
Xor_merge. Join_merge is used when we want to merge the two sets,
|
||||
Intersection_merge is used for intersection, and Xor_merge is used
|
||||
for symmetric difference.
|
||||
*/
|
||||
|
||||
//! Base_merge
|
||||
/*! Base_merge is the base class for all merger classes.
|
||||
All merges used BFS algorithm with a different visitor when discovering
|
||||
a new face.
|
||||
/*! \file Gps_merge.h
|
||||
*
|
||||
* This file contains classes that are responsible for merging two sets of
|
||||
* polygons in the divide-and-conquer algorithm. The file contains 3 mergers:
|
||||
* Join_merge, Intersection_merge and Xor_merge. Join_merge is used when we want
|
||||
* to merge the two sets, Intersection_merge is used for intersection, and
|
||||
* Xor_merge is used for symmetric difference.
|
||||
*/
|
||||
template <class Arrangement_, class Visitor_>
|
||||
class Base_merge
|
||||
{
|
||||
typedef Arrangement_ Arrangement_2;
|
||||
typedef Visitor_ Visitor;
|
||||
typedef typename Arrangement_2::Vertex_handle Vertex_handle;
|
||||
typedef std::pair<Arrangement_2 *,
|
||||
std::vector<Vertex_handle> *> Arr_entry;
|
||||
|
||||
/*! Base_merge
|
||||
* Base_merge is the base class for all merger classes.
|
||||
* All merges used BFS algorithm with a different visitor when discovering
|
||||
* a new face.
|
||||
*/
|
||||
template <typename Arrangement_, typename Visitor_>
|
||||
class Base_merge {
|
||||
using Arrangement_2 = Arrangement_;
|
||||
using Visitor = Visitor_;
|
||||
using Vertex_handle = typename Arrangement_2::Vertex_handle;
|
||||
using Arr_entry = std::pair<Arrangement_2*, std::vector<Vertex_handle>*>;
|
||||
|
||||
public:
|
||||
void operator()(unsigned int i,
|
||||
unsigned int j,
|
||||
unsigned int jump,
|
||||
std::vector<Arr_entry>& arr_vec)
|
||||
{
|
||||
if(i==j)
|
||||
return;
|
||||
void operator()(std::size_t i, std::size_t j, std::size_t jump, std::vector<Arr_entry>& arr_vec) {
|
||||
if (i == j) return;
|
||||
|
||||
const typename Arrangement_2::Geometry_traits_2 * tr =
|
||||
arr_vec[i].first->geometry_traits();
|
||||
Arrangement_2 *res = new Arrangement_2(tr);
|
||||
std::vector<Vertex_handle> *verts = new std::vector<Vertex_handle>;
|
||||
const auto* tr = arr_vec[i].first->geometry_traits();
|
||||
Arrangement_2* res = new Arrangement_2(tr);
|
||||
std::vector<Vertex_handle>* verts = new std::vector<Vertex_handle>;
|
||||
|
||||
Gps_agg_op<Arrangement_2, Visitor>
|
||||
agg_op(*res, *verts, *(res->traits_adaptor()));
|
||||
using Agg_op = Gps_agg_op<Arrangement_2, Visitor, Gps_agg_op_visitor>;
|
||||
Agg_op agg_op(*res, *verts, *(res->traits_adaptor()));
|
||||
agg_op.sweep_arrangements(i, j, jump, arr_vec);
|
||||
|
||||
for(unsigned int count=i; count<=j; count+=jump)
|
||||
{
|
||||
for (std::size_t count = i; count <= j; count += jump) {
|
||||
delete (arr_vec[count].first);
|
||||
delete (arr_vec[count].second);
|
||||
}
|
||||
|
|
@ -74,38 +66,92 @@ public:
|
|||
arr_vec[i].first = res;
|
||||
arr_vec[i].second = verts;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
//! Join_merge
|
||||
/*! Join_merge is used to join two sets of polygons together in the D&C
|
||||
algorithm. It is a base merge with a visitor that joins faces.
|
||||
/*! Base_intercepted_merge
|
||||
* Base_intercepted_merge is the base class for all merger classes that can be
|
||||
* interceted (e.g., when an intersection is detected). All merges used BFS
|
||||
* algorithm with a different visitor when discovering a new face.
|
||||
*/
|
||||
template <class Arrangement_>
|
||||
class Join_merge : public Base_merge<Arrangement_,
|
||||
Gps_bfs_join_visitor<Arrangement_> >
|
||||
{};
|
||||
template <typename Arrangement_, typename Visitor_>
|
||||
class Base_intercepted_merge {
|
||||
using Arrangement_2 = Arrangement_;
|
||||
using Visitor = Visitor_;
|
||||
using Vertex_handle = typename Arrangement_2::Vertex_handle;
|
||||
using Arr_entry = std::pair<Arrangement_2*, std::vector<Vertex_handle>*>;
|
||||
|
||||
public:
|
||||
template <typename InputIterator>
|
||||
bool operator()(InputIterator begin, InputIterator end) {
|
||||
CGAL_assertion(begin != end);
|
||||
|
||||
//! Intersection_merge
|
||||
/*! Intersection_merge is used to merge two sets of polygons creating their
|
||||
intersection.
|
||||
*/
|
||||
template <class Arrangement_>
|
||||
class Intersection_merge : public Base_merge<Arrangement_,
|
||||
Gps_bfs_intersection_visitor<Arrangement_> >
|
||||
{};
|
||||
const auto* tr = begin->first->geometry_traits();
|
||||
Arrangement_2* arr = new Arrangement_2(tr);
|
||||
std::vector<Vertex_handle>* verts = new std::vector<Vertex_handle>;
|
||||
|
||||
//! Xor_merge
|
||||
/*! Xor_merge is used to merge two sets of polygons creating their
|
||||
symmetric difference.
|
||||
*/
|
||||
template <class Arrangement_>
|
||||
class Xor_merge : public Base_merge<Arrangement_,
|
||||
Gps_bfs_xor_visitor<Arrangement_> >
|
||||
{
|
||||
using Agg_op = Gps_agg_op<Arrangement_2, Visitor, Gps_do_intersect_agg_op_visitor>;
|
||||
Agg_op agg_op(*arr, *verts, *(arr->traits_adaptor()));
|
||||
auto res = agg_op.sweep_intercept_arrangements2(begin, end);
|
||||
|
||||
begin->first = arr;
|
||||
begin->second = verts;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
bool operator()(std::size_t i, std::size_t j, std::size_t jump, std::vector<Arr_entry>& arr_vec) {
|
||||
if (i == j) return false;
|
||||
|
||||
const auto* tr = arr_vec[i].first->geometry_traits();
|
||||
Arrangement_2* arr = new Arrangement_2(tr);
|
||||
std::vector<Vertex_handle>* verts = new std::vector<Vertex_handle>;
|
||||
|
||||
using Agg_op = Gps_agg_op<Arrangement_2, Visitor, Gps_do_intersect_agg_op_visitor>;
|
||||
Agg_op agg_op(*arr, *verts, *(arr->traits_adaptor()));
|
||||
auto res = agg_op.sweep_intercept_arrangements(i, j, jump, arr_vec);
|
||||
|
||||
for (auto count = i; count <= j; count += jump) {
|
||||
delete (arr_vec[count].first);
|
||||
arr_vec[count].first = nullptr;
|
||||
delete (arr_vec[count].second);
|
||||
arr_vec[count].second = nullptr;
|
||||
}
|
||||
|
||||
arr_vec[i].first = arr;
|
||||
arr_vec[i].second = verts;
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
/*! Join_merge
|
||||
* Join_merge is used to join two sets of polygons together in the D&C
|
||||
* algorithm. It is a base merge with a visitor that joins faces.
|
||||
*/
|
||||
template <typename Arrangement_>
|
||||
class Join_merge : public Base_merge<Arrangement_, Gps_bfs_join_visitor<Arrangement_>>{};
|
||||
|
||||
/*! Intersection_merge
|
||||
* Intersection_merge is used to merge two sets of polygons creating their
|
||||
* intersection.
|
||||
*/
|
||||
template <typename Arrangement_>
|
||||
class Intersection_merge : public Base_merge<Arrangement_, Gps_bfs_intersection_visitor<Arrangement_>>{};
|
||||
|
||||
/*! Do_intersect_merge
|
||||
* Do_intersect_merge is used to merge two sets of polygons creating their
|
||||
* intersection. When an intersection in the interior of the boundary curves
|
||||
* is detected, the sweep is intercepted.
|
||||
*/
|
||||
template <typename Arrangement_>
|
||||
class Do_intersect_merge : public Base_intercepted_merge<Arrangement_, Gps_bfs_intersection_visitor<Arrangement_>>{};
|
||||
|
||||
/*! Xor_merge
|
||||
* Xor_merge is used to merge two sets of polygons creating their
|
||||
* symmetric difference.
|
||||
*/
|
||||
template <typename Arrangement_>
|
||||
class Xor_merge : public Base_merge<Arrangement_, Gps_bfs_xor_visitor<Arrangement_>>{};
|
||||
|
||||
} //namespace CGAL
|
||||
|
||||
#endif
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -7,11 +7,10 @@
|
|||
// $Id$
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
//
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
|
||||
#ifndef CGAL_BSO_2_GPS_POLYGON_SIMPILFIER_H
|
||||
#define CGAL_BSO_2_GPS_POLYGON_SIMPILFIER_H
|
||||
#ifndef CGAL_GPS_POLYGON_SIMPILFIER_H
|
||||
#define CGAL_GPS_POLYGON_SIMPILFIER_H
|
||||
|
||||
#include <CGAL/license/Boolean_set_operations_2.h>
|
||||
|
||||
|
|
@ -31,34 +30,33 @@ namespace Ss2 = Surface_sweep_2;
|
|||
|
||||
template <typename Arrangement_>
|
||||
class Gps_polygon_simplifier {
|
||||
typedef Arrangement_ Arrangement_2;
|
||||
using Arrangement_2 = Arrangement_;
|
||||
|
||||
typedef typename Arrangement_2::Geometry_traits_2 Geometry_traits_2;
|
||||
typedef typename Arrangement_2::Topology_traits Topology_traits;
|
||||
using Geometry_traits_2 = typename Arrangement_2::Geometry_traits_2;
|
||||
using Topology_traits = typename Arrangement_2::Topology_traits;
|
||||
|
||||
typedef Arrangement_2 Arr;
|
||||
typedef Geometry_traits_2 Gt2;
|
||||
typedef Topology_traits Tt;
|
||||
using Arr = Arrangement_2;
|
||||
using Gt2 = Geometry_traits_2;
|
||||
using Tt = Topology_traits;
|
||||
|
||||
typedef typename Gt2::Curve_const_iterator Curve_const_iterator;
|
||||
typedef typename Gt2::Polygon_2 Polygon_2;
|
||||
typedef typename Gt2::Polygon_with_holes_2 Polygon_with_holes_2;
|
||||
typedef typename Gt2::Construct_curves_2 Construct_curves_2;
|
||||
using Curve_const_iterator = typename Gt2::Curve_const_iterator;
|
||||
using Polygon_2 = typename Gt2::Polygon_2;
|
||||
using Polygon_with_holes_2 = typename Gt2::Polygon_with_holes_2;
|
||||
using Construct_curves_2 = typename Gt2::Construct_curves_2;
|
||||
|
||||
typedef Gps_simplifier_traits<Gt2> Mgt2;
|
||||
typedef typename Mgt2::Curve_data Curve_data;
|
||||
typedef typename Mgt2::X_monotone_curve_2 Meta_X_monotone_curve_2;
|
||||
using Mgt2 = Gps_simplifier_traits<Gt2>;
|
||||
using Curve_data = typename Mgt2::Curve_data;
|
||||
using Meta_X_monotone_curve_2 = typename Mgt2::X_monotone_curve_2;
|
||||
|
||||
typedef typename Arr::Halfedge_handle Halfedge_handle;
|
||||
typedef typename Arr::Halfedge_iterator Halfedge_iterator;
|
||||
typedef typename Arr::Face_handle Face_handle;
|
||||
typedef typename Arr::Face_iterator Face_iterator;
|
||||
typedef typename Arr::Edge_iterator Edge_iterator;
|
||||
typedef typename Arr::Vertex_handle Vertex_handle;
|
||||
typedef typename Arr::Ccb_halfedge_const_circulator
|
||||
Ccb_halfedge_const_circulator;
|
||||
typedef typename Arr::Ccb_halfedge_circulator Ccb_halfedge_circulator;
|
||||
typedef typename Arr::Allocator Allocator;
|
||||
using Halfedge_handle = typename Arr::Halfedge_handle;
|
||||
using Halfedge_iterator = typename Arr::Halfedge_iterator;
|
||||
using Face_handle = typename Arr::Face_handle;
|
||||
using Face_iterator = typename Arr::Face_iterator;
|
||||
using Edge_iterator = typename Arr::Edge_iterator;
|
||||
using Vertex_handle = typename Arr::Vertex_handle;
|
||||
using Ccb_halfedge_const_circulator = typename Arr::Ccb_halfedge_const_circulator;
|
||||
using Ccb_halfedge_circulator = typename Arr::Ccb_halfedge_circulator;
|
||||
using Allocator = typename Arr::Allocator;
|
||||
|
||||
// We obtain a proper helper type from the topology traits of the arrangement.
|
||||
// However, the arrangement is parametrized with the Gt2 geometry traits,
|
||||
|
|
@ -67,22 +65,18 @@ class Gps_polygon_simplifier {
|
|||
// We cannot parameterized the arrangement with the Mgt2 geometry
|
||||
// traits to start with, because it extends the curve type with arrangement
|
||||
// dependent types. (It is parameterized with the arrangement type.)
|
||||
typedef Indexed_event<Mgt2, Arr, Allocator> Event;
|
||||
typedef Arr_construction_subcurve<Mgt2, Event, Allocator>
|
||||
Subcurve;
|
||||
typedef typename Tt::template Construction_helper<Event, Subcurve>
|
||||
Helper_tmp;
|
||||
typedef typename Helper_tmp::template rebind<Mgt2, Arr, Event, Subcurve>::other
|
||||
Helper;
|
||||
typedef Gps_agg_op_base_visitor<Helper, Arr> Visitor;
|
||||
typedef Ss2::Surface_sweep_2<Visitor> Surface_sweep_2;
|
||||
using Event = Indexed_event<Mgt2, Arr, Allocator>;
|
||||
using Subcurve = Arr_construction_subcurve<Mgt2, Event, Allocator>;
|
||||
using Helper_tmp = typename Tt::template Construction_helper<Event, Subcurve>;
|
||||
using Helper = typename Helper_tmp::template rebind<Mgt2, Arr, Event, Subcurve>::other;
|
||||
using Visitor = Gps_agg_op_base_visitor<Helper, Arr>;
|
||||
using Surface_sweep_2 = Ss2::Surface_sweep_2<Visitor>;
|
||||
|
||||
typedef Unique_hash_map<Halfedge_handle, unsigned int>
|
||||
Edges_hash;
|
||||
using Edges_hash = Unique_hash_map<Halfedge_handle, std::size_t>;
|
||||
|
||||
typedef Unique_hash_map<Face_handle, unsigned int> Faces_hash;
|
||||
typedef Gps_bfs_join_visitor<Arr> Bfs_visitor;
|
||||
typedef Gps_bfs_scanner<Arr, Bfs_visitor> Bfs_scanner;
|
||||
using Faces_hash = Unique_hash_map<Face_handle, std::size_t>;
|
||||
using Bfs_visitor = Gps_bfs_join_visitor<Arr>;
|
||||
using Bfs_scanner = Gps_bfs_scanner<Arr, Bfs_visitor>;
|
||||
|
||||
protected:
|
||||
Arr* m_arr;
|
||||
|
|
@ -104,16 +98,14 @@ public:
|
|||
{}
|
||||
|
||||
/*! Destructor. */
|
||||
~Gps_polygon_simplifier()
|
||||
{
|
||||
~Gps_polygon_simplifier() {
|
||||
if (m_own_traits && (m_traits != nullptr)) {
|
||||
delete m_traits;
|
||||
m_traits = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void simplify(const Polygon_2& pgn)
|
||||
{
|
||||
void simplify(const Polygon_2& pgn) {
|
||||
Construct_curves_2 ctr_curves =
|
||||
reinterpret_cast<const Gt2*>(m_traits)->construct_curves_2_object();
|
||||
|
||||
|
|
@ -122,14 +114,13 @@ public:
|
|||
std::pair<Curve_const_iterator, Curve_const_iterator> itr_pair =
|
||||
ctr_curves(pgn);
|
||||
|
||||
unsigned int index = 0;
|
||||
std::size_t index = 0;
|
||||
for (Curve_const_iterator itr = itr_pair.first; itr != itr_pair.second;
|
||||
++itr, ++index)
|
||||
{
|
||||
++itr, ++index) {
|
||||
Curve_data cv_data(1, 0, index);
|
||||
curves_list.push_back(Meta_X_monotone_curve_2(*itr, cv_data));
|
||||
}
|
||||
m_traits->set_polygon_size(static_cast<unsigned int>(curves_list.size()));
|
||||
m_traits->set_polygon_size(curves_list.size());
|
||||
|
||||
m_surface_sweep.sweep(curves_list.begin(), curves_list.end());
|
||||
|
||||
|
|
|
|||
|
|
@ -7,14 +7,13 @@
|
|||
// $Id$
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
//
|
||||
// Author(s): Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ron Wein <wein@post.tau.ac.il>
|
||||
// Boris Kozorovitzky <boriskoz@post.tau.ac.il>
|
||||
// Guy Zucker <guyzucke@post.tau.ac.il>
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ron Wein <wein@post.tau.ac.il>
|
||||
// Boris Kozorovitzky <boriskoz@post.tau.ac.il>
|
||||
// Guy Zucker <guyzucke@post.tau.ac.il>
|
||||
|
||||
#ifndef CGAL_BSO_2_GPS_POLYGON_VALIDATION_2_H
|
||||
#define CGAL_BSO_2_GPS_POLYGON_VALIDATION_2_H
|
||||
#ifndef CGAL_GPS_POLYGON_VALIDATION_2_H
|
||||
#define CGAL_GPS_POLYGON_VALIDATION_2_H
|
||||
|
||||
#include <CGAL/license/Boolean_set_operations_2.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -7,9 +7,8 @@
|
|||
// $Id$
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
//
|
||||
// Author(s): Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Efi Fogel <efifogel@gmail.com>
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Efi Fogel <efifogel@gmail.com>
|
||||
|
||||
#ifndef CGAL_GPS_SIMPLIFIER_TRAITS_H
|
||||
#define CGAL_GPS_SIMPLIFIER_TRAITS_H
|
||||
|
|
@ -23,97 +22,94 @@ namespace CGAL {
|
|||
|
||||
class Gps_simplifier_curve_data {
|
||||
protected:
|
||||
unsigned int m_bc;
|
||||
unsigned int m_twin_bc;
|
||||
unsigned int m_index;
|
||||
std::size_t m_bc;
|
||||
std::size_t m_twin_bc;
|
||||
std::size_t m_index;
|
||||
|
||||
public:
|
||||
Gps_simplifier_curve_data() {}
|
||||
|
||||
Gps_simplifier_curve_data(unsigned int bc, unsigned int twin_bc,
|
||||
unsigned int index):
|
||||
Gps_simplifier_curve_data(std::size_t bc, std::size_t twin_bc,
|
||||
std::size_t index):
|
||||
m_bc(bc),
|
||||
m_twin_bc(twin_bc),
|
||||
m_index(index)
|
||||
{}
|
||||
|
||||
unsigned int bc() const { return m_bc; }
|
||||
std::size_t bc() const { return m_bc; }
|
||||
|
||||
unsigned int twin_bc() const { return m_twin_bc; }
|
||||
std::size_t twin_bc() const { return m_twin_bc; }
|
||||
|
||||
unsigned int index() const { return m_index; }
|
||||
std::size_t index() const { return m_index; }
|
||||
|
||||
unsigned int& index() { return m_index; }
|
||||
std::size_t& index() { return m_index; }
|
||||
|
||||
unsigned int& twin_bc() { return m_twin_bc; }
|
||||
std::size_t& twin_bc() { return m_twin_bc; }
|
||||
|
||||
void set_bc(unsigned int bc) { m_bc = bc; }
|
||||
void set_bc(std::size_t bc) { m_bc = bc; }
|
||||
|
||||
void set_twin_bc(unsigned int twin_bc) { m_twin_bc = twin_bc; }
|
||||
void set_twin_bc(std::size_t twin_bc) { m_twin_bc = twin_bc; }
|
||||
|
||||
void set_index(unsigned int index) { m_index = index; }
|
||||
void set_index(std::size_t index) { m_index = index; }
|
||||
};
|
||||
|
||||
struct Gps_simplifier_point_data {
|
||||
protected:
|
||||
unsigned int m_index;
|
||||
std::size_t m_index;
|
||||
|
||||
public:
|
||||
Gps_simplifier_point_data() {}
|
||||
|
||||
Gps_simplifier_point_data(unsigned int index) : m_index(index) {}
|
||||
Gps_simplifier_point_data(std::size_t index) : m_index(index) {}
|
||||
|
||||
unsigned int index() const { return m_index; }
|
||||
std::size_t index() const { return m_index; }
|
||||
|
||||
void set_index(unsigned int index) { m_index = index; }
|
||||
void set_index(std::size_t index) { m_index = index; }
|
||||
};
|
||||
|
||||
template <typename Traits_>
|
||||
class Gps_simplifier_traits :
|
||||
public Gps_traits_decorator<Traits_,
|
||||
Gps_simplifier_curve_data,
|
||||
Gps_simplifier_point_data>
|
||||
{
|
||||
Gps_simplifier_point_data> {
|
||||
public:
|
||||
typedef Traits_ Traits;
|
||||
typedef Gps_traits_decorator<Traits_,
|
||||
Gps_simplifier_curve_data,
|
||||
Gps_simplifier_point_data> Base;
|
||||
typedef Gps_simplifier_traits<Traits> Self;
|
||||
typedef typename Traits::X_monotone_curve_2 Base_x_monotone_curve_2;
|
||||
typedef typename Traits::Point_2 Base_point_2;
|
||||
typedef typename Traits::Construct_min_vertex_2 Base_Construct_min_vertex_2;
|
||||
typedef typename Traits::Construct_max_vertex_2 Base_Construct_max_vertex_2;
|
||||
typedef typename Traits::Compare_endpoints_xy_2 Base_Compare_endpoints_xy_2;
|
||||
typedef typename Traits::Compare_xy_2 Base_Compare_xy_2;
|
||||
typedef typename Traits::Compare_y_at_x_right_2 Base_Compare_y_at_x_right_2;
|
||||
typedef typename Traits::Compare_y_at_x_2 Base_Compare_y_at_x_2;
|
||||
typedef typename Traits::Intersect_2 Base_Intersect_2;
|
||||
typedef typename Traits::Split_2 Base_Split_2;
|
||||
using Traits = Traits_;
|
||||
using Base = Gps_traits_decorator<Traits_, Gps_simplifier_curve_data, Gps_simplifier_point_data>;
|
||||
using Self = Gps_simplifier_traits<Traits>;
|
||||
using Base_x_monotone_curve_2 = typename Traits::X_monotone_curve_2;
|
||||
using Base_point_2 = typename Traits::Point_2;
|
||||
using Base_Construct_min_vertex_2 = typename Traits::Construct_min_vertex_2;
|
||||
using Base_Construct_max_vertex_2 = typename Traits::Construct_max_vertex_2;
|
||||
using Base_Compare_endpoints_xy_2 = typename Traits::Compare_endpoints_xy_2;
|
||||
using Base_Compare_xy_2 = typename Traits::Compare_xy_2;
|
||||
using Base_Compare_y_at_x_right_2 = typename Traits::Compare_y_at_x_right_2;
|
||||
using Base_Compare_y_at_x_2 = typename Traits::Compare_y_at_x_2;
|
||||
using Base_Intersect_2 = typename Traits::Intersect_2;
|
||||
using Base_Split_2 = typename Traits::Split_2;
|
||||
|
||||
protected:
|
||||
mutable unsigned int m_pgn_size;
|
||||
mutable std::size_t m_pgn_size;
|
||||
|
||||
public:
|
||||
typedef typename Base::X_monotone_curve_2 X_monotone_curve_2;
|
||||
typedef typename Base::Point_2 Point_2;
|
||||
typedef typename Base::Multiplicity Multiplicity;
|
||||
using X_monotone_curve_2 = typename Base::X_monotone_curve_2;
|
||||
using Point_2 = typename Base::Point_2;
|
||||
using Multiplicity = typename Base::Multiplicity;
|
||||
|
||||
typedef typename Base::Curve_data Curve_data;
|
||||
typedef typename Base::Point_data Point_data;
|
||||
using Curve_data = typename Base::Curve_data;
|
||||
using Point_data = typename Base::Point_data;
|
||||
|
||||
Gps_simplifier_traits() {}
|
||||
|
||||
Gps_simplifier_traits(const Traits& tr) : Base(tr) {}
|
||||
|
||||
unsigned int polygon_size() const { return m_pgn_size; }
|
||||
std::size_t polygon_size() const { return m_pgn_size; }
|
||||
|
||||
void set_polygon_size(unsigned int pgn_size) const { m_pgn_size = pgn_size; }
|
||||
void set_polygon_size(std::size_t pgn_size) const { m_pgn_size = pgn_size; }
|
||||
|
||||
bool is_valid_index(unsigned int index) const
|
||||
bool is_valid_index(std::size_t index) const
|
||||
{ return (index < m_pgn_size); }
|
||||
|
||||
unsigned int invalid_index() const { return (m_pgn_size); }
|
||||
std::size_t invalid_index() const { return (m_pgn_size); }
|
||||
|
||||
class Intersect_2 {
|
||||
private:
|
||||
|
|
@ -129,12 +125,9 @@ public:
|
|||
template <typename OutputIterator>
|
||||
OutputIterator operator()(const X_monotone_curve_2& cv1,
|
||||
const X_monotone_curve_2& cv2,
|
||||
OutputIterator oi) const
|
||||
{
|
||||
typedef const std::pair<Base_point_2, Multiplicity>
|
||||
Intersection_base_point;
|
||||
typedef std::variant<Intersection_base_point, Base_x_monotone_curve_2>
|
||||
Intersection_base_result;
|
||||
OutputIterator oi) const {
|
||||
using Intersection_base_point = const std::pair<Base_point_2, Multiplicity>;
|
||||
using Intersection_base_result = std::variant<Intersection_base_point, Base_x_monotone_curve_2>;
|
||||
|
||||
const auto* base_traits = m_traits.m_base_traits;
|
||||
auto base_cmp_xy = base_traits->compare_xy_2_object();
|
||||
|
|
@ -146,7 +139,7 @@ public:
|
|||
//if (m_traits.is_valid_index(cv1.data().index()) &&
|
||||
// m_traits.is_valid_index(cv2.data().index()))
|
||||
//{
|
||||
// unsigned int index_diff =
|
||||
// std::size_t index_diff =
|
||||
// (cv1.data().index() > cv2.data().index()) ?
|
||||
// (cv1.data().index() - cv2.data().index()):
|
||||
// (cv2.data().index() - cv1.data().index());
|
||||
|
|
@ -180,8 +173,8 @@ public:
|
|||
std::get_if<Base_x_monotone_curve_2>(&xection);
|
||||
|
||||
CGAL_assertion(overlap_cv != nullptr);
|
||||
unsigned int ov_bc;
|
||||
unsigned int ov_twin_bc;
|
||||
std::size_t ov_bc;
|
||||
std::size_t ov_twin_bc;
|
||||
if (base_cmp_endpoints(cv1) == base_cmp_endpoints(cv2)) {
|
||||
// cv1 and cv2 have the same directions
|
||||
ov_bc = cv1.data().bc() + cv2.data().bc();
|
||||
|
|
@ -207,7 +200,7 @@ public:
|
|||
};
|
||||
|
||||
/*! Obtain an Intersect_2 functor object. */
|
||||
Intersect_2 intersect_2_object () const { return Intersect_2(*this); }
|
||||
Intersect_2 intersect_2_object() const { return Intersect_2(*this); }
|
||||
|
||||
class Split_2 {
|
||||
private:
|
||||
|
|
@ -220,8 +213,7 @@ public:
|
|||
|
||||
public:
|
||||
void operator()(const X_monotone_curve_2& cv, const Point_2 & p,
|
||||
X_monotone_curve_2& c1, X_monotone_curve_2& c2) const
|
||||
{
|
||||
X_monotone_curve_2& c1, X_monotone_curve_2& c2) const {
|
||||
const auto* base_traits = m_traits.m_base_traits;
|
||||
auto base_split = base_traits->split_2_object();
|
||||
base_split(cv.base(), p.base(), c1.base(), c2.base());
|
||||
|
|
@ -250,8 +242,7 @@ public:
|
|||
* \param cv The curve.
|
||||
* \return The left endpoint.
|
||||
*/
|
||||
Point_2 operator()(const X_monotone_curve_2 & cv) const
|
||||
{
|
||||
Point_2 operator()(const X_monotone_curve_2 & cv) const {
|
||||
const auto* base_traits = m_traits.m_base_traits;
|
||||
auto base_ctr_min_vertex = base_traits->construct_min_vertex_2_object();
|
||||
|
||||
|
|
@ -290,8 +281,7 @@ public:
|
|||
* \param cv The curve.
|
||||
* \return The left endpoint.
|
||||
*/
|
||||
Point_2 operator() (const X_monotone_curve_2 & cv) const
|
||||
{
|
||||
Point_2 operator() (const X_monotone_curve_2 & cv) const {
|
||||
const auto* base_traits = m_traits.m_base_traits;
|
||||
auto base_ctr_max_vertex = base_traits->construct_max_vertex_2_object();
|
||||
if (! m_traits.is_valid_index(cv.data().index()))
|
||||
|
|
@ -329,8 +319,7 @@ public:
|
|||
* \param cv The curve.
|
||||
* \return The left endpoint.
|
||||
*/
|
||||
Comparison_result operator()(const Point_2& p1, const Point_2& p2) const
|
||||
{
|
||||
Comparison_result operator()(const Point_2& p1, const Point_2& p2) const {
|
||||
const auto* base_traits = m_traits.m_base_traits;
|
||||
auto base_cmp_xy = base_traits->compare_xy_2_object();
|
||||
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@
|
|||
// Ron Wein <wein@post.tau.ac.il>
|
||||
// Efi Fogel <efifogel@gmail.com>
|
||||
|
||||
#ifndef CGAL_BSO_2_INDEXED_VISITOR_H
|
||||
#define CGAL_BSO_2_INDEXED_VISITOR_H
|
||||
#ifndef CGAL_INDEXED_VISITOR_H
|
||||
#define CGAL_INDEXED_VISITOR_H
|
||||
|
||||
#include <CGAL/license/Boolean_set_operations_2.h>
|
||||
|
||||
|
|
@ -32,17 +32,16 @@ class Indexed_event :
|
|||
Arrangement_,
|
||||
Allocator_>,
|
||||
Allocator_>,
|
||||
Arrangement_>
|
||||
{
|
||||
Arrangement_> {
|
||||
private:
|
||||
unsigned int m_index;
|
||||
std::size_t m_index;
|
||||
|
||||
public:
|
||||
Indexed_event() : m_index (0) {}
|
||||
|
||||
unsigned int index() const { return (m_index); }
|
||||
std::size_t index() const { return (m_index); }
|
||||
|
||||
void set_index(unsigned int index) { m_index = index; }
|
||||
void set_index(std::size_t index) { m_index = index; }
|
||||
};
|
||||
|
||||
} // namespace CGAL
|
||||
|
|
|
|||
|
|
@ -31,9 +31,9 @@ namespace CGAL {
|
|||
// Utility struct
|
||||
template <typename Polygon>
|
||||
struct Gps_polyline_traits {
|
||||
typedef typename Gps_default_traits<Polygon>::Arr_traits Segment_traits;
|
||||
typedef Arr_polyline_traits_2<Segment_traits> Polyline_traits;
|
||||
typedef Gps_traits_2<Polyline_traits> Traits;
|
||||
using Segment_traits = typename Gps_default_traits<Polygon>::Arr_traits;
|
||||
using Polyline_traits = Arr_polyline_traits_2<Segment_traits>;
|
||||
using Traits = Gps_traits_2<Polyline_traits>;
|
||||
};
|
||||
|
||||
// Helper to map Polygon_2 -> General_polygon_2 / PWH_2 -> General_PWH_2
|
||||
|
|
@ -85,9 +85,7 @@ using Disable_if_Polygon_2_iterator =
|
|||
// Convert Polygon_2 to General_polygon_2<Polyline_traits>
|
||||
template <typename Kernel, typename Container, typename ArrTraits>
|
||||
General_polygon_2<ArrTraits>
|
||||
convert_polygon(const Polygon_2<Kernel, Container>& polygon,
|
||||
const ArrTraits& traits)
|
||||
{
|
||||
convert_polygon(const Polygon_2<Kernel, Container>& polygon, const ArrTraits& traits) {
|
||||
auto ctr = traits.construct_curve_2_object();
|
||||
if (polygon.is_empty()) return General_polygon_2<ArrTraits>();
|
||||
using Point = typename ArrTraits::Point_2;
|
||||
|
|
@ -99,22 +97,20 @@ convert_polygon(const Polygon_2<Kernel, Container>& polygon,
|
|||
General_polygon_2<ArrTraits> gpgn;
|
||||
auto make_x_mtn = traits.make_x_monotone_2_object();
|
||||
make_x_mtn(cv,
|
||||
boost::make_function_output_iterator
|
||||
([&](const Make_x_monotone_result& obj)
|
||||
{ gpgn.push_back(*(std::get_if<X_monotone_curve>(&obj))); }));
|
||||
boost::make_function_output_iterator([&](const Make_x_monotone_result& obj)
|
||||
{ gpgn.push_back(*(std::get_if<X_monotone_curve>(&obj))); }));
|
||||
return gpgn;
|
||||
}
|
||||
|
||||
// Convert Polygon_with_holes_2 to General_polygon_with_holes_2<Polyline_traits>
|
||||
template <typename Kernel, typename Container, typename ArrTraits>
|
||||
General_polygon_with_holes_2<General_polygon_2<ArrTraits> >
|
||||
General_polygon_with_holes_2<General_polygon_2<ArrTraits>>
|
||||
convert_polygon(const Polygon_with_holes_2<Kernel, Container>& pwh,
|
||||
const ArrTraits& traits) {
|
||||
typedef General_polygon_2<ArrTraits> General_pgn;
|
||||
typedef Polygon_2<Kernel, Container> Pgn;
|
||||
auto converter = [&](const Pgn& pgn)->General_pgn {
|
||||
return convert_polygon(pgn, traits);
|
||||
};
|
||||
using General_pgn = General_polygon_2<ArrTraits>;
|
||||
using Pgn = Polygon_2<Kernel, Container>;
|
||||
auto converter = [&](const Pgn& pgn)->General_pgn
|
||||
{ return convert_polygon(pgn, traits); };
|
||||
return General_polygon_with_holes_2<General_polygon_2<ArrTraits>>
|
||||
(convert_polygon(pwh.outer_boundary(), traits),
|
||||
boost::make_transform_iterator(pwh.holes().begin(), converter),
|
||||
|
|
@ -137,14 +133,11 @@ convert_polygon_back(const General_polygon_2<ArrTraits>& gpgn) {
|
|||
// Convert General_polygon_with_holes_2<Polyline_traits> to Polygon_with_holes_2
|
||||
template <typename Kernel, typename Container, typename ArrTraits>
|
||||
Polygon_with_holes_2<Kernel, Container>
|
||||
convert_polygon_back(const General_polygon_with_holes_2
|
||||
<General_polygon_2<ArrTraits> >& gpwh)
|
||||
{
|
||||
convert_polygon_back(const General_polygon_with_holes_2<General_polygon_2<ArrTraits>>& gpwh) {
|
||||
using Pgn = Polygon_2<Kernel, Container>;
|
||||
using General_pgn = General_polygon_2<ArrTraits>;
|
||||
auto converter = [](const General_pgn& gpgn)->Pgn {
|
||||
return convert_polygon_back<Kernel, Container>(gpgn);
|
||||
};
|
||||
auto converter = [](const General_pgn& gpgn)->Pgn
|
||||
{ return convert_polygon_back<Kernel, Container>(gpgn); };
|
||||
return Polygon_with_holes_2<Kernel, Container>
|
||||
(convert_polygon_back<Kernel, Container>(gpwh.outer_boundary()),
|
||||
boost::make_transform_iterator(gpwh.holes().begin(), converter),
|
||||
|
|
@ -155,21 +148,17 @@ convert_polygon_back(const General_polygon_with_holes_2
|
|||
// Polygon_2 to General_polygon_2<Polyline_traits>, or
|
||||
// Polygon_with_holes_2 to General_polygon_with_holes_2<Polyline_traits>
|
||||
template <typename InputIterator, typename Traits>
|
||||
boost::transform_iterator
|
||||
<std::function
|
||||
<typename General_polygon_of_polygon<typename std::iterator_traits
|
||||
<InputIterator>::value_type>::type
|
||||
(typename std::iterator_traits<InputIterator>::reference)>,
|
||||
InputIterator>
|
||||
convert_polygon_iterator(InputIterator it, const Traits& traits)
|
||||
{
|
||||
boost::transform_iterator<std::function<
|
||||
typename General_polygon_of_polygon<typename std::iterator_traits<
|
||||
InputIterator>::value_type>::type
|
||||
(typename std::iterator_traits<InputIterator>::reference)>, InputIterator>
|
||||
convert_polygon_iterator(InputIterator it, const Traits& traits) {
|
||||
using Input_type = typename std::iterator_traits<InputIterator>::value_type;
|
||||
using Return_type = typename General_polygon_of_polygon<Input_type>::type;
|
||||
using Function_type = std::function<Return_type(Input_type)>;
|
||||
|
||||
Function_type func =
|
||||
[&traits](const Input_type& p)->Return_type
|
||||
{ return convert_polygon(p, traits); };
|
||||
Function_type func = [&traits](const Input_type& p)->Return_type
|
||||
{ return convert_polygon(p, traits); };
|
||||
|
||||
return boost::transform_iterator<Function_type, InputIterator>(it, func);
|
||||
}
|
||||
|
|
@ -186,8 +175,7 @@ struct Polygon_converter {
|
|||
|
||||
// Convert and export to output iterator.
|
||||
template <typename ArrTraits>
|
||||
void operator()(const General_polygon_with_holes_2
|
||||
<General_polygon_2<ArrTraits> >& gpwh) const
|
||||
void operator()(const General_polygon_with_holes_2<General_polygon_2<ArrTraits>>& gpwh) const
|
||||
{ *m_output++ = convert_polygon_back<Kernel, Container>(gpwh); }
|
||||
};
|
||||
|
||||
|
|
@ -195,9 +183,7 @@ struct Polygon_converter {
|
|||
// OutputIterator
|
||||
template <typename Kernel, typename Container, typename OutputIterator>
|
||||
struct Polygon_converter_output_iterator :
|
||||
boost::function_output_iterator<Polygon_converter
|
||||
<Kernel, Container, OutputIterator> >
|
||||
{
|
||||
boost::function_output_iterator<Polygon_converter<Kernel, Container, OutputIterator>> {
|
||||
using Converter = Polygon_converter<Kernel, Container, OutputIterator>;
|
||||
using Base = boost::function_output_iterator<Converter>;
|
||||
|
||||
|
|
@ -214,11 +200,8 @@ struct Polygon_converter_output_iterator :
|
|||
// (indirection with Polygon_2)
|
||||
template <typename OutputIterator, typename Kernel, typename Container>
|
||||
Polygon_converter_output_iterator<Kernel, Container, OutputIterator>
|
||||
convert_polygon_back(OutputIterator& output,
|
||||
const Polygon_2<Kernel, Container>&)
|
||||
{
|
||||
return Polygon_converter_output_iterator
|
||||
<Kernel, Container, OutputIterator>(output);
|
||||
convert_polygon_back(OutputIterator& output, const Polygon_2<Kernel, Container>&) {
|
||||
return Polygon_converter_output_iterator<Kernel, Container, OutputIterator>(output);
|
||||
}
|
||||
|
||||
// Converts General_polygon_with_holes_2<Polyline_traits> to Polygon_with_holes_2
|
||||
|
|
@ -226,10 +209,8 @@ convert_polygon_back(OutputIterator& output,
|
|||
template <typename OutputIterator, typename Kernel, typename Container>
|
||||
Polygon_converter_output_iterator<Kernel, Container, OutputIterator>
|
||||
convert_polygon_back(OutputIterator& output,
|
||||
const Polygon_with_holes_2<Kernel, Container>&)
|
||||
{
|
||||
return Polygon_converter_output_iterator
|
||||
<Kernel, Container, OutputIterator>(output);
|
||||
const Polygon_with_holes_2<Kernel, Container>&) {
|
||||
return Polygon_converter_output_iterator<Kernel, Container, OutputIterator>(output);
|
||||
}
|
||||
|
||||
template <typename InputIterator>
|
||||
|
|
@ -238,7 +219,6 @@ struct Iterator_to_gps_traits {
|
|||
typedef typename Gps_default_traits<InputPolygon>::Traits Traits;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif // CGAL_BSO_POLYGON_CONVERSIONS_H
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -8,10 +8,10 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
//
|
||||
// Author(s): Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ron Wein <wein@post.tau.ac.il>
|
||||
// Efi Fogel <efif@post.tau.ac.il>
|
||||
// Simon Giraudot <simon.giraudot@geometryfactory.com>
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ron Wein <wein@post.tau.ac.il>
|
||||
// Efi Fogel <efif@post.tau.ac.il>
|
||||
// Simon Giraudot <simon.giraudot@geometryfactory.com>
|
||||
|
||||
#ifndef CGAL_BOOLEAN_SET_OPERATIONS_2_DO_INTERSECT_H
|
||||
#define CGAL_BOOLEAN_SET_OPERATIONS_2_DO_INTERSECT_H
|
||||
|
|
@ -33,12 +33,18 @@
|
|||
#include <CGAL/Boolean_set_operations_2/Polygon_conversions.h>
|
||||
#include <CGAL/type_traits/is_iterator.h>
|
||||
|
||||
namespace CGAL
|
||||
{
|
||||
namespace CGAL {
|
||||
|
||||
/// \name do_intersect() functions.
|
||||
//@{
|
||||
|
||||
/*! We do not use polyline for do_intersect), as we rely on the overlay traits
|
||||
* to only intercept intersections between the interiors of segments that
|
||||
* comprise the boundary of polygons. Observe that The intersections between the
|
||||
* interiors of polylines that comprise the boundary of polygons may include an
|
||||
* endpoint of a segment, and we do not want that.
|
||||
*/
|
||||
|
||||
// Polygon_2, Polygon_2 ========================================================
|
||||
// With Traits
|
||||
template <typename Kernel, typename Container, typename Traits>
|
||||
|
|
@ -47,24 +53,24 @@ inline bool do_intersect(const Polygon_2<Kernel, Container>& pgn1,
|
|||
Traits& traits)
|
||||
{ return s_do_intersect(pgn1, pgn2, traits); }
|
||||
|
||||
// With Tag_true
|
||||
// without traits
|
||||
template <typename Kernel, typename Container>
|
||||
inline bool do_intersect(const Polygon_2<Kernel, Container>& pgn1,
|
||||
const Polygon_2<Kernel, Container>& pgn2,
|
||||
Tag_true = Tag_true())
|
||||
{ return s_do_intersect(pgn1, pgn2); }
|
||||
|
||||
// With Tag_false
|
||||
template <typename Kernel, typename Container>
|
||||
inline bool do_intersect(const Polygon_2<Kernel, Container>& pgn1,
|
||||
const Polygon_2<Kernel, Container>& pgn2,
|
||||
Tag_false)
|
||||
{
|
||||
typedef Polygon_2<Kernel, Container> Polygon;
|
||||
const Polygon_2<Kernel, Container>& pgn2) {
|
||||
using Polygon = Polygon_2<Kernel, Container>;
|
||||
typename Gps_default_traits<Polygon>::Traits traits;
|
||||
return s_do_intersect(pgn1, pgn2, traits);
|
||||
}
|
||||
|
||||
#ifndef CGAL_NO_DEPRECATED_CODE
|
||||
template <typename Kernel, typename Container, bool b>
|
||||
inline bool do_intersect(const Polygon_2<Kernel, Container>& pgn1,
|
||||
const Polygon_2<Kernel, Container>& pgn2,
|
||||
std::bool_constant<b>) {
|
||||
return do_intersect(pgn1, pgn2);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Polygon_2, Polygon_with_hole_2 ==============================================
|
||||
// With Traits
|
||||
template <typename Kernel, typename Container, typename Traits>
|
||||
|
|
@ -73,25 +79,25 @@ inline bool do_intersect(const Polygon_2<Kernel, Container>& pgn1,
|
|||
Traits& traits)
|
||||
{ return s_do_intersect(pgn1, pgn2, traits); }
|
||||
|
||||
// With Tag_true
|
||||
// Without traits
|
||||
template <typename Kernel, typename Container>
|
||||
inline bool do_intersect(const Polygon_2<Kernel, Container>& pgn1,
|
||||
const Polygon_with_holes_2<Kernel, Container>& pgn2,
|
||||
Tag_true = Tag_true())
|
||||
{ return s_do_intersect(pgn1, pgn2); }
|
||||
|
||||
// With Tag_false
|
||||
template <typename Kernel, typename Container>
|
||||
inline bool do_intersect(const Polygon_2<Kernel, Container>& pgn1,
|
||||
const Polygon_with_holes_2<Kernel, Container>& pgn2,
|
||||
Tag_false)
|
||||
{
|
||||
const Polygon_with_holes_2<Kernel, Container>& pgn2) {
|
||||
// Use the first polygon to determine the (default) traits
|
||||
typedef Polygon_2<Kernel, Container> Polygon;
|
||||
using Polygon = Polygon_2<Kernel, Container>;
|
||||
typename Gps_default_traits<Polygon>::Traits traits;
|
||||
return s_do_intersect(pgn1, pgn2, traits);
|
||||
}
|
||||
|
||||
#ifndef CGAL_NO_DEPRECATED_CODE
|
||||
template <typename Kernel, typename Container, bool b>
|
||||
inline bool do_intersect(const Polygon_2<Kernel, Container>& pgn1,
|
||||
const Polygon_with_holes_2<Kernel, Container>& pgn2,
|
||||
std::bool_constant<b>) {
|
||||
return do_intersect(pgn1, pgn2);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Polygon_with_hole_2, Polygon_2 ==============================================
|
||||
// With Traits
|
||||
template <typename Kernel, typename Container, typename Traits>
|
||||
|
|
@ -100,25 +106,25 @@ inline bool do_intersect(const Polygon_with_holes_2<Kernel, Container>& pgn1,
|
|||
Traits& traits)
|
||||
{ return s_do_intersect(pgn1, pgn2, traits); }
|
||||
|
||||
// With Tag_true
|
||||
// Without traits
|
||||
template <typename Kernel, typename Container>
|
||||
inline bool do_intersect(const Polygon_with_holes_2<Kernel, Container>& pgn1,
|
||||
const Polygon_2<Kernel, Container>& pgn2,
|
||||
Tag_true = Tag_true())
|
||||
{ return s_do_intersect(pgn1, pgn2); }
|
||||
|
||||
// With Tag_false
|
||||
template <typename Kernel, typename Container>
|
||||
inline bool do_intersect(const Polygon_with_holes_2<Kernel, Container>& pgn1,
|
||||
const Polygon_2<Kernel, Container>& pgn2,
|
||||
Tag_false)
|
||||
{
|
||||
const Polygon_2<Kernel, Container>& pgn2) {
|
||||
// Use the first polygon to determine the (default) traits
|
||||
typedef Polygon_with_holes_2<Kernel, Container> Polygon_with_holes;
|
||||
using Polygon_with_holes = Polygon_with_holes_2<Kernel, Container>;
|
||||
typename Gps_default_traits<Polygon_with_holes>::Traits traits;
|
||||
return s_do_intersect(pgn1, pgn2, traits);
|
||||
}
|
||||
|
||||
#ifndef CGAL_NO_DEPRECATED_CODE
|
||||
template <typename Kernel, typename Container, bool b>
|
||||
inline bool do_intersect(const Polygon_with_holes_2<Kernel, Container>& pgn1,
|
||||
const Polygon_2<Kernel, Container>& pgn2,
|
||||
std::bool_constant<b>) {
|
||||
return do_intersect(pgn1, pgn2);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Polygon_with_hole_2, Polygon_with_hole_2 ====================================
|
||||
// With Traits
|
||||
template <typename Kernel, typename Container, typename Traits>
|
||||
|
|
@ -127,25 +133,25 @@ inline bool do_intersect(const Polygon_with_holes_2<Kernel, Container>& pgn1,
|
|||
Traits& traits)
|
||||
{ return s_do_intersect(pgn1, pgn2, traits); }
|
||||
|
||||
// With Tag_true
|
||||
// Without traits
|
||||
template <typename Kernel, typename Container>
|
||||
inline bool do_intersect(const Polygon_with_holes_2<Kernel, Container>& pgn1,
|
||||
const Polygon_with_holes_2<Kernel, Container>& pgn2,
|
||||
Tag_true = Tag_true())
|
||||
{ return s_do_intersect(pgn1, pgn2); }
|
||||
|
||||
// With Tag_false
|
||||
template <typename Kernel, typename Container>
|
||||
inline bool do_intersect(const Polygon_with_holes_2<Kernel, Container>& pgn1,
|
||||
const Polygon_with_holes_2<Kernel, Container>& pgn2,
|
||||
Tag_false)
|
||||
{
|
||||
const Polygon_with_holes_2<Kernel, Container>& pgn2) {
|
||||
// Use the first polygon to determine the (default) traits
|
||||
typedef Polygon_with_holes_2<Kernel, Container> Polygon_with_holes;
|
||||
using Polygon_with_holes = Polygon_with_holes_2<Kernel, Container>;
|
||||
typename Gps_default_traits<Polygon_with_holes>::Traits traits;
|
||||
return s_do_intersect(pgn1, pgn2, traits);
|
||||
}
|
||||
|
||||
#ifndef CGAL_NO_DEPRECATED_CODE
|
||||
template <typename Kernel, typename Container, bool b>
|
||||
inline bool do_intersect(const Polygon_with_holes_2<Kernel, Container>& pgn1,
|
||||
const Polygon_with_holes_2<Kernel, Container>& pgn2,
|
||||
std::bool_constant<b>) {
|
||||
return do_intersect(pgn1, pgn2);
|
||||
}
|
||||
#endif
|
||||
|
||||
// General_polygon_2, General_polygon_2 ========================================
|
||||
// With Traits
|
||||
template <typename ArrTraits, typename GpsTraits>
|
||||
|
|
@ -157,14 +163,22 @@ inline bool do_intersect(const General_polygon_2<ArrTraits>& pgn1,
|
|||
// Without Traits
|
||||
template <typename ArrTraits>
|
||||
inline bool do_intersect(const General_polygon_2<ArrTraits>& pgn1,
|
||||
const General_polygon_2<ArrTraits>& pgn2)
|
||||
{
|
||||
const General_polygon_2<ArrTraits>& pgn2) {
|
||||
// Use the first polygon to determine the (default) traits
|
||||
typedef General_polygon_2<ArrTraits> Polygon;
|
||||
using Polygon = General_polygon_2<ArrTraits>;
|
||||
typename Gps_default_traits<Polygon>::Traits traits;
|
||||
return s_do_intersect(pgn1, pgn2, traits);
|
||||
}
|
||||
|
||||
#ifndef CGAL_NO_DEPRECATED_CODE
|
||||
template <typename ArrTraits, bool b>
|
||||
inline bool do_intersect(const General_polygon_2<ArrTraits>& pgn1,
|
||||
const General_polygon_2<ArrTraits>& pgn2,
|
||||
std::bool_constant<b>) {
|
||||
return do_intersect(pgn1, pgn2);
|
||||
}
|
||||
#endif
|
||||
|
||||
// General_polygon_2, General_polygon_with_holes_2 =============================
|
||||
// With Traits
|
||||
template <typename ArrTraits, typename GpsTraits>
|
||||
|
|
@ -178,14 +192,23 @@ inline bool do_intersect(const General_polygon_2<ArrTraits>& pgn1,
|
|||
template <typename ArrTraits>
|
||||
inline bool do_intersect(const General_polygon_2<ArrTraits>& pgn1,
|
||||
const General_polygon_with_holes_2
|
||||
<General_polygon_2<ArrTraits> >& pgn2)
|
||||
{
|
||||
<General_polygon_2<ArrTraits> >& pgn2) {
|
||||
// Use the first polygon to determine the (default) traits
|
||||
typedef General_polygon_2<ArrTraits> Polygon;
|
||||
using Polygon = General_polygon_2<ArrTraits>;
|
||||
typename Gps_default_traits<Polygon>::Traits traits;
|
||||
return s_do_intersect(pgn1, pgn2, traits);
|
||||
}
|
||||
|
||||
#ifndef CGAL_NO_DEPRECATED_CODE
|
||||
template <typename ArrTraits, bool b>
|
||||
inline bool do_intersect(const General_polygon_2<ArrTraits>& pgn1,
|
||||
const General_polygon_with_holes_2
|
||||
<General_polygon_2<ArrTraits> >& pgn2,
|
||||
std::bool_constant<b>) {
|
||||
return do_intersect(pgn1, pgn2);
|
||||
}
|
||||
#endif
|
||||
|
||||
// General_polygon_with_holes_2, General_polygon_2 =============================
|
||||
// With Traits
|
||||
template <typename ArrTraits, typename GpsTraits>
|
||||
|
|
@ -199,15 +222,25 @@ inline bool do_intersect(const General_polygon_with_holes_2
|
|||
template <typename ArrTraits>
|
||||
inline bool do_intersect(const General_polygon_with_holes_2
|
||||
<General_polygon_2<ArrTraits> >& pgn1,
|
||||
const General_polygon_2<ArrTraits>& pgn2)
|
||||
{
|
||||
const General_polygon_2<ArrTraits>& pgn2) {
|
||||
// Use the first polygon to determine the (default) traits
|
||||
typedef General_polygon_2<ArrTraits> Polygon;
|
||||
typedef General_polygon_with_holes_2<Polygon> Polygon_with_holes;
|
||||
using Polygon = General_polygon_2<ArrTraits>;
|
||||
using Polygon_with_holes = General_polygon_with_holes_2<Polygon>;
|
||||
typename Gps_default_traits<Polygon_with_holes>::Traits traits;
|
||||
return s_do_intersect(pgn1, pgn2, traits);
|
||||
}
|
||||
|
||||
#ifndef CGAL_NO_DEPRECATED_CODE
|
||||
template <typename ArrTraits, bool b>
|
||||
inline bool do_intersect(const General_polygon_with_holes_2
|
||||
<General_polygon_2<ArrTraits> >& pgn1,
|
||||
const General_polygon_2<ArrTraits>& pgn2,
|
||||
std::bool_constant<b>) {
|
||||
return do_intersect(pgn1, pgn2);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// General_polygon_with_holes_2, General_polygon_with_holes_2 ==================
|
||||
// With Traits
|
||||
template <typename Polygon_, typename Traits>
|
||||
|
|
@ -219,14 +252,22 @@ inline bool do_intersect(const General_polygon_with_holes_2<Polygon_>& pgn1,
|
|||
// Without Traits
|
||||
template <typename Polygon_>
|
||||
inline bool do_intersect(const General_polygon_with_holes_2<Polygon_>& pgn1,
|
||||
const General_polygon_with_holes_2<Polygon_>& pgn2)
|
||||
{
|
||||
const General_polygon_with_holes_2<Polygon_>& pgn2) {
|
||||
// Use the first polygon to determine the (default) traits
|
||||
typedef General_polygon_with_holes_2<Polygon_> Polygon_with_holes;
|
||||
using Polygon_with_holes = General_polygon_with_holes_2<Polygon_>;
|
||||
typename Gps_default_traits<Polygon_with_holes>::Traits traits;
|
||||
return s_do_intersect(pgn1, pgn2, traits);
|
||||
}
|
||||
|
||||
#ifndef CGAL_NO_DEPRECATED_CODE
|
||||
template <typename Polygon_, bool b>
|
||||
inline bool do_intersect(const General_polygon_with_holes_2<Polygon_>& pgn1,
|
||||
const General_polygon_with_holes_2<Polygon_>& pgn2,
|
||||
std::bool_constant<b>) {
|
||||
return do_intersect(pgn1, pgn2);
|
||||
}
|
||||
#endif
|
||||
|
||||
//@}
|
||||
|
||||
/// \name Aggregated do_intersect() functions.
|
||||
|
|
@ -235,26 +276,15 @@ inline bool do_intersect(const General_polygon_with_holes_2<Polygon_>& pgn1,
|
|||
// With Traits
|
||||
template <typename InputIterator, typename Traits>
|
||||
inline bool do_intersect(InputIterator begin, InputIterator end, Traits& traits,
|
||||
unsigned int k=5,
|
||||
std::size_t k = 5,
|
||||
std::enable_if_t<CGAL::is_iterator<InputIterator>::value>* = 0)
|
||||
{ return r_do_intersect(begin, end, traits, k); }
|
||||
|
||||
// Without Traits
|
||||
// Tag_true => convert to polylines
|
||||
template <typename InputIterator>
|
||||
inline bool do_intersect(InputIterator begin, InputIterator end,
|
||||
Tag_true = Tag_true(), unsigned int k=5,
|
||||
inline bool do_intersect(InputIterator begin, InputIterator end, std::size_t k = 5,
|
||||
std::enable_if_t<CGAL::is_iterator<InputIterator>::value>* = 0,
|
||||
Enable_if_Polygon_2_iterator<InputIterator>* = 0)
|
||||
{ return r_do_intersect(begin, end, k); }
|
||||
|
||||
// Tag_false => do not convert to polylines
|
||||
template <typename InputIterator>
|
||||
inline bool do_intersect(InputIterator begin, InputIterator end,
|
||||
Tag_false, unsigned int k=5,
|
||||
std::enable_if_t<CGAL::is_iterator<InputIterator>::value>* = 0,
|
||||
Enable_if_Polygon_2_iterator<InputIterator>* = 0)
|
||||
{
|
||||
Enable_if_Polygon_2_iterator<InputIterator>* = 0) {
|
||||
typename Iterator_to_gps_traits<InputIterator>::Traits traits;
|
||||
return r_do_intersect(begin, end, traits, k);
|
||||
}
|
||||
|
|
@ -262,49 +292,57 @@ inline bool do_intersect(InputIterator begin, InputIterator end,
|
|||
// General polygons or polygons with holes
|
||||
template <typename InputIterator>
|
||||
inline bool do_intersect(InputIterator begin, InputIterator end,
|
||||
unsigned int k=5,
|
||||
std::size_t k = 5,
|
||||
std::enable_if_t<CGAL::is_iterator<InputIterator>::value>* = 0,
|
||||
Disable_if_Polygon_2_iterator<InputIterator>* = 0)
|
||||
{
|
||||
Disable_if_Polygon_2_iterator<InputIterator>* = 0) {
|
||||
typename Iterator_to_gps_traits<InputIterator>::Traits traits;
|
||||
return do_intersect(begin, end, traits, k);
|
||||
}
|
||||
|
||||
#ifndef CGAL_NO_DEPRECATED_CODE
|
||||
template <typename InputIterator, bool b>
|
||||
inline bool do_intersect(InputIterator begin, InputIterator end, std::bool_constant<b>,
|
||||
std::enable_if_t<CGAL::is_iterator<InputIterator>::value>* = 0) {
|
||||
return do_intersect(begin, end);
|
||||
}
|
||||
#endif
|
||||
|
||||
// With Traits
|
||||
template <typename InputIterator1, typename InputIterator2, typename Traits>
|
||||
inline bool do_intersect(InputIterator1 begin1, InputIterator1 end1,
|
||||
InputIterator2 begin2, InputIterator2 end2,
|
||||
Traits& traits, unsigned int k=5)
|
||||
Traits& traits, std::size_t k = 5)
|
||||
{ return r_do_intersect(begin1, end1, begin2, end2, traits, k); }
|
||||
|
||||
// Without Traits
|
||||
// Tag_true => convert to polylines
|
||||
template <typename InputIterator1, typename InputIterator2>
|
||||
inline bool do_intersect (InputIterator1 begin1, InputIterator1 end1,
|
||||
InputIterator2 begin2, InputIterator2 end2,
|
||||
Tag_true = Tag_true(), unsigned int k=5,
|
||||
Enable_if_Polygon_2_iterator<InputIterator1>* = 0)
|
||||
{ return r_do_intersect(begin1, end1, begin2, end2, k); }
|
||||
|
||||
// Tag_false => do not convert to polylines
|
||||
template <typename InputIterator1, typename InputIterator2>
|
||||
inline bool do_intersect (InputIterator1 begin1, InputIterator1 end1,
|
||||
InputIterator2 begin2, InputIterator2 end2,
|
||||
Tag_false, unsigned int k=5,
|
||||
Enable_if_Polygon_2_iterator<InputIterator1>* = 0)
|
||||
inline bool do_intersect(InputIterator1 begin1, InputIterator1 end1,
|
||||
InputIterator2 begin2, InputIterator2 end2,
|
||||
std::size_t k = 5,
|
||||
Enable_if_Polygon_2_iterator<InputIterator1>* = 0)
|
||||
{ return r_do_intersect(begin1, end1, begin2, end2, k); }
|
||||
|
||||
// General polygons or polygons with holes
|
||||
template <typename InputIterator1, typename InputIterator2>
|
||||
inline bool do_intersect (InputIterator1 begin1, InputIterator1 end1,
|
||||
InputIterator2 begin2, InputIterator2 end2,
|
||||
unsigned int k=5,
|
||||
Disable_if_Polygon_2_iterator<InputIterator1>* = 0)
|
||||
{
|
||||
inline bool do_intersect(InputIterator1 begin1, InputIterator1 end1,
|
||||
InputIterator2 begin2, InputIterator2 end2,
|
||||
std::size_t k = 5,
|
||||
Disable_if_Polygon_2_iterator<InputIterator1>* = 0) {
|
||||
typename Iterator_to_gps_traits<InputIterator1>::Traits traits;
|
||||
return r_do_intersect(begin1, end1, begin2, end2, traits, k);
|
||||
}
|
||||
|
||||
#ifndef CGAL_NO_DEPRECATED_CODE
|
||||
template <typename InputIterator1, typename InputIterator2, bool b>
|
||||
inline bool do_intersect(InputIterator1 begin1, InputIterator1 end1,
|
||||
InputIterator2 begin2, InputIterator2 end2,
|
||||
std::bool_constant<b>,
|
||||
std::enable_if_t<CGAL::is_iterator<InputIterator1>::value &&
|
||||
CGAL::is_iterator<InputIterator2>::value >* = 0) {
|
||||
return do_intersect(begin1, end1, begin2, end2);
|
||||
}
|
||||
#endif
|
||||
|
||||
//@}
|
||||
|
||||
} //namespace CGAL
|
||||
|
|
|
|||
|
|
@ -7,11 +7,10 @@
|
|||
// $Id$
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
//
|
||||
// Author(s): Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ron Wein <wein@post.tau.ac.il>
|
||||
// Efi Fogel <efif@post.tau.ac.il>
|
||||
// Simon Giraudot <simon.giraudot@geometryfactory.com>
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ron Wein <wein@post.tau.ac.il>
|
||||
// Efi Fogel <efif@post.tau.ac.il>
|
||||
// Simon Giraudot <simon.giraudot@geometryfactory.com>
|
||||
|
||||
#ifndef CGAL_BOOLEAN_SET_OPERATIONS_2_INTERSECTION_H
|
||||
#define CGAL_BOOLEAN_SET_OPERATIONS_2_INTERSECTION_H
|
||||
|
|
@ -33,8 +32,7 @@
|
|||
#include <CGAL/Boolean_set_operations_2/Polygon_conversions.h>
|
||||
#include <CGAL/type_traits/is_iterator.h>
|
||||
|
||||
namespace CGAL
|
||||
{
|
||||
namespace CGAL {
|
||||
|
||||
/// \name intersection() functions.
|
||||
//@{
|
||||
|
|
@ -59,10 +57,9 @@ inline OutputIterator intersection(const Polygon_2<Kernel, Container>& pgn1,
|
|||
template <typename Kernel, typename Container, typename OutputIterator>
|
||||
inline OutputIterator intersection(const Polygon_2<Kernel, Container>& pgn1,
|
||||
const Polygon_2<Kernel, Container>& pgn2,
|
||||
OutputIterator out, Tag_false)
|
||||
{
|
||||
OutputIterator out, Tag_false) {
|
||||
// Use the first polygon to determine the (default) traits
|
||||
typedef Polygon_2<Kernel, Container> Polygon;
|
||||
using Polygon = Polygon_2<Kernel, Container>;
|
||||
typename Gps_default_traits<Polygon>::Traits traits;
|
||||
return s_intersection(pgn1, pgn2, out, traits);
|
||||
}
|
||||
|
|
@ -90,10 +87,9 @@ template <typename Kernel, typename Container, typename OutputIterator>
|
|||
inline OutputIterator
|
||||
intersection(const Polygon_2<Kernel, Container>& pgn1,
|
||||
const Polygon_with_holes_2<Kernel, Container>& pgn2,
|
||||
OutputIterator out, Tag_false)
|
||||
{
|
||||
OutputIterator out, Tag_false) {
|
||||
// Use the first polygon to determine the (default) traits
|
||||
typedef Polygon_2<Kernel, Container> Polygon;
|
||||
using Polygon = Polygon_2<Kernel, Container>;
|
||||
typename Gps_default_traits<Polygon>::Traits traits;
|
||||
return s_intersection(pgn1, pgn2, out, traits);
|
||||
}
|
||||
|
|
@ -121,10 +117,9 @@ template <typename Kernel, typename Container, typename OutputIterator>
|
|||
inline OutputIterator
|
||||
intersection(const Polygon_with_holes_2<Kernel, Container>& pgn1,
|
||||
const Polygon_2<Kernel, Container>& pgn2,
|
||||
OutputIterator out, Tag_false)
|
||||
{
|
||||
OutputIterator out, Tag_false) {
|
||||
// Use the first polygon to determine the (default) traits
|
||||
typedef Polygon_with_holes_2<Kernel, Container> Polygon_with_holes;
|
||||
using Polygon_with_holes = Polygon_with_holes_2<Kernel, Container>;
|
||||
typename Gps_default_traits<Polygon_with_holes>::Traits traits;
|
||||
return s_intersection(pgn1, pgn2, out, traits);
|
||||
}
|
||||
|
|
@ -152,10 +147,9 @@ template <typename Kernel, typename Container, typename OutputIterator>
|
|||
inline OutputIterator
|
||||
intersection(const Polygon_with_holes_2<Kernel, Container>& pgn1,
|
||||
const Polygon_with_holes_2<Kernel, Container>& pgn2,
|
||||
OutputIterator out, Tag_false)
|
||||
{
|
||||
OutputIterator out, Tag_false) {
|
||||
// Use the first polygon to determine the (default) traits
|
||||
typedef Polygon_with_holes_2<Kernel, Container> Polygon_with_holes;
|
||||
using Polygon_with_holes = Polygon_with_holes_2<Kernel, Container>;
|
||||
typename Gps_default_traits<Polygon_with_holes>::Traits traits;
|
||||
return s_intersection(pgn1, pgn2, out, traits);
|
||||
}
|
||||
|
|
@ -172,10 +166,9 @@ inline OutputIterator intersection(const General_polygon_2<ArrTraits>& pgn1,
|
|||
template <typename ArrTraits, typename OutputIterator>
|
||||
inline OutputIterator intersection(const General_polygon_2<ArrTraits>& pgn1,
|
||||
const General_polygon_2<ArrTraits>& pgn2,
|
||||
OutputIterator out)
|
||||
{
|
||||
OutputIterator out) {
|
||||
// Use the first polygon to determine the (default) traits
|
||||
typedef General_polygon_2<ArrTraits> Polygon;
|
||||
using Polygon = General_polygon_2<ArrTraits>;
|
||||
typename Gps_default_traits<Polygon>::Traits traits;
|
||||
return s_intersection(pgn1, pgn2, out, traits);
|
||||
}
|
||||
|
|
@ -194,10 +187,9 @@ template <typename ArrTraits, typename OutputIterator>
|
|||
inline OutputIterator intersection(const General_polygon_2<ArrTraits>& pgn1,
|
||||
const General_polygon_with_holes_2
|
||||
<General_polygon_2<ArrTraits> >& pgn2,
|
||||
OutputIterator out)
|
||||
{
|
||||
OutputIterator out) {
|
||||
// Use the first polygon to determine the (default) traits
|
||||
typedef General_polygon_2<ArrTraits> Polygon;
|
||||
using Polygon = General_polygon_2<ArrTraits>;
|
||||
typename Gps_default_traits<Polygon>::Traits traits;
|
||||
return s_intersection(pgn1, pgn2, out, traits);
|
||||
}
|
||||
|
|
@ -216,11 +208,10 @@ template <typename ArrTraits, typename OutputIterator>
|
|||
inline OutputIterator intersection(const General_polygon_with_holes_2
|
||||
<General_polygon_2<ArrTraits> >& pgn1,
|
||||
const General_polygon_2<ArrTraits>& pgn2,
|
||||
OutputIterator out)
|
||||
{
|
||||
OutputIterator out) {
|
||||
// Use the first polygon to determine the (default) traits
|
||||
typedef General_polygon_2<ArrTraits> Polygon;
|
||||
typedef General_polygon_with_holes_2<Polygon> Polygon_with_holes;
|
||||
using Polygon = General_polygon_2<ArrTraits>;
|
||||
using Polygon_with_holes = General_polygon_with_holes_2<Polygon>;
|
||||
typename Gps_default_traits<Polygon_with_holes>::Traits traits;
|
||||
return s_intersection(pgn1, pgn2, out, traits);
|
||||
}
|
||||
|
|
@ -239,10 +230,9 @@ template <typename Polygon_, typename OutputIterator>
|
|||
inline OutputIterator
|
||||
intersection(const General_polygon_with_holes_2<Polygon_>& pgn1,
|
||||
const General_polygon_with_holes_2<Polygon_>& pgn2,
|
||||
OutputIterator out)
|
||||
{
|
||||
OutputIterator out) {
|
||||
// Use the first polygon to determine the (default) traits
|
||||
typedef General_polygon_with_holes_2<Polygon_> Polygon_with_holes;
|
||||
using Polygon_with_holes = General_polygon_with_holes_2<Polygon_>;
|
||||
typename Gps_default_traits<Polygon_with_holes>::Traits traits;
|
||||
return s_intersection(pgn1, pgn2, out, traits);
|
||||
}
|
||||
|
|
@ -256,7 +246,7 @@ intersection(const General_polygon_with_holes_2<Polygon_>& pgn1,
|
|||
template <typename InputIterator, typename OutputIterator, typename Traits>
|
||||
inline OutputIterator intersection(InputIterator begin, InputIterator end,
|
||||
OutputIterator oi, Traits& traits,
|
||||
unsigned int k=5)
|
||||
std::size_t k = 5)
|
||||
{ return r_intersection(begin, end, oi, traits, k); }
|
||||
|
||||
// Without Traits
|
||||
|
|
@ -265,7 +255,7 @@ template <typename InputIterator, typename OutputIterator>
|
|||
inline OutputIterator
|
||||
intersection(InputIterator begin, InputIterator end,
|
||||
OutputIterator oi, Tag_true = Tag_true(),
|
||||
unsigned int k=5,
|
||||
std::size_t k = 5,
|
||||
Enable_if_Polygon_2_iterator<InputIterator>* = 0)
|
||||
{ return r_intersection(begin, end, oi, k); }
|
||||
|
||||
|
|
@ -273,9 +263,8 @@ intersection(InputIterator begin, InputIterator end,
|
|||
template <typename InputIterator, typename OutputIterator>
|
||||
inline OutputIterator
|
||||
intersection(InputIterator begin, InputIterator end,
|
||||
OutputIterator oi, Tag_false, unsigned int k=5,
|
||||
Enable_if_Polygon_2_iterator<InputIterator>* = 0)
|
||||
{
|
||||
OutputIterator oi, Tag_false, std::size_t k = 5,
|
||||
Enable_if_Polygon_2_iterator<InputIterator>* = 0) {
|
||||
typename Iterator_to_gps_traits<InputIterator>::Traits traits;
|
||||
return r_intersection(begin, end, oi, traits, k);
|
||||
}
|
||||
|
|
@ -284,11 +273,10 @@ intersection(InputIterator begin, InputIterator end,
|
|||
template <typename InputIterator, typename OutputIterator>
|
||||
inline OutputIterator
|
||||
intersection(InputIterator begin, InputIterator end,
|
||||
OutputIterator oi, unsigned int k=5,
|
||||
OutputIterator oi, std::size_t k = 5,
|
||||
// workaround to avoid ambiguous calls with kernel functions
|
||||
std::enable_if_t<CGAL::is_iterator<InputIterator>::value>* = 0,
|
||||
Disable_if_Polygon_2_iterator<InputIterator>* = 0)
|
||||
{
|
||||
Disable_if_Polygon_2_iterator<InputIterator>* = 0) {
|
||||
typename Iterator_to_gps_traits<InputIterator>::Traits traits;
|
||||
return r_intersection(begin, end, oi, traits, k);
|
||||
}
|
||||
|
|
@ -300,7 +288,7 @@ template <typename InputIterator1, typename InputIterator2,
|
|||
inline OutputIterator intersection(InputIterator1 begin1, InputIterator1 end1,
|
||||
InputIterator2 begin2, InputIterator2 end2,
|
||||
OutputIterator oi, Traits& traits,
|
||||
unsigned int k=5)
|
||||
std::size_t k = 5)
|
||||
{ return r_intersection(begin1, end1, begin2, end2, oi, traits, k); }
|
||||
|
||||
// Without Traits
|
||||
|
|
@ -310,7 +298,7 @@ template <typename InputIterator1, typename InputIterator2,
|
|||
inline OutputIterator
|
||||
intersection(InputIterator1 begin1, InputIterator1 end1,
|
||||
InputIterator2 begin2, InputIterator2 end2,
|
||||
OutputIterator oi, Tag_true = Tag_true(), unsigned int k=5,
|
||||
OutputIterator oi, Tag_true = Tag_true(), std::size_t k = 5,
|
||||
Enable_if_Polygon_2_iterator<InputIterator1>* = 0)
|
||||
{ return r_intersection(begin1, end1, begin2, end2, oi, k); }
|
||||
|
||||
|
|
@ -320,9 +308,8 @@ template <typename InputIterator1, typename InputIterator2,
|
|||
inline OutputIterator
|
||||
intersection(InputIterator1 begin1, InputIterator1 end1,
|
||||
InputIterator2 begin2, InputIterator2 end2,
|
||||
OutputIterator oi, Tag_false, unsigned int k=5,
|
||||
Enable_if_Polygon_2_iterator<InputIterator1>* = 0)
|
||||
{
|
||||
OutputIterator oi, Tag_false, std::size_t k = 5,
|
||||
Enable_if_Polygon_2_iterator<InputIterator1>* = 0) {
|
||||
typename Iterator_to_gps_traits<InputIterator1>::Traits traits;
|
||||
return r_intersection(begin1, end1, begin2, end2, oi, traits, k);
|
||||
}
|
||||
|
|
@ -333,9 +320,8 @@ template <typename InputIterator1, typename InputIterator2,
|
|||
inline OutputIterator
|
||||
intersection(InputIterator1 begin1, InputIterator1 end1,
|
||||
InputIterator2 begin2, InputIterator2 end2,
|
||||
OutputIterator oi, unsigned int k=5,
|
||||
Disable_if_Polygon_2_iterator<InputIterator1>* = 0)
|
||||
{
|
||||
OutputIterator oi, std::size_t k = 5,
|
||||
Disable_if_Polygon_2_iterator<InputIterator1>* = 0) {
|
||||
typename Iterator_to_gps_traits<InputIterator1>::Traits traits;
|
||||
return r_intersection(begin1, end1, begin2, end2, oi, traits, k);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,11 +7,10 @@
|
|||
// $Id$
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
//
|
||||
// Author(s): Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ron Wein <wein@post.tau.ac.il>
|
||||
// Efi Fogel <efif@post.tau.ac.il>
|
||||
// Simon Giraudot <simon.giraudot@geometryfactory.com>
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ron Wein <wein@post.tau.ac.il>
|
||||
// Efi Fogel <efif@post.tau.ac.il>
|
||||
// Simon Giraudot <simon.giraudot@geometryfactory.com>
|
||||
|
||||
#ifndef CGAL_BOOLEAN_SET_OPERATIONS_2_JOIN_H
|
||||
#define CGAL_BOOLEAN_SET_OPERATIONS_2_JOIN_H
|
||||
|
|
@ -33,8 +32,7 @@
|
|||
#include <CGAL/Boolean_set_operations_2/Polygon_conversions.h>
|
||||
#include <CGAL/type_traits/is_iterator.h>
|
||||
|
||||
namespace CGAL
|
||||
{
|
||||
namespace CGAL {
|
||||
|
||||
/// \name join() functions.
|
||||
//@{
|
||||
|
|
@ -60,10 +58,9 @@ template <typename Kernel, typename Container>
|
|||
inline bool join(const Polygon_2<Kernel, Container>& pgn1,
|
||||
const Polygon_2<Kernel, Container>& pgn2,
|
||||
Polygon_with_holes_2<Kernel, Container>& res,
|
||||
Tag_false)
|
||||
{
|
||||
Tag_false) {
|
||||
// Use the first polygon to determine the (default) traits
|
||||
typedef Polygon_2<Kernel, Container> Polygon;
|
||||
using Polygon = Polygon_2<Kernel, Container>;
|
||||
typename Gps_default_traits<Polygon>::Traits traits;
|
||||
return s_join(pgn1, pgn2, res, traits);
|
||||
}
|
||||
|
|
@ -89,10 +86,9 @@ template <typename Kernel, typename Container>
|
|||
inline bool join(const Polygon_2<Kernel, Container>& pgn1,
|
||||
const Polygon_with_holes_2<Kernel, Container>& pgn2,
|
||||
Polygon_with_holes_2<Kernel, Container>& res,
|
||||
Tag_false)
|
||||
{
|
||||
Tag_false) {
|
||||
// Use the first polygon to determine the (default) traits
|
||||
typedef Polygon_2<Kernel, Container> Polygon;
|
||||
using Polygon = Polygon_2<Kernel, Container>;
|
||||
typename Gps_default_traits<Polygon>::Traits traits;
|
||||
return s_join(pgn1, pgn2, res, traits);
|
||||
}
|
||||
|
|
@ -118,10 +114,9 @@ template <typename Kernel, typename Container>
|
|||
inline bool join(const Polygon_with_holes_2<Kernel, Container>& pgn1,
|
||||
const Polygon_2<Kernel, Container>& pgn2,
|
||||
Polygon_with_holes_2<Kernel, Container>& res,
|
||||
Tag_false)
|
||||
{
|
||||
Tag_false) {
|
||||
// Use the first polygon to determine the (default) traits
|
||||
typedef Polygon_with_holes_2<Kernel, Container> Polygon_with_holes;
|
||||
using Polygon_with_holes = Polygon_with_holes_2<Kernel, Container>;
|
||||
typename Gps_default_traits<Polygon_with_holes>::Traits traits;
|
||||
return s_join(pgn1, pgn2, res, traits);
|
||||
}
|
||||
|
|
@ -147,10 +142,9 @@ template <typename Kernel, typename Container>
|
|||
inline bool join(const Polygon_with_holes_2<Kernel, Container>& pgn1,
|
||||
const Polygon_with_holes_2<Kernel, Container>& pgn2,
|
||||
Polygon_with_holes_2<Kernel, Container>& res,
|
||||
Tag_false)
|
||||
{
|
||||
Tag_false) {
|
||||
// Use the first polygon to determine the (default) traits
|
||||
typedef Polygon_with_holes_2<Kernel, Container> Polygon_with_holes;
|
||||
using Polygon_with_holes = Polygon_with_holes_2<Kernel, Container>;
|
||||
typename Gps_default_traits<Polygon_with_holes>::Traits traits;
|
||||
return s_join(pgn1, pgn2, res, traits);
|
||||
}
|
||||
|
|
@ -170,10 +164,9 @@ template <typename ArrTraits>
|
|||
inline bool
|
||||
join(const General_polygon_2<ArrTraits>& pgn1,
|
||||
const General_polygon_2<ArrTraits>& pgn2,
|
||||
General_polygon_with_holes_2<General_polygon_2<ArrTraits> >& res)
|
||||
{
|
||||
General_polygon_with_holes_2<General_polygon_2<ArrTraits> >& res) {
|
||||
// Use the first polygon to determine the (default) traits
|
||||
typedef General_polygon_2<ArrTraits> Polygon;
|
||||
using Polygon = General_polygon_2<ArrTraits>;
|
||||
typename Gps_default_traits<Polygon>::Traits traits;
|
||||
return s_join(pgn1, pgn2, res, traits);
|
||||
}
|
||||
|
|
@ -193,10 +186,9 @@ template <typename ArrTraits>
|
|||
inline bool
|
||||
join(const General_polygon_2<ArrTraits>& pgn1,
|
||||
const General_polygon_with_holes_2<General_polygon_2<ArrTraits> >& pgn2,
|
||||
General_polygon_with_holes_2<General_polygon_2<ArrTraits> >& res)
|
||||
{
|
||||
General_polygon_with_holes_2<General_polygon_2<ArrTraits> >& res) {
|
||||
// Use the first polygon to determine the (default) traits
|
||||
typedef General_polygon_2<ArrTraits> Polygon;
|
||||
using Polygon = General_polygon_2<ArrTraits>;
|
||||
typename Gps_default_traits<Polygon>::Traits traits;
|
||||
return s_join(pgn1, pgn2, res, traits);
|
||||
}
|
||||
|
|
@ -216,11 +208,10 @@ template <typename ArrTraits>
|
|||
inline bool
|
||||
join(const General_polygon_with_holes_2<General_polygon_2<ArrTraits> >& pgn1,
|
||||
const General_polygon_2<ArrTraits>& pgn2,
|
||||
General_polygon_with_holes_2<General_polygon_2<ArrTraits> >& res)
|
||||
{
|
||||
General_polygon_with_holes_2<General_polygon_2<ArrTraits> >& res) {
|
||||
// Use the first polygon to determine the (default) traits
|
||||
typedef General_polygon_2<ArrTraits> Polygon;
|
||||
typedef General_polygon_with_holes_2<Polygon> Polygon_with_holes;
|
||||
using Polygon = General_polygon_2<ArrTraits>;
|
||||
using Polygon_with_holes = General_polygon_with_holes_2<Polygon>;
|
||||
typename Gps_default_traits<Polygon_with_holes>::Traits traits;
|
||||
return s_join(pgn1, pgn2, res, traits);
|
||||
}
|
||||
|
|
@ -237,10 +228,9 @@ inline bool join(const General_polygon_with_holes_2<Polygon_>& pgn1,
|
|||
template <typename Polygon_>
|
||||
inline bool join(const General_polygon_with_holes_2<Polygon_>& pgn1,
|
||||
const General_polygon_with_holes_2<Polygon_>& pgn2,
|
||||
General_polygon_with_holes_2<Polygon_>& res)
|
||||
{
|
||||
General_polygon_with_holes_2<Polygon_>& res) {
|
||||
// Use the first polygon to determine the (default) traits
|
||||
typedef General_polygon_with_holes_2<Polygon_> Polygon_with_holes;
|
||||
using Polygon_with_holes = General_polygon_with_holes_2<Polygon_>;
|
||||
typename Gps_default_traits<Polygon_with_holes>::Traits traits;
|
||||
return s_join(pgn1, pgn2, res, traits);
|
||||
}
|
||||
|
|
@ -253,7 +243,7 @@ inline bool join(const General_polygon_with_holes_2<Polygon_>& pgn1,
|
|||
// With Traits
|
||||
template <typename InputIterator, typename OutputIterator, typename Traits>
|
||||
inline OutputIterator join(InputIterator begin, InputIterator end,
|
||||
OutputIterator oi, Traits& traits, unsigned int k=5)
|
||||
OutputIterator oi, Traits& traits, std::size_t k = 5)
|
||||
{ return r_join(begin, end, oi, traits, k); }
|
||||
|
||||
// Without Traits
|
||||
|
|
@ -261,16 +251,15 @@ inline OutputIterator join(InputIterator begin, InputIterator end,
|
|||
template <typename InputIterator, typename OutputIterator>
|
||||
inline OutputIterator join(InputIterator begin, InputIterator end,
|
||||
OutputIterator oi, Tag_true = Tag_true(),
|
||||
unsigned int k=5,
|
||||
std::size_t k = 5,
|
||||
Enable_if_Polygon_2_iterator<InputIterator>* = 0)
|
||||
{ return r_join(begin, end, oi, k); }
|
||||
|
||||
// Tag_false => do not convert to polylines
|
||||
template <typename InputIterator, typename OutputIterator>
|
||||
inline OutputIterator join(InputIterator begin, InputIterator end,
|
||||
OutputIterator oi, Tag_false, unsigned int k=5,
|
||||
Enable_if_Polygon_2_iterator<InputIterator>* = 0)
|
||||
{
|
||||
OutputIterator oi, Tag_false, std::size_t k = 5,
|
||||
Enable_if_Polygon_2_iterator<InputIterator>* = 0) {
|
||||
typename Iterator_to_gps_traits<InputIterator>::Traits traits;
|
||||
return r_join(begin, end, oi, traits, k);
|
||||
}
|
||||
|
|
@ -278,9 +267,8 @@ inline OutputIterator join(InputIterator begin, InputIterator end,
|
|||
// General polygons or polygons with holes
|
||||
template <typename InputIterator, typename OutputIterator>
|
||||
inline OutputIterator join(InputIterator begin, InputIterator end,
|
||||
OutputIterator oi, unsigned int k=5,
|
||||
Disable_if_Polygon_2_iterator<InputIterator>* = 0)
|
||||
{
|
||||
OutputIterator oi, std::size_t k = 5,
|
||||
Disable_if_Polygon_2_iterator<InputIterator>* = 0) {
|
||||
typename Iterator_to_gps_traits<InputIterator>::Traits traits;
|
||||
return r_join(begin, end, oi, traits, k);
|
||||
}
|
||||
|
|
@ -291,7 +279,7 @@ template <typename InputIterator1, typename InputIterator2,
|
|||
typename OutputIterator, typename Traits>
|
||||
inline OutputIterator join(InputIterator1 begin1, InputIterator1 end1,
|
||||
InputIterator2 begin2, InputIterator2 end2,
|
||||
OutputIterator oi, Traits& traits, unsigned int k=5)
|
||||
OutputIterator oi, Traits& traits, std::size_t k = 5)
|
||||
{ return r_join(begin1, end1, begin2, end2, oi, traits, k); }
|
||||
|
||||
// Without Traits
|
||||
|
|
@ -301,7 +289,7 @@ template <typename InputIterator1, typename InputIterator2,
|
|||
inline OutputIterator join(InputIterator1 begin1, InputIterator1 end1,
|
||||
InputIterator2 begin2, InputIterator2 end2,
|
||||
OutputIterator oi, Tag_true = Tag_true(),
|
||||
unsigned int k=5,
|
||||
std::size_t k = 5,
|
||||
Enable_if_Polygon_2_iterator<InputIterator1>* = 0)
|
||||
{ return r_join(begin1, end1, begin2, end2, oi, k); }
|
||||
|
||||
|
|
@ -310,9 +298,8 @@ template <typename InputIterator1, typename InputIterator2,
|
|||
typename OutputIterator>
|
||||
inline OutputIterator join(InputIterator1 begin1, InputIterator1 end1,
|
||||
InputIterator2 begin2, InputIterator2 end2,
|
||||
OutputIterator oi, Tag_false, unsigned int k=5,
|
||||
Enable_if_Polygon_2_iterator<InputIterator1>* = 0)
|
||||
{
|
||||
OutputIterator oi, Tag_false, std::size_t k = 5,
|
||||
Enable_if_Polygon_2_iterator<InputIterator1>* = 0) {
|
||||
typename Iterator_to_gps_traits<InputIterator1>::Traits traits;
|
||||
return r_join(begin1, end1, begin2, end2, oi, traits, k);
|
||||
}
|
||||
|
|
@ -322,9 +309,8 @@ template <typename InputIterator1, typename InputIterator2,
|
|||
typename OutputIterator>
|
||||
inline OutputIterator join(InputIterator1 begin1, InputIterator1 end1,
|
||||
InputIterator2 begin2, InputIterator2 end2,
|
||||
OutputIterator oi, unsigned int k=5,
|
||||
Disable_if_Polygon_2_iterator<InputIterator1>* = 0)
|
||||
{
|
||||
OutputIterator oi, std::size_t k = 5,
|
||||
Disable_if_Polygon_2_iterator<InputIterator1>* = 0) {
|
||||
typename Iterator_to_gps_traits<InputIterator1>::Traits traits;
|
||||
return r_join(begin1, end1, begin2, end2, oi, traits, k);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,11 +7,10 @@
|
|||
// $Id$
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
//
|
||||
// Author(s): Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ron Wein <wein@post.tau.ac.il>
|
||||
// Efi Fogel <efif@post.tau.ac.il>
|
||||
// Simon Giraudot <simon.giraudot@geometryfactory.com>
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ron Wein <wein@post.tau.ac.il>
|
||||
// Efi Fogel <efif@post.tau.ac.il>
|
||||
// Simon Giraudot <simon.giraudot@geometryfactory.com>
|
||||
|
||||
#ifndef CGAL_BOOLEAN_SET_OPERATIONS_SYMMETRIC_DIFFERENCE_H
|
||||
#define CGAL_BOOLEAN_SET_OPERATIONS_SYMMETRIC_DIFFERENCE_H
|
||||
|
|
@ -33,8 +32,7 @@
|
|||
#include <CGAL/Boolean_set_operations_2/Polygon_conversions.h>
|
||||
#include <CGAL/type_traits/is_iterator.h>
|
||||
|
||||
namespace CGAL
|
||||
{
|
||||
namespace CGAL {
|
||||
|
||||
/// \name symmetric_difference() functions.
|
||||
//@{
|
||||
|
|
@ -62,10 +60,9 @@ template <typename Kernel, typename Container, typename OutputIterator>
|
|||
inline OutputIterator
|
||||
symmetric_difference(const Polygon_2<Kernel, Container>& pgn1,
|
||||
const Polygon_2<Kernel, Container>& pgn2,
|
||||
OutputIterator oi, Tag_false)
|
||||
{
|
||||
OutputIterator oi, Tag_false) {
|
||||
// Use the first polygon to determine the (default) traits
|
||||
typedef Polygon_2<Kernel, Container> Polygon;
|
||||
using Polygon = Polygon_2<Kernel, Container>;
|
||||
typename Gps_default_traits<Polygon>::Traits traits;
|
||||
return s_symmetric_difference(pgn1, pgn2, oi, traits);
|
||||
}
|
||||
|
|
@ -93,10 +90,9 @@ template <typename Kernel, typename Container, typename OutputIterator>
|
|||
inline OutputIterator
|
||||
symmetric_difference(const Polygon_2<Kernel, Container>& pgn1,
|
||||
const Polygon_with_holes_2<Kernel, Container>& pgn2,
|
||||
OutputIterator oi, Tag_false)
|
||||
{
|
||||
OutputIterator oi, Tag_false) {
|
||||
// Use the first polygon to determine the (default) traits
|
||||
typedef Polygon_2<Kernel, Container> Polygon;
|
||||
using Polygon = Polygon_2<Kernel, Container>;
|
||||
typename Gps_default_traits<Polygon>::Traits traits;
|
||||
return s_symmetric_difference(pgn1, pgn2, oi, traits);
|
||||
}
|
||||
|
|
@ -124,10 +120,9 @@ template <typename Kernel, typename Container, typename OutputIterator>
|
|||
inline OutputIterator
|
||||
symmetric_difference(const Polygon_with_holes_2<Kernel, Container>& pgn1,
|
||||
const Polygon_2<Kernel, Container>& pgn2,
|
||||
OutputIterator oi, Tag_false)
|
||||
{
|
||||
OutputIterator oi, Tag_false) {
|
||||
// Use the first polygon to determine the (default) traits
|
||||
typedef Polygon_with_holes_2<Kernel, Container> Polygon_with_holes;
|
||||
using Polygon_with_holes = Polygon_with_holes_2<Kernel, Container>;
|
||||
typename Gps_default_traits<Polygon_with_holes>::Traits traits;
|
||||
return s_symmetric_difference(pgn1, pgn2, oi, traits);
|
||||
}
|
||||
|
|
@ -155,10 +150,9 @@ template <typename Kernel, typename Container, typename OutputIterator>
|
|||
inline OutputIterator
|
||||
symmetric_difference(const Polygon_with_holes_2<Kernel, Container>& pgn1,
|
||||
const Polygon_with_holes_2<Kernel, Container>& pgn2,
|
||||
OutputIterator oi, Tag_false)
|
||||
{
|
||||
OutputIterator oi, Tag_false) {
|
||||
// Use the first polygon to determine the (default) traits
|
||||
typedef Polygon_with_holes_2<Kernel, Container> Polygon_with_holes;
|
||||
using Polygon_with_holes = Polygon_with_holes_2<Kernel, Container>;
|
||||
typename Gps_default_traits<Polygon_with_holes>::Traits traits;
|
||||
return s_symmetric_difference(pgn1, pgn2, oi, traits);
|
||||
}
|
||||
|
|
@ -176,10 +170,9 @@ template <typename ArrTraits, typename OutputIterator>
|
|||
inline OutputIterator
|
||||
symmetric_difference(const General_polygon_2<ArrTraits>& pgn1,
|
||||
const General_polygon_2<ArrTraits>& pgn2,
|
||||
OutputIterator oi)
|
||||
{
|
||||
OutputIterator oi) {
|
||||
// Use the first polygon to determine the (default) traits
|
||||
typedef General_polygon_2<ArrTraits> Polygon;
|
||||
using Polygon = General_polygon_2<ArrTraits>;
|
||||
typename Gps_default_traits<Polygon>::Traits traits;
|
||||
return s_symmetric_difference(pgn1, pgn2, oi, traits);
|
||||
}
|
||||
|
|
@ -200,10 +193,9 @@ inline OutputIterator
|
|||
symmetric_difference(const General_polygon_2<ArrTraits>& pgn1,
|
||||
const General_polygon_with_holes_2
|
||||
<General_polygon_2<ArrTraits> >& pgn2,
|
||||
OutputIterator oi)
|
||||
{
|
||||
OutputIterator oi) {
|
||||
// Use the first polygon to determine the (default) traits
|
||||
typedef General_polygon_2<ArrTraits> Polygon;
|
||||
using Polygon = General_polygon_2<ArrTraits>;
|
||||
typename Gps_default_traits<Polygon>::Traits traits;
|
||||
return s_symmetric_difference(pgn1, pgn2, oi, traits);
|
||||
}
|
||||
|
|
@ -224,11 +216,10 @@ inline OutputIterator
|
|||
symmetric_difference(const General_polygon_with_holes_2
|
||||
<General_polygon_2<ArrTraits> >& pgn1,
|
||||
const General_polygon_2<ArrTraits>& pgn2,
|
||||
OutputIterator oi)
|
||||
{
|
||||
OutputIterator oi) {
|
||||
// Use the first polygon to determine the (default) traits
|
||||
typedef General_polygon_2<ArrTraits> Polygon;
|
||||
typedef General_polygon_with_holes_2<Polygon> Polygon_with_holes;
|
||||
using Polygon = General_polygon_2<ArrTraits>;
|
||||
using Polygon_with_holes = General_polygon_with_holes_2<Polygon>;
|
||||
typename Gps_default_traits<Polygon_with_holes>::Traits traits;
|
||||
return s_symmetric_difference(pgn1, pgn2, oi, traits);
|
||||
}
|
||||
|
|
@ -247,9 +238,8 @@ template <typename Polygon_, typename OutputIterator>
|
|||
inline OutputIterator
|
||||
symmetric_difference(const General_polygon_with_holes_2<Polygon_>& pgn1,
|
||||
const General_polygon_with_holes_2<Polygon_>& pgn2,
|
||||
OutputIterator oi)
|
||||
{
|
||||
typedef General_polygon_with_holes_2<Polygon_> Polygon_with_holes;
|
||||
OutputIterator oi) {
|
||||
using Polygon_with_holes = General_polygon_with_holes_2<Polygon_>;
|
||||
typename Gps_default_traits<Polygon_with_holes>::Traits traits;
|
||||
return s_symmetric_difference(pgn1, pgn2, oi, traits);
|
||||
}
|
||||
|
|
@ -264,7 +254,7 @@ template <typename InputIterator, typename OutputIterator, typename Traits>
|
|||
inline
|
||||
OutputIterator symmetric_difference(InputIterator begin, InputIterator end,
|
||||
OutputIterator oi, Traits& traits,
|
||||
unsigned int k=5)
|
||||
std::size_t k = 5)
|
||||
{ return r_symmetric_difference(begin, end, oi, traits, k); }
|
||||
|
||||
// Without Traits
|
||||
|
|
@ -272,7 +262,7 @@ OutputIterator symmetric_difference(InputIterator begin, InputIterator end,
|
|||
template <typename InputIterator, typename OutputIterator>
|
||||
inline OutputIterator
|
||||
symmetric_difference(InputIterator begin, InputIterator end,
|
||||
OutputIterator oi, Tag_true = Tag_true(), unsigned int k=5,
|
||||
OutputIterator oi, Tag_true = Tag_true(), std::size_t k = 5,
|
||||
Enable_if_Polygon_2_iterator<InputIterator>* = 0)
|
||||
{ return r_symmetric_difference(begin, end, oi, k); }
|
||||
|
||||
|
|
@ -280,9 +270,8 @@ symmetric_difference(InputIterator begin, InputIterator end,
|
|||
template <typename InputIterator, typename OutputIterator>
|
||||
inline OutputIterator
|
||||
symmetric_difference(InputIterator begin, InputIterator end,
|
||||
OutputIterator oi, Tag_false, unsigned int k=5,
|
||||
Enable_if_Polygon_2_iterator<InputIterator>* = 0)
|
||||
{
|
||||
OutputIterator oi, Tag_false, std::size_t k = 5,
|
||||
Enable_if_Polygon_2_iterator<InputIterator>* = 0) {
|
||||
typename Iterator_to_gps_traits<InputIterator>::Traits traits;
|
||||
return r_symmetric_difference(begin, end, oi, traits, k);
|
||||
}
|
||||
|
|
@ -291,9 +280,8 @@ symmetric_difference(InputIterator begin, InputIterator end,
|
|||
template <typename InputIterator, typename OutputIterator>
|
||||
inline OutputIterator
|
||||
symmetric_difference(InputIterator begin, InputIterator end,
|
||||
OutputIterator oi, unsigned int k=5,
|
||||
Disable_if_Polygon_2_iterator<InputIterator>* = 0)
|
||||
{
|
||||
OutputIterator oi, std::size_t k = 5,
|
||||
Disable_if_Polygon_2_iterator<InputIterator>* = 0) {
|
||||
typename Iterator_to_gps_traits<InputIterator>::Traits traits;
|
||||
return r_symmetric_difference(begin, end, oi, traits, k);
|
||||
}
|
||||
|
|
@ -306,7 +294,7 @@ inline
|
|||
OutputIterator symmetric_difference(InputIterator1 begin1, InputIterator1 end1,
|
||||
InputIterator2 begin2, InputIterator2 end2,
|
||||
OutputIterator oi, Traits& traits,
|
||||
unsigned int k=5)
|
||||
std::size_t k = 5)
|
||||
{ return r_symmetric_difference(begin1, end1, begin2, end2, oi, traits, k); }
|
||||
|
||||
// Without Traits
|
||||
|
|
@ -316,7 +304,7 @@ template <typename InputIterator1, typename InputIterator2,
|
|||
inline OutputIterator
|
||||
symmetric_difference(InputIterator1 begin1, InputIterator1 end1,
|
||||
InputIterator2 begin2, InputIterator2 end2,
|
||||
OutputIterator oi, Tag_true = Tag_true(), unsigned int k=5,
|
||||
OutputIterator oi, Tag_true = Tag_true(), std::size_t k = 5,
|
||||
Enable_if_Polygon_2_iterator<InputIterator1>* = 0)
|
||||
{ return r_symmetric_difference(begin1, end1, begin2, end2, oi, k); }
|
||||
|
||||
|
|
@ -326,9 +314,8 @@ template <typename InputIterator1, typename InputIterator2,
|
|||
inline OutputIterator
|
||||
symmetric_difference(InputIterator1 begin1, InputIterator1 end1,
|
||||
InputIterator2 begin2, InputIterator2 end2,
|
||||
OutputIterator oi, Tag_false, unsigned int k=5,
|
||||
Enable_if_Polygon_2_iterator<InputIterator1>* = 0)
|
||||
{
|
||||
OutputIterator oi, Tag_false, std::size_t k = 5,
|
||||
Enable_if_Polygon_2_iterator<InputIterator1>* = 0) {
|
||||
typename Iterator_to_gps_traits<InputIterator1>::Traits traits;
|
||||
return r_symmetric_difference(begin1, end1, begin2, end2, oi, traits, k);
|
||||
}
|
||||
|
|
@ -339,9 +326,8 @@ template <typename InputIterator1, typename InputIterator2,
|
|||
inline OutputIterator
|
||||
symmetric_difference(InputIterator1 begin1, InputIterator1 end1,
|
||||
InputIterator2 begin2, InputIterator2 end2,
|
||||
OutputIterator oi, unsigned int k=5,
|
||||
Disable_if_Polygon_2_iterator<InputIterator1>* = 0)
|
||||
{
|
||||
OutputIterator oi, std::size_t k = 5,
|
||||
Disable_if_Polygon_2_iterator<InputIterator1>* = 0) {
|
||||
typename Iterator_to_gps_traits<InputIterator1>::Traits traits;
|
||||
return r_symmetric_difference(begin1, end1, begin2, end2, oi, traits, k);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@
|
|||
// $Id$
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Efi Fogel <efif@post.tau.ac.il>
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Efi Fogel <efif@post.tau.ac.il>
|
||||
|
||||
#ifndef CGAL_GENERAL_POLYGON_SET_2_H
|
||||
#define CGAL_GENERAL_POLYGON_SET_2_H
|
||||
|
|
@ -27,25 +27,20 @@
|
|||
namespace CGAL {
|
||||
|
||||
// General_polygon_set_2
|
||||
template <class Traits_, class Dcel_ = Gps_default_dcel<Traits_> >
|
||||
class General_polygon_set_2 : public General_polygon_set_on_surface_2
|
||||
<Traits_, typename Default_planar_topology<Traits_, Dcel_>::Traits>
|
||||
{
|
||||
protected:
|
||||
typedef General_polygon_set_2<Traits_, Dcel_> Self;
|
||||
template <typename Traits_, typename Dcel_ = Gps_default_dcel<Traits_>>
|
||||
class General_polygon_set_2 :
|
||||
public General_polygon_set_on_surface_2<
|
||||
Traits_, typename Default_planar_topology<Traits_, Dcel_>::Traits> {
|
||||
|
||||
public:
|
||||
typedef Traits_ Traits_2;
|
||||
typedef Dcel_ Dcel;
|
||||
|
||||
typedef General_polygon_set_on_surface_2 <Traits_2,
|
||||
typename Default_planar_topology<Traits_2, Dcel >::Traits>
|
||||
Base;
|
||||
|
||||
typedef CGAL::Arrangement_2<Traits_2, Dcel> Arrangement_2;
|
||||
|
||||
typedef typename Base::Polygon_2 Polygon_2;
|
||||
typedef typename Base::Polygon_with_holes_2 Polygon_with_holes_2;
|
||||
using Traits_2 = Traits_;
|
||||
using Dcel = Dcel_;
|
||||
using Self = General_polygon_set_2<Traits_2, Dcel>;
|
||||
using Topology_traits = typename Default_planar_topology<Traits_2, Dcel>::Traits;
|
||||
using Base = General_polygon_set_on_surface_2<Traits_2, Topology_traits>;
|
||||
using Arrangement_2 = CGAL::Arrangement_2<Traits_2, Dcel>;
|
||||
using Polygon_2 = typename Base::Polygon_2;
|
||||
using Polygon_with_holes_2 = typename Base::Polygon_with_holes_2;
|
||||
|
||||
// default constructor
|
||||
General_polygon_set_2() : Base() {}
|
||||
|
|
@ -80,19 +75,16 @@ public:
|
|||
using Base::join;
|
||||
using Base::symmetric_difference;
|
||||
|
||||
inline void intersection(const Self& ps1, const Self& ps2)
|
||||
{
|
||||
inline void intersection(const Self& ps1, const Self& ps2) {
|
||||
Base::intersection(static_cast<const Base&>(ps1),
|
||||
static_cast<const Base&>(ps2));
|
||||
}
|
||||
|
||||
inline void join(const Self& ps1, const Self& ps2)
|
||||
{
|
||||
inline void join(const Self& ps1, const Self& ps2) {
|
||||
Base::join(static_cast<const Base&>(ps1), static_cast<const Base&>(ps2));
|
||||
}
|
||||
|
||||
inline void symmetric_difference(const Self& ps1, const Self& ps2)
|
||||
{
|
||||
inline void symmetric_difference(const Self& ps1, const Self& ps2) {
|
||||
Base::symmetric_difference(static_cast<const Base&>(ps1),
|
||||
static_cast<const Base&>(ps2));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@
|
|||
// $Id$
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Efi Fogel <efif@post.tau.ac.il>
|
||||
// Author(s): Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Efi Fogel <efif@post.tau.ac.il>
|
||||
// Ophir Setter <ophir.setter@cs.tau.ac.il>
|
||||
|
||||
#ifndef CGAL_GENERAL_POLYGON_SET_ON_SURFACE_2_H
|
||||
|
|
@ -23,54 +23,48 @@
|
|||
|
||||
namespace CGAL {
|
||||
|
||||
namespace Boolean_set_operation_2_internal
|
||||
{
|
||||
struct PreconditionValidationPolicy
|
||||
{
|
||||
/*! is_valid - Checks if a Traits::Polygon_2 OR
|
||||
Traits::Polygon_with_holes_2 are valid.
|
||||
This validation policy checks that polygons are valid in a
|
||||
CGAL_precondition macro. We inherit from Gps_on_surface_base_2
|
||||
and use preconditions to validate the input polygons.
|
||||
namespace Boolean_set_operation_2_internal {
|
||||
|
||||
struct PreconditionValidationPolicy {
|
||||
/*! Checks if a Traits::Polygon_2 or Traits::Polygon_with_holes_2 are valid.
|
||||
* This validation policy checks that polygons are valid in a
|
||||
* CGAL_precondition macro. We inherit from Gps_on_surface_base_2 and use
|
||||
* preconditions to validate the input polygons.
|
||||
*/
|
||||
template <class Polygon, class Traits>
|
||||
inline static void is_valid(const Polygon& p, const Traits& t)
|
||||
{
|
||||
CGAL_precondition(is_valid_unknown_polygon(p, t));
|
||||
CGAL_USE(p); CGAL_USE(t);
|
||||
}
|
||||
};
|
||||
template <typename Polygon, typename Traits>
|
||||
inline static void is_valid(const Polygon& p, const Traits& t) {
|
||||
CGAL_precondition(is_valid_unknown_polygon(p, t));
|
||||
CGAL_USE(p); CGAL_USE(t);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
// General_polygon_set_on_surface_2
|
||||
/*
|
||||
This class is derived from Gps_on_surface_base_2.
|
||||
It enforces the validation conditions for general polygons, and is therefore
|
||||
the basic implementation that should be used by the user
|
||||
*/
|
||||
template <class Traits_, class TopTraits_>
|
||||
class General_polygon_set_on_surface_2 :
|
||||
public Gps_on_surface_base_2<Traits_, TopTraits_,
|
||||
Boolean_set_operation_2_internal::PreconditionValidationPolicy>
|
||||
{
|
||||
/* `General_polygon_set_on_surface_2` class is derived from
|
||||
* `Gps_on_surface_base_2`. It enforces the validation conditions for general
|
||||
* polygons, and is therefore the basic implementation that should be used by
|
||||
* the user
|
||||
*/
|
||||
template <typename Traits_, typename TopTraits_>
|
||||
class General_polygon_set_on_surface_2 :
|
||||
public Gps_on_surface_base_2<
|
||||
Traits_, TopTraits_,
|
||||
Boolean_set_operation_2_internal::PreconditionValidationPolicy> {
|
||||
|
||||
protected:
|
||||
typedef Traits_ Traits_2;
|
||||
typedef General_polygon_set_on_surface_2<Traits_2, TopTraits_> Self;
|
||||
typedef Gps_on_surface_base_2<Traits_2, TopTraits_,
|
||||
Boolean_set_operation_2_internal::PreconditionValidationPolicy> Base;
|
||||
using Traits_2 = Traits_;
|
||||
using Self = General_polygon_set_on_surface_2<Traits_2, TopTraits_>;
|
||||
using Base = Gps_on_surface_base_2<Traits_2, TopTraits_,
|
||||
Boolean_set_operation_2_internal::PreconditionValidationPolicy>;
|
||||
|
||||
public:
|
||||
typedef typename Base::Polygon_2 Polygon_2;
|
||||
typedef typename Base::Polygon_with_holes_2
|
||||
Polygon_with_holes_2;
|
||||
typedef typename Base::Arrangement_on_surface_2
|
||||
Arrangement_on_surface_2;
|
||||
using Polygon_2 = typename Base::Polygon_2;
|
||||
using Polygon_with_holes_2 = typename Base::Polygon_with_holes_2;
|
||||
using Arrangement_on_surface_2 = typename Base::Arrangement_on_surface_2;
|
||||
|
||||
public:
|
||||
|
||||
// default constructor
|
||||
General_polygon_set_on_surface_2() : Base()
|
||||
{}
|
||||
General_polygon_set_on_surface_2() : Base() {}
|
||||
|
||||
// constructor from a traits object
|
||||
General_polygon_set_on_surface_2(const Traits_2& traits) : Base(traits) {}
|
||||
|
|
@ -79,8 +73,7 @@ public:
|
|||
General_polygon_set_on_surface_2(const Self& ps) : Base(ps) {}
|
||||
|
||||
// assignment operator
|
||||
General_polygon_set_on_surface_2& operator=(const Self& ps)
|
||||
{
|
||||
General_polygon_set_on_surface_2& operator=(const Self& ps) {
|
||||
Base::operator=(ps);
|
||||
return (*this);
|
||||
}
|
||||
|
|
@ -90,19 +83,15 @@ public:
|
|||
|
||||
// constructor from a polygon with holes
|
||||
explicit
|
||||
General_polygon_set_on_surface_2(const Polygon_with_holes_2& pwh) :
|
||||
Base(pwh)
|
||||
{}
|
||||
General_polygon_set_on_surface_2(const Polygon_with_holes_2& pwh) : Base(pwh) {}
|
||||
|
||||
// constructor from a polygon and a traits object
|
||||
explicit General_polygon_set_on_surface_2(const Polygon_2& pgn,
|
||||
const Traits_2& traits) :
|
||||
explicit General_polygon_set_on_surface_2(const Polygon_2& pgn, const Traits_2& traits) :
|
||||
Base(pgn, traits) {}
|
||||
|
||||
// constructor from a polygon with holes and a traits object
|
||||
explicit
|
||||
General_polygon_set_on_surface_2(const Polygon_with_holes_2& pwh,
|
||||
const Traits_2& traits) :
|
||||
General_polygon_set_on_surface_2(const Polygon_with_holes_2& pwh, const Traits_2& traits) :
|
||||
Base(pwh, traits)
|
||||
{}
|
||||
|
||||
|
|
@ -142,4 +131,4 @@ private:
|
|||
|
||||
#include <CGAL/enable_warnings.h>
|
||||
|
||||
#endif // CGAL_GENERAL_POLYGON_SET_ON_SURFACE_2_H
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,48 +0,0 @@
|
|||
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
|
||||
#include <CGAL/Boolean_set_operations_2.h>
|
||||
#include <CGAL/Polygon_set_2.h>
|
||||
#include <list>
|
||||
|
||||
typedef CGAL::Exact_predicates_exact_constructions_kernel K;
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
CGAL::Polygon_2<K> ob;
|
||||
ob.push_back(CGAL::Point_2<K>(1, 1));
|
||||
ob.push_back(CGAL::Point_2<K>(1, 0));
|
||||
ob.push_back(CGAL::Point_2<K>(6, 0));
|
||||
ob.push_back(CGAL::Point_2<K>(6, 7));
|
||||
ob.push_back(CGAL::Point_2<K>(0, 7));
|
||||
ob.push_back(CGAL::Point_2<K>(0, 1));
|
||||
|
||||
CGAL::Polygon_2<K> h;
|
||||
h.push_back(CGAL::Point_2<K>(2, 1));
|
||||
h.push_back(CGAL::Point_2<K>(2, 2));
|
||||
h.push_back(CGAL::Point_2<K>(3, 2));
|
||||
h.push_back(CGAL::Point_2<K>(3, 3));
|
||||
h.push_back(CGAL::Point_2<K>(2, 3));
|
||||
h.push_back(CGAL::Point_2<K>(2, 4));
|
||||
h.push_back(CGAL::Point_2<K>(3, 4));
|
||||
h.push_back(CGAL::Point_2<K>(3, 5));
|
||||
h.push_back(CGAL::Point_2<K>(4, 5));
|
||||
h.push_back(CGAL::Point_2<K>(4, 1));
|
||||
|
||||
CGAL::Polygon_with_holes_2<K> ob_with_holes(ob);
|
||||
ob_with_holes.add_hole(h);
|
||||
CGAL::Polygon_set_2<K> inter(ob_with_holes);
|
||||
|
||||
CGAL::Polygon_2<K> new_poly;
|
||||
new_poly.push_back(CGAL::Point_2<K>(1, 1));
|
||||
new_poly.push_back(CGAL::Point_2<K>(2, 1));
|
||||
new_poly.push_back(CGAL::Point_2<K>(2, 2));
|
||||
new_poly.push_back(CGAL::Point_2<K>(2, 3));
|
||||
new_poly.push_back(CGAL::Point_2<K>(2, 4));
|
||||
new_poly.push_back(CGAL::Point_2<K>(2, 5));
|
||||
new_poly.push_back(CGAL::Point_2<K>(3, 5));
|
||||
new_poly.push_back(CGAL::Point_2<K>(4, 5));
|
||||
new_poly.push_back(CGAL::Point_2<K>(4, 6));
|
||||
new_poly.push_back(CGAL::Point_2<K>(1, 6));
|
||||
|
||||
inter.difference(new_poly);
|
||||
}
|
||||
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
#include <vector>
|
||||
|
||||
#include <CGAL/Simple_cartesian.h>
|
||||
|
|
@ -13,35 +12,32 @@
|
|||
#include <CGAL/Polygon_set_2.h>
|
||||
|
||||
//typedef CGAL::Quotient<CGAL::MP_Float> Number_type;
|
||||
typedef int Number_type;
|
||||
using Number_type = int;
|
||||
|
||||
typedef CGAL::Simple_cartesian<Number_type> Kernel;
|
||||
using Kernel = CGAL::Simple_cartesian<Number_type>;
|
||||
|
||||
typedef CGAL::Gps_segment_traits_2<Kernel> Traits;
|
||||
typedef CGAL::Polygon_set_2<Kernel> Ps;
|
||||
using Traits = CGAL::Gps_segment_traits_2<Kernel>;
|
||||
using Ps = CGAL::Polygon_set_2<Kernel>;
|
||||
|
||||
typedef CGAL::Arr_segment_traits_2<Kernel> Arr_traits;
|
||||
typedef CGAL::Gps_traits_2<Arr_traits> General_traits;
|
||||
typedef CGAL::General_polygon_set_2<General_traits> Gps;
|
||||
using Arr_traits = CGAL::Arr_segment_traits_2<Kernel>;
|
||||
using General_traits = CGAL::Gps_traits_2<Arr_traits>;
|
||||
using Gps = CGAL::General_polygon_set_2<General_traits>;
|
||||
|
||||
typedef CGAL::Arr_non_caching_segment_traits_2<Kernel> Nc_traits;
|
||||
typedef CGAL::Gps_segment_traits_2<Kernel,
|
||||
std::vector<Kernel::Point_2>,
|
||||
Nc_traits> Traits_non_caching;
|
||||
typedef CGAL::General_polygon_set_2<Traits_non_caching> Gps_non_caching;
|
||||
using Nc_traits = CGAL::Arr_non_caching_segment_traits_2<Kernel>;
|
||||
using Traits_non_caching = CGAL::Gps_segment_traits_2<Kernel, std::vector<Kernel::Point_2>, Nc_traits>;
|
||||
using Gps_non_caching = CGAL::General_polygon_set_2<Traits_non_caching>;
|
||||
|
||||
template <class GPS>
|
||||
void test()
|
||||
{
|
||||
typedef typename GPS::Traits_2 Traits;
|
||||
typedef typename Traits::Point_2 Point_2;
|
||||
typedef typename Traits::Polygon_2 Polygon_2;
|
||||
typedef typename Traits::Polygon_with_holes_2 Polygon_with_holes_2;
|
||||
template <typename GPS>
|
||||
void test() {
|
||||
using Traits = typename GPS::Traits_2;
|
||||
using Point_2 = typename Traits::Point_2;
|
||||
using Polygon_2 = typename Traits::Polygon_2;
|
||||
using Polygon_with_holes_2 = typename Traits::Polygon_with_holes_2;
|
||||
|
||||
Polygon_2 pgn1, pgn2;
|
||||
Polygon_with_holes_2 pgn_with_holes1, pgn_with_holes2;
|
||||
std::vector<Polygon_2> polygons;
|
||||
std::vector<Polygon_with_holes_2> polygons_with_holes;
|
||||
Polygon_with_holes_2 pgn_with_holes1, pgn_with_holes2;
|
||||
std::vector<Polygon_2> polygons;
|
||||
std::vector<Polygon_with_holes_2> polygons_with_holes;
|
||||
GPS gps;
|
||||
GPS other;
|
||||
|
||||
|
|
@ -242,8 +238,7 @@ void test()
|
|||
GPS new_gps2 = gps;
|
||||
}
|
||||
|
||||
void test_CGAL_Polygon_variants()
|
||||
{
|
||||
void test_CGAL_Polygon_variants() {
|
||||
typedef CGAL::Polygon_2<Kernel> Polygon_2;
|
||||
typedef CGAL::Polygon_with_holes_2<Kernel> Polygon_with_holes_2;
|
||||
typedef CGAL::Gps_default_traits<Polygon_2>::Traits Traits;
|
||||
|
|
@ -257,45 +252,25 @@ void test_CGAL_Polygon_variants()
|
|||
Traits tr;
|
||||
|
||||
CGAL::do_intersect(pgn1, pgn2);
|
||||
CGAL::do_intersect(pgn1, pgn2, CGAL::Tag_true());
|
||||
CGAL::do_intersect(pgn1, pgn2, CGAL::Tag_false());
|
||||
CGAL::do_intersect(pgn1, pgn2, tr);
|
||||
|
||||
CGAL::do_intersect(pgn1, pgn_with_holes2);
|
||||
CGAL::do_intersect(pgn1, pgn_with_holes2, CGAL::Tag_true());
|
||||
CGAL::do_intersect(pgn1, pgn_with_holes2, CGAL::Tag_false());
|
||||
CGAL::do_intersect(pgn1, pgn_with_holes2, tr);
|
||||
|
||||
CGAL::do_intersect(pgn_with_holes1, pgn2);
|
||||
CGAL::do_intersect(pgn_with_holes1, pgn2, CGAL::Tag_true());
|
||||
CGAL::do_intersect(pgn_with_holes1, pgn2, CGAL::Tag_false());
|
||||
CGAL::do_intersect(pgn_with_holes1, pgn2, tr);
|
||||
|
||||
CGAL::do_intersect(pgn_with_holes1, pgn_with_holes2);
|
||||
CGAL::do_intersect(pgn_with_holes1, pgn_with_holes2, CGAL::Tag_true());
|
||||
CGAL::do_intersect(pgn_with_holes1, pgn_with_holes2, CGAL::Tag_false());
|
||||
CGAL::do_intersect(pgn_with_holes1, pgn_with_holes2, tr);
|
||||
|
||||
CGAL::do_intersect(polygons.begin(), polygons.end());
|
||||
CGAL::do_intersect(polygons.begin(), polygons.end(), CGAL::Tag_true());
|
||||
CGAL::do_intersect(polygons.begin(), polygons.end(), CGAL::Tag_false());
|
||||
CGAL::do_intersect(polygons.begin(), polygons.end(), tr);
|
||||
|
||||
CGAL::do_intersect(polygons_with_holes.begin(), polygons_with_holes.end());
|
||||
CGAL::do_intersect(polygons_with_holes.begin(), polygons_with_holes.end(),
|
||||
CGAL::Tag_true());
|
||||
CGAL::do_intersect(polygons_with_holes.begin(), polygons_with_holes.end(),
|
||||
CGAL::Tag_false());
|
||||
CGAL::do_intersect(polygons_with_holes.begin(), polygons_with_holes.end(), tr);
|
||||
|
||||
CGAL::do_intersect(polygons.begin(), polygons.end(),
|
||||
polygons_with_holes.begin(), polygons_with_holes.end());
|
||||
CGAL::do_intersect(polygons.begin(), polygons.end(),
|
||||
polygons_with_holes.begin(), polygons_with_holes.end(),
|
||||
CGAL::Tag_true());
|
||||
CGAL::do_intersect(polygons.begin(), polygons.end(),
|
||||
polygons_with_holes.begin(), polygons_with_holes.end(),
|
||||
CGAL::Tag_false());
|
||||
CGAL::do_intersect(polygons.begin(), polygons.end(),
|
||||
polygons_with_holes.begin(), polygons_with_holes.end(), tr);
|
||||
|
||||
|
|
@ -519,8 +494,7 @@ void test_CGAL_Polygon_variants()
|
|||
CGAL::complement(pgn_with_holes1, std::back_inserter(result), tr);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int main() {
|
||||
test<Gps>();
|
||||
test<Ps>();
|
||||
test<Gps_non_caching>();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,94 @@
|
|||
#include <iostream>
|
||||
|
||||
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
|
||||
#include <CGAL/Boolean_set_operations_2.h>
|
||||
#include <CGAL/Arr_circle_segment_traits_2.h>
|
||||
#include <CGAL/General_polygon_2.h>
|
||||
#include <CGAL/Boolean_set_operations_2.h>
|
||||
// #include <CGAL/draw_arrangement_2.h>
|
||||
|
||||
using Kernel = CGAL::Exact_predicates_exact_constructions_kernel;
|
||||
using Point_2 = Kernel::Point_2;
|
||||
using Polygon_2 = CGAL::Polygon_2<Kernel>;
|
||||
using Circle_2 = Kernel::Circle_2;
|
||||
|
||||
int main() {
|
||||
Kernel kernel;
|
||||
auto ctr_circle = kernel.construct_circle_2_object();
|
||||
auto circle1 = ctr_circle(Point_2(0, 1), 1);
|
||||
auto circle2 = ctr_circle(Point_2(0, -1), 1);
|
||||
auto circle3 = ctr_circle(Point_2(0, 2), 4);
|
||||
|
||||
// 1. Circular arcs and linear segments
|
||||
using Circle_segment_arr_traits_2 = CGAL::Arr_circle_segment_traits_2<Kernel>;
|
||||
using Circle_segment_xcv_2 = Circle_segment_arr_traits_2::X_monotone_curve_2;
|
||||
using Circle_segment_pnt_2 = Circle_segment_arr_traits_2::Point_2;
|
||||
using Circle_segment_gps_traits_2 = CGAL::Gps_traits_2<Circle_segment_arr_traits_2>;
|
||||
using Circle_segment_polygon = Circle_segment_gps_traits_2::General_polygon_2;
|
||||
|
||||
Circle_segment_arr_traits_2 circle_segment_traits;
|
||||
|
||||
Circle_segment_pnt_2 cs_pnt11(1, 1);
|
||||
Circle_segment_pnt_2 cs_pnt12(-1, 1);
|
||||
Circle_segment_xcv_2 xcv11(circle1, cs_pnt11, cs_pnt12, CGAL::COUNTERCLOCKWISE);
|
||||
Circle_segment_xcv_2 xcv12(circle1, cs_pnt12, cs_pnt11, CGAL::COUNTERCLOCKWISE);
|
||||
Circle_segment_polygon pgn1;
|
||||
pgn1.push_back(xcv11);
|
||||
pgn1.push_back(xcv12);
|
||||
|
||||
Circle_segment_pnt_2 cs_pnt21(1, -1);
|
||||
Circle_segment_pnt_2 cs_pnt22(-1, -1);
|
||||
Circle_segment_xcv_2 xcv21(circle2, cs_pnt21, cs_pnt22, CGAL::COUNTERCLOCKWISE);
|
||||
Circle_segment_xcv_2 xcv22(circle2, cs_pnt22, cs_pnt21, CGAL::COUNTERCLOCKWISE);
|
||||
Circle_segment_polygon pgn2;
|
||||
pgn2.push_back(xcv21);
|
||||
pgn2.push_back(xcv22);
|
||||
|
||||
Circle_segment_pnt_2 cs_pnt31(2, 2);
|
||||
Circle_segment_pnt_2 cs_pnt32(-2, 2);
|
||||
Circle_segment_xcv_2 xcv31(circle3, cs_pnt31, cs_pnt32, CGAL::COUNTERCLOCKWISE);
|
||||
Circle_segment_xcv_2 xcv32(circle3, cs_pnt32, cs_pnt31, CGAL::COUNTERCLOCKWISE);
|
||||
Circle_segment_polygon pgn3;
|
||||
pgn3.push_back(xcv31);
|
||||
pgn3.push_back(xcv32);
|
||||
|
||||
// 1.1.
|
||||
auto do_intersect = CGAL::do_intersect(pgn1, pgn2);
|
||||
if (do_intersect) {
|
||||
std::cerr << "The circles intersect (case 1)\n" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 1.2.
|
||||
std::vector<Circle_segment_polygon> pgns1 = { pgn1, pgn2 };
|
||||
do_intersect = CGAL::do_intersect(pgns1.begin(), pgns1.end());
|
||||
if (do_intersect) {
|
||||
std::cerr << "The circles intersect (case 2)\n" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 2.1.
|
||||
do_intersect = CGAL::do_intersect(pgn1, pgn3);
|
||||
if (! do_intersect) {
|
||||
std::cerr << "The circles do not intersect (case 1)\n" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 2.2.
|
||||
std::vector<Circle_segment_polygon> pgns2 = { pgn1, pgn3 };
|
||||
do_intersect = CGAL::do_intersect(pgns2.begin(), pgns2.end());
|
||||
if (! do_intersect) {
|
||||
std::cerr << "The circles do not intersect (case 2)\n" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// using Circle_segment_arr = CGAL::Arrangement_2<Circle_segment_arr_traits_2>;
|
||||
// Circle_segment_arr arr;
|
||||
// CGAL::insert_non_intersecting_curve(arr, xcv11);
|
||||
// CGAL::insert_non_intersecting_curve(arr, xcv12);
|
||||
// CGAL::insert_non_intersecting_curve(arr, xcv21);
|
||||
// CGAL::insert_non_intersecting_curve(arr, xcv22);
|
||||
// CGAL::draw(arr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
\cgalConcept
|
||||
|
||||
The concept `ConformingConstrainedDelaunayTriangulationCellBase_3` refines the concept
|
||||
`TriangulationCellBase_3` and and describes the requirements for a base cell class of
|
||||
`TriangulationCellBase_3` and describes the requirements for a base cell class of
|
||||
the `CGAL::Conforming_constrained_Delaunay_triangulation_3` class.
|
||||
|
||||
\cgalRefines{TriangulationCellBase_3, BaseWithTimeStamp}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
#include <CGAL/Constrained_triangulation_3/internal/config.h>
|
||||
|
||||
#include <CGAL/Conforming_constrained_Delaunay_triangulation_vertex_data_3.h>
|
||||
#include <CGAL/Real_timer.h>
|
||||
#include <CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h>
|
||||
#include <CGAL/Triangulation_segment_traverser_3.h>
|
||||
#include <CGAL/unordered_flat_set.h>
|
||||
|
|
@ -34,8 +35,209 @@
|
|||
|
||||
#ifndef DOXYGEN_RUNNING
|
||||
|
||||
#if CGAL_USE_ITT
|
||||
# include <ittnotify.h>
|
||||
#endif
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
namespace CDT_3 {
|
||||
|
||||
struct Debug_options {
|
||||
enum class Flags {
|
||||
Steiner_points = 0,
|
||||
conforming,
|
||||
input_faces,
|
||||
missing_region,
|
||||
regions,
|
||||
copy_triangulation_into_hole,
|
||||
validity,
|
||||
use_older_cavity_algorithm,
|
||||
debug_finite_edges_map,
|
||||
use_finite_edges_map,
|
||||
debug_subconstraints_to_conform,
|
||||
verbose_special_cases,
|
||||
debug_encroaching_vertices,
|
||||
debug_conforming_validation,
|
||||
debug_constraint_hierarchy,
|
||||
debug_geometric_errors,
|
||||
debug_polygon_insertion,
|
||||
display_statistics,
|
||||
nb_of_flags
|
||||
};
|
||||
|
||||
bool Steiner_points() const { return flags[static_cast<int>(Flags::Steiner_points)]; }
|
||||
void Steiner_points(bool b) { flags.set(static_cast<int>(Flags::Steiner_points), b); }
|
||||
|
||||
bool input_faces() const { return flags[static_cast<int>(Flags::input_faces)]; }
|
||||
void input_faces(bool b) { flags.set(static_cast<int>(Flags::input_faces), b); }
|
||||
|
||||
bool missing_region() const { return flags[static_cast<int>(Flags::missing_region)]; }
|
||||
void missing_region(bool b) { flags.set(static_cast<int>(Flags::missing_region), b); }
|
||||
|
||||
bool regions() const { return flags[static_cast<int>(Flags::regions)]; }
|
||||
void regions(bool b) { flags.set(static_cast<int>(Flags::regions), b); }
|
||||
|
||||
bool copy_triangulation_into_hole() const { return flags[static_cast<int>(Flags::copy_triangulation_into_hole)]; }
|
||||
void copy_triangulation_into_hole(bool b) { flags.set(static_cast<int>(Flags::copy_triangulation_into_hole), b); }
|
||||
|
||||
bool validity() const { return flags[static_cast<int>(Flags::validity)]; }
|
||||
void validity(bool b) { flags.set(static_cast<int>(Flags::validity), b); }
|
||||
|
||||
bool use_older_cavity_algorithm() const { return flags[static_cast<int>(Flags::use_older_cavity_algorithm)]; }
|
||||
bool use_newer_cavity_algorithm() const { return !flags[static_cast<int>(Flags::use_older_cavity_algorithm)]; }
|
||||
void use_older_cavity_algorithm(bool b) { flags.set(static_cast<int>(Flags::use_older_cavity_algorithm), b); }
|
||||
|
||||
bool finite_edges_map() const { return flags[static_cast<int>(Flags::debug_finite_edges_map)]; }
|
||||
void finite_edges_map(bool b) { flags.set(static_cast<int>(Flags::debug_finite_edges_map), b); }
|
||||
|
||||
bool subconstraints_to_conform() const { return flags[static_cast<int>(Flags::debug_subconstraints_to_conform)]; }
|
||||
void subconstraints_to_conform(bool b) { flags.set(static_cast<int>(Flags::debug_subconstraints_to_conform), b); }
|
||||
|
||||
bool use_finite_edges_map_flag() const { return flags[static_cast<int>(Flags::use_finite_edges_map)]; }
|
||||
void use_finite_edges_map(bool b) { flags.set(static_cast<int>(Flags::use_finite_edges_map), b); }
|
||||
|
||||
bool verbose_special_cases() const { return flags[static_cast<int>(Flags::verbose_special_cases)]; }
|
||||
void verbose_special_cases(bool b) { flags.set(static_cast<int>(Flags::verbose_special_cases), b); }
|
||||
|
||||
bool encroaching_vertices() const { return flags[static_cast<int>(Flags::debug_encroaching_vertices)]; }
|
||||
void encroaching_vertices(bool b) { flags.set(static_cast<int>(Flags::debug_encroaching_vertices), b); }
|
||||
|
||||
bool conforming_validation() const { return flags[static_cast<int>(Flags::debug_conforming_validation)]; }
|
||||
void conforming_validation(bool b) { flags.set(static_cast<int>(Flags::debug_conforming_validation), b); }
|
||||
|
||||
bool constraint_hierarchy() const { return flags[static_cast<int>(Flags::debug_constraint_hierarchy)]; }
|
||||
void constraint_hierarchy(bool b) { flags.set(static_cast<int>(Flags::debug_constraint_hierarchy), b); }
|
||||
|
||||
bool geometric_errors() const { return flags[static_cast<int>(Flags::debug_geometric_errors)]; }
|
||||
void geometric_errors(bool b) { flags.set(static_cast<int>(Flags::debug_geometric_errors), b); }
|
||||
|
||||
bool polygon_insertion() const { return flags[static_cast<int>(Flags::debug_polygon_insertion)]; }
|
||||
void polygon_insertion(bool b) { flags.set(static_cast<int>(Flags::debug_polygon_insertion), b); }
|
||||
|
||||
bool display_statistics() const { return flags[static_cast<int>(Flags::display_statistics)]; }
|
||||
void display_statistics(bool b) { flags.set(static_cast<int>(Flags::display_statistics), b); }
|
||||
|
||||
double segment_vertex_epsilon() const { return segment_vertex_epsilon_; }
|
||||
void set_segment_vertex_epsilon(double eps) { segment_vertex_epsilon_ = eps; }
|
||||
|
||||
double vertex_vertex_epsilon() const { return vertex_vertex_epsilon_; }
|
||||
void set_vertex_vertex_epsilon(double eps) { vertex_vertex_epsilon_ = eps; }
|
||||
|
||||
private:
|
||||
std::bitset<static_cast<int>(Flags::nb_of_flags)> flags{};
|
||||
double segment_vertex_epsilon_ = 0.0;
|
||||
double vertex_vertex_epsilon_ = 0.0;
|
||||
}; // end struct Debug_options
|
||||
|
||||
namespace internal {
|
||||
|
||||
auto& tasks_manager() {
|
||||
struct Tasks_manager {
|
||||
enum {
|
||||
READ_INPUT = 0,
|
||||
MERGE_FACETS,
|
||||
INSERT_VERTICES,
|
||||
COMPUTE_DISTANCES,
|
||||
CONFORMING,
|
||||
CDT,
|
||||
OUTPUT,
|
||||
VALIDATION,
|
||||
NB_TASKS
|
||||
};
|
||||
|
||||
#if CGAL_USE_ITT
|
||||
__itt_domain* cdt_3_domain = __itt_domain_create("org.cgal.CDT_3");
|
||||
const std::array<__itt_string_handle*, NB_TASKS> task_handles = {
|
||||
__itt_string_handle_create("CDT_3: read input file"),
|
||||
__itt_string_handle_create("CDT_3: merge facets"),
|
||||
__itt_string_handle_create("CDT_3: insert vertices"),
|
||||
__itt_string_handle_create("CDT_3: compute distances"),
|
||||
__itt_string_handle_create("CDT_3: conforming"),
|
||||
__itt_string_handle_create("CDT_3: cdt"),
|
||||
__itt_string_handle_create("CDT_3: outputs"),
|
||||
__itt_string_handle_create("CDT_3: validation")
|
||||
};
|
||||
#endif
|
||||
std::array<CGAL::Real_timer, NB_TASKS> timers{};
|
||||
struct Scope_guard {
|
||||
Tasks_manager *instance = nullptr;
|
||||
int task_id;
|
||||
Scope_guard(Tasks_manager *instance, int task_id) : instance(instance), task_id(task_id) {
|
||||
instance->timers[task_id].start();
|
||||
#if CGAL_USE_ITT
|
||||
__itt_task_begin(instance->cdt_3_domain, __itt_null, __itt_null, instance->task_handles[task_id]);
|
||||
#endif
|
||||
}
|
||||
auto time() const {
|
||||
return instance->timers[task_id].time();
|
||||
}
|
||||
auto time_ms() const {
|
||||
return instance->timers[task_id].time() / 1000.;
|
||||
}
|
||||
~Scope_guard() {
|
||||
instance->timers[task_id].stop();
|
||||
#if CGAL_USE_ITT
|
||||
__itt_task_end(instance->cdt_3_domain);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
Scope_guard make_task_scope_guard(int task_id) {
|
||||
return Scope_guard(this, task_id);
|
||||
}
|
||||
|
||||
Scope_guard READ_INPUT_TASK_guard() { return make_task_scope_guard(READ_INPUT); }
|
||||
Scope_guard MERGE_FACETS_TASK_guard() { return make_task_scope_guard(MERGE_FACETS); }
|
||||
Scope_guard INSERT_VERTICES_TASK_guard() { return make_task_scope_guard(INSERT_VERTICES); }
|
||||
Scope_guard COMPUTE_DISTANCES_TASK_guard() { return make_task_scope_guard(COMPUTE_DISTANCES); }
|
||||
Scope_guard CONFORMING_TASK_guard() { return make_task_scope_guard(CONFORMING); }
|
||||
Scope_guard CDT_TASK_guard() { return make_task_scope_guard(CDT); }
|
||||
Scope_guard OUTPUT_TASK_guard() { return make_task_scope_guard(OUTPUT); }
|
||||
Scope_guard VALIDATION_TASK_guard() { return make_task_scope_guard(VALIDATION); }
|
||||
|
||||
}; // end struct Intel_OneAPI_ITT_API
|
||||
|
||||
static Tasks_manager instance;
|
||||
return instance;
|
||||
} // end auto& tasks_manager()
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
} // end namespace CDT_3
|
||||
|
||||
inline auto CDT_3_READ_INPUT_TASK_guard() {
|
||||
return CDT_3::internal::tasks_manager().READ_INPUT_TASK_guard();
|
||||
}
|
||||
|
||||
inline auto CDT_3_MERGE_FACETS_TASK_guard() {
|
||||
return CDT_3::internal::tasks_manager().MERGE_FACETS_TASK_guard();
|
||||
}
|
||||
|
||||
inline auto CDT_3_INSERT_VERTICES_TASK_guard() {
|
||||
return CDT_3::internal::tasks_manager().INSERT_VERTICES_TASK_guard();
|
||||
}
|
||||
|
||||
inline auto CDT_3_COMPUTE_DISTANCES_TASK_guard() {
|
||||
return CDT_3::internal::tasks_manager().COMPUTE_DISTANCES_TASK_guard();
|
||||
}
|
||||
|
||||
inline auto CDT_3_CONFORMING_TASK_guard() {
|
||||
return CDT_3::internal::tasks_manager().CONFORMING_TASK_guard();
|
||||
}
|
||||
|
||||
inline auto CDT_3_CDT_TASK_guard() {
|
||||
return CDT_3::internal::tasks_manager().CDT_TASK_guard();
|
||||
}
|
||||
|
||||
inline auto CDT_3_OUTPUT_TASK_guard() {
|
||||
return CDT_3::internal::tasks_manager().OUTPUT_TASK_guard();
|
||||
}
|
||||
|
||||
inline auto CDT_3_VALIDATION_TASK_guard() {
|
||||
return CDT_3::internal::tasks_manager().VALIDATION_TASK_guard();
|
||||
}
|
||||
|
||||
template <typename T_3>
|
||||
class Conforming_Delaunay_triangulation_3 : public T_3 {
|
||||
public:
|
||||
|
|
@ -50,9 +252,9 @@ public:
|
|||
using Line = typename T_3::Geom_traits::Line_3;
|
||||
using Locate_type = typename T_3::Locate_type;
|
||||
|
||||
inline static With_offset_tag with_offset{};
|
||||
inline static With_point_tag with_point{};
|
||||
inline static With_point_and_info_tag with_point_and_info{};
|
||||
inline static With_offset_tag with_offset{ -1 };
|
||||
inline static With_point_tag with_point{ {-1} };
|
||||
inline static With_point_and_info_tag with_point_and_info{ { {-1} } };
|
||||
|
||||
Conforming_Delaunay_triangulation_3(const Geom_traits& gt = Geom_traits())
|
||||
: T_3(gt)
|
||||
|
|
@ -110,7 +312,7 @@ protected:
|
|||
if(v1 > v2) std::swap(v1, v2);
|
||||
auto v1_index = v1->time_stamp();
|
||||
[[maybe_unused]] auto nb_erased = self->all_finite_edges[v1_index].erase(v2);
|
||||
if constexpr (cdt_3_can_use_cxx20_format()) if(self->debug_finite_edges_map() && nb_erased > 0) {
|
||||
if constexpr (cdt_3_can_use_cxx20_format()) if(self->debug().finite_edges_map() && nb_erased > 0) {
|
||||
std::cerr << cdt_3_format("erasing edge {} {}\n", self->display_vert((std::min)(v1, v2)),
|
||||
self->display_vert((std::max)(v1, v2)));
|
||||
}
|
||||
|
|
@ -169,18 +371,17 @@ protected:
|
|||
void add_to_subconstraints_to_conform(Vertex_handle va, Vertex_handle vb,
|
||||
Constrained_polyline_id id) {
|
||||
const auto pair = make_subconstraint(va, vb);
|
||||
#if CGAL_DEBUG_CDT_3 & 32
|
||||
std::cerr << "tr().subconstraints_to_conform.push("
|
||||
<< display_subcstr(pair) << ")\n";
|
||||
#endif // CGAL_DEBUG_CDT_3
|
||||
if(debug().subconstraints_to_conform()) {
|
||||
std::cerr << "tr().subconstraints_to_conform.push("
|
||||
<< display_subcstr(pair) << ")\n";
|
||||
}
|
||||
subconstraints_to_conform.push({pair, id});
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
Constrained_polyline_id insert_constrained_edge_impl(Vertex_handle va, Vertex_handle vb,
|
||||
Visitor&) {
|
||||
Constrained_polyline_id insert_constrained_edge_impl(Vertex_handle va, Vertex_handle vb, Visitor&) {
|
||||
if(va != vb) {
|
||||
if(segment_vertex_epsilon != 0.) {
|
||||
if(debug().segment_vertex_epsilon() != 0.) {
|
||||
auto [min_dist, min_vertex] = min_distance_and_vertex_between_constraint_and_encroaching_vertex(va, vb);
|
||||
check_segment_vertex_distance_or_throw(va, vb, min_vertex, CGAL::to_double(min_dist),
|
||||
Check_distance::NON_SQUARED_DISTANCE);
|
||||
|
|
@ -217,7 +418,7 @@ protected:
|
|||
if(tr().is_infinite(v1) || tr().is_infinite(v2))
|
||||
return;
|
||||
[[maybe_unused]] auto [_, inserted] = all_finite_edges[v1->time_stamp()].insert(v2);
|
||||
if constexpr (cdt_3_can_use_cxx20_format()) if (debug_finite_edges_map() && inserted) {
|
||||
if constexpr (cdt_3_can_use_cxx20_format()) if (debug().finite_edges_map() && inserted) {
|
||||
if(v2 < v1) std::swap(v1, v2);
|
||||
std::cerr << cdt_3_format("new_edge({}, {})\n", display_vert(v1), display_vert(v2));
|
||||
}
|
||||
|
|
@ -268,7 +469,7 @@ protected:
|
|||
if(use_finite_edges_map()) {
|
||||
new_vertex(v);
|
||||
all_finite_edges.clear();
|
||||
if (debug_finite_edges_map()) std::cerr << "all_finite_edges.clear()\n";
|
||||
if (debug().finite_edges_map()) std::cerr << "all_finite_edges.clear()\n";
|
||||
for(auto e: tr().all_edges()) {
|
||||
new_edge(e);
|
||||
}
|
||||
|
|
@ -304,7 +505,7 @@ protected:
|
|||
}
|
||||
}
|
||||
|
||||
void update_max_bbox_edge_length() {
|
||||
void update_max_bbox_edge_length() const {
|
||||
double d_x = bbox.xmax() - bbox.xmin();
|
||||
double d_y = bbox.ymax() - bbox.ymin();
|
||||
double d_z = bbox.zmax() - bbox.zmin();
|
||||
|
|
@ -313,85 +514,15 @@ protected:
|
|||
}
|
||||
|
||||
public:
|
||||
void set_segment_vertex_epsilon(double epsilon) {
|
||||
segment_vertex_epsilon = epsilon;
|
||||
}
|
||||
CDT_3::Debug_options& debug() { return debug_options_; }
|
||||
const CDT_3::Debug_options& debug() const { return debug_options_; }
|
||||
|
||||
bool debug_Steiner_points() const {
|
||||
return debug_flags[static_cast<int>(Debug_flags::Steiner_points)];
|
||||
}
|
||||
|
||||
void debug_Steiner_points(bool b) {
|
||||
debug_flags.set(static_cast<int>(Debug_flags::Steiner_points), b);
|
||||
}
|
||||
|
||||
bool debug_input_faces() const {
|
||||
return debug_flags[static_cast<int>(Debug_flags::input_faces)];
|
||||
}
|
||||
|
||||
void debug_input_faces(bool b) {
|
||||
debug_flags.set(static_cast<int>(Debug_flags::input_faces), b);
|
||||
}
|
||||
|
||||
bool debug_missing_region() const {
|
||||
return debug_flags[static_cast<int>(Debug_flags::missing_region)];
|
||||
}
|
||||
|
||||
void debug_missing_region(bool b) {
|
||||
debug_flags.set(static_cast<int>(Debug_flags::missing_region), b);
|
||||
}
|
||||
|
||||
bool debug_regions() const {
|
||||
return debug_flags[static_cast<int>(Debug_flags::regions)];
|
||||
}
|
||||
|
||||
void debug_regions(bool b) {
|
||||
debug_flags.set(static_cast<int>(Debug_flags::regions), b);
|
||||
}
|
||||
|
||||
bool debug_copy_triangulation_into_hole() const {
|
||||
return debug_flags[static_cast<int>(Debug_flags::copy_triangulation_into_hole)];
|
||||
}
|
||||
|
||||
void debug_copy_triangulation_into_hole(bool b) {
|
||||
debug_flags.set(static_cast<int>(Debug_flags::copy_triangulation_into_hole), b);
|
||||
}
|
||||
|
||||
bool debug_validity() const {
|
||||
return debug_flags[static_cast<int>(Debug_flags::validity)];
|
||||
}
|
||||
|
||||
void debug_validity(bool b) {
|
||||
debug_flags.set(static_cast<int>(Debug_flags::validity), b);
|
||||
}
|
||||
|
||||
bool use_older_cavity_algorithm() const {
|
||||
return debug_flags[static_cast<int>(Debug_flags::use_older_cavity_algorithm)];
|
||||
}
|
||||
|
||||
bool use_newer_cavity_algorithm() const {
|
||||
return !debug_flags[static_cast<int>(Debug_flags::use_older_cavity_algorithm)];
|
||||
}
|
||||
|
||||
void use_older_cavity_algorithm(bool b) {
|
||||
debug_flags.set(static_cast<int>(Debug_flags::use_older_cavity_algorithm), b);
|
||||
}
|
||||
|
||||
bool debug_finite_edges_map() const {
|
||||
return debug_flags[static_cast<int>(Debug_flags::debug_finite_edges_map)];
|
||||
}
|
||||
|
||||
void debug_finite_edges_map(bool b) {
|
||||
debug_flags.set(static_cast<int>(Debug_flags::debug_finite_edges_map), b);
|
||||
}
|
||||
|
||||
bool use_finite_edges_map() const {
|
||||
return update_all_finite_edges_ && debug_flags[static_cast<int>(Debug_flags::use_finite_edges_map)];
|
||||
}
|
||||
|
||||
void use_finite_edges_map(bool b) {
|
||||
debug_flags.set(static_cast<int>(Debug_flags::use_finite_edges_map), b);
|
||||
}
|
||||
// Backward compatibility wrappers (deprecated, use debug().method() instead)
|
||||
bool use_older_cavity_algorithm() const { return debug_options_.use_older_cavity_algorithm(); }
|
||||
bool use_newer_cavity_algorithm() const { return debug_options_.use_newer_cavity_algorithm(); }
|
||||
void use_older_cavity_algorithm(bool b) { debug_options_.use_older_cavity_algorithm(b); }
|
||||
bool use_finite_edges_map() const { return update_all_finite_edges_ && debug_options_.use_finite_edges_map_flag(); }
|
||||
void use_finite_edges_map(bool b) { debug_options_.use_finite_edges_map(b); }
|
||||
|
||||
Vertex_handle insert(const Point &p, Locate_type lt, Cell_handle c,
|
||||
int li, int lj)
|
||||
|
|
@ -419,14 +550,14 @@ public:
|
|||
|
||||
bool is_edge(Vertex_handle va, Vertex_handle vb) const {
|
||||
const bool is_edge_v1 =
|
||||
((debug_finite_edges_map() && use_finite_edges_map()) || !use_finite_edges_map()) && tr().tds().is_edge(va, vb);
|
||||
((debug().finite_edges_map() && use_finite_edges_map()) || !use_finite_edges_map()) && tr().tds().is_edge(va, vb);
|
||||
|
||||
if(use_finite_edges_map() && va > vb) std::swap(va, vb);
|
||||
const auto va_index = va->time_stamp();
|
||||
const bool is_edge_v2 =
|
||||
use_finite_edges_map() && all_finite_edges[va_index].find(vb) != all_finite_edges[va_index].end();
|
||||
|
||||
if(debug_finite_edges_map() && use_finite_edges_map() && is_edge_v1 != is_edge_v2) {
|
||||
if(debug().finite_edges_map() && use_finite_edges_map() && is_edge_v1 != is_edge_v2) {
|
||||
std::cerr << "!! Inconsistent edge status\n";
|
||||
std::cerr << " -> constraint " << display_vert(va) << " " << display_vert(vb) << '\n';
|
||||
std::cerr << " -> edge " << (is_edge_v1 ? "is" : "is not") << " in the triangulation\n";
|
||||
|
|
@ -446,12 +577,12 @@ public:
|
|||
[this](const auto &sc) {
|
||||
const auto [va, vb] = sc;
|
||||
const auto is_edge = this->is_edge(va, vb);
|
||||
#if CGAL_DEBUG_CDT_3 & 128 && CGAL_CAN_USE_CXX20_FORMAT
|
||||
std::cerr << cdt_3_format("is_conforming>> Edge is 3D: {} ({} , {})\n",
|
||||
is_edge,
|
||||
CGAL::IO::oformat(va, with_point_and_info),
|
||||
CGAL::IO::oformat(vb, with_point_and_info));
|
||||
#endif // CGAL_DEBUG_CDT_3
|
||||
if constexpr (cdt_3_can_use_cxx20_format()) if(debug().conforming_validation()) {
|
||||
std::cerr << cdt_3_format("is_conforming>> Edge is 3D: {} ({} , {})\n",
|
||||
is_edge,
|
||||
CGAL::IO::oformat(va, with_point_and_info),
|
||||
CGAL::IO::oformat(vb, with_point_and_info));
|
||||
}
|
||||
return is_edge;
|
||||
});
|
||||
}
|
||||
|
|
@ -462,14 +593,15 @@ public:
|
|||
Vertex_handle vb,
|
||||
Vertex_handle min_vertex,
|
||||
double min_dist,
|
||||
Check_distance option)
|
||||
Check_distance distance_type = Check_distance::NON_SQUARED_DISTANCE) const
|
||||
{
|
||||
if(!max_bbox_edge_length) {
|
||||
update_max_bbox_edge_length();
|
||||
}
|
||||
if((option == Check_distance::NON_SQUARED_DISTANCE && min_dist < segment_vertex_epsilon * *max_bbox_edge_length) ||
|
||||
(option == Check_distance::SQUARED_DISTANCE &&
|
||||
min_dist < CGAL::square(segment_vertex_epsilon * *max_bbox_edge_length)))
|
||||
if((distance_type == Check_distance::NON_SQUARED_DISTANCE &&
|
||||
min_dist < debug().segment_vertex_epsilon() * *max_bbox_edge_length) ||
|
||||
(distance_type == Check_distance::SQUARED_DISTANCE &&
|
||||
min_dist < CGAL::square(debug().segment_vertex_epsilon() * *max_bbox_edge_length)))
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss.precision(std::cerr.precision());
|
||||
|
|
@ -482,6 +614,26 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void check_vertex_vertex_distance_or_throw(Vertex_handle va,
|
||||
Vertex_handle vb,
|
||||
double min_dist) const
|
||||
{
|
||||
if(!max_bbox_edge_length) {
|
||||
update_max_bbox_edge_length();
|
||||
}
|
||||
if(min_dist < debug_options_.vertex_vertex_epsilon() * *max_bbox_edge_length)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss.precision(std::cerr.precision());
|
||||
ss << "Two vertices are too close to each other.\n";
|
||||
ss << " -> vertex " << display_vert(va) << '\n';
|
||||
ss << " -> vertex " << display_vert(vb) << '\n';
|
||||
ss << " -> distance = " << min_dist << '\n';
|
||||
ss << " -> max_bbox_edge_length = " << *max_bbox_edge_length << '\n';
|
||||
CGAL_error_msg(ss.str().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
auto ancestors_of_Steiner_vertex_on_edge(Vertex_handle v) const {
|
||||
std::pair<Vertex_handle, Vertex_handle> result;
|
||||
CGAL_precondition(v->ccdt_3_data().is_Steiner_vertex_on_edge());
|
||||
|
|
@ -587,10 +739,10 @@ protected:
|
|||
if(!constraint_hierarchy.is_subconstraint(va, vb)) {
|
||||
continue;
|
||||
}
|
||||
#if CGAL_DEBUG_CDT_3 & 32
|
||||
std::cerr << "tr().subconstraints_to_conform.pop()="
|
||||
<< display_subcstr(subconstraint) << "\n";
|
||||
#endif // CGAL_DEBUG_CDT_3
|
||||
if(debug().subconstraints_to_conform()) {
|
||||
std::cerr << "tr().subconstraints_to_conform.pop()="
|
||||
<< display_subcstr(subconstraint) << "\n";
|
||||
}
|
||||
conform_subconstraint(subconstraint, constrained_polyline_id, visitor);
|
||||
}
|
||||
}
|
||||
|
|
@ -633,7 +785,7 @@ protected:
|
|||
const auto& [steiner_pt, hint, ref_vertex] = construct_Steiner_point(constraint, subconstraint);
|
||||
[[maybe_unused]] const auto v =
|
||||
insert_Steiner_point_on_subconstraint(steiner_pt, hint, subconstraint, constraint, visitor);
|
||||
if(debug_Steiner_points()) {
|
||||
if(debug().Steiner_points()) {
|
||||
const auto [c_start, c_end] = constraint_extremities(constraint);
|
||||
std::cerr << "(" << IO::oformat(va, with_offset) << ", " << IO::oformat(vb, with_offset) << ")";
|
||||
std::cerr << ": [ " << display_vert(c_start) << " - " << display_vert(c_end) << " ] ";
|
||||
|
|
@ -669,10 +821,10 @@ protected:
|
|||
this->constraint_hierarchy.constraints_end(), c_id) != this->constraint_hierarchy.constraints_end());
|
||||
CGAL_assertion(this->constraint_hierarchy.vertices_in_constraint_begin(c_id) !=
|
||||
this->constraint_hierarchy.vertices_in_constraint_end(c_id));
|
||||
#if CGAL_DEBUG_CDT_3 & 8
|
||||
std::cerr << "constraint " << (void*) c_id.vl_ptr() << " has "
|
||||
<< c_id.vl_ptr()->skip_size() << " vertices\n";
|
||||
#endif // CGAL_DEBUG_CDT_3
|
||||
if(debug().constraint_hierarchy()) {
|
||||
std::cerr << "constraint " << static_cast<void*>(c_id.vl_ptr()) << " has "
|
||||
<< c_id.vl_ptr()->skip_size() << " vertices\n";
|
||||
}
|
||||
const auto begin = this->constraint_hierarchy.vertices_in_constraint_begin(c_id);
|
||||
const auto end = this->constraint_hierarchy.vertices_in_constraint_end(c_id);
|
||||
const auto c_va = *begin;
|
||||
|
|
@ -730,9 +882,9 @@ protected:
|
|||
encroaching_vertices.insert(v);
|
||||
};
|
||||
auto fill_encroaching_vertices = [&](const auto simplex) {
|
||||
#if CGAL_DEBUG_CDT_3 & 0x10
|
||||
std::cerr << " - " << IO::oformat(simplex, With_point_tag{}) << '\n';
|
||||
#endif // CGAL_DEBUG_CDT_3
|
||||
if(debug().encroaching_vertices()) {
|
||||
std::cerr << " - " << IO::oformat(simplex, With_point_tag{}) << '\n';
|
||||
}
|
||||
auto visit_cell = [&](Cell_handle cell) {
|
||||
for(int i = 0, end = this->tr().dimension() + 1; i < end; ++i) {
|
||||
const auto v = cell->vertex(i);
|
||||
|
|
@ -776,9 +928,9 @@ protected:
|
|||
std::cerr << "!! The constraint passes through a vertex!\n";
|
||||
std::cerr << " -> constraint " << display_vert(va) << " " << display_vert(vb) << '\n';
|
||||
std::cerr << " -> vertex " << display_vert(v) << '\n';
|
||||
#if CGAL_DEBUG_CDT_3
|
||||
debug_dump("bug-through-vertex");
|
||||
#endif
|
||||
if(debug().geometric_errors()) {
|
||||
debug_dump("bug-through-vertex");
|
||||
}
|
||||
CGAL_error();
|
||||
}
|
||||
} break;
|
||||
|
|
@ -788,14 +940,14 @@ protected:
|
|||
std::for_each(tr().segment_traverser_simplices_begin(va, vb), tr().segment_traverser_simplices_end(),
|
||||
fill_encroaching_vertices);
|
||||
auto vector_of_encroaching_vertices = encroaching_vertices.extract_sequence();
|
||||
#if CGAL_DEBUG_CDT_3 & 0x10
|
||||
std::cerr << " -> vector_of_encroaching_vertices (before filter):\n";
|
||||
std::for_each(vector_of_encroaching_vertices.begin(),
|
||||
vector_of_encroaching_vertices.end(),
|
||||
[this](Vertex_handle v){
|
||||
std::cerr << " " << this->display_vert(v) << '\n';
|
||||
});
|
||||
#endif // CGAL_DEBUG_CDT_3
|
||||
if(debug().encroaching_vertices()) {
|
||||
std::cerr << " -> vector_of_encroaching_vertices (before filter):\n";
|
||||
std::for_each(vector_of_encroaching_vertices.begin(),
|
||||
vector_of_encroaching_vertices.end(),
|
||||
[this](Vertex_handle v){
|
||||
std::cerr << " " << this->display_vert(v) << '\n';
|
||||
});
|
||||
}
|
||||
auto end = std::remove_if(vector_of_encroaching_vertices.begin(),
|
||||
vector_of_encroaching_vertices.end(),
|
||||
[va, vb, pa, pb, &angle_functor, this](Vertex_handle v) {
|
||||
|
|
@ -804,13 +956,13 @@ protected:
|
|||
this->tr().point(v),
|
||||
pb) == ACUTE;
|
||||
});
|
||||
#if CGAL_DEBUG_CDT_3 & 0x10
|
||||
std::cerr << " -> vector_of_encroaching_vertices (after filter):\n";
|
||||
std::for_each(vector_of_encroaching_vertices.begin(), end, [&](Vertex_handle v) {
|
||||
std::cerr << " " << this->display_vert(v) << " angle " << approximate_angle(pa, this->tr().point(v), pb)
|
||||
<< '\n';
|
||||
});
|
||||
#endif // CGAL_DEBUG_CDT_3
|
||||
if(debug().encroaching_vertices()) {
|
||||
std::cerr << " -> vector_of_encroaching_vertices (after filter):\n";
|
||||
std::for_each(vector_of_encroaching_vertices.begin(), end, [&](Vertex_handle v) {
|
||||
std::cerr << " " << this->display_vert(v) << " angle " << approximate_angle(pa, this->tr().point(v), pb)
|
||||
<< '\n';
|
||||
});
|
||||
}
|
||||
vector_of_encroaching_vertices.erase(end, vector_of_encroaching_vertices.end());
|
||||
return vector_of_encroaching_vertices;
|
||||
}
|
||||
|
|
@ -840,10 +992,10 @@ protected:
|
|||
return {midpoint_functor(pa, pb), va->cell(), va};
|
||||
}
|
||||
|
||||
#if CGAL_DEBUG_CDT_3 & 0x10
|
||||
std::cerr << "construct_Steiner_point( " << display_vert(va) << " , "
|
||||
<< display_vert(vb) << " )\n";
|
||||
#endif // CGAL_DEBUG_CDT_3
|
||||
if(debug().encroaching_vertices()) {
|
||||
std::cerr << "construct_Steiner_point( " << display_vert(va) << " , "
|
||||
<< display_vert(vb) << " )\n";
|
||||
}
|
||||
|
||||
const auto vector_of_encroaching_vertices = encroaching_vertices(va, vb);
|
||||
CGAL_assertion(vector_of_encroaching_vertices.size() > 0);
|
||||
|
|
@ -909,7 +1061,7 @@ protected:
|
|||
return return_orig_result_point(lambda, orig_pb, orig_pa);
|
||||
}
|
||||
} else {
|
||||
if(segment_vertex_epsilon > 0) {
|
||||
if(debug().segment_vertex_epsilon() > 0) {
|
||||
if(!max_bbox_edge_length) {
|
||||
update_max_bbox_edge_length();
|
||||
}
|
||||
|
|
@ -940,8 +1092,7 @@ protected:
|
|||
Constraint_hierarchy constraint_hierarchy = {comp};
|
||||
static_assert(CGAL::cdt_3_msvc_2019_or_older() || CGAL::is_nothrow_movable_v<Constraint_hierarchy>);
|
||||
Bbox_3 bbox{};
|
||||
double segment_vertex_epsilon = 1e-8;
|
||||
std::optional<double> max_bbox_edge_length;
|
||||
mutable std::optional<double> max_bbox_edge_length;
|
||||
using Pair_of_vertex_handles = std::pair<Vertex_handle, Vertex_handle>;
|
||||
boost::container::map<Pair_of_vertex_handles, Constrained_polyline_id> pair_of_vertices_to_cid;
|
||||
Insert_in_conflict_visitor insert_in_conflict_visitor = {this};
|
||||
|
|
@ -973,20 +1124,7 @@ protected:
|
|||
}
|
||||
}
|
||||
|
||||
enum class Debug_flags {
|
||||
Steiner_points = 0,
|
||||
conforming,
|
||||
input_faces,
|
||||
missing_region,
|
||||
regions,
|
||||
copy_triangulation_into_hole,
|
||||
validity,
|
||||
use_older_cavity_algorithm,
|
||||
debug_finite_edges_map,
|
||||
use_finite_edges_map,
|
||||
nb_of_flags
|
||||
};
|
||||
std::bitset<static_cast<int>(Debug_flags::nb_of_flags)> debug_flags{};
|
||||
CDT_3::Debug_options debug_options_{};
|
||||
bool is_Delaunay = true;
|
||||
};
|
||||
|
||||
|
|
@ -994,6 +1132,5 @@ protected:
|
|||
|
||||
#endif // not DOXYGEN_RUNNING
|
||||
|
||||
#
|
||||
|
||||
#endif // CGAL_CONFORMING_DELAUNAY_TRIANGULATION_3_H
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -52,31 +52,33 @@ class Conforming_constrained_Delaunay_triangulation_cell_data_3 {
|
|||
void clear_mark(CDT_3_cell_marker m) { markers.reset(static_cast<unsigned>(m)); }
|
||||
void clear_marks() { markers.reset(); }
|
||||
|
||||
static unsigned int uint(int i) { return static_cast<unsigned int>(i); }
|
||||
|
||||
template <typename Facet_handle>
|
||||
void set_facet_constraint(int i, CDT_3_signed_index face_id,
|
||||
Facet_handle facet_2d)
|
||||
{
|
||||
this->face_id[unsigned(i)] = face_id;
|
||||
this->facet_2d[unsigned(i)] = static_cast<void*>(facet_2d == Facet_handle{} ? nullptr : std::addressof(*facet_2d));
|
||||
this->face_id[uint(i)] = face_id;
|
||||
this->facet_2d[uint(i)] = static_cast<void*>(facet_2d == Facet_handle{} ? nullptr : std::addressof(*facet_2d));
|
||||
}
|
||||
|
||||
template <typename CDT_2>
|
||||
auto face_2 (const CDT_2& cdt, int i) const {
|
||||
using Face = typename CDT_2::Face;
|
||||
auto ptr = static_cast<Face*>(facet_2d[unsigned(i)]);
|
||||
auto ptr = static_cast<Face*>(facet_2d[uint(i)]);
|
||||
return cdt.tds().faces().iterator_to(*ptr);
|
||||
}
|
||||
public:
|
||||
/// @{
|
||||
// @cond SKIP_IN_MANUAL
|
||||
bool is_facet_constrained(int i) const { return face_id[unsigned(i)] >= 0; }
|
||||
bool is_facet_constrained(int i) const { return face_id[uint(i)] >= 0; }
|
||||
|
||||
CDT_3_signed_index face_constraint_index(int i) const {
|
||||
return face_id[unsigned(i)];
|
||||
return face_id[uint(i)];
|
||||
}
|
||||
|
||||
void set_face_constraint_index(int i, CDT_3_signed_index index) {
|
||||
face_id[unsigned(i)] = index;
|
||||
face_id[uint(i)] = index;
|
||||
}
|
||||
/// @endcond
|
||||
};
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include <CGAL/assertions.h>
|
||||
#include <CGAL/Constrained_triangulation_3/internal/config.h>
|
||||
#include <CGAL/Constrained_triangulation_3_types.h>
|
||||
|
||||
#include <bitset>
|
||||
|
||||
|
|
@ -34,7 +35,7 @@ namespace CGAL {
|
|||
struct Conforming_constrained_Delaunay_triangulation_vertex_data_3 {};
|
||||
#else // DOXYGEN_RUNNING
|
||||
|
||||
enum class CDT_3_vertex_type { FREE, CORNER, STEINER_ON_EDGE, STEINER_IN_FACE };
|
||||
enum class CDT_3_vertex_type { FREE, CORNER, INPUT_VERTEX = CORNER, STEINER_ON_EDGE, STEINER_IN_FACE };
|
||||
|
||||
enum class CDT_3_vertex_marker {
|
||||
CLEAR = 0,
|
||||
|
|
@ -91,6 +92,8 @@ public:
|
|||
}
|
||||
|
||||
int number_of_incident_constraints() const {
|
||||
if(vertex_type() == CDT_3_vertex_type::STEINER_IN_FACE)
|
||||
return 0;
|
||||
CGAL_assertion(u.on_edge.nb_of_incident_constraints >= 0);
|
||||
return u.on_edge.nb_of_incident_constraints;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,13 +26,6 @@ create_single_source_cgal_program( "cdt_3_from_off_with_Epeck.cpp")
|
|||
target_link_libraries(cdt_3_from_off_with_Epeck PRIVATE CDT_3_dependencies)
|
||||
create_single_source_cgal_program( "snap_and_cdt3.cpp")
|
||||
|
||||
if(cxx_std_20 IN_LIST CMAKE_CXX_COMPILE_FEATURES)
|
||||
add_executable(cdt_3_from_off_CGAL_DEBUG_CDT_3 cdt_3_from_off)
|
||||
target_compile_definitions(cdt_3_from_off_CGAL_DEBUG_CDT_3 PRIVATE CGAL_DEBUG_CDT_3=255)
|
||||
target_link_libraries(cdt_3_from_off_CGAL_DEBUG_CDT_3 PRIVATE CDT_3_dependencies)
|
||||
cgal_add_test(cdt_3_from_off_CGAL_DEBUG_CDT_3)
|
||||
endif()
|
||||
|
||||
add_executable(test_CDT_3_insert_constrained_edge_from_EDG_file cdt_test_insert_constrained_edge_from_EDG_file.cpp)
|
||||
target_link_libraries(test_CDT_3_insert_constrained_edge_from_EDG_file PRIVATE CDT_3_dependencies)
|
||||
target_compile_definitions(test_CDT_3_insert_constrained_edge_from_EDG_file PUBLIC CGAL_TEST_CDT_3_USE_CDT)
|
||||
|
|
@ -85,7 +78,7 @@ function(CGAL_add_cdt3_from_off_test_aux data_name data_dir)
|
|||
endfunction()
|
||||
|
||||
function(CGAL_add_cdt3_from_off_test data_name)
|
||||
CGAL_add_cdt3_from_off_test_aux(${data_name} ${CGAL_DATA_DIR}/meshes)
|
||||
CGAL_add_cdt3_from_off_test_aux(${data_name} ${CGAL_DATA_DIR}/meshes ${ARGN})
|
||||
endfunction()
|
||||
|
||||
CGAL_add_cdt3_from_off_test("cube")
|
||||
|
|
@ -95,9 +88,10 @@ CGAL_add_cdt3_from_off_test("mpi")
|
|||
CGAL_add_cdt3_from_off_test("3torus")
|
||||
CGAL_add_cdt3_from_off_test("cheese-selection")
|
||||
CGAL_add_cdt3_from_off_test("cheese-selection-2")
|
||||
CGAL_add_cdt3_from_off_test("non_manifold_face_graph")
|
||||
|
||||
function(CGAL_add_cdt3_from_local_off_test data_name)
|
||||
CGAL_add_cdt3_from_off_test_aux(${data_name} ${CMAKE_CURRENT_SOURCE_DIR}/data)
|
||||
CGAL_add_cdt3_from_off_test_aux(${data_name} ${CMAKE_CURRENT_SOURCE_DIR}/data ${ARGN})
|
||||
endfunction()
|
||||
|
||||
CGAL_add_cdt3_from_local_off_test(cheese18)
|
||||
|
|
@ -130,17 +124,15 @@ if (CGAL_CDT_TEST_USE_THINGI)
|
|||
CGAL_add_cdt3_from_local_off_test(1514904-min8)
|
||||
CGAL_add_cdt3_from_local_off_test(1147177-min1)
|
||||
CGAL_add_cdt3_from_local_off_test(1452672-min1)
|
||||
CGAL_add_cdt3_from_local_off_test(135777-min3)
|
||||
CGAL_add_cdt3_from_local_off_test(196123-min3)
|
||||
CGAL_add_cdt3_from_local_off_test(200695-min3)
|
||||
CGAL_add_cdt3_from_local_off_test(285604-min8)
|
||||
CGAL_add_cdt3_from_local_off_test(error_mesh-p_not_equal_0-min2)
|
||||
|
||||
include(./Thingi10k-CDT.cmake)
|
||||
endif()
|
||||
|
||||
if(cxx_std_20 IN_LIST CMAKE_CXX_COMPILE_FEATURES)
|
||||
add_test(NAME "execution of cdt_3_from_off_CGAL_DEBUG_CDT_3 3torus" COMMAND cdt_3_from_off_CGAL_DEBUG_CDT_3 ${CGAL_DATA_DIR}/meshes/3torus.off)
|
||||
cgal_add_compilation_test(cdt_3_from_off_CGAL_DEBUG_CDT_3)
|
||||
cgal_setup_test_properties("execution of cdt_3_from_off_CGAL_DEBUG_CDT_3 3torus" cdt_3_from_off_CGAL_DEBUG_CDT_3)
|
||||
endif()
|
||||
|
||||
get_directory_property(all_tests TESTS)
|
||||
foreach(test ${all_tests})
|
||||
if(test MATCHES cdt|CDT)
|
||||
|
|
|
|||
|
|
@ -109,6 +109,152 @@ set(thingi10k_FAILED_WITH_MERGE_FACETS_CTest_20240222_2201
|
|||
1514904.stl
|
||||
)
|
||||
|
||||
set(thingi10k_FAILED_WITH_SEGFAULT_CTest_20251002
|
||||
1439534.stl
|
||||
196123.stl
|
||||
200695.stl
|
||||
135777.stl
|
||||
285604.stl
|
||||
822697.stl
|
||||
)
|
||||
|
||||
set(thingi10k_FAILED_CTest_20251002
|
||||
100606.stl
|
||||
100644.stl
|
||||
101955.stl
|
||||
109130.stl
|
||||
116873.stl
|
||||
116876.stl
|
||||
135777.stl
|
||||
139737.stl
|
||||
1439534.stl
|
||||
145329.stl
|
||||
145330.stl
|
||||
1505036.stl
|
||||
1514900.stl
|
||||
196121.stl
|
||||
196122.stl
|
||||
196123.stl
|
||||
196126.stl
|
||||
196127.stl
|
||||
199814.stl
|
||||
199818.stl
|
||||
200695.stl
|
||||
215991.stl
|
||||
230152.stl
|
||||
230153.stl
|
||||
239188.stl
|
||||
276937.stl
|
||||
285604.stl
|
||||
285605.stl
|
||||
288352.stl
|
||||
288353.stl
|
||||
288354.stl
|
||||
288355.stl
|
||||
39182.stl
|
||||
39245.stl
|
||||
472050.stl
|
||||
55278.stl
|
||||
61418.stl
|
||||
622000.stl
|
||||
669962.stl
|
||||
67817.stl
|
||||
702204.stl
|
||||
723893.stl
|
||||
822697.stl
|
||||
904476.stl
|
||||
91474.stl
|
||||
95796.stl
|
||||
95797.stl
|
||||
97515.stl
|
||||
)
|
||||
|
||||
set(thingi10k_FAILED_WITH_MERGE_FACETS_CTest_20251028
|
||||
139765.stl
|
||||
1452677.stl
|
||||
1452678.stl
|
||||
1452679.stl
|
||||
145329.stl
|
||||
145330.stl
|
||||
145331.stl
|
||||
1505036.stl
|
||||
1514900.stl
|
||||
153100.stl
|
||||
1652975.stl
|
||||
1652976.stl
|
||||
1706457.stl
|
||||
186546.stl
|
||||
196121.stl
|
||||
196122.stl
|
||||
196123.stl
|
||||
196126.stl
|
||||
196127.stl
|
||||
196194.stl
|
||||
199814.stl
|
||||
199818.stl
|
||||
206318.stl
|
||||
215991.stl
|
||||
230152.stl
|
||||
230153.stl
|
||||
237632.stl
|
||||
239188.stl
|
||||
255657.stl
|
||||
255658.stl
|
||||
276937.stl
|
||||
285603.stl
|
||||
286161.stl
|
||||
288352.stl
|
||||
288446.stl
|
||||
360073.stl
|
||||
362398.stl
|
||||
37743.stl
|
||||
383022.stl
|
||||
39182.stl
|
||||
39245.stl
|
||||
39495.stl
|
||||
39499.stl
|
||||
40841.stl
|
||||
41521.stl
|
||||
42040.stl
|
||||
44025.stl
|
||||
44064.stl
|
||||
44901.stl
|
||||
472050.stl
|
||||
50659.stl
|
||||
51797.stl
|
||||
57811.stl
|
||||
61418.stl
|
||||
61431.stl
|
||||
622000.stl
|
||||
62592.stl
|
||||
62593.stl
|
||||
65144.stl
|
||||
65395.stl
|
||||
65402.stl
|
||||
669962.stl
|
||||
68255.stl
|
||||
702204.stl
|
||||
70381.stl
|
||||
71461.stl
|
||||
723893.stl
|
||||
72419.stl
|
||||
726665.stl
|
||||
77343.stl
|
||||
84624.stl
|
||||
90225.stl
|
||||
906183.stl
|
||||
91147.stl
|
||||
91474.stl
|
||||
93702.stl
|
||||
93703.stl
|
||||
95796.stl
|
||||
95797.stl
|
||||
97515.stl
|
||||
97590.stl
|
||||
97593.stl
|
||||
99895.stl
|
||||
)
|
||||
|
||||
function(CGAL_add_cdt3_test_from_Thingi10k data_name data_filename)
|
||||
set(options "ONLY_MERGE_FACETS")
|
||||
set(oneValueArgs TIMEOUT)
|
||||
|
|
@ -145,6 +291,15 @@ foreach(thingi_file_name ${thingi10k_max_10k_solid})
|
|||
if(thingi_file_name IN_LIST thingi10k_FAILED_WITH_MERGE_FACETS_CTest_20240222_2201)
|
||||
list(APPEND LABELS "CTest_20240222_2201_failed_merge_facets")
|
||||
endif()
|
||||
if(thingi_file_name IN_LIST thingi10k_FAILED_CTest_20251002)
|
||||
list(APPEND LABELS "CTest_20251002_failed")
|
||||
endif()
|
||||
if(thingi_file_name IN_LIST thingi10k_FAILED_WITH_SEGFAULT_CTest_20251002)
|
||||
list(APPEND LABELS "CTest_20251002_failed_segfault")
|
||||
endif()
|
||||
if(thingi_file_name IN_LIST thingi10k_FAILED_WITH_MERGE_FACETS_CTest_20251028)
|
||||
list(APPEND LABELS "CTest_20251028_failed_merge_facets")
|
||||
endif()
|
||||
get_filename_component(thingi_ID "${thingi_file_name}" NAME_WE)
|
||||
CGAL_add_cdt3_test_from_Thingi10k(Thingi10K_${thingi_ID} ${thingi_file_name}
|
||||
TIMEOUT 600 LABELS ${LABELS} ${MY_ONLY_MERGE_FACETS})
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,6 +1,3 @@
|
|||
#if __has_include(<format>)
|
||||
#define CGAL_DEBUG_CDT_3 1
|
||||
#endif
|
||||
#define CGAL_TRIANGULATION_CHECK_EXPENSIVE 1
|
||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/Delaunay_triangulation_3.h>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,3 @@
|
|||
#if __has_include(<format>)
|
||||
#define CGAL_DEBUG_CDT_3 1
|
||||
#endif
|
||||
#define CGAL_TRIANGULATION_CHECK_EXPENSIVE 1
|
||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/Delaunay_triangulation_3.h>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,69 @@
|
|||
OFF
|
||||
42 23 0
|
||||
|
||||
9.4220000000000006 6.265949 1.2926169999999999
|
||||
9.4220000000000006 6.4378760000000002 0.4304
|
||||
9.4299999999999997 6.3669419999999999 1.3120000000000001
|
||||
9.4220000000000006 6.522742 1.2616000000000001
|
||||
9.4299999999999997 1.737943 2.867
|
||||
9.4299999999999997 1.310943 1.46
|
||||
9.4299999999999997 1.167238 0
|
||||
9.4299999999999997 5.7969429999999997 6.9269999999999996
|
||||
9.4299999999999997 16.167649999999998 0
|
||||
9.4299999999999997 4.499943 6.2329999999999997
|
||||
9.4299999999999997 3.3639420000000002 5.3010000000000002
|
||||
9.4299999999999997 2.4309430000000001 4.1639999999999997
|
||||
12.430999999999999 1.167238 0
|
||||
12.430999999999999 1.310943 1.46
|
||||
-7.2230889999999999 -5.1901419999999998 1.2724260000000001
|
||||
-7.2389999999999999 -5.1100570000000003 1.3959999999999999
|
||||
3.7330000000000001 -6.7590570000000003 0.79200000000000004
|
||||
-7.255185 -4.6623049999999999 0.88247529999999996
|
||||
-7.2552779999999997 -4.6682399999999999 0.88692839999999995
|
||||
3.7330000000000001 -6.2710569999999999 0.42699999999999999
|
||||
-7.262251 -4.5335140000000003 0.78721229999999998
|
||||
-7.7199999999999998 -4.2110570000000003 1.929
|
||||
-7.6440000000000001 -4.1590579999999999 1.6100000000000001
|
||||
-7.5739999999999998 -4.3940570000000001 1.726
|
||||
-7.5469999999999997 -3.6850580000000002 1.224
|
||||
-7.5369999999999999 -3.8630580000000001 1.3169999999999999
|
||||
-7.4050000000000002 -4.4780569999999997 1.4410000000000001
|
||||
-7.3220000000000001 -4.3380580000000002 1.022
|
||||
-7.4009999999999998 -4.689057 1.677
|
||||
-7.2534720000000004 -4.6835990000000001 0.89814380000000005
|
||||
9.4299999999999997 10.06494 1.929
|
||||
-7.2789999999999999 -4.0440569999999996 0.34699999999999998
|
||||
9.4299999999999997 6.3669419999999999 1.3120000000000001
|
||||
-7.2230889999999999 -5.1901419999999998 1.2724260000000001
|
||||
3.68716 -6.0934090000000003 0
|
||||
3.7330000000000001 -6.2710569999999999 0.42699999999999999
|
||||
3.7330000000000001 -6.2710569999999999 0.42699999999999999
|
||||
-7.262251 -4.5335140000000003 0.78721229999999998
|
||||
-7.6029999999999998 -4.5610569999999999 2.0139999999999998
|
||||
-7.4050000000000002 -4.4780569999999997 1.4410000000000001
|
||||
-7.3220000000000001 -4.3380580000000002 1.022
|
||||
-7.2599 -4.5207920000000001 0.75421059999999995
|
||||
3 0 1 2
|
||||
3 1 3 2
|
||||
3 4 32 5
|
||||
3 6 5 32
|
||||
3 8 32 30
|
||||
3 9 7 32
|
||||
3 32 7 30
|
||||
3 10 32 11
|
||||
3 4 11 32
|
||||
3 10 9 32
|
||||
3 6 32 8
|
||||
3 13 5 12
|
||||
3 38 23 21
|
||||
3 26 25 22
|
||||
3 24 25 26
|
||||
3 27 39 28
|
||||
3 16 19 14
|
||||
3 35 34 20
|
||||
3 18 29 36
|
||||
3 18 28 29
|
||||
3 15 33 29
|
||||
3 31 40 41
|
||||
3 40 17 37
|
||||
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
OFF
|
||||
37 34 0
|
||||
|
||||
172.45960998535156 327.00732421875 10.000033378601074
|
||||
173.35765075683594 327.18472290039062 10.000033378601074
|
||||
172.45960998535156 327.00732421875 10
|
||||
174.25531005859375 327.36398315429688 10.000033378601074
|
||||
175.282470703125 327.571533203125 10
|
||||
170.58482360839844 325.87066650390625 10
|
||||
170.58482360839844 325.87066650390625 10.000033378601074
|
||||
170.58476257324219 326.1373291015625 10
|
||||
170.58476257324219 326.1373291015625 10.000033378601074
|
||||
170.58488464355469 326.67068481445312 10.000033378601074
|
||||
170.58488464355469 326.67068481445312 10
|
||||
170.58477783203125 326.40402221679688 10.000033378601074
|
||||
170.58477783203125 326.40402221679688 10
|
||||
171.21096801757812 326.77630615234375 10
|
||||
171.21096801757812 326.77630615234375 10.000033378601074
|
||||
171.83589172363281 326.88851928710938 10.000033378601074
|
||||
171.83589172363281 326.88851928710938 10
|
||||
198.59626770019531 331.45306396484375 10
|
||||
171.3594970703125 325.91452026367188 10
|
||||
171.3594970703125 325.91452026367188 10.000033378601074
|
||||
171.10134887695312 325.89859008789062 10
|
||||
171.10134887695312 325.89859008789062 10.000033378601074
|
||||
170.84312438964844 325.88397216796875 10.000033378601074
|
||||
170.84312438964844 325.88397216796875 10
|
||||
173.88740539550781 326.08248901367188 10.000033378601074
|
||||
174.88548278808594 326.13330078125 10
|
||||
173.12164306640625 326.03756713867188 10
|
||||
172.62298583984375 326.00552368164062 10.000033378601074
|
||||
176.65058898925781 326.20169067382812 10
|
||||
179.54045104980469 326.31793212890625 10
|
||||
182.43142700195312 326.40179443359375 10
|
||||
192.267333984375 331.10971069335938 10
|
||||
197.96424865722656 332.17782592773438 10
|
||||
175.15260314941406 328.56558227539062 10.000033378601074
|
||||
175.15260314941406 325.1444091796875 10.000033378601074
|
||||
161.37049865722656 320.09548950195312 10.000033378601074
|
||||
161.37049865722656 332.70773315429688 10.000033378601074
|
||||
3 1 3 2
|
||||
3 2 3 4
|
||||
3 18 26 27
|
||||
3 27 26 24
|
||||
3 4 30 2
|
||||
3 31 32 17
|
||||
3 30 29 2
|
||||
3 2 29 16
|
||||
3 25 10 28
|
||||
3 10 25 12
|
||||
3 18 7 26
|
||||
3 18 20 7
|
||||
3 20 23 7
|
||||
3 23 5 7
|
||||
3 7 12 26
|
||||
3 26 12 25
|
||||
3 10 13 28
|
||||
3 13 16 28
|
||||
3 21 19 34
|
||||
3 21 34 22
|
||||
3 19 27 34
|
||||
3 36 11 35
|
||||
3 3 1 33
|
||||
3 1 0 33
|
||||
3 0 15 33
|
||||
3 15 14 33
|
||||
3 14 9 33
|
||||
3 33 9 36
|
||||
3 11 8 35
|
||||
3 8 6 35
|
||||
3 35 6 34
|
||||
3 6 22 34
|
||||
3 34 27 24
|
||||
3 11 36 9
|
||||
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
OFF
|
||||
25 17 0
|
||||
|
||||
137.05000305175781 47.498001098632812 132.02400207519531
|
||||
137.05000305175781 42.498001098632812 132.65000915527344
|
||||
137.05000305175781 20 131.40000915527344
|
||||
137.05000305175781 14.998001098632812 90.316001892089844
|
||||
137.05000305175781 0 133.90000915527344
|
||||
137.05000305175781 5 131.40000915527344
|
||||
120.80000305175781 0 133.90000915527344
|
||||
134.05000305175781 2.9980001449584961 133.90000915527344
|
||||
136.67401123046875 15.874000549316406 133.90000915527344
|
||||
137.12800598144531 5 132.33399963378906
|
||||
137.12800598144531 20 132.33399963378906
|
||||
137.36601257324219 5 133.24000549316406
|
||||
137.36601257324219 20 133.24000549316406
|
||||
137.75401306152344 5 134.09400939941406
|
||||
137.05000305175781 31.248001098632812 90.316001892089844
|
||||
137.05000305175781 16.248001098632812 133.90000915527344
|
||||
118.55000305175781 2.25 133.90000915527344
|
||||
104.55000305175781 0 133.90000915527344
|
||||
137.05000305175781 32.498001098632812 133.90000915527344
|
||||
55.800003051757812 0 133.90000915527344
|
||||
54.674003601074219 1.124000072479248 133.90000915527344
|
||||
55.050003051757812 0.74800002574920654 133.90000915527344
|
||||
136.30000305175781 31.750001907348633 133.90000915527344
|
||||
39.550003051757812 0 133.90000915527344
|
||||
137.05000305175781 20 118.12000274658203
|
||||
3 0 1 2
|
||||
3 4 5 2
|
||||
3 7 4 8
|
||||
3 10 9 11
|
||||
3 10 11 12
|
||||
3 12 11 13
|
||||
3 14 24 3
|
||||
3 2 15 4
|
||||
3 15 8 4
|
||||
3 17 7 16
|
||||
3 18 2 1
|
||||
3 7 17 6
|
||||
3 2 18 15
|
||||
3 7 8 22
|
||||
3 15 22 8
|
||||
3 20 23 21
|
||||
3 19 21 23
|
||||
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
OFF
|
||||
67 48 0
|
||||
|
||||
25.003999710083008 4.125999927520752 5.3249998092651367
|
||||
24.648000717163086 4.1110000610351562 5.3020000457763672
|
||||
27.875 4.124000072479248 5.3159999847412109
|
||||
28.104999542236328 4.0980000495910645 5.3020000457763672
|
||||
27.547000885009766 -0.76599997282028198 5.3020000457763672
|
||||
24.26300048828125 4.1999998092651367 5.3020000457763672
|
||||
24.350000381469727 -1.2070000171661377 5.3020000457763672
|
||||
22.61199951171875 -1.2680000066757202 5.3020000457763672
|
||||
18.076999664306641 -0.76700001955032349 5.3020000457763672
|
||||
20.534172058105469 6.6471333503723145 5.3020000457763672
|
||||
21.565000534057617 6.2769999504089355 5.3020000457763672
|
||||
21.576999664306641 6.2220001220703125 5.3020000457763672
|
||||
24.184999465942383 4.2010002136230469 5.3020000457763672
|
||||
24.132999420166016 4.2109999656677246 5.3020000457763672
|
||||
23.76099967956543 4.3359999656677246 5.3020000457763672
|
||||
23.552000045776367 4.3480663299560547 5.3020000457763672
|
||||
23.822000503540039 4.2779998779296875 5.3020000457763672
|
||||
23.259000778198242 4.4369997978210449 5.3029999732971191
|
||||
22.599832534790039 5.119999885559082 5.3020000457763672
|
||||
21.814010620117188 5.7782330513000488 5.3020000457763672
|
||||
22.527999877929688 4.9455761909484863 5.3020000457763672
|
||||
21.797874450683594 5.8303966522216797 5.3020968437194824
|
||||
22.527999877929688 4.6591053009033203 5.3020000457763672
|
||||
21.822000503540039 5.8159999847412109 6.0100002288818359
|
||||
21.772134780883789 5.687347412109375 5.3039073944091797
|
||||
21.657405853271484 5.9652857780456543 5.3020000457763672
|
||||
21.655532836914062 5.9393019676208496 5.3023014068603516
|
||||
21.794061660766602 5.8427157402038574 5.3020000457763672
|
||||
21.660037994384766 5.9280643463134766 5.3023800849914551
|
||||
21.660087585449219 5.9279398918151855 5.3023805618286133
|
||||
21.820028305053711 5.6319999694824219 5.3020000457763672
|
||||
21.659999847412109 5.9279999732971191 5.3020000457763672
|
||||
19.494876861572266 4.9111647605895996 5.3020000457763672
|
||||
21.641000747680664 5.9800000190734863 5.3020000457763672
|
||||
21.624000549316406 6.0019998550415039 5.309999942779541
|
||||
-2.1689999103546143 -0.46799999475479126 5.3020000457763672
|
||||
20.37629508972168 6.2305684089660645 5.3020000457763672
|
||||
-2.2790000438690186 -1.3259999752044678 6.0859999656677246
|
||||
-2.1040000915527344 0.082999996840953827 5.320000171661377
|
||||
22.329999923706055 5.0479998588562012 5.3020000457763672
|
||||
19.238409042358398 4.5272407531738281 5.3020000457763672
|
||||
-1.9989999532699585 0.26600000262260437 6.7109999656677246
|
||||
18.052036285400391 3.3704285621643066 5.3020000457763672
|
||||
20.326999664306641 6.2470002174377441 5.0159997940063477
|
||||
19.670000076293945 6.4640002250671387 3.7780001163482666
|
||||
18.603000640869141 4.8670001029968262 3.7780001163482666
|
||||
-0.6029999852180481 6.8179998397827148 2.6359999179840088
|
||||
0.33100000023841858 3.0639998912811279 5.0159997940063477
|
||||
-1.143372654914856 4.4346461296081543 5.3020000457763672
|
||||
-1.1940000057220459 4.5510001182556152 5.0159997940063477
|
||||
0.83399999141693115 3.4670000076293945 3.7780001163482666
|
||||
-3.2599999904632568 10 5.0159997940063477
|
||||
-2.5490000247955322 10 3.7780001163482666
|
||||
-2.3269999027252197 8.1979999542236328 3.7780001163482666
|
||||
-1.6699999570846558 6.4640002250671387 3.7780001163482666
|
||||
-2.1198277473449707 5.846644401550293 5.3020000457763672
|
||||
-3.0250000953674316 8.0860004425048828 5.0159997940063477
|
||||
-1.9939999580383301 3.0099999904632568 5.3020000457763672
|
||||
-1.2384099960327148 4.5272407531738281 5.3020000457763672
|
||||
-2.2780001163482666 3.7369999885559082 5.3020000457763672
|
||||
-2.0220000743865967 0.74299997091293335 6.0689997673034668
|
||||
-1.9220000505447388 1.1330000162124634 5.3020000457763672
|
||||
-1.9739999771118164 0.92799997329711914 5.314000129699707
|
||||
-2.1050000190734863 -0.041999999433755875 6.1490001678466797
|
||||
-2.3269999027252197 6.2470002174377441 5.0159997940063477
|
||||
-0.6029999852180481 4.8670001029968262 3.7780001163482666
|
||||
21.659999847412109 5.9279999732971191 5.3020000457763672
|
||||
3 2 3 0
|
||||
3 5 1 6
|
||||
3 3 4 1
|
||||
3 4 6 1
|
||||
3 12 5 6
|
||||
3 13 12 7
|
||||
3 25 19 30
|
||||
3 19 25 27
|
||||
3 24 29 23
|
||||
3 31 32 25
|
||||
3 25 30 31
|
||||
3 34 66 26
|
||||
3 33 25 32
|
||||
3 66 34 28
|
||||
3 10 11 36
|
||||
3 11 33 36
|
||||
3 27 18 19
|
||||
3 17 18 21
|
||||
3 39 22 32
|
||||
3 20 19 18
|
||||
3 40 32 22
|
||||
3 8 40 22
|
||||
3 16 8 14
|
||||
3 6 7 12
|
||||
3 15 14 8
|
||||
3 8 16 7
|
||||
3 36 9 10
|
||||
3 30 39 32
|
||||
3 31 30 32
|
||||
3 36 33 32
|
||||
3 43 45 44
|
||||
3 22 15 8
|
||||
3 8 42 40
|
||||
3 16 13 7
|
||||
3 49 58 55
|
||||
3 57 59 48
|
||||
3 51 52 56
|
||||
3 64 56 53
|
||||
3 65 54 46
|
||||
3 65 49 54
|
||||
3 49 64 54
|
||||
3 47 65 50
|
||||
3 47 49 65
|
||||
3 38 62 35
|
||||
3 62 61 35
|
||||
3 38 37 63
|
||||
3 41 60 63
|
||||
3 63 37 41
|
||||
|
||||
|
|
@ -40,7 +40,7 @@ int main(int argc, char* argv[])
|
|||
auto cdt = CGAL::make_conforming_constrained_Delaunay_triangulation_3<CDT>(mesh);
|
||||
static_assert(std::is_same_v<decltype(cdt), CDT>);
|
||||
CDT cdt2(mesh);
|
||||
const auto nb_cstr_facets = cdt2.number_of_constrained_facets();
|
||||
[[maybe_unused]] const auto nb_cstr_facets = cdt2.number_of_constrained_facets();
|
||||
|
||||
assert(cdt.triangulation().number_of_vertices() == cdt2.triangulation().number_of_vertices());
|
||||
assert(cdt.number_of_constrained_facets() == cdt2.number_of_constrained_facets());
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
OFF
|
||||
24 11 0
|
||||
|
||||
1.5 0.5 1
|
||||
0.5 0.5 0
|
||||
0.5 0.5 1
|
||||
0 0 0
|
||||
0 0.5 0
|
||||
0.5 0.5 0
|
||||
0.5 1 0
|
||||
0 1 0
|
||||
0.5 0 0
|
||||
1 0 0
|
||||
1 0.5 0
|
||||
1 1 0
|
||||
1.5 1.5 1
|
||||
2.5 1.5 1
|
||||
2.5 0.5 1
|
||||
-0.5 -0.5 1
|
||||
2.5 -0.5 1
|
||||
0.5 1.5 1
|
||||
-0.5 0.5 1
|
||||
1.5 0.5 1
|
||||
1.5 -0.5 1
|
||||
-0.5 1.5 1
|
||||
0.5 0.5 1
|
||||
0.5 -0.5 1
|
||||
3 2 1 0
|
||||
4 4 3 8 5
|
||||
4 7 4 5 6
|
||||
4 5 8 9 10
|
||||
4 6 5 10 11
|
||||
4 12 19 14 13
|
||||
4 19 20 16 14
|
||||
4 17 22 19 12
|
||||
4 22 23 20 19
|
||||
4 21 18 22 17
|
||||
4 18 15 23 22
|
||||
|
||||
|
|
@ -118600,7 +118600,7 @@ both for rendering and for modeling. Contains C code."
|
|||
|
||||
@article{ph-ddocs-92
|
||||
, author = "J. P. Pratt and V. P. Heuring"
|
||||
, title = "Designing digital optical computing systems: power and and crosstalk"
|
||||
, title = "Designing digital optical computing systems: power and crosstalk"
|
||||
, journal = "Appl. Optics"
|
||||
, volume = 31
|
||||
, number = 23
|
||||
|
|
|
|||
|
|
@ -13,12 +13,12 @@
|
|||
\cgalPkgPicture{detail.png}
|
||||
\cgalPkgSummaryBegin
|
||||
\cgalPkgAuthors{Andreas Fabri and Laurent Rineau}
|
||||
\cgalPkgDesc{This package provides classes for displaying \cgal objects and data structures in the <A HREF="https://doc.qt.io/qt-6/graphicsview.html">Qt 5 Graphics View Framework</A>.}
|
||||
\cgalPkgDesc{This package provides classes for displaying \cgal objects and data structures in the <A HREF="https://doc.qt.io/qt-6/graphicsview.html">Qt 6 Graphics View Framework</A>.}
|
||||
\cgalPkgManuals{Chapter_CGAL_and_the_Qt_Graphics_View_Framework,PkgGraphicsViewRef}
|
||||
\cgalPkgSummaryEnd
|
||||
\cgalPkgShortInfoBegin
|
||||
\cgalPkgSince{3.4}
|
||||
\cgalPkgDependsOn{\qt 5}
|
||||
\cgalPkgDependsOn{\qt 6}
|
||||
\cgalPkgBib{cgal:fr-cqgvf}
|
||||
\cgalPkgLicense{\ref licensesGPL "GPL"}
|
||||
\cgalPkgShortInfoEnd
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -462,10 +462,6 @@ namespace CGAL {
|
|||
} // end of the temporary compatibility with CGAL-4.14
|
||||
#endif // CGAL_NO_DEPRECATED_CODE
|
||||
|
||||
#if __has_include(<version>)
|
||||
# include <version>
|
||||
#endif
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
// Typedef for the type of nullptr.
|
||||
|
|
|
|||
|
|
@ -14,15 +14,15 @@
|
|||
|
||||
namespace CGAL { namespace internal {
|
||||
|
||||
template < typename T > inline
|
||||
void use(const T&) {}
|
||||
template <typename ...T> inline
|
||||
void use(T&&...) {}
|
||||
|
||||
template<typename> void use_type() {}
|
||||
|
||||
} }
|
||||
|
||||
/// CGAL_USE() is a macro which aims at removing "variable is unused" warnings.
|
||||
#define CGAL_USE(x) ::CGAL::internal::use(x)
|
||||
#define CGAL_USE(...) ::CGAL::internal::use(__VA_ARGS__)
|
||||
|
||||
/// CGAL_USE_TYPE() is a macro which aims at removing "typedef locally
|
||||
/// defined but not used" warnings.
|
||||
|
|
|
|||
|
|
@ -177,7 +177,7 @@ class Interval_for_container : public Interval_
|
|||
|
||||
|
||||
// remove markers for Interval I starting at left, the left endpoint
|
||||
// of I, and and stopping at the right endpoint of I.
|
||||
// of I, and stopping at the right endpoint of I.
|
||||
Interval_handle removeMarkers(IntervalSLnode<Interval>* left,
|
||||
const Interval& I);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2019
|
||||
// Copyright (c) 2019,2025
|
||||
// GeometryFactory (France)
|
||||
//
|
||||
// This file is part of CGAL (www.cgal.org)
|
||||
|
|
@ -9,6 +9,8 @@
|
|||
//
|
||||
//
|
||||
// Author(s) : Simon Giraudot
|
||||
//
|
||||
// Test file: test/Kernel_23/test_hash_functions.cpp
|
||||
|
||||
#ifndef CGAL_KERNEL_HASH_FUNCTIONS_H
|
||||
#define CGAL_KERNEL_HASH_FUNCTIONS_H
|
||||
|
|
@ -16,18 +18,73 @@
|
|||
#include <boost/functional/hash.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
#include <CGAL/representation_tags.h>
|
||||
#include <CGAL/Aff_transformation_2.h>
|
||||
#include <CGAL/Aff_transformation_3.h>
|
||||
#include <CGAL/Bbox_2.h>
|
||||
#include <CGAL/Bbox_3.h>
|
||||
#include <CGAL/Circle_2.h>
|
||||
#include <CGAL/Iso_rectangle_2.h>
|
||||
#include <CGAL/Iso_cuboid_3.h>
|
||||
#include <CGAL/Point_2.h>
|
||||
#include <CGAL/Point_3.h>
|
||||
#include <CGAL/Segment_2.h>
|
||||
#include <CGAL/Segment_3.h>
|
||||
#include <CGAL/Sphere_3.h>
|
||||
#include <CGAL/Vector_2.h>
|
||||
#include <CGAL/Vector_3.h>
|
||||
#include <CGAL/Weighted_point_2.h>
|
||||
#include <CGAL/Weighted_point_3.h>
|
||||
|
||||
|
||||
namespace CGAL
|
||||
{
|
||||
|
||||
using boost::hash_value;
|
||||
|
||||
template <typename K, typename = void>
|
||||
inline constexpr bool has_rep_tag_v = false;
|
||||
|
||||
template <typename K>
|
||||
inline std::enable_if_t<std::is_same<typename K::Rep_tag, Cartesian_tag>::value, std::size_t>
|
||||
inline constexpr bool has_rep_tag_v<K, std::void_t<typename K::Rep_tag>> = true;
|
||||
|
||||
template <typename K, typename = void>
|
||||
struct Rep_tag {
|
||||
using type = void;
|
||||
};
|
||||
|
||||
template <typename K>
|
||||
struct Rep_tag<K, std::enable_if_t<has_rep_tag_v<K>>> {
|
||||
using type = typename K::Rep_tag;
|
||||
};
|
||||
|
||||
template <typename K>
|
||||
using Rep_tag_t = typename Rep_tag<K>::type;
|
||||
|
||||
template <typename K>
|
||||
inline constexpr bool is_Cartesian_v = std::is_same<Rep_tag_t<K>, Cartesian_tag>::value;
|
||||
|
||||
template <typename K, typename = void>
|
||||
struct Is_kernel_hashable : public std::false_type {};
|
||||
|
||||
template <typename K>
|
||||
struct Is_kernel_hashable<K, std::void_t<decltype(hash_value(std::declval<typename K::FT>()))>> : public std::true_type {};
|
||||
|
||||
template <typename K>
|
||||
inline constexpr bool is_kernel_hashable_v = Is_kernel_hashable<K>::value;
|
||||
|
||||
template <typename K, typename T>
|
||||
using enable_if_Cartesian_and_hashable_t =
|
||||
std::enable_if_t<is_Cartesian_v<K> && is_kernel_hashable_v<K>, T>;
|
||||
|
||||
template <typename K>
|
||||
inline enable_if_Cartesian_and_hashable_t<K, std::size_t>
|
||||
hash_value (const Aff_transformation_2<K>& transform)
|
||||
{
|
||||
std::size_t result = hash_value(transform.cartesian(0,0));
|
||||
for(int i=0; i < 3; ++i)
|
||||
for(int j = 0; j < 3; ++j)
|
||||
for(int j=0; j < 3; ++j)
|
||||
// Skip (0,0) as it was already used to initialize the hash
|
||||
if (!(i == 0 && j == 0))
|
||||
boost::hash_combine(result, hash_value(transform.cartesian(i,j)));
|
||||
return result;
|
||||
|
|
@ -44,7 +101,7 @@ hash_value (const Bbox_2& bbox)
|
|||
}
|
||||
|
||||
template <typename K>
|
||||
inline std::enable_if_t<std::is_same<typename K::Rep_tag, Cartesian_tag>::value, std::size_t>
|
||||
inline enable_if_Cartesian_and_hashable_t<K, std::size_t>
|
||||
hash_value (const Circle_2<K>& circle)
|
||||
{
|
||||
std::size_t result = hash_value(circle.center());
|
||||
|
|
@ -54,7 +111,7 @@ hash_value (const Circle_2<K>& circle)
|
|||
}
|
||||
|
||||
template <typename K>
|
||||
inline std::enable_if_t<std::is_same<typename K::Rep_tag, Cartesian_tag>::value, std::size_t>
|
||||
inline enable_if_Cartesian_and_hashable_t<K, std::size_t>
|
||||
hash_value (const Iso_rectangle_2<K>& iso_rectangle)
|
||||
{
|
||||
std::size_t result = hash_value((iso_rectangle.min)());
|
||||
|
|
@ -63,7 +120,7 @@ hash_value (const Iso_rectangle_2<K>& iso_rectangle)
|
|||
}
|
||||
|
||||
template <typename K>
|
||||
inline std::enable_if_t<std::is_same<typename K::Rep_tag, Cartesian_tag>::value, std::size_t>
|
||||
inline enable_if_Cartesian_and_hashable_t<K, std::size_t>
|
||||
hash_value (const Point_2<K>& point)
|
||||
{
|
||||
std::size_t result = hash_value(point.x());
|
||||
|
|
@ -72,7 +129,7 @@ hash_value (const Point_2<K>& point)
|
|||
}
|
||||
|
||||
template <typename K>
|
||||
inline std::enable_if_t<std::is_same<typename K::Rep_tag, Cartesian_tag>::value, std::size_t>
|
||||
inline enable_if_Cartesian_and_hashable_t<K, std::size_t>
|
||||
hash_value (const Segment_2<K>& segment)
|
||||
{
|
||||
std::size_t result = hash_value(segment.source());
|
||||
|
|
@ -81,7 +138,7 @@ hash_value (const Segment_2<K>& segment)
|
|||
}
|
||||
|
||||
template <typename K>
|
||||
inline std::enable_if_t<std::is_same<typename K::Rep_tag, Cartesian_tag>::value, std::size_t>
|
||||
inline enable_if_Cartesian_and_hashable_t<K, std::size_t>
|
||||
hash_value (const Vector_2<K>& vector)
|
||||
{
|
||||
std::size_t result = hash_value(vector.x());
|
||||
|
|
@ -90,7 +147,7 @@ hash_value (const Vector_2<K>& vector)
|
|||
}
|
||||
|
||||
template <typename K>
|
||||
inline std::enable_if_t<std::is_same<typename K::Rep_tag, Cartesian_tag>::value, std::size_t>
|
||||
inline enable_if_Cartesian_and_hashable_t<K, std::size_t>
|
||||
hash_value (const Weighted_point_2<K>& weighed_point)
|
||||
{
|
||||
std::size_t result = hash_value(weighed_point.point());
|
||||
|
|
@ -99,14 +156,13 @@ hash_value (const Weighted_point_2<K>& weighed_point)
|
|||
}
|
||||
|
||||
template <typename K>
|
||||
inline std::enable_if_t<std::is_same<typename K::Rep_tag, Cartesian_tag>::value, std::size_t>
|
||||
inline enable_if_Cartesian_and_hashable_t<K, std::size_t>
|
||||
hash_value (const Aff_transformation_3<K>& transform)
|
||||
{
|
||||
std::size_t result = hash_value(transform.cartesian(0,0));
|
||||
for(int i = 0; i < 3; ++i)
|
||||
for(int j = 0; j < 4; ++j)
|
||||
if (!(i == 0 && j == 0))
|
||||
boost::hash_combine(result, hash_value(transform.cartesian(i,j)));
|
||||
for(int j = (i == 0 ? 1 : 0); j < 4; ++j)
|
||||
boost::hash_combine(result, hash_value(transform.cartesian(i,j)));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -123,7 +179,7 @@ hash_value (const Bbox_3& bbox)
|
|||
}
|
||||
|
||||
template <typename K>
|
||||
inline std::enable_if_t<std::is_same<typename K::Rep_tag, Cartesian_tag>::value, std::size_t>
|
||||
inline enable_if_Cartesian_and_hashable_t<K, std::size_t>
|
||||
hash_value (const Iso_cuboid_3<K>& iso_cuboid)
|
||||
{
|
||||
std::size_t result = hash_value((iso_cuboid.min)());
|
||||
|
|
@ -132,7 +188,7 @@ hash_value (const Iso_cuboid_3<K>& iso_cuboid)
|
|||
}
|
||||
|
||||
template <typename K>
|
||||
inline std::enable_if_t<std::is_same<typename K::Rep_tag, Cartesian_tag>::value, std::size_t>
|
||||
inline enable_if_Cartesian_and_hashable_t<K, std::size_t>
|
||||
hash_value (const Point_3<K>& point)
|
||||
{
|
||||
std::size_t result = hash_value(point.x());
|
||||
|
|
@ -142,7 +198,7 @@ hash_value (const Point_3<K>& point)
|
|||
}
|
||||
|
||||
template <typename K>
|
||||
inline std::enable_if_t<std::is_same<typename K::Rep_tag, Cartesian_tag>::value, std::size_t>
|
||||
inline enable_if_Cartesian_and_hashable_t<K, std::size_t>
|
||||
hash_value (const Segment_3<K>& segment)
|
||||
{
|
||||
std::size_t result = hash_value(segment.source());
|
||||
|
|
@ -151,7 +207,7 @@ hash_value (const Segment_3<K>& segment)
|
|||
}
|
||||
|
||||
template <typename K>
|
||||
inline std::enable_if_t<std::is_same<typename K::Rep_tag, Cartesian_tag>::value, std::size_t>
|
||||
inline enable_if_Cartesian_and_hashable_t<K, std::size_t>
|
||||
hash_value (const Sphere_3<K>& sphere)
|
||||
{
|
||||
std::size_t result = hash_value(sphere.center());
|
||||
|
|
@ -161,7 +217,7 @@ hash_value (const Sphere_3<K>& sphere)
|
|||
}
|
||||
|
||||
template <typename K>
|
||||
inline std::enable_if_t<std::is_same<typename K::Rep_tag, Cartesian_tag>::value, std::size_t>
|
||||
inline enable_if_Cartesian_and_hashable_t<K, std::size_t>
|
||||
hash_value (const Vector_3<K>& vector)
|
||||
{
|
||||
std::size_t result = hash_value(vector.x());
|
||||
|
|
@ -171,7 +227,7 @@ hash_value (const Vector_3<K>& vector)
|
|||
}
|
||||
|
||||
template <typename K>
|
||||
inline std::enable_if_t<std::is_same<typename K::Rep_tag, Cartesian_tag>::value, std::size_t>
|
||||
inline enable_if_Cartesian_and_hashable_t<K, std::size_t>
|
||||
hash_value (const Weighted_point_3<K>& weighed_point)
|
||||
{
|
||||
std::size_t result = hash_value(weighed_point.point());
|
||||
|
|
@ -179,93 +235,46 @@ hash_value (const Weighted_point_3<K>& weighed_point)
|
|||
return result;
|
||||
}
|
||||
|
||||
struct Forward_to_hash_value {
|
||||
template <typename T>
|
||||
std::size_t operator()(T&& t) const {
|
||||
using boost::hash_value;
|
||||
return hash_value(std::forward<T>(t));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename K, typename = void>
|
||||
struct Maybe_forward_to_hash_value {
|
||||
Maybe_forward_to_hash_value() = delete;
|
||||
Maybe_forward_to_hash_value(const Maybe_forward_to_hash_value&) = delete;
|
||||
};
|
||||
|
||||
template <typename K>
|
||||
struct Maybe_forward_to_hash_value<K, std::enable_if_t<is_kernel_hashable_v<K>>>
|
||||
: public Forward_to_hash_value {};
|
||||
|
||||
|
||||
} //namespace CGAL
|
||||
|
||||
// overloads of std::hash used for using std::unordered_[set/map] on CGAL Kernel objects
|
||||
namespace std
|
||||
{
|
||||
namespace std {
|
||||
template <typename K> struct hash<CGAL::Aff_transformation_2<K>> : CGAL::Maybe_forward_to_hash_value<K> {};
|
||||
template <typename K> struct hash<CGAL::Circle_2<K>> : CGAL::Maybe_forward_to_hash_value<K> {};
|
||||
template <typename K> struct hash<CGAL::Iso_rectangle_2<K>> : CGAL::Maybe_forward_to_hash_value<K> {};
|
||||
template <typename K> struct hash<CGAL::Point_2<K>> : CGAL::Maybe_forward_to_hash_value<K> {};
|
||||
template <typename K> struct hash<CGAL::Segment_2<K>> : CGAL::Maybe_forward_to_hash_value<K> {};
|
||||
template <typename K> struct hash<CGAL::Vector_2<K>> : CGAL::Maybe_forward_to_hash_value<K> {};
|
||||
template <typename K> struct hash<CGAL::Weighted_point_2<K>> : CGAL::Maybe_forward_to_hash_value<K> {};
|
||||
template <> struct hash<CGAL::Bbox_2> : CGAL::Forward_to_hash_value {};
|
||||
template <typename K> struct hash<CGAL::Aff_transformation_3<K>> : CGAL::Maybe_forward_to_hash_value<K> {};
|
||||
template <typename K> struct hash<CGAL::Iso_cuboid_3<K>> : CGAL::Maybe_forward_to_hash_value<K> {};
|
||||
template <typename K> struct hash<CGAL::Point_3<K>> : CGAL::Maybe_forward_to_hash_value<K> {};
|
||||
template <typename K> struct hash<CGAL::Segment_3<K>> : CGAL::Maybe_forward_to_hash_value<K> {};
|
||||
template <typename K> struct hash<CGAL::Sphere_3<K>> : CGAL::Maybe_forward_to_hash_value<K> {};
|
||||
template <typename K> struct hash<CGAL::Vector_3<K>> : CGAL::Maybe_forward_to_hash_value<K> {};
|
||||
template <typename K> struct hash<CGAL::Weighted_point_3<K>> : CGAL::Maybe_forward_to_hash_value<K> {};
|
||||
template <> struct hash<CGAL::Bbox_3> : CGAL::Forward_to_hash_value {};
|
||||
} // namespace std
|
||||
|
||||
template <typename K> struct hash<CGAL::Aff_transformation_2<K> > {
|
||||
std::size_t operator() (const CGAL::Aff_transformation_2<K>& transform) const {
|
||||
return CGAL::hash_value<K> (transform);
|
||||
}
|
||||
};
|
||||
template <> struct hash<CGAL::Bbox_2> {
|
||||
std::size_t operator() (const CGAL::Bbox_2& bbox) const {
|
||||
return CGAL::hash_value (bbox);
|
||||
}
|
||||
};
|
||||
template <typename K> struct hash<CGAL::Circle_2<K> > {
|
||||
std::size_t operator() (const CGAL::Circle_2<K>& circle) const {
|
||||
return CGAL::hash_value<K> (circle);
|
||||
}
|
||||
};
|
||||
template <typename K> struct hash<CGAL::Iso_rectangle_2<K> > {
|
||||
std::size_t operator() (const CGAL::Iso_rectangle_2<K>& iso_rectangle) const {
|
||||
return CGAL::hash_value<K> (iso_rectangle);
|
||||
}
|
||||
};
|
||||
template <typename K> struct hash<CGAL::Point_2<K> > {
|
||||
std::size_t operator() (const CGAL::Point_2<K>& point) const {
|
||||
return CGAL::hash_value<K> (point);
|
||||
}
|
||||
};
|
||||
template <typename K> struct hash<CGAL::Segment_2<K> > {
|
||||
std::size_t operator() (const CGAL::Segment_2<K>& segment) const {
|
||||
return CGAL::hash_value<K> (segment);
|
||||
}
|
||||
};
|
||||
template <typename K> struct hash<CGAL::Vector_2<K> > {
|
||||
std::size_t operator() (const CGAL::Vector_2<K>& vector) const {
|
||||
return CGAL::hash_value<K> (vector);
|
||||
}
|
||||
};
|
||||
template <typename K> struct hash<CGAL::Weighted_point_2<K> > {
|
||||
std::size_t operator() (const CGAL::Weighted_point_2<K>& weighted_point) const {
|
||||
return CGAL::hash_value<K> (weighted_point);
|
||||
}
|
||||
};
|
||||
template <typename K> struct hash<CGAL::Aff_transformation_3<K> > {
|
||||
std::size_t operator() (const CGAL::Aff_transformation_3<K>& transform) const {
|
||||
return CGAL::hash_value<K> (transform);
|
||||
}
|
||||
};
|
||||
template <> struct hash<CGAL::Bbox_3> {
|
||||
std::size_t operator() (const CGAL::Bbox_3& bbox) const {
|
||||
return CGAL::hash_value (bbox);
|
||||
}
|
||||
};
|
||||
template <typename K> struct hash<CGAL::Iso_cuboid_3<K> > {
|
||||
std::size_t operator() (const CGAL::Iso_cuboid_3<K>& iso_cuboid) const {
|
||||
return CGAL::hash_value<K> (iso_cuboid);
|
||||
}
|
||||
};
|
||||
template <typename K> struct hash<CGAL::Point_3<K> > {
|
||||
std::size_t operator() (const CGAL::Point_3<K>& point) const {
|
||||
return CGAL::hash_value<K> (point);
|
||||
}
|
||||
};
|
||||
template <typename K> struct hash<CGAL::Segment_3<K> > {
|
||||
std::size_t operator() (const CGAL::Segment_3<K>& segment) const {
|
||||
return CGAL::hash_value<K> (segment);
|
||||
}
|
||||
};
|
||||
template <typename K> struct hash<CGAL::Sphere_3<K> > {
|
||||
std::size_t operator() (const CGAL::Sphere_3<K>& sphere) const {
|
||||
return CGAL::hash_value<K> (sphere);
|
||||
}
|
||||
};
|
||||
template <typename K> struct hash<CGAL::Vector_3<K> > {
|
||||
std::size_t operator() (const CGAL::Vector_3<K>& vector) const {
|
||||
return CGAL::hash_value<K> (vector);
|
||||
}
|
||||
};
|
||||
template <typename K> struct hash<CGAL::Weighted_point_3<K> > {
|
||||
std::size_t operator() (const CGAL::Weighted_point_3<K>& weighted_point) const {
|
||||
return CGAL::hash_value<K> (weighted_point);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // CGAL_KERNEL_HASH_FUNCTIONS_H
|
||||
|
|
|
|||
|
|
@ -1,13 +1,18 @@
|
|||
// test partially generated by Github Copilot
|
||||
|
||||
#include <unordered_set>
|
||||
|
||||
#include <CGAL/Simple_cartesian.h>
|
||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
|
||||
#include <CGAL/Bbox_2.h>
|
||||
#include <CGAL/Bbox_3.h>
|
||||
|
||||
typedef CGAL::Simple_cartesian<double> SC;
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel Epick;
|
||||
|
||||
static_assert(CGAL::is_kernel_hashable_v<SC>);
|
||||
static_assert(CGAL::is_kernel_hashable_v<Epick>);
|
||||
|
||||
template <typename Object>
|
||||
void test (const Object& obj)
|
||||
{
|
||||
|
|
@ -67,5 +72,3 @@ int main()
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -78,6 +78,9 @@ pushd Triangulation_on_sphere_2_Demo_with_dlls; zip -r ../triangulation_on_spher
|
|||
pushd Lab_Demo_with_dlls; zip -r ../CGALlab.zip *; popd
|
||||
pushd Arrangement_on_surface_2_earth_Demo_with_dlls; zip -r ../arrangements_2_earth.zip *; popd
|
||||
|
||||
# CGAL-6.1
|
||||
pushd Triangulation_on_hyperbolic_surface_2_Demo_with_dlls; zip -r ../triangulation_on_hyperbolic_surface_2.zip *; popd
|
||||
|
||||
# check
|
||||
echo CHECK now. The following lines should be empty.
|
||||
for f in *zip; do unzip -qql $f; done | awk '{print $4}' >| done
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@
|
|||
#include <CGAL/iterator.h>
|
||||
#include <CGAL/number_utils.h>
|
||||
#include <CGAL/Delaunay_triangulation_3.h>
|
||||
#include <CGAL/Mesh_3/internal/Polyline.h>
|
||||
|
||||
#include <CGAL/boost/iterator/transform_iterator.hpp>
|
||||
|
||||
|
|
@ -142,6 +143,8 @@ public:
|
|||
using Distance_Function =
|
||||
typename CGAL::Default::Get<DistanceFunction, NoDistanceFunction>::type;
|
||||
|
||||
using Polyline_iterator = typename CGAL::Mesh_3::internal::Polyline<GT>::const_iterator;
|
||||
|
||||
private:
|
||||
typedef typename CGAL::Kernel_traits<MeshDomain>::Kernel Kernel;
|
||||
typedef Delaunay_triangulation_3<Kernel> Dt;
|
||||
|
|
@ -491,6 +494,8 @@ private:
|
|||
return use_edge_distance_;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private:
|
||||
C3T3& c3t3_;
|
||||
const MeshDomain& domain_;
|
||||
|
|
@ -598,7 +603,9 @@ Protect_edges_sizing_field<C3T3, MD, Sf, Df>::
|
|||
insert_corners()
|
||||
{
|
||||
// Iterate on domain corners
|
||||
typedef std::vector< std::pair<Corner_index, Bare_point> > Initial_corners;
|
||||
using Initial_corner = std::pair<Corner_index, Bare_point>;
|
||||
using Initial_corners = std::vector<Initial_corner>;
|
||||
|
||||
Initial_corners corners;
|
||||
domain_.get_corners(std::back_inserter(corners));
|
||||
|
||||
|
|
@ -609,20 +616,16 @@ insert_corners()
|
|||
#endif
|
||||
|
||||
Dt dt;
|
||||
for ( typename Initial_corners::iterator it = corners.begin(),
|
||||
end = corners.end() ; it != end ; ++it )
|
||||
for ( const auto& [_,p] : corners )
|
||||
{
|
||||
if(forced_stop()) break;
|
||||
const Bare_point& p = it->second;
|
||||
dt.insert(p);
|
||||
}
|
||||
|
||||
for ( typename Initial_corners::iterator cit = corners.begin(),
|
||||
end = corners.end() ; cit != end ; ++cit )
|
||||
for ( const auto& [corner_index, p] : corners )
|
||||
{
|
||||
if(forced_stop()) break;
|
||||
const Bare_point& p = cit->second;
|
||||
Index p_index = domain_.index_from_corner_index(cit->first);
|
||||
Index p_index = domain_.index_from_corner_index(corner_index);
|
||||
|
||||
#if CGAL_MESH_3_PROTECTION_DEBUG & 1
|
||||
std::cerr << "\n** treat corner #" << CGAL::IO::oformat(p_index) << std::endl;
|
||||
|
|
@ -671,7 +674,7 @@ insert_corners()
|
|||
// As C3t3::add_to_complex modifies the 'in_dimension' of the vertex,
|
||||
// we need to backup and re-set the 'is_special' marker after.
|
||||
const bool special_ball = is_special(v);
|
||||
c3t3_.add_to_complex(v,cit->first);
|
||||
c3t3_.add_to_complex(v, corner_index);
|
||||
if(special_ball) {
|
||||
set_special(v);
|
||||
}
|
||||
|
|
@ -1009,6 +1012,7 @@ insert_balls_on_edges()
|
|||
struct Feature_tuple
|
||||
{
|
||||
Curve_index curve_index_;
|
||||
Polyline_iterator polyline_begin_;
|
||||
std::pair<Bare_point, Index> point_s_;
|
||||
std::pair<Bare_point, Index> point_t_;
|
||||
};
|
||||
|
|
@ -1026,16 +1030,17 @@ insert_balls_on_edges()
|
|||
std::cerr << "\n** treat curve #" << curve_index << std::endl;
|
||||
#endif
|
||||
const Bare_point& p = ft.point_s_.first;
|
||||
const Bare_point& q = ft.point_t_.first;
|
||||
|
||||
const Index& p_index = ft.point_s_.second;
|
||||
const Index& q_index = ft.point_t_.second;
|
||||
const Polyline_iterator& p_polyline_iter = ft.polyline_begin_;
|
||||
|
||||
Vertex_handle vp,vq;
|
||||
if ( ! domain_.is_loop(curve_index) )
|
||||
{
|
||||
vp = get_vertex_corner_from_point(p,p_index);
|
||||
vq = get_vertex_corner_from_point(q,q_index);
|
||||
|
||||
const Bare_point& q = ft.point_t_.first;
|
||||
const Index& q_index = ft.point_t_.second;
|
||||
vq = get_vertex_corner_from_point(q, q_index);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1054,10 +1059,11 @@ insert_balls_on_edges()
|
|||
|
||||
FT curve_length = domain_.curve_length(curve_index);
|
||||
|
||||
Bare_point other_point =
|
||||
auto [other_point, _] =
|
||||
domain_.construct_point_on_curve(p,
|
||||
curve_index,
|
||||
curve_length / 2);
|
||||
curve_length / 2,
|
||||
ft.polyline_begin_);
|
||||
p_size = (std::min)(p_size,
|
||||
compute_distance(p, other_point) / 3);
|
||||
vp = smart_insert_point(p,
|
||||
|
|
@ -1066,7 +1072,9 @@ insert_balls_on_edges()
|
|||
p_index,
|
||||
Vertex_handle(),
|
||||
CGAL::Emptyset_iterator()).first;
|
||||
domain_.set_polyline_iterator(p, p_polyline_iter);
|
||||
}
|
||||
|
||||
// No 'else' because in that case 'is_vertex(..)' already filled
|
||||
// the variable 'vp'.
|
||||
vq = vp;
|
||||
|
|
@ -1238,10 +1246,13 @@ insert_balls(const Vertex_handle& vp,
|
|||
curve_index, d_sign)
|
||||
<< ")\n";
|
||||
#endif
|
||||
const Bare_point new_point =
|
||||
domain_.construct_point_on_curve(cp(vp_wp),
|
||||
const Bare_point p = cp(vp_wp);
|
||||
const auto [bp, polyline_iter] = //[Bare_point, Polyline_const_iterator]
|
||||
domain_.construct_point_on_curve(p,
|
||||
curve_index,
|
||||
d_signF * d / 2);
|
||||
d_signF * d / 2,
|
||||
domain_.locate_in_polyline(p, vp->in_dimension(), curve_index));
|
||||
const Bare_point new_point = bp;
|
||||
const int dim = 1; // new_point is on edge
|
||||
const Index index = domain_.index_from_curve_index(curve_index);
|
||||
const FT point_weight = CGAL::square(size_(new_point, dim, index));
|
||||
|
|
@ -1256,8 +1267,10 @@ insert_balls(const Vertex_handle& vp,
|
|||
index,
|
||||
Vertex_handle(),
|
||||
out);
|
||||
if(forced_stop()) return out;
|
||||
const Vertex_handle new_vertex = pair.first;
|
||||
domain_.set_polyline_iterator(new_point, polyline_iter);
|
||||
|
||||
if(forced_stop()) return out;
|
||||
out = pair.second;
|
||||
const FT sn = get_radius(new_vertex);
|
||||
if(sp <= sn) {
|
||||
|
|
@ -1274,7 +1287,7 @@ insert_balls(const Vertex_handle& vp,
|
|||
}
|
||||
} // nonlinear_growth_of_balls
|
||||
|
||||
FT r = (sq - sp) / FT(n+1);
|
||||
const FT r = (sq - sp) / FT(n+1);
|
||||
|
||||
#if CGAL_MESH_3_PROTECTION_DEBUG & 1
|
||||
std::cerr << " n=" << n
|
||||
|
|
@ -1283,9 +1296,9 @@ insert_balls(const Vertex_handle& vp,
|
|||
|
||||
|
||||
// Adjust size of steps, D = covered distance
|
||||
FT D = sp*FT(n+1) + FT((n+1)*(n+2)) / FT(2) * r ;
|
||||
const FT D = sp*FT(n+1) + FT((n+1)*(n+2)) / FT(2) * r ;
|
||||
|
||||
FT dleft_frac = d / D;
|
||||
const FT dleft_frac = d / D;
|
||||
|
||||
// Initialize step sizes
|
||||
FT step_size = sp + r;
|
||||
|
|
@ -1328,26 +1341,32 @@ insert_balls(const Vertex_handle& vp,
|
|||
#endif
|
||||
}
|
||||
|
||||
// Index and dimension
|
||||
const int dim = 1; // new_point is on edge
|
||||
const Index index = domain_.index_from_curve_index(curve_index);
|
||||
|
||||
// Launch balls
|
||||
for ( int i = 1 ; i <= n ; ++i )
|
||||
Polyline_iterator p_loc = domain_.locate_in_polyline(p, vp->in_dimension(), curve_index);
|
||||
CGAL_assertion(p_loc == domain_.locate_point(curve_index, p));
|
||||
Bare_point prev_pt = p;
|
||||
FT dist_to_prev = pt_dist;
|
||||
|
||||
for(int i = 1; i <= n; ++i)
|
||||
{
|
||||
// New point position
|
||||
Bare_point new_point =
|
||||
domain_.construct_point_on_curve(p, curve_index, pt_dist);
|
||||
const auto [new_point, polyline_iter] =
|
||||
domain_.construct_point_on_curve(prev_pt, curve_index, dist_to_prev, p_loc);
|
||||
|
||||
// Weight (use as size the min between norm_step_size and linear interpolation)
|
||||
FT current_size = (std::min)(norm_step_size, sp + CGAL::abs(pt_dist)/d*(sq-sp));
|
||||
FT point_weight = current_size * current_size;
|
||||
|
||||
// Index and dimension
|
||||
Index index = domain_.index_from_curve_index(curve_index);
|
||||
int dim = 1; // new_point is on edge
|
||||
const FT current_size = (std::min)(norm_step_size, sp + CGAL::abs(pt_dist)/d*(sq-sp));
|
||||
const FT point_weight = current_size * current_size;
|
||||
|
||||
// Insert point into c3t3
|
||||
std::pair<Vertex_handle, ErasedVeOutIt> pair =
|
||||
smart_insert_point(new_point, point_weight, dim, index, prev, out);
|
||||
Vertex_handle new_vertex = pair.first;
|
||||
out = pair.second;
|
||||
domain_.set_polyline_iterator(new_point, polyline_iter);
|
||||
|
||||
// Add edge to c3t3
|
||||
if(!c3t3_.is_in_complex(prev, new_vertex)) {
|
||||
|
|
@ -1359,8 +1378,12 @@ insert_balls(const Vertex_handle& vp,
|
|||
step_size += r;
|
||||
norm_step_size = dleft_frac * step_size;
|
||||
|
||||
// Increment distance
|
||||
pt_dist += d_signF * norm_step_size;
|
||||
// Update distance
|
||||
dist_to_prev = d_signF* norm_step_size;
|
||||
pt_dist += dist_to_prev;
|
||||
|
||||
prev_pt = new_point;
|
||||
p_loc = polyline_iter;
|
||||
}
|
||||
|
||||
// Insert last edge into c3t3
|
||||
|
|
@ -1553,15 +1576,28 @@ approx_is_too_large(const Edge& e, const bool is_edge_in_complex) const
|
|||
if ( ! is_edge_in_complex )
|
||||
return false;
|
||||
|
||||
const Bare_point& pa = e.first->vertex(e.second)->point().point();
|
||||
const Bare_point& pb = e.first->vertex(e.third)->point().point();
|
||||
Vertex_handle va = e.first->vertex(e.second);
|
||||
Vertex_handle vb = e.first->vertex(e.third);
|
||||
|
||||
const Bare_point& pa = va->point().point();
|
||||
const Bare_point& pb = vb->point().point();
|
||||
|
||||
const Curve_index curve_index = c3t3_.curve_index(e);
|
||||
Polyline_iterator pa_it = domain_.locate_in_polyline(pa, va->in_dimension(), curve_index);
|
||||
Polyline_iterator pb_it = domain_.locate_in_polyline(pb, vb->in_dimension(), curve_index);
|
||||
|
||||
// Construct the geodesic middle point
|
||||
const Curve_index curve_index = c3t3_.curve_index(e);
|
||||
const FT signed_geodesic_distance = domain_.signed_geodesic_distance(pa, pb, curve_index);
|
||||
const Bare_point geodesic_middle = (signed_geodesic_distance >= FT(0))
|
||||
? domain_.construct_point_on_curve(pa, curve_index, signed_geodesic_distance / 2)
|
||||
: domain_.construct_point_on_curve(pb, curve_index, -signed_geodesic_distance / 2);
|
||||
const FT signed_geodesic_distance
|
||||
= domain_.signed_geodesic_distance(pa, pb, pa_it, pb_it, curve_index);
|
||||
const auto [geodesic_middle, _ /*polyline_iter*/] = (signed_geodesic_distance >= FT(0))
|
||||
? domain_.construct_point_on_curve(pa,
|
||||
curve_index,
|
||||
signed_geodesic_distance / 2,
|
||||
pa_it)
|
||||
: domain_.construct_point_on_curve(pb,
|
||||
curve_index,
|
||||
-signed_geodesic_distance / 2,
|
||||
pb_it);
|
||||
|
||||
const Bare_point edge_middle = CGAL::midpoint(pa, pb);
|
||||
const FT squared_evaluated_distance = CGAL::squared_distance(edge_middle, geodesic_middle);
|
||||
|
|
@ -1822,12 +1858,14 @@ curve_segment_length(const Vertex_handle v1,
|
|||
v2_valid_curve_index = (domain_.curve_index(v2->index()) == curve_index);
|
||||
}
|
||||
|
||||
const Weighted_point& v1_wp = c3t3_.triangulation().point(v1);
|
||||
const Weighted_point& v2_wp = c3t3_.triangulation().point(v2);
|
||||
const Bare_point p1 = cp(c3t3_.triangulation().point(v1));
|
||||
const Bare_point p2 = cp(c3t3_.triangulation().point(v2));
|
||||
|
||||
FT arc_length = (v1_valid_curve_index && v2_valid_curve_index)
|
||||
? domain_.curve_segment_length(cp(v1_wp),
|
||||
cp(v2_wp),
|
||||
? domain_.curve_segment_length(p1,
|
||||
p2,
|
||||
domain_.locate_in_polyline(p1, v1->in_dimension(), curve_index),
|
||||
domain_.locate_in_polyline(p2, v2->in_dimension(), curve_index),
|
||||
curve_index,
|
||||
orientation)
|
||||
: compute_distance(v1, v2); //curve polyline may not be consistent
|
||||
|
|
@ -1879,10 +1917,16 @@ is_sampling_dense_enough(const Vertex_handle& v1, const Vertex_handle& v2,
|
|||
const Weighted_point& v1_wp = c3t3_.triangulation().point(v1);
|
||||
const Weighted_point& v2_wp = c3t3_.triangulation().point(v2);
|
||||
|
||||
const Bare_point p1 = cp(v1_wp);
|
||||
const Bare_point p2 = cp(v2_wp);
|
||||
|
||||
const bool cov = domain_.is_curve_segment_covered(curve_index,
|
||||
orientation,
|
||||
cp(v1_wp), cp(v2_wp),
|
||||
cw(v1_wp), cw(v2_wp));
|
||||
orientation,
|
||||
p1, p2,
|
||||
cw(v1_wp), cw(v2_wp),
|
||||
domain_.locate_in_polyline(p1, v1->in_dimension(), curve_index),
|
||||
domain_.locate_in_polyline(p2, v2->in_dimension(), curve_index));
|
||||
|
||||
#if CGAL_MESH_3_PROTECTION_DEBUG & 1
|
||||
if(cov) {
|
||||
std::cerr << " But the curve is locally covered\n";
|
||||
|
|
@ -1915,18 +1959,28 @@ orientation_of_walk(const Vertex_handle& start,
|
|||
|
||||
const Weighted_point& start_wp = c3t3_.triangulation().point(start);
|
||||
const Weighted_point& next_wp = c3t3_.triangulation().point(next);
|
||||
const Bare_point start_p = cp(start_wp);
|
||||
const Bare_point next_p = cp(next_wp);
|
||||
|
||||
if(domain_.is_loop(curve_index)) {
|
||||
// if the curve is a cycle, the direction is the direction passing
|
||||
// through the next vertex, and the next-next vertex
|
||||
Vertex_handle next_along_curve = next_vertex_along_curve(next,start,curve_index);
|
||||
const Weighted_point& next_along_curve_wp = c3t3_.triangulation().point(next_along_curve);
|
||||
const Bare_point next_along_curve_p = cp(next_along_curve_wp);
|
||||
|
||||
return domain_.distance_sign_along_loop(
|
||||
cp(start_wp), cp(next_wp), cp(next_along_curve_wp), curve_index);
|
||||
} else {
|
||||
start_p, next_p, next_along_curve_p, curve_index,
|
||||
domain_.locate_in_polyline(start_p, start->in_dimension(), curve_index),
|
||||
domain_.locate_in_polyline(next_p, next->in_dimension(), curve_index),
|
||||
domain_.locate_in_polyline(next_along_curve_p, next_along_curve->in_dimension(), curve_index));
|
||||
}
|
||||
else
|
||||
{
|
||||
// otherwise, the sign is just the sign of the geodesic distance
|
||||
return domain_.distance_sign(cp(start_wp), cp(next_wp), curve_index);
|
||||
return domain_.distance_sign(start_p, next_p, curve_index,
|
||||
domain_.locate_in_polyline(start_p, start->in_dimension(), curve_index),
|
||||
domain_.locate_in_polyline(next_p, next->in_dimension(), curve_index));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,561 @@
|
|||
// Copyright (c) 2009-2010 INRIA Sophia-Antipolis (France).
|
||||
// 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) : Stéphane Tayeb, Laurent Rineau
|
||||
//
|
||||
//******************************************************************************
|
||||
// File Description :
|
||||
//
|
||||
//******************************************************************************
|
||||
|
||||
#ifndef CGAL_MESH_3_INTERNAL_POLYLINE_H
|
||||
#define CGAL_MESH_3_INTERNAL_POLYLINE_H
|
||||
|
||||
#include <CGAL/license/Mesh_3.h>
|
||||
|
||||
#include <CGAL/iterator.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
/// @cond DEVELOPERS
|
||||
namespace Mesh_3 {
|
||||
namespace internal {
|
||||
|
||||
template <typename Kernel>
|
||||
class Polyline
|
||||
{
|
||||
typedef typename Kernel::Point_3 Point_3;
|
||||
typedef typename Kernel::Segment_3 Segment_3;
|
||||
typedef typename Kernel::FT FT;
|
||||
|
||||
typedef std::vector<Point_3> Data;
|
||||
|
||||
public:
|
||||
typedef typename Data::const_iterator const_iterator;
|
||||
typedef std::pair<Point_3, const_iterator> Point_and_location;
|
||||
|
||||
Polyline() {}
|
||||
~Polyline() {}
|
||||
|
||||
/// adds a point at the end of the polyline
|
||||
void add_point(const Point_3& p)
|
||||
{
|
||||
if( points_.empty() || p != end_point() ) {
|
||||
points_.push_back(p);
|
||||
}
|
||||
}
|
||||
|
||||
/// returns the starting point of the polyline
|
||||
const Point_3& start_point() const
|
||||
{
|
||||
CGAL_assertion( ! points_.empty() );
|
||||
return points_.front();
|
||||
}
|
||||
|
||||
/// returns the ending point of the polyline
|
||||
const Point_3& end_point() const
|
||||
{
|
||||
CGAL_assertion( ! points_.empty() );
|
||||
return points_.back();
|
||||
}
|
||||
|
||||
/// returns `true` if the polyline is not degenerate
|
||||
bool is_valid() const
|
||||
{
|
||||
return points_.size() > 1;
|
||||
}
|
||||
|
||||
/// returns `true` if polyline is a loop
|
||||
bool is_loop() const
|
||||
{
|
||||
return start_point() == end_point();
|
||||
}
|
||||
|
||||
const_iterator next(const_iterator it, Orientation orientation) const {
|
||||
if(orientation == POSITIVE) {
|
||||
CGAL_assertion(it != (points_.end() - 1));
|
||||
if(it == (points_.end() - 2)) {
|
||||
CGAL_assertion(is_loop());
|
||||
it = points_.begin();
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
} else {
|
||||
CGAL_assertion(orientation == NEGATIVE);
|
||||
CGAL_assertion(it != points_.begin());
|
||||
if(it == (points_.begin() + 1)) {
|
||||
CGAL_assertion(is_loop());
|
||||
it = points_.end() - 1;
|
||||
} else {
|
||||
--it;
|
||||
}
|
||||
}
|
||||
return it;
|
||||
}
|
||||
|
||||
bool is_curve_segment_covered(CGAL::Orientation orientation,
|
||||
const Point_3& c1, const Point_3& c2,
|
||||
const FT sq_r1, const FT sq_r2,
|
||||
const const_iterator cc1_it,
|
||||
const const_iterator cc2_it) const
|
||||
{
|
||||
CGAL_assertion(orientation != CGAL::ZERO);
|
||||
typename Kernel::Has_on_bounded_side_3 cover_pred =
|
||||
Kernel().has_on_bounded_side_3_object();
|
||||
|
||||
typedef typename Kernel::Sphere_3 Sphere_3;
|
||||
const Sphere_3 s1(c1, sq_r1);
|
||||
const Sphere_3 s2(c2, sq_r2);
|
||||
|
||||
const_iterator c1_it = cc1_it;
|
||||
const_iterator c2_it = cc2_it;
|
||||
|
||||
if(orientation == CGAL::NEGATIVE) {
|
||||
++c1_it;
|
||||
++c2_it;
|
||||
CGAL_assertion(c1_it != points_.end());
|
||||
CGAL_assertion(c2_it != points_.end());
|
||||
}
|
||||
|
||||
if(c1_it == c2_it) return cover_pred(s1, s2, c1, c2);
|
||||
const_iterator next_it = this->next(c1_it, orientation);
|
||||
|
||||
if(!cover_pred(s1, s2, c1, *next_it)) return false;
|
||||
|
||||
for(const_iterator it = next_it; it != c2_it; /* in body */) {
|
||||
next_it = this->next(it, orientation);
|
||||
if(!cover_pred(s1, s2, *it, *next_it)) return false;
|
||||
it = next_it;
|
||||
} // end loop ]c1_it, c2_it[
|
||||
|
||||
return cover_pred(s1, s2, *c2_it, c2);
|
||||
}
|
||||
|
||||
bool is_curve_segment_covered(CGAL::Orientation orientation,
|
||||
const Point_3& c1, const Point_3& c2,
|
||||
const FT sq_r1, const FT sq_r2) const
|
||||
{
|
||||
return is_curve_segment_covered(orientation,
|
||||
c1, c2, sq_r1, sq_r2, locate(c1), locate(c2));
|
||||
}
|
||||
|
||||
FT curve_segment_length(const Point_3& p, const Point_3 q,
|
||||
CGAL::Orientation orientation) const
|
||||
{
|
||||
CGAL_assertion(orientation != CGAL::ZERO);
|
||||
const_iterator p_it = locate(p);
|
||||
const_iterator q_it = locate(q);
|
||||
return curve_segment_length(p, q, orientation, p_it, q_it);
|
||||
}
|
||||
|
||||
FT curve_segment_length(const Point_3& p, const Point_3 q,
|
||||
CGAL::Orientation orientation,
|
||||
const_iterator p_it,
|
||||
const_iterator q_it) const
|
||||
{
|
||||
CGAL_assertion(orientation != CGAL::ZERO);
|
||||
CGAL_assertion(p_it == locate(p));
|
||||
CGAL_assertion(q_it == locate(q));
|
||||
|
||||
if(p_it == q_it) {
|
||||
const CGAL::Comparison_result cmp = compare_distance(*p_it,p,q);
|
||||
if( (cmp != LARGER && orientation == POSITIVE) ||
|
||||
(cmp != SMALLER && orientation == NEGATIVE) )
|
||||
{
|
||||
// If the orientation of `p` and `q` on the segment is compatible
|
||||
// with `orientation`, then return the distance between the two
|
||||
// points.
|
||||
return distance(p, q);
|
||||
}
|
||||
}
|
||||
|
||||
if(orientation == CGAL::NEGATIVE) {
|
||||
++p_it;
|
||||
++q_it;
|
||||
CGAL_assertion(p_it != points_.end());
|
||||
CGAL_assertion(q_it != points_.end());
|
||||
}
|
||||
|
||||
const_iterator next_it = this->next(p_it, orientation);
|
||||
FT result = distance(p, *next_it);
|
||||
for(const_iterator it = next_it; it != q_it; /* in body */) {
|
||||
next_it = this->next(it, orientation);
|
||||
result += distance(*it, *next_it);
|
||||
it = next_it;
|
||||
} // end loop ]p_it, q_it[
|
||||
result += distance(*q_it, q);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/// returns the angle at the first point.
|
||||
/// \pre The polyline must be a loop.
|
||||
Angle angle_at_first_point() const {
|
||||
CGAL_precondition(is_loop());
|
||||
const Point_3& first = points_.front();
|
||||
const Point_3& next_p = points_[1];
|
||||
const Point_3& prev = points_[points_.size() - 2];
|
||||
return angle(prev, first, next_p);
|
||||
}
|
||||
|
||||
/// returns the length of the polyline
|
||||
FT length() const
|
||||
{
|
||||
if(length_ < 0.)
|
||||
{
|
||||
FT result(0);
|
||||
const_iterator it = points_.begin();
|
||||
const_iterator previous = it++;
|
||||
|
||||
for(const_iterator end = points_.end(); it != end; ++it, ++previous) {
|
||||
result += distance(*previous, *it);
|
||||
}
|
||||
length_ = result;
|
||||
}
|
||||
return length_;
|
||||
}
|
||||
|
||||
/// returns the signed geodesic distance between `p` and `q`.
|
||||
FT signed_geodesic_distance(const Point_3& p, const Point_3& q) const
|
||||
{
|
||||
// Locate p & q on polyline
|
||||
const_iterator pit = locate(p);
|
||||
const_iterator qit = locate(q,false);
|
||||
|
||||
return signed_geodesic_distance(p, q, pit, qit);
|
||||
}
|
||||
|
||||
FT signed_geodesic_distance(const Point_3& p, const Point_3& q,
|
||||
const_iterator pit, const_iterator qit) const
|
||||
{
|
||||
CGAL_assertion(pit == locate(p));
|
||||
CGAL_assertion(qit == locate(q, false));
|
||||
|
||||
// If p and q are in the same segment of the polyline
|
||||
if ( pit == qit )
|
||||
{
|
||||
FT result = distance(p,q);
|
||||
|
||||
// Find the closest point to *pit
|
||||
if ( compare_distance(*pit,p,q) != CGAL::LARGER )
|
||||
{ return result; }
|
||||
else
|
||||
{ return -result; }
|
||||
}
|
||||
if(is_loop())
|
||||
{
|
||||
FT positive_distance, negative_distance;
|
||||
if(pit <= qit)
|
||||
{
|
||||
positive_distance = curve_segment_length(p, q, CGAL::POSITIVE, pit, qit);
|
||||
negative_distance = length() - positive_distance;
|
||||
}
|
||||
else
|
||||
{
|
||||
negative_distance = curve_segment_length(q, p, CGAL::POSITIVE, qit, pit);
|
||||
positive_distance = length() - negative_distance;
|
||||
}
|
||||
return (positive_distance < negative_distance) ? positive_distance : (-negative_distance);
|
||||
}
|
||||
else
|
||||
{
|
||||
return (pit <= qit)
|
||||
? curve_segment_length(p, q, CGAL::POSITIVE, pit, qit)
|
||||
: ( - curve_segment_length(p, q, CGAL::NEGATIVE, pit, qit) );
|
||||
}
|
||||
}
|
||||
|
||||
const_iterator previous_segment_source(const_iterator it) const
|
||||
{
|
||||
CGAL_assertion(it != points_.end());
|
||||
if(it == first_segment_source())
|
||||
{
|
||||
CGAL_assertion(is_loop());
|
||||
it = last_segment_source();
|
||||
}
|
||||
else
|
||||
{
|
||||
--it;
|
||||
}
|
||||
return it;
|
||||
}
|
||||
|
||||
const_iterator next_segment_source(const_iterator it) const
|
||||
{
|
||||
CGAL_assertion(it != points_.end());
|
||||
if(it == last_segment_source())
|
||||
{
|
||||
if(is_loop())
|
||||
return first_segment_source();
|
||||
else
|
||||
return points_.end();
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
return it;
|
||||
}
|
||||
}
|
||||
|
||||
/// returns a point at geodesic distance `distance` from p along the
|
||||
/// polyline. The polyline is oriented from starting point to end point.
|
||||
/// The distance could be negative.
|
||||
Point_3 point_at(const Point_3& start_pt, FT distance) const
|
||||
{
|
||||
return point_at(start_pt, distance, locate(start_pt)).first;
|
||||
}
|
||||
|
||||
/// returns a point at geodesic distance `distance` from `start_pt` along the
|
||||
/// polyline. The polyline is oriented from starting point to end point.
|
||||
/// The distance could be negative.
|
||||
Point_and_location point_at(const Point_3& start_pt,
|
||||
FT distance,
|
||||
const_iterator start_it) const
|
||||
{
|
||||
CGAL_assertion(start_it == locate(start_pt));
|
||||
|
||||
const Point_3& start_it_pt = *start_it;
|
||||
const_iterator start_it_locate_pt
|
||||
= (start_it == points_.begin()) ? start_it : std::prev(start_it);
|
||||
|
||||
distance += curve_segment_length(start_it_pt, start_pt, CGAL::POSITIVE,
|
||||
start_it_locate_pt, start_it);
|
||||
|
||||
// If polyline is a loop, ensure that distance is given from start_it
|
||||
if(is_loop())
|
||||
{
|
||||
if(distance < FT(0)) { distance += length(); }
|
||||
else if(distance > length()) { distance -= length(); }
|
||||
}
|
||||
else if(distance < FT(0)) // If polyline is not a loop and distance is < 0, go backward
|
||||
{
|
||||
Point_3 new_start = start_pt;
|
||||
while(distance < FT(0))
|
||||
{
|
||||
start_it = previous_segment_source(start_it);
|
||||
distance += this->distance(new_start, *start_it);
|
||||
new_start = *start_it;
|
||||
}
|
||||
}
|
||||
|
||||
CGAL_assertion(distance >= FT(0));
|
||||
CGAL_assertion(distance <= length());
|
||||
|
||||
// Initialize iterators
|
||||
const_iterator pit = start_it; // start at start_it, and walk forward
|
||||
const_iterator previous = pit++;
|
||||
|
||||
// Iterate to find which segment contains the point we want to construct
|
||||
FT segment_length = this->distance(*previous, *pit);
|
||||
while(distance > segment_length)
|
||||
{
|
||||
distance -= segment_length;
|
||||
|
||||
// Increment iterators and update length
|
||||
previous = next_segment_source(previous);
|
||||
pit = next_segment_source(pit);
|
||||
|
||||
if(pit == points_.end())
|
||||
{
|
||||
CGAL_assertion(distance < this->distance(*previous, end_point()));
|
||||
break; // return {*previous, previous}
|
||||
}
|
||||
else
|
||||
segment_length = this->distance(*previous, *pit);
|
||||
}
|
||||
|
||||
// return point at distance from current segment source
|
||||
using Vector_3 = typename Kernel::Vector_3;
|
||||
auto vector = Kernel().construct_vector_3_object();
|
||||
Vector_3 v = (pit != points_.end()) ? vector(*previous, *pit)
|
||||
: vector(*previous, end_point());
|
||||
|
||||
return {(*previous) + (distance / CGAL::sqrt(v.squared_length())) * v,
|
||||
previous};
|
||||
}
|
||||
|
||||
const_iterator locate_corner(const Point_3& p) const
|
||||
{
|
||||
const_iterator res = points_.end();
|
||||
if(p == start_point())
|
||||
res = points_.begin();
|
||||
else if(p == end_point())
|
||||
res = last_segment_source();
|
||||
|
||||
CGAL_assertion(res == locate(p));
|
||||
CGAL_assertion(res != points_.end());
|
||||
return res;
|
||||
}
|
||||
|
||||
const_iterator locate_point(const Point_3& p) const
|
||||
{
|
||||
return locate(p);
|
||||
}
|
||||
|
||||
bool are_ordered_along(const Point_3& p, const Point_3& q,
|
||||
const_iterator pit, const_iterator qit) const
|
||||
{
|
||||
CGAL_precondition(!is_loop());
|
||||
|
||||
// Locate p & q on polyline
|
||||
CGAL_assertion(pit == locate(p));
|
||||
CGAL_assertion(qit == locate(q, true));
|
||||
|
||||
// Points are not located on the same segment
|
||||
if ( pit != qit ) { return (pit <= qit); }
|
||||
|
||||
// pit == qit, then we have to sort p&q along (pit,pit+1)
|
||||
return ( compare_distance(*pit,p,q) != CGAL::LARGER );
|
||||
}
|
||||
|
||||
bool are_ordered_along(const Point_3& p, const Point_3& q) const
|
||||
{
|
||||
return are_ordered_along(p, q, locate(p), locate(q, true));
|
||||
}
|
||||
|
||||
private:
|
||||
const_iterator first_segment_source() const
|
||||
{
|
||||
CGAL_precondition(is_valid());
|
||||
return points_.begin();
|
||||
}
|
||||
|
||||
const_iterator last_segment_source() const
|
||||
{
|
||||
CGAL_precondition(is_valid());
|
||||
return (points_.end() - 2);
|
||||
}
|
||||
|
||||
/// returns an iterator on the starting point of the segment of the
|
||||
/// polyline which contains p
|
||||
/// if end_point_first is true, then --end is returned instead of begin
|
||||
/// if p is the starting point of a loop.
|
||||
const_iterator locate(const Point_3& p, bool end_point_first=false) const
|
||||
{
|
||||
CGAL_precondition(is_valid());
|
||||
|
||||
// First look if p is one of the points of the polyline
|
||||
const_iterator result = std::find(points_.begin(), points_.end(), p);
|
||||
if ( result != points_.end() )
|
||||
{
|
||||
if ( result != points_.begin() )
|
||||
{ return --result; }
|
||||
else
|
||||
{
|
||||
// Treat loops
|
||||
if ( end_point_first && p == end_point() )
|
||||
{ return last_segment_source(); }
|
||||
else
|
||||
{ return result; }
|
||||
}
|
||||
}
|
||||
|
||||
CGAL_assertion(result == points_.end());
|
||||
|
||||
// Get result by projecting p on the polyline
|
||||
const_iterator it = points_.begin();
|
||||
const_iterator previous = it;
|
||||
Segment_3 nearest_segment;
|
||||
const_iterator nearest_vertex = it;
|
||||
result = nearest_vertex;
|
||||
bool nearest_is_a_segment = false;
|
||||
|
||||
while ( ++it != points_.end() )
|
||||
{
|
||||
Segment_3 seg (*previous, *it);
|
||||
|
||||
if(nearest_is_a_segment)
|
||||
{
|
||||
if(compare_distance(p, *it, nearest_segment) == CGAL::SMALLER)
|
||||
{
|
||||
nearest_vertex = it;
|
||||
nearest_is_a_segment = false;
|
||||
result = it;
|
||||
if (possibly(angle(*previous, *it, p) == CGAL::ACUTE) &&
|
||||
compare_distance(p, seg, *nearest_vertex) == CGAL::SMALLER)
|
||||
{
|
||||
nearest_segment = seg;
|
||||
nearest_is_a_segment = true;
|
||||
result = previous;
|
||||
}
|
||||
}
|
||||
else if(compare_distance(p, seg, nearest_segment) == CGAL::SMALLER)
|
||||
{
|
||||
nearest_segment = seg;
|
||||
result = previous;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(compare_distance(p, *it, *nearest_vertex) == CGAL::SMALLER)
|
||||
{
|
||||
nearest_vertex = it;
|
||||
result = it;
|
||||
}
|
||||
if ((nearest_vertex != it ||
|
||||
possibly(angle(*previous, *it, p) == CGAL::ACUTE)) &&
|
||||
compare_distance(p, seg, *nearest_vertex) == CGAL::SMALLER)
|
||||
{
|
||||
nearest_segment = seg;
|
||||
nearest_is_a_segment = true;
|
||||
result = previous;
|
||||
}
|
||||
}
|
||||
previous = it;
|
||||
} // end the while loop on the vertices of the polyline
|
||||
|
||||
if(result == points_.begin()) {
|
||||
return (end_point_first && !nearest_is_a_segment) ? last_segment_source() : points_.begin();
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FT distance(const Point_3& p, const Point_3& q) const
|
||||
{
|
||||
typename Kernel::Compute_squared_distance_3 sq_distance =
|
||||
Kernel().compute_squared_distance_3_object();
|
||||
return CGAL::sqrt(sq_distance(p, q));
|
||||
}
|
||||
|
||||
Angle angle(const Point_3& p,
|
||||
const Point_3& angle_vertex_point,
|
||||
const Point_3& q) const
|
||||
{
|
||||
typename Kernel::Angle_3 compute_angle = Kernel().angle_3_object();
|
||||
return compute_angle(p,angle_vertex_point,q);
|
||||
}
|
||||
|
||||
template <typename T1, typename T2>
|
||||
CGAL::Sign compare_distance(const Point_3& p,
|
||||
const T1& obj1,
|
||||
const T2& obj2) const
|
||||
{
|
||||
typename Kernel::Compare_distance_3 compare_distance =
|
||||
Kernel().compare_distance_3_object();
|
||||
return compare_distance(p,obj1,obj2);
|
||||
}
|
||||
|
||||
public:
|
||||
Data points_;
|
||||
|
||||
private:
|
||||
mutable FT length_ = -1.;
|
||||
|
||||
}; // end class Polyline
|
||||
|
||||
|
||||
} // end namespace internal
|
||||
} // end namespace Mesh_3
|
||||
} // end namespace CGAL
|
||||
|
||||
#endif // CGAL_MESH_3_INTERNAL_POLYLINE_H
|
||||
|
|
@ -30,12 +30,14 @@
|
|||
#include <CGAL/Real_timer.h>
|
||||
#include <CGAL/property_map.h>
|
||||
#include <CGAL/SMDS_3/internal/indices_management.h>
|
||||
#include <CGAL/Mesh_3/internal/Polyline.h>
|
||||
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <variant>
|
||||
#include <memory>
|
||||
|
|
@ -46,411 +48,6 @@ namespace CGAL {
|
|||
namespace Mesh_3 {
|
||||
namespace internal {
|
||||
|
||||
template <typename Kernel>
|
||||
class Polyline
|
||||
{
|
||||
typedef typename Kernel::Point_3 Point_3;
|
||||
typedef typename Kernel::Segment_3 Segment_3;
|
||||
typedef typename Kernel::FT FT;
|
||||
|
||||
typedef std::vector<Point_3> Data;
|
||||
|
||||
public:
|
||||
typedef typename Data::const_iterator const_iterator;
|
||||
|
||||
Polyline() {}
|
||||
~Polyline() {}
|
||||
|
||||
/// adds a point at the end of the polyline
|
||||
void add_point(const Point_3& p)
|
||||
{
|
||||
if( points_.empty() || p != end_point() ) {
|
||||
points_.push_back(p);
|
||||
}
|
||||
}
|
||||
|
||||
/// returns the starting point of the polyline
|
||||
const Point_3& start_point() const
|
||||
{
|
||||
CGAL_assertion( ! points_.empty() );
|
||||
return points_.front();
|
||||
}
|
||||
|
||||
/// returns the ending point of the polyline
|
||||
const Point_3& end_point() const
|
||||
{
|
||||
CGAL_assertion( ! points_.empty() );
|
||||
return points_.back();
|
||||
}
|
||||
|
||||
/// returns `true` if the polyline is not degenerate
|
||||
bool is_valid() const
|
||||
{
|
||||
return points_.size() > 1;
|
||||
}
|
||||
|
||||
/// returns `true` if polyline is a loop
|
||||
bool is_loop() const
|
||||
{
|
||||
return start_point() == end_point();
|
||||
}
|
||||
|
||||
const_iterator next(const_iterator it, Orientation orientation) const {
|
||||
if(orientation == POSITIVE) {
|
||||
CGAL_assertion(it != (points_.end() - 1));
|
||||
if(it == (points_.end() - 2)) {
|
||||
CGAL_assertion(is_loop());
|
||||
it = points_.begin();
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
} else {
|
||||
CGAL_assertion(orientation == NEGATIVE);
|
||||
CGAL_assertion(it != points_.begin());
|
||||
if(it == (points_.begin() + 1)) {
|
||||
CGAL_assertion(is_loop());
|
||||
it = points_.end() - 1;
|
||||
} else {
|
||||
--it;
|
||||
}
|
||||
}
|
||||
return it;
|
||||
}
|
||||
|
||||
bool is_curve_segment_covered(CGAL::Orientation orientation,
|
||||
const Point_3& c1, const Point_3& c2,
|
||||
const FT sq_r1, const FT sq_r2) const
|
||||
{
|
||||
CGAL_assertion(orientation != CGAL::ZERO);
|
||||
typename Kernel::Has_on_bounded_side_3 cover_pred =
|
||||
Kernel().has_on_bounded_side_3_object();
|
||||
|
||||
typedef typename Kernel::Sphere_3 Sphere_3;
|
||||
const Sphere_3 s1(c1, sq_r1);
|
||||
const Sphere_3 s2(c2, sq_r2);
|
||||
|
||||
const_iterator c1_it = locate(c1);
|
||||
const_iterator c2_it = locate(c2);
|
||||
|
||||
if(orientation == CGAL::NEGATIVE) {
|
||||
++c1_it;
|
||||
++c2_it;
|
||||
CGAL_assertion(c1_it != points_.end());
|
||||
CGAL_assertion(c2_it != points_.end());
|
||||
}
|
||||
|
||||
if(c1_it == c2_it) return cover_pred(s1, s2, c1, c2);
|
||||
const_iterator next_it = this->next(c1_it, orientation);
|
||||
|
||||
if(!cover_pred(s1, s2, c1, *next_it)) return false;
|
||||
|
||||
for(const_iterator it = next_it; it != c2_it; /* in body */) {
|
||||
next_it = this->next(it, orientation);
|
||||
if(!cover_pred(s1, s2, *it, *next_it)) return false;
|
||||
it = next_it;
|
||||
} // end loop ]c1_it, c2_it[
|
||||
|
||||
return cover_pred(s1, s2, *c2_it, c2);
|
||||
}
|
||||
|
||||
FT curve_segment_length(const Point_3& p, const Point_3 q,
|
||||
CGAL::Orientation orientation) const
|
||||
{
|
||||
CGAL_assertion(orientation != CGAL::ZERO);
|
||||
const_iterator p_it = locate(p);
|
||||
const_iterator q_it = locate(q);
|
||||
return curve_segment_length(p, q, orientation, p_it, q_it);
|
||||
}
|
||||
|
||||
FT curve_segment_length(const Point_3& p, const Point_3 q,
|
||||
CGAL::Orientation orientation,
|
||||
const_iterator p_it,
|
||||
const_iterator q_it) const
|
||||
{
|
||||
CGAL_assertion(orientation != CGAL::ZERO);
|
||||
|
||||
if(p_it == q_it) {
|
||||
const CGAL::Comparison_result cmp = compare_distance(*p_it,p,q);
|
||||
if( (cmp != LARGER && orientation == POSITIVE) ||
|
||||
(cmp != SMALLER && orientation == NEGATIVE) )
|
||||
{
|
||||
// If the orientation of `p` and `q` on the segment is compatible
|
||||
// with `orientation`, then return the distance between the two
|
||||
// points.
|
||||
return distance(p, q);
|
||||
}
|
||||
}
|
||||
|
||||
if(orientation == CGAL::NEGATIVE) {
|
||||
++p_it;
|
||||
++q_it;
|
||||
CGAL_assertion(p_it != points_.end());
|
||||
CGAL_assertion(q_it != points_.end());
|
||||
}
|
||||
|
||||
const_iterator next_it = this->next(p_it, orientation);
|
||||
FT result = distance(p, *next_it);
|
||||
for(const_iterator it = next_it; it != q_it; /* in body */) {
|
||||
next_it = this->next(it, orientation);
|
||||
result += distance(*it, *next_it);
|
||||
it = next_it;
|
||||
} // end loop ]p_it, q_it[
|
||||
result += distance(*q_it, q);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/// returns the angle at the first point.
|
||||
/// \pre The polyline must be a loop.
|
||||
Angle angle_at_first_point() const {
|
||||
CGAL_precondition(is_loop());
|
||||
const Point_3& first = points_.front();
|
||||
const Point_3& next_p = points_[1];
|
||||
const Point_3& prev = points_[points_.size() - 2];
|
||||
return angle(prev, first, next_p);
|
||||
}
|
||||
|
||||
/// returns the length of the polyline
|
||||
FT length() const
|
||||
{
|
||||
//TODO: cache result
|
||||
FT result (0);
|
||||
const_iterator it = points_.begin();
|
||||
const_iterator previous = it++;
|
||||
|
||||
for ( const_iterator end = points_.end() ; it != end ; ++it, ++previous )
|
||||
{
|
||||
result += distance(*previous,*it);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// returns the signed geodesic distance between `p` and `q`.
|
||||
FT signed_geodesic_distance(const Point_3& p, const Point_3& q) const
|
||||
{
|
||||
// Locate p & q on polyline
|
||||
const_iterator pit = locate(p);
|
||||
const_iterator qit = locate(q,false);
|
||||
|
||||
// If p and q are in the same segment of the polyline
|
||||
if ( pit == qit )
|
||||
{
|
||||
FT result = distance(p,q);
|
||||
|
||||
// Find the closest point to *pit
|
||||
if ( compare_distance(*pit,p,q) != CGAL::LARGER )
|
||||
{ return result; }
|
||||
else
|
||||
{ return -result; }
|
||||
}
|
||||
if(is_loop()) {
|
||||
const FT positive_distance = curve_segment_length(p, q, CGAL::POSITIVE, pit, qit);
|
||||
const FT negative_distance = curve_segment_length(p, q, CGAL::NEGATIVE, pit, qit);
|
||||
return (positive_distance < negative_distance)
|
||||
? positive_distance
|
||||
: (- negative_distance);
|
||||
} else {
|
||||
return (pit <= qit)
|
||||
? curve_segment_length(p, q, CGAL::POSITIVE, pit, qit)
|
||||
: ( - curve_segment_length(p, q, CGAL::NEGATIVE, pit, qit) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// returns a point at geodesic distance `distance` from p along the
|
||||
/// polyline. The polyline is oriented from starting point to end point.
|
||||
/// The distance could be negative.
|
||||
Point_3 point_at(const Point_3& p, FT distance) const
|
||||
{
|
||||
// use first point of the polyline instead of p
|
||||
distance += curve_segment_length(start_point(),p,CGAL::POSITIVE);
|
||||
|
||||
// If polyline is a loop, ensure that distance is given from start_point()
|
||||
if ( is_loop() )
|
||||
{
|
||||
if ( distance < FT(0) ) { distance += length(); }
|
||||
else if ( distance > length() ) { distance -= length(); }
|
||||
}
|
||||
|
||||
CGAL_assertion( distance >= FT(0) );
|
||||
CGAL_assertion( distance <= length() );
|
||||
|
||||
// Initialize iterators
|
||||
const_iterator pit = points_.begin();
|
||||
const_iterator previous = pit++;
|
||||
|
||||
// Iterate to find which segment contains the point we want to construct
|
||||
FT segment_length = this->distance(*previous,*pit);
|
||||
while ( distance > segment_length )
|
||||
{
|
||||
distance -= segment_length;
|
||||
|
||||
// Increment iterators and update length
|
||||
++previous;
|
||||
++pit;
|
||||
|
||||
if (pit == points_.end())
|
||||
return *previous;
|
||||
|
||||
segment_length = this->distance(*previous,*pit);
|
||||
}
|
||||
|
||||
// return point at distance from current segment source
|
||||
typedef typename Kernel::Vector_3 Vector_3;
|
||||
Vector_3 v (*previous, *pit);
|
||||
|
||||
return (*previous) + (distance / CGAL::sqrt(v.squared_length())) * v;
|
||||
}
|
||||
|
||||
bool are_ordered_along(const Point_3& p, const Point_3& q) const
|
||||
{
|
||||
CGAL_precondition(!is_loop());
|
||||
|
||||
// Locate p & q on polyline
|
||||
const_iterator pit = locate(p);
|
||||
const_iterator qit = locate(q,true);
|
||||
|
||||
// Points are not located on the same segment
|
||||
if ( pit != qit ) { return (pit <= qit); }
|
||||
|
||||
// pit == qit, then we have to sort p&q along (pit,pit+1)
|
||||
return ( compare_distance(*pit,p,q) != CGAL::LARGER );
|
||||
}
|
||||
|
||||
private:
|
||||
const_iterator first_segment_source() const
|
||||
{
|
||||
CGAL_precondition(is_valid());
|
||||
return points_.begin();
|
||||
}
|
||||
|
||||
const_iterator last_segment_source() const
|
||||
{
|
||||
CGAL_precondition(is_valid());
|
||||
return (points_.end() - 2);
|
||||
}
|
||||
|
||||
/// returns an iterator on the starting point of the segment of the
|
||||
/// polyline which contains p
|
||||
/// if end_point_first is true, then --end is returned instead of begin
|
||||
/// if p is the starting point of a loop.
|
||||
const_iterator locate(const Point_3& p, bool end_point_first=false) const
|
||||
{
|
||||
CGAL_precondition(is_valid());
|
||||
|
||||
// First look if p is one of the points of the polyline
|
||||
const_iterator result = std::find(points_.begin(), points_.end(), p);
|
||||
if ( result != points_.end() )
|
||||
{
|
||||
if ( result != points_.begin() )
|
||||
{ return --result; }
|
||||
else
|
||||
{
|
||||
// Treat loops
|
||||
if ( end_point_first && p == end_point() )
|
||||
{ return last_segment_source(); }
|
||||
else
|
||||
{ return result; }
|
||||
}
|
||||
}
|
||||
|
||||
CGAL_assertion(result == points_.end());
|
||||
|
||||
// Get result by projecting p on the polyline
|
||||
const_iterator it = points_.begin();
|
||||
const_iterator previous = it;
|
||||
Segment_3 nearest_segment;
|
||||
const_iterator nearest_vertex = it;
|
||||
result = nearest_vertex;
|
||||
bool nearest_is_a_segment = false;
|
||||
|
||||
while ( ++it != points_.end() )
|
||||
{
|
||||
Segment_3 seg (*previous, *it);
|
||||
|
||||
if(nearest_is_a_segment)
|
||||
{
|
||||
if(compare_distance(p, *it, nearest_segment) == CGAL::SMALLER)
|
||||
{
|
||||
nearest_vertex = it;
|
||||
nearest_is_a_segment = false;
|
||||
result = it;
|
||||
if (possibly(angle(*previous, *it, p) == CGAL::ACUTE) &&
|
||||
compare_distance(p, seg, *nearest_vertex) == CGAL::SMALLER)
|
||||
{
|
||||
nearest_segment = seg;
|
||||
nearest_is_a_segment = true;
|
||||
result = previous;
|
||||
}
|
||||
}
|
||||
else if(compare_distance(p, seg, nearest_segment) == CGAL::SMALLER)
|
||||
{
|
||||
nearest_segment = seg;
|
||||
result = previous;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(compare_distance(p, *it, *nearest_vertex) == CGAL::SMALLER)
|
||||
{
|
||||
nearest_vertex = it;
|
||||
result = it;
|
||||
}
|
||||
if ((nearest_vertex != it ||
|
||||
possibly(angle(*previous, *it, p) == CGAL::ACUTE)) &&
|
||||
compare_distance(p, seg, *nearest_vertex) == CGAL::SMALLER)
|
||||
{
|
||||
nearest_segment = seg;
|
||||
nearest_is_a_segment = true;
|
||||
result = previous;
|
||||
}
|
||||
}
|
||||
previous = it;
|
||||
} // end the while loop on the vertices of the polyline
|
||||
|
||||
|
||||
if(result == points_.begin()) {
|
||||
return (end_point_first && !nearest_is_a_segment) ? last_segment_source() : points_.begin();
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// FT squared_distance(const Point_3& p, const Point_3& q) const
|
||||
// {
|
||||
// typename Kernel::Compute_squared_distance_3 sq_distance =
|
||||
// Kernel().compute_squared_distance_3_object();
|
||||
// return sq_distance(p,q);
|
||||
// }
|
||||
|
||||
FT distance(const Point_3& p, const Point_3& q) const
|
||||
{
|
||||
return CGAL::sqrt(squared_distance(p, q));
|
||||
}
|
||||
|
||||
Angle angle(const Point_3& p,
|
||||
const Point_3& angle_vertex_point,
|
||||
const Point_3& q) const
|
||||
{
|
||||
typename Kernel::Angle_3 compute_angle = Kernel().angle_3_object();
|
||||
return compute_angle(p,angle_vertex_point,q);
|
||||
}
|
||||
|
||||
template <typename T1, typename T2>
|
||||
CGAL::Sign compare_distance(const Point_3& p,
|
||||
const T1& obj1,
|
||||
const T2& obj2) const
|
||||
{
|
||||
typename Kernel::Compare_distance_3 compare_distance =
|
||||
Kernel().compare_distance_3_object();
|
||||
return compare_distance(p,obj1,obj2);
|
||||
}
|
||||
|
||||
public:
|
||||
Data points_;
|
||||
}; // end class Polyline
|
||||
|
||||
|
||||
template <typename GT, typename MapIterator>
|
||||
struct Mesh_domain_segment_of_curve_primitive{
|
||||
typedef typename std::iterator_traits<MapIterator>::value_type Map_value_type;
|
||||
|
|
@ -567,6 +164,10 @@ public:
|
|||
typedef GT R;
|
||||
typedef typename MD::Point_3 Point_3;
|
||||
|
||||
using Polyline = Mesh_3::internal::Polyline<GT>;
|
||||
using Polyline_const_iterator = typename Polyline::const_iterator;
|
||||
using Point_and_location = typename Polyline::Point_and_location;
|
||||
|
||||
/// \name Creation
|
||||
/// @{
|
||||
|
||||
|
|
@ -713,24 +314,55 @@ public:
|
|||
const Curve_index& curve_index,
|
||||
CGAL::Orientation orientation) const;
|
||||
|
||||
FT curve_segment_length(const Point_3& p,
|
||||
const Point_3 q,
|
||||
const Polyline_const_iterator p_it,
|
||||
const Polyline_const_iterator q_it,
|
||||
const Curve_index& curve_index,
|
||||
CGAL::Orientation orientation) const;
|
||||
|
||||
/// implements `MeshDomainWithFeatures_3::curve_length()`.
|
||||
FT curve_length(const Curve_index& curve_index) const;
|
||||
|
||||
/// implements `MeshDomainWithFeatures_3::construct_point_on_curve()`.
|
||||
Point_and_location
|
||||
construct_point_on_curve(const Point_3& starting_point,
|
||||
const Curve_index& curve_index,
|
||||
FT distance,
|
||||
Polyline_const_iterator starting_point_it) const;
|
||||
|
||||
/// implements `MeshDomainWithFeatures_3::construct_point_on_curve()`.
|
||||
Point_3
|
||||
construct_point_on_curve(const Point_3& starting_point,
|
||||
const Curve_index& curve_index,
|
||||
FT distance) const;
|
||||
|
||||
/// implements `MeshDomainWithFeatures_3::distance_sign_along_loop()`.
|
||||
CGAL::Sign distance_sign_along_loop(const Point_3& p,
|
||||
const Point_3& q,
|
||||
const Point_3& r,
|
||||
const Curve_index& index) const;
|
||||
|
||||
CGAL::Sign distance_sign_along_loop(const Point_3& p,
|
||||
const Point_3& q,
|
||||
const Point_3& r,
|
||||
const Curve_index& index,
|
||||
Polyline_const_iterator pit,
|
||||
Polyline_const_iterator qit,
|
||||
Polyline_const_iterator rit) const;
|
||||
|
||||
|
||||
/// implements `MeshDomainWithFeatures_3::distance_sign()`.
|
||||
CGAL::Sign distance_sign(const Point_3& p, const Point_3& q,
|
||||
CGAL::Sign distance_sign(const Point_3& p,
|
||||
const Point_3& q,
|
||||
const Curve_index& index) const;
|
||||
|
||||
CGAL::Sign distance_sign(const Point_3& p,
|
||||
const Point_3& q,
|
||||
const Curve_index& index,
|
||||
Polyline_const_iterator pit,
|
||||
Polyline_const_iterator qit) const;
|
||||
|
||||
/// implements `MeshDomainWithFeatures_3::is_loop()`.
|
||||
bool is_loop(const Curve_index& index) const;
|
||||
|
||||
|
|
@ -740,6 +372,19 @@ public:
|
|||
const Point_3& c1, const Point_3& c2,
|
||||
const FT sq_r1, const FT sq_r2) const;
|
||||
|
||||
bool is_curve_segment_covered(const Curve_index& index,
|
||||
CGAL::Orientation orientation,
|
||||
const Point_3& c1, const Point_3& c2,
|
||||
const FT sq_r1, const FT sq_r2,
|
||||
const Polyline_const_iterator c1_it,
|
||||
const Polyline_const_iterator c2_it) const;
|
||||
|
||||
/// locates the corner point `p` on the curve identified by `curve_index`
|
||||
Polyline_const_iterator locate_corner(const Curve_index& curve_index,
|
||||
const Point_3& p) const;
|
||||
|
||||
Polyline_const_iterator locate_point(const Curve_index& curve_index, const Point_3& p) const;
|
||||
|
||||
/**
|
||||
* Returns the index to be stored in a vertex lying on the surface identified
|
||||
* by `index`.
|
||||
|
|
@ -795,6 +440,11 @@ public:
|
|||
FT signed_geodesic_distance(const Point_3& p, const Point_3& q,
|
||||
const Curve_index& curve_index) const;
|
||||
|
||||
FT signed_geodesic_distance(const Point_3& p, const Point_3& q,
|
||||
Polyline_const_iterator pit,
|
||||
Polyline_const_iterator qit,
|
||||
const Curve_index& curve_index) const;
|
||||
|
||||
template <typename Surf_p_index, typename IncidenceMap>
|
||||
void reindex_patches(const std::vector<Surf_p_index>& map, IncidenceMap& incidence_map);
|
||||
|
||||
|
|
@ -837,8 +487,6 @@ private:
|
|||
|
||||
private:
|
||||
typedef std::map<Point_3,Corner_index> Corners;
|
||||
|
||||
typedef Mesh_3::internal::Polyline<GT> Polyline;
|
||||
typedef std::map<Curve_index, Polyline> Edges;
|
||||
typedef std::map<Curve_index, Surface_patch_index_set > Edges_incidences;
|
||||
typedef std::map<Corner_index, std::set<Curve_index> > Corners_tmp_incidences;
|
||||
|
|
@ -851,6 +499,8 @@ private:
|
|||
typedef CGAL::AABB_traits_3<GT,
|
||||
Curves_primitives> AABB_curves_traits;
|
||||
|
||||
// typedef typename Polyline::const_iterator Polyline_const_iterator;
|
||||
|
||||
Corners corners_;
|
||||
Corners_tmp_incidences corners_tmp_incidences_;
|
||||
Corner_index current_corner_index_;
|
||||
|
|
@ -867,6 +517,7 @@ public:
|
|||
private:
|
||||
mutable std::shared_ptr<Curves_AABB_tree> curves_aabb_tree_ptr_;
|
||||
mutable bool curves_aabb_tree_is_built;
|
||||
mutable std::unordered_map<Point_3, Polyline_const_iterator> vertex_to_polyline_iterator_;
|
||||
|
||||
public:
|
||||
const Corners_incidences& corners_incidences_map() const
|
||||
|
|
@ -914,6 +565,45 @@ public:
|
|||
#endif
|
||||
} // build_curves_aabb_tree()
|
||||
|
||||
Polyline_const_iterator locate_in_polyline(const Point_3& p,
|
||||
const int dim,
|
||||
const Curve_index& index) const
|
||||
{
|
||||
CGAL_assertion(dim < 2);
|
||||
|
||||
Polyline_const_iterator it;
|
||||
if(dim == 0) // corner
|
||||
it = locate_corner(index, p);
|
||||
else
|
||||
it = vertex_to_polyline_iterator_.at(p);
|
||||
|
||||
return it;
|
||||
}
|
||||
|
||||
void set_polyline_iterator(const Point_3& p, Polyline_const_iterator it) const
|
||||
{
|
||||
vertex_to_polyline_iterator_[p] = it;
|
||||
}
|
||||
|
||||
void dump_curve(const Curve_index& index, const std::string& prefix) const
|
||||
{
|
||||
std::string filename(prefix);
|
||||
filename += std::to_string(index) + ".polylines.txt";
|
||||
|
||||
std::ofstream os(filename);
|
||||
typename Edges::const_iterator eit = edges_.find(index);
|
||||
if(eit == edges_.end()) {
|
||||
os << "No curve with index " << index << std::endl;
|
||||
return;
|
||||
}
|
||||
const Polyline& polyline = eit->second;
|
||||
os << polyline.points_.size();
|
||||
for(const auto& p : polyline.points_)
|
||||
os << " " << p;
|
||||
os << std::endl;
|
||||
os.close();
|
||||
}
|
||||
|
||||
/// @endcond
|
||||
|
||||
}; // class Mesh_domain_with_polyline_features_3
|
||||
|
|
@ -962,6 +652,7 @@ get_curves(OutputIterator out) const
|
|||
}
|
||||
|
||||
*out++ = {eit->first,
|
||||
eit->second.points_.begin(),
|
||||
std::make_pair(p,p_index),
|
||||
std::make_pair(q,q_index)};
|
||||
}
|
||||
|
|
@ -1000,6 +691,22 @@ curve_segment_length(const Point_3& p, const Point_3 q,
|
|||
return eit->second.curve_segment_length(p, q, orientation);
|
||||
}
|
||||
|
||||
template <class MD_>
|
||||
typename Mesh_domain_with_polyline_features_3<MD_>::FT
|
||||
Mesh_domain_with_polyline_features_3<MD_>::
|
||||
curve_segment_length(const Point_3& p,
|
||||
const Point_3 q,
|
||||
const Polyline_const_iterator p_it,
|
||||
const Polyline_const_iterator q_it,
|
||||
const Curve_index& curve_index,
|
||||
CGAL::Orientation orientation) const
|
||||
{
|
||||
// Get corresponding polyline
|
||||
typename Edges::const_iterator eit = edges_.find(curve_index);
|
||||
CGAL_assertion(eit != edges_.end());
|
||||
|
||||
return eit->second.curve_segment_length(p, q, orientation, p_it, q_it);
|
||||
}
|
||||
|
||||
template <class MD_>
|
||||
typename Mesh_domain_with_polyline_features_3<MD_>::FT
|
||||
|
|
@ -1014,6 +721,22 @@ curve_length(const Curve_index& curve_index) const
|
|||
}
|
||||
|
||||
|
||||
template <class MD_>
|
||||
typename Mesh_domain_with_polyline_features_3<MD_>::Point_and_location
|
||||
Mesh_domain_with_polyline_features_3<MD_>::
|
||||
construct_point_on_curve(const Point_3& starting_point,
|
||||
const Curve_index& curve_index,
|
||||
FT distance,
|
||||
Polyline_const_iterator starting_point_it) const
|
||||
{
|
||||
// Get corresponding polyline
|
||||
typename Edges::const_iterator eit = edges_.find(curve_index);
|
||||
CGAL_assertion(eit != edges_.end());
|
||||
|
||||
// Return point at geodesic_distance distance from starting_point
|
||||
return eit->second.point_at(starting_point, distance, starting_point_it);
|
||||
}
|
||||
|
||||
template <class MD_>
|
||||
typename Mesh_domain_with_polyline_features_3<MD_>::Point_3
|
||||
Mesh_domain_with_polyline_features_3<MD_>::
|
||||
|
|
@ -1026,7 +749,7 @@ construct_point_on_curve(const Point_3& starting_point,
|
|||
CGAL_assertion(eit != edges_.end());
|
||||
|
||||
// Return point at geodesic_distance distance from starting_point
|
||||
return eit->second.point_at(starting_point,distance);
|
||||
return eit->second.point_at(starting_point, distance);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1183,7 +906,8 @@ add_features_and_incidences(InputIterator first, InputIterator end,
|
|||
template <class MD_>
|
||||
typename Mesh_domain_with_polyline_features_3<MD_>::FT
|
||||
Mesh_domain_with_polyline_features_3<MD_>::
|
||||
signed_geodesic_distance(const Point_3& p, const Point_3& q,
|
||||
signed_geodesic_distance(const Point_3& p,
|
||||
const Point_3& q,
|
||||
const Curve_index& curve_index) const
|
||||
{
|
||||
// Get corresponding polyline
|
||||
|
|
@ -1191,7 +915,23 @@ signed_geodesic_distance(const Point_3& p, const Point_3& q,
|
|||
CGAL_assertion(eit != edges_.end());
|
||||
|
||||
// Compute geodesic_distance
|
||||
return eit->second.signed_geodesic_distance(p,q);
|
||||
return eit->second.signed_geodesic_distance(p, q);
|
||||
}
|
||||
|
||||
template <class MD_>
|
||||
typename Mesh_domain_with_polyline_features_3<MD_>::FT
|
||||
Mesh_domain_with_polyline_features_3<MD_>::
|
||||
signed_geodesic_distance(const Point_3& p, const Point_3& q,
|
||||
Polyline_const_iterator pit,
|
||||
Polyline_const_iterator qit,
|
||||
const Curve_index& curve_index) const
|
||||
{
|
||||
// Get corresponding polyline
|
||||
typename Edges::const_iterator eit = edges_.find(curve_index);
|
||||
CGAL_assertion(eit != edges_.end());
|
||||
|
||||
// Compute geodesic_distance
|
||||
return eit->second.signed_geodesic_distance(p, q, pit, qit);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1477,7 +1217,9 @@ template <class MD_>
|
|||
CGAL::Sign
|
||||
Mesh_domain_with_polyline_features_3<MD_>::
|
||||
distance_sign(const Point_3& p, const Point_3& q,
|
||||
const Curve_index& index) const
|
||||
const Curve_index& index,
|
||||
Polyline_const_iterator pit,
|
||||
Polyline_const_iterator qit) const
|
||||
{
|
||||
typename Edges::const_iterator eit = edges_.find(index);
|
||||
CGAL_assertion(eit != edges_.end());
|
||||
|
|
@ -1485,12 +1227,30 @@ distance_sign(const Point_3& p, const Point_3& q,
|
|||
|
||||
if ( p == q )
|
||||
return CGAL::ZERO;
|
||||
else if ( eit->second.are_ordered_along(p,q) )
|
||||
else if ( eit->second.are_ordered_along(p,q,pit,qit) )
|
||||
return CGAL::POSITIVE;
|
||||
else
|
||||
return CGAL::NEGATIVE;
|
||||
}
|
||||
|
||||
template <class MD_>
|
||||
CGAL::Sign
|
||||
Mesh_domain_with_polyline_features_3<MD_>::
|
||||
distance_sign(const Point_3& p,
|
||||
const Point_3& q,
|
||||
const Curve_index& curve_index) const
|
||||
{
|
||||
typename Edges::const_iterator eit = edges_.find(curve_index);
|
||||
CGAL_assertion(eit != edges_.end());
|
||||
CGAL_precondition(!eit->second.is_loop());
|
||||
|
||||
if(p == q)
|
||||
return CGAL::ZERO;
|
||||
else if(eit->second.are_ordered_along(p, q))
|
||||
return CGAL::POSITIVE;
|
||||
else
|
||||
return CGAL::NEGATIVE;
|
||||
}
|
||||
|
||||
template <class MD_>
|
||||
CGAL::Sign
|
||||
|
|
@ -1517,6 +1277,34 @@ distance_sign_along_loop(const Point_3& p,
|
|||
else { return CGAL::NEGATIVE; }
|
||||
}
|
||||
|
||||
template <class MD_>
|
||||
CGAL::Sign Mesh_domain_with_polyline_features_3<MD_>::
|
||||
distance_sign_along_loop(const Point_3& p,
|
||||
const Point_3& q,
|
||||
const Point_3& r,
|
||||
const Curve_index& index,
|
||||
Polyline_const_iterator pit,
|
||||
Polyline_const_iterator qit,
|
||||
Polyline_const_iterator rit) const
|
||||
{
|
||||
CGAL_assertion(p != q);
|
||||
CGAL_assertion(p != r);
|
||||
CGAL_assertion(r != q);
|
||||
|
||||
// Find edge
|
||||
typename Edges::const_iterator eit = edges_.find(index);
|
||||
CGAL_assertion(eit != edges_.end());
|
||||
CGAL_assertion(eit->second.is_loop());
|
||||
|
||||
FT pq = eit->second.curve_segment_length(p,q,CGAL::POSITIVE,pit,qit);
|
||||
FT pr = eit->second.curve_segment_length(p,r,CGAL::POSITIVE,pit,rit);
|
||||
|
||||
// Compare pq and pr
|
||||
if ( pq <= pr ) { return CGAL::POSITIVE; } else {
|
||||
return CGAL::NEGATIVE;
|
||||
}
|
||||
}
|
||||
|
||||
template <class MD_>
|
||||
bool
|
||||
Mesh_domain_with_polyline_features_3<MD_>::
|
||||
|
|
@ -1535,13 +1323,53 @@ Mesh_domain_with_polyline_features_3<MD_>::
|
|||
is_curve_segment_covered(const Curve_index& index,
|
||||
CGAL::Orientation orientation,
|
||||
const Point_3& c1, const Point_3& c2,
|
||||
const FT sq_r1, const FT sq_r2) const
|
||||
const FT sq_r1, const FT sq_r2,
|
||||
const Polyline_const_iterator c1_it,
|
||||
const Polyline_const_iterator c2_it) const
|
||||
{
|
||||
typename Edges::const_iterator eit = edges_.find(index);
|
||||
CGAL_assertion(eit != edges_.end());
|
||||
|
||||
return eit->second.is_curve_segment_covered(orientation,
|
||||
c1, c2, sq_r1, sq_r2);
|
||||
c1, c2,
|
||||
sq_r1, sq_r2,
|
||||
c1_it, c2_it);
|
||||
}
|
||||
|
||||
template <class MD_>
|
||||
bool
|
||||
Mesh_domain_with_polyline_features_3<MD_>::
|
||||
is_curve_segment_covered(const Curve_index& index,
|
||||
CGAL::Orientation orientation,
|
||||
const Point_3& c1, const Point_3& c2,
|
||||
const FT sq_r1, const FT sq_r2) const
|
||||
{
|
||||
typename Edges::const_iterator eit = edges_.find(index);
|
||||
CGAL_assertion(eit != edges_.end());
|
||||
|
||||
return eit->second.is_curve_segment_covered(orientation, c1, c2, sq_r1, sq_r2);
|
||||
}
|
||||
|
||||
template <class MD_>
|
||||
typename Mesh_domain_with_polyline_features_3<MD_>::Polyline_const_iterator
|
||||
Mesh_domain_with_polyline_features_3<MD_>::
|
||||
locate_corner(const Curve_index& curve_index,
|
||||
const Point_3& p) const
|
||||
{
|
||||
typename Edges::const_iterator eit = edges_.find(curve_index);
|
||||
CGAL_assertion(eit != edges_.end());
|
||||
return eit->second.locate_corner(p);
|
||||
}
|
||||
|
||||
template <class MD_>
|
||||
typename Mesh_domain_with_polyline_features_3<MD_>::Polyline_const_iterator
|
||||
Mesh_domain_with_polyline_features_3<MD_>::
|
||||
locate_point(const Curve_index& curve_index,
|
||||
const Point_3& p) const
|
||||
{
|
||||
typename Edges::const_iterator eit = edges_.find(curve_index);
|
||||
CGAL_assertion(eit != edges_.end());
|
||||
return eit->second.locate_point(p);
|
||||
}
|
||||
|
||||
} //namespace CGAL
|
||||
|
|
|
|||
|
|
@ -228,23 +228,28 @@ public:
|
|||
|
||||
//fill incidences of corners with curves
|
||||
d_ptr->corners_incident_curves.resize(d_ptr->corners.size());
|
||||
for(const typename Corners_indices::value_type& pair : d_ptr->corners_indices) {
|
||||
d_ptr->dt.insert(pair.first);
|
||||
for(const auto& [corner_pt, corner_index] : d_ptr->corners_indices)
|
||||
{
|
||||
d_ptr->dt.insert(corner_pt);
|
||||
|
||||
// Fill `corners_incident_curves[corner_id]`
|
||||
Curves_ids& incident_curves = d_ptr->corners_incident_curves[pair.second];
|
||||
d_ptr->domain.get_corner_incident_curves(pair.second,
|
||||
Curves_ids& incident_curves = d_ptr->corners_incident_curves[corner_index];
|
||||
d_ptr->domain.get_corner_incident_curves(corner_index,
|
||||
std::inserter(incident_curves,
|
||||
incident_curves.end()));
|
||||
// For each incident loops, insert a point on the loop, as far as
|
||||
// For each incident loop, insert a point on the loop, as far as
|
||||
// possible.
|
||||
for(Curve_index curve_index : incident_curves) {
|
||||
for(Curve_index curve_index : incident_curves)
|
||||
{
|
||||
if(domain.is_loop(curve_index)) {
|
||||
FT curve_length = d_ptr->domain.curve_length(curve_index);
|
||||
Point_3 other_point =
|
||||
d_ptr->domain.construct_point_on_curve(pair.first,
|
||||
auto loc =
|
||||
d_ptr->domain.locate_corner(curve_index, corner_pt);
|
||||
auto [other_point, _] =
|
||||
d_ptr->domain.construct_point_on_curve(corner_pt,
|
||||
curve_index,
|
||||
curve_length / 2);
|
||||
curve_length / 2,
|
||||
loc);
|
||||
d_ptr->dt.insert(other_point);
|
||||
}
|
||||
}
|
||||
|
|
@ -570,7 +575,12 @@ public:
|
|||
if (const Point_3* pp = std::get_if<Point_3>(&*int_res))
|
||||
{
|
||||
FT new_sqd = CGAL::squared_distance(p, *pp);
|
||||
FT dist = CGAL::abs(d_ptr->domain.signed_geodesic_distance(p, *pp, curve_id));
|
||||
auto p_polyline_const_it = ppid.second.second;
|
||||
auto pp_polyline_const_it = prim.id().second;
|
||||
FT dist = CGAL::abs(d_ptr->domain.signed_geodesic_distance(p, *pp,
|
||||
p_polyline_const_it,
|
||||
pp_polyline_const_it,
|
||||
curve_id));
|
||||
|
||||
#ifdef CGAL_MESH_3_PROTECTION_HIGH_VERBOSITY
|
||||
std::cerr << "Intersection point : Point_3(" << *pp << ") ";
|
||||
|
|
|
|||
|
|
@ -11,6 +11,11 @@
|
|||
#ifndef CGAL_NT_WRAPPER_H
|
||||
#define CGAL_NT_WRAPPER_H
|
||||
|
||||
|
||||
#include <CGAL/config.h>
|
||||
|
||||
#if __cpp_lib_source_location
|
||||
|
||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
|
||||
#include <CGAL/Coercion_traits.h>
|
||||
|
|
@ -184,4 +189,6 @@ struct Wrapped_epeck
|
|||
|
||||
} // namespace CGAL
|
||||
|
||||
#endif // __cpp_lib_source_location
|
||||
|
||||
#endif // CGAL_NT_WRAPPER_H
|
||||
|
|
@ -45,6 +45,7 @@
|
|||
#include <CGAL/Periodic_3_Delaunay_triangulation_traits_3.h>
|
||||
#include <CGAL/Periodic_3_Delaunay_triangulation_3.h>
|
||||
#include <CGAL/Time_stamper.h>
|
||||
#include <CGAL/Mesh_3/internal/Polyline.h>
|
||||
|
||||
#include <CGAL/boost/iterator/transform_iterator.hpp>
|
||||
|
||||
|
|
@ -98,6 +99,8 @@ public:
|
|||
typedef typename MeshDomain::Corner_index Corner_index;
|
||||
typedef typename MeshDomain::Index Index;
|
||||
|
||||
using Polyline_iterator = typename CGAL::Mesh_3::internal::Polyline<Gt>::const_iterator;
|
||||
|
||||
private:
|
||||
typedef typename CGAL::Kernel_traits<MeshDomain>::Kernel Kernel;
|
||||
|
||||
|
|
@ -1884,35 +1887,40 @@ Protect_edges_sizing_field<C3T3, MD, Sf>::
|
|||
insert_balls_on_edges()
|
||||
{
|
||||
// Get features
|
||||
typedef std::tuple<Curve_index,
|
||||
std::pair<Bare_point,Index>,
|
||||
std::pair<Bare_point,Index> > Feature_tuple;
|
||||
typedef std::vector<Feature_tuple> Input_features;
|
||||
// Get features
|
||||
struct Feature_tuple
|
||||
{
|
||||
Curve_index curve_index_;
|
||||
Polyline_iterator polyline_begin_;
|
||||
std::pair<Bare_point, Index> point_s_;
|
||||
std::pair<Bare_point, Index> point_t_;
|
||||
};
|
||||
typedef std::vector<Feature_tuple> Input_features;
|
||||
|
||||
Input_features input_features;
|
||||
domain_.get_curves(std::back_inserter(input_features));
|
||||
|
||||
// Iterate on edges
|
||||
for(typename Input_features::iterator fit = input_features.begin(),
|
||||
end = input_features.end() ; fit != end ; ++fit)
|
||||
for(const Feature_tuple& ft : input_features)
|
||||
{
|
||||
const Curve_index& curve_index = std::get<0>(*fit);
|
||||
const Curve_index& curve_index = ft.curve_index_;
|
||||
if(! is_treated(curve_index))
|
||||
{
|
||||
#if CGAL_MESH_3_PROTECTION_DEBUG & 1
|
||||
std::cerr << "** treat curve #" << curve_index << std::endl;
|
||||
std::cerr << "is it a loop? " << domain_.is_loop(curve_index) << std::endl;
|
||||
#endif
|
||||
const Bare_point& p = std::get<1>(*fit).first;
|
||||
const Bare_point& q = std::get<2>(*fit).first;
|
||||
|
||||
const Index& p_index = std::get<1>(*fit).second;
|
||||
const Index& q_index = std::get<2>(*fit).second;
|
||||
const Bare_point& p = ft.point_s_.first;
|
||||
const Index& p_index = ft.point_s_.second;
|
||||
const Polyline_iterator& p_polyline_iter = ft.polyline_begin_;
|
||||
|
||||
Vertex_handle vp,vq;
|
||||
if(! domain_.is_loop(curve_index))
|
||||
{
|
||||
vp = get_vertex_corner_from_point(p, p_index);
|
||||
|
||||
const Bare_point& q = ft.point_t_.first;
|
||||
const Index& q_index = ft.point_t_.second;
|
||||
vq = get_vertex_corner_from_point(q, q_index);
|
||||
}
|
||||
else
|
||||
|
|
@ -1943,6 +1951,7 @@ insert_balls_on_edges()
|
|||
p_index,
|
||||
curve_index,
|
||||
CGAL::Emptyset_iterator()).first;
|
||||
domain_.set_polyline_iterator(p, p_polyline_iter);
|
||||
}
|
||||
// No 'else' because in that case 'is_vertex(..)' already filled
|
||||
// the variable 'vp'.
|
||||
|
|
|
|||
|
|
@ -1366,7 +1366,7 @@ preprocess_bounded_error_squared_Hausdorff_distance_impl(const TriangleMesh1& tm
|
|||
|
||||
if(is_one_sided_distance) // one-sided distance
|
||||
{
|
||||
if(tm1_only.size() > 0) // create TM1 and and full TM2
|
||||
if(tm1_only.size() > 0) // create TM1 and full TM2
|
||||
{
|
||||
tm1_tree.insert(tm1_only.begin(), tm1_only.end(), tm1, vpm1);
|
||||
tm2_tree.insert(faces2.begin(), faces2.end(), tm2, vpm2);
|
||||
|
|
|
|||
|
|
@ -76,35 +76,6 @@ struct is_convertible_without_narrowing : details::is_convertible_without_narrow
|
|||
template <typename From, typename To>
|
||||
inline constexpr bool is_convertible_without_narrowing_v = is_convertible_without_narrowing<From, To>::value;
|
||||
|
||||
#if 0
|
||||
namespace is_complete_internals
|
||||
{
|
||||
template<class T>
|
||||
std::enable_if_t<sizeof(T) != 0, std::true_type>
|
||||
check(T(*)());
|
||||
|
||||
std::false_type check(...);
|
||||
};
|
||||
|
||||
template<class T, class Base = decltype(is_complete_internals::check(typename std::enable_if<true, T(*)()>::type()))>
|
||||
struct is_complete : Base { };
|
||||
|
||||
template <class T>
|
||||
inline constexpr bool is_complete_v = is_complete<T>::value;
|
||||
|
||||
namespace is_complete_testsuite
|
||||
{
|
||||
|
||||
struct S1;
|
||||
static_assert(!is_complete<S1>::value, "error");
|
||||
struct S2
|
||||
{
|
||||
static_assert(!is_complete<S2>::value, "error");
|
||||
};
|
||||
struct S3 {};
|
||||
static_assert(is_complete<S3>::value, "error");
|
||||
}
|
||||
#endif
|
||||
|
||||
} // end namespace CGAL
|
||||
|
||||
|
|
|
|||
|
|
@ -38,6 +38,24 @@
|
|||
|
||||
namespace CGAL {
|
||||
|
||||
namespace internal_is_hashable {
|
||||
using boost::hash_value;
|
||||
|
||||
template <typename T, typename = void>
|
||||
struct Has_hash_value : std::false_type {};
|
||||
|
||||
template <typename T>
|
||||
using hash_value_type = decltype(hash_value(std::declval<T>()));
|
||||
template <typename T>
|
||||
struct Has_hash_value<T, std::void_t<hash_value_type<T>>>
|
||||
: std::is_convertible<hash_value_type<T>, std::size_t>
|
||||
{};
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline constexpr bool is_hashable_v =
|
||||
internal_is_hashable::Has_hash_value<T>::value && std::is_default_constructible_v<std::hash<T>>;
|
||||
|
||||
template <
|
||||
typename Key,
|
||||
typename T,
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ create_single_source_cgal_program("test_dispatch_output.cpp")
|
|||
create_single_source_cgal_program("test_Flattening_iterator.cpp")
|
||||
create_single_source_cgal_program("test_Handle_with_policy.cpp")
|
||||
create_single_source_cgal_program("test_In_place_list.cpp")
|
||||
create_single_source_cgal_program("test_is_hashable.cpp")
|
||||
create_single_source_cgal_program("test_is_iterator.cpp")
|
||||
create_single_source_cgal_program("test_is_streamable.cpp")
|
||||
create_single_source_cgal_program("test_lexcompare_outputrange.cpp")
|
||||
|
|
|
|||
|
|
@ -0,0 +1,86 @@
|
|||
// test partially generated by Github Copilot
|
||||
|
||||
#include <CGAL/unordered_flat_map.h>
|
||||
#include <CGAL/Point_2.h>
|
||||
#include <CGAL/Point_3.h>
|
||||
#include <CGAL/Vector_2.h>
|
||||
#include <CGAL/Simple_cartesian.h>
|
||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
|
||||
#include <string>
|
||||
#include <utility> // std::pair
|
||||
|
||||
// Test types without hash support
|
||||
struct No_hash {};
|
||||
struct No_default_constructible_hash {};
|
||||
|
||||
// Provide boost::hash_value for No_default_constructible_hash
|
||||
namespace boost {
|
||||
std::size_t hash_value(const No_default_constructible_hash&) { return 42; }
|
||||
}
|
||||
|
||||
// But make std::hash not default constructible
|
||||
namespace std {
|
||||
template <>
|
||||
struct hash<No_default_constructible_hash> {
|
||||
hash() = delete; // Not default constructible
|
||||
std::size_t operator()(const No_default_constructible_hash&) const { return 42; }
|
||||
};
|
||||
}
|
||||
|
||||
int main() {
|
||||
using CGAL::is_hashable_v;
|
||||
using SC = CGAL::Simple_cartesian<double>;
|
||||
using Epick = CGAL::Exact_predicates_inexact_constructions_kernel;
|
||||
using Epeck = CGAL::Exact_predicates_exact_constructions_kernel;
|
||||
|
||||
// Built-in types should be hashable
|
||||
static_assert(is_hashable_v<int>);
|
||||
static_assert(is_hashable_v<double>);
|
||||
static_assert(is_hashable_v<float>);
|
||||
static_assert(is_hashable_v<long>);
|
||||
static_assert(is_hashable_v<std::string>);
|
||||
|
||||
// Types without hash support should not be hashable
|
||||
static_assert(!is_hashable_v<No_hash>);
|
||||
|
||||
// Types with hash_value but non-default-constructible std::hash should not be hashable
|
||||
static_assert(!is_hashable_v<No_default_constructible_hash>);
|
||||
|
||||
// CGAL kernel objects should be hashable (with Cartesian kernels)
|
||||
static_assert(is_hashable_v<SC::Point_2>);
|
||||
static_assert(is_hashable_v<SC::Point_3>);
|
||||
static_assert(is_hashable_v<SC::Vector_2>);
|
||||
static_assert(is_hashable_v<SC::Vector_3>);
|
||||
static_assert(is_hashable_v<SC::Segment_2>);
|
||||
static_assert(is_hashable_v<SC::Segment_3>);
|
||||
static_assert(is_hashable_v<SC::Aff_transformation_2>);
|
||||
static_assert(is_hashable_v<SC::Aff_transformation_3>);
|
||||
static_assert(is_hashable_v<SC::Circle_2>);
|
||||
static_assert(is_hashable_v<SC::Sphere_3>);
|
||||
static_assert(is_hashable_v<SC::Iso_rectangle_2>);
|
||||
static_assert(is_hashable_v<SC::Iso_cuboid_3>);
|
||||
static_assert(is_hashable_v<SC::Weighted_point_2>);
|
||||
static_assert(is_hashable_v<SC::Weighted_point_3>);
|
||||
|
||||
// Test with Epick kernel
|
||||
static_assert(is_hashable_v<Epick::Point_2>);
|
||||
static_assert(is_hashable_v<Epick::Point_3>);
|
||||
static_assert(is_hashable_v<Epick::Vector_2>);
|
||||
static_assert(is_hashable_v<Epick::Vector_3>);
|
||||
|
||||
// Test with Epeck kernel
|
||||
static_assert(!is_hashable_v<Epeck::Point_2>);
|
||||
static_assert(!is_hashable_v<Epeck::Point_3>);
|
||||
static_assert(!is_hashable_v<Epeck::Vector_2>);
|
||||
static_assert(!is_hashable_v<Epeck::Vector_3>);
|
||||
|
||||
// Bbox types should be hashable
|
||||
static_assert(is_hashable_v<CGAL::Bbox_2>);
|
||||
static_assert(is_hashable_v<CGAL::Bbox_3>);
|
||||
|
||||
// std::pair should not be hashable (no std::hash specialization in standard)
|
||||
static_assert(!is_hashable_v<std::pair<int, int>>);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -7,8 +7,8 @@
|
|||
// $Id$
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Efi Fogel <efif@post.tau.ac.il>
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Efi Fogel <efif@post.tau.ac.il>
|
||||
|
||||
#ifndef CGAL_SURFACE_SWEEP_2_DEFAULT_VISITOR_BASE_H
|
||||
#define CGAL_SURFACE_SWEEP_2_DEFAULT_VISITOR_BASE_H
|
||||
|
|
@ -50,28 +50,27 @@ template <typename GeometryTraits_2, typename Event_, typename Subcurve_,
|
|||
typename Allocator_, typename Visitor_>
|
||||
class Default_visitor_base {
|
||||
public:
|
||||
typedef GeometryTraits_2 Geometry_traits_2;
|
||||
typedef Event_ Event;
|
||||
typedef Subcurve_ Subcurve;
|
||||
typedef Allocator_ Allocator;
|
||||
typedef Visitor_ Visitor;
|
||||
using Geometry_traits_2 = GeometryTraits_2;
|
||||
using Event = Event_;
|
||||
using Subcurve = Subcurve_;
|
||||
using Allocator = Allocator_;
|
||||
using Visitor = Visitor_;
|
||||
|
||||
private:
|
||||
typedef Geometry_traits_2 Gt2;
|
||||
typedef Default_visitor_base<Gt2, Event, Subcurve, Allocator, Visitor>
|
||||
Self;
|
||||
using Gt2 = Geometry_traits_2;
|
||||
using Self = Default_visitor_base<Gt2, Event, Subcurve, Allocator, Visitor>;
|
||||
|
||||
public:
|
||||
typedef typename Subcurve::Status_line_iterator Status_line_iterator;
|
||||
using Status_line_iterator = typename Subcurve::Status_line_iterator;
|
||||
|
||||
typedef typename Gt2::X_monotone_curve_2 X_monotone_curve_2;
|
||||
typedef typename Gt2::Point_2 Point_2;
|
||||
using X_monotone_curve_2 = typename Gt2::X_monotone_curve_2;
|
||||
using Point_2 = typename Gt2::Point_2;
|
||||
using Multiplicity = typename Gt2::Multiplicity;
|
||||
|
||||
typedef typename Event::Subcurve_iterator Event_subcurve_iterator;
|
||||
typedef typename Event::Subcurve_reverse_iterator
|
||||
Event_subcurve_reverse_iterator;
|
||||
using Event_subcurve_iterator = typename Event::Subcurve_iterator;
|
||||
using Event_subcurve_reverse_iterator = typename Event::Subcurve_reverse_iterator;
|
||||
|
||||
typedef No_intersection_surface_sweep_2<Visitor> Surface_sweep_2;
|
||||
using Surface_sweep_2 = No_intersection_surface_sweep_2<Visitor>;
|
||||
|
||||
protected:
|
||||
// Data members:
|
||||
|
|
@ -134,7 +133,8 @@ public:
|
|||
void update_event(Event* /* e */,
|
||||
Subcurve* /* sc1 */,
|
||||
Subcurve* /* sc2 */,
|
||||
bool /* is_new */)
|
||||
bool /* is_new */,
|
||||
Multiplicity /* multiplicity */)
|
||||
{}
|
||||
|
||||
/*! Update the event. */
|
||||
|
|
|
|||
|
|
@ -7,9 +7,9 @@
|
|||
// $Id$
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ron Wein <wein@post.tau.ac.il>
|
||||
// Efi Fogel <efif@post.tau.ac.il>
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ron Wein <wein@post.tau.ac.il>
|
||||
// Efi Fogel <efif@post.tau.ac.il>
|
||||
|
||||
#ifndef CGAL_SURFACE_SWEEP_2_DO_INTERIOR_INTERSECT_VISITORS_H
|
||||
#define CGAL_SURFACE_SWEEP_2_DO_INTERIOR_INTERSECT_VISITORS_H
|
||||
|
|
@ -39,27 +39,27 @@ template <typename GeometryTraits_2,
|
|||
class Do_interior_intersect_visitor :
|
||||
public Default_visitor<Do_interior_intersect_visitor<GeometryTraits_2,
|
||||
Allocator_>,
|
||||
GeometryTraits_2, Allocator_>
|
||||
{
|
||||
GeometryTraits_2, Allocator_> {
|
||||
public:
|
||||
typedef GeometryTraits_2 Geometry_traits_2;
|
||||
typedef Allocator_ Allocator;
|
||||
using Geometry_traits_2 = GeometryTraits_2;
|
||||
using Allocator = Allocator_;
|
||||
|
||||
private:
|
||||
typedef Geometry_traits_2 Gt2;
|
||||
typedef Do_interior_intersect_visitor<Gt2, Allocator> Self;
|
||||
typedef Default_visitor<Self, Gt2, Allocator> Base;
|
||||
using Gt2 = Geometry_traits_2;
|
||||
using Self = Do_interior_intersect_visitor<Gt2, Allocator>;
|
||||
using Base = Default_visitor<Self, Gt2, Allocator>;
|
||||
|
||||
public:
|
||||
typedef typename Base::Event Event;
|
||||
typedef typename Base::Subcurve Subcurve;
|
||||
using Event = typename Base::Event;
|
||||
using Subcurve = typename Base::Subcurve;
|
||||
|
||||
typedef typename Subcurve::Status_line_iterator Status_line_iterator;
|
||||
using Status_line_iterator = typename Subcurve::Status_line_iterator;
|
||||
|
||||
typedef typename Gt2::X_monotone_curve_2 X_monotone_curve_2;
|
||||
typedef typename Gt2::Point_2 Point_2;
|
||||
using X_monotone_curve_2 = typename Gt2::X_monotone_curve_2;
|
||||
using Point_2 = typename Gt2::Point_2;
|
||||
using Multiplicity = typename Gt2::Multiplicity;
|
||||
|
||||
typedef typename Base::Surface_sweep_2 Surface_sweep_2;
|
||||
using Surface_sweep_2 = typename Base::Surface_sweep_2;
|
||||
|
||||
protected:
|
||||
// Data members:
|
||||
|
|
@ -69,8 +69,7 @@ public:
|
|||
Do_interior_intersect_visitor() : m_found_x(false) {}
|
||||
|
||||
template <typename CurveIterator>
|
||||
void sweep(CurveIterator begin, CurveIterator end)
|
||||
{
|
||||
void sweep(CurveIterator begin, CurveIterator end) {
|
||||
std::vector<X_monotone_curve_2> curves_vec;
|
||||
std::vector<Point_2> points_vec;
|
||||
|
||||
|
|
@ -89,7 +88,8 @@ public:
|
|||
void update_event(Event* /* e */,
|
||||
Subcurve* /* sc1 */,
|
||||
Subcurve* /* sc2 */,
|
||||
bool /* is_new */)
|
||||
bool /* is_new */,
|
||||
Multiplicity /* multiplicity */)
|
||||
{ m_found_x = true; }
|
||||
|
||||
void update_event(Event* /* e */,
|
||||
|
|
@ -115,8 +115,7 @@ public:
|
|||
{}
|
||||
|
||||
template <typename XCurveIterator>
|
||||
void sweep_xcurves(XCurveIterator begin, XCurveIterator end)
|
||||
{
|
||||
void sweep_xcurves(XCurveIterator begin, XCurveIterator end) {
|
||||
// Perform the sweep.
|
||||
Surface_sweep_2* sl = this->surface_sweep();
|
||||
sl->sweep(begin, end);
|
||||
|
|
@ -129,8 +128,7 @@ public:
|
|||
|
||||
bool after_handle_event(Event* /* event */,
|
||||
Status_line_iterator /* iter */,
|
||||
bool /* flag */)
|
||||
{
|
||||
bool /* flag */) {
|
||||
if (m_found_x) {
|
||||
Surface_sweep_2* sl = this->surface_sweep();
|
||||
sl->stop_sweep();
|
||||
|
|
|
|||
|
|
@ -7,9 +7,9 @@
|
|||
// $Id$
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Efi Fogel <efif@post.tau.ac.il>
|
||||
// (based on old version by Tali Zvi)
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Efi Fogel <efif@post.tau.ac.il>
|
||||
// (based on a previous version developed by Tali Zvi)
|
||||
|
||||
#ifndef CGAL_SURFACE_SWEEP_2_IMPL_H
|
||||
#define CGAL_SURFACE_SWEEP_2_IMPL_H
|
||||
|
|
@ -33,8 +33,7 @@ namespace Surface_sweep_2 {
|
|||
// Initialize the data structures for the sweep-line algorithm.
|
||||
//
|
||||
template <typename Vis>
|
||||
void Surface_sweep_2<Vis>::_init_structures()
|
||||
{
|
||||
void Surface_sweep_2<Vis>::_init_structures() {
|
||||
// Initialize the structures maintained by the base sweep-line class.
|
||||
Base::_init_structures();
|
||||
}
|
||||
|
|
@ -43,8 +42,7 @@ void Surface_sweep_2<Vis>::_init_structures()
|
|||
// Complete the sweep (complete the data structures).
|
||||
//
|
||||
template <typename Vis>
|
||||
void Surface_sweep_2<Vis>::_complete_sweep()
|
||||
{
|
||||
void Surface_sweep_2<Vis>::_complete_sweep() {
|
||||
CGAL_SS_PRINT_START_EOL("completing the sweep");
|
||||
|
||||
// Complete the sweep process using base sweep-line class.
|
||||
|
|
@ -68,8 +66,7 @@ void Surface_sweep_2<Vis>::_complete_sweep()
|
|||
// Handle the subcurves to the left of the current event point.
|
||||
//
|
||||
template <typename Vis>
|
||||
void Surface_sweep_2<Vis>::_handle_left_curves()
|
||||
{
|
||||
void Surface_sweep_2<Vis>::_handle_left_curves() {
|
||||
CGAL_SS_PRINT_START("handling left curves at (");
|
||||
CGAL_SS_DEBUG(this->PrintEvent(this->m_currentEvent));
|
||||
CGAL_SS_PRINT_TEXT(")");
|
||||
|
|
@ -189,14 +186,12 @@ void Surface_sweep_2<Vis>::_handle_left_curves()
|
|||
// and with a left end not being the current event
|
||||
//
|
||||
template <typename Vis>
|
||||
void Surface_sweep_2<Vis>::_clip_non_active_curve_at_current_event(Subcurve* subcurve)
|
||||
{
|
||||
void Surface_sweep_2<Vis>::_clip_non_active_curve_at_current_event(Subcurve* subcurve) {
|
||||
// ignore active curve (will be split at intersection point)
|
||||
if (subcurve->hint() != this->m_statusLine.end() &&
|
||||
subcurve->hint() != Status_line_iterator() ) return;
|
||||
|
||||
if (!subcurve->is_start_point(this->m_currentEvent))
|
||||
{
|
||||
if (! subcurve->is_start_point(this->m_currentEvent)) {
|
||||
CGAL_SS_PRINT_TEXT("Splitting ");
|
||||
CGAL_SS_PRINT_CURVE(subcurve);
|
||||
CGAL_SS_PRINT_EOL();
|
||||
|
|
@ -215,13 +210,11 @@ void Surface_sweep_2<Vis>::_clip_non_active_curve_at_current_event(Subcurve* sub
|
|||
// Handle the overlaps between subcurves to the right of the current event point.
|
||||
//
|
||||
template <typename Vis>
|
||||
void Surface_sweep_2<Vis>::_handle_overlaps_in_right_curves()
|
||||
{
|
||||
const std::vector< std::pair<Subcurve*, Subcurve*> >& subcurve_pairs
|
||||
= this->m_currentEvent->overlaps_on_right;
|
||||
void Surface_sweep_2<Vis>::_handle_overlaps_in_right_curves() {
|
||||
const std::vector< std::pair<Subcurve*, Subcurve*> >& subcurve_pairs =
|
||||
this->m_currentEvent->overlaps_on_right;
|
||||
|
||||
if (!subcurve_pairs.empty())
|
||||
{
|
||||
if (!subcurve_pairs.empty()) {
|
||||
// handling overlaps on the right of the current event.
|
||||
// Only one curve from the overlapping curve is currently
|
||||
// in the right curves of the event. Other curve overlapping
|
||||
|
|
@ -240,11 +233,10 @@ void Surface_sweep_2<Vis>::_handle_overlaps_in_right_curves()
|
|||
// in the following map having a curve on the right of the event
|
||||
// as key, we get all the curves that overlap with that curve
|
||||
// on the right of the event
|
||||
typedef std::map<Subcurve*, std::vector<Subcurve*> > Subcurve_map;
|
||||
typedef std::map<Subcurve*, std::vector<Subcurve*>> Subcurve_map;
|
||||
Subcurve_map tests_per_subcurve_on_right;
|
||||
|
||||
for (std::size_t i=0; i<nb_p; ++i)
|
||||
{
|
||||
for (std::size_t i = 0; i < nb_p; ++i) {
|
||||
CGAL_SS_PRINT_TEXT("(");
|
||||
CGAL_SS_PRINT(subcurve_pairs[i].first);
|
||||
CGAL_SS_PRINT_TEXT(",");
|
||||
|
|
@ -254,13 +246,10 @@ void Surface_sweep_2<Vis>::_handle_overlaps_in_right_curves()
|
|||
tests_per_subcurve_on_right[subcurve_pairs[i].first].push_back(subcurve_pairs[i].second);
|
||||
}
|
||||
|
||||
for(typename Subcurve_map::iterator it = tests_per_subcurve_on_right.begin(),
|
||||
end = tests_per_subcurve_on_right.end(); it!=end; ++it)
|
||||
{
|
||||
for (auto it = tests_per_subcurve_on_right.begin(), end = tests_per_subcurve_on_right.end(); it != end; ++it) {
|
||||
std::size_t nbc = it->second.size();
|
||||
// remove possible duplicates
|
||||
if (nbc>1)
|
||||
{
|
||||
if (nbc > 1) {
|
||||
std::sort(it->second.begin(), it->second.end());
|
||||
typename std::vector<Subcurve*>::iterator last =
|
||||
std::unique(it->second.begin(), it->second.end());
|
||||
|
|
@ -277,8 +266,7 @@ void Surface_sweep_2<Vis>::_handle_overlaps_in_right_curves()
|
|||
else{
|
||||
// get the curve just after the key in the sorted set of curves on the right as it might be replaced
|
||||
Subcurve_iterator next_after = this->m_currentEvent->get_curve_after_on_right(it->first);
|
||||
for (std::size_t i=0; i<nbc; ++i)
|
||||
{
|
||||
for (std::size_t i = 0; i < nbc; ++i) {
|
||||
_intersect(it->second[i], *std::prev(next_after), this->m_currentEvent);
|
||||
CGAL_assertion(it->second.size()==nbc); // make sure the container was not updated
|
||||
}
|
||||
|
|
@ -289,27 +277,19 @@ void Surface_sweep_2<Vis>::_handle_overlaps_in_right_curves()
|
|||
}
|
||||
|
||||
// split curves not already split. TODO: this should be done above?
|
||||
for (Event_subcurve_iterator subcurve_it = this->m_currentEvent->right_curves_begin();
|
||||
subcurve_it != this->m_currentEvent->right_curves_end();
|
||||
++subcurve_it)
|
||||
{
|
||||
for (auto subcurve_it = this->m_currentEvent->right_curves_begin();
|
||||
subcurve_it != this->m_currentEvent->right_curves_end(); ++subcurve_it)
|
||||
_clip_non_active_curve_at_current_event(*subcurve_it);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Handle the subcurves to the right of the current event point.
|
||||
//
|
||||
template <typename Vis>
|
||||
void Surface_sweep_2<Vis>::_handle_right_curves()
|
||||
{
|
||||
|
||||
for(Event_subcurve_iterator sc_it = this->m_currentEvent->right_curves_begin(),
|
||||
sc_it_end = this->m_currentEvent->right_curves_end();
|
||||
sc_it!=sc_it_end; ++sc_it)
|
||||
{
|
||||
void Surface_sweep_2<Vis>::_handle_right_curves() {
|
||||
for (auto sc_it = this->m_currentEvent->right_curves_begin(), sc_it_end = this->m_currentEvent->right_curves_end();
|
||||
sc_it != sc_it_end; ++sc_it)
|
||||
(*sc_it)->reset_left_event();
|
||||
}
|
||||
|
||||
CGAL_SS_PRINT_START("handling right curves at (");
|
||||
CGAL_SS_DEBUG(this->PrintEvent(this->m_currentEvent));
|
||||
|
|
@ -329,15 +309,11 @@ void Surface_sweep_2<Vis>::_handle_right_curves()
|
|||
// - We also check to see if the two intersect again to the right of the
|
||||
// point.
|
||||
|
||||
Event_subcurve_iterator currentOne =
|
||||
this->m_currentEvent->right_curves_begin();
|
||||
Event_subcurve_iterator rightCurveEnd =
|
||||
this->m_currentEvent->right_curves_end();
|
||||
Event_subcurve_iterator currentOne = this->m_currentEvent->right_curves_begin();
|
||||
Event_subcurve_iterator rightCurveEnd = this->m_currentEvent->right_curves_end();
|
||||
|
||||
CGAL_SS_PRINT_INSERT(*currentOne);
|
||||
Status_line_iterator slIter =
|
||||
this->m_statusLine.insert_before(this->m_status_line_insert_hint,
|
||||
*currentOne);
|
||||
Status_line_iterator slIter = this->m_statusLine.insert_before(this->m_status_line_insert_hint, *currentOne);
|
||||
Subcurve* sc = *currentOne;
|
||||
sc->set_hint(slIter);
|
||||
|
||||
|
|
@ -352,8 +328,7 @@ void Surface_sweep_2<Vis>::_handle_right_curves()
|
|||
++currentOne;
|
||||
while (currentOne != rightCurveEnd) {
|
||||
CGAL_SS_PRINT_INSERT(*currentOne);
|
||||
slIter = this->m_statusLine.insert_before(this->m_status_line_insert_hint,
|
||||
*currentOne);
|
||||
slIter = this->m_statusLine.insert_before(this->m_status_line_insert_hint, *currentOne);
|
||||
|
||||
Subcurve* sc = *currentOne;
|
||||
sc->set_hint(slIter);
|
||||
|
|
@ -390,12 +365,8 @@ bool Surface_sweep_2<Vis>::_add_curve_to_right(Event* event, Subcurve* curve)
|
|||
CGAL_SS_PRINT_CURVE(curve);
|
||||
CGAL_SS_PRINT_EOL();
|
||||
|
||||
Event_subcurve_iterator iter;
|
||||
for (iter = event->right_curves_begin(); iter != event->right_curves_end();
|
||||
++iter)
|
||||
{
|
||||
if (*iter == curve)
|
||||
{
|
||||
for (auto iter = event->right_curves_begin(); iter != event->right_curves_end(); ++iter) {
|
||||
if (*iter == curve) {
|
||||
CGAL_SS_PRINT_END_EOL("adding a Curve to the right (curve exists)");
|
||||
return false;
|
||||
}
|
||||
|
|
@ -405,8 +376,7 @@ bool Surface_sweep_2<Vis>::_add_curve_to_right(Event* event, Subcurve* curve)
|
|||
if ((*iter)->are_all_leaves_contained(curve)) {
|
||||
CGAL_SS_PRINT_END_EOL("adding a Curve to the right (containing curve exists)");
|
||||
|
||||
if ( (*iter)->right_event() != curve->right_event() )
|
||||
{
|
||||
if ((*iter)->right_event() != curve->right_event()) {
|
||||
CGAL_assertion( this->m_queueEventLess((*iter)->right_event(), curve->right_event()) == SMALLER ); // subcurve has to end before
|
||||
_add_curve_to_right( (*iter)->right_event(), curve); // WARNING recursive
|
||||
}
|
||||
|
|
@ -417,8 +387,7 @@ bool Surface_sweep_2<Vis>::_add_curve_to_right(Event* event, Subcurve* curve)
|
|||
}
|
||||
|
||||
if (curve->are_all_leaves_contained(*iter)) {
|
||||
if ( (*iter)->right_event() != curve->right_event() )
|
||||
{
|
||||
if ( (*iter)->right_event() != curve->right_event()) {
|
||||
CGAL_assertion(this->m_queueEventLess(curve->right_event(), (*iter)->right_event()) == SMALLER); // subcurve has to end before
|
||||
_add_curve_to_right( curve->right_event(), *iter); // WARNING recursive
|
||||
}
|
||||
|
|
@ -426,8 +395,7 @@ bool Surface_sweep_2<Vis>::_add_curve_to_right(Event* event, Subcurve* curve)
|
|||
(*iter)->right_event()->remove_curve_from_left(*iter);
|
||||
|
||||
*iter = curve; // replace the current curve with the new one.
|
||||
CGAL_SS_PRINT_END_EOL
|
||||
("replacing a Curve to the right (curve partially overlaps)");
|
||||
CGAL_SS_PRINT_END_EOL("replacing a Curve to the right (curve partially overlaps)");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -443,11 +411,10 @@ bool Surface_sweep_2<Vis>::_add_curve_to_right(Event* event, Subcurve* curve)
|
|||
}
|
||||
|
||||
// a new overlap needs to be computed
|
||||
if (event!=this->m_currentEvent)
|
||||
if (event != this->m_currentEvent)
|
||||
event->overlaps_on_right.push_back(
|
||||
std::make_pair(static_cast<Subcurve*>(*(pair_res.second)),
|
||||
static_cast<Subcurve*>(curve))
|
||||
);
|
||||
static_cast<Subcurve*>(curve)));
|
||||
else
|
||||
_intersect(static_cast<Subcurve*>(curve),
|
||||
static_cast<Subcurve*>(*(pair_res.second)),
|
||||
|
|
@ -467,8 +434,7 @@ bool Surface_sweep_2<Vis>::_add_curve_to_right(Event* event, Subcurve* curve)
|
|||
//
|
||||
template <typename Vis>
|
||||
void Surface_sweep_2<Vis>::_remove_curve_from_status_line(Subcurve* leftCurve,
|
||||
bool remove_for_good)
|
||||
{
|
||||
bool remove_for_good) {
|
||||
CGAL_SS_PRINT_START("removing a curve from the status line, ");
|
||||
CGAL_SS_PRINT_CURVE(leftCurve);
|
||||
CGAL_SS_PRINT_EOL();
|
||||
|
|
@ -513,8 +479,7 @@ void Surface_sweep_2<Vis>::_remove_curve_from_status_line(Subcurve* leftCurve,
|
|||
//
|
||||
template <typename Vis>
|
||||
void Surface_sweep_2<Vis>::_intersect(Subcurve* c1, Subcurve* c2,
|
||||
Event* event_for_overlap)
|
||||
{
|
||||
Event* event_for_overlap) {
|
||||
CGAL_SS_PRINT_START("computing intersection of ");
|
||||
CGAL_SS_PRINT_CURVE(c1);
|
||||
CGAL_SS_PRINT_TEXT(" and ");
|
||||
|
|
@ -538,8 +503,7 @@ void Surface_sweep_2<Vis>::_intersect(Subcurve* c1, Subcurve* c2,
|
|||
Subcurve_vector all_leaves_diff;
|
||||
Subcurve* first_parent = nullptr;
|
||||
if ((c1->originating_subcurve1() != nullptr) ||
|
||||
(c2->originating_subcurve2() != nullptr))
|
||||
{
|
||||
(c2->originating_subcurve2() != nullptr)) {
|
||||
// get the subcurve leaves of c1 and of c2. Then extract from the smallest
|
||||
// set the subcurves leaves that are not in the other one. If empty, it
|
||||
// means that a subcurves is completely contained in another one.
|
||||
|
|
@ -628,9 +592,7 @@ void Surface_sweep_2<Vis>::_intersect(Subcurve* c1, Subcurve* c2,
|
|||
CGAL_SS_PRINT_CURVE(first_parent);
|
||||
CGAL_SS_PRINT_EOL();
|
||||
X_monotone_curve_2 xc = first_parent->last_curve();
|
||||
for (auto sc_it = all_leaves_diff.begin();
|
||||
sc_it != all_leaves_diff.end(); ++sc_it)
|
||||
{
|
||||
for (auto sc_it = all_leaves_diff.begin(); sc_it != all_leaves_diff.end(); ++sc_it) {
|
||||
CGAL_SS_PRINT_TEXT("Inter with curve: ");
|
||||
CGAL_SS_PRINT_CURVE((*sc_it));
|
||||
CGAL_SS_PRINT_EOL();
|
||||
|
|
@ -681,12 +643,10 @@ void Surface_sweep_2<Vis>::_intersect(Subcurve* c1, Subcurve* c2,
|
|||
if ((ps_x1 == ps_x2) && (ps_y1 == ps_y2) &&
|
||||
((ps_x1 != ARR_INTERIOR) || (ps_y1 != ARR_INTERIOR)) &&
|
||||
this->m_traits->is_closed_2_object()(c1->last_curve(), ARR_MIN_END) &&
|
||||
this->m_traits->is_closed_2_object()(c2->last_curve(), ARR_MIN_END))
|
||||
{
|
||||
this->m_traits->is_closed_2_object()(c2->last_curve(), ARR_MIN_END)) {
|
||||
if ((std::get_if<Intersection_point>(&(*vi)) != nullptr) &&
|
||||
this->m_traits->equal_2_object()(ctr_min(c1->last_curve()),
|
||||
ctr_min(c2->last_curve())))
|
||||
{
|
||||
ctr_min(c2->last_curve()))) {
|
||||
CGAL_SS_PRINT_TEXT("Skipping common left endpoint on boundary ...");
|
||||
CGAL_SS_PRINT_EOL();
|
||||
++vi;
|
||||
|
|
@ -719,12 +679,10 @@ void Surface_sweep_2<Vis>::_intersect(Subcurve* c1, Subcurve* c2,
|
|||
if ((ps_x1 == ps_x2) && (ps_y1 == ps_y2) &&
|
||||
((ps_x1 != ARR_INTERIOR) || (ps_y2 != ARR_INTERIOR)) &&
|
||||
this->m_traits->is_closed_2_object()(c1->last_curve(), ARR_MAX_END) &&
|
||||
this->m_traits->is_closed_2_object()(c2->last_curve(), ARR_MAX_END))
|
||||
{
|
||||
this->m_traits->is_closed_2_object()(c2->last_curve(), ARR_MAX_END)) {
|
||||
if (this->m_traits->equal_2_object()
|
||||
(this->m_traits->construct_max_vertex_2_object()(c1->last_curve()),
|
||||
this->m_traits->construct_max_vertex_2_object()(c2->last_curve())))
|
||||
{
|
||||
this->m_traits->construct_max_vertex_2_object()(c2->last_curve()))) {
|
||||
vector_inserter vi_last = vi_end;
|
||||
|
||||
--vi_last;
|
||||
|
|
@ -791,8 +749,7 @@ template <typename Vis>
|
|||
void Surface_sweep_2<Vis>::_create_intersection_point(const Point_2& xp,
|
||||
Multiplicity multiplicity,
|
||||
Subcurve*& c1,
|
||||
Subcurve*& c2)
|
||||
{
|
||||
Subcurve*& c2) {
|
||||
CGAL_SS_PRINT_START_EOL("creating an intersection point between");
|
||||
CGAL_SS_PRINT_CURVE(c1);
|
||||
CGAL_SS_PRINT_EOL();
|
||||
|
|
@ -814,7 +771,7 @@ void Surface_sweep_2<Vis>::_create_intersection_point(const Point_2& xp,
|
|||
|
||||
e->set_intersection();
|
||||
|
||||
this->m_visitor->update_event(e, c1, c2, true);
|
||||
this->m_visitor->update_event(e, c1, c2, true, multiplicity);
|
||||
e->push_back_curve_to_left(c1);
|
||||
e->push_back_curve_to_left(c2);
|
||||
|
||||
|
|
@ -858,7 +815,7 @@ void Surface_sweep_2<Vis>::_create_intersection_point(const Point_2& xp,
|
|||
_add_curve_to_right(e, c1);
|
||||
_add_curve_to_right(e, c2);
|
||||
e->set_intersection();
|
||||
this->m_visitor->update_event(e, c1, c2, false);
|
||||
this->m_visitor->update_event(e, c1, c2, false, multiplicity);
|
||||
|
||||
if (multiplicity == 0) {
|
||||
if (e->is_right_curve_bigger(c1, c2, this->m_traits)) std::swap(c1, c2);
|
||||
|
|
@ -895,8 +852,7 @@ _create_overlapping_curve(const X_monotone_curve_2& overlap_cv,
|
|||
Subcurve*& c1 , Subcurve*& c2,
|
||||
const Subcurve_vector& all_leaves_diff,
|
||||
Subcurve* first_parent,
|
||||
Event* event_on_overlap)
|
||||
{
|
||||
Event* event_on_overlap) {
|
||||
// An overlap occurs:
|
||||
CGAL_SS_PRINT_START_EOL("creating an overlapping curve");
|
||||
|
||||
|
|
@ -935,14 +891,12 @@ _create_overlapping_curve(const X_monotone_curve_2& overlap_cv,
|
|||
if ((ps_x_r != ARR_INTERIOR) || (ps_y_r != ARR_INTERIOR)) {
|
||||
// CGAL_assertion(c1->right_event() == c2->right_event());
|
||||
// right_event = c1->right_event();
|
||||
right_event = this->_push_event(overlap_cv, ARR_MAX_END, Event::DEFAULT,
|
||||
ps_x_r, ps_y_r).first;
|
||||
right_event = this->_push_event(overlap_cv, ARR_MAX_END, Event::DEFAULT, ps_x_r, ps_y_r).first;
|
||||
}
|
||||
else {
|
||||
auto max_vertex = this->m_traits->construct_max_vertex_2_object();
|
||||
auto right_end = max_vertex(overlap_cv);
|
||||
right_event = this->_push_event(right_end, Event::DEFAULT, ARR_INTERIOR,
|
||||
ARR_INTERIOR).first;
|
||||
right_event = this->_push_event(right_end, Event::DEFAULT, ARR_INTERIOR, ARR_INTERIOR).first;
|
||||
}
|
||||
|
||||
if (!c1->is_start_point(left_event)) {
|
||||
|
|
@ -968,12 +922,9 @@ _create_overlapping_curve(const X_monotone_curve_2& overlap_cv,
|
|||
|
||||
// Allocate the new Subcurve for the overlap
|
||||
Subcurve* overlap_sc=nullptr;
|
||||
if (all_leaves_diff.empty())
|
||||
{
|
||||
if (all_leaves_diff.empty()) {
|
||||
// first check that an equivalent curve is not already in left_event
|
||||
for (Subcurve_iterator iter = left_event->right_curves_begin();
|
||||
iter != left_event->right_curves_end(); ++iter)
|
||||
{
|
||||
for (auto iter = left_event->right_curves_begin(); iter != left_event->right_curves_end(); ++iter) {
|
||||
if ((*iter)->has_same_leaves(c1, c2)) {
|
||||
CGAL_SS_PRINT_TEXT("Reuse overlapping curve ");
|
||||
CGAL_SS_PRINT_CURVE(*iter);
|
||||
|
|
@ -983,8 +934,7 @@ _create_overlapping_curve(const X_monotone_curve_2& overlap_cv,
|
|||
}
|
||||
}
|
||||
|
||||
if (overlap_sc==nullptr)
|
||||
{
|
||||
if (overlap_sc == nullptr) {
|
||||
CGAL_SS_PRINT_TEXT("Allocate a new subcurve for the overlap (no common subcurves)");
|
||||
CGAL_SS_PRINT_EOL();
|
||||
// no duplicate only one curve is needed
|
||||
|
|
@ -1005,10 +955,7 @@ _create_overlapping_curve(const X_monotone_curve_2& overlap_cv,
|
|||
CGAL_SS_PRINT_EOL();
|
||||
|
||||
// create an overlapping curve per subcurve in second_parent that is not in first_parent
|
||||
for (typename std::vector<Subcurve*>::const_iterator sc_it = all_leaves_diff.begin();
|
||||
sc_it != all_leaves_diff.end();
|
||||
++sc_it)
|
||||
{
|
||||
for (auto sc_it = all_leaves_diff.begin(); sc_it != all_leaves_diff.end(); ++sc_it) {
|
||||
overlap_sc = this->m_subCurveAlloc.allocate(1);
|
||||
std::allocator_traits<Subcurve_alloc>::construct(this->m_subCurveAlloc,overlap_sc, this->m_masterSubcurve);
|
||||
overlap_sc->set_hint(this->m_statusLine.end());
|
||||
|
|
@ -1063,8 +1010,7 @@ _create_overlapping_curve(const X_monotone_curve_2& overlap_cv,
|
|||
// or updated.
|
||||
//
|
||||
template <typename Vis>
|
||||
void Surface_sweep_2<Vis>::_add_curve(Event* e, Subcurve* sc, Attribute type)
|
||||
{
|
||||
void Surface_sweep_2<Vis>::_add_curve(Event* e, Subcurve* sc, Attribute type) {
|
||||
if (sc == nullptr) return;
|
||||
|
||||
if (type == Event::LEFT_END) {
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
\cgalPkgDependsOn{\ref PkgCombinatorialMaps}
|
||||
\cgalPkgBib{cgal:ddpt-thss}
|
||||
\cgalPkgLicense{\ref licensesGPL "GPL"}
|
||||
\cgalPkgDemo{2D Triangulations on Hyperbolic Surfaces,nofilefornow.zip}
|
||||
\cgalPkgDemo{2D Triangulations on Hyperbolic Surfaces,triangulation_on_hyperbolic_surface_2.zip}
|
||||
\cgalPkgShortInfoEnd
|
||||
|
||||
\cgalPkgDescriptionEnd
|
||||
|
|
|
|||
Loading…
Reference in New Issue