Compare commits

...

120 Commits

Author SHA1 Message Date
Jane Tournois 71dcddb981
Merge 5b574bfaae into dbcace69e6 2025-12-02 12:16:55 +01:00
Laurent Rineau dbcace69e6 fix oddities inherited from LaTeX 2025-11-26 11:52:09 +01:00
Laurent Rineau bac686d05b
Fix leftover qt5 (#9152)
## Release Management

* Affected package(s): `GraphicsView`
* Issue(s) solved (if any): -
* Feature/Small Feature (if any): -
* License and copyright ownership: no changes
2025-11-26 09:39:38 +01:00
Laurent Rineau 30f63794c3
Spelling correction (#9146)
Spelling correction
2025-11-25 23:30:39 +01:00
Mael Rouxel-Labbé d14619c335 Fix leftover qt5 2025-11-24 21:23:08 +01:00
Laurent Rineau 50a187db38 fix Markdown lint warnings
There were real formatting issues.
2025-11-24 12:21:49 +01:00
Laurent Rineau 95a315335f remove duplicate paragraphs 2025-11-24 11:44:55 +01:00
Sébastien Loriot ff5166fbee fix version 2025-11-24 10:21:41 +01:00
Sébastien Loriot 9f2fcb5e28 Merge remote-tracking branch 'cgal/6.1.x-branch' into 'cgal/main' 2025-11-21 17:41:27 +01:00
Sebastien Loriot 85ef57ffa1
CDT_3 bug-fix: throw exceptions instead of raw crashs (like segfaults) (#9089)
## Summary of Changes

Bug-fix for `CGAL::Conforming_constrained_Delaunay_triangulation_3` in
CGAL-6.1.

## Release Management

* Affected package(s): Constrained_triangulation_3
* License and copyright ownership: GeometryFactory
2025-11-21 17:40:00 +01:00
Sebastien Loriot aefbc23955
precompiled demos for CGAL-6.1 (#9132)
## Summary of Changes

Small fixes for precompiled demos

## Release Management

* Affected package(s): Maintenance
* License and copyright ownership: N/A
2025-11-21 17:39:12 +01:00
albert-github da0f634cb2 Spelling correction
Spelling correction
2025-11-21 11:10:23 +01:00
Laurent Rineau 7bf5687d5d Remove -fexperimental-library 2025-11-21 10:42:35 +01:00
Sebastien Loriot 1069678f36
Optimize the `do_intersect()` functions of the 2D Regularized Boolean Set Operation" package (made it tolerant to inexact kernels.) (#9050)
## Summary of Changes

Optimized `do_intersect(polygon, polygon)`, `do_intersect(begin, end)`,
and `do_intersect(begin1, end1, begin2, end2)`:
(i) Terminated the execution once an intersection is detected. (In the
past, the intersection was computed in one phase and examined in a
subsequent phase.)
(ii) Made the variants of the free functions `do_intersect()` that apply
to linear polygons, robust even with an inexact-construction kernel. The
variants that apply to generalized polygons endure inexact constructions
much more than before; however, there are rare degenerate cases that are
still require an exact construction kernel.

In general, the changes described here do not affect the default
interface, so a small feature is not required. However, it is a major
impact, and it does affect the interface as described bellow, and even
somehow break backward compatibility.

Recently, the code of the package "2D Regularized Boolean Set
Operations" was optimized. In particular, a 3rd optional parameter was
introduced in the free functions. It determined whether the boundaries
of the input polygons are treated as cyclic sequences of single
(`x`-monotone) segments or as a cyclic sequences of (`x`-monotone)
polylines. The change described here eliminates this 3rd parameter, and
brings the interface of the `do_intersect() function back to the
original design with two input polygons.

## Release Management

* Affected package(s): Boolean_set_operations_2, Surface_sweep,
Arrangement_on_surface_2
* Feature/Small Feature (if any):
[here](https://cgalwiki.geometryfactory.com/CGAL/Members/wiki/Features/Small_Features/do_intersect_polygon_2_predicates_only)
* Link to compiled documentation (obligatory for small feature) [*wrong
link name to be changed*](httpssss://wrong_URL_to_be_changed/Manual/Pkg)
* License and copyright ownership: TAU
2025-11-21 09:21:02 +01:00
Laurent Rineau cda931ec46 fix a warning 2025-11-20 15:23:40 +01:00
Andreas Fabri e98fa21cc9 Fix warning in CGAL-6.2-Ic-41 2025-11-20 11:35:50 +01:00
Laurent Rineau e0a720452d fix a warning 2025-11-20 11:35:24 +01:00
Laurent Rineau c856e40662 re-add <version> to fix clangd warnings 2025-11-20 11:35:17 +01:00
Laurent Rineau ef6f9d8c3c fix compilation error without C++20 2025-11-20 11:35:11 +01:00
Laurent Rineau 18e5836373 fix usage of <version>
That C++20 header is already conditionally included bu `<CGAL/config.h>`.

See e6b4d83cff/Installation/include/CGAL/config.h (L322)
2025-11-20 11:35:02 +01:00
Andreas Fabri 3e1a8c110d (std::numeric_limits<std::size_t>::max)() 2025-11-20 11:34:38 +01:00
Jane Tournois 5b574bfaae move CGAL::Mesh_3::internal::Polyline class to its own header 2025-11-18 12:08:25 +01:00
Jane Tournois b804ec9394 duplicate functions to keep original API valid 2025-11-18 10:10:54 +01:00
Jane Tournois 6ec5daa6b9 cleaning 2025-11-17 12:46:47 +01:00
Jane Tournois e74e5de28a move map to Mesh_domain_with_polyline_features_3 and use it in Protect_edges_sizing_field 2025-11-17 12:42:44 +01:00
Jane Tournois 5c5c48ba16 improve readability 2025-11-14 10:46:12 +01:00
Jane Tournois 9587991deb Merge branch 'Mesh_3-speedup_balls-jtournois' of https://github.com/janetournois/cgal into Mesh_3-speedup_balls-jtournois
# Conflicts:
#	Mesh_3/include/CGAL/Sizing_field_with_aabb_tree.h
2025-11-14 10:35:37 +01:00
Jane Tournois b44e132565 fix compilation for return type 2025-11-14 10:34:02 +01:00
Jane Tournois 789d4c4f9d wip using locate_corner() 2025-11-14 10:32:23 +01:00
Jane Tournois 0a6df0877a wip using locate_corner() 2025-11-13 15:38:20 +01:00
Laurent Rineau 1602be1348 precompiled demos for CGAL-6.1 2025-11-13 13:29:35 +01:00
Laurent Rineau c751ee6bc9 fix for AppleClang 2025-11-12 12:35:12 +01:00
Sébastien Loriot 7e1f685ea3 changes is for 6.2 2025-11-03 15:49:49 +01:00
Sébastien Loriot f92b41ae0a Merge remote-tracking branch 'cgal/main' into 'efifogel/Bso_2-do_intersect_efif' 2025-11-03 15:47:22 +01:00
Sébastien Loriot e4469c043e handle backward compatibility 2025-11-03 15:46:19 +01:00
Laurent Rineau 2a5351cc0a
Update Kernel_23/include/CGAL/Kernel/hash_functions.h
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-10-31 15:40:42 +01:00
Laurent Rineau f508d6fe1d
Update STL_Extension/include/CGAL/unordered_flat_map.h
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-10-31 15:40:22 +01:00
Laurent Rineau 7f4703e248 fix a warning 2025-10-31 09:47:34 +01:00
Laurent Rineau e13da7cbd4 restore the output 2025-10-31 09:47:34 +01:00
Laurent Rineau 5cc8ec7d71 hide unwanted stats or warnings 2025-10-31 09:47:20 +01:00
Laurent Rineau b5c3b5f895 fix typo 2025-10-29 15:32:11 +01:00
Laurent Rineau ab9e0ebc8a fix a few segfaults 2025-10-29 14:12:50 +01:00
Laurent Rineau 6706e0468e set epsilons to 0 by default 2025-10-29 14:12:50 +01:00
Laurent Rineau fd21dfb67d fix clang warning 2025-10-29 14:12:50 +01:00
Laurent Rineau bc42fb4a40 set the default random 2025-10-29 14:12:50 +01:00
Laurent Rineau 07e0ea785d CDT_3: fix for Epeck 2025-10-29 14:12:50 +01:00
Laurent Rineau edbc32959d refactor debug API so that cdt_3_from_off can use the official API 2025-10-29 14:12:50 +01:00
Laurent Rineau b068e62ffb cleanup of cdt_3_from_off.cpp, and move ITT code to CDT_3 2025-10-29 14:12:50 +01:00
Laurent Rineau b85035ff87 fix warnings 2025-10-29 14:12:50 +01:00
Laurent Rineau c48b4cb6c2 handle isolated non-manifold vertices into constrained faces 2025-10-29 14:12:50 +01:00
Laurent Rineau d34201ed38 fix a conversion warning (-1 converted to `std::size_t`) 2025-10-29 14:12:50 +01:00
Laurent Rineau 15a155ec30 rename to `insert_vertices_range` and use `spatial_sort` 2025-10-29 14:12:50 +01:00
Laurent Rineau e02c1495bf add a declarative RAII macro 2025-10-29 14:12:50 +01:00
Laurent Rineau 28d6ac5e49 missing include 2025-10-29 14:12:50 +01:00
Laurent Rineau 7fe0100855 add other minified data sets from Thingi 2025-10-17 17:15:46 +02:00
Laurent Rineau e7ab5002a3 add the test non_manifold_face_graph.off 2025-10-17 16:31:14 +02:00
Laurent Rineau 940ac3d6e4 try to please AppleCLang 15
- ...by adding an explicit deduction guide.
  - and add -fexperimental-library (so that ranges::join is found).
2025-10-17 11:46:08 +02:00
Laurent Rineau 8746a29fa9 fix warnings about unused arguments or captures 2025-10-17 10:55:55 +02:00
Laurent Rineau bc770242a5 minor: fix a warning 2025-10-16 17:20:34 +02:00
Laurent Rineau 61013d5053 more refactoring 2025-10-16 17:20:20 +02:00
Laurent Rineau d7faad95dd factoring part of the code into a function 2025-10-15 16:30:25 +02:00
Laurent Rineau bac2c06026 refactoring of cdt_3_from_off.cpp 2025-10-14 23:50:17 +02:00
Laurent Rineau 75c2ac5a68 bug-fix: use longest border polyline to compute the normal
fix bug of Thingi 1439534
2025-10-13 17:52:41 +02:00
Laurent Rineau b11e42c4a7 improve the assertion 2025-10-13 17:52:41 +02:00
Laurent Rineau 7d9dbdafcd WIP: copy-paste to merge the two implementation
TODO: extract a common function
2025-10-13 17:52:41 +02:00
Laurent Rineau 21df7dad86 fix a bug
fixes Thingi test cases 200695 and 822697
2025-10-13 17:52:09 +02:00
Laurent Rineau 4d3d2f4f03 simplify the code 2025-10-10 10:35:38 +02:00
Laurent Rineau 626675ea08 use the traits class 2025-10-10 10:33:46 +02:00
Laurent Rineau 71c2425b6e more debug 2025-10-10 10:33:27 +02:00
Laurent Rineau c26c013b5a reorganize some of the debugging code 2025-10-08 15:59:00 +02:00
Jane Tournois 2bde2295f4 fix location of start_point in construct_point_on_curve()
and add tons of assertions
2025-10-03 13:55:13 +02:00
Laurent Rineau 89393e1b7c improve the minifier for errors 2025-10-03 10:54:40 +02:00
Laurent Rineau ba10efcbe4 more runtime debug possibilities 2025-10-03 09:38:10 +02:00
Laurent Rineau 2a815ff510 add a label to the fdata sets segfaulting with --merge-facets 2025-10-03 09:37:02 +02:00
Laurent Rineau 8c150b865c remove completely the type traits `CGAL::is_complete_v<T>`
- its use would be undefined-behavior if `T` was later defined as complete,
- its implementation was undefined-behavior anyway, because `sizeof` cannot be used on incomplete types
2025-09-30 17:35:12 +02:00
Laurent Rineau d309bc89ce fix typo "and and" 2025-09-30 17:11:15 +02:00
Laurent Rineau f4aa383177 add new runtime debug flags 2025-09-30 12:49:02 +02:00
Jane Tournois 2c98528a97 avoid redefinition of Polyline 2025-09-29 11:32:53 +02:00
Jane Tournois 26130f161d fix API for Sizing_field_with_aabb_tree,
and deal with the case where distance < 0 in point_at(),
because we don't want to start from start_point all over
2025-09-26 15:19:18 +02:00
Jane Tournois 2d2773e4ed fix set_polyline_iterator() in insert_balls_on_edges()
the iterator we need is the one of p, not the one of `other_point`!

+ constify what can be
+ make loops more readable
2025-09-26 10:17:56 +02:00
Jane Tournois 2e15f13dc4 remove cout 2025-09-26 10:16:16 +02:00
Sebastien Loriot 93d3356dd9
Fix warning 2025-09-23 17:28:04 +02:00
Jane Tournois 389bb11390 fix point_at() for the loop case 2025-09-23 13:06:59 +02:00
Efi Fogel 9b3132a2cd Pacify MSVC (min/max issue) 2025-09-18 13:16:20 +03:00
Efi Fogel 05dd65609d Cleaned up; eliminate warnings 2025-09-16 14:41:21 +03:00
Efi Fogel 2e087bc108 Removed unused (formal) variables 2025-09-16 14:41:00 +03:00
Efi Fogel bd6a4ca392 Removed redundant using statement 2025-09-13 19:15:39 +03:00
Andreas Fabri 3988fe2009
Update Gps_on_surface_base_2.h (std::min)(..) 2025-09-12 17:15:07 +02:00
Efi Fogel 0f2aa39b62 Fixed template template use 2025-09-10 18:46:58 +03:00
Efi Fogel ba19fbd67d ops; fixed typo 2025-09-10 18:46:26 +03:00
Efi Fogel 65c797ab44 Fixed definition of template template parameter 2025-09-10 18:38:03 +03:00
Efi Fogel a9e0eeec8f Commented out formal unused variable 2025-09-10 18:36:08 +03:00
Efi Fogel dc422a7531 Removed unused variable (indent) 2025-09-10 18:35:49 +03:00
Efi Fogel e73cf18c12 Removed unused typedefs 2025-09-10 18:35:30 +03:00
Efi Fogel bc29da5ee3 Removed tab 2025-09-09 21:25:12 +03:00
Efi Fogel 1d62c37822 Added some notes to indicate that inexact constructions are tolerated for do_intersect() when applied to (linear) polygons 2025-09-07 00:28:11 +03:00
Efi Fogel 4a6d766d8c Just realized the my the visitor of the surface sweep has never been published, so changes to it are not concidered as breaking backward compatibilty 2025-09-06 20:56:06 +03:00
Efi Fogel f8c9340c1c Enhanced the comment about the optimization of `do_intersect()` of the 2D Regularized Boolean Set Operation package 2025-09-06 20:50:01 +03:00
Efi Fogel 5b6df813f5 Fixed do_intersect() and cleaned up 2025-09-06 20:41:49 +03:00
Jane Tournois 46d0d0799e use saved polyline_iterator everywhere
mesh_polyhedral_domain_with_features works fine with this version
2025-09-02 09:35:52 +02:00
Efi Fogel b871b81d57 Added a description of an optimization for the do_intersect() of the 2D Regularized Boolean Operation package 2025-09-01 15:34:57 +03:00
Efi Fogel 29715e44a4 Added an alternative divide & conquer for running do_intersect. 2025-08-30 20:47:31 +03:00
Efi Fogel f4a02aeaef Cleaned up 2025-08-30 20:46:42 +03:00
Jane Tournois dbcbff15fc use iterator for construct_point_on_curve() 2025-08-29 16:40:07 +02:00
Jane Tournois 17e3ee7189 use iterator in curve_segment_length()
add a special locate_corner() because we don't want to store
all incident polylines to a corner, and that it's only a few, cheap, locate operations
2025-08-29 15:24:35 +02:00
Jane Tournois c350da1ac7 make domain.construct_point_on_curve() return location on polyline
and use it in domain.curve_segment_is_covered()
2025-08-28 12:40:04 +02:00
Efi Fogel f69ad03ef8 Interception sweep for do_intersect() 2025-08-28 12:11:48 +03:00
Jane Tournois da2b0edcd1 cache polyline length and use it in loop case 2025-08-27 16:50:52 +02:00
Efi Fogel a366725c85 Enhanced and removed the UsePolylines tag from do_intersect() 2025-08-27 14:39:24 +03:00
Efi Fogel 1c45ed834c Cleaned up 2025-08-26 22:33:24 +03:00
Efi Fogel 375681748d Cleaned up 2025-08-26 22:30:48 +03:00
Efi Fogel 81bb832333 More clean ups 2025-08-26 22:04:00 +03:00
Efi Fogel a74945062c Cleaned up; replaced `typedef` with `using`, etc. 2025-08-26 21:58:34 +03:00
Efi Fogel e5049d4b03 Last touches and fixes for testing whether two polygons intersect 2025-08-26 14:55:53 +03:00
Efi Fogel 1bd923b393 Removed all tags related to polylines 2025-08-26 14:55:22 +03:00
Efi Fogel c677355de2 Removed printout 2025-08-26 14:55:14 +03:00
Efi Fogel 0f528545c7 Suppressed using Polyline with do_intersect() and fixed the do-intersect oberlay sweep-line visitor 2025-08-25 19:10:19 +03:00
Efi Fogel 35721db0b9 Cleaned up 2025-08-25 19:09:36 +03:00
Efi Fogel d41efe0330 Cleaned up 2025-08-25 19:09:21 +03:00
Efi Fogel bf1bc2fc85 Cleaned up 2025-08-25 16:43:17 +03:00
76 changed files with 8012 additions and 6278 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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