Compare commits

...

437 Commits

Author SHA1 Message Date
Camille Lanuel 84dbd555f3
Merge 21b63cf7a9 into 26a5fc70e4 2025-12-04 10:09:10 +01:00
Sébastien Loriot 26a5fc70e4 Merge remote-tracking branch 'cgal/6.1.x-branch' into 'cgal/main' 2025-12-03 11:54:47 +01:00
Sébastien Loriot 39dd7c5028 Merge remote-tracking branch 'cgal/6.0.x-branch' into 'cgal/6.1.x-branch' 2025-12-03 11:54:12 +01:00
Sebastien Loriot def6c38d76
Lab: Use Results to Avoid Warning (#9156)
## Summary of Changes

Check that `open()` worked to avoid warnings
[here](https://cgal.geometryfactory.com/CGAL/testsuite/CGAL-6.2-Ic-50/Lab_Demo/TestReport_cgaltest_ArchLinux-clang-CXX20-Release.gz).

## Release Management

* Affected package(s): Lab

* License and copyright ownership: unchanged
2025-12-03 11:52:48 +01:00
Andreas Fabri f503ce9359 Lab: use results 2025-12-03 11:51:43 +01:00
Sebastien Loriot be305f320f
[Small Feature] VTK IO support for Linear_cell_complex (#8998)
## Summary

This small feature adds the ability to read and write `.vtk` files
(legacy ASCII)
for 3D Linear_cell_complex (dimension 3, ambient dimension 3). 

It supports per-vertex and per-volume scalar fields and handles various
VTK cell types.

## Motivation

Enable import/export of mesh structures and scalar fields between CGAL
and VTK-based visualization tools
(ParaView, VisIt, etc.). Simplifies debugging and integration into
scientific pipelines.

## API Changes

- New functions in `Linear_cell_complex_vtk_io.h`:
  - `read_lcc_from_vtk()`
  - `write_lcc_to_vtk()`

Header-only implementation, no external dependency.

## Included

- Full implementation in `Linear_cell_complex_vtk_io.h` (merged `.impl`)
- Minimal example with `.3map` and `.vtk` files
- Unit test with scalar field preservation and structure comparison

## Maintainers

Feel free to suggest naming adjustments or style corrections. The
feature is scoped cleanly and does not affect other packages.


* Feature/Small Feature (if any):
[Read_write_vtk_for_LCC](https://cgalwiki.geometryfactory.com/CGAL/Members/wiki/Features/Small_Features/Read_write_vtk_for_LCC)
2025-12-03 11:50:01 +01:00
Sebastien Loriot b8db056348
Point_set: move IO code to Stream_support (#9109)
## Summary of Changes

Make `Point_set_3` independent from `Point_set_processing`. No API
changes and no changes in `#include` directories.

## Release Management

* Affected package(s):  Point_set, Point_set_processing, Stream_support
* Issue(s) solved (if any): fix #0000, fix #0000,...
* Feature/Small Feature (if any):
* 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: Some files change from GPL to LGPL,
so I hope @palliez is ok.
2025-12-03 11:49:27 +01:00
Sebastien Loriot 18ee149f2e
Aos 2 fixes efif (#9133)
## Summary of Changes

This addresses issue #9084. In particular, I replaced `Cartesian` with
`Simple_cartesian` in all traits.
I also defined Multiplicity to be `std::size_t` in all traits. In
addition, I replaced `typedef` with `using` and properly indented and
cleaned up the code in the source files I touched. I simplified the code
that approximates a point of the traits classes `Arr_linear_traits_2`,
`Arr_segment_traits_2`, and `Arr_non_caching_segment_basic_traits_2.h`.
I did not use the
[GAL::Cartesian_coverter](https://doc.cgal.org/latest/Kernel_23/classCGAL_1_1Cartesian__converter.html)
(mentioned in issue #9084) because the code is now simple as it is(just
one line in each traits class).

I also added a missing `inline` in draw_arrangement_2. This is unrelated
to the above.

## Release Management

* Affected package(s): Arrangement_on_surface_2
* Issue(s) solved (if any): fix #9084
* Feature/Small Feature (if any):
* 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-12-03 11:45:33 +01:00
Sebastien Loriot 15d96571a1
CDT3: Fix face_constraint_index() (#9155)
## Summary of Changes

Fix the function and add it in an example so that it gets tested.

## Release Management

* Affected package(s): Constraind_triangulation_3
* License and copyright ownership: unchanged
2025-12-03 11:37:59 +01:00
Sebastien Loriot 06996f077f
fix(Polygon_repair): Ensure WKT POLYGON are closed (#9148)
## Summary of Changes

Fix WKT polygon definitions to comply with OGC standards

  ### Problem
Several WKT files contained invalid polygon definitions where the first
and last coordinates did not match, violating the OGC Simple Features
specification, which requires polygon rings to be closed.

This caused errors when attempting to read these files with other
libraries like SFCGAL, even though CGAL's WKT method handles unclosed
polygons gracefully.

  ### Changes
- **examples/Polygon_repair/data/winding.wkt**: Added closing point (0
0)
  - **examples/Polygon_repair/data/flat.wkt**: Closed all 4 polygons
- **test/Polygon_repair/data/in/overlapping-edge-inside.wkt**: Closed
second polygon in MULTIPOLYGON

  ### Notes
- `test/Polygon_repair/data/in/not-closed.wkt` was intentionally left
unclosed as it serves as a test case for the repair algorithm
- These changes do not affect CGAL's test results, as the repair
algorithm produces identical output for both closed and unclosed input

## Release Management

* Affected package(s):
* Issue(s) solved (if any): fix #0000, fix #0000,...
* Feature/Small Feature (if any):
* 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:
2025-12-03 11:37:47 +01:00
Sebastien Loriot 5f8a8fe359
Periodic_3_triangulation_3: Fix warning in demo (#9147)
## Summary of Changes

Fix warning in
[CGAL-6.2-Ic-46](https://cgal.geometryfactory.com/CGAL/testsuite/CGAL-6.2-Ic-46/Periodic_3_triangulation_3_Demo/TestReport_cgaltest_Fedora-rawhide.gz)

## Release Management

* Affected package(s):  Periodic_3_triangulation_3

* License and copyright ownership:  unchanged
2025-12-03 11:37:34 +01:00
Andreas Fabri 543d424f58 Periodic_triangulation_3: Fix warning in demo 2025-12-03 11:36:14 +01:00
Laurent Rineau 8e3a59a27b simplify the code 2025-11-28 14:41:18 +01:00
Andreas Fabri 40ac746be7 CDT3: Fix face_constraint_index() 2025-11-27 13:54:50 +00:00
Efi Fogel 9d28892e5f Changed Approximate_curve_length_2 => Approximate_length_2, and added missing const 2025-11-26 16:48:30 +02: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
Andreas Fabri 92a896abb9 Fix anchor 2025-11-25 16:39:10 +00:00
Andreas Fabri 1b3556184a Fix warning in read_las_points.h 2025-11-25 07:35:10 +00: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
Guillaume Damiand fdf06fe969 add default parameter 2025-11-21 15:01:14 +01:00
Loïc Bartoletti c8099415d4 fix(Polygon_repair): Ensure WKT POLYGON are closed 2025-11-21 11:50: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
Andreas Fabri a0c32277d0 little doc fix in Frechet (not in extra PR) 2025-11-21 09:08:58 +00: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 884e9fc4ee Document a @param 2025-11-20 14:02:31 +00:00
Andreas Fabri cee9effe09 Document a @param 2025-11-20 13:56:43 +00:00
Sebastien Loriot eb14bf2a17
backticks and rephrasing
Co-authored-by: Mael <mael.rouxel.labbe@geometryfactory.com>
2025-11-20 13:23:26 +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
Andreas Fabri 970f16913b Merge remote-tracking branch 'cgal/main' into Point_set-reduce_dependencies-GF 2025-11-20 10:14:49 +00:00
Sébastien Loriot 583a8364c9 Merge remote-tracking branch 'cgal/6.1.x-branch' into 'cgal/main' 2025-11-20 10:29:11 +01:00
Sebastien Loriot 3ebe9203a7
Fix PMP on i386/i686 (32 bits, with the x87 FPU) (#8911)
## Summary of Changes

Fix PMP on i386/i686 (32 bits, with the x87 FPU).

## Release Management

* Affected package(s): PMP, Number_types
2025-11-20 10:28:31 +01:00
Sebastien Loriot bf25dd27b8
Stream support: Fix for Epeck (#9072)
## Summary of Changes

For file formats that expect floating point coordinates we convert on
the fly so that `CGAL::io::write_polygon_soup()` also works for polygon
soups with ` FT` which are non-float/double, e.g.
`Exact_predicates_exact_constructions_kernel`.
Additionally, we document the named parameter `point_map` as it was
missing.

## Release Management

* Affected package(s): Stream_support
* Issue(s) solved (if any): fix #9071
* License and copyright ownership: unchanged 
* upon integration update and test #9109
2025-11-20 10:27:33 +01:00
Sebastien Loriot 8ee288ee22
Spelling correction (#9144)
Spelling correction
2025-11-20 09:29:55 +01:00
albert-github e9fb73cadf Spelling correction
Spelling correction
2025-11-19 15:28:15 +01:00
Sébastien Loriot f98d968ed0 Merge remote-tracking branch 'cgal/6.1.x-branch' into 'cgal/main' 2025-11-19 14:46:33 +01:00
Sébastien Loriot 9bd1705bf8 Merge remote-tracking branch 'cgal/6.0.x-branch' into 'cgal/6.1.x-branch' 2025-11-19 14:45:21 +01:00
Sebastien Loriot 0fc710e95d
Fix bad 'if' condition & warning (#9126)
## Summary of Changes

```
Building CXX object test/Stream_support/CMakeFiles/issue8155.dir/issue8155.cpp.o
cd /home/cgal_tester/build/src/cmake/platforms/ArchLinux-clang-CXX20-Release/test/Stream_support && /bin/clang++ -DCGAL_DATA_DIR=\"/mnt/testsuite/data\" -DCGAL_TEST_SUITE=1 -DCGAL_USE_GMPXX=1 -I/home/cgal_tester/build/src/cmake/platforms/ArchLinux-clang-CXX20-Release/include -I/mnt/testsuite/include -isystem /usr/local/boost/include -Wall -O3 -std=c++20 -DCGAL_NDEBUG -MD -MT test/Stream_support/CMakeFiles/issue8155.dir/issue8155.cpp.o -MF CMakeFiles/issue8155.dir/issue8155.cpp.o.d -o CMakeFiles/issue8155.dir/issue8155.cpp.o -c /mnt/testsuite/test/Stream_support/issue8155.cpp
/mnt/testsuite/test/Stream_support/issue8155.cpp:27:17: warning: overlapping comparisons always evaluate to true [-Wtautological-overlap-compare]
   27 |     if (len > 0 || len != 1.0) {
      |         ~~~~~~~~^~~~~~~~~~~~~
1 warning generated.
```


https://cgal.geometryfactory.com/CGAL/testsuite/CGAL-6.2-Ic-36/Stream_support/TestReport_cgaltest_ArchLinux-clang-CXX20-Release.gz

## Release Management

* Affected package(s): `Stream_support`
* Issue(s) solved (if any): n/a
* Feature/Small Feature (if any): n/a
* License and copyright ownership: no change
2025-11-19 14:43:26 +01:00
Sebastien Loriot dee5ed8cc2
Fix edge collapse with incident non-triangular faces (#9117)
Make collapse able to handle non-triangular faces. The fix is easy as
you simply don't need to join faces in case the face won't disappear
after collapse

**TODO:**
update doc and constrained version
2025-11-19 14:42:28 +01:00
Sebastien Loriot 737bcb264e
Doc: fixing thirdparty links (#9134)
## Summary of Changes

fixed Metis/Eigen3/Qt6 links in Thirdparty
removed LEDA from doc as it is outdated

## Release Management

* Affected package(s): Documentation
2025-11-19 14:41:58 +01:00
Sebastien Loriot 2f9854b422
Fix warning about discarding return type of function with [[nodiscard]] (#9127)
## Summary of Changes

```
Building CXX object test/Generator_Demo/CMakeFiles/Generator_2.dir/Generator_2.cpp.o
cd /home/cgal_tester/build/src/cmake/platforms/ArchLinux-clang/test/Generator_Demo && /bin/clang++ -DCGAL_TEST_SUITE=1 -DCGAL_USE_GMPXX=1 -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NO_KEYWORDS -DQT_OPENGLWIDGETS_LIB -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -I/home/cgal_tester/build/src/cmake/platforms/ArchLinux-clang/test/Generator_Demo -I/mnt/testsuite/test/Generator_Demo -I/home/cgal_tester/build/src/cmake/platforms/ArchLinux-clang/include -I/mnt/testsuite/include -I/home/cgal_tester/build/src/cmake/platforms/ArchLinux-clang/test/AABB_tree_Demo -isystem /home/cgal_tester/build/src/cmake/platforms/ArchLinux-clang/test/Generator_Demo/Generator_2_autogen/include -isystem /usr/include/qt6/QtCore -isystem /usr/include/qt6 -isystem /usr/lib/qt6/mkspecs/linux-g++ -isystem /usr/include/qt6/QtOpenGLWidgets -isystem /usr/include/qt6/QtOpenGL -isystem /usr/include/qt6/QtGui -isystem /usr/include/qt6/QtWidgets -Wall  -fno-direct-access-external-data -MD -MT test/Generator_Demo/CMakeFiles/Generator_2.dir/Generator_2.cpp.o -MF CMakeFiles/Generator_2.dir/Generator_2.cpp.o.d -o CMakeFiles/Generator_2.dir/Generator_2.cpp.o -c /mnt/testsuite/test/Generator_Demo/Generator_2.cpp
In file included from /mnt/testsuite/test/Generator_Demo/Generator_2.cpp:27:
In file included from /mnt/testsuite/include/CGAL/Qt/DemosMainWindow.h:130:
/mnt/testsuite/include/CGAL/Qt/DemosMainWindow_impl.h:224:3: warning: ignoring return value of function declared with 'nodiscard' attribute [-Wunused-result]
  224 |   about_CGAL.open(QIODevice::ReadOnly);
      |   ^~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~
1 warning generated.
```


https://cgal.geometryfactory.com/CGAL/testsuite/CGAL-6.2-Ic-36/Generator_Demo/TestReport_gimeno_ArchLinux-clang.gz

## Release Management

* Affected package(s): `GraphicsView`
* Issue(s) solved (if any): n/a
* Feature/Small Feature (if any): n/a
* License and copyright ownership: no change
2025-11-19 14:41:07 +01:00
Sven Oesau e12a760f03 fixed Metis/Eigen3/Qt6 links in Thirdparty
removed LEDA from doc as it is outdated
2025-11-13 16:32:40 +01:00
Mael eb992b38ca
Fix missing I/O function links 2025-11-13 15:20:23 +01:00
Efi Fogel 3ccdc134fe Slightly simplified the code of Approximate_2::operator()(xcv...) 2025-11-13 15:10:17 +02:00
Laurent Rineau 1602be1348 precompiled demos for CGAL-6.1 2025-11-13 13:29:35 +01:00
Andreas Fabri ba17e0bdde cleanup an example 2025-11-13 11:05:26 +00:00
Laurent Rineau 12445cc6e1 revert unintended modification 2025-11-13 11:52:21 +01:00
Sébastien Loriot e7205b985d Merge remote-tracking branch 'cgal/6.1.x-branch' into 'cgal/main' 2025-11-13 10:42:42 +01:00
Sébastien Loriot 12a0f67674 Merge remote-tracking branch 'cgal/6.0.x-branch' into 'cgal/6.1.x-branch' 2025-11-13 10:41:53 +01:00
Efi Fogel 5812c1d6b5 Changed Cartesian to Simple_cartesian. Used size_t for Multiplicity. Properly indented and cleaned up. 2025-11-13 11:10:49 +02:00
Sebastien Loriot 07347da411
Fix Ceres deprecation warning (#9121)
## Summary of Changes

Changing the used cmake target for Ceres to Ceres::ceres.

## Release Management

* Affected package(s): Installation, Polygon_mesh_processing
2025-11-13 10:02:36 +01:00
Andreas Fabri 1dc39039e9 merge cgal/main 2025-11-13 08:48:43 +00:00
Sebastien Loriot 1673cd0f9e
Fix OBJ loader crashing the demo on reading failure (#9128)
## Release Management

* Affected package(s): `Lab`
* Issue(s) solved (if any): a few entries in #6690 
* Feature/Small Feature (if any): n/a
* License and copyright ownership: no change
2025-11-13 09:40:07 +01:00
Sebastien Loriot dfc5fb5065
IO: write_PLY() for Epeck (#7874)
## Summary of Changes

As reported in #7868 the function `CGAL::IO::write_PLY()` used in binary
mode does not correctly write the coordinates if the points are from a
kernel with exact constructions.
~~This PR applies `to_double()" to the coordinates.~~

~~After a discussion with @MaelRL we decided that the user is in charge
to pass a `vertex_point_map` as named parameter that does the
conversion. This is straightforward as we offer the
[`Cartesian_converter_property_map`](https://doc.cgal.org/latest/Property_map/structCGAL_1_1Cartesian__converter__property__map.html).~~

Moving back to the previous proposal: hardcode some to_double and
to_float casts such that we meet the requirements of the file format,
whatever the input.

As the problem is the same for the vertex normals we add a named
parameter `vertex_normal_map`.

### Todo
- [x] Fix the generic function `write_polygon_mesh()`. Currently it is
fixed for `Surface_mesh`

## Release Management

* Affected package(s): Stream_support
* Issue(s) solved (if any): fix #7868 and fix
https://github.com/CGAL/cgal/issues/7327
* License and copyright ownership:  unchanged
* upcoming integration, update #9072 and test it
2025-11-13 09:38:55 +01:00
Efi Fogel 48262b8068 Removed unnecessary include 2025-11-13 10:28:01 +02:00
Efi Fogel 24d3cd4bec Added missing inline 2025-11-13 09:33:58 +02:00
Laurent Rineau d226e504c4 fix a warning
use the correct implementation `popupAboutCGAL` from the base class
2025-11-12 16:48:59 +01:00
Laurent Rineau 097fc2c5ab fix memory leaks 2025-11-12 16:48:29 +01:00
Laurent Rineau c751ee6bc9 fix for AppleClang 2025-11-12 12:35:12 +01:00
Sébastien Loriot 066159f792 assertion should be before the removal... 2025-11-10 10:17:33 +01:00
Mael Rouxel-Labbé 333a15584f Handle (invalid) zero vertex index in face 2025-11-07 22:02:20 +01:00
Mael Rouxel-Labbé cd787c84d1 Use verbose OBJ reader in Lab 2025-11-07 22:02:08 +01:00
Mael Rouxel-Labbé 0ac856dd41 Fix OBJ loader crahsing the demo on reading failure 2025-11-07 21:00:12 +01:00
Mael Rouxel-Labbé 31734df2ef Fix warning about discarding return type of function with [[nodiscard]] 2025-11-07 17:16:31 +01:00
Mael Rouxel-Labbé 3ef43324bb Fix bad 'if' condition & warning 2025-11-07 17:05:21 +01:00
Sébastien Loriot 3c7d507530 update doc + apply changes to the constrained version 2025-11-06 19:40:48 +01:00
Guillaume Damiand 76552ccca1 class name 2025-11-06 18:16:43 +01:00
Guillaume Damiand 546d0b2871 verbs 2025-11-06 18:14:37 +01:00
Sébastien Loriot af94906903 leftover from Eigen5 update 2025-11-06 10:08:56 +01:00
Sébastien Loriot 3b0d95e0e5 Merge remote-tracking branch 'cgal/6.1.x-branch' into 'cgal/main' 2025-11-06 10:07:15 +01:00
Sven Oesau ffda347171 adding support for Eigen3 5.0.0 (6.1 version)
moving the Eigen3 version check into CGAL_Eigen3_support.cmake
2025-11-06 10:06:29 +01:00
Sébastien Loriot a9b369650a Merge remote-tracking branch 'cgal/6.0.x-branch' into 'cgal/6.1.x-branch' 2025-11-06 10:04:46 +01:00
Sebastien Loriot faae741666
Eigen3 5.0.0 support (#9112)
## Summary of Changes

Adding support for Eigen3 5.0.0 by updating CMakeLists.txt scripts.

## Release Management

* Issue(s) solved (if any): fix #9110
2025-11-06 10:03:20 +01:00
Sven Oesau 9e36c6744b adding support for Eigen3 5.0.0
moving the Eigen3 version check into CGAL_Eigen3_support.cmake
2025-11-06 10:01:01 +01:00
Guillaume Damiand 828d57a419
Update Combinatorial_map/include/CGAL/Combinatorial_map.h
Co-authored-by: Andreas Fabri <andreas.fabri@geometryfactory.com>
2025-11-06 09:45:20 +01:00
Guillaume Damiand 6f2c3d819e
Merge branch 'main' into Small_feature/read_write_vtk_for_LCC 2025-11-06 09:38:10 +01:00
Guillaume Damiand 459fcf3c3f adart -> d1 2025-11-05 20:46:02 +01:00
Guillaume Damiand 1c1245d5c0 update comments 2025-11-05 20:37:36 +01:00
Guillaume Damiand d1c66eaa0f formatting 2025-11-05 20:29:40 +01:00
Laurent Rineau c63a3d721e
Spelling correction (#9120)
Spelling correction
2025-11-05 11:12:08 +01:00
Sven Oesau 05bf3c4ffc Changing cmake target for Ceres 2025-11-04 17:04:58 +01:00
Sébastien Loriot 3569406da1 master -> main remaining 2025-11-04 11:32:32 +01:00
albert-github d3d5d4575a Spelling correction
Spelling correction
2025-11-04 11:15:57 +01:00
Sebastien Loriot 458e79bde8
master > main across scripts and documentation (#9076)
## Summary of Changes

TODO:
- [x] github wiki
([9d7282a](6ae93584f0...9d7282a43f))
- [x] cgal.org (https://github.com/CGAL/cgal-web/pull/75)
- [ ] testsuite plateforms
- [ ] gf.com

## Release Management

* Affected package(s): Various
* Issue(s) solved (if any): n/a
* Feature/Small Feature (if any): -
* License and copyright ownership: no change
2025-11-03 18:52:56 +01:00
Sebastien Loriot 8a136c50c9
CGAL: An Halfedge (#9119)
## Summary of Changes

Replace several "an"  by "a"

## Release Management

* Affected package(s):   global
* License and copyright ownership:  unchanged
2025-11-03 18:51:32 +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
Andreas Fabri 4b89f17b42 CGAL: An Halfedge 2025-11-03 14:37:50 +00:00
Sébastien Loriot 41ad794c39 Merge pull request #9069 from efifogel/gsoc2025-aos_demo-shepard
Gsoc2025 aos demo shepard
2025-11-03 13:56:29 +01:00
Sébastien Loriot 837939c8ee Merge pull request #9036 from efifogel/Aos_2-approximate_unbounded-efif
Aos 2 approximate unbounded efif
2025-11-03 09:43:25 +01:00
Sébastien Loriot 25005a97d8 clean up 2025-11-03 09:24:31 +01:00
Andreas Fabri 25844edf50 examples/tests/demo 2025-10-31 16:47:53 +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
Andreas Fabri 6bd5ec4f8b Move guards in low level file 2025-10-31 13:08:07 +01:00
Andreas Fabri eaa25c500b fix CI 2025-10-31 12:39:55 +01:00
Andreas Fabri 64e33bd6cb fix links 2025-10-31 12:25:24 +01:00
Sébastien Loriot 3fe83c7ce0 handle non-triangular faces 2025-10-31 11:36:44 +01:00
Andreas Fabri f28e643ed0 move read_points.h 2025-10-31 10:54:27 +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
Andreas Fabri 2d39ab4dd8 cleanup 2025-10-31 09:40:05 +01:00
Andreas Fabri 2fb9a2d832 doc links 2025-10-30 22:44:47 +01:00
Andreas Fabri 7c3b2302b5 doc links 2025-10-30 22:28:15 +01:00
Andreas Fabri 8b4e81ab5c doc links 2025-10-30 22:26:00 +01:00
Sébastien Loriot 20ae7dfc0d Merge remote-tracking branch 'cgal/6.1.x-branch' into 'cgal/main' 2025-10-30 20:24:05 +01:00
Sébastien Loriot b66ebf958b Merge remote-tracking branch 'cgal/6.0.x-branch' into 'cgal/6.1.x-branch' 2025-10-30 20:23:21 +01:00
Sebastien Loriot c60cc5049d
Workaround erros with recent gcc (#9105)
Should fix [those
errors](https://cgal.geometryfactory.com/CGAL/testsuite/CGAL-6.2-Ic-23/Stream_lines_2/TestReport_lrineau_Ubuntu-latest-GCC6-CXX1z.gz)
2025-10-30 20:17:22 +01:00
Sebastien Loriot 80b4d1a1be
Frechet Distance: Fix bugs in Lambda (#9103)
## Summary of Changes

_Describe what your pull request changes to CGAL (this can be skipped if
it solves an issue already in the tracker or if it is a Feature or Small
Feature submitted to the CGAL Wiki)._

## Release Management

* Affected package(s): Frechet Distance
* License and copyright ownership:  unchanged
2025-10-30 20:16:29 +01:00
Sébastien Loriot c882eab5b5 Merge pull request #9048 from LeoValque/SMS-slow_Garland-Heckbert
New line quadrics for Garland-Heckbert policies
2025-10-30 20:12:47 +01:00
Andreas Fabri 44306e981a doc 2025-10-30 18:11:15 +01:00
Andreas Fabri 25060734a0 forward declarations must come first 2025-10-30 17:46:45 +01:00
Andreas Fabri e70e2109f4 XYZ 2025-10-30 15:05:58 +01:00
Andreas Fabri fb748f6442 Move LAS 2025-10-30 14:51:26 +01:00
Andreas Fabri 622b652652 Add to BGL dependencies 2025-10-30 13:54:35 +01:00
Andreas Fabri 5050b54bfe robustify normal computation for STL 2025-10-30 12:03:22 +01:00
Andreas Fabri 35613b984f Deal with generic version 2025-10-30 11:45:28 +01:00
Andreas Fabri 00f5ae061d Use Simple_cartesian<Exact_rational> 2025-10-30 09:36:53 +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
Efi Fogel def7ea788f Merge branch 'gsoc2025-aos_demo-shepard' of github.com:efifogel/cgal into gsoc2025-aos_demo-shepard 2025-10-29 13:07:46 +02:00
Efi Fogel 8aaeff1a8e Pacify old clang (12); specifica pinstantiation of Arr_coordinate_converter 2025-10-29 13:05:18 +02:00
Sébastien Loriot dcaad3d140 add missing license include directives 2025-10-28 14:11:19 +01:00
Efi Fogel e1e41fd199 Removed unused variable 2025-10-28 14:22:56 +02:00
Andreas Fabri f766834601 Use CGAL_NP_TEMPLATE_PARAMETERS_NO_DEFAULT 2025-10-25 11:00:50 +01:00
Andreas Fabri 5e26465b2c fix 2025-10-25 10:28:36 +01:00
Andreas Fabri 67220b911b fix 2025-10-25 10:17:18 +01:00
Andreas Fabri 37b6a7214d R/W for points in OFF format is now in CGAL/IO/OFF.h 2025-10-25 09:58:21 +01:00
Efi Fogel cd04470eef Enabled compilation without Qt support 2025-10-25 11:02:45 +03:00
Efi Fogel d1afc52902 Cleaned up and removed unused variables and types 2025-10-25 10:52:25 +03:00
Andreas Fabri 592b8824ec Add forwarding include files 2025-10-24 15:49:55 +01:00
Efi Fogel a1b5cd58da Cleaned up and initialized m_left_on_boundary properly 2025-10-23 12:56:05 +03:00
Efi Fogel 5ed29f9173 Cleaned up; Pacify MSVC; suppressed warnings. 2025-10-23 12:11:31 +03:00
Andreas Fabri 7c9b9d1592 less dependencies 2025-10-23 09:47:05 +01:00
Efi Fogel 6314299598 Cleaned up; supress warnings 2025-10-23 11:06:32 +03:00
Andreas Fabri 6d011a62ae Point_set: move IO code to Stream_support 2025-10-23 08:52:04 +01:00
Efi Fogel f806219fc8 Merge branch 'Aos_2-approximate_unbounded-efif' into gsoc2025-aos_demo-shepard 2025-10-23 10:20:37 +03:00
Efi Fogel 8e11587719 Cleaned up 2025-10-23 10:00:43 +03:00
Efi Fogel 5df526f70c Fixed link to draw() 2025-10-23 09:25:49 +03:00
Efi Fogel d2b801937f Removed erroneous (CGAL) namespace 2025-10-23 09:24:43 +03:00
Efi Fogel 06e505520e Fixed link to draw() 2025-10-23 09:21:44 +03:00
Efi Fogel 909cbce367 Pacify MSVC (min/max issues) 2025-10-23 09:16:33 +03:00
Efi Fogel 8a3c77fc0d Fixed draw() links 2025-10-23 09:09:45 +03:00
Efi Fogel 58e7083445 Fixed link to draw() functions 2025-10-23 09:00:18 +03:00
Efi Fogel 8b6325b101 cleaned up 2025-10-23 09:00:02 +03:00
Efi Fogel 8e8ad1a824 Merge branch 'master' into Aos_2-approximate_unbounded-efif 2025-10-22 20:08:00 +03:00
Andreas Fabri 8623f28bb0 Use internal::construct_normal_of_STL_face() 2025-10-22 10:32:00 +01:00
Andreas Fabri 4c27d08372
Apply suggestions from code review
Co-authored-by: Mael <mael.rouxel.labbe@geometryfactory.com>
2025-10-22 11:17:31 +02:00
Andreas Fabri 4acccc210b Fix in doc of STL_extension 2025-10-21 18:11:12 +01:00
Sébastien Loriot 86122eaa00 fix conflict and invalid change 2025-10-21 18:37:22 +02:00
Sebastien Loriot adfcc7d102
more verbose 2025-10-21 18:08:22 +02:00
Andreas Fabri 5d82eed3ea
Update Stream_support/include/CGAL/IO/STL.h 2025-10-21 17:26:45 +02:00
Andreas Fabri c5b5a54952 cleanup 2025-10-21 16:22:02 +01:00
Andreas Fabri 5085762946 Fix return value 2025-10-21 16:22:02 +01:00
Andreas Fabri b3cb80760c Fix 2025-10-21 16:22:02 +01:00
Andreas Fabri 098e05e134 Add debug output 2025-10-21 16:22:02 +01:00
Andreas Fabri 4d6541c3c4 Add testcase that fails 2025-10-21 16:22:02 +01:00
Andreas Fabri 4ed4d096bf Add testcase that fails 2025-10-21 16:22:02 +01:00
Efi Fogel e7682069fe Introduced is_to_left() for points and used it to handle intersection spoints on the boundary 2025-10-21 14:49:42 +03:00
Efi Fogel 8730763d39 Restored preconditions 2025-10-21 14:49:19 +03:00
Efi Fogel 4d85bc3e63 Cleaned up 2025-10-21 14:49:00 +03:00
Sébastien Loriot 712464b690 try to please recent gcc 2025-10-21 08:26:34 +02:00
Laurent Rineau 7fe0100855 add other minified data sets from Thingi 2025-10-17 17:15:46 +02:00
lvalque c2e38c2070 Merge branch 'SMS-slow_Garland-Heckbert' of github.com:LeoValque/cgal into SMS-slow_Garland-Heckbert 2025-10-17 16:47:41 +02:00
lvalque 8ad92851a1 Replace Bounded_normal_change_placement per Bounded_normal_change_filter 2025-10-17 16:47:31 +02:00
Laurent Rineau e7ab5002a3 add the test non_manifold_face_graph.off 2025-10-17 16:31:14 +02:00
Andreas Fabri d9ba43a9ba Make it constexpr to avoid error in CI 2025-10-17 12:40:30 +01:00
Andreas Fabri 98a3051235 copy style 2025-10-17 10:48:26 +01: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
Andreas Fabri da011b2abe No longer #if 0 2025-10-17 10:43:33 +01:00
Andreas Fabri 3706528a0c
Update Stream_support/include/CGAL/IO/PLY/PLY_writer.h
Co-authored-by: Mael <mael.rouxel.labbe@geometryfactory.com>
2025-10-17 11:20:06 +02:00
Laurent Rineau 8746a29fa9 fix warnings about unused arguments or captures 2025-10-17 10:55:55 +02:00
Sebastien Loriot 878ba3fc53
suggestions from Mael
Co-authored-by: Mael <mael.rouxel.labbe@geometryfactory.com>
2025-10-17 10:28:57 +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
Andreas Fabri 62a9c9e04f cleanup 2025-10-15 16:23:59 +01:00
Sébastien Loriot 67349ccbe1 include for boost range 2025-10-15 16:49:15 +02:00
Laurent Rineau d7faad95dd factoring part of the code into a function 2025-10-15 16:30:25 +02:00
Sébastien Loriot 8215abd980 fix compilation and warnings 2025-10-15 09:57:32 +02:00
Laurent Rineau bac2c06026 refactoring of cdt_3_from_off.cpp 2025-10-14 23:50:17 +02:00
Andreas Fabri 358a588eae Deal with binary VTP for non-double kernel 2025-10-14 14:21:39 +01:00
Andreas Fabri c43058de26 Changes after Mael's comments 2025-10-14 09:24:44 +01: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
Guillaume Damiand f6425d7773 write error message only once 2025-10-11 14:57:17 +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
Guillaume Damiand 2ca338068b doc for read/write_vtk lcc in stream support 2025-10-10 10:22:11 +02:00
Guillaume Damiand e1ec2fd1d2 Document cmap read/write; and lcc read/write vtk 2025-10-10 09:55:12 +02:00
Guillaume Damiand ce1c890cb0 order of parameter for lcc vtk functions 2025-10-10 09:42:43 +02:00
Guillaume Damiand 8c84316796 doc for lcc vtk io 2025-10-09 18:57:19 +02:00
Guillaume Damiand ed6eb76670 spaces 2025-10-09 18:53:22 +02:00
Guillaume Damiand 66bb36e336 add example in lcc for write_vtk; add groups 2025-10-09 18:47:58 +02:00
Guillaume Damiand cd248c2638 Change order of parameters for lcc read/write vtk 2025-10-09 18:40:47 +02:00
Guillaume Damiand 1a03f8c6e1 update following Mael review 2025-10-09 17:32:55 +02:00
Mael 284df7125d
Remove trailing ws 2025-10-09 16:17:53 +02:00
Mael 3a350bf354
Apply suggestions from code review 2025-10-09 14:36:15 +02:00
Laurent Rineau c26c013b5a reorganize some of the debugging code 2025-10-08 15:59:00 +02:00
Sven Oesau 0ffa81d3c4 fix warnings 2025-10-08 13:36:35 +02:00
Andreas Fabri 865c1d2ed7 Fix error in test case 2025-10-06 13:05:32 +01:00
lvalque 0417a52217
Update Installation/CHANGES.md
Co-authored-by: Andreas Fabri <andreas.fabri@geometryfactory.com>
2025-10-06 13:50:44 +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
Sébastien Loriot 24024424ef use constexpr 2025-10-02 15:11:02 +02:00
lvalque d3c069a10d Replace -et al.- in doc due to Doxygen behaviour 2025-10-02 14:41:20 +02:00
lvalque ee1de0fdb9 Apply suggestions from review 2025-10-02 11:23:46 +02:00
Andreas Fabri 39531baac8 Use has_vnormal 2025-10-02 07:23:22 +01:00
lvalque bbc6238843 Apply review suggestions 2025-10-01 15:50:02 +02:00
Andreas Fabri 18f1f65bbf Fix plugin 2025-10-01 10:34:24 +01:00
Andreas Fabri 9a99df4a9d Comment static_assert 2025-10-01 09:38:38 +01:00
Andreas Fabri 737079e530 Fix warning 2025-10-01 09:15:54 +01:00
lvalque 68853c0f88 Update of GH bench with plane and line 2025-09-30 18:00:30 +02:00
lvalque 47099e5943 Correct anchor name 2025-09-30 17:41:13 +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
lvalque 38a644974d Link fig 2025-09-30 17:19:26 +02:00
lvalque 0e80f3e740 Correct doc errors 2025-09-30 17:13:46 +02:00
Laurent Rineau d309bc89ce fix typo "and and" 2025-09-30 17:11:15 +02:00
lvalque 3c482672aa Figure using octocat model of Thingi 2025-09-30 17:01:27 +02:00
lvalque e21cfa301d Update package description 2025-09-30 16:05:56 +02:00
Laurent Rineau f4aa383177 add new runtime debug flags 2025-09-30 12:49:02 +02:00
lvalque 90f9e19efe Update CHANGES.md accordin g to the previous commit 2025-09-30 10:35:50 +02:00
lvalque b2f5a21d0f Update doc of GH_plane_and_line 2025-09-30 10:22:03 +02:00
Andreas Fabri 0a743e6a1a Document named parameter verbose 2025-09-30 08:41:58 +01:00
Andreas Fabri 36b66946b8 after Mael's review 2025-09-30 08:30:55 +01:00
Andreas Fabri 89ba13f977 fix doxygen warning 2025-09-30 08:13:22 +01:00
Andreas Fabri 33bd58bbef fix doxygen warning 2025-09-30 06:47:14 +01:00
Andreas Fabri e652a7976a fix doxygen warning 2025-09-29 16:21:33 +01:00
Andreas Fabri 3be4ffce37 Fix plugin 2025-09-29 15:42:59 +01:00
Andreas Fabri 3567ba1456 Fix plugin 2025-09-29 15:08:02 +01:00
Andreas Fabri 806e65f259 undo 2025-09-29 15:05:47 +01:00
Andreas Fabri a9a60b5a00 Fix plugin 2025-09-29 15:01:00 +01:00
Andreas Fabri 92dc53c58a Undo change 2025-09-29 14:20:39 +01:00
Andreas Fabri b97c4b78c3 Convert on the fly to double 2025-09-29 13:55:26 +01:00
Efi Fogel 93d5fecf1c Suppress drawing when runing ctest 2025-09-28 09:16:12 +03:00
Andreas Fabri 5103fb4eb7 merge 2025-09-26 17:18:25 +01:00
Andreas Fabri fad48f7305 Fix dependencies 2025-09-26 17:00:05 +01:00
Andreas Fabri bdee2836df Fix dependencies 2025-09-26 16:16:27 +01:00
Andreas Fabri 39fe8b3a6d convert directly to Simple_cartesian<float> 2025-09-26 16:03:31 +01:00
Andreas Fabri 61cf55efee Convert internally to double as required by file format. Document the point property map which is implemented 2025-09-26 15:46:08 +01:00
Andreas Fabri 0cf9d434b6 Convert internally to double as required by file format. Document the point property map which is implemented 2025-09-26 15:22:32 +01:00
Sébastien Loriot f06f6b7dcf trailing whitespace 2025-09-23 19:46:27 +02:00
Sebastien Loriot 93d3356dd9
Fix warning 2025-09-23 17:28:04 +02:00
Mael Rouxel-Labbé 561ec37dc6 Remove extra space between NP entries 2025-09-22 11:53:21 +02:00
Mael Rouxel-Labbé 5c058a8c9b Fix missing \relates \ingroup for some property maps 2025-09-22 11:53:06 +02:00
Mael Rouxel-Labbé b668fb4b5a Fix grammar 2025-09-22 11:52:46 +02:00
Andreas Fabri d7cfaccfa1 Add Property_map to dependencies 2025-09-19 15:55:08 +01:00
Andreas Fabri 316c455034 Fix Default for the point_map type 2025-09-19 15:51:53 +01:00
Andreas Fabri 7d4852a60f trailing whitespace 2025-09-19 15:46:42 +01:00
Andreas Fabri 6c4aeabb9d Document the named parameter point_map and use it in the issue 2025-09-19 15:38:46 +01:00
Mael Rouxel-Labbé 6567d54ca3 master > main across scripts and documentation 2025-09-19 16:08:27 +02:00
Efi Fogel 2a8aa908fa Ops, missed a few min/max occurrences. 2025-09-19 09:53:34 +03:00
Efi Fogel 9b3132a2cd Pacify MSVC (min/max issue) 2025-09-18 13:16:20 +03:00
Efi Fogel 81e1650c78 Pacify MSVC (min/max issue) 2025-09-18 13:05:41 +03:00
Andreas Fabri 967aee62e9 Stream_support: Fix for Epeck 2025-09-18 09:19:19 +01:00
Efi Fogel 2046b32e80 Removed drawing until it is supported for rational curves 2025-09-17 11:07:04 +03:00
lvalque f09d4efc03 Missing new namedparameter changed of previous commit 2025-09-17 09:25:50 +02:00
Efi Fogel 0879232f8e Fixed drawing with a bounding box 2025-09-17 10:14:07 +03:00
Shepard Liu d297dd4e53 restore changes of cgal_test.cmake 2025-09-17 13:01:56 +08:00
Shepard Liu 8a026f7ec5 cleaned up unwanted changes 2025-09-17 12:52:07 +08: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
Shepard Liu f40f4a8629 compilation on windows & small bug fix 2025-09-16 11:04:04 +08:00
lvalque 5ebcf81952 Test NamedParameter of GH_plane_and_line_policies 2025-09-15 18:42:38 +02:00
lvalque 70ebce80ff Vertex normal map used as a function to avoid cascaded templating 2025-09-15 18:11:58 +02:00
Efi Fogel bd6a4ca392 Removed redundant using statement 2025-09-13 19:15:39 +03:00
lvalque 449ba102eb NamedParameter 2025-09-12 19:11:14 +02:00
Andreas Fabri 3988fe2009
Update Gps_on_surface_base_2.h (std::min)(..) 2025-09-12 17:15:07 +02:00
lvalque f56a295dd2 Extern VertexNormalMap can now be provided to GH_line_policies and normals are computed only one time 2025-09-12 10:56:29 +02:00
lvalque e1bfc585f7 correct indentation 2025-09-12 10:54:26 +02:00
lvalque 0b073d1249 Remove test_issue_8988 from test 2025-09-11 19:15:57 +02:00
lvalque c8110a71eb
Apply suggestions from code review
Co-authored-by: Mael <mael.rouxel.labbe@geometryfactory.com>
Co-authored-by: Andreas Fabri <andreas.fabri@geometryfactory.com>
2025-09-11 15:20:16 +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
lvalque 25aa21635a Comment unitialized argument and link eigen correctly 2025-09-10 14:33:18 +02:00
Efi Fogel bc29da5ee3 Removed tab 2025-09-09 21:25:12 +03:00
Efi Fogel a137e76807 Removed tabs 2025-09-09 21:23:00 +03:00
lvalque d99baac07f solved conflict 2025-09-09 11:01:38 +02:00
lvalque 8c94773841 dependancies and changes.md 2025-09-09 11:00:01 +02:00
Andreas Fabri 1fc69dc279
Update GarlandHeckbert_plane_and_line_policies.h
A brief description ends at a dot.
2025-09-09 09:48:16 +02:00
lvalque 74dd1678e4 Correct mistake in names of GarlandHeckbert doc 2025-09-09 09:24:01 +02:00
lvalque e2979aa0f2 Merge branch 'SMS-slow_Garland-Heckbert' of github.com:LeoValque/cgal into SMS-slow_Garland-Heckbert 2025-09-08 18:37:40 +02:00
lvalque d5f5b7b4f0 Add page of GH_plane_and_line_policies 2025-09-08 18:37:29 +02:00
lvalque fa724ed0ed
Apply suggestions from code review
Co-authored-by: Andreas Fabri <andreas.fabri@geometryfactory.com>
2025-09-08 18:14:57 +02:00
lvalque 82e9d4e5b9 rename plane_plus_line to plane_and_line 2025-09-08 18:10:25 +02:00
Guillaume Damiand 4d615a31b6 Cleanup 2025-09-08 13:06:42 +02:00
Guillaume Damiand 5a3dbda022 Test for read write vtk + data files 2025-09-08 12:30:48 +02:00
Efi Fogel 6a47eb77e4 Added missing examples 2025-09-07 16:28:04 +03:00
Efi Fogel e36f71e2a7 Ordered 2025-09-07 16:27:58 +03:00
Efi Fogel 55dcfcfb46 Fiex typo 2025-09-07 16:27:46 +03:00
Efi Fogel a9e46362aa Fixed link to draw() 2025-09-07 15:43:04 +03:00
Guillaume Damiand 876db072d8 LCC: compute topology of volumes 2025-09-07 10:02:14 +02:00
Guillaume Damiand 8ebeb13896 Creation of prisms and pyramids are now members of cmap and lcc 2025-09-07 09:57:36 +02:00
Guillaume Damiand f25a684c95 Read / write vtk for lcc 2025-09-07 09:55:49 +02:00
Guillaume Damiand 3382ac0d18 Example for LCC write vtk 2025-09-07 09:50:04 +02:00
Guillaume Damiand 707375e780 Add method to test some volume topology. 2025-09-07 09:34:49 +02: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
lvalque 2532df1eaf Remove unused variables 2025-09-05 10:28:17 +02:00
Guillaume Damiand f41b5b60f7 Add prisms and pyramids creation 2025-09-03 12:46:19 +02:00
lvalque f758f57b6a Remove unused assertion variable 2025-09-03 09:52:11 +02:00
lvalque 5c7abdd617 Documentation of plane_plus_line_policies 2025-09-02 18:35:15 +02:00
lvalque 32973ffa12 Add plane_plus_line in test of garlandheckbert 2025-09-01 17:39:39 +02:00
lvalque 883233d15d add test_issue_8988 in Surface_mesh_simplification 2025-09-01 16:56:38 +02:00
lvalque 708efa82b5 Update bench_garland_heckbert 2025-09-01 16:49:46 +02:00
lvalque 260af72d6e Clean and add commentary on an unkept modficiation 2025-09-01 16:35:50 +02:00
lvalque 294c3e0b88 Correct GH_policies.h and GH_plane_plus_line_policies.h that use policies that are now internal 2025-09-01 16:34:58 +02:00
lvalque 6a65d677e3 GH_composed_policies now able to take polcies as arguments and it and GH_line_policies now internal to CGAL 2025-09-01 16:31:32 +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
Efi Fogel f69ad03ef8 Interception sweep for do_intersect() 2025-08-28 12:11:48 +03: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
Efi Fogel 25b1f95449 Fixed a typo 2025-08-24 17:51:22 +03:00
Shepard Liu 0a3d8084ea fix typo guassian -> gaussian 2025-08-24 21:40:01 +08:00
Shepard Liu c9038d7c73 fixed drawing out of bounds triangles near polar & cleanup 2025-08-24 21:37:34 +08:00
Efi Fogel 556e6b9993 Removed erroneous CGAL:: (from CGAL::Approximate_...) 2025-08-22 14:09:19 +03:00
Efi Fogel dcf954f72a Updated concepts 2025-08-19 22:18:33 +03:00
Efi Fogel babe5e421a Updated concepts 2025-08-19 22:17:47 +03:00
Efi Fogel 20051d4e7e Enhanced 2025-08-19 22:08:41 +03:00
Efi Fogel 67f8c1f6e6 Enhanced 2025-08-19 22:07:47 +03:00
Efi Fogel 6dd570be9c Added missing include CGAL/Cartesian.h 2025-08-19 17:51:53 +03:00
Efi Fogel 6616a6a4e4 Added missing include CGAL/Cartesian.h 2025-08-19 17:49:54 +03:00
Efi Fogel 6eb52494c6 Guarded for unbounded faces 2025-08-19 17:46:08 +03:00
Efi Fogel 3b24522834 Add Approximate_2 2025-08-19 17:40:15 +03:00
Efi Fogel 30e041c966 Fixed typo in Bbox type 2025-08-19 17:40:03 +03:00
Efi Fogel d9766a2279 Enhanced the description of the draw() overloads 2025-08-19 17:39:50 +03:00
Efi Fogel beee32e945 Guard for unbounded faces 2025-08-19 17:38:37 +03:00
Efi Fogel 750b099594 Add Approximate_2 2025-08-19 17:34:35 +03:00
Efi Fogel 4157771db4 Fixed typo in Bbox type 2025-08-19 17:33:55 +03:00
Efi Fogel 33e2cd51d4 Enhanced the description of the draw() overloads 2025-08-18 22:37:34 +03:00
Efi Fogel 9092a603ce Added functionality to draw arrangements induced by unbounded curves 2025-08-18 16:08:20 +03:00
Efi Fogel e20cfc56b5 Introduced ApproximateUnbounded_2 concept 2025-08-18 16:00:06 +03:00
Efi Fogel 9a5280076a Added draw() overloads that accept a bounding box and fixed the Approximate_2 concept documentation 2025-08-18 15:59:56 +03:00
ybellargui cc19bd4a80 Refine VTK I/O example and test 2025-08-15 13:58:24 +02:00
Efi Fogel 3d56370164 Added functionality to draw arrangements induced by unbounded curves 2025-08-14 19:29:52 +03:00
Efi Fogel 39141d7dcf Merge branch 'gsoc2025-aos_demo-shepard' of github.com:CGAL/cgal-public-dev into gsoc2025-aos_demo-shepard 2025-08-14 18:31:11 +03:00
Efi Fogel dabe5675b6 Introduced ApproximateUnbounded_2 concept 2025-08-14 18:30:32 +03:00
Efi Fogel eca5afe6ee Added draw() overloads that accept a bounding box and fixed the Approximate_2 concept documentation 2025-08-14 17:58:18 +03:00
ybellargui 464c591b5a Add VTK I/O support for Linear_cell_complex with dual scalar types 2025-08-11 14:52:05 +02:00
Yliess Bellargui e0634c4ab1 Add VTK I/O support for Linear_cell_complex 2025-08-06 22:34:33 +02:00
lvalque 1a59d8cd3c benchmark for garland_heckbert policies 2025-08-06 16:48:41 +02:00
lvalque 029fb1b6b3 Add plane_plus_line_policies to GarlantHeckbert example 2025-08-06 16:40:17 +02:00
lvalque 7e4791ffb2 add GH_composed_policies 2025-08-06 10:49:27 +02:00
lvalque 96b1e77987 remove old code 2025-08-06 10:14:11 +02:00
lvalque 3413272070 add a function compute_quadrics_from_vertex in GH_policies_base 2025-08-06 10:00:11 +02:00
lvalque 7063e4e261 Quadrics line policies 2025-08-06 09:50:27 +02:00
Shepard Liu 7471dc847d feat: support drawing spherical faces 2025-08-05 21:34:44 +08:00
Yliess Bellargui c37745641a [Small Feature] Add VTK read/write support for Linear_cell_complex 2025-07-30 15:38:39 +02:00
Yliess Bellargui 09365799e9 [Small Feature] Add VTK IO support for Linear_cell_complex<3,3> 2025-07-30 15:38:39 +02:00
Shepard Liu b3657277d7 made initial bounding box more precise and added margin around the bbox 2025-07-24 17:14:27 +08:00
Shepard Liu fb9afae4ac more cleanups, align with code conventions and refactor
1
2025-07-23 19:28:56 +08:00
Efi Fogel 616931594a Cleaned up 2025-07-17 13:12:59 +03:00
Shepard Liu e70cf9fa17 bug fixes and support g++ 2025-07-14 22:24:40 +08:00
Shepard Liu 30b9a29ee9 Code cleanup and bug fixes 2025-07-13 13:40:08 +08:00
Laurent Rineau e187dc03cb fix 2025-07-02 15:45:22 +02:00
Efi Fogel 99aeb5f80a Pacify gcc and cleaned up 2025-07-02 16:36:47 +03:00
Shepard Liu ac7b7f62bd clean up deleted unit test target 2025-07-02 19:31:10 +08:00
Shepard Liu cd1951be26 fix drawing degenerate paths 2025-07-01 21:46:59 +08:00
Shepard Liu 3f90d36604 feat: draw function and classes for arrangement on surface 2
Now works for segment traits, linear traits and conic traits.
2025-06-30 15:43:27 +08:00
Sébastien Loriot ad20fa497a always declare a value you are using 2025-06-03 18:44:59 +02:00
Sebastien Loriot 4cfd48ba76
fix warning 2025-06-03 18:29:59 +02:00
Efi Fogel 094651581f Fixed dispatching 2025-05-29 18:18:49 +03:00
Efi Fogel 0ff050c414 Fixed dispatching 2025-05-28 18:29:22 +03:00
Efi Fogel 35f66f80b6 Improved dispatching 2025-05-28 16:15:58 +03:00
Efi Fogel 2caff8f2d8 More clean ups 2025-05-28 14:55:01 +03:00
Efi Fogel 559833c00b Merge branch 'master' into gsoc2025-aos_demo-shepard 2025-05-28 14:24:24 +03:00
Efi Fogel bdbe99276c Fixed indentation 2025-05-28 14:23:25 +03:00
Laurent Rineau b66c3743ec fix FPU_get_cw with CGAL_ALWAYS_ROUND_TO_NEAREST 2025-05-28 00:52:20 +02:00
Laurent Rineau 5b2887240c fix a precondition
with a 80 bits floating points, it can be wrong when
the two numbers are supposed to be equal.
2025-05-27 23:44:34 +02:00
Andreas Fabri 5171477b26 Fix tests 2024-06-17 15:57:38 +01:00
Andreas Fabri 05014378d6 Add doxygen 2024-06-11 15:50:21 +01:00
Andreas Fabri 0e27e7632c cleanup 2024-06-11 15:36:07 +01:00
Andreas Fabri 7ab9468594 typename 2024-06-11 14:24:03 +01:00
Andreas Fabri a316b67548 Merge remote-tracking branch 'cgal/master' into IO-read_PLY_Epeck-GF 2024-06-11 14:14:18 +01:00
Andreas Fabri ba87b5c2e5 typename 2024-06-11 14:10:56 +01:00
Andreas Fabri a08388c4e3 Also write normals in the generic code 2024-06-11 14:02:31 +01:00
Andreas Fabri 969062e3df Add the possibility to pass a vertex normal map 2024-06-11 13:15:04 +01:00
Mael Rouxel-Labbé cfcc90d649 Add extra lines to clarify that the blocks aren't related 2024-06-10 14:01:24 +02:00
Mael Rouxel-Labbé c5a688590a Test the write output 2024-06-10 14:01:24 +02:00
Mael Rouxel-Labbé 710666a51b Use the normal computation function that uses approximate_sqrt
As to be able to write even for kernels that do not offer sqrt
2024-06-10 14:01:24 +02:00
Andreas Fabri c58286d716 Add #include 2024-06-07 15:30:25 +01:00
Andreas Fabri 6cba601ff3 WIP just to get it working 2024-06-07 15:06:37 +01:00
Andreas Fabri fe86a79bdc Fix the test 2024-06-07 09:01:29 +01:00
Andreas Fabri 7a984104fa Add code that shows the issue 2024-06-07 08:43:36 +01:00
Sébastien Loriot d876fbab69 add missing include 2023-11-22 15:21:04 +01:00
Andreas Fabri 5eb93449c5 Fix ascii output 2023-11-22 08:37:13 +00:00
Andreas Fabri 40dee7d2a0 whitespace 2023-11-20 14:04:56 +00:00
Andreas Fabri 2d72f21107 IO: read_PLY() for Epeck 2023-11-20 13:09:59 +00:00
412 changed files with 23837 additions and 12859 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

@ -164,7 +164,7 @@ jobs:
wget --no-verbose cgal.github.io -O index.html
if ! egrep -qF "/$PR_NUMBER/$ROUND" index.html || [ "$force" = "yes" ]; then
#list impacted packages
LIST_OF_PKGS=$(git diff --name-only origin/master...HEAD |cut -s -d/ -f1 |sort -u | xargs -I {} echo {} && ls -d {}/package_info 2>/dev/null |cut -d/ -f1 |egrep -v Installation||true)
LIST_OF_PKGS=$(git diff --name-only origin/main...HEAD |cut -s -d/ -f1 |sort -u | xargs -I {} echo {} && ls -d {}/package_info 2>/dev/null |cut -d/ -f1 |egrep -v Installation||true)
if [ "$LIST_OF_PKGS" = "" ]; then
echo "DoxygenError=No package affected." >> $GITHUB_OUTPUT
exit 1

View File

@ -221,7 +221,7 @@ a visible circle through an iterator called
`ApolloniusGraphVertexBase_2` concept and is implemented by its
model, the `Apollonius_graph_vertex_base_2<Gt,StoreHidden>`
class. It is also possible to iterate through the entire set of hidden
sites using an homonymous iterator defined by the
sites using a homonymous iterator defined by the
`Apollonius_graph_2<Gt,Agds>` class.
Since storing hidden sites may not be of interest in some cases (e.g.,

View File

@ -56,7 +56,7 @@ public:
/// @{
/*!
Creates an hierarchy of Apollonius graphs using `gt` as
Creates a hierarchy of Apollonius graphs using `gt` as
geometric traits.
*/
Apollonius_graph_hierarchy_2(Gt gt=Gt());

View File

@ -4890,7 +4890,7 @@ using Arrangement = CGAL::Arrangement_2<Traits>;
<!-- ----------------------------------------------------------------------- -->
\cgalFigureBegin{aos_fig-conic_multiplicities,conic_multiplicities.png}
An arrangement of a circular arc and an hyperbolic arc, as constructed
An arrangement of a circular arc and a hyperbolic arc, as constructed
in \ref Arrangement_on_surface_2/conic_multiplicities.cpp.
\cgalFigureEnd
<!-- ----------------------------------------------------------------------- -->
@ -6841,9 +6841,9 @@ arrangement-with-history from a file:
\cgalExample{Arrangement_on_surface_2/io_curve_history.cpp}
\cgalAdvancedBegin
The arrangement package also includes the free functions `write(arr,
os, formatter)` and `read(arr, os, formatter)` that operate on a given
arrangement-with-history instance `arr`. Both functions are
The arrangement package also includes the free functions
`write(arr, os, formatter)` and `read(arr, os, formatter)` that operate
on a given arrangement-with-history instance `arr`. Both functions are
parameterized by a `formatter` object, which defines the I/O
format. The package contains a template called,
`Arr_with_hist_text_formatter<ArranagmentFormatter>`, which extends an
@ -6855,12 +6855,24 @@ and defines a simple textual input/output format.
\subsection arr_ssecarr_io_vis Drawing an Arrangement
<!-- ----------------------------------------------------------------------- -->
An arrangement data structure can be visualized by calling the \link PkgArrangementOnSurface2Draw CGAL::draw<arr>() \endlink function as shown in the following example. This function opens a new window showing the given arrangement. A call to this function is blocking; that is, the program continues execution only after the user closes the window.
An arrangement data structure can be visualized by calling one of the
\link PkgArrangementOnSurface2Draw `CGAL::draw()` \endlink
overloaded template functions. Every variant opens a new window
showing the given arrangement. A call to any \link
PkgArrangementOnSurface2Draw `CGAL::draw()` \endlink function is
blocking; that is, the program continues execution only after the user
closes the window. The most simple variant accepts the arrangement to
draw and an optional string used as the title of the window. In the
following example we exploit a variant that also accepts an object the
type of which is an instance of the class template
`Graphics_scene_options`. It allows us to tune the drawings.
\cgalExample{Arrangement_on_surface_2/draw_arr.cpp}
This function requires `CGAL_Qt6`, and is only available if the macro `CGAL_USE_BASIC_VIEWER` is defined.
Linking with the cmake target `CGAL::CGAL_Basic_viewer` will link with `CGAL_Qt6` and add the definition `CGAL_USE_BASIC_VIEWER`.
This function requires `CGAL_Qt6`, and is only available if the macro
`CGAL_USE_BASIC_VIEWER` is defined. Linking with the cmake target
`CGAL::CGAL_Basic_viewer` will link with `CGAL_Qt6` and add the
definition `CGAL_USE_BASIC_VIEWER`.
\cgalFigureBegin{aos_fig-draw_arr,draw_arr.png}
A snapshot of the window created by the program
@ -6868,6 +6880,10 @@ A snapshot of the window created by the program
of 14 vertices, 15 edges, and 3 faces. Notice that the colors are generated at random.
\cgalFigureEnd
Another pair of overloaded \link PkgArrangementOnSurface2Draw
`CGAL::draw()` \endlink functions also accept a bounding box. Each
of these two variants can be ised to draw arrangements induced by
unbounded curves.
<!-- ======================================================================= -->
\section aos_sec-bgl Adapting to Boost Graphs

View File

@ -32,7 +32,7 @@ namespace CGAL {
* same direction as a precondition. Moreover, `Arr_circle_segment_traits_2`
* supports the merging of curves of opposite directions.
*
* \cgalModels{AosTraits_2,AosApproximateTraits_2,AosDirectionalXMonotoneTraits_2}
* \cgalModels{AosTraits_2,AosApproximateTraits_2,AosApproximatePointTraits_2,AosDirectionalXMonotoneTraits_2}
*
*/
template <typename Kernel>

View File

@ -80,7 +80,7 @@ namespace CGAL {
* to have the same direction as a precondition. Moreover, `Arr_conic_traits_2`
* supports the merging of curves of opposite directions.
*
* \cgalModels{AosTraits_2,AosLandmarkTraits_2,AosApproximateTraits_2,AosDirectionalXMonotoneTraits_2}
* \cgalModels{AosTraits_2,AosLandmarkTraits_2,AosApproximateTraits_2,AosApproximatePointTraits_2,AosDirectionalXMonotoneTraits_2}
*
* \cgalHeading{Types}
*/

View File

@ -21,7 +21,7 @@ namespace CGAL {
* we can find out its actual type and convert it to the respective kernel
* object (say, to a `Kernel::Ray_2`).
*
* \cgalModels{AosTraits_2,AosLandmarkTraits_2,AosOpenBoundaryTraits_2}
* \cgalModels{AosTraits_2,AosLandmarkTraits_2,AosOpenBoundaryTraits_2,AosApproximatePointTraits_2,AosApproximateTraits_2,AosApproximateUnboundedTraits_2}
*/
template <typename Kernel>
class Arr_linear_traits_2 {

View File

@ -3,9 +3,8 @@ namespace CGAL {
/*! \ingroup PkgArrangementOnSurface2Ref
*
* `Arr_observer<Arrangement_2>` is an alias for
* `Aos_observer<Arrangement_on_surface_2>`,
* where `Arrangement_2` derives from `Arrangement_on_surface_2` and the latter
* is an instance of the template
* `Aos_observer<Arrangement_on_surface_2>`, where `Arrangement_2` derives from
* `Arrangement_on_surface_2` and the latter is an instance of the template
* `CGAL::Arrangement_on_surface_2<GeometryTraits, TopologyTraits>`.
*/

View File

@ -52,7 +52,7 @@ namespace CGAL {
* same direction as a precondition. Moreover, `Arr_segment_traits_2` supports
* the merging of curves of opposite directions.
*
* \cgalModels{AosTraits_2,AosLandmarkTraits_2,AosApproximateTraits_2,AosDirectionalXMonotoneTraits_2}
* \cgalModels{AosTraits_2,AosLandmarkTraits_2,AosApproximateTraits_2,AosApproximatePointTraits_2,AosDirectionalXMonotoneTraits_2}
*/
template <typename Kernel>
class Arr_segment_traits_2 : public Kernel {

View File

@ -19,6 +19,8 @@
#include <CGAL/Qt/Basic_viewer.h>
#include "CGAL/Bbox_2.h"
#ifdef DOXYGEN_RUNNING
namespace CGAL {
@ -26,8 +28,8 @@ namespace CGAL {
/*! \ingroup PkgArrangementOnSurface2Draw
* The function opens a new window and draws `arr`, an instance of the
* `CGAL::Arrangement_2` class template. Parameters of the drawing are taken
* from the optional graphics scene options parameter.
* `CGAL::Arrangement_on_surface_2` class template. Parameters of the drawing
* are taken from the optional graphics scene options parameter.
*
* A call to this function blocks the execution of the program until the drawing
* window is closed. This function requires `CGAL_Qt6`, and is only available if
@ -35,57 +37,64 @@ namespace CGAL {
* `CGAL::CGAL_Basic_viewer` will link with `CGAL_Qt6` and add the definition
* `CGAL_USE_BASIC_VIEWER`.
*
* \tparam GeometryTraits_2 a geometry traits type, a model of a 2D arrangement
* traits concept. At this point it must be an instance of either
* `CGAL::Arr_segment_traits_2` or `CGAL::Arr_conic_traits_2`.
* \tparam Dcel the \dcel type, a model of the `AosDcel` concept.
* \tparam GeometryTraits a geometry traits type, a model of a 2D arrangement
* geometry traits concept. Observe that not all geometery-traits models are
* supported.
*
* \tparam TopologyTraits a topology traits type, a model of the
* `AosTopologyTraits` concept.
*
* \tparam GSOptions a model of `GraphicsSceneOptions` concept.
*
* \param arr the 2D arrangement to draw.
* \param gso the graphics scene options parameter.
* \param bbox a bounding box in parameter space.
* \param gso the graphics scene options.
* \param title the optional title of the window.
*
* \sa `AosDcel`
* \sa `AosTraits_2`
* \sa `AosTopologyTraits`
* \sa `GraphicsSceneOptions`
*/
template <typename GeometryTraits_2, typename Dcel, typename GSOptions>
void draw(const Arrangement_2<GeometryTraits_2, Dcel>& arr,
const GSOptions& gso);
template <typename GeometryTraits, typename TopologyTraits>
void draw(const Arrangement_on_surface_2<GeometryTraits, TopologyTraits>& arr,
const Bbox_2& bbox, const GSOptions& gso,
const char* title = "2D Arrangement on Surface");
/*! \ingroup PkgArrangementOnSurface2Draw
*
* A shortcut to `CGAL::draw(arr, Graphics_scene_options{})`.
* A shortcut to `CGAL::draw(arr, bbox, Graphics_scene_options<Aos,
* Aos::Vertex_const_handle, Aos::Halfedge_const_handle,
* Aos::Face_const_handle>{})`, where `Aos` is
* `Arrangement_on_surface_2<GeometryTraits, TopologyTraits>`.
*/
template <typename GeometryTraits_2, typename Dcel>
void draw(const Arrangement_2<GeometryTraits_2, Dcel>& arr);
template <typename GeometryTraits, typename TopologyTraits>
void draw(const Arrangement_on_surface_2<GeometryTraits, TopologyTraits>& arr,
const Bbox_2& bbox, const char* title = "2D Arrangement on Surface");
/*! \ingroup PkgArrangementOnSurface2Draw
*
* adds the vertices, edges and faces of `arr` into the given graphic scene
* `gs`. Parameters of the cells are taken from the optional graphics scene
* options parameter `gso`. Note that `gs` is not cleared before being filled
* (to enable to draw several data structures in the same basic viewer).
*
* \tparam GeometryTraits_2 a geometry traits type, a model of a 2D arrangement
* traits concept. At this point it must be an instance of either
* `CGAL::Arr_segment_traits_2` or `CGAL::Arr_conic_traits_2`.
* \tparam Dcel the \dcel type, a model of the `AosDcel` concept.
* \tparam GSOptions a model of `GraphicsSceneOptions` concept.
*
* \param arr the 2D arrangement to draw.
* \param gs the graphic scene to fill.
* \param gso the graphics scene options parameter.
* Similar to `CGAL::draw(arr, bbox, gso)`, where the bounding box `bbox` is
* computed to bound all points and curves of the arrangement in parameter
* space.
*/
template <typename GeometryTraits_2, typename Dcel, typename GSOptions>
void add_to_graphics_scene(const Arrangement_2<GeometryTraits_2, Dcel>& arr,
CGAL::Graphics_scene& gs, const GSOptions& gso);
template <typename GeometryTraits, typename TopologyTraits>
void draw(const Arrangement_on_surface_2<GeometryTraits, TopologyTraits>& arr,
const GSOptions& gso, const char* title = "2D Arrangement on Surface");
/*! \ingroup PkgArrangementOnSurface2Draw
* A shortcut to `CGAL::add_to_graphics_scene(arr, gs,
* Graphics_scene_options{})`.
*
* A shortcut to `CGAL::draw(arr, Graphics_scene_options<Aos,
* Aos::Vertex_const_handle, Aos::Halfedge_const_handle,
* Aos::Face_const_handle>{})`, where `Aos` is
* `Arrangement_on_surface_2<GeometryTraits, TopologyTraits>`.
*/
template <typename GeometryTraits_2, typename Dcel>
void add_to_graphics_scene(const Arrangement_2<GeometryTraits_2, Dcel>& arr,
CGAL::Graphics_scene& gs);
template <typename GeometryTraits, typename TopologyTraits>
void draw(const Arrangement_on_surface_2<GeometryTraits, TopologyTraits>& arr,
const char* title = "2D Arrangement on Surface");
} /* namespace CGAL */

View File

@ -18,8 +18,6 @@
* \cgalHasModels{CGAL::Arr_rational_function_traits_2<AlgebraicKernel_d_1>}
* \cgalHasModelsEnd
*
* \sa `AosConstructXMonotoneCurveTraits_2`
* \sa `AosXMonotoneTraits_2`
* \sa `AosTraits_2`
*/
class AosApproximatePointTraits_2 {
@ -35,7 +33,7 @@ public:
/// \name Functor Types
/// @{
/// models the concept `AosTraits::Approximate_2`.
/// models the concept `AosTraits::ApproximatePoint_2`.
typedef unspecified_type Approximate_2;
/// @}

View File

@ -17,7 +17,9 @@
* \cgalHasModelsEnd
*
* \sa `AosApproximatePointTraits_2`
* \sa `draw()`
* \sa `AosConstructXMonotoneCurveTraits_2`
* \sa `AosXMonotoneTraits_2`
* \sa \link PkgArrangementOnSurface2Draw `CGAL::draw()`\endlink
*/
class AosApproximateTraits_2 {
public:

View File

@ -0,0 +1,40 @@
/*! \ingroup PkgArrangementOnSurface2ConceptsTraits
* \cgalConcept
*
* The concept `AosApproximateUnboundedTraits_2` refines the concept
* `AosApproximateTraits_2`. A model of this concept is able to approximate a
* curve constrained to a given bounding box (in addition to the ability to
* approximate a point and a curve without constraints).
*
* \cgalRefines{AosApproximateTraits_2}
*
* \cgalHasModelsBegin
* \cgalHasModels{CGAL::Arr_linear_traits_2<Kernel>}
* \cgalHasModelsEnd
*
* \sa `AosApproximateTraits_2`
* \sa \link PkgArrangementOnSurface2Draw `CGAL::draw()`\endlink
*/
class AosApproximateUnboundedTraits_2 {
public:
/// \name Types
/// @{
/// @}
/// \name Functor Types
/// @{
/// models the concept `AosTraits::ApproximateUnbounded_2`.
typedef unspecified_type Approximate_2;
/// @}
/// \name Accessing Functor Objects
/// @{
///
Approximate_2 approximate_2_object() const;
/// @}
}

View File

@ -0,0 +1,28 @@
namespace AosTraits {
/*! \ingroup PkgArrangementOnSurface2ConceptsFunctionObjects
* \cgalConcept
*
* \cgalRefines{Functor}
*
* \cgalHasModelsBegin
* \cgalHasModels{AosApproximatePointTraits_2::Approximate_2}
* \cgalHasModels{AosApproximateTraits_2::Approximate_2}
* \cgalHasModelsEnd
*/
class ApproximatePoint_2 {
public:
/// \name Operations
/// A model of this concept must provide:
/// @{
/*! obtains an approximation of `p`'s \f$x\f$-coordinate (if `i == 0`), or of
* `p`'s \f$y\f$-coordinate (if `i == 1`).
* \pre `i` is either 0 or 1.
*/
Approximate_number_type operator()(AosTraits::Point_2 p, int i);
/// @}
}; /* end AosTraits::Approximate_2 */
}

View File

@ -0,0 +1,49 @@
namespace AosTraits {
/*! \ingroup PkgArrangementOnSurface2ConceptsFunctionObjects
* \cgalConcept
*
* \cgalRefines{Approximate_2}
*
* \cgalHasModelsBegin
* \cgalHasModels{AosApproximatePointTraits_2::Approximate_2}
* \cgalHasModels{AosApproximateTraits_2::Approximate_2}
* \cgalHasModels{AosApproximateUnboundedTraits_2::Approximate_2}
* \cgalHasModelsEnd
*/
class ApproximateUnbounded_2 {
public:
/// \name Operations
/// A model of this concept must provide:
/// @{
/*! approximates a given \f$x\f$-monotone curve constrained to a bounding
* box. It computes one or more sequences of approximate points that represent
* the disconnected portions of a polyline that approximates `xcv` within the
* bounding box `bbox`, and inserts them into output containers given through
* the output iterator `oi`. The first point of the first sequence and the
* last point of the last sequence are always approximations of the endpoints
* of the given curve.
*
* \param xcv The exact \f$x\f$-monotone curve.
* \param error The error bound of the polyline approximation. This is the
* Hausdorff distance between the curve and the polyline that
* approximates the curve.
* \param oi An output iterator for the output containers.
* \param bbox the bounding box.
* \param l2r A Boolean flag that indicates whether the curve direction is
* left to right.
* \return The past-the-end iterator of the output container.
*
* \pre Dereferencing `oi` must yield an object the type of which is a
* container, where the value type of this container is
* `AosApproximateTraits_2::Approximate_point_2`.
*/
template <typename OutputIterator>
OutputIterator operator()(const X_monotone_curve_2& xcv, double error, OutputIterator oi,
const Bbox_2& bbox, bool l2r = true) const;
/// @}
}; /* end AosTraits::Approximate_2 */
}

View File

@ -3,7 +3,7 @@ namespace AosTraits {
/*! \ingroup PkgArrangementOnSurface2ConceptsFunctionObjects
* \cgalConcept
*
* \cgalRefines{Functor}
* \cgalRefines{ApproximatePoint_2}
*
* \cgalHasModelsBegin
* \cgalHasModels{AosApproximatePointTraits_2::Approximate_2}
@ -16,15 +16,9 @@ public:
/// A model of this concept must provide:
/// @{
/*! obtains an approximation of `p`'s \f$x\f$-coordinate (if `i == 0`), or of
* `p`'s \f$y\f$-coordinate (if `i == 1`).
* \pre `i` is either 0 or 1.
*/
CGAL::Approximate_number_type operator()(AosTraits::Point_2 p, int i);
/*! obtains an approximation of `p`.
*/
CGAL::Approximate_point_2 operator()(AosTraits::Point_2 p);
Approximate_point_2 operator()(AosTraits::Point_2 p);
/*! approximates a given \f$x\f$-monotone curve. It computes a sequence of
* approximate points that represent an approximate polyline, and inserts
@ -42,7 +36,7 @@ public:
* \return The past-the-end iterator of the output container.
*
* \pre Dereferencing `oi` must yield an object of type
* `Arr_conic_traits_2::Approximate_point_2`.
* `AosApproximateTraits_2::Approximate_point_2`.
*/
template <typename OutputIterator>
OutputIterator operator()(const X_monotone_curve_2& xcv, double error,

View File

@ -136,7 +136,7 @@ public:
/// \name Face Creation
/// The following function is invoked whenever a new face is
/// created. It is guaranteed that all halfedges along the face
/// boundary have already been created an have their auxiliary data
/// boundary have already been created and have their auxiliary data
/// fields attached to them:
/// @{

View File

@ -113,6 +113,7 @@ implemented as peripheral classes or as free (global) functions.
- `AosApproximateTraits_2`
- `AosApproximatePointTraits_2`
- `AosApproximateUnboundedTraits_2`
- `AosBasicTopologyTraits`
- `AosBasicTraits_2`
- `AosBottomSideTraits_2`
@ -167,6 +168,8 @@ implemented as peripheral classes or as free (global) functions.
\cgalCRPSection{Function Object Concepts}
- `AosTraits::Approximate_2`
- `AosTraits::ApproximatePoint_2`
- `AosTraits::ApproximateUnbounded_2`
- `AosTraits::AreMergeable_2`
- `AosTraits::CompareX_2`
- `AosTraits::CompareXy_2`
@ -262,6 +265,6 @@ implemented as peripheral classes or as free (global) functions.
- \link PkgArrangementOnSurface2op_right_shift `CGAL::operator<<` \endlink
\cgalCRPSection{Draw an `Arrangemen_2` object}
- \link PkgArrangementOnSurface2Draw CGAL::draw<>() \endlink
- \link PkgArrangementOnSurface2Draw CGAL::draw<>() \endlink
*/

View File

@ -1,52 +1,59 @@
/*!
\example Arrangement_on_surface_2/aggregated_insertion.cpp
\example Arrangement_on_surface_2/algebraic_curves.cpp
\example Arrangement_on_surface_2/algebraic_segments.cpp
\example Arrangement_on_surface_2/batched_point_location.cpp
\example Arrangement_on_surface_2/Bezier_curves.cpp
\example Arrangement_on_surface_2/bgl_dual_adapter.cpp
\example Arrangement_on_surface_2/bgl_primal_adapter.cpp
\example Arrangement_on_surface_2/bounded_vertical_decomposition.cpp
\example Arrangement_on_surface_2/circles.cpp
\example Arrangement_on_surface_2/circular_arcs.cpp
\example Arrangement_on_surface_2/conics.cpp
\example Arrangement_on_surface_2/conic_multiplicities.cpp
\example Arrangement_on_surface_2/consolidated_curve_data.cpp
\example Arrangement_on_surface_2/count_and_trace.cpp
\example Arrangement_on_surface_2/curve_history.cpp
\example Arrangement_on_surface_2/dcel_extension.cpp
\example Arrangement_on_surface_2/dcel_extension_io.cpp
\example Arrangement_on_surface_2/dual_lines.cpp
\example Arrangement_on_surface_2/dual_with_data.cpp
\example Arrangement_on_surface_2/edge_insertion.cpp
\example Arrangement_on_surface_2/edge_manipulation.cpp
\example Arrangement_on_surface_2/edge_manipulation_curve_history.cpp
\example Arrangement_on_surface_2/face_extension.cpp
\example Arrangement_on_surface_2/face_extension_overlay.cpp
\example Arrangement_on_surface_2/generic_curve_data.cpp
\example Arrangement_on_surface_2/global_insertion.cpp
\example Arrangement_on_surface_2/global_removal.cpp
\example Arrangement_on_surface_2/incremental_insertion.cpp
\example Arrangement_on_surface_2/io.cpp
\example Arrangement_on_surface_2/io_curve_history.cpp
\example Arrangement_on_surface_2/isolated_vertices.cpp
\example Arrangement_on_surface_2/observer.cpp
\example Arrangement_on_surface_2/overlay.cpp
\example Arrangement_on_surface_2/overlay_color.cpp
\example Arrangement_on_surface_2/overlay_unbounded.cpp
\example Arrangement_on_surface_2/point_location.cpp
\example Arrangement_on_surface_2/polylines.cpp
\example Arrangement_on_surface_2/predefined_kernel.cpp
\example Arrangement_on_surface_2/predefined_kernel_non_intersecting.cpp
\example Arrangement_on_surface_2/rational_functions.cpp
\example Arrangement_on_surface_2/special_edge_insertion.cpp
\example Arrangement_on_surface_2/spherical_insert.cpp
\example Arrangement_on_surface_2/unbounded_non_intersecting.cpp
\example Arrangement_on_surface_2/unbounded_rational_functions.cpp
\example Arrangement_on_surface_2/vertical_ray_shooting.cpp
\example Arrangement_on_surface_2/draw_arr.cpp
\example Arrangement_on_surface_2/linear_conics.cpp
\example Arrangement_on_surface_2/parabolas.cpp
\example Arrangement_on_surface_2/ellipses.cpp
\example Arrangement_on_surface_2/hyperbolas.cpp
*/
* \example Arrangement_on_surface_2/aggregated_insertion.cpp
* \example Arrangement_on_surface_2/algebraic_curves.cpp
* \example Arrangement_on_surface_2/algebraic_segments.cpp
* \example Arrangement_on_surface_2/batched_point_location.cpp
* \example Arrangement_on_surface_2/Bezier_curves.cpp
* \example Arrangement_on_surface_2/bgl_dual_adapter.cpp
* \example Arrangement_on_surface_2/bgl_primal_adapter.cpp
* \example Arrangement_on_surface_2/bounded_vertical_decomposition.cpp
* \example Arrangement_on_surface_2/circles.cpp
* \example Arrangement_on_surface_2/circular_arcs.cpp
* \example Arrangement_on_surface_2/conics.cpp
* \example Arrangement_on_surface_2/conic_multiplicities.cpp
* \example Arrangement_on_surface_2/consolidated_curve_data.cpp
* \example Arrangement_on_surface_2/count_and_trace.cpp
* \example Arrangement_on_surface_2/curve_history.cpp
* \example Arrangement_on_surface_2/dcel_extension.cpp
* \example Arrangement_on_surface_2/dcel_extension_io.cpp
* \example Arrangement_on_surface_2/draw_agas.cpp
* \example Arrangement_on_surface_2/draw_arr.cpp
* \example Arrangement_on_surface_2/dual_lines.cpp
* \example Arrangement_on_surface_2/dual_with_data.cpp
* \example Arrangement_on_surface_2/edge_insertion.cpp
* \example Arrangement_on_surface_2/edge_manipulation.cpp
* \example Arrangement_on_surface_2/edge_manipulation_curve_history.cpp
* \example Arrangement_on_surface_2/ellipses.cpp
* \example Arrangement_on_surface_2/face_extension.cpp
* \example Arrangement_on_surface_2/face_extension_overlay.cpp
* \example Arrangement_on_surface_2/generic_curve_data.cpp
* \example Arrangement_on_surface_2/global_insertion.cpp
* \example Arrangement_on_surface_2/global_removal.cpp
* \example Arrangement_on_surface_2/hyperbolas.cpp
* \example Arrangement_on_surface_2/incremental_insertion.cpp
* \example Arrangement_on_surface_2/io.cpp
* \example Arrangement_on_surface_2/io_curve_history.cpp
* \example Arrangement_on_surface_2/io_unbounded.cpp
* \example Arrangement_on_surface_2/isolated_vertices.cpp
* \example Arrangement_on_surface_2/linear_conics.cpp
* \example Arrangement_on_surface_2/observer.cpp
* \example Arrangement_on_surface_2/overlay.cpp
* \example Arrangement_on_surface_2/overlay_color.cpp
* \example Arrangement_on_surface_2/overlay_unbounded.cpp
* \example Arrangement_on_surface_2/parabolas.cpp
* \example Arrangement_on_surface_2/point_location.cpp
* \example Arrangement_on_surface_2/polycurve_bezier.cpp
* \example Arrangement_on_surface_2/polycurve_circular_arc.cpp
* \example Arrangement_on_surface_2/polycurve_conic.cpp
* \example Arrangement_on_surface_2/polycurve_geodesic.cpp
* \example Arrangement_on_surface_2/polylines.cpp
* \example Arrangement_on_surface_2/predefined_kernel.cpp
* \example Arrangement_on_surface_2/predefined_kernel_non_intersecting.cpp
* \example Arrangement_on_surface_2/rational_functions.cpp
* \example Arrangement_on_surface_2/special_edge_insertion.cpp
* \example Arrangement_on_surface_2/spherical_insert.cpp
* \example Arrangement_on_surface_2/unbounded_non_intersecting.cpp
* \example Arrangement_on_surface_2/unbounded_rational_functions.cpp
* \example Arrangement_on_surface_2/unb_planar_vertical_decomposition.cpp
* \example Arrangement_on_surface_2/vertical_ray_shooting.cpp
*/

View File

@ -15,16 +15,21 @@ foreach(cppfile ${cppfiles})
create_single_source_cgal_program("${cppfile}")
endforeach()
if(CGAL_Qt6_FOUND)
target_link_libraries(draw_arr PRIVATE CGAL::CGAL_Basic_viewer)
target_link_libraries(linear_conics PRIVATE CGAL::CGAL_Basic_viewer)
target_link_libraries(parabolas PRIVATE CGAL::CGAL_Basic_viewer)
target_link_libraries(ellipses PRIVATE CGAL::CGAL_Basic_viewer)
target_link_libraries(hyperbolas PRIVATE CGAL::CGAL_Basic_viewer)
target_link_libraries(polylines PRIVATE CGAL::CGAL_Basic_viewer)
target_link_libraries(circles PRIVATE CGAL::CGAL_Basic_viewer)
target_link_libraries(circular_arcs PRIVATE CGAL::CGAL_Basic_viewer)
target_link_libraries(draw_arr PRIVATE CGAL::CGAL_Basic_viewer)
target_link_libraries(draw_agas PRIVATE CGAL::CGAL_Basic_viewer)
target_link_libraries(ellipses PRIVATE CGAL::CGAL_Basic_viewer)
target_link_libraries(hyperbolas PRIVATE CGAL::CGAL_Basic_viewer)
target_link_libraries(linear_conics PRIVATE CGAL::CGAL_Basic_viewer)
target_link_libraries(parabolas PRIVATE CGAL::CGAL_Basic_viewer)
target_link_libraries(polylines PRIVATE CGAL::CGAL_Basic_viewer)
target_link_libraries(rational_functions PRIVATE CGAL::CGAL_Basic_viewer)
target_link_libraries(spherical_insert PRIVATE CGAL::CGAL_Basic_viewer)
target_link_libraries(spherical_overlay PRIVATE CGAL::CGAL_Basic_viewer)
target_link_libraries(unbounded_non_intersecting PRIVATE CGAL::CGAL_Basic_viewer)
else()
message(
STATUS

View File

@ -21,14 +21,15 @@ int main() {
// Locate the vertex with maximal degree.
auto vit = arr.vertices_begin();
Arrangement::Vertex_const_handle v_max = vit;
for (++vit; vit != arr.vertices_end(); ++vit)
if (vit->degree() > v_max->degree()) v_max = vit;
for(++vit; vit != arr.vertices_end(); ++vit)
if(vit->degree() > v_max->degree()) v_max = vit;
// Locate the vertex with maximum degree.
std::cout << "The vertex with maximal degree in the arrangement is: "
<< "v_max = (" << v_max->point() << ") "
<< "with degree " << v_max->degree() << "." << std::endl;
CGAL::draw(arr);
CGAL::draw(arr, "circles");
return 0;
}

View File

@ -24,8 +24,7 @@ int main() {
// Create a line segment (C4) with the same supporting line (y = x), but
// having one endpoint with irrational coordinates.
CoordNT sqrt_15 = CoordNT(0, 1, 15); // = sqrt(15)
curves.push_back(Curve(s3.supporting_line(),
Point(3, 3), Point(sqrt_15, sqrt_15)));
curves.push_back(Curve(s3.supporting_line(), Point(3, 3), Point(sqrt_15, sqrt_15)));
// Create a circular arc (C5) that is the upper half of the circle centered at
// (1, 1) with squared radius 3. Create the circle with clockwise orientation,
@ -51,13 +50,12 @@ int main() {
// Create a circular arc (C7) defined by two endpoints and a midpoint,
// all having rational coordinates. This arc is the upper right
// quarter of a circle centered at the origin with radius 5.
curves.push_back(Curve(Rational_point(0, 5), Rational_point(3, 4),
Rational_point(5, 0)));
curves.push_back(Curve(Rational_point(0, 5), Rational_point(3, 4), Rational_point(5, 0)));
// Construct the arrangement of the curves and print its size.
Arrangement arr;
Arrangement arr;
insert(arr, curves.begin(), curves.end());
print_arrangement_size(arr);
CGAL::draw(arr);
CGAL::draw(arr, "circular_arcs");
return 0;
}

View File

@ -0,0 +1,106 @@
#include <vector>
#include <CGAL/draw_arrangement_2.h>
#include "arr_geodesic.h"
#include "arr_print.h"
void draw_face_crossing_boundary() {
Arrangement arr;
const auto& traits = *arr.geometry_traits();
auto ctr_p = traits.construct_point_2_object();
auto ctr_cv = traits.construct_curve_2_object();
auto p1 = ctr_p(-0.95, 0.32, 0), p2 = ctr_p(-0.87, 0.02, 0.49), p3 = ctr_p(-0.93, -0.36, 0),
p4 = ctr_p(-0.81, -0.03, -0.59);
auto arcs = {ctr_cv(p1, p2), ctr_cv(p2, p3), ctr_cv(p3, p4), ctr_cv(p4, p1)};
CGAL::insert(arr, arcs.begin(), arcs.end());
print_arrangement_size(arr);
CGAL::draw(arr, "face crossing boundary");
}
void draw_lakes() {
Arrangement arr;
const auto& traits = *arr.geometry_traits();
auto ctr_p = traits.construct_point_2_object();
auto ctr_cv = traits.construct_curve_2_object();
auto poly1 = {
ctr_p(-0.27, -0.053, -0.96), ctr_p(-0.76, -0.15, -0.63), ctr_p(-0.98, -0.19, -0.063), ctr_p(-0.98, -0.098, 0.2),
ctr_p(-0.44, -0.18, 0.88), ctr_p(0.39, -0.0049, 0.92), ctr_p(-0.01, 0.39, 0.92), ctr_p(-0.54, 0.66, 0.53),
ctr_p(-0.83, 0.56, 0.025), ctr_p(-0.57, 0.32, -0.75), ctr_p(-0.087, 0.048, -1), ctr_p(-0.048, 0.088, -1),
ctr_p(0.12, -0.14, -0.98), ctr_p(-0.12, -0.14, -0.98),
};
auto poly2 = {ctr_p(-0.24, -0.53, -0.81), ctr_p(-0.47, -0.54, -0.69), ctr_p(-0.68, -0.65, -0.32),
ctr_p(-0.71, -0.68, 0.2), ctr_p(-0.54, -0.52, 0.67), ctr_p(-0.18, -0.72, 0.67),
ctr_p(0.31, -0.68, 0.67), ctr_p(0.71, -0.69, 0.11), ctr_p(0.6, -0.58, -0.56),
ctr_p(0.21, -0.62, -0.75)};
auto poly3 = {ctr_p(0.44, 0.27, -0.86), ctr_p(0.58, -0.063, -0.81), ctr_p(0.87, -0.094, -0.48),
ctr_p(0.97, -0.1, 0.2), ctr_p(0.46, 0.77, 0.45), ctr_p(-0.023, 0.89, 0.45),
ctr_p(-0.3, 0.95, 0.11), ctr_p(-0.22, 0.69, -0.69), ctr_p(-0.076, 0.35, -0.93)};
auto poly4 = {
ctr_p(0.4, 0.67, -0.63), ctr_p(0.78, 0.39, -0.48), ctr_p(0.92, 0.35, -0.15),
ctr_p(0.52, 0.86, 0.025), ctr_p(0.068, 0.99, -0.15), ctr_p(0.22, 0.85, -0.48),
};
std::vector<Curve> arcs;
std::vector<std::vector<Point>> polygons{poly1, poly2, poly3, poly4};
for(const auto& poly : polygons) {
for(size_t i = 0; i < poly.size(); ++i) {
size_t next = (i + 1) % poly.size();
arcs.push_back(ctr_cv(poly[i], poly[next]));
}
}
CGAL::insert(arr, arcs.begin(), arcs.end());
print_arrangement_size(arr);
CGAL::draw(arr, "lakes");
}
void draw_gaussian_map() {
Arrangement arr;
const auto& traits = *arr.geometry_traits();
auto ctr_p = traits.construct_point_2_object();
auto ctr_cv = traits.construct_curve_2_object();
auto p1 = ctr_p(1, 1, 1), p2 = ctr_p(-1, -1, 1), p3 = ctr_p(-1, 1, -1), p4 = ctr_p(1, -1, -1);
auto arcs = {ctr_cv(p1, p2), ctr_cv(p2, p3), ctr_cv(p3, p1), ctr_cv(p1, p4), ctr_cv(p2, p4), ctr_cv(p3, p4)};
CGAL::insert(arr, arcs.begin(), arcs.end());
print_arrangement_size(arr);
CGAL::draw(arr, "gaussian map of a tetrahedron");
}
void draw_random_arcs(int n) {
Arrangement arr;
const auto& traits = *arr.geometry_traits();
auto ctr_p = traits.construct_point_2_object();
auto ctr_cv = traits.construct_curve_2_object();
CGAL::Random random;
std::vector<Point> points;
for(int i = 0; i < n; ++i) {
double x = random.get_double(-1.0, 1.0);
double y = random.get_double(-1.0, 1.0);
double z = random.get_double(-1.0, 1.0);
points.push_back(ctr_p(x, y, z));
}
std::vector<Curve> curves;
for(int i = 0; i < n; ++i) {
int j = random.get_int(0, n - 1);
if(i == j)
j = (j + 1) % n;
curves.push_back(ctr_cv(points[i], points[j]));
}
CGAL::insert(arr, curves.begin(), curves.end());
print_arrangement_size(arr);
CGAL::draw(arr, (std::to_string(n) + " random arcs").c_str());
}
int main() {
draw_face_crossing_boundary();
draw_lakes();
draw_gaussian_map();
draw_random_arcs(100);
return 0;
}

View File

@ -1,13 +1,13 @@
#include <string>
#include <CGAL/Random.h>
#include <CGAL/Arr_linear_traits_2.h>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Arrangement_2.h>
#include <CGAL/Arr_segment_traits_2.h>
#include <CGAL/Arr_non_caching_segment_traits_2.h>
#include <CGAL/draw_arrangement_2.h>
using Kernel = CGAL::Exact_predicates_exact_constructions_kernel;
using Traits = CGAL::Arr_segment_traits_2<Kernel>;
using Point = Traits::Point_2;
using Arrangement_2 = CGAL::Arrangement_2<Traits>;
/*! Convert HSV to RGB color space
* Converts a given set of HSV values `h', `s', `v' into RGB coordinates.
* The output RGB values are in the range [0, 255], and the input HSV values
@ -17,9 +17,8 @@ using Arrangement_2 = CGAL::Arrangement_2<Traits>;
* \param sat Saturation component range: [0, 1]
* \param value Value component range: [0, 1]
* \return tuple<red, green, blue>, where each component is in the range [0, 255]
*/
std::tuple<unsigned char, unsigned char, unsigned char>
hsv_to_rgb(float hue, float sat, float value) {
*/
std::tuple<unsigned char, unsigned char, unsigned char> hsv_to_rgb(float hue, float sat, float value) {
float red, green, blue;
float fc = value * sat; // Chroma
float hue_prime = fmod(hue / 60.0f, 6.f);
@ -75,49 +74,175 @@ hsv_to_rgb(float hue, float sat, float value) {
return std::make_tuple(redc, greenc, bluec);
}
int main() {
void draw_rect() {
using Kernel = CGAL::Exact_predicates_exact_constructions_kernel;
using Traits = CGAL::Arr_non_caching_segment_traits_2<Kernel>;
using Point = Traits::Point_2;
using Arrangement = CGAL::Arrangement_2<Traits>;
Traits traits;
Arrangement_2 arr(&traits);
Arrangement arr(&traits);
auto ctr_xcv = traits.construct_x_monotone_curve_2_object();
CGAL::insert(arr, ctr_xcv(Point(-2,-2), Point(2,-2)));
CGAL::insert(arr, ctr_xcv(Point(2,-2), Point(2,2)));
CGAL::insert(arr, ctr_xcv(Point(2,2), Point(-2,2)));
CGAL::insert(arr, ctr_xcv(Point(-2,2), Point(-2,-2)));
CGAL::insert(arr, ctr_xcv(Point(-2, -2), Point(2, -2)));
CGAL::insert(arr, ctr_xcv(Point(2, -2), Point(2, 2)));
CGAL::insert(arr, ctr_xcv(Point(2, 2), Point(-2, 2)));
CGAL::insert(arr, ctr_xcv(Point(-2, 2), Point(-2, -2)));
CGAL::insert(arr, ctr_xcv(Point(-1,-1), Point(1,-1)));
CGAL::insert(arr, ctr_xcv(Point(1,-1), Point(1,1)));
CGAL::insert(arr, ctr_xcv(Point(1,1), Point(-1,1)));
CGAL::insert(arr, ctr_xcv(Point(-1,1), Point(-1,-1)));
CGAL::insert(arr, ctr_xcv(Point(-1, -1), Point(1, -1)));
CGAL::insert(arr, ctr_xcv(Point(1, -1), Point(1, 1)));
CGAL::insert(arr, ctr_xcv(Point(1, 1), Point(-1, 1)));
CGAL::insert(arr, ctr_xcv(Point(-1, 1), Point(-1, -1)));
CGAL::insert(arr, ctr_xcv(Point(-2,-2), Point(-2,-4)));
CGAL::insert(arr, ctr_xcv(Point(2,-2), Point(4,-2)));
CGAL::insert(arr, ctr_xcv(Point(-2, -2), Point(-2, -4)));
CGAL::insert(arr, ctr_xcv(Point(2, -2), Point(4, -2)));
CGAL::insert(arr, ctr_xcv(Point(0,0), Point(0,-3)));
CGAL::insert(arr, ctr_xcv(Point(0, 0), Point(0, -3)));
std::cout << arr.number_of_vertices() << ", "
<< arr.number_of_edges() << ", "
<< arr.number_of_faces() << std::endl;
std::cout << arr.number_of_vertices() << ", " << arr.number_of_edges() << ", " << arr.number_of_faces() << std::endl;
std::size_t id(0);
CGAL::Graphics_scene_options<Arrangement, typename Arrangement::Vertex_const_handle,
typename Arrangement::Halfedge_const_handle, typename Arrangement::Face_const_handle>
gso;
gso.colored_face = [](const Arrangement&, Arrangement::Face_const_handle) -> bool { return true; };
CGAL::Graphics_scene_options<Arrangement_2,
typename Arrangement_2::Vertex_const_handle,
typename Arrangement_2::Halfedge_const_handle,
typename Arrangement_2::Face_const_handle> gso;
gso.colored_face=[](const Arrangement_2&, Arrangement_2::Face_const_handle) -> bool
{ return true; };
gso.face_color = [](const Arrangement&, Arrangement::Face_const_handle fh) -> CGAL::IO::Color {
CGAL::Random random((size_t(fh.ptr())));
float h = 360.0f * random.get_double(0, 1);
float s = 0.5;
float v = 0.5;
auto [r, g, b] = hsv_to_rgb(h, s, v);
return CGAL::IO::Color(r, g, b);
};
gso.face_color=[&id](const Arrangement_2& arr, Arrangement_2::Face_const_handle) -> CGAL::IO::Color
{
float h = 360.0f * id++ / arr.number_of_faces();
float s = 0.5;
float v = 0.5;
auto [r, g, b] = hsv_to_rgb(h, s, v);
return CGAL::IO::Color(r,g,b);
};
CGAL::draw(arr, gso, "hsv colors");
return EXIT_SUCCESS;
CGAL::draw(arr, gso, "rect with hsv colors");
}
void draw_nested() {
using Kernel = CGAL::Exact_predicates_exact_constructions_kernel;
using Traits = CGAL::Arr_segment_traits_2<Kernel>;
using Point = Traits::Point_2;
using Arrangement = CGAL::Arrangement_2<Traits>;
using X_monotone_curve = Traits::X_monotone_curve_2;
Arrangement arr;
auto traits = arr.traits();
auto ctr_xcv = traits->construct_x_monotone_curve_2_object();
std::vector<X_monotone_curve> curves;
{
// a hexagon centered at the origin
const double r = 10.0;
for (int i = 0; i < 6; ++i) {
int next = (i + 1) % 6;
Point source(r * cos(i * CGAL_PI / 3), r * sin(i * CGAL_PI / 3));
Point target(r * cos(next * CGAL_PI / 3), r * sin(next * CGAL_PI / 3));
curves.push_back(ctr_xcv(source, target));
}
}
{
// a square inside the hexagon
const double size = 4.0;
Point p1(-size, size), p2(size, size), p3(size, -size), p4(-size, -size);
auto rect = {ctr_xcv(p1, p2), ctr_xcv(p2, p3), ctr_xcv(p3, p4), ctr_xcv(p4, p1)};
curves.insert(curves.end(), rect.begin(), rect.end());
}
{
// two adjacent triangle inside the square
Point p1(-1, 0), p2(1, 0), p3(0, sqrt(3)), p4(0, -sqrt(3));
auto tri1 = {ctr_xcv(p1, p2), ctr_xcv(p2, p3), ctr_xcv(p3, p1)};
auto tri2 = {ctr_xcv(p1, p2), ctr_xcv(p2, p4), ctr_xcv(p4, p1)};
curves.insert(curves.end(), tri1.begin(), tri1.end());
curves.insert(curves.end(), tri2.begin(), tri2.end());
}
// a degenerate hole inside the square
auto degen_seg = ctr_xcv({-1, -3}, {1, -3});
curves.push_back(degen_seg);
// an isolated vertex inside the square
auto iso_point = Point{1, -1};
CGAL::insert(arr, curves.begin(), curves.end());
CGAL::insert_point(arr, iso_point);
CGAL::draw(arr, "nested polygons");
}
void draw_unbounded_linear_grid() {
using Kernel = CGAL::Exact_predicates_exact_constructions_kernel;
using Traits = CGAL::Arr_linear_traits_2<Kernel>;
using Point = Traits::Point_2;
using Segment = Traits::Segment_2;
using Line = Traits::Line_2;
using X_monotone_curve = Traits::X_monotone_curve_2;
using Arrangement = CGAL::Arrangement_2<Traits>;
Arrangement arr;
// Insert a n*n grid
int n = 5;
for (int i = 0; i < n; ++i) {
Point p1(i * 5, 0);
Point p2(i * 5, 1);
CGAL::insert(arr, X_monotone_curve(Line(p1, p2)));
}
for (int i = 0; i < n; ++i) {
Point p1(0, i * 5);
Point p2(1, i * 5);
CGAL::insert(arr, X_monotone_curve(Line(p1, p2)));
}
// Generate a inner square(2*2) for all cells
// And an inner triangle for each square
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
Point p1(i * 5 + 1, j * 5 + 1);
Point p2(i * 5 + 4, j * 5 + 4);
CGAL::insert(arr, X_monotone_curve(Segment(p1, Point(p2.x(), p1.y()))));
CGAL::insert(arr, X_monotone_curve(Segment(Point(p1.x(), p2.y()), p2)));
CGAL::insert(arr, X_monotone_curve(Segment(p1, Point(p1.x(), p2.y()))));
CGAL::insert(arr, X_monotone_curve(Segment(Point(p2.x(), p1.y()), p2)));
// Insert a triangle inside the square
Point tri_p1(i * 5 + 2, j * 5 + 2);
Point tri_p2(i * 5 + 3, j * 5 + 2);
Point tri_p3(i * 5 + 2.5, j * 5 + 3);
CGAL::insert(arr, X_monotone_curve(Segment(tri_p1, tri_p2)));
CGAL::insert(arr, X_monotone_curve(Segment(tri_p2, tri_p3)));
CGAL::insert(arr, X_monotone_curve(Segment(tri_p3, tri_p1)));
// Connect the triangle to the square
Point top(i * 5 + 2.5, j * 5 + 4);
CGAL::insert(arr, X_monotone_curve(Segment(tri_p1, top)));
}
}
CGAL::draw(arr, "unbounded linear grid");
}
void draw_random_segments(int n) {
using Kernel = CGAL::Exact_predicates_exact_constructions_kernel;
using Traits = CGAL::Arr_segment_traits_2<Kernel>;
using Point = Traits::Point_2;
using Arrangement = CGAL::Arrangement_2<Traits>;
using X_monotone_curve = Traits::X_monotone_curve_2;
Arrangement arr;
auto traits = arr.traits();
auto ctr_xcv = traits->construct_x_monotone_curve_2_object();
CGAL::Random random;
std::vector<X_monotone_curve> curves;
for (int i = 0; i < n; ++i) {
double x1 = random.get_double(-100, 100);
double y1 = random.get_double(-100, 100);
double x2 = random.get_double(-100, 100);
double y2 = random.get_double(-100, 100);
curves.push_back(ctr_xcv(Point(x1, y1), Point(x2, y2)));
}
CGAL::insert(arr, curves.begin(), curves.end());
CGAL::draw(arr, (std::to_string(n) + " random segments").c_str());
}
int main() {
draw_rect();
draw_nested();
draw_unbounded_linear_grid();
draw_random_segments(100);
return EXIT_SUCCESS;
}

View File

@ -17,14 +17,10 @@ int main() {
auto ctr_cv = traits.construct_curve_2_object();
// Insert a full x-major ellipse
CGAL::insert(arr, ctr_cv(1, 4, 0, 0, 0, -16, CGAL::COUNTERCLOCKWISE,
Point(4,0), Point(0,2)));
CGAL::insert(arr, ctr_cv(1, 4, 0, 0, 0, -16, CGAL::COUNTERCLOCKWISE,
Point(0,2), Point(-4,0)));
CGAL::insert(arr, ctr_cv(1, 4, 0, 0, 0, -16, CGAL::COUNTERCLOCKWISE,
Point(-4,0), Point(0,-2)));
CGAL::insert(arr, ctr_cv(1, 4, 0, 0, 0, -16, CGAL::COUNTERCLOCKWISE,
Point(0,-2), Point(4,0)));
CGAL::insert(arr, ctr_cv(1, 4, 0, 0, 0, -16, CGAL::COUNTERCLOCKWISE, Point(4, 0), Point(0, 2)));
CGAL::insert(arr, ctr_cv(1, 4, 0, 0, 0, -16, CGAL::COUNTERCLOCKWISE, Point(0, 2), Point(-4, 0)));
CGAL::insert(arr, ctr_cv(1, 4, 0, 0, 0, -16, CGAL::COUNTERCLOCKWISE, Point(-4, 0), Point(0, -2)));
CGAL::insert(arr, ctr_cv(1, 4, 0, 0, 0, -16, CGAL::COUNTERCLOCKWISE, Point(0, -2), Point(4, 0)));
// Insert a full y-major ellipse
CGAL::insert(arr, ctr_cv(4, 1, 0, 0, 0, -16));
@ -39,7 +35,7 @@ int main() {
print_arrangement_size(arr);
CGAL::draw(arr);
CGAL::draw(arr, "ellipses");
return 0;
}

View File

@ -19,63 +19,46 @@ int main() {
// Insert a hyperbolic arc (C1), supported by the hyperbola y = 1/x
// (or: xy - 1 = 0) with the endpoints (1/4, 4) and (2, 1/2).
// The arc is counterclockwise oriented.
CGAL::insert(arr, ctr_cv(0, 0, 1, 0, 0, -1, CGAL::COUNTERCLOCKWISE,
Point(Rational(1,4), 4), Point(2, Rational(1,2))));
CGAL::insert(arr, ctr_cv(0, 0, -1, 0, 0, -1, CGAL::CLOCKWISE,
Point(Rational(-1,4), 4), Point(-2, Rational(1,2))));
CGAL::insert(arr,
ctr_cv(0, 0, 1, 0, 0, -1, CGAL::COUNTERCLOCKWISE, Point(Rational(1, 4), 4), Point(2, Rational(1, 2))));
CGAL::insert(arr, ctr_cv(0, 0, -1, 0, 0, -1, CGAL::CLOCKWISE, Point(Rational(-1, 4), 4), Point(-2, Rational(1, 2))));
CGAL::insert(arr, ctr_cv(2, -1, 0, 0, 0, -2, CGAL::COUNTERCLOCKWISE,
Point(3, 4), Point(1, 0)));
CGAL::insert(arr, ctr_cv(2, -1, 0, 0, 0, -2, CGAL::COUNTERCLOCKWISE,
Point(1, 0), Point(3, -4)));
CGAL::insert(arr, ctr_cv(2, -1, 0, 0, 0, -2, CGAL::CLOCKWISE,
Point(-3, 4), Point(-1, 0)));
CGAL::insert(arr, ctr_cv(2, -1, 0, 0, 0, -2, CGAL::CLOCKWISE,
Point(-1, 0), Point(-3, -4)));
CGAL::insert(arr, ctr_cv(2, -1, 0, 0, 0, -2, CGAL::COUNTERCLOCKWISE, Point(3, 4), Point(1, 0)));
CGAL::insert(arr, ctr_cv(2, -1, 0, 0, 0, -2, CGAL::COUNTERCLOCKWISE, Point(1, 0), Point(3, -4)));
CGAL::insert(arr, ctr_cv(2, -1, 0, 0, 0, -2, CGAL::CLOCKWISE, Point(-3, 4), Point(-1, 0)));
CGAL::insert(arr, ctr_cv(2, -1, 0, 0, 0, -2, CGAL::CLOCKWISE, Point(-1, 0), Point(-3, -4)));
CGAL::insert(arr, ctr_cv(-1, 2, 0, 0, 0, -2, CGAL::CLOCKWISE,
Point(4, 3), Point(0, 1)));
CGAL::insert(arr, ctr_cv(-1, 2, 0, 0, 0, -2, CGAL::CLOCKWISE,
Point(0, 1), Point(-4, 3)));
CGAL::insert(arr, ctr_cv(-1, 2, 0, 0, 0, -2, CGAL::COUNTERCLOCKWISE,
Point(4, -3), Point(0, -1)));
CGAL::insert(arr, ctr_cv(-1, 2, 0, 0, 0, -2, CGAL::COUNTERCLOCKWISE,
Point(0, -1), Point(-4, -3)));
CGAL::insert(arr, ctr_cv(-1, 2, 0, 0, 0, -2, CGAL::CLOCKWISE, Point(4, 3), Point(0, 1)));
CGAL::insert(arr, ctr_cv(-1, 2, 0, 0, 0, -2, CGAL::CLOCKWISE, Point(0, 1), Point(-4, 3)));
CGAL::insert(arr, ctr_cv(-1, 2, 0, 0, 0, -2, CGAL::COUNTERCLOCKWISE, Point(4, -3), Point(0, -1)));
CGAL::insert(arr, ctr_cv(-1, 2, 0, 0, 0, -2, CGAL::COUNTERCLOCKWISE, Point(0, -1), Point(-4, -3)));
CGAL::insert(arr, ctr_cv(4, 46, -144, 0, 0, -100, CGAL::COUNTERCLOCKWISE,
Point(-5, 0),
CGAL::insert(arr, ctr_cv(4, 46, -144, 0, 0, -100, CGAL::COUNTERCLOCKWISE, Point(-5, 0),
Point(Rational(14, 10), Rational(48, 10))));
CGAL::insert(arr, ctr_cv(4, 46, -144, 0, 0, -100, CGAL::COUNTERCLOCKWISE,
Point(5, 0),
CGAL::insert(arr, ctr_cv(4, 46, -144, 0, 0, -100, CGAL::COUNTERCLOCKWISE, Point(5, 0),
Point(Rational(-14, 10), Rational(-48, 10))));
// 4*x*x + 46*y*y - 144*x*y - 100
CGAL::insert(arr, ctr_cv(46, 4, -144, 0, 0, -100, CGAL::CLOCKWISE,
Point(0, -5),
Point(Rational(48, 10), Rational(14, 10))));
CGAL::insert(arr, ctr_cv(46, 4, -144, 0, 0, -100, CGAL::CLOCKWISE,
Point(0, 5),
Point(Rational(-48, 10), Rational(-14, 10))));
CGAL::insert(
arr, ctr_cv(46, 4, -144, 0, 0, -100, CGAL::CLOCKWISE, Point(0, -5), Point(Rational(48, 10), Rational(14, 10))));
CGAL::insert(
arr, ctr_cv(46, 4, -144, 0, 0, -100, CGAL::CLOCKWISE, Point(0, 5), Point(Rational(-48, 10), Rational(-14, 10))));
// 46*x*x + 4*y*y - 144*x*y - 100
CGAL::insert(arr, ctr_cv(4, 46, 144, 0, 0, -100, CGAL::CLOCKWISE,
Point(-5, 0),
Point(Rational(14,10), Rational(-48,10))));
CGAL::insert(arr, ctr_cv(4, 46, 144, 0, 0, -100, CGAL::CLOCKWISE,
Point(5, 0),
Point(Rational(-14,10), Rational(48,10))));
CGAL::insert(
arr, ctr_cv(4, 46, 144, 0, 0, -100, CGAL::CLOCKWISE, Point(-5, 0), Point(Rational(14, 10), Rational(-48, 10))));
CGAL::insert(
arr, ctr_cv(4, 46, 144, 0, 0, -100, CGAL::CLOCKWISE, Point(5, 0), Point(Rational(-14, 10), Rational(48, 10))));
// 4*x*x + 46*y*y + 144*x*y - 100
CGAL::insert(arr, ctr_cv(46, 4, 144, 0, 0, -100, CGAL::COUNTERCLOCKWISE,
Point(0, -5),
Point(Rational(-48,10), Rational(14,10))));
CGAL::insert(arr, ctr_cv(46, 4, 144, 0, 0, -100, CGAL::COUNTERCLOCKWISE,
Point(0, 5),
Point(Rational(48,10), Rational(-14,10))));
CGAL::insert(arr, ctr_cv(46, 4, 144, 0, 0, -100, CGAL::COUNTERCLOCKWISE, Point(0, -5),
Point(Rational(-48, 10), Rational(14, 10))));
CGAL::insert(arr, ctr_cv(46, 4, 144, 0, 0, -100, CGAL::COUNTERCLOCKWISE, Point(0, 5),
Point(Rational(48, 10), Rational(-14, 10))));
print_arrangement_size(arr);
CGAL::draw(arr);
CGAL::draw(arr, "hyperbolas");
return 0;
}

View File

@ -20,8 +20,8 @@ int main() {
Point p2(0, -1);
Point p3(0, 1);
Point p4(1, 0);
Point p5(Rational(1,2),Rational(1,2));
Point p6(Rational(-1,2),Rational(1,2));
Point p5(Rational(1, 2), Rational(1, 2));
Point p6(Rational(-1, 2), Rational(1, 2));
Rat_point rp0(0, 0);
Rat_point rp1(1, 0);
Rat_point rp2(0, 1);
@ -56,7 +56,7 @@ int main() {
print_arrangement_size(arr);
CGAL::draw(arr);
CGAL::draw(arr, "linear_conics");
return 0;
}

View File

@ -18,62 +18,49 @@ int main() {
// x-major
// insert the parabola y = x^2; (-1,1)--(1,1)
CGAL::insert(arr, ctr_cv(1, 0, 0, 0, -1, 0, CGAL::COUNTERCLOCKWISE,
Point(-1, 1), Point(1, 1)));
CGAL::insert(arr, ctr_cv(1, 0, 0, 0, -1, 0, CGAL::COUNTERCLOCKWISE, Point(-1, 1), Point(1, 1)));
// translated
// Insert the parabola y = x^2 - 2x + 2; (1,1)--(2,2)
CGAL::insert(arr, ctr_cv(1, 0, 0, -2, -1, 2, CGAL::COUNTERCLOCKWISE,
Point(1, 1), Point(2, 2)));
CGAL::insert(arr, ctr_cv(1, 0, 0, 2, -1, 2, CGAL::COUNTERCLOCKWISE,
Point(-2, 2), Point(-1, 1)));
CGAL::insert(arr, ctr_cv(1, 0, 0, -2, -1, 2, CGAL::COUNTERCLOCKWISE, Point(1, 1), Point(2, 2)));
CGAL::insert(arr, ctr_cv(1, 0, 0, 2, -1, 2, CGAL::COUNTERCLOCKWISE, Point(-2, 2), Point(-1, 1)));
// rotated
// Insert the parabola y = x^2 rotated clockwise about theta, such that
// sin(theta) = 0.6, cos(theta) = 0.8
CGAL::insert(arr, ctr_cv(16, 9, -24, -15, -20, 0, CGAL::COUNTERCLOCKWISE,
Point(Rational(-2,10), Rational(14,10)),
Point(Rational(14,10), Rational(2,10))));
CGAL::insert(arr, ctr_cv(16, 9, 24, 15, -20, 0, CGAL::CLOCKWISE,
Point(Rational(2,10), Rational(14,10)),
Point(Rational(-14,10), Rational(2,10))));
CGAL::insert(arr, ctr_cv(16, 9, 24, -15, 20, 0, CGAL::COUNTERCLOCKWISE,
Point(Rational(14,10), Rational(-2,10)),
Point(Rational(-2,10), Rational(-14,10))));
CGAL::insert(arr, ctr_cv(16, 9, -24, 15, 20, 0, CGAL::COUNTERCLOCKWISE,
Point(Rational(2,10), Rational(-14,10)),
Point(Rational(-14,10), Rational(-2,10))));
CGAL::insert(arr, ctr_cv(16, 9, -24, -15, -20, 0, CGAL::COUNTERCLOCKWISE, Point(Rational(-2, 10), Rational(14, 10)),
Point(Rational(14, 10), Rational(2, 10))));
CGAL::insert(arr, ctr_cv(16, 9, 24, 15, -20, 0, CGAL::CLOCKWISE, Point(Rational(2, 10), Rational(14, 10)),
Point(Rational(-14, 10), Rational(2, 10))));
CGAL::insert(arr, ctr_cv(16, 9, 24, -15, 20, 0, CGAL::COUNTERCLOCKWISE, Point(Rational(14, 10), Rational(-2, 10)),
Point(Rational(-2, 10), Rational(-14, 10))));
CGAL::insert(arr, ctr_cv(16, 9, -24, 15, 20, 0, CGAL::COUNTERCLOCKWISE, Point(Rational(2, 10), Rational(-14, 10)),
Point(Rational(-14, 10), Rational(-2, 10))));
// 16*x*x+9*y*y-24*x*y-15*x-20*y
CGAL::insert(arr, ctr_cv(9, 16, -24, -20, -15, 0, CGAL::COUNTERCLOCKWISE,
Point(Rational(2,10), Rational(14,10)),
Point(Rational(14,10), Rational(-2,10))));
CGAL::insert(arr, ctr_cv(9, 16, 24, -20, 15, 0, CGAL::CLOCKWISE,
Point(Rational(2,10), Rational(-14,10)),
Point(Rational(14,10), Rational(2,10))));
CGAL::insert(arr, ctr_cv(9, 16, 24, 20, -15, 0, CGAL::COUNTERCLOCKWISE,
Point(Rational(-14,10), Rational(-2,10)),
Point(Rational(-2,10), Rational(14,10))));
CGAL::insert(arr, ctr_cv(9, 16, -24, 20, 15, 0, CGAL::COUNTERCLOCKWISE,
Point(Rational(-2,10), Rational(-14,10)),
Point(Rational(-14,10), Rational(2,10))));
CGAL::insert(arr, ctr_cv(9, 16, -24, -20, -15, 0, CGAL::COUNTERCLOCKWISE, Point(Rational(2, 10), Rational(14, 10)),
Point(Rational(14, 10), Rational(-2, 10))));
CGAL::insert(arr, ctr_cv(9, 16, 24, -20, 15, 0, CGAL::CLOCKWISE, Point(Rational(2, 10), Rational(-14, 10)),
Point(Rational(14, 10), Rational(2, 10))));
CGAL::insert(arr, ctr_cv(9, 16, 24, 20, -15, 0, CGAL::COUNTERCLOCKWISE, Point(Rational(-14, 10), Rational(-2, 10)),
Point(Rational(-2, 10), Rational(14, 10))));
CGAL::insert(arr, ctr_cv(9, 16, -24, 20, 15, 0, CGAL::COUNTERCLOCKWISE, Point(Rational(-2, 10), Rational(-14, 10)),
Point(Rational(-14, 10), Rational(2, 10))));
// 9*x*x+16*y*y-24*x*y+20*x+15*y
// rotated & translated
CGAL::insert(arr, ctr_cv(16, 9, -24, -23, -14, 36, CGAL::COUNTERCLOCKWISE,
Point(Rational(8,10), Rational(24,10)),
Point(Rational(24,10), Rational(12,10))));
CGAL::insert(arr, ctr_cv(16, 9, 24, 23, -14, 36, CGAL::CLOCKWISE,
Point(Rational(-8,10), Rational(24,10)),
Point(Rational(-24,10), Rational(12,10))));
CGAL::insert(arr, ctr_cv(16, 9, -24, -23, -14, 36, CGAL::COUNTERCLOCKWISE, Point(Rational(8, 10), Rational(24, 10)),
Point(Rational(24, 10), Rational(12, 10))));
CGAL::insert(arr, ctr_cv(16, 9, 24, 23, -14, 36, CGAL::CLOCKWISE, Point(Rational(-8, 10), Rational(24, 10)),
Point(Rational(-24, 10), Rational(12, 10))));
// 16*x*x+9*y*y-24*x*y-23*x-14*y+36
print_arrangement_size(arr);
CGAL::draw(arr);
CGAL::draw(arr, "parabolas");
return 0;
}

View File

@ -45,7 +45,7 @@ int main() {
insert(arr, pi1);
insert(arr, pi2);
insert(arr, pi3);
print_arrangement_size(arr); // print the arrangement size
CGAL::draw(arr);
print_arrangement_size(arr); // print the arrangement size
CGAL::draw(arr, "polylines");
return 0;
}

View File

@ -17,7 +17,7 @@ int main() {
#include "arr_print.h"
int main() {
CGAL::IO::set_pretty_mode(std::cout); // for nice printouts.
CGAL::IO::set_pretty_mode(std::cout); // for nice printouts.
// Define a traits class object and a constructor for rational functions.
Traits traits;
@ -31,24 +31,24 @@ int main() {
// Create an arc (C1) supported by the polynomial y = x^4 - 6x^2 + 8,
// defined over the (approximate) interval [-2.1, 2.1].
Polynomial P1 = CGAL::ipower(x,4) - 6*x*x + 8;
Polynomial P1 = CGAL::ipower(x, 4) - 6 * x * x + 8;
Alg_real l(Bound(-2.1)), r(Bound(2.1));
arcs.push_back(construct(P1, l, r));
// Create an arc (C2) supported by the function y = x / (1 + x^2),
// defined over the interval [-3, 3].
Polynomial P2 = x;
Polynomial Q2 = 1 + x*x;
Polynomial Q2 = 1 + x * x;
arcs.push_back(construct(P2, Q2, Alg_real(-3), Alg_real(3)));
// Create an arc (C3) supported by the parbola y = 8 - x^2,
// defined over the interval [-2, 3].
Polynomial P3 = 8 - x*x;
Polynomial P3 = 8 - x * x;
arcs.push_back(construct(P3, Alg_real(-2), Alg_real(3)));
// Create an arc (C4) supported by the line y = -2x,
// defined over the interval [-3, 0].
Polynomial P4 = -2*x;
Polynomial P4 = -2 * x;
arcs.push_back(construct(P4, Alg_real(-3), Alg_real(0)));
// Construct the arrangement of the four arcs.

View File

@ -1,6 +1,5 @@
//! \file examples/Arrangement_on_surface_2/spherical_insert.cpp
// Constructing an arrangement of arcs of great circles.
#include <list>
#include <cmath>
#include <cstdio>
@ -9,6 +8,7 @@
#include <CGAL/Arrangement_on_surface_2.h>
#include <CGAL/Arr_geodesic_arc_on_sphere_traits_2.h>
#include <CGAL/Arr_spherical_topology_traits_2.h>
#include <CGAL/draw_arrangement_2.h>
#include "arr_geodesic.h"
#include "arr_print.h"
@ -20,12 +20,11 @@ int main() {
Arrangement arr(&traits);
Point p1 = ctr_p(0, 0, -1), p3 = ctr_p(0, -1, 0), p5 = ctr_p(-1, 0, 0);
Point p2 = ctr_p(0, 0, 1), p4 = ctr_p(0, 1, 0), p6 = ctr_p( 1, 0, 0);
Curve arcs[] = {
ctr_cv(p6, p1), ctr_cv(p6, p2), ctr_cv(p4, p1), ctr_cv(p4, p2),
ctr_cv(p5, p1), ctr_cv(p5, p2), ctr_cv(p3, p1), ctr_cv(p3, p2),
ctr_cv(p6, p4), ctr_cv(p6, p3), ctr_cv(p5, p4), ctr_cv(p5, p3) };
CGAL::insert(arr, arcs, arcs + sizeof(arcs)/sizeof(Curve));
Point p2 = ctr_p(0, 0, 1), p4 = ctr_p(0, 1, 0), p6 = ctr_p(1, 0, 0);
Curve arcs[] = {ctr_cv(p6, p1), ctr_cv(p6, p2), ctr_cv(p4, p1), ctr_cv(p4, p2), ctr_cv(p5, p1), ctr_cv(p5, p2),
ctr_cv(p3, p1), ctr_cv(p3, p2), ctr_cv(p6, p4), ctr_cv(p6, p3), ctr_cv(p5, p4), ctr_cv(p5, p3)};
CGAL::insert(arr, arcs, arcs + sizeof(arcs) / sizeof(Curve));
print_arrangement_size(arr);
CGAL::draw(arr, "spherical insert");
return 0;
}

View File

@ -3,6 +3,7 @@
#include <CGAL/Arr_overlay_2.h>
#include <CGAL/Arr_default_overlay_traits.h>
#include <CGAL/draw_arrangement_2.h>
#include "arr_geodesic_on_sphere.h"
@ -34,8 +35,8 @@ int main() {
Arrangement overlay_arr;
Overlay_traits overlay_traits;
overlay(arr1, arr2, overlay_arr, overlay_traits);
std::cout << "No. of vertices: " << overlay_arr.number_of_vertices()
<< std::endl;
std::cout << "No. of vertices: " << overlay_arr.number_of_vertices() << std::endl;
CGAL::draw(overlay_arr, "spherical overlay");
return 0;
}

View File

@ -4,6 +4,7 @@
#include <cassert>
#include "CGAL/draw_arrangement_2.h"
#include "arr_linear.h"
#include "arr_print.h"
@ -14,8 +15,8 @@ int main() {
// then, insert a point that lies on the line splitting it into two.
X_monotone_curve c1 = Line(Point(-1, 0), Point(1, 0));
arr.insert_in_face_interior(c1, arr.unbounded_face());
Vertex_handle v = insert_point(arr, Point(0,0));
assert(! v->is_at_open_boundary());
Vertex_handle v = insert_point(arr, Point(0, 0));
assert(!v->is_at_open_boundary());
// Add two more rays using the specialized insertion functions.
arr.insert_from_right_vertex(Ray(Point(0, 0), Point(-1, 1)), v); // c2
@ -30,25 +31,27 @@ int main() {
// Print the outer CCBs of the unbounded faces.
int k = 1;
for (auto it = arr.unbounded_faces_begin(); it != arr.unbounded_faces_end();
++it)
{
std::cout << "Face no. " << k++ << "(" << it->is_unbounded() << ","
<< it->number_of_holes() << ")" << ": ";
for(auto it = arr.unbounded_faces_begin(); it != arr.unbounded_faces_end(); ++it) {
std::cout << "Face no. " << k++ << "(" << it->is_unbounded() << "," << it->number_of_holes() << ")" << ": ";
Arrangement::Ccb_halfedge_const_circulator first = it->outer_ccb();
auto curr = first;
if (! curr->source()->is_at_open_boundary())
if(!curr->source()->is_at_open_boundary())
std::cout << "(" << curr->source()->point() << ")";
do {
Arrangement::Halfedge_const_handle e = curr;
if (! e->is_fictitious()) std::cout << " [" << e->curve() << "] ";
else std::cout << " [ ... ] ";
if(!e->is_fictitious())
std::cout << " [" << e->curve() << "] ";
else
std::cout << " [ ... ] ";
if (! e->target()->is_at_open_boundary())
if(!e->target()->is_at_open_boundary())
std::cout << "(" << e->target()->point() << ")";
} while (++curr != first);
} while(++curr != first);
std::cout << std::endl;
}
CGAL::draw(arr, "unbounded_non_intersecting");
return 0;
}

View File

@ -30,7 +30,7 @@
#include <CGAL/tags.h>
#include <CGAL/Arr_tags.h>
#include <CGAL/Cartesian.h>
#include <CGAL/Simple_cartesian.h>
#include <CGAL/Arr_geometry_traits/Circle_segment_2.h>
namespace CGAL {
@ -41,31 +41,31 @@ namespace CGAL {
template <typename Kernel_, bool Filter = true>
class Arr_circle_segment_traits_2 {
public:
typedef Kernel_ Kernel;
typedef typename Kernel::FT NT;
typedef typename Kernel::Point_2 Rational_point_2;
typedef typename Kernel::Segment_2 Rational_segment_2;
typedef typename Kernel::Circle_2 Rational_circle_2;
typedef _One_root_point_2<NT, Filter> Point_2;
typedef typename Point_2::CoordNT CoordNT;
typedef _Circle_segment_2<Kernel, Filter> Curve_2;
typedef _X_monotone_circle_segment_2<Kernel, Filter> X_monotone_curve_2;
typedef unsigned int Multiplicity;
typedef Arr_circle_segment_traits_2<Kernel, Filter> Self;
using Kernel = Kernel_;
using NT = typename Kernel::FT;
using Rational_point_2 = typename Kernel::Point_2;
using Rational_segment_2 = typename Kernel::Segment_2;
using Rational_circle_2 = typename Kernel::Circle_2;
using Point_2 = _One_root_point_2<NT, Filter>;
using CoordNT = typename Point_2::CoordNT;
using Curve_2 = _Circle_segment_2<Kernel, Filter>;
using X_monotone_curve_2 = _X_monotone_circle_segment_2<Kernel, Filter>;
using Multiplicity = std::size_t;
using Self = Arr_circle_segment_traits_2<Kernel, Filter>;
// Category tags:
typedef Tag_true Has_left_category;
typedef Tag_true Has_merge_category;
typedef Tag_false Has_do_intersect_category;
using Has_left_category = Tag_true;
using Has_merge_category = Tag_true;
using Has_do_intersect_category = Tag_false;
typedef Arr_oblivious_side_tag Left_side_category;
typedef Arr_oblivious_side_tag Bottom_side_category;
typedef Arr_oblivious_side_tag Top_side_category;
typedef Arr_oblivious_side_tag Right_side_category;
using Left_side_category = Arr_oblivious_side_tag;
using Bottom_side_category = Arr_oblivious_side_tag;
using Top_side_category = Arr_oblivious_side_tag;
using Right_side_category = Arr_oblivious_side_tag;
protected:
// Type definition for the intersection points mapping.
typedef typename X_monotone_curve_2::Intersection_map Intersection_map;
using Intersection_map = typename X_monotone_curve_2::Intersection_map;
mutable Intersection_map inter_map; // Mapping pairs of curve IDs to their
// intersection points.
@ -78,8 +78,7 @@ public:
{}
/*! obtains the next curve index. */
static unsigned int get_index ()
{
static unsigned int get_index() {
#ifdef CGAL_NO_ATOMIC
static unsigned int index;
#else
@ -91,8 +90,7 @@ public:
/// \name Basic functor definitions.
//@{
class Compare_x_2
{
class Compare_x_2 {
public:
/*! compares the \f$x\f$-coordinates of two points.
* \param p1 The first point.
@ -101,23 +99,17 @@ public:
* SMALLER if x(p1) < x(p2);
* EQUAL if x(p1) = x(p2).
*/
Comparison_result operator() (const Point_2& p1, const Point_2& p2) const
{
if (p1.identical (p2))
return (EQUAL);
Comparison_result operator() (const Point_2& p1, const Point_2& p2) const {
if (p1.identical (p2)) return (EQUAL);
return (CGAL::compare (p1.x(), p2.x()));
}
};
/*! obtains a `Compare_x_2` functor object. */
Compare_x_2 compare_x_2_object () const
{
return Compare_x_2();
}
Compare_x_2 compare_x_2_object () const { return Compare_x_2(); }
class Compare_xy_2
{
class Compare_xy_2 {
public:
/*! compares two points lexigoraphically: by x, then by y.
* \param p1 The first point.
@ -126,15 +118,11 @@ public:
* SMALLER if x(p1) < x(p2), or if x(p1) = x(p2) and y(p1) < y(p2);
* EQUAL if the two points are equal.
*/
Comparison_result operator() (const Point_2& p1, const Point_2& p2) const
{
if (p1.identical (p2))
return (EQUAL);
Comparison_result operator() (const Point_2& p1, const Point_2& p2) const {
if (p1.identical (p2)) return (EQUAL);
Comparison_result res = CGAL::compare (p1.x(), p2.x());
if (res != EQUAL)
return (res);
Comparison_result res = CGAL::compare(p1.x(), p2.x());
if (res != EQUAL) return (res);
return (CGAL::compare (p1.y(), p2.y()));
}
@ -142,69 +130,51 @@ public:
/*! obtains a Compare_xy_2 functor object. */
Compare_xy_2 compare_xy_2_object () const
{
return Compare_xy_2();
}
{ return Compare_xy_2(); }
class Construct_min_vertex_2
{
class Construct_min_vertex_2 {
public:
/*! obtains the left endpoint of the \f$x\f$-monotone curve (segment).
* \param cv The curve.
* \return The left endpoint.
*/
const Point_2& operator() (const X_monotone_curve_2 & cv) const
{
return (cv.left());
}
{ return (cv.left()); }
};
/*! obtains a `Construct_min_vertex_2` functor object. */
Construct_min_vertex_2 construct_min_vertex_2_object () const
{
return Construct_min_vertex_2();
}
{ return Construct_min_vertex_2(); }
class Construct_max_vertex_2
{
class Construct_max_vertex_2 {
public:
/*! obtains the right endpoint of the \f$x\f$-monotone curve (segment).
* \param cv The curve.
* \return The right endpoint.
*/
const Point_2& operator() (const X_monotone_curve_2 & cv) const
{
return (cv.right());
}
{ return (cv.right()); }
};
/*! obtains a Construct_max_vertex_2 functor object. */
Construct_max_vertex_2 construct_max_vertex_2_object () const
{
return Construct_max_vertex_2();
}
{ return Construct_max_vertex_2(); }
class Is_vertical_2
{
class Is_vertical_2 {
public:
/*! checks whether the given \f$x\f$-monotone curve is a vertical segment.
* \param cv The curve.
* \return (true) if the curve is a vertical segment; (false) otherwise.
*/
bool operator() (const X_monotone_curve_2& cv) const
{
return (cv.is_vertical());
}
{ return (cv.is_vertical()); }
};
/*! obtains an `Is_vertical_2` functor object. */
Is_vertical_2 is_vertical_2_object () const
{
return Is_vertical_2();
}
{ return Is_vertical_2(); }
class Compare_y_at_x_2
{
class Compare_y_at_x_2 {
public:
/*! returns the location of the given point with respect to the input curve.
* \param cv The curve.
@ -214,23 +184,19 @@ public:
* LARGER if y(p) > cv(x(p)), i.e. the point is above the curve;
* EQUAL if p lies on the curve.
*/
Comparison_result operator() (const Point_2& p,
const X_monotone_curve_2& cv) const
{
CGAL_precondition (cv.is_in_x_range (p));
Comparison_result operator()(const Point_2& p,
const X_monotone_curve_2& cv) const {
CGAL_precondition (cv.is_in_x_range(p));
return (cv.point_position (p));
return (cv.point_position(p));
}
};
/*! obtains a `Compare_y_at_x_2` functor object. */
Compare_y_at_x_2 compare_y_at_x_2_object () const
{
return Compare_y_at_x_2();
}
{ return Compare_y_at_x_2(); }
class Compare_y_at_x_right_2
{
class Compare_y_at_x_right_2 {
public:
/*! compares the y value of two \f$x\f$-monotone curves immediately to the
* right of their intersection point.
@ -244,30 +210,29 @@ public:
*/
Comparison_result operator() (const X_monotone_curve_2& cv1,
const X_monotone_curve_2& cv2,
const Point_2& p) const
{
const Point_2& p) const {
// Make sure that p lies on both curves, and that both are defined to its
// right (so their right endpoint is lexicographically larger than p).
CGAL_precondition (cv1.point_position (p) == EQUAL &&
cv2.point_position (p) == EQUAL);
if ((CGAL::compare (cv1.left().x(),cv1.right().x()) == EQUAL) &&
(CGAL::compare (cv2.left().x(),cv2.right().x()) == EQUAL))
{ //both cv1 and cv2 are vertical
(CGAL::compare (cv2.left().x(),cv2.right().x()) == EQUAL)) {
//both cv1 and cv2 are vertical
CGAL_precondition (!(cv1.right()).equals(p) && !(cv2.right()).equals(p));
}
else if ((CGAL::compare (cv1.left().x(),cv1.right().x()) != EQUAL) &&
(CGAL::compare (cv2.left().x(),cv2.right().x()) == EQUAL))
{ //only cv1 is vertical
(CGAL::compare (cv2.left().x(),cv2.right().x()) == EQUAL)) {
//only cv1 is vertical
CGAL_precondition (!(cv1.right()).equals(p));
}
else if ((CGAL::compare (cv1.left().x(),cv1.right().x()) == EQUAL) &&
(CGAL::compare (cv2.left().x(),cv2.right().x()) != EQUAL))
{ //only cv2 is vertical
(CGAL::compare (cv2.left().x(),cv2.right().x()) != EQUAL)) {
//only cv2 is vertical
CGAL_precondition (!(cv2.right()).equals(p));
}
else
{ //both cv1 and cv2 are non vertical
else {
//both cv1 and cv2 are non vertical
CGAL_precondition (CGAL::compare (cv1.right().x(),p.x()) == LARGER &&
CGAL::compare (cv2.right().x(),p.x()) == LARGER);
}
@ -278,12 +243,9 @@ public:
/*! obtains a `Compare_y_at_x_right_2` functor object. */
Compare_y_at_x_right_2 compare_y_at_x_right_2_object () const
{
return Compare_y_at_x_right_2();
}
{ return Compare_y_at_x_right_2(); }
class Compare_y_at_x_left_2
{
class Compare_y_at_x_left_2 {
public:
/*! compares the \f$y\f$-value of two \f$x\f$-monotone curves immediately to
* the left of their intersection point.
@ -297,8 +259,7 @@ public:
*/
Comparison_result operator() (const X_monotone_curve_2& cv1,
const X_monotone_curve_2& cv2,
const Point_2& p) const
{
const Point_2& p) const {
// Make sure that p lies on both curves, and that both are defined to its
// left (so their left endpoint is lexicographically smaller than p).
@ -306,25 +267,25 @@ public:
cv2.point_position (p) == EQUAL);
if ((CGAL::compare (cv1.left().x(),cv1.right().x()) == EQUAL) &&
(CGAL::compare (cv2.left().x(),cv2.right().x()) == EQUAL))
{ //both cv1 and cv2 are vertical
CGAL_precondition (!(cv1.left()).equals(p) && !(cv2.left()).equals(p));
}
else if ((CGAL::compare (cv1.left().x(),cv1.right().x()) != EQUAL) &&
(CGAL::compare (cv2.left().x(),cv2.right().x()) == EQUAL))
{ //only cv1 is vertical
CGAL_precondition (!(cv1.left()).equals(p));
}
else if ((CGAL::compare (cv1.left().x(),cv1.right().x()) == EQUAL) &&
(CGAL::compare (cv2.left().x(),cv2.right().x()) != EQUAL))
{ //only cv2 is vertical
CGAL_precondition (!(cv2.left()).equals(p));
}
else
{ //both cv1 and cv2 are non vertical
(CGAL::compare (cv2.left().x(),cv2.right().x()) == EQUAL)) {
//both cv1 and cv2 are vertical
CGAL_precondition (!(cv1.left()).equals(p) && !(cv2.left()).equals(p));
}
else if ((CGAL::compare (cv1.left().x(),cv1.right().x()) != EQUAL) &&
(CGAL::compare (cv2.left().x(),cv2.right().x()) == EQUAL)) {
//only cv1 is vertical
CGAL_precondition (!(cv1.left()).equals(p));
}
else if ((CGAL::compare (cv1.left().x(),cv1.right().x()) == EQUAL) &&
(CGAL::compare (cv2.left().x(),cv2.right().x()) != EQUAL)) {
//only cv2 is vertical
CGAL_precondition (!(cv2.left()).equals(p));
}
else {
//both cv1 and cv2 are non vertical
CGAL_precondition (CGAL::compare (cv1.left().x(),p.x()) == SMALLER &&
CGAL::compare (cv2.left().x(),p.x()) == SMALLER);
}
}
// Compare the two curves immediately to the left of p:
return (cv1.compare_to_left (cv2, p));
}
@ -332,12 +293,9 @@ public:
/*! obtains a `Compare_y_at_x_left_2` functor object. */
Compare_y_at_x_left_2 compare_y_at_x_left_2_object () const
{
return Compare_y_at_x_left_2();
}
{ return Compare_y_at_x_left_2(); }
class Equal_2
{
class Equal_2 {
public:
/*! checks if the two \f$x\f$-monotone curves are the same (have the same
* graph).
@ -346,10 +304,8 @@ public:
* \return (true) if the two curves are the same; (false) otherwise.
*/
bool operator() (const X_monotone_curve_2& cv1,
const X_monotone_curve_2& cv2) const
{
if (&cv1 == &cv2)
return (true);
const X_monotone_curve_2& cv2) const {
if (&cv1 == &cv2) return (true);
return (cv1.equals (cv2));
}
@ -360,24 +316,20 @@ public:
* \return (true) if the two point are the same; (false) otherwise.
*/
bool operator() (const Point_2& p1, const Point_2& p2) const
{
return (p1.equals (p2));
}
{ return (p1.equals (p2)); }
};
/*! obtains an `Equal_2` functor object. */
Equal_2 equal_2_object () const
{
return Equal_2();
}
{ return Equal_2(); }
//@}
/// \name Functor definitions for approximations. Used by the landmarks
// point-location strategy and the drawing procedure.
//@{
typedef double Approximate_number_type;
typedef CGAL::Cartesian<Approximate_number_type> Approximate_kernel;
typedef Approximate_kernel::Point_2 Approximate_point_2;
using Approximate_number_type = double;
using Approximate_kernel = CGAL::Simple_cartesian<Approximate_number_type>;
using Approximate_point_2 = Approximate_kernel::Point_2;
class Approximate_2 {
protected:
@ -557,7 +509,7 @@ public:
*/
class Make_x_monotone_2 {
private:
typedef Arr_circle_segment_traits_2<Kernel_, Filter> Self;
using Self = Arr_circle_segment_traits_2<Kernel_, Filter>;
bool m_use_cache;
@ -573,8 +525,7 @@ public:
* \return the past-the-end iterator.
*/
template <typename OutputIterator>
OutputIterator operator()(const Curve_2& cv, OutputIterator oi) const
{
OutputIterator operator()(const Curve_2& cv, OutputIterator oi) const {
// Increment the serial number of the curve cv, which will serve as its
// unique identifier.
unsigned int index = 0;
@ -591,7 +542,7 @@ public:
// Check the case of a degenerate circle (a point).
const typename Kernel::Circle_2& circ = cv.supporting_circle();
CGAL::Sign sign_rad = CGAL::sign (circ.squared_radius());
CGAL::Sign sign_rad = CGAL::sign (circ.squared_radius());
CGAL_precondition (sign_rad != NEGATIVE);
if (sign_rad == ZERO) {
@ -603,8 +554,8 @@ public:
// The curve is circular: compute the to vertical tangency points
// of the supporting circle.
Point_2 vpts[2];
unsigned int n_vpts = cv.vertical_tangency_points (vpts);
Point_2 vpts[2];
unsigned int n_vpts = cv.vertical_tangency_points (vpts);
if (cv.is_full()) {
CGAL_assertion (n_vpts == 2);
@ -674,8 +625,7 @@ public:
Make_x_monotone_2 make_x_monotone_2_object() const
{ return Make_x_monotone_2(m_use_cache); }
class Split_2
{
class Split_2 {
public:
/*! splits a given \f$x\f$-monotone curve at a given point into two
@ -687,8 +637,7 @@ public:
* \pre `p` lies on cv but is not one of its end-points.
*/
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 {
CGAL_precondition (cv.point_position(p)==EQUAL &&
! p.equals (cv.source()) &&
! p.equals (cv.target()));
@ -699,10 +648,7 @@ public:
};
/*! obtains a `Split_2` functor object. */
Split_2 split_2_object () const
{
return Split_2();
}
Split_2 split_2_object () const { return Split_2(); }
class Intersect_2 {
private:
@ -730,8 +676,7 @@ public:
/*! obtains an `Intersect_2` functor object. */
Intersect_2 intersect_2_object() const { return (Intersect_2(inter_map)); }
class Are_mergeable_2
{
class Are_mergeable_2 {
public:
/*! checks whether it is possible to merge two given \f$x\f$-monotone curves.
* \param cv1 The first curve.
@ -742,24 +687,19 @@ public:
*/
bool operator() (const X_monotone_curve_2& cv1,
const X_monotone_curve_2& cv2) const
{
return (cv1.can_merge_with (cv2));
}
{ return (cv1.can_merge_with (cv2)); }
};
/*! obtains an `Are_mergeable_2` functor object. */
Are_mergeable_2 are_mergeable_2_object () const
{
return Are_mergeable_2();
}
{ return Are_mergeable_2(); }
/*! \class Merge_2
* A functor that merges two \f$x\f$-monotone arcs into one.
*/
class Merge_2
{
class Merge_2 {
protected:
typedef Arr_circle_segment_traits_2<Kernel, Filter> Traits;
using Traits = Arr_circle_segment_traits_2<Kernel, Filter>;
/*! The traits (in case it has state) */
const Traits* m_traits;
@ -780,8 +720,7 @@ public:
*/
void operator() (const X_monotone_curve_2& cv1,
const X_monotone_curve_2& cv2,
X_monotone_curve_2& c) const
{
X_monotone_curve_2& c) const {
CGAL_precondition(m_traits->are_mergeable_2_object()(cv2, cv1));
c = cv1;
@ -790,20 +729,15 @@ public:
};
/*! obtains a `Merge_2` functor object. */
Merge_2 merge_2_object () const
{
return Merge_2(this);
}
Merge_2 merge_2_object () const { return Merge_2(this); }
class Compare_endpoints_xy_2
{
class Compare_endpoints_xy_2 {
public:
/*! compares lexicogrphic the endpoints of a \f$x\f$-monotone curve.
* \param cv the curve
* \return `SMALLER` if the curve is directed right, else return `LARGER`.
*/
Comparison_result operator()(const X_monotone_curve_2& cv) const
{
Comparison_result operator()(const X_monotone_curve_2& cv) const {
if(cv.is_directed_right())
return(SMALLER);
return (LARGER);
@ -812,32 +746,25 @@ public:
/*! obtains a `Compare_endpoints_xy_2` functor object. */
Compare_endpoints_xy_2 compare_endpoints_xy_2_object() const
{
return Compare_endpoints_xy_2();
}
{ return Compare_endpoints_xy_2(); }
class Construct_opposite_2
{
class Construct_opposite_2 {
public:
/*! constructs an opposite \f$x\f$-monotone curve.
* \param cv the curve
* \return an opposite \f$x\f$-monotone curve.
*/
X_monotone_curve_2 operator()(const X_monotone_curve_2& cv) const
{
return cv.construct_opposite();
}
{ return cv.construct_opposite(); }
};
/*! obtains a `Construct_opposite_2` functor object. */
Construct_opposite_2 construct_opposite_2_object() const
{
return Construct_opposite_2();
}
{ return Construct_opposite_2(); }
class Trim_2 {
protected:
typedef Arr_circle_segment_traits_2<Kernel, Filter> Traits;
using Traits = Arr_circle_segment_traits_2<Kernel, Filter>;
/*! The traits (in case it has state) */
const Traits& m_traits;
@ -860,8 +787,7 @@ public:
*/
X_monotone_curve_2 operator()(const X_monotone_curve_2& xcv,
const Point_2& src,
const Point_2& tgt)const
{
const Point_2& tgt)const {
// make functor objects
CGAL_precondition_code(Compare_y_at_x_2 compare_y_at_x_2 =
m_traits.compare_y_at_x_2_object());
@ -885,7 +811,6 @@ public:
Trim_2 trim_2_object() const { return Trim_2(*this); }
// @}
};
} // namespace CGAL

View File

@ -40,55 +40,54 @@
namespace CGAL {
namespace internal{
template <class CircularKernel>
class Non_x_monotonic_Circular_arc_2
: public CircularKernel::Circular_arc_2
{
typedef typename CircularKernel::FT FT;
typedef typename CircularKernel::Point_2 Point_2;
typedef typename CircularKernel::Line_2 Line_2;
typedef typename CircularKernel::Circle_2 Circle_2;
typedef typename CircularKernel::Circular_arc_point_2
Circular_arc_point_2;
typedef typename CircularKernel::Circular_arc_2 Base;
template <typename CircularKernel>
class Non_x_monotonic_Circular_arc_2 :
public CircularKernel::Circular_arc_2 {
using FT = typename CircularKernel::FT;
using Point_2 = typename CircularKernel::Point_2;
using Line_2 = typename CircularKernel::Line_2;
using Circle_2 = typename CircularKernel::Circle_2;
using Circular_arc_point_2 = typename CircularKernel::Circular_arc_point_2;
using Base = typename CircularKernel::Circular_arc_2;
public:
Non_x_monotonic_Circular_arc_2(): Base(){}
Non_x_monotonic_Circular_arc_2(const Circle_2 &c): Base(c){}
Non_x_monotonic_Circular_arc_2(const Circle_2& c): Base(c){}
// Not Documented
Non_x_monotonic_Circular_arc_2(const Circle_2 &support,
const Line_2 &l1, const bool b_l1,
const Line_2 &l2, const bool b_l2)
: Base(support,l1,b_l1,l2,b_l2){}
Non_x_monotonic_Circular_arc_2(const Circle_2& support,
const Line_2& l1, const bool b_l1,
const Line_2& l2, const bool b_l2) :
Base(support,l1,b_l1,l2,b_l2){}
// Not Documented
Non_x_monotonic_Circular_arc_2(const Circle_2 &c,
const Circle_2 &c1, const bool b_1,
const Circle_2 &c2, const bool b_2)
: Base(c,c1,b_1,c2,b_2)
Non_x_monotonic_Circular_arc_2(const Circle_2& c,
const Circle_2& c1, const bool b_1,
const Circle_2& c2, const bool b_2) :
Base(c,c1,b_1,c2,b_2)
{}
Non_x_monotonic_Circular_arc_2(const Point_2 &start,
const Point_2 &middle,
const Point_2 &end)
: Base(start,middle,end)
Non_x_monotonic_Circular_arc_2(const Point_2& start,
const Point_2& middle,
const Point_2& end) :
Base(start,middle,end)
{}
Non_x_monotonic_Circular_arc_2(const Circle_2 &support,
const Circular_arc_point_2 &begin,
const Circular_arc_point_2 &end)
: Base(support,begin,end)
Non_x_monotonic_Circular_arc_2(const Circle_2& support,
const Circular_arc_point_2& begin,
const Circular_arc_point_2& end) :
Base(support,begin,end)
{}
Non_x_monotonic_Circular_arc_2(const Point_2 &start,
const Point_2 &end,
const FT &bulge)
: Base(start,end,bulge)
Non_x_monotonic_Circular_arc_2(const Point_2& start,
const Point_2& end,
const FT& bulge) :
Base(start,end,bulge)
{}
Non_x_monotonic_Circular_arc_2(const Base& a) : Base(a) {}
Non_x_monotonic_Circular_arc_2(const Base& a) : Base(a) {}
};
} //namespace internal
@ -98,45 +97,40 @@ public:
template < typename CircularKernel >
class Arr_circular_arc_traits_2 {
CircularKernel ck;
public:
using Kernel = CircularKernel;
using Curve_2 = internal::Non_x_monotonic_Circular_arc_2<CircularKernel>;
using X_monotone_curve_2 = typename CircularKernel::Circular_arc_2;
typedef CircularKernel Kernel;
typedef internal::Non_x_monotonic_Circular_arc_2<CircularKernel> Curve_2;
typedef typename CircularKernel::Circular_arc_2 X_monotone_curve_2;
using Point = typename CircularKernel::Circular_arc_point_2;
using Point_2 = typename CircularKernel::Circular_arc_point_2;
typedef typename CircularKernel::Circular_arc_point_2 Point;
typedef typename CircularKernel::Circular_arc_point_2 Point_2;
using Multiplicity = std::size_t;
typedef unsigned int Multiplicity;
using Has_left_category = CGAL::Tag_false;
using Has_merge_category = CGAL::Tag_false;
using Has_do_intersect_category = CGAL::Tag_false;
typedef CGAL::Tag_false Has_left_category;
typedef CGAL::Tag_false Has_merge_category;
typedef CGAL::Tag_false Has_do_intersect_category;
using Left_side_category = Arr_oblivious_side_tag;
using Bottom_side_category = Arr_oblivious_side_tag;
using Top_side_category = Arr_oblivious_side_tag;
using Right_side_category = Arr_oblivious_side_tag;
typedef Arr_oblivious_side_tag Left_side_category;
typedef Arr_oblivious_side_tag Bottom_side_category;
typedef Arr_oblivious_side_tag Top_side_category;
typedef Arr_oblivious_side_tag Right_side_category;
Arr_circular_arc_traits_2(const CircularKernel& k = CircularKernel()) : ck(k) {}
Arr_circular_arc_traits_2(const CircularKernel &k = CircularKernel())
: ck(k) {}
typedef typename CircularKernel::Compare_x_2 Compare_x_2;
typedef typename CircularKernel::Compare_xy_2 Compare_xy_2;
typedef typename CircularKernel::Compare_y_at_x_2 Compare_y_at_x_2;
typedef typename CircularKernel::Compare_y_to_right_2 Compare_y_at_x_right_2;
typedef typename CircularKernel::Construct_circular_max_vertex_2
Construct_max_vertex_2;
typedef typename CircularKernel::Construct_circular_min_vertex_2
Construct_min_vertex_2;
typedef typename CircularKernel::Equal_2 Equal_2;
using Compare_x_2 = typename CircularKernel::Compare_x_2;
using Compare_xy_2 = typename CircularKernel::Compare_xy_2;
using Compare_y_at_x_2 = typename CircularKernel::Compare_y_at_x_2;
using Compare_y_at_x_right_2 = typename CircularKernel::Compare_y_to_right_2;
using Construct_max_vertex_2 = typename CircularKernel::Construct_circular_max_vertex_2;
using Construct_min_vertex_2 = typename CircularKernel::Construct_circular_min_vertex_2;
using Equal_2 = typename CircularKernel::Equal_2;
// typedef typename CircularKernel::Make_x_monotone_2 Make_x_monotone_2;
typedef typename CircularKernel::Split_2 Split_2;
typedef typename CircularKernel::Intersect_2 Intersect_2;
typedef typename CircularKernel::Is_vertical_2 Is_vertical_2;
using Split_2 = typename CircularKernel::Split_2;
using Intersect_2 = typename CircularKernel::Intersect_2;
using Is_vertical_2 = typename CircularKernel::Is_vertical_2;
Compare_x_2 compare_x_2_object() const
{ return ck.compare_x_2_object(); }
@ -160,26 +154,23 @@ public:
{ return ck.split_2_object(); }
Intersect_2 intersect_2_object() const
{ return ck.intersect_2_object(); }
{ return ck.intersect_2_object(); }
Construct_max_vertex_2 construct_max_vertex_2_object() const
{ return ck.construct_circular_max_vertex_2_object(); }
{ return ck.construct_circular_max_vertex_2_object(); }
Construct_min_vertex_2 construct_min_vertex_2_object() const
{ return ck.construct_circular_min_vertex_2_object(); }
{ return ck.construct_circular_min_vertex_2_object(); }
Is_vertical_2 is_vertical_2_object() const
{ return ck.is_vertical_2_object(); }
{ return ck.is_vertical_2_object(); }
//! A functor for subdividing curves into x-monotone curves.
class Make_x_monotone_2 {
public:
template <typename OutputIterator>
OutputIterator operator()(const Curve_2& arc, OutputIterator oi) const
{
typedef std::variant<Point_2, X_monotone_curve_2>
Make_x_monotone_result;
OutputIterator operator()(const Curve_2& arc, OutputIterator oi) const {
using Make_x_monotone_result = std::variant<Point_2, X_monotone_curve_2>;
std::vector<Make_x_monotone_result> objs;
CircularKernel().make_x_monotone_2_object()(arc, std::back_inserter(objs));

View File

@ -41,515 +41,395 @@
#include <CGAL/Arr_tags.h>
namespace CGAL {
namespace VariantFunctors{
// Takes an iterator range of Object(Line/Circular_arc/Point),
// returns a variant of Line, Circular_arc, and Point_2.
template <class CK, class Arc1, class Arc2, class OutputIterator>
OutputIterator
object_to_object_variant(const std::vector<CGAL::Object>& res1,
OutputIterator res2)
{
typedef typename CK::Circular_arc_point_2 Point_2;
typedef std::variant<Arc1, Arc2> X_monotone_curve_2;
typedef std::variant<Point_2, X_monotone_curve_2>
Make_x_monotone_result;
namespace VariantFunctors {
for (auto it = res1.begin(); it != res1.end(); ++it) {
if (const Arc1* arc = CGAL::object_cast<Arc1>(&*it)) {
std::variant<Arc1, Arc2> v = *arc;
*res2++ = Make_x_monotone_result(v);
}
else if (const Arc2* line = CGAL::object_cast<Arc2>(&*it)) {
std::variant<Arc1, Arc2> v = *line;
*res2++ = Make_x_monotone_result(v);
}
else if (const Point_2* p = CGAL::object_cast<Point_2>(&*it)) {
*res2++ = Make_x_monotone_result(*p);
}
else CGAL_error();
// Takes an iterator range of Object(Line/Circular_arc/Point),
// returns a variant of Line, Circular_arc, and Point_2.
template <typename CK, typename Arc1, typename Arc2, typename OutputIterator>
OutputIterator object_to_object_variant(const std::vector<CGAL::Object>& res1,
OutputIterator res2) {
using Point_2 = typename CK::Circular_arc_point_2;
using X_monotone_curve_2 = std::variant<Arc1, Arc2>;
using Make_x_monotone_result = std::variant<Point_2, X_monotone_curve_2>;
for (auto it = res1.begin(); it != res1.end(); ++it) {
if (const Arc1* arc = CGAL::object_cast<Arc1>(&*it)) {
std::variant<Arc1, Arc2> v = *arc;
*res2++ = Make_x_monotone_result(v);
}
else if (const Arc2* line = CGAL::object_cast<Arc2>(&*it)) {
std::variant<Arc1, Arc2> v = *line;
*res2++ = Make_x_monotone_result(v);
}
else if (const Point_2* p = CGAL::object_cast<Point_2>(&*it)) {
*res2++ = Make_x_monotone_result(*p);
}
else CGAL_error();
}
return res2;
}
template <typename CircularKernel, typename Arc1, typename Arc2>
class Compare_y_to_right_2 {
public:
using result_type = CGAL::Comparison_result;
using Circular_arc_point_2 = typename CircularKernel::Circular_arc_point_2;
result_type operator()(const std::variant<Arc1, Arc2>& a1,
const std::variant<Arc1, Arc2>& a2,
const Circular_arc_point_2& p) const {
if (const Arc1* arc1 = std::get_if<Arc1>(&a1)) {
if (const Arc1* arc2 = std::get_if<Arc1>(&a2)) {
return CircularKernel().compare_y_to_right_2_object()(*arc1, *arc2, p);
}
return res2;
else {
const Arc2* arc2e = std::get_if<Arc2>(&a2);
return CircularKernel().compare_y_to_right_2_object()(*arc1, *arc2e, p);
}
}
const Arc2* arc1 = std::get_if<Arc2>(&a1);
if (const Arc1* arc2 = std::get_if<Arc1>(&a2)) {
return CircularKernel().compare_y_to_right_2_object()(*arc1, *arc2, p);
}
const Arc2* arc2e = std::get_if<Arc2>(&a2);
return CircularKernel().compare_y_to_right_2_object()(*arc1, *arc2e, p);
}
};
template <typename CircularKernel>
class Variant_Equal_2 {
public:
template <typename T>
bool operator()(const T& a0, const T& a1) const
{ return CircularKernel().equal_2_object()(a0,a1); }
template <typename T1, typename T2>
bool operator()(const T1& , const T2&) const
{ return false; }
};
template <typename CircularKernel, class Arc1, class Arc2>
class Equal_2 : public CircularKernel::Equal_2 {
public:
using Curve_2 = std::variant< Arc1, Arc2>;
using result_type = bool;
using CircularKernel::Equal_2::operator();
using Circular_arc_point_2 = typename CircularKernel::Circular_arc_point_2;
using Line_arc_2 = typename CircularKernel::Line_arc_2;
using Circular_arc_2 = typename CircularKernel::Circular_arc_2;
using CK_Equal_2 = typename CircularKernel::Equal_2;
result_type operator()(const Circular_arc_point_2& p0,
const Circular_arc_point_2& p1) const
{ return CK_Equal_2()(p0, p1); }
result_type operator()(const Circular_arc_2& a0, const Circular_arc_2& a1) const
{ return CK_Equal_2()(a0, a1); }
result_type operator()(const Line_arc_2& a0, const Line_arc_2& a1) const
{ return CK_Equal_2()(a0, a1); }
result_type operator()(const Line_arc_2& /*a0*/, const Circular_arc_2& /*a1*/) const
{ return false; }
result_type operator()(const Circular_arc_2& /*a0*/, const Line_arc_2& /*a1*/) const
{ return false; }
result_type operator()(const Curve_2& a0, const Curve_2& a1) const
{ return std::visit(Variant_Equal_2<CircularKernel>(), a0, a1); }
};
template <typename CircularKernel, typename Arc1, typename Arc2>
class Compare_y_at_x_2 {
public:
using Circular_arc_point_2 = typename CircularKernel::Circular_arc_point_2;
using result_type = CGAL::Comparison_result;
result_type operator()(const Circular_arc_point_2& p,
const std::variant< Arc1, Arc2>& A1) const {
if (const Arc1* arc1 = std::get_if<Arc1>(&A1)){
return CircularKernel().compare_y_at_x_2_object()(p, *arc1);
}
else {
const Arc2* arc2 = std::get_if<Arc2>(&A1);
return CircularKernel().compare_y_at_x_2_object()(p, *arc2);
}
}
};
template <typename CircularKernel>
class Variant_Do_overlap_2 {
public:
template <typename T>
bool operator()(const T& a0, const T& a1) const
{ return CircularKernel().do_overlap_2_object()(a0, a1); }
template <typename T1, typename T2>
bool operator()(const T1&, const T2&) const
{ return false; }
};
template <typename CircularKernel, typename Arc1, typename Arc2>
class Do_overlap_2 {
public:
using Circular_arc_point_2 = typename CircularKernel::Circular_arc_point_2;
using result_type = bool;
result_type operator()(const std::variant< Arc1, Arc2>& A0,
const std::variant< Arc1, Arc2>& A1) const
{ return std::visit(Variant_Do_overlap_2<CircularKernel>(), A0, A1); }
};
//! A functor for subdividing curves into x-monotone curves.
template <typename CircularKernel, typename Arc1, typename Arc2>
class Make_x_monotone_2 {
public:
using Circular_arc_point_2 = typename CircularKernel::Circular_arc_point_2;
template <typename OutputIterator, typename Not_X_Monotone>
OutputIterator operator()(const std::variant<Arc1, Arc2, Not_X_Monotone>& A,
OutputIterator res) const {
if ( const Arc1* arc1 = std::get_if<Arc1>(&A)) {
return CircularKernel().make_x_monotone_2_object()(*arc1, res);
}
else {
const Arc2* arc2 = std::get_if<Arc2>(&A);
return CircularKernel().make_x_monotone_2_object()(*arc2, res);
}
}
};
template <typename CircularKernel, typename Arc1, typename Arc2>
class Intersect_2 {
public:
using Circular_arc_point_2 = typename CircularKernel::Circular_arc_point_2;
template <typename OutputIterator>
OutputIterator operator()(const std::variant< Arc1, Arc2>& c1,
const std::variant< Arc1, Arc2>& c2,
OutputIterator oi) const {
if (const Arc1* arc1 = std::get_if<Arc1>(&c1)) {
if ( const Arc1* arc2 = std::get_if<Arc1>(&c2)) {
return CircularKernel().intersect_2_object()(*arc1, *arc2, oi);
}
const Arc2* arc2 = std::get_if<Arc2>(&c2);
return CircularKernel().intersect_2_object()(*arc1, *arc2, oi);
}
template <class CircularKernel, class Arc1, class Arc2>
class Compare_y_to_right_2
{
public:
typedef CGAL::Comparison_result result_type;
typedef typename CircularKernel::Circular_arc_point_2
Circular_arc_point_2;
result_type
operator()(const std::variant< Arc1, Arc2 > &a1,
const std::variant< Arc1, Arc2 > &a2,
const Circular_arc_point_2 &p) const
{
if ( const Arc1* arc1 = std::get_if<Arc1>( &a1 ) ){
if ( const Arc1* arc2 = std::get_if<Arc1>( &a2 ) ){
return CircularKernel()
.compare_y_to_right_2_object()(*arc1, *arc2, p);
}
else {
const Arc2* arc2e = std::get_if<Arc2>( &a2 );
return CircularKernel()
.compare_y_to_right_2_object()(*arc1, *arc2e, p);
}
}
const Arc2* arc1 = std::get_if<Arc2>( &a1 );
if ( const Arc1* arc2 = std::get_if<Arc1>( &a2 ) ){
return CircularKernel()
.compare_y_to_right_2_object()(*arc1, *arc2, p);
}
const Arc2* arc2e = std::get_if<Arc2>( &a2 );
return CircularKernel()
.compare_y_to_right_2_object()(*arc1, *arc2e, p);
}
};
template <class CircularKernel>
class Variant_Equal_2
{
public :
template < typename T >
bool
operator()(const T &a0, const T &a1) const
{
return CircularKernel().equal_2_object()(a0,a1);
}
template < typename T1, typename T2 >
bool
operator()(const T1 &, const T2 &) const
{
return false;
}
};
template <class CircularKernel, class Arc1, class Arc2>
class Equal_2
: public CircularKernel::Equal_2
{
public:
typedef std::variant< Arc1, Arc2 > Curve_2;
typedef bool result_type;
using CircularKernel::Equal_2::operator();
typedef typename CircularKernel::Circular_arc_point_2
Circular_arc_point_2;
typedef typename CircularKernel::Line_arc_2 Line_arc_2;
typedef typename CircularKernel::Circular_arc_2 Circular_arc_2;
typedef typename CircularKernel::Equal_2 CK_Equal_2;
result_type
operator() (const Circular_arc_point_2 &p0,
const Circular_arc_point_2 &p1) const
{ return CK_Equal_2()(p0, p1); }
result_type
operator() (const Circular_arc_2 &a0, const Circular_arc_2 &a1) const
{ return CK_Equal_2()(a0, a1); }
result_type
operator() (const Line_arc_2 &a0, const Line_arc_2 &a1) const
{ return CK_Equal_2()(a0, a1); }
result_type
operator() ( const Line_arc_2 &/*a0*/, const Circular_arc_2 &/*a1*/) const
{ return false; }
result_type
operator() ( const Circular_arc_2 &/*a0*/, const Line_arc_2 &/*a1*/) const
{ return false; }
result_type
operator()(const Curve_2 &a0, const Curve_2 &a1) const
{
return std::visit
( Variant_Equal_2<CircularKernel>(), a0, a1 );
}
};
template <class CircularKernel, class Arc1, class Arc2>
class Compare_y_at_x_2
{
public:
typedef typename CircularKernel::Circular_arc_point_2
Circular_arc_point_2;
typedef CGAL::Comparison_result result_type;
result_type
operator() (const Circular_arc_point_2 &p,
const std::variant< Arc1, Arc2 > &A1) const
{
if ( const Arc1* arc1 = std::get_if<Arc1>( &A1 ) ){
return CircularKernel().compare_y_at_x_2_object()(p, *arc1);
}
else {
const Arc2* arc2 = std::get_if<Arc2>( &A1 );
return CircularKernel().compare_y_at_x_2_object()(p, *arc2);
}
}
};
template <class CircularKernel>
class Variant_Do_overlap_2
{
public:
template < typename T >
bool
operator()(const T &a0, const T &a1) const
{
return CircularKernel().do_overlap_2_object()(a0, a1);
}
template < typename T1, typename T2 >
bool
operator()(const T1 &, const T2 &) const
{
return false;
}
};
template <class CircularKernel, class Arc1, class Arc2>
class Do_overlap_2
{
public:
typedef typename CircularKernel::Circular_arc_point_2
Circular_arc_point_2;
typedef bool result_type;
result_type
operator()(const std::variant< Arc1, Arc2 > &A0,
const std::variant< Arc1, Arc2 > &A1) const
{
return std::visit
( Variant_Do_overlap_2<CircularKernel>(), A0, A1 );
}
};
//! A functor for subdividing curves into x-monotone curves.
template <class CircularKernel, class Arc1, class Arc2>
class Make_x_monotone_2
{
public:
typedef typename CircularKernel::Circular_arc_point_2
Circular_arc_point_2;
template < class OutputIterator,class Not_X_Monotone >
OutputIterator
operator()(const std::variant<Arc1, Arc2, Not_X_Monotone> &A,
OutputIterator res) const
{
if ( const Arc1* arc1 = std::get_if<Arc1>( &A ) ) {
return CircularKernel().
make_x_monotone_2_object()(*arc1, res);
}
else {
const Arc2* arc2 = std::get_if<Arc2>( &A );
return CircularKernel().
make_x_monotone_2_object()(*arc2, res);
}
}
};
template <class CircularKernel, class Arc1, class Arc2>
class Intersect_2
{
public:
typedef typename CircularKernel::Circular_arc_point_2
Circular_arc_point_2;
template < class OutputIterator >
OutputIterator
operator()(const std::variant< Arc1, Arc2 > &c1,
const std::variant< Arc1, Arc2 > &c2,
OutputIterator oi) const
{
if ( const Arc1* arc1 = std::get_if<Arc1>( &c1 ) ){
if ( const Arc1* arc2 = std::get_if<Arc1>( &c2 ) ){
return CircularKernel().intersect_2_object()(*arc1, *arc2, oi);
}
const Arc2* arc2 = std::get_if<Arc2>( &c2 );
return CircularKernel().intersect_2_object()(*arc1, *arc2, oi);
}
const Arc2* arc1e = std::get_if<Arc2>( &c1 );
if ( const Arc1* arc2 = std::get_if<Arc1>( &c2 ) ){
return CircularKernel().intersect_2_object()(*arc1e, *arc2, oi);
}
const Arc2* arc2 = std::get_if<Arc2>( &c2 );
return CircularKernel().intersect_2_object()(*arc1e, *arc2, oi);
}
};
template <class CircularKernel, class Arc1, class Arc2>
class Split_2
{
public:
typedef typename CircularKernel::Circular_arc_point_2
Circular_arc_point_2;
typedef void result_type;
result_type
operator()(const std::variant< Arc1, Arc2 > &A,
const Circular_arc_point_2 &p,
std::variant< Arc1, Arc2 > &ca1,
std::variant< Arc1, Arc2 > &ca2) const
{
// TODO : optimize by extracting the references from the variants ?
if ( const Arc1* arc1 = std::get_if<Arc1>( &A ) ){
Arc1 carc1;
Arc1 carc2;
CircularKernel().split_2_object()(*arc1, p, carc1, carc2);
ca1 = carc1;
ca2 = carc2;
return ;
}
else{
const Arc2* arc2 = std::get_if<Arc2>( &A );
Arc2 cline1;
Arc2 cline2;
CircularKernel().split_2_object()(*arc2, p, cline1, cline2);
ca1 = cline1;
ca2 = cline2;
return ;
}
}
};
template <class CircularKernel>
class Variant_Construct_min_vertex_2
{
typedef typename CircularKernel::Circular_arc_point_2
Circular_arc_point_2;
public :
typedef Circular_arc_point_2 result_type;
//typedef const result_type& qualified_result_type;
template < typename T >
//std::remove_reference_t<qualified_result_type>
Circular_arc_point_2
operator()(const T &a) const
{
//CGAL_kernel_precondition(CircularKernel().compare_xy_2_object()(a.left(), a.right())==CGAL::SMALLER);
return CircularKernel().construct_circular_min_vertex_2_object()(a);
}
};
template <class CircularKernel, class Arc1, class Arc2>
class Construct_min_vertex_2//: public Has_qrt
{
typedef typename CircularKernel::Circular_arc_point_2 Point_2;
public:
typedef Point_2 result_type;
//typedef const result_type& qualified_result_type;
//std::remove_reference_t<qualified_result_type>
result_type
operator() (const std::variant< Arc1, Arc2 > & cv) const
{
return std::visit
( Variant_Construct_min_vertex_2<CircularKernel>(), cv );
}
};
template <class CircularKernel>
class Variant_Construct_max_vertex_2
{
typedef typename CircularKernel::Circular_arc_point_2
Circular_arc_point_2;
public:
typedef Circular_arc_point_2 result_type;
//typedef const result_type& qualified_result_type;
template < typename T >
//std::remove_reference_t<qualified_result_type>
Circular_arc_point_2
operator()(const T &a) const
{
//CGAL_kernel_precondition(CircularKernel().compare_xy_2_object()(a.left(), a.right())==CGAL::SMALLER);
return (CircularKernel().construct_circular_max_vertex_2_object()(a));
}
};
template <class CircularKernel, class Arc1, class Arc2>
class Construct_max_vertex_2//: public Has_qrt
{
typedef typename CircularKernel::Circular_arc_point_2 Point_2;
public:
/*! obtains the right endpoint of the x-monotone curve (segment).
* \param cv The curve.
* \return The right endpoint.
*/
typedef Point_2 result_type;
//typedef const result_type& qualified_result_type;
//std::remove_reference<qualified_result_type>
result_type
operator() (const std::variant< Arc1, Arc2 > & cv) const
{
return std::visit
( Variant_Construct_max_vertex_2<CircularKernel>(), cv );
}
};
template <class CircularKernel>
class Variant_Is_vertical_2
{
public:
template < typename T >
bool
operator()(const T &a) const
{
return CircularKernel().is_vertical_2_object()(a);
}
};
template <class CircularKernel, class Arc1, class Arc2>
class Is_vertical_2
{
public:
typedef bool result_type;
bool operator() (const std::variant< Arc1, Arc2 >& cv) const
{
return std::visit
( Variant_Is_vertical_2<CircularKernel>(), cv );
}
};
const Arc2* arc1e = std::get_if<Arc2>(&c1);
if ( const Arc1* arc2 = std::get_if<Arc1>(&c2)) {
return CircularKernel().intersect_2_object()(*arc1e, *arc2, oi);
}
const Arc2* arc2 = std::get_if<Arc2>(&c2);
return CircularKernel().intersect_2_object()(*arc1e, *arc2, oi);
}
};
template <typename CircularKernel, typename Arc1, typename Arc2>
class Split_2 {
public:
using Circular_arc_point_2 = typename CircularKernel::Circular_arc_point_2;
using result_type = void;
// an empty class used to have different types between Curve_2 and X_monotone_curve_2
// in Arr_circular_line_arc_traits_2.
namespace internal_Argt_traits {
struct Not_X_Monotone{};
inline std::ostream& operator << (std::ostream& os, const Not_X_Monotone&)
{return os;}
result_type operator()(const std::variant< Arc1, Arc2>& A,
const Circular_arc_point_2& p,
std::variant< Arc1, Arc2>& ca1,
std::variant< Arc1, Arc2>& ca2) const {
// TODO : optimize by extracting the references from the variants ?
if (const Arc1* arc1 = std::get_if<Arc1>(&A)) {
Arc1 carc1;
Arc1 carc2;
CircularKernel().split_2_object()(*arc1, p, carc1, carc2);
ca1 = carc1;
ca2 = carc2;
return ;
}
else {
const Arc2* arc2 = std::get_if<Arc2>(&A);
Arc2 cline1;
Arc2 cline2;
CircularKernel().split_2_object()(*arc2, p, cline1, cline2);
ca1 = cline1;
ca2 = cline2;
return ;
}
}
};
/// Traits class for CGAL::Arrangement_2 (and similar) based on a CircularKernel.
template <typename CircularKernel>
class Variant_Construct_min_vertex_2 {
using Circular_arc_point_2 = typename CircularKernel::Circular_arc_point_2;
public:
using result_type = Circular_arc_point_2;
// using qualified_result_type = const result_type& ;
template < typename CircularKernel>
class Arr_circular_line_arc_traits_2 {
template <typename T>
//std::remove_reference_t<qualified_result_type>
Circular_arc_point_2 operator()(const T& a) const {
//CGAL_kernel_precondition(CircularKernel().compare_xy_2_object()(a.left(), a.right())==CGAL::SMALLER);
return CircularKernel().construct_circular_min_vertex_2_object()(a);
}
};
typedef Arr_circular_line_arc_traits_2< CircularKernel > Self;
template <typename CircularKernel, typename Arc1, typename Arc2>
class Construct_min_vertex_2 {
//: public Has_qrt
using Point_2 = typename CircularKernel::Circular_arc_point_2;
typedef typename CircularKernel::Line_arc_2 Arc1;
typedef typename CircularKernel::Circular_arc_2 Arc2;
public:
using result_type = Point_2;
// using qualified_result_type = const result_type&;
public:
//std::remove_reference_t<qualified_result_type>
result_type operator() (const std::variant< Arc1, Arc2>& cv) const
{ return std::visit(Variant_Construct_min_vertex_2<CircularKernel>(), cv); }
};
typedef CircularKernel Kernel;
typedef typename CircularKernel::Circular_arc_point_2
Circular_arc_point_2;
template <typename CircularKernel>
class Variant_Construct_max_vertex_2 {
using Circular_arc_point_2 = typename CircularKernel::Circular_arc_point_2;
public:
using result_type = Circular_arc_point_2;
// using qualified_result_type = const result_type&;
typedef typename CircularKernel::Circular_arc_point_2 Point;
typedef typename CircularKernel::Circular_arc_point_2 Point_2;
template <typename T>
//std::remove_reference_t<qualified_result_type>
Circular_arc_point_2 operator()(const T& a) const {
//CGAL_kernel_precondition(CircularKernel().compare_xy_2_object()(a.left(), a.right())==CGAL::SMALLER);
return (CircularKernel().construct_circular_max_vertex_2_object()(a));
}
};
typedef unsigned int Multiplicity;
template <typename CircularKernel, typename Arc1, typename Arc2>
class Construct_max_vertex_2 {
//: public Has_qrt
using Point_2 = typename CircularKernel::Circular_arc_point_2;
typedef CGAL::Tag_false Has_left_category;
typedef CGAL::Tag_false Has_merge_category;
typedef CGAL::Tag_false Has_do_intersect_category;
public:
/*! obtains the right endpoint of the x-monotone curve (segment).
* \param cv The curve.
* \return The right endpoint.
*/
using result_type = Point_2;
// using qualified_result_type = const result_type&;
typedef Arr_oblivious_side_tag Left_side_category;
typedef Arr_oblivious_side_tag Bottom_side_category;
typedef Arr_oblivious_side_tag Top_side_category;
typedef Arr_oblivious_side_tag Right_side_category;
//std::remove_reference<qualified_result_type>
result_type operator() (const std::variant<Arc1, Arc2>& cv) const
{ return std::visit(Variant_Construct_max_vertex_2<CircularKernel>(), cv); }
};
typedef internal_Argt_traits::Not_X_Monotone Not_X_Monotone;
template <typename CircularKernel>
class Variant_Is_vertical_2 {
public:
template <typename T>
bool operator()(const T& a) const
{ return CircularKernel().is_vertical_2_object()(a); }
};
typedef std::variant< Arc1, Arc2, Not_X_Monotone > Curve_2;
typedef std::variant< Arc1, Arc2 > X_monotone_curve_2;
template <typename CircularKernel, typename Arc1, typename Arc2>
class Is_vertical_2 {
public:
using result_type = bool;
private:
CircularKernel ck;
public:
bool operator() (const std::variant<Arc1, Arc2>& cv) const
{ return std::visit(Variant_Is_vertical_2<CircularKernel>(), cv); }
};
Arr_circular_line_arc_traits_2(const CircularKernel &k = CircularKernel())
: ck(k) {}
}
typedef typename CircularKernel::Compare_x_2 Compare_x_2;
typedef typename CircularKernel::Compare_xy_2 Compare_xy_2;
typedef typename
VariantFunctors::Construct_min_vertex_2<CircularKernel, Arc1, Arc2>
Construct_min_vertex_2;
typedef
VariantFunctors::Construct_max_vertex_2<CircularKernel, Arc1, Arc2>
Construct_max_vertex_2;
typedef VariantFunctors::Is_vertical_2<CircularKernel, Arc1, Arc2>
Is_vertical_2;
typedef VariantFunctors::Compare_y_at_x_2<CircularKernel, Arc1, Arc2>
Compare_y_at_x_2;
typedef VariantFunctors::Compare_y_to_right_2<CircularKernel, Arc1, Arc2>
Compare_y_at_x_right_2;
typedef VariantFunctors::Equal_2<CircularKernel, Arc1, Arc2>
Equal_2;
typedef VariantFunctors::Make_x_monotone_2<CircularKernel, Arc1, Arc2>
Make_x_monotone_2;
typedef VariantFunctors::Split_2<CircularKernel, Arc1, Arc2>
Split_2;
typedef VariantFunctors::Intersect_2<CircularKernel, Arc1, Arc2>
Intersect_2;
// an empty class used to have different types between Curve_2 and X_monotone_curve_2
// in Arr_circular_line_arc_traits_2.
namespace internal_Argt_traits {
Compare_x_2 compare_x_2_object() const
{ return ck.compare_x_2_object(); }
struct Not_X_Monotone{};
Compare_xy_2 compare_xy_2_object() const
{ return ck.compare_xy_2_object(); }
inline std::ostream& operator << (std::ostream& os, const Not_X_Monotone&) { return os; }
Compare_y_at_x_2 compare_y_at_x_2_object() const
{ return Compare_y_at_x_2(); }
}
Compare_y_at_x_right_2 compare_y_at_x_right_2_object() const
{ return Compare_y_at_x_right_2(); }
/// Traits class for CGAL::Arrangement_2 (and similar) based on a CircularKernel.
Equal_2 equal_2_object() const
{ return Equal_2(); }
template <typename CircularKernel>
class Arr_circular_line_arc_traits_2 {
using Self = Arr_circular_line_arc_traits_2<CircularKernel>;
Make_x_monotone_2 make_x_monotone_2_object() const
{ return Make_x_monotone_2(); }
using Arc1 = typename CircularKernel::Line_arc_2;
using Arc2 = typename CircularKernel::Circular_arc_2;
Split_2 split_2_object() const
{ return Split_2(); }
public:
using Kernel = CircularKernel;
using Circular_arc_point_2 = typename CircularKernel::Circular_arc_point_2;
Intersect_2 intersect_2_object() const
{ return Intersect_2(); }
using Point = typename CircularKernel::Circular_arc_point_2;
using Point_2 = typename CircularKernel::Circular_arc_point_2;
Construct_min_vertex_2 construct_min_vertex_2_object() const
{ return Construct_min_vertex_2(); }
using Multiplicity = std::size_t;
Construct_max_vertex_2 construct_max_vertex_2_object() const
{ return Construct_max_vertex_2(); }
using Has_left_category = CGAL::Tag_false;
using Has_merge_category = CGAL::Tag_false;
using Has_do_intersect_category = CGAL::Tag_false;
Is_vertical_2 is_vertical_2_object() const
{ return Is_vertical_2();}
using Left_side_category = Arr_oblivious_side_tag;
using Bottom_side_category = Arr_oblivious_side_tag;
using Top_side_category = Arr_oblivious_side_tag;
using Right_side_category = Arr_oblivious_side_tag;
using Not_X_Monotone = internal_Argt_traits::Not_X_Monotone;
using Curve_2 = std::variant<Arc1, Arc2, Not_X_Monotone>;
using X_monotone_curve_2 = std::variant<Arc1, Arc2>;
private:
CircularKernel ck;
public:
Arr_circular_line_arc_traits_2(const CircularKernel& k = CircularKernel()) : ck(k) {}
using Compare_x_2 = typename CircularKernel::Compare_x_2;
using Compare_xy_2 = typename CircularKernel::Compare_xy_2;
using Construct_min_vertex_2 = typename VariantFunctors::Construct_min_vertex_2<CircularKernel, Arc1, Arc2>;
using Construct_max_vertex_2 = VariantFunctors::Construct_max_vertex_2<CircularKernel, Arc1, Arc2>;
using Is_vertical_2 = VariantFunctors::Is_vertical_2<CircularKernel, Arc1, Arc2>;
using Compare_y_at_x_2 = VariantFunctors::Compare_y_at_x_2<CircularKernel, Arc1, Arc2>;
using Compare_y_at_x_right_2 = VariantFunctors::Compare_y_to_right_2<CircularKernel, Arc1, Arc2>;
using Equal_2 = VariantFunctors::Equal_2<CircularKernel, Arc1, Arc2>;
using Make_x_monotone_2 = VariantFunctors::Make_x_monotone_2<CircularKernel, Arc1, Arc2>;
using Split_2 = VariantFunctors::Split_2<CircularKernel, Arc1, Arc2>;
using Intersect_2 = VariantFunctors::Intersect_2<CircularKernel, Arc1, Arc2>;
Compare_x_2 compare_x_2_object() const
{ return ck.compare_x_2_object(); }
Compare_xy_2 compare_xy_2_object() const
{ return ck.compare_xy_2_object(); }
Compare_y_at_x_2 compare_y_at_x_2_object() const
{ return Compare_y_at_x_2(); }
Compare_y_at_x_right_2 compare_y_at_x_right_2_object() const
{ return Compare_y_at_x_right_2(); }
Equal_2 equal_2_object() const
{ return Equal_2(); }
Make_x_monotone_2 make_x_monotone_2_object() const
{ return Make_x_monotone_2(); }
Split_2 split_2_object() const
{ return Split_2(); }
Intersect_2 intersect_2_object() const
{ return Intersect_2(); }
Construct_min_vertex_2 construct_min_vertex_2_object() const
{ return Construct_min_vertex_2(); }
Construct_max_vertex_2 construct_max_vertex_2_object() const
{ return Construct_max_vertex_2(); }
Is_vertical_2 is_vertical_2_object() const
{ return Is_vertical_2();}
};
} // namespace CGAL

View File

@ -32,7 +32,7 @@
#include <boost/math/constants/constants.hpp>
#include <CGAL/Cartesian.h>
#include <CGAL/Simple_cartesian.h>
#include <CGAL/tags.h>
#include <CGAL/Arr_tags.h>
#include <CGAL/Arr_enums.h>
@ -59,37 +59,37 @@ namespace CGAL {
template <typename RatKernel, typename AlgKernel, typename NtTraits>
class Arr_conic_traits_2 {
public:
typedef RatKernel Rat_kernel;
typedef AlgKernel Alg_kernel;
typedef NtTraits Nt_traits;
using Rat_kernel = RatKernel;
using Alg_kernel = AlgKernel;
using Nt_traits = NtTraits;
typedef typename Rat_kernel::FT Rational;
typedef typename Rat_kernel::Point_2 Rat_point_2;
typedef typename Rat_kernel::Segment_2 Rat_segment_2;
typedef typename Rat_kernel::Line_2 Rat_line_2;
typedef typename Rat_kernel::Circle_2 Rat_circle_2;
using Rational = typename Rat_kernel::FT;
using Rat_point_2 = typename Rat_kernel::Point_2;
using Rat_segment_2 = typename Rat_kernel::Segment_2;
using Rat_line_2 = typename Rat_kernel::Line_2;
using Rat_circle_2 = typename Rat_kernel::Circle_2;
typedef typename Alg_kernel::FT Algebraic;
typedef typename Alg_kernel::Point_2 Alg_point_2;
using Algebraic = typename Alg_kernel::FT;
using Alg_point_2 = typename Alg_kernel::Point_2;
typedef typename Nt_traits::Integer Integer;
using Integer = typename Nt_traits::Integer;
// Category tags:
typedef Tag_true Has_left_category;
typedef Tag_true Has_merge_category;
typedef Tag_false Has_do_intersect_category;
using Has_left_category = Tag_true;
using Has_merge_category = Tag_true;
using Has_do_intersect_category = Tag_false;
//typedef std::true_type Has_line_segment_constructor;
typedef Arr_oblivious_side_tag Left_side_category;
typedef Arr_oblivious_side_tag Bottom_side_category;
typedef Arr_oblivious_side_tag Top_side_category;
typedef Arr_oblivious_side_tag Right_side_category;
using Left_side_category = Arr_oblivious_side_tag;
using Bottom_side_category = Arr_oblivious_side_tag;
using Top_side_category = Arr_oblivious_side_tag;
using Right_side_category = Arr_oblivious_side_tag;
// Traits objects:
typedef Conic_arc_2<Rat_kernel, Alg_kernel, Nt_traits> Curve_2;
typedef Conic_x_monotone_arc_2<Curve_2> X_monotone_curve_2;
typedef Conic_point_2<Alg_kernel> Point_2;
typedef size_t Multiplicity;
using Curve_2 = Conic_arc_2<Rat_kernel, Alg_kernel, Nt_traits>;
using X_monotone_curve_2 = Conic_x_monotone_arc_2<Curve_2>;
using Point_2 = Conic_point_2<Alg_kernel>;
using Multiplicity = std::size_t;
private:
// Type definition for the intersection points mapping.
@ -106,16 +106,14 @@ private:
}
};
typedef std::pair<Point_2, Multiplicity> Intersection_point;
typedef std::list<Intersection_point> Intersection_list;
typedef std::map<Conic_pair, Intersection_list, Less_conic_pair>
Intersection_map;
typedef typename Intersection_map::iterator Intersection_map_iterator;
using Intersection_point = std::pair<Point_2, Multiplicity>;
using Intersection_list = std::list<Intersection_point>;
using Intersection_map = std::map<Conic_pair, Intersection_list, Less_conic_pair>;
using Intersection_map_iterator = typename Intersection_map::iterator;
typedef std::shared_ptr<Rat_kernel> Shared_rat_kernel;
typedef std::shared_ptr<Alg_kernel> Shared_alg_kernel;
typedef std::shared_ptr<Nt_traits> Shared_nt_traits;
using Shared_rat_kernel = std::shared_ptr<Rat_kernel>;
using Shared_alg_kernel = std::shared_ptr<Alg_kernel>;
using Shared_nt_traits = std::shared_ptr<Nt_traits>;
const Shared_rat_kernel m_rat_kernel;
const Shared_alg_kernel m_alg_kernel;
@ -127,10 +125,10 @@ private:
public:
/*! constructs default.
*/
Arr_conic_traits_2()
: m_rat_kernel(std::make_shared<Rat_kernel>()),
m_alg_kernel(std::make_shared<Alg_kernel>()),
m_nt_traits(std::make_shared<Nt_traits>())
Arr_conic_traits_2() :
m_rat_kernel(std::make_shared<Rat_kernel>()),
m_alg_kernel(std::make_shared<Alg_kernel>()),
m_nt_traits(std::make_shared<Nt_traits>())
{}
/*! constructs from resources.
@ -360,8 +358,7 @@ public:
*/
Comparison_result operator()(const X_monotone_curve_2& xcv1,
const X_monotone_curve_2& xcv2,
const Point_2& p) const
{
const Point_2& p) const {
// Make sure that p lies on both curves, and that both are defined to its
// left (so their left endpoint is lexicographically smaller than p).
CGAL_precondition(m_traits.contains_point(xcv1, p) &&
@ -538,8 +535,7 @@ public:
*/
Comparison_result operator()(const X_monotone_curve_2& xcv1,
const X_monotone_curve_2& xcv2,
const Point_2& p) const
{
const Point_2& p) const {
// Make sure that p lies on both curves, and that both are defined to its
// left (so their left endpoint is lexicographically smaller than p).
CGAL_precondition(m_traits.contains_point(xcv1, p) &&
@ -703,8 +699,7 @@ public:
* \return `true` if the two curves are the same; `false` otherwise.
*/
bool operator()(const X_monotone_curve_2& xcv1,
const X_monotone_curve_2& xcv2) const
{
const X_monotone_curve_2& xcv2) const {
if (&xcv1 == &xcv2) return true;
return equals(xcv1, xcv2);
}
@ -924,8 +919,7 @@ public:
if (((cv.orientation() == COUNTERCLOCKWISE) &&
(start_pos == order_vpts)) ||
((cv.orientation() == CLOCKWISE) && (start_pos != order_vpts)))
{
((cv.orientation() == CLOCKWISE) && (start_pos != order_vpts))) {
ind_first = 1;
ind_second = 0;
}
@ -1101,8 +1095,7 @@ public:
else if (m_traits.is_between_endpoints(xcv2, xcv1.source()) &&
m_traits.is_between_endpoints(xcv2, xcv1.target()) &&
(m_traits.is_strictly_between_endpoints(xcv2, xcv1.source()) ||
m_traits.is_strictly_between_endpoints(xcv2, xcv1.target())))
{
m_traits.is_strictly_between_endpoints(xcv2, xcv1.target()))) {
// Case 4 - *this: +----------->
// arc: +================>
overlap = xcv1;
@ -1285,8 +1278,7 @@ public:
for (i = 0; i < n_xs; ++i) {
for (j = 0; j < n_ys; ++j) {
if (xcv1.is_on_supporting_conic(xs[i], ys[j]) &&
xcv2.is_on_supporting_conic(xs[i], ys[j]))
{
xcv2.is_on_supporting_conic(xs[i], ys[j])) {
// Create the intersection point and set its generating conics.
Point_2 ip(xs[i], ys[j]);
@ -1314,8 +1306,7 @@ public:
OutputIterator intersect(const X_monotone_curve_2& xcv1,
const X_monotone_curve_2& xcv2,
Intersection_map& inter_map,
OutputIterator oi) const
{
OutputIterator oi) const {
if (m_traits.has_same_supporting_conic(xcv1, xcv2)) {
// Check for overlaps between the two arcs.
X_monotone_curve_2 overlap;
@ -1392,8 +1383,7 @@ public:
// both \f$x\f$-monotone arcs.
for (auto iter = inter_list.begin(); iter != inter_list.end(); ++iter) {
if (m_traits.is_between_endpoints(xcv1, (*iter).first) &&
m_traits.is_between_endpoints(xcv2, (*iter).first))
{
m_traits.is_between_endpoints(xcv2, (*iter).first)) {
*oi++ = *iter;
}
}
@ -1481,8 +1471,7 @@ public:
*/
void operator()(const X_monotone_curve_2& xcv1,
const X_monotone_curve_2& xcv2,
X_monotone_curve_2& xcv) const
{
X_monotone_curve_2& xcv) const {
CGAL_precondition(m_traits.are_mergeable_2_object()(xcv2, xcv1));
xcv = xcv1;
merge(xcv, xcv2);
@ -1523,11 +1512,11 @@ public:
* point-location strategy and the drawing function.
*/
//@{
typedef double Approximate_number_type;
typedef CGAL::Cartesian<Approximate_number_type> Approximate_kernel;
typedef Approximate_kernel::Point_2 Approximate_point_2;
using Approximate_number_type = double;
using Approximate_kernel = CGAL::Simple_cartesian<Approximate_number_type>;
using Approximate_point_2 = Approximate_kernel::Point_2;
class Approximate_curve_length_2 {
class Approximate_length_2 {
protected:
using Traits = Arr_conic_traits_2<Rat_kernel, Alg_kernel, Nt_traits>;
@ -1537,7 +1526,7 @@ public:
/*! constructs
* \param traits the traits.
*/
Approximate_curve_length_2(const Traits& traits) : m_traits(traits) {}
Approximate_length_2(const Traits& traits) : m_traits(traits) {}
friend class Arr_conic_traits_2<Rat_kernel, Alg_kernel, Nt_traits>;
@ -1557,7 +1546,7 @@ public:
private:
/*! obtains the segment length.
*/
double segment_length(const X_monotone_curve_2& xcv) {
double segment_length(const X_monotone_curve_2& xcv) const {
auto min_vertex = m_traits.construct_min_vertex_2_object();
auto max_vertex = m_traits.construct_max_vertex_2_object();
const auto& minv = min_vertex(xcv);
@ -1597,7 +1586,7 @@ public:
/*! obtains the parabolic arc length.
*/
double parabola_length(const X_monotone_curve_2& xcv) {
double parabola_length(const X_monotone_curve_2& xcv) const {
double r_m, t_m, s_m, u_m, v_m, w_m;
double cost, sint;
double xs_t, ys_t, xt_t, yt_t;
@ -1617,7 +1606,7 @@ public:
return d;
}
double ellipse_length(const X_monotone_curve_2& xcv) {
double ellipse_length(const X_monotone_curve_2& xcv) const {
double r_m, t_m, s_m, u_m, v_m, w_m;
double cost, sint;
double xs_t, ys_t, xt_t, yt_t;
@ -1638,7 +1627,7 @@ public:
return d;
}
double hyperbola_length(const X_monotone_curve_2& /* xcv */) {
double hyperbola_length(const X_monotone_curve_2& /* xcv */) const {
CGAL_error_msg("Not implemented yet!");
double l(0.0);
return l;
@ -1901,8 +1890,7 @@ public:
template <typename OutputIterator>
OutputIterator approximate_parabola(const X_monotone_curve_2& xcv,
double error, OutputIterator oi,
bool l2r = true)
const {
bool l2r = true) const {
// std::cout << "PARABOLA\n";
auto min_vertex = m_traits.construct_min_vertex_2_object();
auto max_vertex = m_traits.construct_max_vertex_2_object();
@ -2104,8 +2092,7 @@ public:
*/
X_monotone_curve_2 operator()(const Curve_2& cv,
const Point_2& source, const Point_2& target,
const Conic_id& id) const
{
const Conic_id& id) const {
// Set the two endpoints.
X_monotone_curve_2 xcv(cv, id);
xcv.set_source(source);
@ -2122,8 +2109,7 @@ public:
* \return A segment connecting `source` and `target`.
*/
X_monotone_curve_2 operator()(const Point_2& source, const Point_2& target)
const
{
const {
X_monotone_curve_2 xcv;
// Set the basic properties.
@ -2157,8 +2143,7 @@ public:
X_monotone_curve_2 operator()(const Algebraic& a, const Algebraic& b,
const Algebraic& c,
const Point_2& source, const Point_2& target)
const
{
const {
auto cmp_xy = m_traits.m_alg_kernel->compare_xy_2_object();
Comparison_result res = cmp_xy(source, target);
CGAL_precondition(res != EQUAL);
@ -2238,8 +2223,7 @@ public:
*/
Curve_2 operator()(const Rational& r, const Rational& s, const Rational& t,
const Rational& u, const Rational& v, const Rational& w)
const
{
const {
// Ensure that the given curve is an ellipse (4rs - t^2 is positive).
CGAL_precondition(CGAL::sign(4*r*s - t*t) == POSITIVE);
@ -2445,8 +2429,7 @@ public:
if (! m_traits.is_strictly_between_endpoints(arc, mp2) ||
! m_traits.is_strictly_between_endpoints(arc, mp3) ||
! m_traits.is_strictly_between_endpoints(arc, mp4))
{
! m_traits.is_strictly_between_endpoints(arc, mp4)) {
arc.reset_flags(); // invalid arc
return arc;
}
@ -2853,8 +2836,7 @@ public:
* \pre both points must be interior and must lie on \c cv
*/
X_monotone_curve_2 operator()(const X_monotone_curve_2& xcv,
const Point_2& src, const Point_2& tgt) const
{
const Point_2& src, const Point_2& tgt) const {
// make functor objects
CGAL_precondition_code(Compare_y_at_x_2 compare_y_at_x_2 =
m_traits.compare_y_at_x_2_object());
@ -3084,16 +3066,14 @@ public:
const auto& target = cv.target();
// Make sure both endpoint lie on the supporting conic.
if (! is_on_supporting_conic(cv, source) ||
! is_on_supporting_conic(cv, target))
{
! is_on_supporting_conic(cv, target)) {
cv.reset_flags(); // invalid arc
return;
}
// Check whether we have a degree 2 curve.
if ((CGAL::sign(r) != ZERO) || (CGAL::sign(s) != ZERO) ||
(CGAL::sign(t) != ZERO))
{
(CGAL::sign(t) != ZERO)) {
if (cv.orientation() == COLLINEAR) {
// Make sure the midpoint is on the line pair (thus making sure that
// the two points are not taken from different lines).
@ -3105,8 +3085,7 @@ public:
m_nt_traits->convert(u)) * p_mid.x() +
(m_nt_traits->convert(s)*p_mid.y() +
m_nt_traits->convert(v)) * p_mid.y() +
m_nt_traits->convert(w)) != ZERO)
{
m_nt_traits->convert(w)) != ZERO) {
cv.reset_flags(); // invalid arc
return;
}
@ -3645,8 +3624,7 @@ public:
// Compute the degree of the underlying conic.
if ((CGAL::sign(xcv.r()) != ZERO) ||
(CGAL::sign(xcv.s()) != ZERO) ||
(CGAL::sign(xcv.t()) != ZERO))
{
(CGAL::sign(xcv.t()) != ZERO)) {
xcv.set_flag(X_monotone_curve_2::DEGREE_2);
xcv.set_flag(X_monotone_curve_2::IS_SPECIAL_SEGMENT);
}
@ -3856,8 +3834,7 @@ public:
for (int j = 0; j < n_ys; ++j) {
if (CGAL::compare(m_nt_traits->convert(Integer(two*s)) * ys[j],
-(m_nt_traits->convert(t) * xs[i] +
m_nt_traits->convert(v))) == EQUAL)
{
m_nt_traits->convert(v))) == EQUAL) {
ps[n++] = Point_2(xs[i], ys[j]);
break;
}
@ -4128,8 +4105,7 @@ public:
double& xs_t, double& ys_t, double& ts,
double& xt_t, double& yt_t, double& tt,
double& a, double& b, double& cx, double& cy,
bool l2r = true)
const {
bool l2r = true) const {
auto min_vertex = construct_min_vertex_2_object();
auto max_vertex = construct_max_vertex_2_object();
const auto& src = (l2r) ? min_vertex(xcv) : max_vertex(xcv);
@ -4206,8 +4182,7 @@ public:
double& xs_t, double& ys_t, double& ts,
double& xt_t, double& yt_t, double& tt,
double& a, double& b, double& cx, double& cy,
bool l2r = true)
const {
bool l2r = true) const {
auto min_vertex = construct_min_vertex_2_object();
auto max_vertex = construct_max_vertex_2_object();
const auto& src = (l2r) ? min_vertex(xcv) : max_vertex(xcv);

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

@ -28,7 +28,7 @@
#include <variant>
#include <CGAL/config.h>
#include <CGAL/Cartesian.h>
#include <CGAL/Simple_cartesian.h>
#include <CGAL/tags.h>
#include <CGAL/tss.h>
#include <CGAL/intersections.h>
@ -2856,7 +2856,7 @@ public:
/// \name Functor definitions for the landmarks point-location strategy.
//@{
using Approximate_number_type = double;
using Approximate_kernel = CGAL::Cartesian<Approximate_number_type>;
using Approximate_kernel = CGAL::Simple_cartesian<Approximate_number_type>;
using Approximate_point_2 = Arr_extended_direction_3<Approximate_kernel>;
using Approximate_kernel_vector_3 = Approximate_kernel::Vector_3;
using Approximate_kernel_direction_3 = Approximate_kernel::Direction_3;

View File

@ -21,7 +21,6 @@
* Definition of the Bezier_bounding_rational_traits<Kernel> class.
*/
#include <CGAL/Cartesian.h>
#include <CGAL/Polygon_2_algorithms.h>
#include <CGAL/Arr_geometry_traits/de_Casteljau_2.h>

View File

@ -41,9 +41,9 @@ class _One_root_point_2_rep {
friend class _One_root_point_2<NumberType_, Filter_>;
public:
typedef NumberType_ NT;
typedef _One_root_point_2_rep<NT, Filter_> Self;
typedef Sqrt_extension<NT, NT, Tag_true,Boolean_tag<Filter_> > CoordNT;
using NT = NumberType_;
using Self = _One_root_point_2_rep<NT, Filter_>;
using CoordNT = Sqrt_extension<NT, NT, Tag_true,Boolean_tag<Filter_> >;
private:
CoordNT _x; // The coordinates.
@ -70,18 +70,17 @@ public:
*/
template <typename NumberType_, bool Filter_>
class _One_root_point_2 :
public Handle_for<_One_root_point_2_rep<NumberType_, Filter_> >
{
public Handle_for<_One_root_point_2_rep<NumberType_, Filter_>> {
public:
typedef NumberType_ NT;
typedef _One_root_point_2<NT, Filter_> Self;
using NT = NumberType_;
using Self = _One_root_point_2<NT, Filter_>;
private:
typedef _One_root_point_2_rep<NT, Filter_> Point_rep;
typedef Handle_for<Point_rep> Point_handle;
using Point_rep = _One_root_point_2_rep<NT, Filter_>;
using Point_handle = Handle_for<Point_rep>;
public:
typedef typename Point_rep::CoordNT CoordNT;
using CoordNT = typename Point_rep::CoordNT;
/*! constructs default. */
_One_root_point_2() : Point_handle(Point_rep()) {}
@ -106,8 +105,7 @@ public:
const CoordNT& y() const { return (this->ptr()->_y); }
/*! checks for equality. */
bool equals(const Self& p) const
{
bool equals(const Self& p) const {
if (this->identical(p)) return (true);
return (CGAL::compare(this->ptr()->_x, p.ptr()->_x) == EQUAL &&
@ -119,8 +117,7 @@ public:
bool operator == (const Self& p) const { return equals(p); }
/*! sets the point coordinates. */
void set(const NT& x, const NT& y)
{
void set(const NT& x, const NT& y) {
this->copy_on_write();
this->ptr()->_x = CoordNT(x);
this->ptr()->_y = CoordNT(y);
@ -128,8 +125,7 @@ public:
}
/*! sets the point coordinates. */
void set(const CoordNT& x, const CoordNT& y)
{
void set(const CoordNT& x, const CoordNT& y) {
this->copy_on_write();
this->ptr()->_x = x;
this->ptr()->_y = y;
@ -141,8 +137,7 @@ public:
*/
template <typename NT, bool Filter>
std::ostream& operator<<(std::ostream& os,
const _One_root_point_2<NT, Filter>& p)
{
const _One_root_point_2<NT, Filter>& p) {
os << CGAL::to_double(p.x()) << ' ' << CGAL::to_double(p.y());
return (os);
}
@ -165,15 +160,15 @@ std::istream & operator >> (std::istream & is,
template <typename Kernel_, bool Filter_>
class _Circle_segment_2 {
public:
typedef Kernel_ Kernel;
typedef typename Kernel::FT NT;
typedef _One_root_point_2<NT, Filter_> Point_2;
typedef typename Kernel::Circle_2 Circle_2;
typedef typename Kernel::Segment_2 Segment_2;
typedef typename Kernel::Line_2 Line_2;
using Kernel = Kernel_;
using NT = typename Kernel::FT;
using Point_2 = _One_root_point_2<NT, Filter_>;
using Circle_2 = typename Kernel::Circle_2;
using Segment_2 = typename Kernel::Segment_2;
using Line_2 = typename Kernel::Line_2;
protected:
typedef typename Point_2::CoordNT CoordNT;
using CoordNT = typename Point_2::CoordNT;
// Data members:
Line_2 m_line; // The supporting line (for line segments).
@ -234,8 +229,7 @@ public:
m_has_radius(false),
m_source(source),
m_target(target),
m_orient(COLLINEAR)
{
m_orient(COLLINEAR) {
CGAL_precondition(CGAL::compare(source.x() * line.a() + line.c(),
-source.y() * line.b()) == EQUAL);
@ -282,8 +276,7 @@ public:
m_has_radius(false),
m_source(source),
m_target(target),
m_orient(circ.orientation())
{
m_orient(circ.orientation()) {
CGAL_assertion(m_orient != COLLINEAR);
CGAL_precondition
@ -315,8 +308,7 @@ public:
m_radius(r),
m_source(source),
m_target(target),
m_orient(orient)
{
m_orient(orient) {
CGAL_assertion(orient != COLLINEAR);
CGAL_precondition
@ -343,8 +335,7 @@ public:
m_is_full(false),
m_has_radius(false),
m_source(p1.x(), p1.y()),
m_target(p3.x(), p3.y())
{
m_target(p3.x(), p3.y()) {
// Set the source and target.
NT x1 = p1.x();
NT y1 = p1.y();
@ -359,7 +350,7 @@ public:
// Compute the lines: A1*x + B1*y + C1 = 0,
// and: A2*x + B2*y + C2 = 0,
// where:
const NT _two = 2;
const NT _two = 2;
const NT A1 = _two*(x1 - x2);
const NT B1 = _two*(y1 - y2);
@ -423,8 +414,7 @@ public:
/*! obtains the supporting line.
* \pre The curve orientation is COLLINEAR.
*/
const Line_2& supporting_line() const
{
const Line_2& supporting_line() const {
CGAL_precondition(m_orient == COLLINEAR);
return m_line;
}
@ -432,8 +422,7 @@ public:
/*! obtains the supporting circle.
* \pre The curve orientation is not COLLINEAR.
*/
const Circle_2& supporting_circle() const
{
const Circle_2& supporting_circle() const {
CGAL_precondition(m_orient != COLLINEAR);
return m_circ;
}
@ -444,8 +433,7 @@ public:
/*! obtains the source point.
* \pre The curve is not a full circle.
*/
const Point_2& source() const
{
const Point_2& source() const {
CGAL_precondition(! m_is_full);
return (m_source);
}
@ -453,8 +441,7 @@ public:
/*! obtains the target point.
* \pre The curve is not a full circle.
*/
const Point_2& target() const
{
const Point_2& target() const {
CGAL_precondition(! m_is_full);
return (m_target);
}
@ -464,8 +451,7 @@ public:
* \pre The curve is circular.
* \return The number of points (0, 1, or 2).
*/
unsigned int vertical_tangency_points(Point_2* vpts) const
{
unsigned int vertical_tangency_points(Point_2* vpts) const {
CGAL_precondition(m_orient != COLLINEAR);
unsigned int n_vpts = 0;
@ -519,8 +505,7 @@ private:
*/
unsigned int _ccw_vertical_tangency_points(const Point_2& src,
const Point_2& trg,
Point_2* vpts) const
{
Point_2* vpts) const {
unsigned int n_vpts = 0;
const NT& x0 = m_circ.center().x();
const NT& y0 = m_circ.center().y();
@ -547,8 +532,7 @@ private:
if ((qs % 4) == 1) {
// We collect the left tangency point when going from Q[1] to Q[2]:
if (CGAL::compare(x0, trg.x()) != LARGER ||
CGAL::compare(y0, trg.y()) != EQUAL)
{
CGAL::compare(y0, trg.y()) != EQUAL) {
if (m_has_radius)
vpts[n_vpts] = Point_2(CoordNT(x0 - m_radius), y0);
else
@ -561,8 +545,7 @@ private:
else if ((qs % 4) == 3) {
// We collect the right tangency point when going from Q[3] to Q[0]:
if (CGAL::compare(x0, trg.x()) != SMALLER ||
CGAL::compare(y0, trg.y()) != EQUAL)
{
CGAL::compare(y0, trg.y()) != EQUAL) {
if (m_has_radius)
vpts[n_vpts] = Point_2(CoordNT(x0 + m_radius), y0);
else
@ -581,8 +564,7 @@ private:
/*! obtains the index of the quarter-plane containing the given point,
* where the circle center is considered to be the origin.
*/
int _quart_index(const Point_2& p) const
{
int _quart_index(const Point_2& p) const {
// The plane looks like:
//
// Q[1] : | Q[0]:
@ -608,8 +590,7 @@ private:
*/
template <typename Kernel, bool Filter>
std::ostream&
operator<<(std::ostream& os, const _Circle_segment_2<Kernel, Filter>& c)
{
operator<<(std::ostream& os, const _Circle_segment_2<Kernel, Filter>& c) {
if (c.orientation() == COLLINEAR) {
os<< "segment: " << c.source() << " -> " << c.target();
}
@ -632,35 +613,33 @@ operator<<(std::ostream& os, const _Circle_segment_2<Kernel, Filter>& c)
template <typename Kernel_, bool Filter_>
class _X_monotone_circle_segment_2 {
public:
typedef Kernel_ Kernel;
typedef _X_monotone_circle_segment_2<Kernel, Filter_> Self;
typedef typename Kernel::FT NT;
typedef _One_root_point_2<NT, Filter_> Point_2;
typedef typename Kernel::Circle_2 Circle_2;
typedef typename Kernel::Line_2 Line_2;
typedef typename Point_2::CoordNT CoordNT;
using Kernel = Kernel_;
using Self = _X_monotone_circle_segment_2<Kernel, Filter_>;
using NT = typename Kernel::FT;
using Point_2 = _One_root_point_2<NT, Filter_>;
using Circle_2 = typename Kernel::Circle_2;
using Line_2 = typename Kernel::Line_2;
using CoordNT = typename Point_2::CoordNT;
// Type definition for the intersection points mapping.
typedef std::pair<unsigned int, unsigned int> Curve_id_pair;
typedef unsigned int Multiplicity;
typedef std::pair<Point_2, Multiplicity> Intersection_point;
typedef std::list<Intersection_point> Intersection_list;
using Curve_id_pair = std::pair<unsigned int, unsigned int>;
using Multiplicity = std::size_t;
using Intersection_point = std::pair<Point_2, Multiplicity>;
using Intersection_list = std::list<Intersection_point>;
/*! \struct Less functor for Curve_id_pair.
*/
struct Less_id_pair {
bool operator()(const Curve_id_pair& ip1, const Curve_id_pair& ip2) const
{
bool operator()(const Curve_id_pair& ip1, const Curve_id_pair& ip2) const {
// Compare the pairs of IDs lexicographically.
return (ip1.first < ip2.first ||
(ip1.first == ip2.first && ip1.second < ip2.second));
}
};
typedef std::map<Curve_id_pair, Intersection_list, Less_id_pair>
Intersection_map;
typedef typename Intersection_map::value_type Intersection_map_entry;
typedef typename Intersection_map::iterator Intersection_map_iterator;
using Intersection_map = std::map<Curve_id_pair, Intersection_list, Less_id_pair>;
using Intersection_map_entry = typename Intersection_map::value_type;
using Intersection_map_iterator = typename Intersection_map::iterator;
protected:
NT m_first; // The x-coordinate of the circle center.
@ -713,8 +692,7 @@ public:
m_third(line.c()),
m_source(source),
m_target(target),
m_info(index << INDEX_SHIFT_BITS)
{
m_info(index << INDEX_SHIFT_BITS) {
// Check if the segment is directed left or right:
Comparison_result res = CGAL::compare(source.x(), target.x());
@ -740,8 +718,7 @@ public:
const typename Kernel::Point_2& target) :
m_source(source.x(), source.y()),
m_target(target.x(), target.y()),
m_info(0)
{
m_info(0) {
Line_2 line(source, target);
m_first = line.a();
m_second = line.b();
@ -778,8 +755,7 @@ public:
m_third(circ.squared_radius()),
m_source(source),
m_target(target),
m_info(index << INDEX_SHIFT_BITS)
{
m_info(index << INDEX_SHIFT_BITS) {
// Check if the segment is directed left or right:
Comparison_result res = CGAL::compare (source.x(), target.x());
@ -802,8 +778,7 @@ public:
/*! obtains the supporting line.
* \pre The arc is linear (a line segment).
*/
Line_2 supporting_line() const
{
Line_2 supporting_line() const {
CGAL_precondition (is_linear());
return (Line_2 (a(), b(), c()));
}
@ -811,8 +786,7 @@ public:
/*! obtains the supporting circle.
* \pre The arc is circular.
*/
Circle_2 supporting_circle() const
{
Circle_2 supporting_circle() const {
CGAL_precondition (is_circular());
typename Kernel::Point_2 center(x0(), y0());
@ -843,8 +817,7 @@ public:
/*! checks whether the given point is in the x-range of the arc.
*/
bool is_in_x_range(const Point_2& p) const
{
bool is_in_x_range(const Point_2& p) const {
Comparison_result res = CGAL::compare (p.x(), left().x());
if (res == SMALLER) return false;
@ -858,8 +831,7 @@ public:
{ return ((m_info & IS_VERTICAL_SEGMENT_MASK) != 0); }
/*! obtains the orientation of the arc. */
inline Orientation orientation() const
{
inline Orientation orientation() const {
unsigned int or_ = (m_info & ORIENTATION_MASK);
if (or_ == COUNTERCLOCKWISE_CODE) return (CGAL::COUNTERCLOCKWISE);
else if (or_ == CLOCKWISE_CODE) return (CGAL::CLOCKWISE);
@ -870,16 +842,14 @@ public:
/*! checks the position of a given point with respect to the arc.
*/
Comparison_result point_position(const Point_2& p) const
{
Comparison_result point_position(const Point_2& p) const {
if (is_linear()) return (_line_point_position(p));
else return (_circ_point_position (p));
}
/*! compares the two arcs to the right of their intersection point.
*/
Comparison_result compare_to_right(const Self& cv, const Point_2& p) const
{
Comparison_result compare_to_right(const Self& cv, const Point_2& p) const {
if (is_linear()) {
if (cv.is_linear()) return (_lines_compare_to_right (cv, p));
Comparison_result res = cv._circ_line_compare_to_right (*this, p);
@ -894,8 +864,7 @@ public:
/*! compares the two arcs to the left of their intersection point.
*/
Comparison_result compare_to_left(const Self& cv, const Point_2& p) const
{
Comparison_result compare_to_left(const Self& cv, const Point_2& p) const {
if (is_linear()) {
if (cv.is_linear()) return (_lines_compare_to_left (cv, p));
Comparison_result res = cv._circ_line_compare_to_left(*this, p);
@ -910,8 +879,7 @@ public:
/*! checks whether the two arcs have the same supporting curve.
*/
bool has_same_supporting_curve(const Self& cv) const
{
bool has_same_supporting_curve(const Self& cv) const {
// Check if the curve indices are the same.
if (_index() != 0 && _index() == cv._index()) return true;
@ -950,8 +918,7 @@ public:
/*! checks whether the two curves are equal.
*/
bool equals(const Self& cv) const
{
bool equals(const Self& cv) const {
if (! this->has_same_supporting_curve(cv)) return false;
if (is_linear()) {
@ -969,8 +936,7 @@ public:
/*! splits the curve at a given point into two sub-arcs.
*/
void split(const Point_2& p, Self& c1, Self& c2) const
{
void split(const Point_2& p, Self& c1, Self& c2) const {
// Copy the properties of this arc to the sub-arcs.
c1 = *this;
c2 = *this;
@ -990,8 +956,7 @@ public:
*/
template <typename OutputIterator>
OutputIterator intersect(const Self& cv, OutputIterator oi,
Intersection_map* inter_map = nullptr) const
{
Intersection_map* inter_map = nullptr) const {
// First check whether the two arcs have the same supporting curve.
if (has_same_supporting_curve(cv)) {
// Check for overlaps between the two arcs.
@ -1064,8 +1029,7 @@ public:
// Report only the intersection points that lie on both arcs.
for (auto iter = inter_list.begin(); iter != inter_list.end(); ++iter) {
if (this->_is_between_endpoints (iter->first) &&
cv._is_between_endpoints (iter->first))
{
cv._is_between_endpoints (iter->first)) {
*oi++ = *iter;
}
}
@ -1075,8 +1039,7 @@ public:
/*! checks whether it is possible to merge our arc with the given arc.
*/
bool can_merge_with(const Self& cv) const
{
bool can_merge_with(const Self& cv) const {
// In order to merge the two arcs, they should have the same supporting
// curve.
if (! this->has_same_supporting_curve(cv)) return false;
@ -1089,8 +1052,7 @@ public:
/*! merges our arc with the given arc.
* \pre The two arcs are mergeable.
*/
void merge(const Self& cv)
{
void merge(const Self& cv) {
CGAL_precondition(this->can_merge_with (cv));
// Check if we should extend the arc to the left or to the right.
@ -1109,8 +1071,7 @@ public:
}
/*! constructs an opposite arc. */
Self construct_opposite() const
{
Self construct_opposite() const {
Self opp_cv;
opp_cv.m_first = this->m_first;
opp_cv.m_second = this->m_second;
@ -1127,8 +1088,7 @@ public:
return (opp_cv);
}
Bbox_2 bbox() const
{
Bbox_2 bbox() const {
double x_min = to_double(left().x());
double x_max = to_double(right().x());
double y_min = to_double(left().y());
@ -1167,8 +1127,7 @@ protected:
/*! checks if the circular arc lies on the upper half of the supporting circle.
*/
inline bool _is_upper() const
{
inline bool _is_upper() const {
Orientation orient = orientation();
bool dir_right = ((m_info & IS_DIRECTED_RIGHT_MASK) != 0);
@ -1197,8 +1156,7 @@ protected:
/*! checks the position of a given point with respect to a line segment.
*/
Comparison_result _line_point_position(const Point_2& p) const
{
Comparison_result _line_point_position(const Point_2& p) const {
// Check if we have a vertical segment.
CGAL_precondition(is_in_x_range(p));
@ -1229,20 +1187,17 @@ protected:
/*! checks the position of a given point with respect to a circular arc.
*/
Comparison_result _circ_point_position(const Point_2& p) const
{
Comparison_result _circ_point_position(const Point_2& p) const {
Comparison_result c_res = CGAL::compare (p.y(), y0());
if (_is_upper()) {
// Check if p lies below the "equator" (while the arc lies above it):
if (c_res == SMALLER)
return (SMALLER);
if (c_res == SMALLER) return (SMALLER);
}
else {
// Check if p lies above the "equator" (while the arc lies below it):
if (c_res == LARGER)
return (LARGER);
if (c_res == LARGER) return (LARGER);
}
// Check if p lies inside the supporting circle, namely we have to check
@ -1271,8 +1226,7 @@ protected:
/*! compares two line segments to the right of their intersection point.
*/
Comparison_result _lines_compare_to_right(const Self& cv,
const Point_2& /* p */) const
{
const Point_2& /* p */) const {
if (_index() != 0 && _index() == cv._index()) return (EQUAL);
// Special treatment for vertical segments: a vertical segment is larger
@ -1292,8 +1246,7 @@ protected:
* their intersection point.
*/
Comparison_result _circ_line_compare_to_right(const Self& cv,
const Point_2& p) const
{
const Point_2& p) const {
// A vertical segment lies above any other circle to the right of p:
if (cv.is_vertical()) return (SMALLER);
@ -1334,8 +1287,7 @@ protected:
/*! compares two circular arcs to the right of their intersection point.
*/
Comparison_result _circs_compare_to_right(const Self& cv,
const Point_2& p) const
{
const Point_2& p) const {
if (_index() != 0 && _index() == cv._index()) {
// Check the case of comparing two circular arcs that originate from the
// same supporting circle. Their comparison result is not EQUAL only if
@ -1413,13 +1365,11 @@ protected:
// Compare the slopes of the two tangents to the circles.
Comparison_result slope_res;
if (sign_slope1 == ZERO && sign_slope2 == ZERO)
{
if (sign_slope1 == ZERO && sign_slope2 == ZERO) {
// Special case were both circles have a horizontal tangent:
slope_res = EQUAL;
}
else
{
else {
// Actually compare the slopes.
const bool swap_res = (sign_denom1 != sign_denom2);
const CoordNT A = NT(cv.y0() - y0())*p.x() + (y0()*cv.x0() - cv.y0()*x0());
@ -1466,8 +1416,7 @@ protected:
/*! compares two line segments to the left of their intersection point.
*/
Comparison_result _lines_compare_to_left(const Self& cv,
const Point_2& ) const
{
const Point_2& ) const {
if (_index() != 0 && _index() == cv._index()) return (EQUAL);
// Special treatment for vertical segments: a vertical segment is smaller
@ -1489,8 +1438,7 @@ protected:
* their intersection point.
*/
Comparison_result _circ_line_compare_to_left(const Self& cv,
const Point_2& p) const
{
const Point_2& p) const {
// A vertical segment lies below any other circle to the left of p:
if (cv.is_vertical()) return (LARGER);
@ -1534,8 +1482,7 @@ protected:
/*! compares the two arcs to the left of their intersection point.
*/
Comparison_result _circs_compare_to_left(const Self& cv,
const Point_2& p) const
{
const Point_2& p) const {
if (_index() != 0 && _index() == cv._index()) {
// Check the case of comparing two circular arcs that originate from the
// same supporting circle. Their comparison result is not EQUAL only if
@ -1614,8 +1561,7 @@ protected:
// Compare the slopes of the two tangents to the circles.
Comparison_result slope_res;
if (sign_slope1 == ZERO && sign_slope2 == ZERO)
{
if (sign_slope1 == ZERO && sign_slope2 == ZERO) {
// Special case were both circles have a horizontal tangent:
slope_res = EQUAL;
}
@ -1668,8 +1614,7 @@ protected:
/*! computes the intersections between two line segments.
*/
void _lines_intersect(const Self& cv,
Intersection_list& inter_list) const
{
Intersection_list& inter_list) const {
// The intersection of the lines:
// a1*x + b1*y + c1 = 0 and a2*x + b2*y + c2 = 0 ,
// is given by:
@ -1695,8 +1640,7 @@ protected:
* the supporting line of the segment cv.
*/
void _circ_line_intersect(const Self& cv,
Intersection_list& inter_list) const
{
Intersection_list& inter_list) const {
Point_2 p;
unsigned int mult;
@ -1818,8 +1762,7 @@ protected:
/*! computes the intersections between two circles.
*/
void _circs_intersect(const Self& cv, Intersection_list& inter_list) const
{
void _circs_intersect(const Self& cv, Intersection_list& inter_list) const {
Point_2 p;
unsigned int mult;
@ -1884,8 +1827,7 @@ protected:
/*! checks if the given point lies on the arc.
* \pre p lies on the supporting curve.
*/
bool _is_between_endpoints(const Point_2& p) const
{
bool _is_between_endpoints(const Point_2& p) const {
if (is_linear()) {
if (is_vertical()) {
// Check if the point is in the y-range of the arc.
@ -1908,8 +1850,7 @@ protected:
// Check whether p lies on the upper or on the lower part of the circle.
Comparison_result c_res = CGAL::compare(p.y(), y0());
if ((_is_upper() && c_res == SMALLER) || (! _is_upper() && c_res == LARGER))
{
if ((_is_upper() && c_res == SMALLER) || (! _is_upper() && c_res == LARGER)) {
// The point lies on the other half of the circle:
return false;
}
@ -1921,8 +1862,7 @@ protected:
/*! checks whether the given point lies in the interior of the arc.
* \pre p lies on the supporting curve.
*/
bool _is_strictly_between_endpoints(const Point_2& p) const
{
bool _is_strictly_between_endpoints(const Point_2& p) const {
if (p.equals (m_source) || p.equals (m_target)) return false;
return (_is_between_endpoints(p));
}
@ -1932,8 +1872,7 @@ protected:
* \param overlap Output: The overlapping arc (if any).
* \return Whether we found an overlap.
*/
bool _compute_overlap(const Self& cv, Self& overlap) const
{
bool _compute_overlap(const Self& cv, Self& overlap) const {
// Check if the two arcs are identical.
if (is_linear()) {
// In case of line segments we can swap the source and target:
@ -1999,10 +1938,9 @@ protected:
return false;
}
public:
public:
template <class OutputIterator>
void approximate(OutputIterator oi, unsigned int n) const
{
void approximate(OutputIterator oi, unsigned int n) const {
const double x_left = CGAL::to_double(this->source().x());
const double y_left = CGAL::to_double(this->source().y());
@ -2045,8 +1983,7 @@ protected:
* \pre Both ps and pt lies on the arc and must conform with the current
* direction of the arc.
*/
Self trim(const Point_2& ps, const Point_2& pt) const
{
Self trim(const Point_2& ps, const Point_2& pt) const {
Self arc = *this;
arc.m_source = ps;
@ -2063,8 +2000,7 @@ protected:
template <class Kernel, bool Filter>
std::ostream&
operator<<(std::ostream& os,
const _X_monotone_circle_segment_2<Kernel, Filter> & arc)
{
const _X_monotone_circle_segment_2<Kernel, Filter>& arc) {
if (! arc.is_linear())
os << "(" << arc.supporting_circle() << ") ";

View File

@ -43,46 +43,41 @@ namespace CGAL {
// Traits class for CGAL::Arrangement_2 (and similar) based on a
// CircularKernel.
template < typename CircularKernel >
template <typename CircularKernel>
class Arr_line_arc_traits_2 {
CircularKernel ck;
public:
using Kernel = CircularKernel;
using Curve_2 = typename CircularKernel::Line_arc_2;
using X_monotone_curve_2 = typename CircularKernel::Line_arc_2;
using Multiplicity = std::size_t;
typedef CircularKernel Kernel;
typedef typename CircularKernel::Line_arc_2 Curve_2;
typedef typename CircularKernel::Line_arc_2 X_monotone_curve_2;
typedef unsigned int Multiplicity;
using Point = typename CircularKernel::Circular_arc_point_2;
using Point_2 = typename CircularKernel::Circular_arc_point_2;
typedef typename CircularKernel::Circular_arc_point_2 Point;
typedef typename CircularKernel::Circular_arc_point_2 Point_2;
using Has_left_category = CGAL::Tag_false;
using Has_merge_category = CGAL::Tag_false;
using Has_do_intersect_category = CGAL::Tag_false;
typedef CGAL::Tag_false Has_left_category;
typedef CGAL::Tag_false Has_merge_category;
typedef CGAL::Tag_false Has_do_intersect_category;
using Left_side_category = Arr_oblivious_side_tag;
using Bottom_side_category = Arr_oblivious_side_tag;
using Top_side_category = Arr_oblivious_side_tag;
using Right_side_category = Arr_oblivious_side_tag;
typedef Arr_oblivious_side_tag Left_side_category;
typedef Arr_oblivious_side_tag Bottom_side_category;
typedef Arr_oblivious_side_tag Top_side_category;
typedef Arr_oblivious_side_tag Right_side_category;
Arr_line_arc_traits_2(const CircularKernel& k = CircularKernel()) : ck(k) {}
Arr_line_arc_traits_2(const CircularKernel &k = CircularKernel())
: ck(k) {}
typedef typename CircularKernel::Compare_x_2 Compare_x_2;
typedef typename CircularKernel::Compare_xy_2 Compare_xy_2;
typedef typename CircularKernel::Compare_y_at_x_2 Compare_y_at_x_2;
typedef typename CircularKernel::Compare_y_to_right_2 Compare_y_at_x_right_2;
typedef typename CircularKernel::Equal_2 Equal_2;
// typedef typename CircularKernel::Make_x_monotone_2 Make_x_monotone_2;
typedef typename CircularKernel::Split_2 Split_2;
typedef typename CircularKernel::Construct_circular_min_vertex_2
Construct_min_vertex_2;
typedef typename CircularKernel::Construct_circular_max_vertex_2
Construct_max_vertex_2;
typedef typename CircularKernel::Is_vertical_2 Is_vertical_2;
typedef typename CircularKernel::Intersect_2 Intersect_2;
using Compare_x_2 = typename CircularKernel::Compare_x_2;
using Compare_xy_2 = typename CircularKernel::Compare_xy_2;
using Compare_y_at_x_2 = typename CircularKernel::Compare_y_at_x_2;
using Compare_y_at_x_right_2 = typename CircularKernel::Compare_y_to_right_2;
using Equal_2 = typename CircularKernel::Equal_2;
// using Make_x_monotone_2 = typename CircularKernel::Make_x_monotone_2;
using Split_2 = typename CircularKernel::Split_2;
using Construct_min_vertex_2 = typename CircularKernel::Construct_circular_min_vertex_2;
using Construct_max_vertex_2 = typename CircularKernel::Construct_circular_max_vertex_2;
using Is_vertical_2 = typename CircularKernel::Is_vertical_2;
using Intersect_2 = typename CircularKernel::Intersect_2;
Compare_x_2 compare_x_2_object() const
{ return ck.compare_x_2_object(); }
@ -106,7 +101,7 @@ public:
{ return ck.split_2_object(); }
Intersect_2 intersect_2_object() const
{ return ck.intersect_2_object(); }
{ return ck.intersect_2_object(); }
Construct_min_vertex_2 construct_min_vertex_2_object() const
{ return ck.construct_circular_min_vertex_2_object(); }
@ -121,9 +116,8 @@ public:
class Make_x_monotone_2 {
public:
template <typename OutputIterator>
OutputIterator operator()(const Curve_2& line, OutputIterator oi) const
{
typedef std::variant<Point_2, X_monotone_curve_2> Make_x_monotone_result;
OutputIterator operator()(const Curve_2& line, OutputIterator oi) const {
using Make_x_monotone_result = std::variant<Point_2, X_monotone_curve_2>;
*oi++ = Make_x_monotone_result(line);
return oi;
}
@ -137,4 +131,4 @@ public:
#include <CGAL/enable_warnings.h>
#endif // CGAL_CIRCULAR_KERNEL_LINE_ARC_TRAITS_H
#endif

View File

@ -28,11 +28,13 @@
#include <variant>
#include <CGAL/Simple_cartesian.h>
#include <CGAL/tags.h>
#include <CGAL/intersections.h>
#include <CGAL/Arr_tags.h>
#include <CGAL/Arr_enums.h>
#include <CGAL/Arr_geometry_traits/Segment_assertions.h>
#include "CGAL/number_utils.h"
namespace CGAL {
@ -47,58 +49,55 @@ class Arr_linear_traits_2 : public Kernel_ {
friend class Arr_linear_object_2<Kernel_>;
public:
typedef Kernel_ Kernel;
typedef typename Kernel::FT FT;
using Kernel = Kernel_;
using FT = typename Kernel::FT;
typedef typename Algebraic_structure_traits<FT>::Is_exact
Has_exact_division;
using Has_exact_division = typename Algebraic_structure_traits<FT>::Is_exact;
// Category tags:
typedef Tag_true Has_left_category;
typedef Tag_true Has_merge_category;
typedef Tag_false Has_do_intersect_category;
using Has_left_category = Tag_true;
using Has_merge_category = Tag_true;
using Has_do_intersect_category = Tag_false;
typedef Arr_open_side_tag Left_side_category;
typedef Arr_open_side_tag Bottom_side_category;
typedef Arr_open_side_tag Top_side_category;
typedef Arr_open_side_tag Right_side_category;
using Left_side_category = Arr_open_side_tag;
using Bottom_side_category = Arr_open_side_tag;
using Top_side_category = Arr_open_side_tag;
using Right_side_category = Arr_open_side_tag;
typedef typename Kernel::Line_2 Line_2;
typedef typename Kernel::Ray_2 Ray_2;
typedef typename Kernel::Segment_2 Segment_2;
using Line_2 = typename Kernel::Line_2;
using Ray_2 = typename Kernel::Ray_2;
using Segment_2 = typename Kernel::Segment_2;
typedef CGAL::Segment_assertions<Arr_linear_traits_2<Kernel> >
Segment_assertions;
using Segment_assertions = CGAL::Segment_assertions<Arr_linear_traits_2<Kernel>>;
/*! \class Representation of a linear with cached data.
*/
class _Linear_object_cached_2 {
public:
typedef typename Kernel::Line_2 Line_2;
typedef typename Kernel::Ray_2 Ray_2;
typedef typename Kernel::Segment_2 Segment_2;
typedef typename Kernel::Point_2 Point_2;
using Line_2 = typename Kernel::Line_2;
using Ray_2 = typename Kernel::Ray_2;
using Segment_2 = typename Kernel::Segment_2;
using Point_2 = typename Kernel::Point_2;
protected:
Line_2 l; // The supporting line.
Point_2 ps; // The source point (if exists).
Point_2 pt; // The target point (if exists).
bool has_source; // Is the source point valid
Line_2 l; // The supporting line.
Point_2 ps; // The source point (if exists).
Point_2 pt; // The target point (if exists).
bool has_source; // Is the source point valid
// (false for a line).
bool has_target; // Is the target point valid
bool has_target; // Is the target point valid
// (false for a line and for a ray).
bool is_right; // Is the object directed to the right
bool is_right; // Is the object directed to the right
// (for segments and rays).
bool is_vert; // Is this a vertical object.
bool is_horiz; // Is this a horizontal object.
bool has_pos_slope; // Does the supporting line has a positive
bool is_vert; // Is this a vertical object.
bool is_horiz; // Is this a horizontal object.
bool has_pos_slope; // Does the supporting line has a positive
// slope (if all three flags is_vert, is_horiz
// and has_pos_slope are false, then the line
// has a negative slope).
bool is_degen; // Is the object degenerate (a single point).
bool is_degen; // Is the object degenerate (a single point).
public:
/*! constructs default.
*/
_Linear_object_cached_2() :
@ -119,8 +118,7 @@ public:
ps(source),
pt(target),
has_source(true),
has_target(true)
{
has_target(true) {
Kernel kernel;
Comparison_result res = kernel.compare_xy_2_object()(source, target);
@ -142,8 +140,7 @@ public:
*/
_Linear_object_cached_2(const Segment_2& seg) :
has_source(true),
has_target(true)
{
has_target(true) {
Kernel kernel;
CGAL_assertion_msg(! kernel.is_degenerate_2_object()(seg),
@ -170,8 +167,7 @@ public:
*/
_Linear_object_cached_2(const Ray_2& ray) :
has_source(true),
has_target(false)
{
has_target(false) {
Kernel kernel;
CGAL_assertion_msg(! kernel.is_degenerate_2_object()(ray),
@ -199,8 +195,7 @@ public:
_Linear_object_cached_2(const Line_2& ln) :
l(ln),
has_source(false),
has_target(false)
{
has_target(false) {
Kernel kernel;
CGAL_assertion_msg(! kernel.is_degenerate_2_object()(ln),
@ -224,8 +219,7 @@ public:
* \return `ARR_LEFT_BOUNDARY` if the left point is near the boundary;
* `ARR_INTERIOR` if the \f$x\f$-coordinate is finite.
*/
Arr_parameter_space left_infinite_in_x() const
{
Arr_parameter_space left_infinite_in_x() const {
if (is_vert || is_degen) return (ARR_INTERIOR);
return (is_right) ?
@ -238,8 +232,7 @@ public:
* `ARR_INTERIOR` if the \f$y\f$-coordinate is finite.
* `ARR_TOP_BOUNDARY` if the left point is at \f$y = +\infty\f$;
*/
Arr_parameter_space left_infinite_in_y() const
{
Arr_parameter_space left_infinite_in_y() const {
if (is_horiz || is_degen) return ARR_INTERIOR;
if (is_vert) {
@ -261,8 +254,7 @@ public:
/*! obtains the (lexicographically) left endpoint.
* \pre The left point is finite.
*/
const Point_2& left() const
{
const Point_2& left() const {
CGAL_precondition(has_left());
return (is_right ? ps : pt);
}
@ -272,8 +264,7 @@ public:
* \pre p lies on the supporting line to the left of the right endpoint.
*/
void set_left(const Point_2& p,
bool CGAL_assertion_code(check_validity) = true)
{
bool CGAL_assertion_code(check_validity) = true) {
CGAL_precondition(! is_degen);
CGAL_precondition_code(Kernel kernel);
@ -294,8 +285,7 @@ public:
/*! sets the (lexicographically) left endpoint as infinite.
*/
void set_left()
{
void set_left() {
CGAL_precondition(! is_degen);
if (is_right) has_source = false;
@ -306,8 +296,7 @@ public:
* \return `ARR_RIGHT_BOUNDARY` if the right point is near the boundary;
* `ARR_INTERIOR` if the \f$x\f$-coordinate is finite.
*/
Arr_parameter_space right_infinite_in_x() const
{
Arr_parameter_space right_infinite_in_x() const {
if (is_vert || is_degen) return ARR_INTERIOR;
return (is_right) ?
@ -320,8 +309,7 @@ public:
* `ARR_INTERIOR` if the \f$y\f$-coordinate is finite.
* `ARR_TOP_BOUNDARY` if the right point is at \f$y = +\infty\f$;
*/
Arr_parameter_space right_infinite_in_y() const
{
Arr_parameter_space right_infinite_in_y() const {
if (is_horiz || is_degen) return ARR_INTERIOR;
if (is_vert) {
@ -343,8 +331,7 @@ public:
/*! obtains the (lexicographically) right endpoint.
* \pre The right endpoint is finite.
*/
const Point_2& right() const
{
const Point_2& right() const {
CGAL_precondition(has_right());
return (is_right ? pt : ps);
}
@ -354,8 +341,7 @@ public:
* \pre p lies on the supporting line to the right of the left endpoint.
*/
void set_right(const Point_2& p,
bool CGAL_assertion_code(check_validity) = true)
{
bool CGAL_assertion_code(check_validity) = true) {
CGAL_precondition(! is_degen);
CGAL_precondition_code(Kernel kernel);
CGAL_precondition
@ -375,8 +361,7 @@ public:
/*! sets the (lexicographically) right endpoint as infinite.
*/
void set_right()
{
void set_right() {
CGAL_precondition(! is_degen);
if (is_right) has_target = false;
@ -385,16 +370,14 @@ public:
/*! obtains the supporting line.
*/
const Line_2& supp_line() const
{
const Line_2& supp_line() const {
CGAL_precondition(! is_degen);
return (l);
}
/*! checks whether the curve is vertical.
*/
bool is_vertical() const
{
bool is_vertical() const {
CGAL_precondition(! is_degen);
return (is_vert);
}
@ -412,8 +395,7 @@ public:
* \return (true) is in the \f$x\f$-range of the segment; (false) if it is
* not.
*/
bool is_in_x_range(const Point_2& p) const
{
bool is_in_x_range(const Point_2& p) const {
Kernel kernel;
typename Kernel_::Compare_x_2 compare_x = kernel.compare_x_2_object();
Comparison_result res1;
@ -452,8 +434,7 @@ public:
* \return (true) is in the \f$y\f$-range of the segment; (false) if it is
* not.
*/
bool is_in_y_range(const Point_2& p) const
{
bool is_in_y_range(const Point_2& p) const {
CGAL_precondition(is_vertical());
Kernel kernel;
@ -481,8 +462,7 @@ public:
private:
/*! determines if the supporting line has a positive slope.
*/
bool _has_positive_slope() const
{
bool _has_positive_slope() const {
if (is_vert) return true;
if (is_horiz) return false;
@ -496,10 +476,10 @@ public:
public:
// Traits objects
typedef typename Kernel::Point_2 Point_2;
typedef Arr_linear_object_2<Kernel> X_monotone_curve_2;
typedef Arr_linear_object_2<Kernel> Curve_2;
typedef unsigned int Multiplicity;
using Point_2 = typename Kernel::Point_2;
using X_monotone_curve_2 = Arr_linear_object_2<Kernel>;
using Curve_2 = Arr_linear_object_2<Kernel>;
using Multiplicity = std::size_t;
public:
/*! constructs default.
@ -512,7 +492,7 @@ public:
/*! A functor that compares the \f$x\f$-coordinates of two points */
class Compare_x_2 {
protected:
typedef Arr_linear_traits_2<Kernel> Traits;
using Traits = Arr_linear_traits_2<Kernel>;
/*! The traits (in case it has state) */
const Traits& m_traits;
@ -536,8 +516,7 @@ public:
* SMALLER if x(p1) < x(p2);
* EQUAL if x(p1) = x(p2).
*/
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 Kernel& kernel = m_traits;
return (kernel.compare_x_2_object()(p1, p2));
}
@ -565,7 +544,7 @@ public:
class Trim_2 {
protected:
typedef Arr_linear_traits_2<Kernel> Traits;
using Traits = Arr_linear_traits_2<Kernel>;
/*! The traits (in case it has state) */
const Traits& m_traits;
@ -584,10 +563,8 @@ public:
public:
X_monotone_curve_2 operator()(const X_monotone_curve_2 xcv,
const Point_2 src,
const Point_2 tgt)
{
/*
* "Line_segment, line, and ray" will become line segments
const Point_2 tgt) {
/* "Line_segment, line, and ray" will become line segments
* when trimmed.
*/
Equal_2 equal = Equal_2();
@ -617,7 +594,7 @@ public:
class Construct_opposite_2{
protected:
typedef Arr_linear_traits_2<Kernel> Traits;
using Traits = Arr_linear_traits_2<Kernel>;
/*! The traits (in case it has state) */
const Traits& m_traits;
@ -634,8 +611,7 @@ public:
friend class Arr_linear_traits_2<Kernel>;
public:
X_monotone_curve_2 operator()(const X_monotone_curve_2& xcv) const
{
X_monotone_curve_2 operator()(const X_monotone_curve_2& xcv) const {
CGAL_precondition(! xcv.is_degenerate());
X_monotone_curve_2 opp_xcv;
@ -665,8 +641,7 @@ public:
* SMALLER if x(p1) < x(p2), or if x(p1) = x(p2) and y(p1) < y(p2);
* EQUAL if the two points are equal.
*/
Comparison_result operator()(const Point_2& p1, const Point_2& p2) const
{
Comparison_result operator()(const Point_2& p1, const Point_2& p2) const {
Kernel kernel;
return (kernel.compare_xy_2_object()(p1, p2));
}
@ -683,8 +658,7 @@ public:
* \pre The left end of cv is a valid (bounded) point.
* \return The left endpoint.
*/
const Point_2& operator()(const X_monotone_curve_2& cv) const
{
const Point_2& operator()(const X_monotone_curve_2& cv) const {
CGAL_precondition(! cv.is_degenerate());
CGAL_precondition(cv.has_left());
@ -704,8 +678,7 @@ public:
* \pre The right end of cv is a valid (bounded) point.
* \return The right endpoint.
*/
const Point_2& operator()(const X_monotone_curve_2& cv) const
{
const Point_2& operator()(const X_monotone_curve_2& cv) const {
CGAL_precondition(! cv.is_degenerate());
CGAL_precondition(cv.has_right());
@ -724,8 +697,7 @@ public:
* \param cv The curve.
* \return (true) if the curve is a vertical segment; (false) otherwise.
*/
bool operator()(const X_monotone_curve_2& cv) const
{
bool operator()(const X_monotone_curve_2& cv) const {
CGAL_precondition(! cv.is_degenerate());
return (cv.is_vertical());
}
@ -739,7 +711,7 @@ public:
*/
class Compare_y_at_x_2 {
protected:
typedef Arr_linear_traits_2<Kernel> Traits;
using Traits = Arr_linear_traits_2<Kernel>;
/*! The traits (in case it has state) */
const Traits& m_traits;
@ -765,8 +737,7 @@ public:
* EQUAL if p lies on the curve.
*/
Comparison_result operator()(const Point_2& p,
const X_monotone_curve_2& cv) const
{
const X_monotone_curve_2& cv) const {
CGAL_precondition(! cv.is_degenerate());
CGAL_precondition(cv.is_in_x_range(p));
@ -807,8 +778,7 @@ public:
*/
Comparison_result operator()(const X_monotone_curve_2& cv1,
const X_monotone_curve_2& cv2,
const Point_2& CGAL_precondition_code(p)) const
{
const Point_2& CGAL_precondition_code(p)) const {
CGAL_precondition(! cv1.is_degenerate());
CGAL_precondition(! cv2.is_degenerate());
@ -859,8 +829,7 @@ public:
*/
Comparison_result operator()(const X_monotone_curve_2& cv1,
const X_monotone_curve_2& cv2,
const Point_2& CGAL_precondition_code(p)) const
{
const Point_2& CGAL_precondition_code(p)) const {
CGAL_precondition(! cv1.is_degenerate());
CGAL_precondition(! cv2.is_degenerate());
@ -904,8 +873,7 @@ public:
* \return (true) if the two curves are the same; (false) otherwise.
*/
bool operator()(const X_monotone_curve_2& cv1,
const X_monotone_curve_2& cv2) const
{
const X_monotone_curve_2& cv2) const {
CGAL_precondition(! cv1.is_degenerate());
CGAL_precondition(! cv2.is_degenerate());
@ -916,17 +884,13 @@ public:
if (! equal(cv1.supp_line(), cv2.supp_line()) &&
! equal(cv1.supp_line(),
kernel.construct_opposite_line_2_object()(cv2.supp_line())))
{
return false;
}
// Check that either the two left endpoints are at infinity, or they
// are bounded and equal.
if ((cv1.has_left() != cv2.has_left()) ||
(cv1.has_left() && ! equal(cv1.left(), cv2.left())))
{
return false;
}
// Check that either the two right endpoints are at infinity, or they
// are bounded and equal.
@ -939,8 +903,7 @@ public:
* \param p2 The second point.
* \return (true) if the two point are the same; (false) otherwise.
*/
bool operator()(const Point_2& p1, const Point_2& p2) const
{
bool operator()(const Point_2& p1, const Point_2& p2) const {
Kernel kernel;
return (kernel.equal_2_object()(p1, p2));
}
@ -971,8 +934,7 @@ public:
* the left at the line right end.
*/
Arr_parameter_space operator()(const X_monotone_curve_2 & xcv,
Arr_curve_end ce) const
{
Arr_curve_end ce) const {
CGAL_precondition(! xcv.is_degenerate());
return (ce == ARR_MIN_END) ?
xcv.left_infinite_in_x() : xcv.right_infinite_in_x();
@ -1013,8 +975,7 @@ public:
* right end.
*/
Arr_parameter_space operator()(const X_monotone_curve_2 & xcv,
Arr_curve_end ce) const
{
Arr_curve_end ce) const {
CGAL_precondition(! xcv.is_degenerate());
return (ce == ARR_MIN_END) ?
@ -1038,7 +999,7 @@ public:
*/
class Compare_x_on_boundary_2 {
protected:
typedef Arr_linear_traits_2<Kernel> Traits;
using Traits = Arr_linear_traits_2<Kernel>;
/*! The traits (in case it has state) */
const Traits& m_traits;
@ -1072,8 +1033,7 @@ public:
*/
Comparison_result operator()(const Point_2 & p,
const X_monotone_curve_2 & xcv,
Arr_curve_end ) const
{
Arr_curve_end ) const {
CGAL_precondition(! xcv.is_degenerate());
CGAL_precondition(xcv.is_vertical());
@ -1103,8 +1063,7 @@ public:
Comparison_result operator()(const X_monotone_curve_2 & xcv1,
Arr_curve_end /* ce1 */,
const X_monotone_curve_2 & xcv2,
Arr_curve_end /* ce2 */) const
{
Arr_curve_end /* ce2 */) const {
CGAL_precondition(! xcv1.is_degenerate());
CGAL_precondition(! xcv2.is_degenerate());
CGAL_precondition(xcv1.is_vertical());
@ -1150,8 +1109,7 @@ public:
Comparison_result
operator()(const X_monotone_curve_2& CGAL_precondition_code(xcv1),
const X_monotone_curve_2& CGAL_precondition_code(xcv2),
Arr_curve_end /* ce2 */) const
{
Arr_curve_end /* ce2 */) const {
CGAL_precondition(! xcv1.is_degenerate());
CGAL_precondition(! xcv2.is_degenerate());
CGAL_precondition(xcv1.is_vertical());
@ -1169,7 +1127,7 @@ public:
*/
class Compare_y_near_boundary_2 {
protected:
typedef Arr_linear_traits_2<Kernel> Traits;
using Traits = Arr_linear_traits_2<Kernel>;
/*! The traits (in case it has state) */
const Traits& m_traits;
@ -1197,8 +1155,7 @@ public:
*/
Comparison_result operator()(const X_monotone_curve_2 & xcv1,
const X_monotone_curve_2 & xcv2,
Arr_curve_end ce) const
{
Arr_curve_end ce) const {
// Make sure both curves are defined at \f$x = -\infty\f$ (or at
// \f$x = +\infty\f$).
CGAL_precondition(! xcv1.is_degenerate());
@ -1250,11 +1207,9 @@ public:
* \return The past-the-end iterator.
*/
template <typename OutputIterator>
OutputIterator operator()(const Curve_2& cv, OutputIterator oi) const
{
OutputIterator operator()(const Curve_2& cv, OutputIterator oi) const {
// Wrap the segment with a variant.
typedef std::variant<Point_2, X_monotone_curve_2>
Make_x_monotone_result;
using Make_x_monotone_result = std::variant<Point_2, X_monotone_curve_2>;
*oi++ = Make_x_monotone_result(cv);
return oi;
}
@ -1275,8 +1230,7 @@ public:
* \pre `p` lies on `cv` but is not one of its end-points.
*/
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 {
CGAL_precondition(! cv.is_degenerate());
// Make sure that p lies on the interior of the curve.
@ -1304,7 +1258,7 @@ public:
class Intersect_2 {
protected:
typedef Arr_linear_traits_2<Kernel> Traits;
using Traits = Arr_linear_traits_2<Kernel>;
/*! The traits (in case it has state) */
const Traits& m_traits;
@ -1328,9 +1282,8 @@ public:
template <typename OutputIterator>
OutputIterator operator()(const X_monotone_curve_2& cv1,
const X_monotone_curve_2& cv2,
OutputIterator oi) const
{
typedef std::pair<Point_2, Multiplicity> Intersection_point;
OutputIterator oi) const {
using Intersection_point = std::pair<Point_2, Multiplicity>;
CGAL_precondition(! cv1.is_degenerate());
CGAL_precondition(! cv2.is_degenerate());
@ -1427,8 +1380,7 @@ public:
* by the same line and share a common endpoint; (false) otherwise.
*/
bool operator()(const X_monotone_curve_2& cv1,
const X_monotone_curve_2& cv2) const
{
const X_monotone_curve_2& cv2) const {
CGAL_precondition(! cv1.is_degenerate());
CGAL_precondition(! cv2.is_degenerate());
@ -1458,7 +1410,7 @@ public:
*/
class Merge_2 {
protected:
typedef Arr_linear_traits_2<Kernel> Traits;
using Traits = Arr_linear_traits_2<Kernel>;
/*! The traits (in case it has state) */
const Traits& m_traits;
@ -1479,8 +1431,7 @@ public:
*/
void operator()(const X_monotone_curve_2& cv1,
const X_monotone_curve_2& cv2,
X_monotone_curve_2& c) const
{
X_monotone_curve_2& c) const {
CGAL_precondition(m_traits.are_mergeable_2_object()(cv2, cv1));
CGAL_precondition(!cv1.is_degenerate());
@ -1490,8 +1441,7 @@ public:
// Check which curve extends to the right of the other.
if (cv1.has_right() && cv2.has_left() &&
equal(cv1.right(), cv2.left()))
{
equal(cv1.right(), cv2.left())) {
// cv2 extends cv1 to the right.
c = cv1;
@ -1517,9 +1467,24 @@ public:
/// \name Functor definitions for the landmarks point-location strategy.
//@{
typedef double Approximate_number_type;
using Approximate_number_type = double;
using Approximate_kernel = CGAL::Simple_cartesian<Approximate_number_type>;
using Approximate_point_2 = Approximate_kernel::Point_2;
class Approximate_2 {
protected:
using Traits = Arr_linear_traits_2<Kernel>;
/*! The traits (in case it has state) */
const Traits& m_traits;
/*! constructs
* \param traits the traits.
*/
Approximate_2(const Traits& traits) : m_traits(traits) {}
friend class Arr_linear_traits_2<Kernel>;
public:
/*! obtains an approximation of a point coordinate.
* \param p The exact point.
@ -1528,15 +1493,102 @@ public:
* \return An approximation of `p`'s \f$x\f$-coordinate (if `i` == 0), or an
* approximation of `p`'s \f$y\f$-coordinate (if `i` == 1).
*/
Approximate_number_type operator()(const Point_2& p, int i) const
{
Approximate_number_type operator()(const Point_2& p, int i) const {
CGAL_precondition((i == 0) || (i == 1));
return (i == 0) ? CGAL::to_double(p.x()) : CGAL::to_double(p.y());
}
/*! obtains an approximation of a point.
*/
Approximate_point_2 operator()(const Point_2& p) const
{ return Approximate_point_2(operator()(p, 0), operator()(p, 1)); }
/*! obtains an approximation of an \f$x\f$-monotone curve.
*/
template <typename OutputIterator>
OutputIterator operator()(const X_monotone_curve_2& xcv, double /* error */,
OutputIterator oi, bool l2r = true) const {
if(xcv.is_ray() || xcv.is_line()) return oi;
auto min_vertex = m_traits.construct_min_vertex_2_object();
auto max_vertex = m_traits.construct_max_vertex_2_object();
const auto& src = (l2r) ? min_vertex(xcv) : max_vertex(xcv);
const auto& trg = (l2r) ? max_vertex(xcv) : min_vertex(xcv);
*oi++ = operator()(src);
*oi++ = operator()(trg);
return oi;
}
/*! obtains an approximation of an \f$x\f$-monotone curve.
*/
template <typename OutputIterator>
OutputIterator operator()(const X_monotone_curve_2& xcv, double /* error */,
OutputIterator oi, const Bbox_2& bbox,
bool l2r = true) const {
using Approx_pnt = Approximate_point_2;
using Approx_seg = Approximate_kernel::Segment_2;
using Approx_ray = Approximate_kernel::Ray_2;
using Approx_lin = Approximate_kernel::Line_2;
auto xmin = bbox.xmin();
auto ymin = bbox.ymin();
auto xmax = bbox.xmax();
auto ymax = bbox.ymax();
Approximate_kernel::Iso_rectangle_2 rect(xmin, ymin, xmax, ymax);
if (xcv.is_ray()) {
auto ray = xcv.ray();
Kernel kernel;
auto construct_vertex = kernel.construct_point_on_2_object();
Approx_pnt s = this->operator()(construct_vertex(ray, 0));
Approx_pnt t = this->operator()(construct_vertex(ray, 1));
const auto result = CGAL::intersection(rect, Approx_ray(s, t));
if (! result) return oi;
if (const auto* res_seg = std::get_if<Approx_seg>(&*result)) {
*oi++ = l2r ? (res_seg->min)() : (res_seg->max)();
*oi++ = l2r ? (res_seg->max)() : (res_seg->min)();
return oi;
}
const auto* res_pnt = std::get_if<Approx_pnt>(&*result);
CGAL_assertion(res_pnt != nullptr);
*oi++ = *res_pnt;
return oi;
}
if (xcv.is_line()) {
const Line_2 & supp_line = xcv.supp_line();
Approx_lin approx_supp_line(
CGAL::to_double(supp_line.a()),
CGAL::to_double(supp_line.b()),
CGAL::to_double(supp_line.c()));
const auto result = CGAL::intersection(rect, approx_supp_line);
if (! result) return oi;
if (const auto* res_seg = std::get_if<Approx_seg>(&*result)) {
*oi++ = l2r ? (res_seg->min)() : (res_seg->max)();
*oi++ = l2r ? (res_seg->max)() : (res_seg->min)();
return oi;
}
const auto* res_pnt = std::get_if<Approx_pnt>(&*result);
CGAL_assertion(res_pnt != nullptr);
*oi++ = *res_pnt;
return oi;
}
Approx_seg seg(this->operator()(xcv.source()), this->operator()(xcv.target()));
const auto result = CGAL::intersection(rect, seg);
if (! result) return oi;
if (const auto* res_seg = std::get_if<Approx_seg>(&*result)) {
*oi++ = l2r ? (res_seg->min)() : (res_seg->max)();
*oi++ = l2r ? (res_seg->max)() : (res_seg->min)();
return oi;
}
const auto* res_pnt = std::get_if<Approx_pnt>(&*result);
CGAL_assertion(res_pnt != nullptr);
*oi++ = *res_pnt;
return oi;
}
};
/*! obtains an `Approximate_2` functor object. */
Approximate_2 approximate_2_object() const { return Approximate_2(); }
Approximate_2 approximate_2_object() const { return Approximate_2(*this); }
//! Functor
class Construct_x_monotone_curve_2 {
@ -1547,8 +1599,7 @@ public:
* \pre p and q must not be the same.
* \return A segment connecting `p` and `q`.
*/
X_monotone_curve_2 operator()(const Point_2& p, const Point_2& q) const
{
X_monotone_curve_2 operator()(const Point_2& p, const Point_2& q) const {
Kernel kernel;
Segment_2 seg = kernel.construct_segment_2_object()(p, q);
@ -1565,7 +1616,7 @@ public:
//@{
//! Functor
typedef Construct_x_monotone_curve_2 Construct_curve_2;
using Construct_curve_2 = Construct_x_monotone_curve_2;
/*! obtains a `Construct_curve_2` functor object. */
Construct_curve_2 construct_curve_2_object() const
@ -1578,18 +1629,16 @@ public:
*/
template <typename Kernel_>
class Arr_linear_object_2 :
public Arr_linear_traits_2<Kernel_>::_Linear_object_cached_2
{
typedef typename Arr_linear_traits_2<Kernel_>::_Linear_object_cached_2
Base;
public Arr_linear_traits_2<Kernel_>::_Linear_object_cached_2 {
using Base = typename Arr_linear_traits_2<Kernel_>::_Linear_object_cached_2;
public:
typedef Kernel_ Kernel;
using Kernel = Kernel_;
typedef typename Kernel::Point_2 Point_2;
typedef typename Kernel::Segment_2 Segment_2;
typedef typename Kernel::Ray_2 Ray_2;
typedef typename Kernel::Line_2 Line_2;
using Point_2 = typename Kernel::Point_2;
using Segment_2 = typename Kernel::Segment_2;
using Ray_2 = typename Kernel::Ray_2;
using Line_2 = typename Kernel::Line_2;
public:
/*! constructs default.
@ -1629,8 +1678,7 @@ public:
/*! casts to a segment.
* \pre The linear object is really a segment.
*/
Segment_2 segment() const
{
Segment_2 segment() const {
CGAL_precondition(is_segment());
Kernel kernel;
@ -1646,8 +1694,7 @@ public:
/*! casts to a ray.
* \pre The linear object is really a ray.
*/
Ray_2 ray() const
{
Ray_2 ray() const {
CGAL_precondition(is_ray());
Kernel kernel;
@ -1666,8 +1713,7 @@ public:
/*! casts to a line.
* \pre The linear object is really a line.
*/
Line_2 line() const
{
Line_2 line() const {
CGAL_precondition(is_line());
return (this->l);
}
@ -1675,8 +1721,7 @@ public:
/*! obtains the supporting line.
* \pre The object is not a point.
*/
const Line_2& supporting_line() const
{
const Line_2& supporting_line() const {
CGAL_precondition(! this->is_degen);
return (this->l);
}
@ -1684,8 +1729,7 @@ public:
/*! obtains the source point.
* \pre The object is a point, a segment or a ray.
*/
const Point_2& source() const
{
const Point_2& source() const {
CGAL_precondition(! is_line());
if (this->is_degen) return (this->ps); // For a point.
@ -1696,16 +1740,14 @@ public:
/*! obtains the target point.
* \pre The object is a point or a segment.
*/
const Point_2& target() const
{
const Point_2& target() const {
CGAL_precondition(! is_line() && ! is_ray());
return (this->pt);
}
/*! creates a bounding box for the linear object.
*/
Bbox_2 bbox() const
{
Bbox_2 bbox() const {
CGAL_precondition(this->is_segment());
Kernel kernel;
Segment_2 seg = kernel.construct_segment_2_object()(this->ps, this->pt);
@ -1724,8 +1766,7 @@ public:
*/
template <typename Kernel, typename OutputStream>
OutputStream& operator<<(OutputStream& os,
const Arr_linear_object_2<Kernel>& lobj)
{
const Arr_linear_object_2<Kernel>& lobj) {
// Print a letter identifying the object type, then the object itself.
if (lobj.is_segment()) os << " S " << lobj.segment();
else if (lobj.is_ray()) os << " R " << lobj.ray();
@ -1736,8 +1777,7 @@ OutputStream& operator<<(OutputStream& os,
/*! Importer for the segment class used by the traits-class.
*/
template <typename Kernel, typename InputStream>
InputStream& operator>>(InputStream& is, Arr_linear_object_2<Kernel>& lobj)
{
InputStream& operator>>(InputStream& is, Arr_linear_object_2<Kernel>& lobj) {
// Read the object type.
char c;
do {

View File

@ -30,7 +30,7 @@
* functors required by the concept it models.
*/
#include <CGAL/Cartesian.h>
#include <CGAL/Simple_cartesian.h>
#include <CGAL/Algebraic_structure_traits.h>
#include <CGAL/number_utils.h>
#include <CGAL/tags.h>
@ -44,34 +44,28 @@ namespace CGAL {
* A model of the AosBasicTraits_2 concept that handles \f$x\f$-monotone
* non-intersecting line segments.
*/
template <class T_Kernel>
class Arr_non_caching_segment_basic_traits_2 : public T_Kernel
{
template <typename T_Kernel>
class Arr_non_caching_segment_basic_traits_2 : public T_Kernel {
public:
typedef T_Kernel Kernel;
typedef typename Kernel::FT FT;
using Kernel = T_Kernel;
using FT = typename Kernel::FT;
private:
typedef Algebraic_structure_traits<FT> AST;
typedef typename AST::Is_exact FT_is_exact;
using AST = Algebraic_structure_traits<FT>;
using FT_is_exact = typename AST::Is_exact;
public:
typedef Boolean_tag<FT_is_exact::value> Has_exact_division;
typedef
CGAL::Segment_assertions<Arr_non_caching_segment_basic_traits_2<Kernel> >
Segment_assertions;
using Has_exact_division = Boolean_tag<FT_is_exact::value>;
using Segment_assertions = CGAL::Segment_assertions<Arr_non_caching_segment_basic_traits_2<Kernel>>;
// Categories:
typedef Tag_true Has_left_category;
typedef Tag_false Has_do_intersect_category;
using Has_left_category = Tag_true;
using Has_do_intersect_category = Tag_false;
typedef Arr_oblivious_side_tag Left_side_category;
typedef Arr_oblivious_side_tag Bottom_side_category;
typedef Arr_oblivious_side_tag Top_side_category;
typedef Arr_oblivious_side_tag Right_side_category;
using Left_side_category = Arr_oblivious_side_tag;
using Bottom_side_category = Arr_oblivious_side_tag;
using Top_side_category = Arr_oblivious_side_tag;
using Right_side_category = Arr_oblivious_side_tag;
/*! constructs default */
Arr_non_caching_segment_basic_traits_2() {}
@ -80,30 +74,30 @@ public:
//@{
// Traits types:
typedef typename Kernel::Point_2 Point_2;
typedef typename Kernel::Segment_2 X_monotone_curve_2;
typedef unsigned int Multiplicity;
using Point_2 = typename Kernel::Point_2;
using X_monotone_curve_2 = typename Kernel::Segment_2;
using Multiplicity = std::size_t;
/*! Compare the \f$x\f$-coordinates of two points. */
typedef typename Kernel::Compare_x_2 Compare_x_2;
/*! compares the \f$x\f$-coordinates of two points. */
using Compare_x_2 = typename Kernel::Compare_x_2;
/*! Compare two points lexigoraphically; by \f$x\f$, then by \f$y\f$. */
typedef typename Kernel::Compare_xy_2 Compare_xy_2;
/*! compares two points lexigoraphically; by \f$x\f$, then by \f$y\f$. */
using Compare_xy_2 = typename Kernel::Compare_xy_2;
/*! Obtain the left endpoint of a given segment. */
typedef typename Kernel::Construct_min_vertex_2 Construct_min_vertex_2;
/*! obtains the left endpoint of a given segment. */
using Construct_min_vertex_2 = typename Kernel::Construct_min_vertex_2;
/*! Obtain the right endpoint of a given segment. */
typedef typename Kernel::Construct_max_vertex_2 Construct_max_vertex_2;
/*! obtains the right endpoint of a given segment. */
using Construct_max_vertex_2 = typename Kernel::Construct_max_vertex_2;
/*! Check whether a given segment is vertical. */
typedef typename Kernel::Is_vertical_2 Is_vertical_2;
/*! checks whether a given segment is vertical. */
using Is_vertical_2 = typename Kernel::Is_vertical_2;
/*! Return the location of a given point with respect to an input segment. */
typedef typename Kernel::Compare_y_at_x_2 Compare_y_at_x_2;
/*! returns the location of a given point with respect to an input segment. */
using Compare_y_at_x_2 = typename Kernel::Compare_y_at_x_2;
/*! Check if two segments or if two points are identical. */
typedef typename Kernel::Equal_2 Equal_2;
/*! checks if two segments or if two points are identical. */
using Equal_2 = typename Kernel::Equal_2;
//@}
@ -127,8 +121,7 @@ public:
*/
Comparison_result operator()(const X_monotone_curve_2& cv1,
const X_monotone_curve_2& cv2,
const Point_2& CGAL_precondition_code(p)) const
{
const Point_2& CGAL_precondition_code(p)) const {
Kernel kernel;
// The two segments must be defined at q and also to its left.
@ -140,13 +133,13 @@ public:
Compare_xy_2 compare_xy = kernel.compare_xy_2_object();
typename Kernel::Construct_vertex_2 construct_vertex =
kernel.construct_vertex_2_object();
const Point_2 & source1 = construct_vertex(cv1, 0);
const Point_2 & target1 = construct_vertex(cv1, 1);
const Point_2 & left1 =
const Point_2& source1 = construct_vertex(cv1, 0);
const Point_2& target1 = construct_vertex(cv1, 1);
const Point_2& left1 =
(kernel.less_xy_2_object()(source1, target1)) ? source1 : target1;
const Point_2 & source2 = construct_vertex(cv2, 0);
const Point_2 & target2 = construct_vertex(cv2, 1);
const Point_2 & left2 =
const Point_2& source2 = construct_vertex(cv2, 0);
const Point_2& target2 = construct_vertex(cv2, 1);
const Point_2& left2 =
(kernel.less_xy_2_object()(source2, target2)) ? source2 : target2;
);
@ -181,10 +174,9 @@ public:
* to the right of `p`: `SMALLER`, `LARGER`, or `EQUAL`.
*/
Comparison_result operator()(const X_monotone_curve_2 & cv1,
const X_monotone_curve_2 & cv2,
const Point_2 & CGAL_precondition_code(p)) const
{
Comparison_result operator()(const X_monotone_curve_2& cv1,
const X_monotone_curve_2& cv2,
const Point_2& CGAL_precondition_code(p)) const {
Kernel kernel;
// The two segments must be defined at q and also to its right.
@ -196,13 +188,13 @@ public:
Compare_xy_2 compare_xy = kernel.compare_xy_2_object();
typename Kernel::Construct_vertex_2 construct_vertex =
kernel.construct_vertex_2_object();
const Point_2 & source1 = construct_vertex(cv1, 0);
const Point_2 & target1 = construct_vertex(cv1, 1);
const Point_2 & right1 =
const Point_2& source1 = construct_vertex(cv1, 0);
const Point_2& target1 = construct_vertex(cv1, 1);
const Point_2& right1 =
(kernel.less_xy_2_object()(source1, target1)) ? target1 : source1;
const Point_2 & source2 = construct_vertex(cv2, 0);
const Point_2 & target2 = construct_vertex(cv2, 1);
const Point_2 & right2 =
const Point_2& source2 = construct_vertex(cv2, 0);
const Point_2& target2 = construct_vertex(cv2, 1);
const Point_2& right2 =
(kernel.less_xy_2_object()(source2, target2)) ? target2 : source2;
);
@ -222,9 +214,9 @@ public:
/// \name Functor definitions for the landmarks point-location strategy.
//@{
typedef double Approximate_number_type;
typedef CGAL::Cartesian<Approximate_number_type> Approximate_kernel;
typedef Approximate_kernel::Point_2 Approximate_point_2;
using Approximate_number_type = double;
using Approximate_kernel = CGAL::Simple_cartesian<Approximate_number_type>;
using Approximate_point_2 = Approximate_kernel::Point_2;
class Approximate_2 {
protected:
@ -267,12 +259,8 @@ public:
auto max_vertex = m_traits.construct_max_vertex_2_object();
const auto& src = (l2r) ? min_vertex(xcv) : max_vertex(xcv);
const auto& trg = (l2r) ? max_vertex(xcv) : min_vertex(xcv);
auto xs = CGAL::to_double(src.x());
auto ys = CGAL::to_double(src.y());
auto xt = CGAL::to_double(trg.x());
auto yt = CGAL::to_double(trg.y());
*oi++ = Approximate_point_2(xs, ys);
*oi++ = Approximate_point_2(xt, yt);
*oi++ = operator()(src);
*oi++ = operator()(trg);
return oi;
}
};
@ -280,7 +268,7 @@ public:
/*! obtains an Approximate_2 functor object. */
Approximate_2 approximate_2_object () const { return Approximate_2(*this); }
typedef typename Kernel::Construct_segment_2 Construct_x_monotone_curve_2;
using Construct_x_monotone_curve_2 = typename Kernel::Construct_segment_2;
/*! obtains a `Construct_x_monotone_curve_2` functor object. */
Construct_x_monotone_curve_2 construct_x_monotone_curve_2_object () const

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

@ -1115,6 +1115,7 @@ public:
using Approximate_number_type = void;
using Approximate_point_2 = void;
using Approximate_2 = void;
using Approximate_kernel = void;
};
template <typename T>
@ -1123,6 +1124,7 @@ public:
using Approximate_number_type = typename T::Approximate_number_type;
using Approximate_2 = typename T::Approximate_2;
using Approximate_point_2 = typename T::Approximate_point_2;
using Approximate_kernel = typename T::Approximate_kernel;
};
using Approximate_number_type =
@ -1131,6 +1133,8 @@ public:
typename has_approximate_2<Subcurve_traits_2>::Approximate_2;
using Approximate_point_2 =
typename has_approximate_2<Subcurve_traits_2>::Approximate_point_2;
using Approximate_kernel =
typename has_approximate_2<Subcurve_traits_2>::Approximate_kernel;
/*! obtains an Approximate_2 functor object. */
Approximate_2 approximate_2_object_impl(std::false_type) const

View File

@ -597,6 +597,7 @@ public:
//
using Approximate_number_type = typename Base::Approximate_number_type;
using Approximate_point_2 = typename Base::Approximate_point_2;
using Approximate_kernel = typename Base::Approximate_kernel;
class Approximate_2 : public Base::Approximate_2 {
protected:

View File

@ -28,7 +28,7 @@
#include <variant>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Cartesian.h>
#include <CGAL/Simple_cartesian.h>
#include <CGAL/tags.h>
#include <CGAL/intersections.h>
#include <CGAL/Arr_tags.h>
@ -52,35 +52,32 @@ class Arr_segment_2;
template <typename Kernel_ = Exact_predicates_exact_constructions_kernel>
class Arr_segment_traits_2 : public Kernel_ {
friend class Arr_segment_2<Kernel_>;
public:
typedef Kernel_ Kernel;
typedef typename Kernel::FT FT;
using Kernel = Kernel_;
using FT = typename Kernel::FT;
typedef typename Algebraic_structure_traits<FT>::Is_exact
Has_exact_division;
using Has_exact_division = typename Algebraic_structure_traits<FT>::Is_exact;
// Category tags:
typedef Tag_true Has_left_category;
typedef Tag_true Has_merge_category;
typedef Tag_false Has_do_intersect_category;
using Has_left_category = Tag_true;
using Has_merge_category = Tag_true;
using Has_do_intersect_category = Tag_false;
typedef Arr_oblivious_side_tag Left_side_category;
typedef Arr_oblivious_side_tag Bottom_side_category;
typedef Arr_oblivious_side_tag Top_side_category;
typedef Arr_oblivious_side_tag Right_side_category;
using Left_side_category = Arr_oblivious_side_tag;
using Bottom_side_category = Arr_oblivious_side_tag;
using Top_side_category = Arr_oblivious_side_tag;
using Right_side_category = Arr_oblivious_side_tag;
typedef typename Kernel::Line_2 Line_2;
typedef CGAL::Segment_assertions<Arr_segment_traits_2<Kernel> >
Segment_assertions;
using Line_2 = typename Kernel::Line_2;
using Segment_assertions = CGAL::Segment_assertions<Arr_segment_traits_2<Kernel>>;
/*! \class Representation of a segment with cached data.
*/
class _Segment_cached_2 {
public:
typedef typename Kernel::Line_2 Line_2;
typedef typename Kernel::Segment_2 Segment_2;
typedef typename Kernel::Point_2 Point_2;
using Line_2 = typename Kernel::Line_2;
using Segment_2 = typename Kernel::Segment_2;
using Point_2 = typename Kernel::Point_2;
protected:
mutable Line_2 m_l; // the line that supports the segment.
@ -228,10 +225,10 @@ public:
public:
// Traits objects
typedef typename Kernel::Point_2 Point_2;
typedef Arr_segment_2<Kernel> X_monotone_curve_2;
typedef Arr_segment_2<Kernel> Curve_2;
typedef unsigned int Multiplicity;
using Point_2 = typename Kernel::Point_2;
using X_monotone_curve_2 = Arr_segment_2<Kernel>;
using Curve_2 = Arr_segment_2<Kernel>;
using Multiplicity = std::size_t;
public:
/*! constructs default. */
@ -242,7 +239,7 @@ public:
class Compare_x_2 {
protected:
typedef Arr_segment_traits_2<Kernel> Traits;
using Traits = Arr_segment_traits_2<Kernel>;
//! The traits (in case it has state).
const Traits& m_traits;
@ -262,8 +259,7 @@ public:
* `SMALLER` if x(p1) < x(p2);
* `EQUAL` if x(p1) = x(p2).
*/
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 Kernel& kernel = m_traits;
return (kernel.compare_x_2_object()(p1, p2));
}
@ -274,7 +270,7 @@ public:
class Compare_xy_2 {
protected:
typedef Arr_segment_traits_2<Kernel> Traits;
using Traits = Arr_segment_traits_2<Kernel>;
/*! The traits (in case it has state) */
const Traits& m_traits;
@ -294,8 +290,7 @@ public:
* SMALLER if x(p1) < x(p2), or if x(p1) = x(p2) and y(p1) < y(p2);
* EQUAL if the two points are equal.
*/
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 Kernel& kernel = m_traits;
return (kernel.compare_xy_2_object()(p1, p2));
}
@ -347,7 +342,7 @@ public:
class Compare_y_at_x_2 {
protected:
typedef Arr_segment_traits_2<Kernel> Traits;
using Traits = Arr_segment_traits_2<Kernel>;
/*! The traits (in case it has state) */
const Traits& m_traits;
@ -369,8 +364,7 @@ public:
* `EQUAL` if `p` lies on the curve.
*/
Comparison_result operator()(const Point_2& p,
const X_monotone_curve_2& cv) const
{
const X_monotone_curve_2& cv) const {
CGAL_precondition(m_traits.is_in_x_range_2_object()(cv, p));
const Kernel& kernel = m_traits;
@ -396,7 +390,7 @@ public:
class Compare_y_at_x_left_2 {
protected:
typedef Arr_segment_traits_2<Kernel> Traits;
using Traits = Arr_segment_traits_2<Kernel>;
/*! The traits (in case it has state) */
const Traits& m_traits;
@ -421,8 +415,7 @@ public:
*/
Comparison_result operator()(const X_monotone_curve_2& cv1,
const X_monotone_curve_2& cv2,
const Point_2& CGAL_assertion_code(p)) const
{
const Point_2& CGAL_assertion_code(p)) const {
const Kernel& kernel = m_traits;
// Make sure that p lies on both curves, and that both are defined to its
@ -450,7 +443,7 @@ public:
class Compare_y_at_x_right_2 {
protected:
typedef Arr_segment_traits_2<Kernel> Traits;
using Traits = Arr_segment_traits_2<Kernel>;
/*! The traits (in case it has state) */
const Traits& m_traits;
@ -475,8 +468,7 @@ public:
*/
Comparison_result operator()(const X_monotone_curve_2& cv1,
const X_monotone_curve_2& cv2,
const Point_2& CGAL_assertion_code(p)) const
{
const Point_2& CGAL_assertion_code(p)) const {
const Kernel& kernel = m_traits;
// Make sure that p lies on both curves, and that both are defined to its
@ -502,7 +494,7 @@ public:
class Equal_2 {
protected:
typedef Arr_segment_traits_2<Kernel> Traits;
using Traits = Arr_segment_traits_2<Kernel>;
/*! The traits (in case it has state) */
const Traits& m_traits;
@ -522,8 +514,7 @@ public:
* \return (true) if the two curves are the same; (false) otherwise.
*/
bool operator()(const X_monotone_curve_2& cv1,
const X_monotone_curve_2& cv2) const
{
const X_monotone_curve_2& cv2) const {
const Kernel& kernel = m_traits;
typename Kernel::Equal_2 equal = kernel.equal_2_object();
@ -536,8 +527,7 @@ public:
* \param p2 the second point.
* \return (true) if the two point are the same; (false) otherwise.
*/
bool operator()(const Point_2& p1, const Point_2& p2) const
{
bool operator()(const Point_2& p1, const Point_2& p2) const {
const Kernel& kernel = m_traits;
return (kernel.equal_2_object()(p1, p2));
}
@ -566,11 +556,9 @@ public:
* \return the past-the-end output iterator.
*/
template <typename OutputIterator>
OutputIterator operator()(const Curve_2& cv, OutputIterator oi) const
{
OutputIterator operator()(const Curve_2& cv, OutputIterator oi) const {
// Wrap the segment with a variant.
typedef std::variant<Point_2, X_monotone_curve_2>
Make_x_monotone_result;
using Make_x_monotone_result = std::variant<Point_2, X_monotone_curve_2>;
*oi++ = Make_x_monotone_result(cv);
return oi;
}
@ -582,7 +570,7 @@ public:
class Split_2 {
protected:
typedef Arr_segment_traits_2<Kernel> Traits;
using Traits = Arr_segment_traits_2<Kernel>;
/*! The traits (in case it has state) */
const Traits& m_traits;
@ -595,7 +583,7 @@ public:
friend class Arr_segment_traits_2<Kernel>;
public:
/*! split a given \f$x\f$-monotone curve at a given point into two
/*! splits a given \f$x\f$-monotone curve at a given point into two
* sub-curves.
* \param cv the curve to split
* \param p the split point.
@ -604,8 +592,7 @@ public:
* \pre `p` lies on cv but is not one of its endpoints.
*/
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 {
// Make sure that p lies on the interior of the curve.
CGAL_precondition_code(const Kernel& kernel = m_traits;
auto compare_xy = kernel.compare_xy_2_object());
@ -628,7 +615,7 @@ public:
class Intersect_2 {
protected:
typedef Arr_segment_traits_2<Kernel> Traits;
using Traits = Arr_segment_traits_2<Kernel>;
/*! The traits (in case it has state) */
const Traits& m_traits;
@ -644,8 +631,7 @@ public:
// this point, we already know which point is left / right for
// both segments
bool do_intersect(const Point_2& A1, const Point_2& A2,
const Point_2& B1, const Point_2& B2) const
{
const Point_2& B1, const Point_2& B2) const {
const Kernel& kernel = m_traits;
auto compare_xy = kernel.compare_xy_2_object();
namespace interx = CGAL::Intersections::internal;
@ -686,8 +672,7 @@ public:
/*! determines whether the bounding boxes of two segments overlap
*/
bool do_bboxes_overlap(const X_monotone_curve_2& cv1,
const X_monotone_curve_2& cv2) const
{
const X_monotone_curve_2& cv2) const {
const Kernel& kernel = m_traits;
auto construct_bbox = kernel.construct_bbox_2_object();
auto bbox1 = construct_bbox(cv1.source()) + construct_bbox(cv1.target());
@ -707,9 +692,8 @@ public:
template <typename OutputIterator>
OutputIterator operator()(const X_monotone_curve_2& cv1,
const X_monotone_curve_2& cv2,
OutputIterator oi) const
{
typedef std::pair<Point_2, Multiplicity> Intersection_point;
OutputIterator oi) const {
using Intersection_point = std::pair<Point_2, Multiplicity>;
// Early ending with Bbox overlapping test
if (! do_bboxes_overlap(cv1, cv2)) return oi;
@ -787,7 +771,7 @@ public:
class Are_mergeable_2 {
protected:
typedef Arr_segment_traits_2<Kernel> Traits;
using Traits = Arr_segment_traits_2<Kernel>;
/*! The traits (in case it has state) */
const Traits& m_traits;
@ -808,8 +792,7 @@ public:
* \pre `cv1` and `cv2` share a common endpoint.
*/
bool operator()(const X_monotone_curve_2& cv1,
const X_monotone_curve_2& cv2) const
{
const X_monotone_curve_2& cv2) const {
const Kernel& kernel = m_traits;
typename Kernel::Equal_2 equal = kernel.equal_2_object();
if (! equal(cv1.right(), cv2.left()) &&
@ -832,7 +815,7 @@ public:
*/
class Merge_2 {
protected:
typedef Arr_segment_traits_2<Kernel> Traits;
using Traits = Arr_segment_traits_2<Kernel>;
/*! The traits (in case it has state) */
const Traits& m_traits;
@ -853,14 +836,13 @@ public:
*/
void operator()(const X_monotone_curve_2& cv1,
const X_monotone_curve_2& cv2,
X_monotone_curve_2& c) const
{
X_monotone_curve_2& c) const {
CGAL_precondition(m_traits.are_mergeable_2_object()(cv1, cv2));
const Kernel& kernel = m_traits;
auto equal = kernel.equal_2_object();
// Check which curve extends to the right of the other.
// checks which curve extends to the right of the other.
if (equal(cv1.right(), cv2.left())) {
// cv2 extends cv1 to the right.
c = cv1;
@ -882,9 +864,9 @@ public:
/// \name Functor definitions for the landmarks point-location strategy.
//@{
typedef double Approximate_number_type;
typedef CGAL::Cartesian<Approximate_number_type> Approximate_kernel;
typedef Approximate_kernel::Point_2 Approximate_point_2;
using Approximate_number_type = double;
using Approximate_kernel = CGAL::Simple_cartesian<Approximate_number_type>;
using Approximate_point_2 = Approximate_kernel::Point_2;
class Approximate_2 {
protected:
@ -927,12 +909,8 @@ public:
auto max_vertex = m_traits.construct_max_vertex_2_object();
const auto& src = (l2r) ? min_vertex(xcv) : max_vertex(xcv);
const auto& trg = (l2r) ? max_vertex(xcv) : min_vertex(xcv);
auto xs = CGAL::to_double(src.x());
auto ys = CGAL::to_double(src.y());
auto xt = CGAL::to_double(trg.x());
auto yt = CGAL::to_double(trg.y());
*oi++ = Approximate_point_2(xs, ys);
*oi++ = Approximate_point_2(xt, yt);
*oi++ = operator()(src);
*oi++ = operator()(trg);
return oi;
}
};
@ -943,7 +921,7 @@ public:
//! Functor
class Construct_x_monotone_curve_2 {
protected:
typedef Arr_segment_traits_2<Kernel> Traits;
using Traits = Arr_segment_traits_2<Kernel>;
//! The traits (in case it has state).
const Traits& m_traits;
@ -956,7 +934,7 @@ public:
friend class Arr_segment_traits_2<Kernel>;
public:
typedef typename Kernel::Segment_2 Segment_2;
using Segment_2 = typename Kernel::Segment_2;
/*! obtains an \f$x\f$-monotone curve connecting two given endpoints.
* \param source the first point.
@ -965,8 +943,7 @@ public:
* \return a segment connecting `source` and `target`.
*/
X_monotone_curve_2 operator()(const Point_2& source,
const Point_2& target) const
{
const Point_2& target) const {
const Kernel& kernel = m_traits;
auto line = kernel.construct_line_2_object()(source, target);
Comparison_result res = kernel.compare_xy_2_object()(source, target);
@ -985,8 +962,7 @@ public:
* \pre the segment is not degenerate.
* \return a segment that is the same as `seg`..
*/
X_monotone_curve_2 operator()(const Segment_2& seg) const
{
X_monotone_curve_2 operator()(const Segment_2& seg) const {
const Kernel& kernel = m_traits;
auto line = kernel.construct_line_2_object()(seg);
auto vertex_ctr = kernel.construct_vertex_2_object();
@ -1011,8 +987,7 @@ public:
*/
X_monotone_curve_2 operator()(const Line_2& line,
const Point_2& source,
const Point_2& target) const
{
const Point_2& target) const {
const Kernel& kernel = m_traits;
CGAL_precondition
(Segment_assertions::_assert_is_point_on(source, line,
@ -1039,7 +1014,7 @@ public:
//@{
//! Functor
typedef Construct_x_monotone_curve_2 Construct_curve_2;
using Construct_curve_2 = Construct_x_monotone_curve_2;
/*! obtains a `Construct_curve_2` functor object. */
Construct_curve_2 construct_curve_2_object() const
@ -1051,7 +1026,7 @@ public:
class Trim_2 {
protected:
typedef Arr_segment_traits_2<Kernel> Traits;
using Traits = Arr_segment_traits_2<Kernel>;
/*! The traits (in case it has state). */
const Traits& m_traits;
@ -1074,8 +1049,7 @@ public:
public:
X_monotone_curve_2 operator()(const X_monotone_curve_2& xcv,
const Point_2& src,
const Point_2& tgt)const
{
const Point_2& tgt) const {
CGAL_precondition_code(Equal_2 equal = m_traits.equal_2_object());
CGAL_precondition_code(Compare_y_at_x_2 compare_y_at_x =
m_traits.compare_y_at_x_2_object());
@ -1119,7 +1093,7 @@ public:
class Construct_opposite_2 {
public:
/*! Construct an opposite \f$x\f$-monotone (with swapped source and target).
/*! constructs an opposite \f$x\f$-monotone (with swapped source and target).
* \param cv the curve.
* \return the opposite curve.
*/
@ -1137,12 +1111,12 @@ public:
class Is_in_x_range_2 {
protected:
typedef Arr_segment_traits_2<Kernel> Traits;
using Traits = Arr_segment_traits_2<Kernel>;
//! The traits (in case it has state).
const Traits& m_traits;
/*! Construct
/*! constructs
* \param traits the traits (in case it has state)
*/
Is_in_x_range_2(const Traits& traits) : m_traits(traits) {}
@ -1156,8 +1130,7 @@ public:
* \param p the point.
* \return true if p is in the \f$x\f$-range of cv; false otherwise.
*/
bool operator()(const X_monotone_curve_2& cv, const Point_2& p) const
{
bool operator()(const X_monotone_curve_2& cv, const Point_2& p) const {
const Kernel& kernel = m_traits;
auto compare_x = kernel.compare_x_2_object();
Comparison_result res1 = compare_x(p, cv.left());
@ -1176,7 +1149,7 @@ public:
class Is_in_y_range_2 {
protected:
typedef Arr_segment_traits_2<Kernel> Traits;
using Traits = Arr_segment_traits_2<Kernel>;
//! The traits (in case it has state).
const Traits& m_traits;
@ -1195,8 +1168,7 @@ public:
* \param p the point.
* \return true if p is in the \f$y\f$-range of cv; false otherwise.
*/
bool operator()(const X_monotone_curve_2& cv, const Point_2& p) const
{
bool operator()(const X_monotone_curve_2& cv, const Point_2& p) const {
const Kernel& kernel = m_traits;
auto compare_y = kernel.compare_y_2_object();
Comparison_result res1 = compare_y(p, cv.left());
@ -1232,8 +1204,7 @@ template <typename Kernel>
Arr_segment_traits_2<Kernel>::
_Segment_cached_2::_Segment_cached_2(const Segment_2& seg) :
m_is_vert(false),
m_is_computed(false)
{
m_is_computed(false) {
Kernel kernel;
auto vertex_ctr = kernel.construct_vertex_2_object();
@ -1255,8 +1226,7 @@ _Segment_cached_2::_Segment_cached_2(const Point_2& source,
m_ps(source),
m_pt(target),
m_is_vert(false),
m_is_computed(false)
{
m_is_computed(false) {
Kernel kernel;
Comparison_result res = kernel.compare_xy_2_object()(m_ps, m_pt);
@ -1274,8 +1244,7 @@ _Segment_cached_2::_Segment_cached_2(const Line_2& line,
const Point_2& target) :
m_l(line),
m_ps(source),
m_pt(target)
{
m_pt(target) {
Kernel kernel;
CGAL_precondition
@ -1312,8 +1281,7 @@ _Segment_cached_2(const Line_2& line,
//! \brief assigns.
template <typename Kernel>
const typename Arr_segment_traits_2<Kernel>::_Segment_cached_2&
Arr_segment_traits_2<Kernel>::_Segment_cached_2::operator=(const Segment_2& seg)
{
Arr_segment_traits_2<Kernel>::_Segment_cached_2::operator=(const Segment_2& seg) {
Kernel kernel;
auto vertex_ctr = kernel.construct_vertex_2_object();
@ -1338,8 +1306,7 @@ Arr_segment_traits_2<Kernel>::_Segment_cached_2::operator=(const Segment_2& seg)
//! \brief obtains the supporting line.
template <typename Kernel>
const typename Kernel::Line_2&
Arr_segment_traits_2<Kernel>::_Segment_cached_2::line() const
{
Arr_segment_traits_2<Kernel>::_Segment_cached_2::line() const {
if (!m_is_computed) {
Kernel kernel;
m_l = kernel.construct_line_2_object()(m_ps, m_pt);
@ -1351,8 +1318,7 @@ Arr_segment_traits_2<Kernel>::_Segment_cached_2::line() const
//! \brief determines whether the curve is vertical.
template <typename Kernel>
bool Arr_segment_traits_2<Kernel>::_Segment_cached_2::is_vertical() const
{
bool Arr_segment_traits_2<Kernel>::_Segment_cached_2::is_vertical() const {
// Force computation of line is orientation is still unknown
if (! m_is_computed) line();
CGAL_precondition(!m_is_degen);
@ -1397,8 +1363,7 @@ Arr_segment_traits_2<Kernel>::_Segment_cached_2::right() const
//! \brief sets the (lexicographically) left endpoint.
template <typename Kernel>
void Arr_segment_traits_2<Kernel>::_Segment_cached_2::set_left(const Point_2& p)
{
void Arr_segment_traits_2<Kernel>::_Segment_cached_2::set_left(const Point_2& p) {
CGAL_precondition(! m_is_degen);
CGAL_precondition_code(Kernel kernel);
CGAL_precondition
@ -1411,8 +1376,7 @@ void Arr_segment_traits_2<Kernel>::_Segment_cached_2::set_left(const Point_2& p)
//! \brief sets the (lexicographically) right endpoint.
template <typename Kernel>
void Arr_segment_traits_2<Kernel>::_Segment_cached_2::set_right(const Point_2& p)
{
void Arr_segment_traits_2<Kernel>::_Segment_cached_2::set_right(const Point_2& p) {
CGAL_precondition(! m_is_degen);
CGAL_precondition_code(Kernel kernel);
CGAL_precondition
@ -1428,8 +1392,7 @@ void Arr_segment_traits_2<Kernel>::_Segment_cached_2::set_right(const Point_2& p
*/
template <typename Kernel>
bool Arr_segment_traits_2<Kernel>::_Segment_cached_2::
is_in_x_range(const Point_2& p) const
{
is_in_x_range(const Point_2& p) const {
Kernel kernel;
typename Kernel::Compare_x_2 compare_x = kernel.compare_x_2_object();
const Comparison_result res1 = compare_x(p, left());
@ -1446,8 +1409,7 @@ is_in_x_range(const Point_2& p) const
*/
template <typename Kernel>
bool Arr_segment_traits_2<Kernel>::_Segment_cached_2::
is_in_y_range(const Point_2& p) const
{
is_in_y_range(const Point_2& p) const {
Kernel kernel;
typename Kernel::Compare_y_2 compare_y = kernel.compare_y_2_object();
const Comparison_result res1 = compare_y(p, left());
@ -1464,31 +1426,31 @@ is_in_y_range(const Point_2& p) const
*/
template <typename Kernel_>
class Arr_segment_2 : public Arr_segment_traits_2<Kernel_>::_Segment_cached_2 {
typedef Kernel_ Kernel;
using Kernel = Kernel_;
typedef typename Arr_segment_traits_2<Kernel>::_Segment_cached_2 Base;
typedef typename Kernel::Segment_2 Segment_2;
typedef typename Kernel::Point_2 Point_2;
typedef typename Kernel::Line_2 Line_2;
using Base = typename Arr_segment_traits_2<Kernel>::_Segment_cached_2;
using Segment_2 = typename Kernel::Segment_2;
using Point_2 = typename Kernel::Point_2;
using Line_2 = typename Kernel::Line_2;
public:
/*! Construct default. */
/*! constructs default. */
Arr_segment_2();
/*! Construct a segment from a "kernel" segment.
/*! constructs a segment from a "kernel" segment.
* \param seg the segment.
* \pre the segment is not degenerate.
*/
Arr_segment_2(const Segment_2& seg);
/*! Construct a segment from two endpoints.
/*! constructs a segment from two endpoints.
* \param source the source point.
* \param target the target point.
* \pre `source` and `target` are not equal.
*/
Arr_segment_2(const Point_2& source, const Point_2& target);
/*! Construct a segment from a line and two endpoints.
/*! constructs a segment from a line and two endpoints.
* \param line the supporting line.
* \param source the source point.
* \param target the target point.
@ -1498,7 +1460,7 @@ public:
Arr_segment_2(const Line_2& line,
const Point_2& source, const Point_2& target);
/*! Construct a segment from all fields.
/*! constructs a segment from all fields.
* \param line the supporting line.
* \param source the source point.
* \param target the target point.
@ -1510,11 +1472,11 @@ public:
const Point_2& source, const Point_2& target,
bool is_directed_right, bool is_vert, bool is_degen);
/*! Cast to a segment.
/*! casts to a segment.
*/
operator Segment_2() const;
/*! Flip the segment (swap its source and target).
/*! flips the segment (swap its source and target).
*/
Arr_segment_2 flip() const;
@ -1558,8 +1520,7 @@ Arr_segment_2<Kernel>::Arr_segment_2(const Line_2& line,
//! \brief casts to a segment.
template <typename Kernel>
Arr_segment_2<Kernel>::operator typename Kernel::Segment_2() const
{
Arr_segment_2<Kernel>::operator typename Kernel::Segment_2() const {
Kernel kernel;
auto seg_ctr = kernel.construct_segment_2_object();
return seg_ctr(this->source(), this->target());
@ -1567,8 +1528,7 @@ Arr_segment_2<Kernel>::operator typename Kernel::Segment_2() const
//! \brief flips the segment (swap its source and target).
template <typename Kernel>
Arr_segment_2<Kernel> Arr_segment_2<Kernel>::flip() const
{
Arr_segment_2<Kernel> Arr_segment_2<Kernel>::flip() const {
return Arr_segment_2(this->line(), this->target(), this->source(),
! (this->is_directed_right()), this->is_vertical(),
this->is_degenerate());
@ -1586,8 +1546,7 @@ Bbox_2 Arr_segment_2<Kernel>::bbox() const
/*! Exporter for the segment class used by the traits-class.
*/
template <typename Kernel, typename OutputStream>
OutputStream& operator<<(OutputStream& os, const Arr_segment_2<Kernel>& seg)
{
OutputStream& operator<<(OutputStream& os, const Arr_segment_2<Kernel>& seg) {
os << static_cast<typename Kernel::Segment_2>(seg);
return (os);
}
@ -1595,8 +1554,7 @@ OutputStream& operator<<(OutputStream& os, const Arr_segment_2<Kernel>& seg)
/*! Importer for the segment class used by the traits-class.
*/
template <typename Kernel, typename InputStream>
InputStream& operator>>(InputStream& is, Arr_segment_2<Kernel>& seg)
{
InputStream& operator>>(InputStream& is, Arr_segment_2<Kernel>& seg) {
typename Kernel::Segment_2 kernel_seg;
is >> kernel_seg;
seg = kernel_seg;

View File

@ -37,12 +37,12 @@ init_with_hint(const X_monotone_curve_2& cv, Pl_result_type obj) {
// associated with valid endpoints.
m_cv = cv;
auto psx = m_geom_traits->parameter_space_in_x_2_object();
auto psy = m_geom_traits->parameter_space_in_y_2_object();
if (m_geom_traits->is_closed_2_object()(m_cv, ARR_MIN_END)) {
// The left endpoint is valid.
const Arr_parameter_space ps_x1 =
m_geom_traits->parameter_space_in_x_2_object()(m_cv, ARR_MIN_END);
const Arr_parameter_space ps_y1 =
m_geom_traits->parameter_space_in_y_2_object()(m_cv, ARR_MIN_END);
const Arr_parameter_space ps_x1 = psx(m_cv, ARR_MIN_END);
const Arr_parameter_space ps_y1 = psy(m_cv, ARR_MIN_END);
m_has_left_pt = true;
m_left_on_boundary = (ps_x1 != ARR_INTERIOR || ps_y1 != ARR_INTERIOR);
m_left_pt = m_geom_traits->construct_min_vertex_2_object()(m_cv);
@ -55,10 +55,8 @@ init_with_hint(const X_monotone_curve_2& cv, Pl_result_type obj) {
if (m_geom_traits->is_closed_2_object()(m_cv, ARR_MAX_END)) {
// The right endpoint is valid.
const Arr_parameter_space ps_x2 =
m_geom_traits->parameter_space_in_x_2_object()(m_cv, ARR_MAX_END);
const Arr_parameter_space ps_y2 =
m_geom_traits->parameter_space_in_y_2_object()(m_cv, ARR_MAX_END);
const Arr_parameter_space ps_x2 = psx(m_cv, ARR_MAX_END);
const Arr_parameter_space ps_y2 = psy(m_cv, ARR_MAX_END);
m_has_right_pt = true;
m_right_on_boundary = (ps_x2 != ARR_INTERIOR || ps_y2 != ARR_INTERIOR);
m_right_pt = m_geom_traits->construct_max_vertex_2_object()(m_cv);
@ -252,11 +250,12 @@ bool Arrangement_zone_2<Arrangement, ZoneVisitor>::
do_overlap_impl(const X_monotone_curve_2& cv1,
const X_monotone_curve_2& cv2,
const Point_2& p, Arr_not_all_sides_oblivious_tag) const {
typename Traits_adaptor_2::Compare_y_at_x_right_2 cmp_right =
m_geom_traits->compare_y_at_x_right_2_object();
auto cmp_right = m_geom_traits->compare_y_at_x_right_2_object();
auto psx = m_geom_traits->parameter_space_in_x_2_object();
auto psy = m_geom_traits->parameter_space_in_y_2_object();
auto psx1 = m_geom_traits->parameter_space_in_x_2_object()(cv1, ARR_MIN_END);
auto psy1 = m_geom_traits->parameter_space_in_y_2_object()(cv1, ARR_MIN_END);
auto psx1 = psx(cv1, ARR_MIN_END);
auto psy1 = psy(cv1, ARR_MIN_END);
if ((psx1 == ARR_INTERIOR) && (psy1 == ARR_INTERIOR))
return (cmp_right(cv1, cv2, p) == EQUAL);
@ -265,8 +264,8 @@ do_overlap_impl(const X_monotone_curve_2& cv1,
bool vertical2 = m_geom_traits->is_vertical_2_object()(cv2);
if (vertical1 != vertical2) return false;
auto psx2 = m_geom_traits->parameter_space_in_x_2_object()(cv2, ARR_MIN_END);
auto psy2 = m_geom_traits->parameter_space_in_y_2_object()(cv2, ARR_MIN_END);
auto psx2 = psx(cv2, ARR_MIN_END);
auto psy2 = psy(cv2, ARR_MIN_END);
// If, for example, both curves are vertical and the bottom boundary is
// contracted, they may have different parameter space in x values.
@ -277,8 +276,7 @@ do_overlap_impl(const X_monotone_curve_2& cv1,
// left boundary, they completely lie on the left boundary and they overlap.
if (vertical1) return true;
typename Traits_adaptor_2::Compare_y_near_boundary_2 cmp_near =
m_geom_traits->compare_y_near_boundary_2_object();
auto cmp_near = m_geom_traits->compare_y_near_boundary_2_object();
return (cmp_near(cv1, cv2, ARR_MIN_END) == EQUAL);
}
@ -407,7 +405,7 @@ _direct_intersecting_edge_to_right(const X_monotone_curve_2& cv_ins,
// Check whether the curve lies above of below the edge immediately to
// the right of its left endpoint.
const Comparison_result pos_res =
const Comparison_result pos_res =
m_geom_traits->compare_y_at_x_right_2_object()(cv_ins, query_he->curve(),
cv_left_pt);
@ -459,7 +457,7 @@ _direct_intersecting_edge_to_left(const X_monotone_curve_2& cv_ins,
// Check whether the curve lies above of below the edge (we use the curve
// position predicate, as we know they cruves do not overlap and intersect
// only at the split point).
Comparison_result pos_res =
Comparison_result pos_res =
m_geom_traits->compare_y_position_2_object()(cv_ins, query_he->curve());
if (pos_res == EQUAL) {
@ -729,14 +727,14 @@ _is_to_left_impl(const Point_2& p, Halfedge_handle he,
// Check the boundary conditions of the minimal end of the curve associated
// with the given halfedge.
auto ps_in_x = m_geom_traits->parameter_space_in_x_2_object();
auto ps_x_min = ps_in_x(he->curve(), ARR_MIN_END);
auto psx = m_geom_traits->parameter_space_in_x_2_object();
auto ps_x_min = psx(he->curve(), ARR_MIN_END);
// Any point is not to the left of the left boundary.
if (ps_x_min == ARR_LEFT_BOUNDARY) return false;
auto ps_in_y = m_geom_traits->parameter_space_in_y_2_object();
auto ps_y_min = ps_in_y(he->curve(), ARR_MIN_END);
auto psy = m_geom_traits->parameter_space_in_y_2_object();
auto ps_y_min = psy(he->curve(), ARR_MIN_END);
if (ps_y_min != ARR_INTERIOR) {
// Check if p is to the left of the minimal curve-end:
auto cmp_x = m_geom_traits->compare_x_point_curve_end_2_object();
@ -766,16 +764,16 @@ _is_to_right_impl(const Point_2& p, Halfedge_handle he,
// Check the boundary conditions of the maximal end of the curve associated
// with the given halfedge.
auto ps_in_x = m_geom_traits->parameter_space_in_x_2_object();
auto ps_x_max = ps_in_x(he->curve(), ARR_MAX_END);
auto psx = m_geom_traits->parameter_space_in_x_2_object();
auto ps_x_max = psx(he->curve(), ARR_MAX_END);
// Any point is not to the right of the right boundary.
if (ps_x_max == ARR_RIGHT_BOUNDARY) return false;
// Any interior point is to the right of the left boundary.
if (ps_x_max == ARR_LEFT_BOUNDARY) return true;
auto ps_in_y = m_geom_traits->parameter_space_in_y_2_object();
auto ps_y_max = ps_in_y(he->curve(), ARR_MAX_END);
auto psy = m_geom_traits->parameter_space_in_y_2_object();
auto ps_y_max = psy(he->curve(), ARR_MAX_END);
if (ps_y_max != ARR_INTERIOR) {
// Check if p is to the right of the maximal curve-end:
auto cmp_x = m_geom_traits->compare_x_point_curve_end_2_object();
@ -790,6 +788,59 @@ _is_to_right_impl(const Point_2& p, Halfedge_handle he,
return (m_geom_traits->compare_xy_2_object()(p, v_right->point()) == LARGER);
}
//! checks whether a point lies to the left of another point.
template <typename Arrangement, typename ZoneVisitor>
bool Arrangement_zone_2<Arrangement, ZoneVisitor>::
is_to_left_impl(const Point_2& p1, Arr_parameter_space /* ps1 */,
const Point_2& p2, Arr_parameter_space /* ps2 */,
Arr_all_sides_oblivious_tag) const {
auto cmp_xy = m_geom_traits->compare_xy_2_object();
return (cmp_xy(p2, p1) == SMALLER);
}
//! checks whether a point lies to the left of another point.
template <typename Arrangement, typename ZoneVisitor>
bool Arrangement_zone_2<Arrangement, ZoneVisitor>::
is_to_left_impl(const Point_2& p1, Arr_parameter_space /* ps1 */,
const Point_2& p2, Arr_parameter_space /* ps2 */,
Arr_has_identified_side_tag) const {
auto is_on_y_ident = m_geom_traits->is_on_y_identification_2_object();
if (is_on_y_ident(p1)) {
if (is_on_y_ident(p2)) {
auto cmp_y_on_boundary = m_geom_traits->compare_y_on_boundary_2_object();
return (cmp_y_on_boundary(p2, p1) == SMALLER);
}
return false;
}
if (is_on_y_ident(p2)) return true;
auto cmp_xy = m_geom_traits->compare_xy_2_object();
return (cmp_xy(p2, p1) == SMALLER);
}
//! checks whether a point lies to the left of another point.
template <typename Arrangement, typename ZoneVisitor>
bool Arrangement_zone_2<Arrangement, ZoneVisitor>::
is_to_left_impl(const Point_2& p1, Arr_parameter_space ps1,
const Point_2& p2, Arr_parameter_space ps2,
Arr_boundary_cond_tag) const {
if (ps1 == ARR_LEFT_BOUNDARY) {
if (ps2 == ARR_LEFT_BOUNDARY) {
auto cmp_y_on_boundary = m_geom_traits->compare_y_on_boundary_2_object();
return (cmp_y_on_boundary(p2, p1) == SMALLER);
}
return false;
}
if (ps1 == ARR_RIGHT_BOUNDARY) {
if (ps2 == ARR_RIGHT_BOUNDARY) {
auto cmp_y_on_boundary = m_geom_traits->compare_y_on_boundary_2_object();
return (cmp_y_on_boundary(p2, p1) == SMALLER);
}
return true;
}
auto cmp_xy = m_geom_traits->compare_xy_2_object();
return (cmp_xy(p2, p1) == SMALLER);
}
//-----------------------------------------------------------------------------
// Compute the (lexicographically) leftmost intersection of the query
// curve with a given halfedge on the boundary of a face in the arrangement.
@ -866,11 +917,7 @@ _leftmost_intersection(Ccb_halfedge_circulator he_curr, bool on_boundary,
// Found a simple intersection point. Check if it is the leftmost
// intersection point so far.
if (! m_found_intersect ||
((intersection_location != ARR_RIGHT_BOUNDARY) &&
((leftmost_location == ARR_RIGHT_BOUNDARY) ||
compare_xy(ip, m_intersect_p) == SMALLER)))
{
if (! m_found_intersect || is_to_left(m_intersect_p, leftmost_location, ip, intersection_location)) {
// Store the leftmost intersection point and the halfedge handle.
m_intersect_p = ip;
m_ip_multiplicity = int_p->second;
@ -1034,9 +1081,14 @@ _zone_in_face(Face_handle face, bool on_boundary) {
// Set m_cv to be the remaining portion.
m_has_left_pt = true;
m_left_on_boundary = false;
m_left_pt = m_intersect_p;
m_cv = m_sub_cv2;
auto psx = m_geom_traits->parameter_space_in_x_2_object();
auto psy = m_geom_traits->parameter_space_in_y_2_object();
auto ps_x = psx(m_left_pt);
auto ps_y = psy(m_left_pt);
m_left_on_boundary = (ps_x != ARR_INTERIOR || ps_y != ARR_INTERIOR);
}
const X_monotone_curve_2* p_orig_curve = nullptr;
@ -1220,11 +1272,9 @@ bool Arrangement_zone_2<Arrangement, ZoneVisitor>::_zone_in_overlap() {
#endif
// Obtain some geometry-traits functors.
typename Traits_adaptor_2::Equal_2 equal = m_geom_traits->equal_2_object();
typename Traits_adaptor_2::Is_closed_2 is_closed =
m_geom_traits->is_closed_2_object();
typename Traits_adaptor_2::Construct_max_vertex_2 ctr_max_vertex =
m_geom_traits->construct_max_vertex_2_object();
auto equal = m_geom_traits->equal_2_object();
auto is_closed = m_geom_traits->is_closed_2_object();
auto ctr_max_vertex = m_geom_traits->construct_max_vertex_2_object();
// Check if the right end of m_overlap_cv is bounded. If so, compute its
// right endpoint.
@ -1310,8 +1360,13 @@ bool Arrangement_zone_2<Arrangement, ZoneVisitor>::_zone_in_overlap() {
// Set m_cv to be the remaining portion.
m_has_left_pt = true;
m_left_on_boundary = false;
m_left_pt = cv_right_pt;
auto psx = m_geom_traits->parameter_space_in_x_2_object();
auto psy = m_geom_traits->parameter_space_in_y_2_object();
auto ps_x = psx(m_left_pt);
auto ps_y = psy(m_left_pt);
m_left_on_boundary = (ps_x != ARR_INTERIOR || ps_y != ARR_INTERIOR);
m_cv = m_sub_cv2;
// Move to the remaining portion of the curve, whose left endpoint is the

View File

@ -415,6 +415,24 @@ private:
Arr_parameter_space& intersection_location,
Arr_boundary_cond_tag) const;
/*! checks whether an point lies to the left of another point.
*/
bool is_to_left(const Point_2& p1, Arr_parameter_space ps1,
const Point_2& p2, Arr_parameter_space ps2) const
{ return is_to_left_impl(p1, ps1, p2, ps2, Left_or_right_sides_category()); }
bool is_to_left_impl(const Point_2& p1, Arr_parameter_space ps1,
const Point_2& p2, Arr_parameter_space ps2,
Arr_all_sides_oblivious_tag) const;
bool is_to_left_impl(const Point_2& p1, Arr_parameter_space ps1,
const Point_2& p2, Arr_parameter_space ps2,
Arr_has_identified_side_tag) const;
bool is_to_left_impl(const Point_2& p1, Arr_parameter_space ps1,
const Point_2& p2, Arr_parameter_space ps2,
Arr_boundary_cond_tag) const;
/*! computes the (lexicographically) leftmost intersection of the query
* curve with a given halfedge on the boundary of a face in the arrangement.
*/

View File

@ -0,0 +1,72 @@
// Copyright (c) 2025
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and 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): Shepard Liu <shepard0liu@gmail.com>
#ifndef CGAL_DRAW_AOS_ARR_APPROXIMATION_CACHE_H
#define CGAL_DRAW_AOS_ARR_APPROXIMATION_CACHE_H
#include <CGAL/license/Arrangement_on_surface_2.h>
#include <boost/range/iterator_range.hpp>
#include <CGAL/Arr_enums.h>
#include <CGAL/unordered_flat_map.h>
#include <CGAL/Draw_aos/type_utils.h>
namespace CGAL {
namespace draw_aos {
/** @brief Cache class for approximating arrangement on surface.
*
* When iterating over the arrangement dcel, a feature(vertex, halfedge, face) might be visited multiple times.
* This cache stores the approximated geometry for each feature to avoid redundant calculations.
* @tparam Arrangement
*/
template <typename Arrangement>
class Arr_approximation_cache {
using Geom_traits = typename Arrangement::Geometry_traits_2;
using Approx_traits = Arr_approximate_traits<Geom_traits>;
using Vertex_cache_obj = typename Approx_traits::Point;
using Halfedge_cache_obj = typename Approx_traits::Polyline;
using Face_cache_obj = typename Approx_traits::Triangle_soup;
using Vertex_const_handle = typename Arrangement::Vertex_const_handle;
using Halfedge_const_handle = typename Arrangement::Halfedge_const_iterator;
using Face_const_handle = typename Arrangement::Face_const_handle;
using Vertex_cache = unordered_flat_map<Vertex_const_handle, Vertex_cache_obj>;
using Halfedge_cache = unordered_flat_map<Halfedge_const_handle, Halfedge_cache_obj>;
using Face_cache = unordered_flat_map<Face_const_handle, Face_cache_obj>;
public:
Arr_approximation_cache() = default;
const Vertex_cache& vertices() const { return m_vertices; }
const Halfedge_cache& halfedges() const { return m_halfedges; }
const Face_cache& faces() const { return m_faces; }
Vertex_cache& vertices() { return m_vertices; }
Halfedge_cache& halfedges() { return m_halfedges; }
Face_cache& faces() { return m_faces; }
private:
Vertex_cache m_vertices;
Halfedge_cache m_halfedges;
Face_cache m_faces;
};
} // namespace draw_aos
} // namespace CGAL
#endif

View File

@ -0,0 +1,258 @@
// Copyright (c) 2025
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and 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): Shepard Liu <shepard0liu@gmail.com>
#ifndef CGAL_DRAW_AOS_ARR_BOUNDED_APPROXIMATE_FACE_H
#define CGAL_DRAW_AOS_ARR_BOUNDED_APPROXIMATE_FACE_H
#include <CGAL/license/Arrangement_on_surface_2.h>
#include <iterator>
#include <optional>
#include <utility>
#include <algorithm>
#include <boost/iterator/function_output_iterator.hpp>
#include <CGAL/Arr_enums.h>
#include <CGAL/Bbox_2.h>
#include <CGAL/Draw_aos/Arr_bounded_approximate_halfedge.h>
#include <CGAL/Draw_aos/Arr_bounded_approximate_vertex.h>
#include <CGAL/Draw_aos/Arr_bounded_face_triangulator.h>
#include <CGAL/Draw_aos/Arr_render_context.h>
#include <CGAL/Draw_aos/type_utils.h>
namespace CGAL {
namespace draw_aos {
/*! \brief Functor to approximate arrangement face with triangles within a bounding box.
*
* \tparam Arrangement
*/
template <typename Arrangement>
class Arr_bounded_approximate_face {
using Face_const_handle = typename Arrangement::Face_const_handle;
using Halfedge_const_handle = typename Arrangement::Halfedge_const_handle;
using Vertex_const_handle = typename Arrangement::Vertex_const_handle;
using Ccb_halfedge_const_circulator = typename Arrangement::Ccb_halfedge_const_circulator;
using Geom_traits = typename Arrangement::Geometry_traits_2;
using Approx_traits = Arr_approximate_traits<Geom_traits>;
using Point = typename Approx_traits::Point;
using Polyline = typename Approx_traits::Polyline;
using Triangle_soup = typename Approx_traits::Triangle_soup;
using Bounded_approximate_vertex = Arr_bounded_approximate_vertex<Arrangement>;
using Bounded_approximate_halfedge = Arr_bounded_approximate_halfedge<Arrangement>;
using Bounded_render_context = Arr_bounded_render_context<Arrangement>;
using Triangulator = Arr_bounded_face_triangulator<Arrangement>;
static constexpr bool Is_on_curved_surface = is_or_derived_from_curved_surf_traits_v<Geom_traits>;
struct Left_to_right_tag {};
struct Right_to_left_tag {};
private:
/*! \brief A stateful geometry simplifier that simplifies horizontal and vertical segments
*
* \tparam OutputIterator
*/
template <typename OutputIterator>
class Colinear_simplifier {
public:
Colinear_simplifier(OutputIterator out_it) : m_out_it(out_it) {}
void dump() {
if (m_start.has_value()) {
*m_out_it++ = m_start.value();
m_start.reset();
}
if (m_mid.has_value()) {
*m_out_it++ = m_mid.value();
m_mid.reset();
}
}
void push_back(Point p) {
if (m_mid.has_value()) {
if (((p.y() == m_mid->y()) && (p.y() == m_start->y())) || ((p.x() == m_mid->x()) && (p.x() == m_start->x())))
// Three points are collinear horizontally or vertically.
m_mid = p;
else {
*m_out_it++ = m_start.value();
m_start = m_mid;
m_mid = p;
}
return;
}
if (m_start.has_value())
m_mid = p;
else
m_start = p;
}
~Colinear_simplifier() { dump(); }
private:
OutputIterator m_out_it;
std::optional<Point> m_start, m_mid;
};
class Context : public Bounded_render_context {
using Simplifier = Colinear_simplifier<std::back_insert_iterator<Triangulator>>;
public:
Context(const Bounded_render_context& ctx, Triangulator& triangulator) :
Bounded_render_context(ctx),
m_triangulator(triangulator) {
if constexpr(!Is_on_curved_surface) m_simplifier.emplace(std::back_inserter(m_triangulator));
}
// Let's not accidentally copy this object.
Context(const Context&) = delete;
Context& operator=(const Context&) = delete;
void insert(Point pt) {
if (Approx_traits::is_null(pt) || pt == m_last_pt) return;
pt = Point(pt.x(), std::clamp(pt.y(), this->ymin(), this->ymax()));
if constexpr(!Is_on_curved_surface) {
m_simplifier->push_back(pt);
return;
}
m_triangulator.push_back(pt);
m_last_pt = pt;
}
void start_ccb() { m_triangulator.start_constraint(); }
void end_ccb() {
if constexpr(!Is_on_curved_surface) m_simplifier->dump();
m_triangulator.end_constraint();
}
const std::optional<Point>& last_pt() const { return m_last_pt; }
private:
Triangulator& m_triangulator;
// Colinear simplifier is only used for optimizing planar arrangements.
std::optional<Simplifier> m_simplifier;
std::optional<Point> m_last_pt;
};
private:
static Arr_parameter_space side_of_fict_edge(const Halfedge_const_handle& he) {
const auto& source = he->source();
const auto& target = he->target();
auto sx = source->parameter_space_in_x();
auto sy = source->parameter_space_in_y();
auto tx = target->parameter_space_in_x();
auto ty = target->parameter_space_in_y();
if (sx == tx && sx != ARR_INTERIOR) return sx;
if (sy == ty && sy != ARR_INTERIOR) return sy;
CGAL_assertion(false && "Unexpected parameter space for fictitious edge ends.");
return ARR_INTERIOR;
}
// Generate dummy segment for fictitious edge he at its corresponding boundary.
static Polyline approximate_fict_edge(const Context& ctx, const Halfedge_const_handle& he) {
auto side = side_of_fict_edge(he);
// There's no need to handle fictitious edges on left or right boundaries.
if (side == ARR_LEFT_BOUNDARY || side == ARR_RIGHT_BOUNDARY) return Polyline{};
if (side == ARR_BOTTOM_BOUNDARY) return Polyline{ctx.bottom_left(), ctx.bottom_right()};
if (side == ARR_TOP_BOUNDARY) return Polyline{ctx.top_right(), ctx.top_left()};
CGAL_assertion(false && "Unexpected side for a fictitious edge.");
return Polyline{};
}
void approximate_vertex(Context& /* ctx */, const Vertex_const_handle& vh) const {
if (vh->is_at_open_boundary()) return;
m_bounded_approx_vertex(vh);
}
void approximate_halfedge(Context& ctx, const Halfedge_const_handle& he) const {
const Polyline& polyline = he->is_fictitious() ? approximate_fict_edge(ctx, he) : m_bounded_approx_halfedge(he);
for (const auto& curr_pt : polyline) ctx.insert(curr_pt);
}
void approximate_ccb(Context& ctx, Ccb_halfedge_const_circulator start) const {
// Try to start on a concrete halfedge.
// For any unbounded face, there can't be more than 4 adjacent fictitious edges.
for (int i = 0; i < 4 && start->is_fictitious(); ++i) ++start;
ctx.start_ccb();
auto circ = start;
do {
approximate_halfedge(ctx, circ);
approximate_vertex(ctx, circ->target());
} while(++circ != start);
ctx.end_ccb();
}
public:
Arr_bounded_approximate_face(const Bounded_render_context& ctx) :
m_ctx(ctx),
m_bounded_approx_halfedge(ctx),
m_bounded_approx_vertex(ctx)
{}
/*! \brief Approximate an arrangement face with a bunch of triangles.
*
* \param fh
* \return const Triangulated_face&
*/
const Triangle_soup& operator()(const Face_const_handle& fh) const {
CGAL_precondition_msg(!fh->is_fictitious(), "Cannot approximate a fictitious face.");
auto [iter, inserted] = m_ctx.m_cache.faces().try_emplace(fh);
Triangle_soup& ts = iter->second;
if (! inserted || m_ctx.is_cancelled()) return ts;
auto triangulator = Triangulator(m_ctx, fh);
auto ctx = Context(m_ctx, triangulator);
if (! Is_on_curved_surface && !fh->has_outer_ccb()) {
// Skip approximation of the unbounded face in planar arrangements.
// However, degenerate holes still need to be approximated.
for (auto inner_ccb = fh->inner_ccbs_begin(); inner_ccb != fh->inner_ccbs_end(); ++inner_ccb) {
auto circ = *inner_ccb;
do {
if (circ->face() != circ->twin()->face()) continue;
m_bounded_approx_halfedge(circ);
} while(++circ != *inner_ccb);
}
for (auto vh = fh->isolated_vertices_begin(); vh != fh->isolated_vertices_end(); ++vh) m_bounded_approx_vertex(vh);
return ts;
}
for (auto outer_ccb = fh->outer_ccbs_begin(); outer_ccb != fh->outer_ccbs_end(); ++outer_ccb)
approximate_ccb(ctx, *outer_ccb);
for (auto inner_ccb = fh->inner_ccbs_begin(); inner_ccb != fh->inner_ccbs_end(); ++inner_ccb)
approximate_ccb(ctx, *inner_ccb);
for (auto iso_vertex = fh->isolated_vertices_begin(); iso_vertex != fh->isolated_vertices_end(); ++iso_vertex)
approximate_vertex(ctx, iso_vertex);
return ts = std::move(triangulator);
}
private:
const Bounded_render_context& m_ctx;
const Bounded_approximate_halfedge m_bounded_approx_halfedge;
const Bounded_approximate_vertex m_bounded_approx_vertex;
};
} // namespace draw_aos
} // namespace CGAL
#endif

View File

@ -0,0 +1,337 @@
// Copyright (c) 2025
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and 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): Shepard Liu <shepard0liu@gmail.com>
#ifndef CGAL_DRAW_AOS_ARR_BOUNDED_APPROXIMATE_HALFEDGE_H
#define CGAL_DRAW_AOS_ARR_BOUNDED_APPROXIMATE_HALFEDGE_H
#include <CGAL/license/Arrangement_on_surface_2.h>
#include <algorithm>
#include <array>
#include <cstdlib>
#include <optional>
#include <type_traits>
#include <boost/iterator/function_output_iterator.hpp>
#include <CGAL/enum.h>
#include <CGAL/Arr_enums.h>
#include <CGAL/Arr_has.h>
#include <CGAL/Draw_aos/Arr_render_context.h>
#include <CGAL/Draw_aos/type_utils.h>
namespace CGAL {
namespace draw_aos {
/** @brief Functor to approximate an x-monotone curve within an bounding box.
*
* The Approximation is done from xmin to xmax with a given step. For parts outbound the y limits and precedes or
* succeeds a part within, the approximation may be skipped but there will be at least one point outside the bbox
* for indication.
*/
template <typename Arrangement>
class Arr_bounded_approximate_halfedge {
using Geom_traits = typename Arrangement::Geometry_traits_2;
using Halfedge_const_handle = typename Arrangement::Halfedge_const_handle;
using Gt_point = typename Geom_traits::Point_2;
using Approx_traits = Arr_approximate_traits<Geom_traits>;
using Approx_nt = typename Approx_traits::Approx_nt;
using Approx_point = typename Approx_traits::Approx_point;
using Point = typename Approx_traits::Point;
using Polyline = typename Approx_traits::Polyline;
using Approx_kernel = typename Approx_traits::Approx_kernel;
using Approx_line_2 = typename Approx_kernel::Line_2;
using X_monotone_curve_2 = typename Geom_traits::X_monotone_curve_2;
using Bounded_render_context = Arr_bounded_render_context<Arrangement>;
using Boundary_lines = std::array<Approx_line_2, 4>;
constexpr static bool Has_approximate_xcv_with_bounds =
has_approximate_xcv_with_bounds_v<Geom_traits, typename Geom_traits::Approximate_2>;
private:
struct Context : public Bounded_render_context {
Context(const Bounded_render_context& ctx, const X_monotone_curve_2& curve, Polyline& polyline) :
Bounded_render_context(ctx),
m_polyline(polyline), m_curve(curve)
{}
// Prevent accidental copying.
Context(const Context&) = delete;
Context& operator=(const Context&) = delete;
public:
/*! \brief Insert a point to the polyline if it is within the x-range of the curve
* \note Will be replaced after AosApproximateUnboundedTraits_2 is fully available.
* \param pt
*/
void insert(Point pt) {
if (pt.x() < this->xmin()) {
// We need the last point if not yet x-inbound.
m_last_pt = pt;
return;
}
else if (pt.x() > this->xmax()) return;
m_polyline.push_back(pt);
m_last_pt = pt;
}
const std::optional<Point>& last_pt() const { return m_last_pt; }
private:
std::optional<Point> m_last_pt;
public:
Polyline& m_polyline;
const X_monotone_curve_2& m_curve;
};
/*! \brief Computes the intersection point between the given boundary side and the line segment from last_pt to pt.
*/
Point boundary_intersection(const Context& ctx, Point pt, Boundary_side side) const {
std::optional<double> x, y;
const Approx_line_2* line = nullptr;
switch(side) {
case Boundary_side::Left:
x = ctx.xmin();
line = &m_left;
break;
case Boundary_side::Right:
x = ctx.xmax();
line = &m_right;
break;
case Boundary_side::Top:
y = ctx.ymax();
line = &m_top;
break;
case Boundary_side::Bottom:
y = ctx.ymin();
line = &m_bottom;
break;
default:
CGAL_assertion(false && "Unexpected side of boundary.");
}
Point inter = std::get<Point>(*CGAL::intersection(Approx_line_2(*ctx.last_pt(), pt), *line));
if (x.has_value()) return Point(*x, inter.y());
return Point(inter.x(), *y);
}
/*! \brief Trace approximated curve point in ltr ordering, adding boundary intersections if necessary.
*
* \note This method will eventually be replaced by AosApproximateUnboundedTraits_2.
*/
void trace_add(Context& ctx, Point pt) const {
if (! ctx.last_pt().has_value()) {
ctx.insert(pt);
return;
}
if (ctx.last_pt()->x() < ctx.xmin() && pt.x() >= ctx.xmin())
ctx.insert(boundary_intersection(ctx, pt, Boundary_side::Left));
if (ctx.last_pt()->y() < ctx.ymin()) {
if (pt.y() > ctx.ymin()) ctx.insert(boundary_intersection(ctx, pt, Boundary_side::Bottom));
if (pt.y() > ctx.ymax()) ctx.insert(boundary_intersection(ctx, pt, Boundary_side::Top));
}
else if (ctx.last_pt()->y() > ctx.ymax()) {
if (pt.y() < ctx.ymax()) ctx.insert(boundary_intersection(ctx, pt, Boundary_side::Top));
if (pt.y() < ctx.ymin()) ctx.insert(boundary_intersection(ctx, pt, Boundary_side::Bottom));
}
else {
if (pt.y() < ctx.ymin())
ctx.insert(boundary_intersection(ctx, pt, Boundary_side::Bottom));
else if (pt.y() > ctx.ymax())
ctx.insert(boundary_intersection(ctx, pt, Boundary_side::Top));
}
if (ctx.last_pt()->x() <= ctx.xmax() && pt.x() > ctx.xmax())
ctx.insert(boundary_intersection(ctx, pt, Boundary_side::Right));
ctx.insert(pt);
}
/*! \brief Check if the point is within the x-range of the curve.
*/
static bool is_in_x_range(const Context& ctx, const Gt_point& pt) {
const Geom_traits& traits = ctx.m_traits;
const X_monotone_curve_2& curve = ctx.m_curve;
if constexpr(has_is_in_x_range_v<Geom_traits>) return curve.is_in_x_range(pt);
if constexpr(!has_parameter_space_in_x_2<Geom_traits>::value) {
const auto& min_pt = traits.construct_min_vertex_2_object()(curve);
const auto& max_pt = traits.construct_max_vertex_2_object()(curve);
return ((traits.compare_x_2_object()(pt, min_pt) != CGAL::SMALLER) &&
(traits.compare_x_2_object()(pt, max_pt) != CGAL::LARGER));
}
Comparison_result left_cmp;
if (auto left_loc = traits.parameter_space_in_x_2_object()(curve, ARR_MIN_END); left_loc == ARR_INTERIOR)
left_cmp = traits.compare_x_2_object()(pt, traits.construct_min_vertex_2_object()(curve));
else if (left_loc == ARR_LEFT_BOUNDARY)
left_cmp = CGAL::LARGER;
else
left_cmp = traits.compare_x_on_boundary_2_object()(pt, curve, ARR_MIN_END);
if (left_cmp == CGAL::SMALLER) return false;
if (left_cmp == CGAL::EQUAL) return true;
Comparison_result right_cmp;
if (auto right_loc = traits.parameter_space_in_x_2_object()(curve, ARR_MAX_END); right_loc == ARR_INTERIOR)
right_cmp = traits.compare_x_2_object()(pt, traits.construct_max_vertex_2_object()(curve));
else if (right_loc == ARR_RIGHT_BOUNDARY)
right_cmp = CGAL::SMALLER;
else
right_cmp = traits.compare_x_on_boundary_2_object()(pt, curve, ARR_MAX_END);
return right_cmp != CGAL::LARGER;
}
/*! \brief transform approximated curve points(ltr ordering) in place based on the halfedge, giving correct
* ordering, continuity, etc.
*/
static void transform_polyline(Context& ctx, Polyline& polyline, const Halfedge_const_handle& he)
{ transform_polyline_impl<Geom_traits>(ctx, polyline, he); }
// For planar arrangements, we only need to reverse the polyline if the halfedge is rtl.
template <typename Gt, std::enable_if_t<!is_or_derived_from_curved_surf_traits_v<Gt>, int> = 0>
static void transform_polyline_impl(Context&, Polyline& polyline, const Halfedge_const_handle& he) {
if (he->direction() == CGAL::ARR_LEFT_TO_RIGHT) return;
std::reverse(polyline.begin(), polyline.end());
}
template <typename Gt, std::enable_if_t<is_or_derived_from_agas_v<Gt>, int> = 0>
static void transform_polyline_impl(Context& ctx, Polyline& polyline, const Halfedge_const_handle& he) {
using Direction_3 = typename Geom_traits::Direction_3;
using Vector_3 = typename Geom_traits::Vector_3;
if (polyline.size() < 2) return;
const X_monotone_curve_2& curve = he->curve();
const auto& traits = ctx.m_traits;
if (curve.is_vertical()) {
Direction_3 normal_dir = curve.is_directed_right() ? curve.normal() : -curve.normal();
Direction_3 azimuth_dir(CGAL::cross_product(Vector_3(0, 0, 1), normal_dir.vector()));
Approx_nt azimuth = ctx.to_uv(traits.approximate_2_object()(traits.construct_point_2_object()(azimuth_dir))).x();
if (azimuth == 0 && he->direction() == ARR_LEFT_TO_RIGHT) azimuth = 2 * CGAL_PI;
std::transform(polyline.begin(), polyline.end(), polyline.begin(),
[azimuth](Point pt) { return Point(azimuth, pt.y()); });
}
else if (polyline.back().x() == 0) {
// For strictly x-monotone arcs whose target point sits on the boundary, the x should be set to 2 * CGAL_PI
polyline.back() = Point(2 * CGAL_PI, polyline.back().y());
}
if (he->direction() == CGAL::ARR_LEFT_TO_RIGHT) return;
std::reverse(polyline.begin(), polyline.end());
}
void approximate_curve(Context& ctx) const { approximate_curve_impl<Geom_traits>(ctx); }
// If Approximate_2 supports curve approximation with bounding box
template <typename Gt, std::enable_if_t<has_approximate_xcv_with_bounds_v<Gt, typename Gt::Approximate_2>, int> = 0>
void approximate_curve_impl(Context& ctx) const {
const Geom_traits& traits = ctx.m_traits;
const X_monotone_curve_2& curve = ctx.m_curve;
Polyline& polyline = ctx.m_polyline;
auto compare_y_at_x_2 = traits.compare_y_at_x_2_object();
if (is_in_x_range(ctx, m_top_left)) {
if (compare_y_at_x_2(m_top_left, curve) == CGAL::SMALLER) {
polyline.insert(polyline.end(), {Approx_traits::Null_point, Point(ctx.xmin(), ctx.ymax())});
}
else if (compare_y_at_x_2(m_bottom_left, curve) == CGAL::LARGER) {
polyline.insert(polyline.end(), {Approx_traits::Null_point, Point(ctx.xmin(), ctx.ymin())});
}
}
traits.approximate_2_object()(curve, ctx.m_approx_error,
boost::make_function_output_iterator([&ctx, this](Approx_point approx_pt)
{ ctx.m_polyline.push_back(snap_to_boundary(ctx, ctx.to_uv(approx_pt))); }),
ctx.bbox(), true);
if (is_in_x_range(ctx, m_top_right)) {
if (compare_y_at_x_2(m_top_right, curve) == CGAL::SMALLER) {
polyline.insert(polyline.end(), {Point(ctx.xmax(), ctx.ymax()), Approx_traits::Null_point});
}
else if (compare_y_at_x_2(m_bottom_right, curve) == CGAL::LARGER) {
polyline.insert(polyline.end(), {Point(ctx.xmax(), ctx.ymin()), Approx_traits::Null_point});
}
}
}
// If Approximate_2 does not support curve approximation with bounding box
template <typename Gt, std::enable_if_t<!has_approximate_xcv_with_bounds_v<Gt, typename Gt::Approximate_2>, int> = 0>
void approximate_curve_impl(Context& ctx) const {
auto approx = m_ctx.m_traits.approximate_2_object();
approx(ctx.m_curve, ctx.m_approx_error,
boost::make_function_output_iterator([&ctx, this](Approx_point pt) { trace_add(ctx, ctx.to_uv(pt)); }), true);
}
/*! \brief Adjusts a point by snapping it to the nearest boundary to reduce floating-point error.
*
* \return The adjusted (snapped) point if it lies within snapping tolerance, or the original point otherwise.
*/
Point snap_to_boundary(const Context& ctx, Point pt) const {
Approx_nt x = pt.x(), y = pt.y();
if (std::abs(x - ctx.xmin()) < m_ep_left) x = ctx.xmin();
else if (std::abs(x - ctx.xmax()) < m_ep_right) x = ctx.xmax();
if (std::abs(y - ctx.ymin()) < m_ep_bottom) y = ctx.ymin();
else if (std::abs(y - ctx.ymax()) < m_ep_top) y = ctx.ymax();
return Point(x, y);
}
public:
Arr_bounded_approximate_halfedge(const Bounded_render_context& ctx) :
m_ctx(ctx),
m_left(ctx.bottom_left(), ctx.top_left()),
m_right(ctx.bottom_right(), ctx.top_right()),
m_bottom(ctx.bottom_left(), ctx.bottom_right()),
m_top(ctx.top_left(), ctx.top_right()) {
Construct_gt_point_2<Geom_traits> ctr_p;
m_top_left = ctr_p(ctx.to_cartesian(ctx.top_left()));
m_top_right = ctr_p(ctx.to_cartesian(ctx.top_right()));
m_bottom_left = ctr_p(ctx.to_cartesian(ctx.bottom_left()));
m_bottom_right = ctr_p(ctx.to_cartesian(ctx.bottom_right()));
Approx_nt ep_base = std::numeric_limits<Approx_nt>::epsilon();
m_ep_left = std::max(std::abs(ep_base * ctx.xmin()), ep_base);
m_ep_right = std::max(std::abs(ep_base * ctx.xmax()), ep_base);
m_ep_bottom = std::max(std::abs(ep_base * ctx.ymin()), ep_base);
m_ep_top = std::max(std::abs(ep_base * ctx.ymax()), ep_base);
}
const Polyline& operator()(const Halfedge_const_handle& he) const {
CGAL_assertion(!he->is_fictitious());
auto& cache = m_ctx.m_cache.halfedges();
auto [iter, inserted] = cache.try_emplace(he, Polyline());
Polyline& polyline = iter->second;
if (!inserted) return polyline;
if (m_ctx.is_cancelled()) return polyline;
const X_monotone_curve_2& curve = he->curve();
Context ctx(m_ctx, curve, polyline);
approximate_curve(ctx);
Polyline poly_copy(polyline);
transform_polyline(ctx, polyline, he);
// also approximate the twin halfedge
auto [twin_iter, twin_inserted] = cache.try_emplace(he->twin(), std::move(poly_copy));
if (twin_inserted) transform_polyline(ctx, twin_iter->second, he->twin());
// The previous iterator might have been invalidated by the second try_emplace call, so we do an extra lookup.
return cache.at(he);
}
private:
const Bounded_render_context& m_ctx;
Approx_line_2 m_left, m_right, m_bottom, m_top;
Gt_point m_top_left, m_top_right, m_bottom_left, m_bottom_right;
Approx_nt m_ep_left, m_ep_right, m_ep_bottom, m_ep_top;
};
} // namespace draw_aos
} // namespace CGAL
#endif

View File

@ -0,0 +1,60 @@
// Copyright (c) 2025
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and 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): Shepard Liu <shepard0liu@gmail.com>
#ifndef CGAL_DRAW_AOS_ARR_BOUNDED_APPROXIMATE_VERTEX_H
#define CGAL_DRAW_AOS_ARR_BOUNDED_APPROXIMATE_VERTEX_H
#include <CGAL/license/Arrangement_on_surface_2.h>
#include <CGAL/Draw_aos/type_utils.h>
#include <CGAL/Draw_aos/Arr_render_context.h>
namespace CGAL {
namespace draw_aos {
template <typename Arrangement>
class Arr_bounded_approximate_vertex {
using Geom_traits = typename Arrangement::Geometry_traits_2;
using Point_2 = typename Geom_traits::Point_2;
using Vertex_const_handle = typename Arrangement::Vertex_const_handle;
using Point_geom = typename Arr_approximate_traits<Geom_traits>::Point;
using Bounded_render_context = Arr_bounded_render_context<Arrangement>;
public:
Arr_bounded_approximate_vertex(const Bounded_render_context& ctx) : m_ctx(ctx) {}
/** @brief Approximate a vertex within the x-bounded range.
*
* The function uses cached values if available.
* @precondition: The vertex must have an associated point.
*
* @param vh the vertex handle
* @return const Point_geom&
*/
const Point_geom& operator()(const Vertex_const_handle& vh) const {
auto [iter, inserted] = m_ctx.m_cache.vertices().try_emplace(vh);
Point_geom& point = iter->second;
if (! inserted) return point;
return point = m_ctx.to_uv(m_ctx.m_traits.approximate_2_object()(vh->point()));
}
private:
const Bounded_render_context& m_ctx;
};
} // namespace draw_aos
} // namespace CGAL
#endif

View File

@ -0,0 +1,317 @@
// Copyright (c) 2025
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and 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): Shepard Liu <shepard0liu@gmail.com>
#ifndef CGAL_DRAW_AOS_ARR_FACE_TRIANGULATOR_H
#define CGAL_DRAW_AOS_ARR_FACE_TRIANGULATOR_H
#include <CGAL/license/Arrangement_on_surface_2.h>
#include <algorithm>
#include <optional>
#include <type_traits>
#include <utility>
#include <vector>
#include <boost/iterator/function_output_iterator.hpp>
#include <boost/iterator/transform_iterator.hpp>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Triangulation_vertex_base_with_info_2.h>
#include <CGAL/mark_domain_in_triangulation.h>
#include <CGAL/unordered_flat_map.h>
#include <CGAL/Constrained_triangulation_2.h>
#include <CGAL/Constrained_triangulation_face_base_2.h>
#include <CGAL/Bbox_2.h>
#include <CGAL/Constrained_Delaunay_triangulation_2.h>
#include <CGAL/Draw_aos/Arr_render_context.h>
#include <CGAL/Draw_aos/type_utils.h>
#if defined(CGAL_DRAW_AOS_DEBUG) && defined(CGAL_DRAW_AOS_TRIANGULATOR_DEBUG_FILE_DIR)
#include <fstream>
#include <filesystem>
template <typename Arrangement>
class Arr_bounded_face_triangulator;
template <typename Arrangement>
void debug_print(const Arr_bounded_face_triangulator<Arrangement>& triangulator);
#endif
namespace CGAL {
namespace draw_aos {
/**
* @brief Triangulator for a face of an arrangement within a bounding box.
*/
template <typename Arrangement>
class Arr_bounded_face_triangulator {
using Geom_traits = typename Arrangement::Geometry_traits_2;
constexpr static bool Is_on_curved_surface = is_or_derived_from_curved_surf_traits_v<Geom_traits>;
using Approx_traits = Arr_approximate_traits<Geom_traits>;
using Point = typename Approx_traits::Point;
using Approx_point = typename Approx_traits::Approx_point;
using Approx_kernel = typename Approx_traits::Approx_kernel;
using Triangle_soup = typename Approx_traits::Triangle_soup;
using Triangle = typename Triangle_soup::Triangle;
using Face_const_handle = typename Arrangement::Face_const_handle;
#if defined(CGAL_DRAW_AOS_DEBUG)
template <typename T>
friend void debug_print(const Arr_bounded_face_triangulator<T>& triangulator);
#endif
enum Point_type { Vertex_only, Constraint_only, Vertex_and_constraint };
/*! \brief A index wrapper defaulted to invalid.
*/
class Index {
public:
Index() = default;
Index(int idx) : m_index(idx) {}
bool is_valid() const { return m_index != Invalid_index; }
operator int() const { return m_index; }
private:
constexpr static int Invalid_index = -1;
int m_index{Invalid_index};
};
using Epick = Exact_predicates_inexact_constructions_kernel;
using Vb = Triangulation_vertex_base_with_info_2<Index, Epick>;
using Fb = Constrained_triangulation_face_base_2<Epick>;
using Tds = Triangulation_data_structure_2<Vb, Fb>;
// For planar arrangements, Constrained_triangulation_2 is enough.
using Ct = std::conditional_t<Is_on_curved_surface,
Constrained_Delaunay_triangulation_2<Epick, Tds, Exact_predicates_tag>,
Constrained_triangulation_2<Epick, Tds, Exact_predicates_tag>>;
using KPoint = Epick::Point_2;
using KPoint_with_index = std::pair<KPoint, Index>;
using Bounded_render_context = Arr_bounded_render_context<Arrangement>;
public:
using value_type = Point;
private:
static KPoint to_kpoint(Point pt) { return KPoint(pt.x(), pt.y()); }
/*! \brief Offset a point on a specific boundary outward by a given offset.
*
* \pre side != Boundary_side::None
*/
static Point offset_boundary_point(Point pt, Boundary_side side, double offset) {
CGAL_precondition(side != Boundary_side::None);
switch(side) {
case Boundary_side::Left: return Point(pt.x() - offset, pt.y());
case Boundary_side::Right: return Point(pt.x() + offset, pt.y());
case Boundary_side::Top: return Point(pt.x(), pt.y() + offset);
case Boundary_side::Bottom: return Point(pt.x(), pt.y() - offset);
default: return pt; // Should not reach here
}
}
/*! \brief Find the shared boundary side of two points, or None if they are not on the same boundary.
*/
Boundary_side shared_boundary(const Point& pt1, const Point& pt2) const {
if (m_ctx.is_on_left(pt1) && m_ctx.is_on_left(pt2)) return Boundary_side::Left;
if (m_ctx.is_on_right(pt1) && m_ctx.is_on_right(pt2)) return Boundary_side::Right;
if (m_ctx.is_on_bottom(pt1) && m_ctx.is_on_bottom(pt2)) return Boundary_side::Bottom;
if (m_ctx.is_on_top(pt1) && m_ctx.is_on_top(pt2)) return Boundary_side::Top;
return Boundary_side::None;
}
/*! \brief Add a helper point on the shared boundary of two points if they are on the same boundary side.
*
* When triangulating a arrangement face within a bounding box, curves outside the bounding box are projected on the
* four sides of the bbox. Topological errors could be introduced if several segments are lying on the same side.
* Thus we add the midpoint in between the two points on boundary and move it outward with an increasing offset.
*/
void add_boundary_helper_point(Point from, Point to) {
// Arrangements on curved surfaces currently draws the entire parameter space, so there's no need to add
// helper points.
if constexpr(Is_on_curved_surface) return;
if (from == to) return;
auto shared_side = shared_boundary(from, to);
if (shared_side == Boundary_side::None) return;
Point mid = CGAL::midpoint(from, to);
m_points.push_back(offset_boundary_point(mid, shared_side, m_offset += 0.1));
m_point_types.push_back(Constraint_only);
}
void insert_all_vertices() {
auto vertex_filter = [this](int idx) { return m_point_types[idx] != Constraint_only; };
auto index_to_point_with_info = [this](int idx) -> KPoint_with_index {
return std::make_pair(to_kpoint(m_points[idx]), idx);
};
auto indexes_begin = boost::make_counting_iterator<int>(0);
auto indexes_end = boost::make_counting_iterator<int>(m_points.size());
auto filtered_begin = boost::make_filter_iterator(vertex_filter, indexes_begin, indexes_end);
auto filtered_end = boost::make_filter_iterator(vertex_filter, indexes_end, indexes_end);
auto transformed_begin = boost::make_transform_iterator(filtered_begin, index_to_point_with_info);
auto transformed_end = boost::make_transform_iterator(filtered_end, index_to_point_with_info);
// Constrained_triangulation_2 and Constrained_Delaunay_triangulation_2 have slightly different interfaces.
if constexpr(Is_on_curved_surface)
m_ct.insert(transformed_begin, transformed_end);
else
m_ct.template insert_with_info<KPoint_with_index>(transformed_begin, transformed_end);
}
void insert_all_constraints() {
auto constraint_filter = [this](int idx) { return m_point_types[idx] != Vertex_only; };
auto index_to_point = [this](int idx) -> KPoint { return to_kpoint(m_points[idx]); };
for (auto [start_idx, end_idx] : m_cst_ranges) {
auto indexes_begin = boost::make_counting_iterator<int>(start_idx);
auto indexes_end = boost::make_counting_iterator<int>(end_idx);
auto filtered_begin = boost::make_filter_iterator(constraint_filter, indexes_begin, indexes_end);
auto filtered_end = boost::make_filter_iterator(constraint_filter, indexes_end, indexes_end);
auto transformed_begin = boost::make_transform_iterator(filtered_begin, index_to_point);
auto transformed_end = boost::make_transform_iterator(filtered_end, index_to_point);
m_ct.insert_constraint(transformed_begin, transformed_end, true);
}
}
public:
Arr_bounded_face_triangulator(const Bounded_render_context& ctx, Face_const_handle fh) :
m_ctx(ctx),
m_fh(fh)
{}
void push_back(Point pt) {
CGAL_assertion_msg(m_curr_cst_begin.has_value(), "Call start_constraint() before push_back().");
if (m_points.size() - *m_curr_cst_begin >= 1) add_boundary_helper_point(m_points.back(), pt);
m_points.push_back(pt);
m_point_types.push_back(Vertex_and_constraint);
}
void start_constraint() { m_curr_cst_begin = m_points.size(); }
void end_constraint() {
CGAL_assertion_msg(m_curr_cst_begin.has_value(), "Call start_constraint() before end_constraint().");
int cst_begin = *m_curr_cst_begin;
m_curr_cst_begin.reset();
if (m_points.size() - cst_begin <= 2) {
m_points.erase(m_points.begin() + cst_begin, m_points.end());
m_point_types.erase(m_point_types.begin() + cst_begin, m_point_types.end());
return;
}
add_boundary_helper_point(m_points.back(), m_points[cst_begin]);
m_cst_ranges.emplace_back(cst_begin, m_points.size());
}
/*! \brief Converts the triangulator to a triangulated face, moving internal data to the result.
*
* \return Triangulated_face
*/
operator Triangle_soup() && {
CGAL_assertion_msg(!m_curr_cst_begin.has_value(), "Call end_constraint() before conversion");
if (m_points.empty()) return Triangle_soup();
if constexpr(Is_on_curved_surface) {
if (auto it = m_ctx.m_face_points.find(m_fh); it != m_ctx.m_face_points.end()) {
m_points.insert(m_points.end(), it->second.begin(), it->second.end());
m_point_types.insert(m_point_types.end(), it->second.size(), Vertex_only);
}
}
insert_all_vertices();
insert_all_constraints();
if (m_ct.number_of_faces() == 0) return Triangle_soup();
#if defined(CGAL_DRAW_AOS_DEBUG)
debug_print(*this);
#endif
unordered_flat_map<typename Ct::Face_handle, bool> in_domain_map;
in_domain_map.reserve(m_ct.number_of_faces());
boost::associative_property_map<decltype(in_domain_map)> in_domain(in_domain_map);
CGAL::mark_domain_in_triangulation(m_ct, in_domain);
// Collect triangles within the constrained domain.
Triangle_soup ts;
ts.triangles.reserve(m_ct.number_of_faces());
for (auto fit = m_ct.finite_faces_begin(); fit != m_ct.finite_faces_end(); ++fit) {
Index v1 = fit->vertex(0)->info();
Index v2 = fit->vertex(1)->info();
Index v3 = fit->vertex(2)->info();
if (! v1.is_valid() || !v2.is_valid() || !v3.is_valid()) continue;
if (! get(in_domain, fit)) continue;
ts.triangles.push_back(Triangle{v1, v2, v3});
}
ts.points = std::move(m_points);
return ts;
}
private:
const Bounded_render_context& m_ctx;
Face_const_handle m_fh;
Ct m_ct;
std::vector<Point> m_points;
std::vector<Point_type> m_point_types;
std::vector<std::pair<int, int>> m_cst_ranges;
std::optional<int> m_curr_cst_begin;
double m_offset{0};
};
#if defined(CGAL_DRAW_AOS_DEBUG) && defined(CGAL_DRAW_AOS_TRIANGULATOR_DEBUG_FILE_DIR)
template <typename Arrangement>
void debug_print(const Arr_bounded_face_triangulator<Arrangement>& triangulator) {
const auto& ctx = triangulator.m_ctx;
const auto& m_points = triangulator.m_points;
const auto& m_point_types = triangulator.m_point_types;
using Point_type = typename Arr_bounded_face_triangulator<Arrangement>::Point_type;
using Path = std::filesystem::path;
Path debug_dir(CGAL_DRAW_AOS_TRIANGULATOR_DEBUG_FILE_DIR);
std::string index_file_name = "index.txt";
Path index_file_path = debug_dir / index_file_name;
std::string points_file_name_prefix = "face_" + std::to_string(*ctx.debug_counter) + "_points";
std::string ccb_constraint_file_name_prefix = "face_" + std::to_string(*ctx.debug_counter) + "_constraint";
const_cast<int&>(*ctx.debug_counter)++;
std::ofstream ofs_index(index_file_path, std::ios::app);
auto points_filename = points_file_name_prefix + ".txt";
auto points_path = debug_dir / points_filename;
std::ofstream ofs_points(points_path);
ofs_index << points_filename << std::endl;
for (int i = 0; i < triangulator.m_points.size(); ++i) {
if (m_point_types[i] == Point_type::Constraint_only) continue;
const auto& pt = m_points[i];
ofs_points << pt.x() << " " << pt.y() << "\n";
}
int counter = 0;
for (auto [start_idx, end_idx] : triangulator.m_cst_ranges) {
auto filename = ccb_constraint_file_name_prefix + "_" + std::to_string(counter++) + ".txt";
auto filepath = debug_dir / filename;
ofs_index << filename << std::endl;
std::ofstream ofs_ccb_constraint(filepath);
for (int i = start_idx; i < end_idx; ++i) {
if (m_point_types[i] == Point_type::Vertex_only) continue;
const auto& pt = m_points[i];
ofs_ccb_constraint << pt.x() << " " << pt.y() << "\n";
}
}
}
#endif
} // namespace draw_aos
} // namespace CGAL
#endif

View File

@ -0,0 +1,67 @@
// Copyright (c) 2025
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and 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): Shepard Liu <shepard0liu@gmail.com>
#ifndef CGAL_DRAW_AOS_ARR_BOUNDED_RENDERER_H
#define CGAL_DRAW_AOS_ARR_BOUNDED_RENDERER_H
#include <CGAL/license/Arrangement_on_surface_2.h>
#include <CGAL/Bbox_2.h>
#include <CGAL/Draw_aos/Arr_approximation_cache.h>
#include <CGAL/Draw_aos/Arr_bounded_approximate_face.h>
#include <CGAL/Draw_aos/Arr_render_context.h>
#include <CGAL/Draw_aos/type_utils.h>
namespace CGAL {
namespace draw_aos {
/** @brief Render arrangement on surface within a bounding box.
*/
template <typename Arrangement>
class Arr_bounded_renderer {
using Geom_traits = typename Arrangement::Geometry_traits_2;
using Face_const_handle = typename Arrangement::Face_const_handle;
using Render_context = Arr_render_context<Arrangement>;
using Approx_cache = Arr_approximation_cache<Arrangement>;
public:
Arr_bounded_renderer(const Render_context& ctx, Bbox_2 bbox) :
m_ctx(ctx),
m_bbox(bbox)
{}
Approx_cache render() const {
Approx_cache cache;
if(m_ctx.is_cancelled()) return cache;
cache.vertices().reserve(m_ctx.m_arr.number_of_vertices());
cache.halfedges().reserve(m_ctx.m_arr.number_of_halfedges());
cache.faces().reserve(m_ctx.m_arr.number_of_faces());
Arr_bounded_render_context<Arrangement> derived_ctx(m_ctx, m_bbox, cache);
Arr_bounded_approximate_face<Arrangement> bounded_approx_face(derived_ctx);
for(Face_const_handle fh = m_ctx.m_arr.faces_begin(); fh != m_ctx.m_arr.faces_end(); ++fh) bounded_approx_face(fh);
return cache;
}
private:
const Render_context& m_ctx;
const Bbox_2 m_bbox;
};
} // namespace draw_aos
} // namespace CGAL
#endif

View File

@ -0,0 +1,112 @@
// Copyright (c) 2025
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and 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): Shepard Liu <shepard0liu@gmail.com>
#ifndef CGAL_DRAW_AOS_ARR_COORDINATE_CONVERTER_H
#define CGAL_DRAW_AOS_ARR_COORDINATE_CONVERTER_H
#include <CGAL/license/Arrangement_on_surface_2.h>
#include <cmath>
#include <CGAL/number_type_config.h>
#include <CGAL/Arr_geodesic_arc_on_sphere_traits_2.h>
#include <CGAL/Draw_aos/type_utils.h>
namespace CGAL {
namespace draw_aos {
/*! \brief class handling coordinate conversion between 2D parameterized surface coordinates and cartesian coordinates.
*
* \tparam GeomTraits
*/
template <typename GeomTraits>
class Arr_coordinate_converter {
using Geom_traits = GeomTraits;
using Approx_traits = Arr_approximate_traits<Geom_traits>;
using Approx_point = typename Approx_traits::Approx_point;
using Point = typename Approx_traits::Point;
public:
Arr_coordinate_converter(const GeomTraits& traits) : m_traits(traits) {}
/*! \brief converts a point in cartesian coordinates to parameterized surface coordinates.
*
* \param pt
* \return Point
*/
Point to_uv(Approx_point pt) const { return pt; }
/*! \brief Converts a point in parameterized surface coordinates to cartesian coordinates.
*
* \param pt
* \return Approx_point
*/
Approx_point to_cartesian(Point pt) const { return pt; }
private:
const GeomTraits& m_traits;
};
/*! \brief Converter specialization for geodesic arc on sphere traits.
*
* provides conversions between spherical coordinates and right-handed Cartesian coordinates. Sphercial coordinates are
* represented as azimuth ( [0, 2 Pi) ) and polar ( [0, Pi] ) angle in radians. Points on the identification curve have
* azimuth == 0. The south pole has polar == 0.
*
* \tparam Kernel
* \tparam atanX
* \tparam atanY
*/
template <typename Kernel, int atanX, int atanY>
class Arr_coordinate_converter<Arr_geodesic_arc_on_sphere_traits_2<Kernel, atanX, atanY>> {
using Geom_traits = Arr_geodesic_arc_on_sphere_traits_2<Kernel>;
using Approx_traits = Arr_approximate_traits<Geom_traits>;
using Approx_point = typename Approx_traits::Approx_point;
using Approx_nt = typename Approx_traits::Approx_nt;
using Point = typename Approx_traits::Point;
public:
Arr_coordinate_converter(const Geom_traits& traits) : m_traits(traits) {}
Point to_uv(Approx_point point) const {
if(point.location() == Approx_point::MAX_BOUNDARY_LOC) return Point(0, CGAL_PI);
if(point.location() == Approx_point::MIN_BOUNDARY_LOC) return Point(0, 0);
Approx_nt azimuth_from_id =
std::fmod(std::atan2(point.dy(), point.dx()) - std::atan2(atanY, atanX) + 2 * CGAL_PI, 2 * CGAL_PI);
return Point(azimuth_from_id, std::acos(-point.dz()));
}
Approx_point to_cartesian(Point point) const {
using Direction_3 = typename Geom_traits::Approximate_kernel::Direction_3;
Approx_nt polar = point.y();
if(point.y() == CGAL_PI) return Approx_point(Direction_3(0, 0, 1), Approx_point::MAX_BOUNDARY_LOC);
if(point.y() == 0) return Approx_point(Direction_3(0, 0, -1), Approx_point::MIN_BOUNDARY_LOC);
Approx_nt azimuth = point.x() + std::atan2(atanY, atanX);
Approx_nt x = std::sin(polar) * std::cos(azimuth);
Approx_nt y = std::sin(polar) * std::sin(azimuth);
Approx_nt z = -std::cos(polar);
Direction_3 dir(x, y, z);
return Approx_point(dir, azimuth == 0 ? Approx_point::MID_BOUNDARY_LOC : Approx_point::NO_BOUNDARY_LOC);
}
private:
const Geom_traits& m_traits;
};
} // namespace draw_aos
} // namespace CGAL
#endif

View File

@ -0,0 +1,101 @@
// Copyright (c) 2025
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and 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): Shepard Liu <shepard0liu@gmail.com>
#ifndef CGAL_DRAW_AOS_ARR_FACE_POINT_GENERATOR_H
#define CGAL_DRAW_AOS_ARR_FACE_POINT_GENERATOR_H
#include <CGAL/license/Arrangement_on_surface_2.h>
#include <utility>
#include <variant>
#include <vector>
#include <boost/iterator/function_output_iterator.hpp>
#include "CGAL/unordered_flat_map.h"
#include "CGAL/Arr_batched_point_location.h"
#include "CGAL/Arr_point_location_result.h"
#include "CGAL/Draw_aos/Arr_coordinate_converter.h"
#include "CGAL/Draw_aos/type_utils.h"
namespace CGAL {
namespace draw_aos {
/*! \brief Generate face interior points.
*
* \tparam Arrangement
*/
template <typename Arrangement, typename = void>
class Arr_face_point_generator;
template <typename Arrangement>
class Arr_face_point_generator<Arrangement,
std::enable_if_t<!is_or_derived_from_curved_surf_traits_v
<typename Arrangement::Geometry_traits_2>>> {
using Point_geom = typename Arr_approximate_traits<typename Arrangement::Geometry_traits_2>::Point;
using Face_const_handle = typename Arrangement::Face_const_handle;
public:
using Face_points_map = unordered_flat_map<Face_const_handle, std::vector<Point_geom>>;
// No-op implementation for non-curved surface arrangements.
Face_points_map operator()(const Arrangement&, double) { return {}; }
};
template <typename Arrangement>
class Arr_face_point_generator<Arrangement,
std::enable_if_t<is_or_derived_from_agas_v<typename Arrangement::Geometry_traits_2>>> {
using Geom_traits = typename Arrangement::Geometry_traits_2;
using Approx_traits = Arr_approximate_traits<Geom_traits>;
using Approx_nt = typename Approx_traits::Approx_nt;
using Point = typename Approx_traits::Point;
using Face_const_handle = typename Arrangement::Face_const_handle;
using Gt_point = typename Geom_traits::Point_2;
using Query_result = std::pair<Gt_point, typename Arr_point_location_result<Arrangement>::Type>;
public:
using Face_points_map = unordered_flat_map<Face_const_handle, std::vector<Point>>;
Face_points_map operator()(const Arrangement& arr, double error) {
const Geom_traits& traits = *arr.geometry_traits();
// Grid sampling in parameter space.
Approx_nt cell_size = 2.0 * std::acos(1 - error);
std::vector<Gt_point> points;
Arr_coordinate_converter<Geom_traits> coords(traits);
points.reserve(2 * CGAL_PI / cell_size * CGAL_PI / cell_size);
for (Approx_nt x = 0; x < 2 * CGAL_PI; x += cell_size) {
for (Approx_nt y = 0; y < CGAL_PI; y += cell_size) {
auto pt = coords.to_cartesian(Point(x, y));
points.push_back(traits.construct_point_2_object()(pt.dx(), pt.dy(), pt.dz()));
}
}
unordered_flat_map<Face_const_handle, std::vector<Point>> face_points;
CGAL::locate(arr, points.begin(), points.end(),
boost::make_function_output_iterator([&face_points, &traits, &coords](const Query_result& res) {
if (! std::holds_alternative<Face_const_handle>(res.second)) return;
Face_const_handle fh = std::get<Face_const_handle>(res.second);
auto [it, _] = face_points.try_emplace(fh, std::vector<Point>());
it->second.push_back(coords.to_uv(traits.approximate_2_object()(res.first)));
}));
return face_points;
}
};
} // namespace draw_aos
} // namespace CGAL
#endif

View File

@ -0,0 +1,178 @@
// Copyright (c) 2025
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and 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): Shepard Li <shepard0liu@gmail.com>
#ifndef CGAL_DRAW_AOS_ARR_RENDER_CONTEXT_H
#define CGAL_DRAW_AOS_ARR_RENDER_CONTEXT_H
#include <CGAL/license/Arrangement_on_surface_2.h>
#include <cstdlib>
#include <memory>
#include <atomic>
#include <chrono>
#include <CGAL/Bbox_2.h>
#include <CGAL/Arr_point_location_result.h>
#include <CGAL/Arr_trapezoid_ric_point_location.h>
#include <CGAL/Arrangement_2.h>
#include <CGAL/Draw_aos/Arr_approximation_cache.h>
#include <CGAL/Draw_aos/type_utils.h>
#include <CGAL/Draw_aos/Arr_face_point_generator.h>
#include <CGAL/Draw_aos/Arr_coordinate_converter.h>
#if defined(CGAL_DRAW_AOS_DEBUG)
#include <fstream>
#endif
namespace CGAL {
namespace draw_aos {
/** @brief A cancellable context mixin for asynchronous operations. It also tracks elapsed time for performance
* profiling.
*
* The idea is borrowed from golang with a simple implementation.
* @see https://pkg.go.dev/context
*/
class Arr_cancellable_context_mixin {
using Clock = std::chrono::steady_clock;
using Duration = Clock::duration;
using Time_point = std::chrono::time_point<Clock, Duration>;
protected:
Arr_cancellable_context_mixin() :
m_start_time(Clock::now()),
m_cancelled(std::make_shared<std::atomic<bool>>(false))
{}
public:
Time_point start_time() const { return m_start_time; }
Time_point end_time() const { return m_end_time; }
Duration elapsed_time() const { return Clock::now() - m_start_time; }
bool is_cancelled() const { return m_cancelled->load(); }
void cancel() {
m_cancelled->store(true, std::memory_order_relaxed);
m_end_time = Clock::now();
}
private:
Time_point m_start_time, m_end_time;
std::shared_ptr<std::atomic<bool>> m_cancelled;
};
/** @brief Boundary context mixin for rendering arrangements within a bounding box.
* Provides extended functionality for checking point-bbox relations.
*
* @tparam GeomTraits the geometry traits class.
*/
template <typename GeomTraits>
class Arr_bounds_context_mixin {
using Geom_traits = GeomTraits;
using Approx_traits = Arr_approximate_traits<Geom_traits>;
using Point = typename Approx_traits::Point;
using Approx_nt = typename Approx_traits::Approx_nt;
protected:
Arr_bounds_context_mixin(const Bbox_2& bbox) : m_bbox(bbox) {}
public:
double xmin() const { return m_bbox.xmin(); }
double xmax() const { return m_bbox.xmax(); }
double ymin() const { return m_bbox.ymin(); }
double ymax() const { return m_bbox.ymax(); }
const Bbox_2& bbox() const { return m_bbox; }
bool contains_x(Approx_nt x) const { return xmin() <= x && x <= xmax(); }
bool contains_y(Approx_nt y) const { return ymin() <= y && y <= ymax(); }
bool contains(Point pt) const { return contains_x(pt.x()) && contains_y(pt.y()); }
Point top_left() const { return Point(xmin(), ymax()); }
Point top_right() const { return Point(xmax(), ymax()); }
Point bottom_left() const { return Point(xmin(), ymin()); }
Point bottom_right() const { return Point(xmax(), ymin()); }
bool is_on_left(Point pt) const { return pt.x() == xmin() && contains_y(pt.y()); }
bool is_on_right(Point pt) const { return pt.x() == xmax() && contains_y(pt.y()); }
bool is_on_bottom(Point pt) const { return pt.y() == ymin() && contains_x(pt.x()); }
bool is_on_top(Point pt) const { return pt.y() == ymax() && contains_x(pt.x()); }
bool is_on_boundary(Point pt) const { return is_on_left(pt) || is_on_right(pt) || is_on_bottom(pt) || is_on_top(pt); }
private:
const Bbox_2 m_bbox;
};
template <typename GeomTraits>
using Arr_parameterization_context_mixin = Arr_coordinate_converter<GeomTraits>;
template <typename Arrangement>
class Arr_render_context :
public Arr_cancellable_context_mixin,
public Arr_parameterization_context_mixin<typename Arrangement::Geometry_traits_2> {
using Cancellable_context_mixin = Arr_cancellable_context_mixin;
using Param_context_mixin = Arr_parameterization_context_mixin<typename Arrangement::Geometry_traits_2>;
using Geom_traits = typename Arrangement::Geometry_traits_2;
using Face_points_map = typename Arr_face_point_generator<Arrangement>::Face_points_map;
public:
Arr_render_context(const Arrangement& arr, double approx_error, Face_points_map& face_points) :
Cancellable_context_mixin(),
Param_context_mixin(*arr.geometry_traits()),
m_arr(arr),
m_traits(*arr.geometry_traits()),
m_approx_error(approx_error),
m_face_points(face_points) {
#if defined(CGAL_DRAW_AOS_DEBUG) && defined(CGAL_DRAW_AOS_TRIANGULATOR_DEBUG_FILE_DIR)
std::filesystem::path debug_file_dir(CGAL_DRAW_AOS_TRIANGULATOR_DEBUG_FILE_DIR);
// clear the index file.
std::filesystem::remove(debug_file_dir / "index.txt");
#endif
}
public:
const Arrangement& m_arr;
const Geom_traits& m_traits;
const double m_approx_error;
const Face_points_map& m_face_points;
#if defined(CGAL_DRAW_AOS_DEBUG)
std::shared_ptr<int> debug_counter = std::make_shared<int>(0);
#endif
};
template <typename Arrangement>
class Arr_bounded_render_context :
public Arr_render_context<Arrangement>,
public Arr_bounds_context_mixin<typename Arrangement::Geometry_traits_2> {
using Geom_traits = typename Arrangement::Geometry_traits_2;
using Approx_point = typename Geom_traits::Approximate_point_2;
using Render_context = Arr_render_context<Arrangement>;
using Bounds_context_mixin = Arr_bounds_context_mixin<Geom_traits>;
using Approx_cache = Arr_approximation_cache<Arrangement>;
public:
Arr_bounded_render_context(const Render_context& ctx, const Bbox_2& bbox, Approx_cache& cache) :
Render_context(ctx),
Bounds_context_mixin(bbox),
m_cache(cache)
{}
public:
Approx_cache& m_cache;
};
} // namespace draw_aos
} // namespace CGAL
#endif

View File

@ -0,0 +1,358 @@
// Copyright (c) 2025
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and 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): Shepard Liu <shepard0liu@gmail.com>
#ifndef ARR_VIEWER_H
#define ARR_VIEWER_H
#include <algorithm>
#include <array>
#include <cstdlib>
#include <type_traits>
#include <QWidget>
#include <CGAL/Qt/Basic_viewer.h>
#include <CGAL/Qt/camera.h>
#include <CGAL/IO/Color.h>
#include <CGAL/Basic_viewer.h>
#include <CGAL/Bbox_2.h>
#include <CGAL/Graphics_scene.h>
#include <CGAL/Qt/camera.h>
#include <CGAL/Graphics_scene.h>
#include <CGAL/Graphics_scene_options.h>
#include <CGAL/Buffer_for_vao.h>
#include <CGAL/Arr_enums.h>
#include <CGAL/Draw_aos/type_utils.h>
#include <CGAL/Draw_aos/Arr_render_context.h>
#include <CGAL/Draw_aos/Arr_bounded_renderer.h>
#include <CGAL/Draw_aos/Arr_coordinate_converter.h>
#include <CGAL/Draw_aos/Arr_face_point_generator.h>
namespace CGAL {
namespace draw_aos {
/*! \brief Viewport helper functions
*
* \tparam Arrangement
*/
template <typename Arrangement, typename = void>
class Arr_viewport_helpers;
// Specialization for planar arrangements
template <typename Arrangement>
class Arr_viewport_helpers<Arrangement,
std::enable_if_t<! is_or_derived_from_curved_surf_traits_v
<typename Arrangement::Geometry_traits_2>>> {
using Geom_traits = typename Arrangement::Geometry_traits_2;
using Approx_traits = Arr_approximate_traits<Geom_traits>;
using Approx_point = typename Approx_traits::Approx_point;
using Camera = qglviewer::Camera;
using Point = typename Approx_traits::Point;
using Local_point = Buffer_for_vao::Local_point;
protected:
Arr_viewport_helpers(const Arrangement& arr) : m_arr(arr) {}
/*! \brief Computes a subpixel-level approximation error based on the bounding box and viewport width.
*
* \param bbox
* \param viewport_width width of the viewport in pixels
* \return double
*/
double approximation_error(const Bbox_2& bbox, int viewport_width) const
{ return bbox.x_span() / viewport_width; }
/*! \brief Computes a parameter space bounding box that contains everything in the arrangement with some margin.
*
* \note For arrangement induced by unbounded curves, the bounding box only fits all vertices.
* \return Bbox_2
*/
Bbox_2 arr_bbox() const {
const auto& traits = *m_arr.geometry_traits();
Bbox_2 bbox;
// Computes a rough bounding box from the vertices.
for (const auto& vh : m_arr.vertex_handles())
bbox += traits.approximate_2_object()(vh->point()).bbox();
double approx_error = approximation_error(bbox, 100);
// Computes a more precise bounding box from the halfedges.
auto approx = traits.approximate_2_object();
for (const auto& he : m_arr.halfedge_handles()) {
approx(he->curve(), approx_error,
boost::make_function_output_iterator([&bbox](Approx_point pt) { bbox += pt.bbox(); }));
}
// Place margin around the bbox.
double dx = bbox.x_span() * 0.1;
double dy = bbox.y_span() * 0.1;
bbox = Bbox_2(bbox.xmin() - dx, bbox.ymin() - dy, bbox.xmax() + dx, bbox.ymax() + dy);
// Make sure the bbox is not degenerate.
if (bbox.x_span() == 0) bbox += Bbox_2(bbox.xmin() - 1, bbox.ymin(), bbox.xmax() + 1, bbox.ymax());
if (bbox.y_span() == 0) bbox += Bbox_2(bbox.xmin(), bbox.ymin() - 1, bbox.xmax(), bbox.ymax() + 1);
return bbox;
}
/*! \brief Fits the camera to bbox.
*
* \param bbox
* \param camera
*/
void fit_camera(const Bbox_2& bbox, Camera& cam) const {
using Vec = qglviewer::Vec;
cam.fitBoundingBox(Vec(bbox.xmin(), bbox.ymin(), 0.0), Vec(bbox.xmax(), bbox.ymax(), 0.0));
}
/*! \brief Computes parameter space axis aligned bounding box from camera parameters.
*
* \param cam
* \return Bbox_2
*/
Bbox_2 screen_to_world(const Camera& cam) const {
QMatrix4x4 mvp;
cam.getModelViewProjectionMatrix(mvp.data());
QMatrix4x4 inverse_mvp = mvp.inverted();
// Define 4 corners of the near plane in NDC (-1 to 1 in x and y)
std::array<QVector4D, 4> clip_space_corners{QVector4D(-1.0, -1.0, 0.0, 1.0), QVector4D(-1.0, 1.0, 0.0, 1.0),
QVector4D(1.0, -1.0, 0.0, 1.0), QVector4D(1.0, 1.0, 0.0, 1.0)};
double xmin = std::numeric_limits<double>::max();
double xmax = std::numeric_limits<double>::lowest();
double ymin = std::numeric_limits<double>::max();
double ymax = std::numeric_limits<double>::lowest();
for (const QVector4D& corner : clip_space_corners) {
QVector4D world = inverse_mvp * corner;
if (world.w() != 0.0) world /= world.w();
double x = world.x();
double y = world.y();
xmin = std::min(xmin, x);
xmax = std::max(xmax, x);
ymin = std::min(ymin, y);
ymax = std::max(ymax, y);
}
return Bbox_2(xmin, ymin, xmax, ymax);
}
/*! \brief Converts a parameter space point to a local point of the buffer object.
*
* \param pt
* \return Local_point
*/
Local_point to_local_point(Point pt) const { return Local_point(pt.x(), pt.y(), 0.0); }
private:
const Arrangement& m_arr;
};
// Spherical arrangement specialization
template <typename Arrangement>
class Arr_viewport_helpers<Arrangement,
std::enable_if_t<is_or_derived_from_agas_v<typename Arrangement::Geometry_traits_2>>> {
using Geom_traits = typename Arrangement::Geometry_traits_2;
using Approx_traits = Arr_approximate_traits<Geom_traits>;
using Approx_point = typename Approx_traits::Approx_point;
using Camera = qglviewer::Camera;
using Point = typename Approx_traits::Point;
using Local_point = Buffer_for_vao::Local_point;
protected:
Arr_viewport_helpers(const Arrangement& arr) : m_arr(arr) {}
Bbox_2 arr_bbox() const { return Bbox_2(0, 0, 2 * CGAL_PI, CGAL_PI); }
Bbox_2 screen_to_world(const Camera& /* cam */) const { return Bbox_2(0, 0, 2 * CGAL_PI, CGAL_PI); }
void fit_camera(const Bbox_2&, Camera& cam) {
using Vec = qglviewer::Vec;
cam.setSceneCenter(Vec(0, 0, 0));
cam.fitSphere(Vec(0, 0, 0), 1.1); // slightly larger than the unit sphere
}
double approximation_error(const Bbox_2& bbox, int viewport_width) const {
// If crossing hemisphere
if (bbox.x_span() >= CGAL_PI) return 1.0 / viewport_width;
// Otherwise we evaluate the error bound with respect to the longest longitude arc
double theta =
std::abs(bbox.ymin() - CGAL_PI / 2.0) < std::abs(bbox.ymax() - CGAL_PI / 2.0) ? bbox.ymin() : bbox.ymax();
return bbox.x_span() * std::sin(theta) / viewport_width;
}
Buffer_for_vao::Local_point to_local_point(Point pt) const {
auto approx_pt = Arr_coordinate_converter<Geom_traits>(*m_arr.geometry_traits()).to_cartesian(pt);
return Buffer_for_vao::Local_point(approx_pt.dx(), approx_pt.dy(), approx_pt.dz());
}
private:
const Arrangement& m_arr;
};
/*! Viewer for visualizing arrangements on surface.
*
* \tparam Arrangement
* \tparam GSOptions
*/
template <typename Arrangement, typename GSOptions>
class Arr_viewer : public Qt::Basic_viewer, Arr_viewport_helpers<Arrangement> {
using Basic_viewer = Qt::Basic_viewer;
using Helpers = Arr_viewport_helpers<Arrangement>;
using Vertex_const_handle = typename Arrangement::Vertex_const_handle;
using Halfedge_const_handle = typename Arrangement::Halfedge_const_handle;
using Face_const_handle = typename Arrangement::Face_const_handle;
using Geom_traits = typename Arrangement::Geometry_traits_2;
using Approx_traits = Arr_approximate_traits<Geom_traits>;
using Approx_point = typename Approx_traits::Approx_point;
using Point = typename Approx_traits::Point;
using Point_generator = Arr_face_point_generator<Arrangement>;
using Faces_point_map = typename Point_generator::Face_points_map;
struct Render_params {
bool operator==(const Render_params& other) const
{ return bbox == other.bbox && approx_error == other.approx_error; }
Bbox_2 bbox;
double approx_error{0};
};
constexpr static bool Is_on_curved_surface = is_or_derived_from_curved_surf_traits_v<Geom_traits>;
private:
static bool contains(const Bbox_2& bbox, const Point& pt)
{ return bbox.xmin() <= pt.x() && pt.x() <= bbox.xmax() && bbox.ymin() <= pt.y() && pt.y() <= bbox.ymax(); }
int viewport_width() const {
std::array<GLint, 4> viewport;
this->camera_->getViewport(viewport.data());
return viewport[2];
}
Render_params compute_render_params() {
Render_params params;
params.bbox = this->screen_to_world(*this->camera_);
params.approx_error = this->approximation_error(params.bbox, viewport_width());
return params;
}
void render_arr(const Render_params& params) {
const Bbox_2& bbox = params.bbox;
auto face_points = Point_generator()(m_arr, params.approx_error);
Arr_render_context<Arrangement> ctx(m_arr, params.approx_error, face_points);
Arr_bounded_renderer<Arrangement> renderer(ctx, bbox);
auto cache = renderer.render();
// add faces
for (const auto& [fh, tf] : cache.faces()) {
if (! m_gso.draw_face(m_arr, fh)) continue;
bool colored_face = m_gso.colored_face(m_arr, fh);
auto color = colored_face ? m_gso.face_color(m_arr, fh) : CGAL::IO::Color();
for (const auto& tri : tf.triangles) {
if (colored_face) m_gs.face_begin(color);
else m_gs.face_begin();
for (const auto i : tri) m_gs.add_point_in_face(this->to_local_point(tf.points[i]));
m_gs.face_end();
}
}
// add edges
for (const auto& [he, polyline] : cache.halfedges()) {
if (he->direction() == ARR_RIGHT_TO_LEFT || !m_gso.draw_edge(m_arr, he) || polyline.size() < 2) continue;
bool colored_edge = m_gso.colored_edge(m_arr, he);
auto color = colored_edge ? m_gso.edge_color(m_arr, he) : CGAL::IO::Color();
// skip first two if starts with a sep point.
int start_idx = Approx_traits::is_null(polyline.front()) ? 2 : 0;
// skip last two if ends with a sep point.
int end_idx = Approx_traits::is_null(polyline.back()) ? polyline.size() - 2 : polyline.size();
for (int i = start_idx; i < end_idx - 1; ++i) {
const auto& src = polyline[i];
const auto& tgt = polyline[i + 1];
if (Approx_traits::is_null(src) || Approx_traits::is_null(tgt)) continue;
if (! contains(bbox, src) || !contains(bbox, tgt)) continue;
if (colored_edge)
m_gs.add_segment(this->to_local_point(src), this->to_local_point(tgt), color);
else
m_gs.add_segment(this->to_local_point(src), this->to_local_point(tgt));
}
}
// add vertices
for (const auto& [vh, pt] : cache.vertices()) {
if (! m_gso.draw_vertex(m_arr, vh) || !contains(bbox, pt)) continue;
if (m_gso.colored_vertex(m_arr, vh))
m_gs.add_point(this->to_local_point(pt), m_gso.vertex_color(m_arr, vh));
else
m_gs.add_point(this->to_local_point(pt));
}
}
/*! \brief Rerender scene within the given bounding box.
*
* \param bbox
*/
void rerender(const Render_params& params) {
if (params == m_last_params) return;
m_last_params = params;
m_gs.clear();
render_arr(params);
Basic_viewer::redraw();
}
public:
Arr_viewer(QWidget* parent, const Arrangement& arr, const GSOptions& gso, const char* title, Bbox_2 initial_bbox) :
Basic_viewer(parent, m_gs, title),
Helpers(arr),
m_gso(gso),
m_arr(arr),
m_coords(*arr.geometry_traits()) {
if ((initial_bbox.x_span() == 0) || (initial_bbox.y_span() == 0) || (Is_on_curved_surface))
m_initial_bbox = this->arr_bbox();
else
m_initial_bbox = initial_bbox;
}
virtual void draw() override {
Render_params params = compute_render_params();
#if defined(CGAL_DRAW_AOS_DEBUG)
if constexpr(! is_or_derived_from_agas_v<Geom_traits>) {
Bbox_2& bbox = params.bbox;
double dx = (bbox.xmax() - bbox.xmin()) * 0.1;
double dy = (bbox.ymax() - bbox.ymin()) * 0.1;
bbox = Bbox_2(bbox.xmin() + dx, bbox.ymin() + dy, bbox.xmax() - dx, bbox.ymax() - dy);
std::cout << "Camera changed, recomputing arrangement bounding box: " << bbox << std::endl;
}
#endif
rerender(params);
if (! m_initialized) {
// The initial render must be done with original camera parameters or the width of edges gets exaggerated.
// So we fit the camera after initial render.
this->fit_camera(m_initial_bbox, *this->camera_);
m_initialized = true;
}
Basic_viewer::draw();
}
virtual ~Arr_viewer() {}
private:
Graphics_scene m_gs;
GSOptions m_gso;
const Arrangement& m_arr;
bool m_initialized{false};
Bbox_2 m_initial_bbox;
const Arr_coordinate_converter<Geom_traits> m_coords;
Render_params m_last_params;
};
} // namespace draw_aos
} // namespace CGAL
#endif

View File

@ -0,0 +1,223 @@
// Copyright (c) 2025
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and 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): Shepard Liu <shepard0liu@gmail.com>
#ifndef CGAL_DRAW_AOS_TYPE_UTILS_H
#define CGAL_DRAW_AOS_TYPE_UTILS_H
#include <CGAL/license/Arrangement_on_surface_2.h>
#include <limits>
#include <vector>
#include <type_traits>
#include <cmath>
#include <CGAL/Arr_geodesic_arc_on_sphere_traits_2.h>
namespace CGAL {
namespace draw_aos {
enum class Boundary_side {
Top = 0,
Left = 1,
Bottom = 2,
Right = 3,
None = -1,
};
template <typename, typename = std::void_t<>>
struct has_approximate_2_object : std::false_type {};
template <typename Gt>
struct has_approximate_2_object<Gt, std::void_t<decltype(std::declval<Gt>().approximate_2_object())>> : std::true_type
{};
// Detect whether Gt has defined a member function approximate_2_object()
template <typename Gt>
inline constexpr bool has_approximate_2_object_v = has_approximate_2_object<Gt>::value;
template <typename, typename, typename = std::void_t<>>
struct has_approximate_point : std::false_type {};
template <typename Gt, typename A>
struct has_approximate_point<Gt,
A,
std::void_t<decltype(std::declval<A>()(std::declval<const typename Gt::Point_2&>()))>> :
std::true_type
{};
// Detect whether A has operator()(const Gt::Point_2&)
template <typename Gt, typename A>
inline constexpr bool has_approximate_point_v = has_approximate_point<Gt, A>::value;
template <typename, typename, typename, typename = std::void_t<>>
struct has_approximate_xcv : std::false_type {};
template <typename Gt, typename A, typename O>
struct has_approximate_xcv
<Gt,
A,
O,
std::void_t<decltype(std::declval<A&>()(std::declval<const typename Gt::X_monotone_curve_2&>(),
std::declval<double>(),
std::declval<O>(),
std::declval<bool>()))>> : std::true_type
{};
// Detect whether A has operator()(const Gt::X_monotone_curve_2&, double, OutputIterator, bool)?
template <typename Gt, typename A>
constexpr bool has_approximate_xcv_v = has_approximate_xcv<Gt, A, void*>::value;
template <typename, typename, typename, typename = std::void_t<>>
struct has_approximate_xcv_with_bounds : std::false_type
{};
template <typename Gt, typename A, typename O>
struct has_approximate_xcv_with_bounds
<Gt,
A,
O,
std::void_t<decltype(std::declval<A&>()(std::declval<const typename Gt::X_monotone_curve_2&>(),
std::declval<double>(),
std::declval<O>(),
std::declval<Bbox_2>(),
std::declval<bool>()))>> : std::true_type
{};
// Detect whether A has operator()(const X_monotone_curve&, double, OutputIterator, Bbox_2, bool)
template <typename Gt, typename A>
inline constexpr bool has_approximate_xcv_with_bounds_v = has_approximate_xcv_with_bounds<Gt, A, void*>::value;
// Detect whether a geometry traits has all the necessary types and functions for approximation
template <typename Gt>
constexpr bool has_approximate_traits_v =
has_approximate_2_object_v<Gt> && has_approximate_point_v<Gt, typename Gt::Approximate_2> &&
(has_approximate_xcv_v<Gt, typename Gt::Approximate_2> ||
has_approximate_xcv_with_bounds_v<Gt, typename Gt::Approximate_2>);
template <typename Gt, typename = std::void_t<>>
struct has_is_in_x_range : std::false_type
{};
template <typename Gt>
struct has_is_in_x_range<Gt,
std::void_t<decltype(std::declval<typename Gt::X_monotone_curve_2>().is_in_x_range
(std::declval<const typename Gt::Point_2&>()))>> : std::true_type
{};
// Detect whether Gt::X_monotone_curve_2 has a member function bool is_in_x_range(const Gt::Point_2&)
template <typename Gt>
inline constexpr bool has_is_in_x_range_v = has_is_in_x_range<Gt>::value;
// Detect whether Gt is or derives from Arr_geodesic_arc_on_sphere_traits_2<*, *, *>
template <typename Gt>
struct is_or_derived_from_agas {
private:
template <typename Kernel_, int AtanX, int AtanY>
static std::true_type test(const Arr_geodesic_arc_on_sphere_traits_2<Kernel_, AtanX, AtanY>*);
static std::false_type test(...);
public:
static constexpr bool value = decltype(test(static_cast<const Gt*>(nullptr)))::value;
};
template <typename Gt>
inline constexpr bool is_or_derived_from_agas_v = is_or_derived_from_agas<Gt>::value;
// Detect whether T is or derives from a geometry traits on curved surfaces
template <typename Gt>
inline constexpr bool is_or_derived_from_curved_surf_traits_v = is_or_derived_from_agas_v<Gt>;
// Static helpers to get template arguments from a geometry traits
template <typename Gt>
struct tmpl_args {};
template <typename Kernel_, int AtanX, int AtanY>
struct tmpl_args<Arr_geodesic_arc_on_sphere_traits_2<Kernel_, AtanX, AtanY>> {
using Kernel = Kernel_;
static constexpr int atan_x = AtanX;
static constexpr int atan_y = AtanY;
};
/*! \brief Approximation data types
*
* \tparam Gt Geometry traits
*/
template <typename Gt>
class Arr_approximate_traits {
using Geom_traits = Gt;
template <typename P, typename I>
struct Triangle_soup_ {
using Index = I;
using Triangle = std::array<Index, 3>;
using Point = P;
std::vector<Point> points;
std::vector<Triangle> triangles;
};
public:
using Approx_point = typename Geom_traits::Approximate_point_2;
using Approx_nt = typename Geom_traits::Approximate_number_type;
using Approx_kernel = typename Geom_traits::Approximate_kernel;
// 2D parameter space point
using Point = typename Approx_kernel::Point_2;
using Polyline = std::vector<Point>;
using Triangle_soup = Triangle_soup_<Point, int>;
// A null point with NaN coordinates. Use ::is_null(pt) to check if a point is null.
inline static const Point Null_point =
Point(std::numeric_limits<Approx_nt>::signaling_NaN(), std::numeric_limits<Approx_nt>::signaling_NaN());
static bool is_null(Point pt) { return std::isnan(pt.x()) || std::isnan(pt.y()); }
};
/*!
* \brief Functor to construct a Point_2 from an Approximate_point_2.
*
* \tparam Gt Geometry traits
*/
template <typename Gt>
class Construct_gt_point_2 {
using Approx_traits = Arr_approximate_traits<Gt>;
using Approx_point = typename Approx_traits::Approx_point;
using Gt_point = typename Gt::Point_2;
public:
Gt_point operator()(const Approx_point& pt) const { return Gt_point(pt.x(), pt.y()); }
};
// Specialization for Arr_geodesic_arc_on_sphere_traits_2
template <typename Kernel, int AtanX, int AtanY>
class Construct_gt_point_2<Arr_geodesic_arc_on_sphere_traits_2<Kernel, AtanX, AtanY>> {
using Geom_traits = Arr_geodesic_arc_on_sphere_traits_2<Kernel, AtanX, AtanY>;
using Approx_traits = Arr_approximate_traits<Arr_geodesic_arc_on_sphere_traits_2<Kernel, AtanX, AtanY>>;
using Approx_point = typename Approx_traits::Approx_point;
using Gt_point = typename Geom_traits::Point_2;
public:
Gt_point operator()(const Approx_point& pt) const {
using Direction_3 = typename Kernel::Direction_3;
return Gt_point(Direction_3(pt.dx(), pt.dy(), pt.dz()),
static_cast<typename Gt_point::Location_type>(pt.location()));
}
};
} // namespace draw_aos
} // namespace CGAL
#endif // CGAL_DRAW_AOS_TYPE_UTILS_H

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.

File diff suppressed because it is too large Load Diff

View File

@ -1491,4 +1491,4 @@ if(CGAL_DISABLE_GMP)
foreach(_test ${LIST_OF_TESTS})
set_property(TEST ${_test} APPEND PROPERTY ENVIRONMENT CGAL_DISABLE_GMP=1)
endforeach()
endif()
endif()

View File

@ -31,7 +31,7 @@ the dot operator, and a typical usage is thus:
\code {.cpp}
Graph g1, g2;
Vertex_point_map_2 vpm_2; // an hypothetical custom property map assigning a Point to the vertices of g2
Vertex_point_map_2 vpm_2; // a hypothetical custom property map assigning a Point to the vertices of g2
// without any named parameter (default values are used)
CGAL::copy_face_graph(g1, g2);

View File

@ -1563,10 +1563,10 @@ does_satisfy_link_condition(typename boost::graph_traits<Graph>::edge_descriptor
*
* After the collapse of edge `e` the following holds:
* - The edge `e` is no longer in `g`.
* - The faces incident to edge `e` are no longer in `g`.
* - The triangle faces incident to edge `e` are no longer in `g`.
* - `v0` is no longer in `g`.
* - If `h` is not a border halfedge, `p_h` is no longer in `g` and is replaced by `o_n_h`.
* - If the opposite of `h` is not a border halfedge, `p_o_h` is no longer in `g` and is replaced by `o_n_o_h`.
* - If `h` is part of a triangle face, `p_h` is no longer in `g` and is replaced by `o_n_h`.
* - If the opposite of `h` is part of a triangle face, `p_o_h` is no longer in `g` and is replaced by `o_n_o_h`.
* - The halfedges kept in `g` that had `v0` as target and source now have `v1` as target and source, respectively.
* - No other incidence information is changed in `g`.
*
@ -1595,9 +1595,8 @@ collapse_edge(typename boost::graph_traits<Graph>::edge_descriptor e,
bool lBottomFaceExists = ! is_border(qp,g);
bool lTopLeftFaceExists = lTopFaceExists && ! is_border(pt,g);
bool lBottomRightFaceExists = lBottomFaceExists && ! is_border(qb,g);
CGAL_precondition( !lTopFaceExists || (lTopFaceExists && ( degree(target(pt, g), g) > 2 ) ) ) ;
CGAL_precondition( !lBottomFaceExists || (lBottomFaceExists && ( degree(target(qb, g), g) > 2 ) ) ) ;
bool lBottomIsTriangle = lBottomFaceExists && is_triangle(qp,g);
bool lTopIsTriangle = lTopFaceExists && is_triangle(pq,g);
vertex_descriptor q = target(pq, g);
vertex_descriptor p = source(pq, g);
@ -1605,7 +1604,7 @@ collapse_edge(typename boost::graph_traits<Graph>::edge_descriptor e,
bool lP_Erased = false;
if ( lTopFaceExists )
if ( lTopIsTriangle)
{
CGAL_precondition( ! is_border(opposite(pt, g),g) ) ; // p-q-t is a face of the mesh
if ( lTopLeftFaceExists )
@ -1632,7 +1631,7 @@ collapse_edge(typename boost::graph_traits<Graph>::edge_descriptor e,
}
}
if ( lBottomFaceExists )
if ( lBottomIsTriangle)
{
CGAL_precondition( ! is_border(opposite(qb, g),g) ) ; // p-q-b is a face of the mesh
if ( lBottomRightFaceExists )
@ -1679,7 +1678,7 @@ collapse_edge(typename boost::graph_traits<Graph>::edge_descriptor e,
* collapses an edge in a graph having non-collapsable edges.
*
* Let `h` be the halfedge of `e`, and let `v0` and `v1` be the source and target vertices of `h`.
* Collapses the edge `e` replacing it with `v1`, as described in the paragraph above
* Collapses the edge `e` replacing it with `v1`, as described in the other overload
* and guarantees that an edge `e2`, for which `get(edge_is_constrained_map, e2)==true`,
* is not removed after the collapse.
*
@ -1689,14 +1688,14 @@ collapse_edge(typename boost::graph_traits<Graph>::edge_descriptor e,
*
* \returns vertex `v1`.
* \pre This function requires `g` to be an oriented 2-manifold with or without boundaries.
* Furthermore, the edge `v0v1` must satisfy the link condition, which guarantees that the surface mesh is also 2-manifold after the edge collapse.
* \pre `get(edge_is_constrained_map, v0v1) == false`.
* Furthermore, the edge `e` must satisfy the link condition, which guarantees that the surface mesh is also 2-manifold after the edge collapse.
* \pre `get(edge_is_constrained_map, e) == false`.
* \pre `v0` and `v1` are not both incident to a constrained edge.
*/
template<typename Graph, typename EdgeIsConstrainedMap>
typename boost::graph_traits<Graph>::vertex_descriptor
collapse_edge(typename boost::graph_traits<Graph>::edge_descriptor v0v1,
collapse_edge(typename boost::graph_traits<Graph>::edge_descriptor e,
Graph& g,
EdgeIsConstrainedMap Edge_is_constrained_map)
{
@ -1704,11 +1703,11 @@ collapse_edge(typename boost::graph_traits<Graph>::edge_descriptor v0v1,
typedef typename Traits::vertex_descriptor vertex_descriptor;
typedef typename Traits::halfedge_descriptor halfedge_descriptor;
CGAL_precondition(is_valid_edge_descriptor(v0v1, g));
CGAL_precondition(does_satisfy_link_condition(v0v1,g));
CGAL_precondition(!get(Edge_is_constrained_map, v0v1));
CGAL_precondition(is_valid_edge_descriptor(e, g));
CGAL_precondition(does_satisfy_link_condition(e,g));
CGAL_precondition(!get(Edge_is_constrained_map, e));
halfedge_descriptor pq = halfedge(v0v1,g);
halfedge_descriptor pq = halfedge(e,g);
halfedge_descriptor qp = opposite(pq,g);
halfedge_descriptor pt = opposite(prev(pq,g),g);
@ -1718,6 +1717,8 @@ collapse_edge(typename boost::graph_traits<Graph>::edge_descriptor v0v1,
bool lTopFaceExists = ! is_border(pq,g) ;
bool lBottomFaceExists = ! is_border(qp,g) ;
bool lTopIsTriangle = lTopFaceExists && is_triangle(pq,g);
bool lBottomIsTriangle = lBottomFaceExists && is_triangle(qp,g);
vertex_descriptor q = target(pq,g);
vertex_descriptor p = source(pq,g);
@ -1728,7 +1729,7 @@ collapse_edge(typename boost::graph_traits<Graph>::edge_descriptor v0v1,
// If the top facet exists, we need to choose one out of the two edges which one disappears:
// p-t if it is not constrained and t-q otherwise
if ( lTopFaceExists )
if ( lTopIsTriangle )
{
if ( !get(Edge_is_constrained_map,edge(pt,g)) )
{
@ -1742,7 +1743,7 @@ collapse_edge(typename boost::graph_traits<Graph>::edge_descriptor v0v1,
// If the bottom facet exists, we need to choose one out of the two edges which one disappears:
// q-b if it is not constrained and b-p otherwise
if ( lBottomFaceExists )
if ( lBottomIsTriangle )
{
if ( !get(Edge_is_constrained_map,edge(qb,g)) )
{
@ -1753,7 +1754,7 @@ collapse_edge(typename boost::graph_traits<Graph>::edge_descriptor v0v1,
}
}
if (lTopFaceExists && lBottomFaceExists)
if (lTopIsTriangle && lBottomIsTriangle)
{
if ( face(edges_to_erase[0],g) == face(edges_to_erase[1],g)
&& (! is_border(edges_to_erase[0],g)) )
@ -1800,7 +1801,7 @@ collapse_edge(typename boost::graph_traits<Graph>::edge_descriptor v0v1,
}
else
{
if (lTopFaceExists)
if (lTopIsTriangle)
{
if (!(is_border(edges_to_erase[0],g))){
join_face(edges_to_erase[0],g);
@ -1815,21 +1816,32 @@ collapse_edge(typename boost::graph_traits<Graph>::edge_descriptor v0v1,
remove_face(opposite(edges_to_erase[0],g),g);
return q;
}
if (! (is_border(edges_to_erase[0],g))){
// q will be removed, swap it with p
internal::swap_vertices(p, q, g);
join_face(edges_to_erase[0],g);
join_vertex(qp,g);
return q;
}
if(!is_border(opposite(next(qp,g),g),g))
else
{
// q will be removed, swap it with p
internal::swap_vertices(p, q, g);
if (lBottomIsTriangle)
{
if (! (is_border(edges_to_erase[0],g))){
// q will be removed, swap it with p
internal::swap_vertices(p, q, g);
join_face(edges_to_erase[0],g);
CGAL_assertion(source(qp,g)==p);
join_vertex(qp,g);
return q;
}
if(!is_border(opposite(next(qp,g),g),g))
{
// q will be removed, swap it with p
internal::swap_vertices(p, q, g);
}
remove_face(opposite(edges_to_erase[0],g),g);
return q;
}
else
{
join_vertex(pq,g);
return q;
}
}
remove_face(opposite(edges_to_erase[0],g),g);
return q;
}
}
@ -1896,7 +1908,7 @@ bool satisfies_link_condition(typename boost::graph_traits<Graph>::edge_descript
* \param h halfedge descriptor
* \param g the graph
*
* \returns an halfedge linking the two vertices adjacent to the vertex being removed.
* \returns a halfedge linking the two vertices adjacent to the vertex being removed.
*
* \pre `degree(target(h, g), g) == 2`.
*

View File

@ -18,6 +18,7 @@
#include <CGAL/boost/graph/IO/Generic_facegraph_builder.h>
#include <CGAL/Named_function_parameters.h>
#include <CGAL/boost/graph/named_params_helper.h>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <fstream>
#include <string>
@ -44,7 +45,7 @@ class PLY_builder
typedef typename Base::Face_container Face_container;
public:
PLY_builder(std::istream& is) : Base(is) { }
PLY_builder(std::istream& is, std::string& comments) : Base(is), comments(comments) { }
template <typename NamedParameters>
bool read(std::istream& is,
@ -52,19 +53,22 @@ public:
Face_container& faces,
const NamedParameters& np)
{
return read_PLY(is, points, faces, np);
return read_PLY(is, points, faces, comments, np);
}
std::string& comments;
};
template <typename Graph, typename CGAL_NP_TEMPLATE_PARAMETERS>
bool read_PLY_BGL(std::istream& is,
Graph& g,
std::string& comments,
const CGAL_NP_CLASS& np = parameters::default_values())
{
typedef typename CGAL::GetVertexPointMap<Graph, CGAL_NP_CLASS>::type VPM;
typedef typename boost::property_traits<VPM>::value_type Point;
internal::PLY_builder<Graph, Point> builder(is);
internal::PLY_builder<Graph, Point> builder(is, comments);
return builder(g, np);
}
@ -84,6 +88,7 @@ bool read_PLY_BGL(std::istream& is,
\param is the input stream
\param g the graph to be built from the input data
\param comments a string included line by line in the header of the PLY stream (each line will be precedeed by "comment ")
\param np optional \ref bgl_namedparameters "Named Parameters" described below
\cgalNamedParamsBegin
@ -132,15 +137,31 @@ template <typename Graph,
typename CGAL_NP_TEMPLATE_PARAMETERS>
bool read_PLY(std::istream& is,
Graph& g,
std::string& comments,
const CGAL_NP_CLASS& np = parameters::default_values()
#ifndef DOXYGEN_RUNNING
, std::enable_if_t<!internal::is_Point_set_or_Range_or_Iterator<Graph>::value>* = nullptr
#endif
)
{
return internal::read_PLY_BGL(is, g, np);
return internal::read_PLY_BGL(is, g, comments, np);
}
template <typename Graph,
typename CGAL_NP_TEMPLATE_PARAMETERS>
bool read_PLY(std::istream& is,
Graph& g,
const CGAL_NP_CLASS& np = parameters::default_values()
#ifndef DOXYGEN_RUNNING
, std::enable_if_t<!internal::is_Point_set_or_Range_or_Iterator<Graph>::value>* = nullptr
#endif
)
{
std::string unused_comments;
return internal::read_PLY_BGL(is, g, unused_comments, np);
}
/*!
\ingroup PkgBGLIoFuncsPLY
@ -153,6 +174,7 @@ bool read_PLY(std::istream& is,
\param fname the name of the input file
\param g the graph to be built from the input data
\param comments a string included line by line in the header of the PLY stream (each line will be precedeed by "comment" )
\param np optional \ref bgl_namedparameters "Named Parameters" described below
\cgalNamedParamsBegin
@ -207,6 +229,7 @@ template <typename Graph,
typename CGAL_NP_TEMPLATE_PARAMETERS>
bool read_PLY(const std::string& fname,
Graph& g,
std::string& comments,
const CGAL_NP_CLASS& np = parameters::default_values()
#ifndef DOXYGEN_RUNNING
, std::enable_if_t<!internal::is_Point_set_or_Range_or_Iterator<Graph>::value>* = nullptr
@ -218,16 +241,29 @@ bool read_PLY(const std::string& fname,
{
std::ifstream is(fname, std::ios::binary);
CGAL::IO::set_mode(is, CGAL::IO::BINARY);
return internal::read_PLY_BGL(is, g, np);
return read_PLY(is, g, comments, np);
}
else
{
std::ifstream is(fname);
CGAL::IO::set_mode(is, CGAL::IO::ASCII);
return internal::read_PLY_BGL(is, g, np);
return read_PLY(is, g, comments, np);
}
}
template <typename Graph,
typename CGAL_NP_TEMPLATE_PARAMETERS>
bool read_PLY(const std::string& fname,
Graph& g,
const CGAL_NP_CLASS& np = parameters::default_values()
#ifndef DOXYGEN_RUNNING
, std::enable_if_t<!internal::is_Point_set_or_Range_or_Iterator<Graph>::value>* = nullptr
#endif
)
{
std::string unused_comment;
return read_PLY(fname, g, unused_comment, np);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
// Write
@ -259,6 +295,15 @@ bool read_PLY(const std::string& fname,
must be available in `Graph`.}
\cgalParamNEnd
\cgalParamNBegin{vertex_normal_map}
\cgalParamDescription{a property map associating normals to the vertices of `g`}
\cgalParamType{a class model of `ReadablePropertyMap` with `boost::graph_traits<Graph>::%vertex_descriptor`
as key type and `%Vector_3` as value type}
\cgalParamDefault{`boost::get(CGAL::vertex_point, g)`}
\cgalParamExtra{If this parameter is omitted, an internal property map for `CGAL::vertex_point_t`
must be available in `Graph`.}
\cgalParamNEnd
\cgalParamNBegin{vertex_index_map}
\cgalParamDescription{a property map associating to each vertex of `graph` a unique index}
\cgalParamType{a class model of `WritablePropertyMap` with `boost::graph_traits<Graph>::%vertex_descriptor`
@ -326,6 +371,8 @@ bool write_PLY(std::ostream& os,
bool has_vcolor = !is_default_parameter<CGAL_NP_CLASS, internal_np::vertex_color_map_t>::value;
bool has_fcolor = !is_default_parameter<CGAL_NP_CLASS, internal_np::face_color_map_t>::value;
constexpr bool has_vnormal = !is_default_parameter<CGAL_NP_CLASS, internal_np::vertex_normal_map_t>::value;
VIMap vim = CGAL::get_initialized_vertex_index_map(g, np);
Vpm vpm = choose_parameter(get_parameter(np, internal_np::vertex_point),
get_const_property_map(boost::vertex_point, g));
@ -351,8 +398,20 @@ bool write_PLY(std::ostream& os,
}
}
os << "element vertex " << vertices(g).size() << std::endl;
internal::output_property_header(os, make_ply_point_writer (CGAL::Identity_property_map<Point_3>()));
if constexpr (std::is_same<typename Kernel_traits<Point_3>::Kernel::FT, float>::value)
{
internal::output_property_header(os, make_ply_point_writer (CGAL::Identity_property_map<Point_3>()));
}
else
{
typedef typename Kernel_traits<Point_3>::Kernel K;
typedef decltype(std::declval<CGAL::Cartesian_converter<K, Epick> >().operator()(std::declval<Point_3>())) Target_point;
auto fvpm = CGAL::make_cartesian_converter_property_map<Target_point>(vpm);
internal::output_property_header(os, make_ply_point_writer (fvpm));
}
//if vcm is not default add v:color property
if(has_vcolor)
{
@ -362,10 +421,30 @@ bool write_PLY(std::ostream& os,
<< "property uchar alpha" << std::endl;
}
if constexpr (has_vnormal)
{
auto vnm = get_parameter(np, internal_np::vertex_normal_map);
typedef decltype(vnm) Normal_map;
typedef typename Normal_map::value_type Vector_3;
typedef typename Kernel_traits<Vector_3>::Kernel K;
typedef typename K::FT FT;
if constexpr (std::is_same<FT, float>::value)
{
internal::output_property_header(os, make_ply_normal_writer (CGAL::Identity_property_map<Vector_3>()));
}
else
{
typedef decltype(std::declval<CGAL::Cartesian_converter<K, Epick> >().operator()(std::declval<Vector_3>())) Target_vector;
auto fvnm = CGAL::make_cartesian_converter_property_map<Target_vector>(vnm);
internal::output_property_header(os, make_ply_normal_writer (fvnm));
}
}
os << "element face " << faces(g).size() << std::endl;
internal::output_property_header(
os, std::make_pair(CGAL::Identity_property_map<std::vector<std::size_t> >(),
PLY_property<std::vector<int> >("vertex_indices")));
//if fcm is not default add f:color property
if(has_fcolor)
{
@ -378,8 +457,42 @@ bool write_PLY(std::ostream& os,
for(vertex_descriptor vd : vertices(g))
{
const Point_3& p = get(vpm, vd);
internal::output_properties(os, &p, make_ply_point_writer (CGAL::Identity_property_map<Point_3>()));
if constexpr (std::is_same<typename Kernel_traits<Point_3>::Kernel::FT, float>::value)
{
decltype(auto) p = get(vpm, vd);
internal::output_properties(os, &p, make_ply_point_writer (CGAL::Identity_property_map<Point_3>()));
}
else
{
typedef typename Kernel_traits<Point_3>::Kernel K;
typedef CGAL::cpp20::remove_cvref_t<decltype(std::declval<CGAL::Cartesian_converter<K, Epick> >().operator()(std::declval<Point_3>()))> Target_point;
CGAL::Cartesian_converter_property_map<Target_point, Vpm> fvpm = CGAL::make_cartesian_converter_property_map<Target_point>(vpm);
decltype(auto) fp = get(fvpm, vd);
internal::output_properties(os, &fp, make_ply_point_writer (CGAL::Identity_property_map<Target_point>()));
}
std::cout << "using generic writer" << std::endl;
if constexpr (!parameters::is_default_parameter<CGAL_NP_CLASS, internal_np::vertex_normal_map_t>::value)
{
auto vnm = get_parameter(np, internal_np::vertex_normal_map);
typedef decltype(vnm) Normal_map;
typedef typename Normal_map::value_type Vector_3;
if constexpr (std::is_same<typename Kernel_traits<Vector_3>::Kernel::FT, float>::value)
{
decltype(auto) vec = get(vnm,vd);
internal::output_properties(os, &vec, make_ply_normal_writer (CGAL::Identity_property_map<Vector_3>()));
}
else
{
typedef typename Kernel_traits<Vector_3>::Kernel K;
typedef CGAL::cpp20::remove_cvref_t<decltype(std::declval<CGAL::Cartesian_converter<K, Epick> >().operator()(std::declval<Vector_3>()))> Target_vector;
auto fvnm = CGAL::make_cartesian_converter_property_map<Target_vector>(vnm);
decltype(auto) fvec = get(fvnm, vd);
internal::output_properties(os, &fvec, make_ply_normal_writer (CGAL::Identity_property_map<Target_vector>()));
}
}
if(has_vcolor)
{
const CGAL::IO::Color& c = get(vcm, vd);
@ -455,6 +568,15 @@ bool write_PLY(std::ostream& os, const Graph& g, const CGAL_NP_CLASS& np = param
must be available in `Graph`.}
\cgalParamNEnd
\cgalParamNBegin{vertex_normal_map}
\cgalParamDescription{a property map associating normals to the vertices of `g`}
\cgalParamType{a class model of `ReadablePropertyMap` with `boost::graph_traits<Graph>::%vertex_descriptor`
as key type and `%Vector_3` as value type}
\cgalParamDefault{`boost::get(CGAL::vertex_point, g)`}
\cgalParamExtra{If this parameter is omitted, an internal property map for `CGAL::vertex_point_t`
must be available in `Graph`.}
\cgalParamNEnd
\cgalParamNBegin{vertex_index_map}
\cgalParamDescription{a property map associating to each vertex of `graph` a unique index between `0` and `num_vertices(graph) - 1`}
\cgalParamType{a class model of `ReadablePropertyMap` with `boost::graph_traits<Graph>::%vertex_descriptor`

View File

@ -537,7 +537,7 @@ bool is_valid_polygon_mesh(const Mesh& g, bool verb = false)
return false;
// test for 2-manifoldness
// Distinct facets on each side of an halfedge.
// Distinct facets on each side of a halfedge.
for(halfedge_descriptor i : halfedges(g))
{
valid = (face(i, g) != face(opposite(i, g), g));

View File

@ -1,13 +1,19 @@
Algebraic_foundations
Arithmetic_kernel
BGL
Cartesian_kernel
Circulator
Distance_2
Distance_3
Filtered_kernel
Homogeneous_kernel
Hash_map
Installation
Intersections_2
Intersections_3
Interval_support
Kernel_23
Kernel_d
Modular_arithmetic
Number_types
Profiling_tools
@ -15,3 +21,4 @@ Property_map
Random_numbers
STL_Extension
Stream_support
CGAL_Core

View File

@ -0,0 +1,42 @@
OFF
25 13 0
0.39160239696502686 1.3864846229553223 4.8046874923102223e-08
0.053782559931278229 1.3864846229553223 4.8046874923102223e-08
-0.94644606113433838 1.6651756763458252 4.8046874923102223e-08
-1.3082554340362549 1.7385153770446777 4.8046874923102223e-08
-1.3033660650253296 1.1860226392745972 4.8046874923102223e-08
1.61628258228302 -0.17601536214351654 4.8046874923102223e-08
0.55834579467773438 -0.19216139614582062 4.8046874923102223e-08
0.053782559931278229 -0.17601536214351654 4.8046874923102223e-08
-0.24240998923778534 -0.22679123282432556 4.8046874923102223e-08
-0.58168435096740723 -0.25845989584922791 4.8046874923102223e-08
-1.2915089130401611 -0.17601536214351654 4.8046874923102223e-08
-1.50871741771698 -0.17601536214351654 4.8046874923102223e-08
1.61628258228302 -1.7385153770446777 4.8046874923102223e-08
1.1978726387023926 -1.7385153770446777 4.8046874923102223e-08
0.71942150592803955 -1.7385153770446777 4.8046874923102223e-08
0.053782559931278229 -1.7385153770446777 4.8046874923102223e-08
-0.73973840475082397 -1.7385153770446777 4.8046874923102223e-08
1.61628258228302 0.36264327168464661 4.8046874923102223e-08
-0.26156377792358398 0.45463424921035767 4.8046874923102223e-08
-0.028661971911787987 -0.78840988874435425 4.8046874923102223e-08
0.053782559931278229 -1.2213115692138672 4.8046874923102223e-08
-1.5918357372283936 1.5331641435623169 4.8046874923102223e-08
-1.6162823438644409 0.87338578701019287 4.8046874923102223e-08
-1.50871741771698 -0.0072435899637639523 4.8046874923102223e-08
-1.50871741771698 -1.3000825643539429 4.8046874923102223e-08
7 18 2 3 4 22 9 8
3 2 18 1
7 18 7 6 5 17 0 1
7 12 5 6 7 8 19 13
6 11 24 16 15 20 10
3 9 19 8
4 10 20 19 9
3 7 18 8
3 14 20 15
4 13 19 20 14
3 3 21 4
4 9 22 23 10
3 10 23 11

View File

@ -2,7 +2,6 @@
#include <CGAL/boost/graph/Euler_operations.h>
#include <CGAL/boost/graph/IO/OFF.h>
#include <boost/range/distance.hpp>
#include <string>
@ -213,12 +212,30 @@ collapse_edge_test()
assert(found == 2);
CGAL::clear(test_mesh);
}
// Case 6 non pure triangle mesh
{
Mesh ref;
if(!CGAL::IO::read_OFF("data/polygon_mesh_to_collapse.off", ref))
{
std::cout << "Error reading file: data/polygon_mesh_to_collapse.off" << std::endl;
exit(1);
}
std::size_t nbe=halfedges(ref).size();
for (std::size_t i=0; i< nbe; ++i)
{
Mesh m = ref;
auto h = *std::next(halfedges(m).begin(), i);
if (CGAL::Euler::does_satisfy_link_condition(edge(h,m),m))
CGAL::Euler::collapse_edge(edge(h,m), m);
assert(CGAL::is_valid_polygon_mesh(m));
}
}
}
int main()
{
collapse_edge_test<Polyhedron>();
collapse_edge_test<SM>();

View File

@ -1,9 +1,7 @@
# Created by the script cgal_create_cmake_script.
# This is the CMake script for compiling a CGAL application.
project(Barycentric_coordinates_2_Benchmarks)
cmake_minimum_required(VERSION 3.12...3.31)
project(Barycentric_coordinates_2_Benchmarks)
find_package(CGAL REQUIRED COMPONENTS Core)
@ -14,8 +12,9 @@ create_single_source_cgal_program("benchmark_polygon_16_vertices.cpp")
create_single_source_cgal_program("benchmark_polygon_100_vertices.cpp")
create_single_source_cgal_program("benchmark_mv_34_vertices.cpp")
find_package(Eigen3 3.1.0 QUIET) # (3.1.0 or greater)
find_package(Eigen3 QUIET)
include(CGAL_Eigen3_support)
if(TARGET CGAL::Eigen3_support)
create_single_source_cgal_program("benchmark_hm_4_vertices.cpp")
target_link_libraries(benchmark_hm_4_vertices PRIVATE CGAL::Eigen3_support)

View File

@ -17,8 +17,9 @@ create_single_source_cgal_program("terrain_height_modeling.cpp")
# this code is deprecated:
create_single_source_cgal_program("deprecated_coordinates.cpp")
find_package(Eigen3 3.1.0 QUIET) # (3.1.0 or greater)
find_package(Eigen3 QUIET)
include(CGAL_Eigen3_support)
if(TARGET CGAL::Eigen3_support)
create_single_source_cgal_program("affine_coordinates.cpp")
target_link_libraries(affine_coordinates PRIVATE CGAL::Eigen3_support)

View File

@ -42,8 +42,9 @@ create_single_source_cgal_program("test_wp_deprecated_api.cpp")
create_single_source_cgal_program("test_mv_deprecated_api.cpp")
create_single_source_cgal_program("test_dh_deprecated_api.cpp")
find_package(Eigen3 3.1.0 QUIET) # (3.1.0 or greater)
find_package(Eigen3 QUIET)
include(CGAL_Eigen3_support)
if(TARGET CGAL::Eigen3_support)
create_single_source_cgal_program("test_hm_unit_square.cpp")
target_link_libraries(test_hm_unit_square PRIVATE CGAL::Eigen3_support)

View File

@ -11,7 +11,7 @@ project(Basic_viewer_Examples)
#CGAL_Qt6 is needed for the drawing.
find_package(CGAL REQUIRED OPTIONAL_COMPONENTS Qt6)
find_package(Eigen3 3.1.0)
find_package(Eigen3 QUIET)
include(CGAL_Eigen3_support)
create_single_source_cgal_program("draw_lcc.cpp")

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

Some files were not shown because too many files have changed in this diff Show More