mirror of https://github.com/CGAL/cgal
Compare commits
437 Commits
4af1cf10aa
...
84dbd555f3
| Author | SHA1 | Date |
|---|---|---|
|
|
84dbd555f3 | |
|
|
26a5fc70e4 | |
|
|
39dd7c5028 | |
|
|
def6c38d76 | |
|
|
f503ce9359 | |
|
|
be305f320f | |
|
|
b8db056348 | |
|
|
18ee149f2e | |
|
|
15d96571a1 | |
|
|
06996f077f | |
|
|
5f8a8fe359 | |
|
|
543d424f58 | |
|
|
8e3a59a27b | |
|
|
40ac746be7 | |
|
|
9d28892e5f | |
|
|
dbcace69e6 | |
|
|
bac686d05b | |
|
|
30f63794c3 | |
|
|
92a896abb9 | |
|
|
1b3556184a | |
|
|
d14619c335 | |
|
|
50a187db38 | |
|
|
95a315335f | |
|
|
ff5166fbee | |
|
|
9f2fcb5e28 | |
|
|
85ef57ffa1 | |
|
|
aefbc23955 | |
|
|
fdf06fe969 | |
|
|
c8099415d4 | |
|
|
da0f634cb2 | |
|
|
7bf5687d5d | |
|
|
a0c32277d0 | |
|
|
1069678f36 | |
|
|
cda931ec46 | |
|
|
884e9fc4ee | |
|
|
cee9effe09 | |
|
|
eb14bf2a17 | |
|
|
e98fa21cc9 | |
|
|
e0a720452d | |
|
|
c856e40662 | |
|
|
ef6f9d8c3c | |
|
|
18e5836373 | |
|
|
3e1a8c110d | |
|
|
970f16913b | |
|
|
583a8364c9 | |
|
|
3ebe9203a7 | |
|
|
bf25dd27b8 | |
|
|
8ee288ee22 | |
|
|
e9fb73cadf | |
|
|
f98d968ed0 | |
|
|
9bd1705bf8 | |
|
|
0fc710e95d | |
|
|
dee5ed8cc2 | |
|
|
737bcb264e | |
|
|
2f9854b422 | |
|
|
e12a760f03 | |
|
|
eb992b38ca | |
|
|
3ccdc134fe | |
|
|
1602be1348 | |
|
|
ba17e0bdde | |
|
|
12445cc6e1 | |
|
|
e7205b985d | |
|
|
12a0f67674 | |
|
|
5812c1d6b5 | |
|
|
07347da411 | |
|
|
1dc39039e9 | |
|
|
1673cd0f9e | |
|
|
dfc5fb5065 | |
|
|
48262b8068 | |
|
|
24d3cd4bec | |
|
|
d226e504c4 | |
|
|
097fc2c5ab | |
|
|
c751ee6bc9 | |
|
|
066159f792 | |
|
|
333a15584f | |
|
|
cd787c84d1 | |
|
|
0ac856dd41 | |
|
|
31734df2ef | |
|
|
3ef43324bb | |
|
|
3c7d507530 | |
|
|
76552ccca1 | |
|
|
546d0b2871 | |
|
|
af94906903 | |
|
|
3b0d95e0e5 | |
|
|
ffda347171 | |
|
|
a9b369650a | |
|
|
faae741666 | |
|
|
9e36c6744b | |
|
|
828d57a419 | |
|
|
6f2c3d819e | |
|
|
459fcf3c3f | |
|
|
1c1245d5c0 | |
|
|
d1c66eaa0f | |
|
|
c63a3d721e | |
|
|
05bf3c4ffc | |
|
|
3569406da1 | |
|
|
d3d5d4575a | |
|
|
458e79bde8 | |
|
|
8a136c50c9 | |
|
|
7e1f685ea3 | |
|
|
f92b41ae0a | |
|
|
e4469c043e | |
|
|
4b89f17b42 | |
|
|
41ad794c39 | |
|
|
837939c8ee | |
|
|
25005a97d8 | |
|
|
25844edf50 | |
|
|
2a5351cc0a | |
|
|
f508d6fe1d | |
|
|
6bd5ec4f8b | |
|
|
eaa25c500b | |
|
|
64e33bd6cb | |
|
|
3fe83c7ce0 | |
|
|
f28e643ed0 | |
|
|
7f4703e248 | |
|
|
e13da7cbd4 | |
|
|
5cc8ec7d71 | |
|
|
2d39ab4dd8 | |
|
|
2fb9a2d832 | |
|
|
7c3b2302b5 | |
|
|
8b4e81ab5c | |
|
|
20ae7dfc0d | |
|
|
b66ebf958b | |
|
|
c60cc5049d | |
|
|
80b4d1a1be | |
|
|
c882eab5b5 | |
|
|
44306e981a | |
|
|
25060734a0 | |
|
|
e70e2109f4 | |
|
|
fb748f6442 | |
|
|
622b652652 | |
|
|
5050b54bfe | |
|
|
35613b984f | |
|
|
00f5ae061d | |
|
|
b5c3b5f895 | |
|
|
ab9e0ebc8a | |
|
|
6706e0468e | |
|
|
fd21dfb67d | |
|
|
bc42fb4a40 | |
|
|
07e0ea785d | |
|
|
edbc32959d | |
|
|
b068e62ffb | |
|
|
b85035ff87 | |
|
|
c48b4cb6c2 | |
|
|
d34201ed38 | |
|
|
15a155ec30 | |
|
|
e02c1495bf | |
|
|
28d6ac5e49 | |
|
|
def7ea788f | |
|
|
8aaeff1a8e | |
|
|
dcaad3d140 | |
|
|
e1e41fd199 | |
|
|
f766834601 | |
|
|
5e26465b2c | |
|
|
67220b911b | |
|
|
37b6a7214d | |
|
|
cd04470eef | |
|
|
d1afc52902 | |
|
|
592b8824ec | |
|
|
a1b5cd58da | |
|
|
5ed29f9173 | |
|
|
7c9b9d1592 | |
|
|
6314299598 | |
|
|
6d011a62ae | |
|
|
f806219fc8 | |
|
|
8e11587719 | |
|
|
5df526f70c | |
|
|
d2b801937f | |
|
|
06e505520e | |
|
|
909cbce367 | |
|
|
8a3c77fc0d | |
|
|
58e7083445 | |
|
|
8b6325b101 | |
|
|
8e8ad1a824 | |
|
|
8623f28bb0 | |
|
|
4c27d08372 | |
|
|
4acccc210b | |
|
|
86122eaa00 | |
|
|
adfcc7d102 | |
|
|
5d82eed3ea | |
|
|
c5b5a54952 | |
|
|
5085762946 | |
|
|
b3cb80760c | |
|
|
098e05e134 | |
|
|
4d6541c3c4 | |
|
|
4ed4d096bf | |
|
|
e7682069fe | |
|
|
8730763d39 | |
|
|
4d85bc3e63 | |
|
|
712464b690 | |
|
|
7fe0100855 | |
|
|
c2e38c2070 | |
|
|
8ad92851a1 | |
|
|
e7ab5002a3 | |
|
|
d9ba43a9ba | |
|
|
98a3051235 | |
|
|
940ac3d6e4 | |
|
|
da011b2abe | |
|
|
3706528a0c | |
|
|
8746a29fa9 | |
|
|
878ba3fc53 | |
|
|
bc770242a5 | |
|
|
61013d5053 | |
|
|
62a9c9e04f | |
|
|
67349ccbe1 | |
|
|
d7faad95dd | |
|
|
8215abd980 | |
|
|
bac2c06026 | |
|
|
358a588eae | |
|
|
c43058de26 | |
|
|
75c2ac5a68 | |
|
|
b11e42c4a7 | |
|
|
7d9dbdafcd | |
|
|
21df7dad86 | |
|
|
f6425d7773 | |
|
|
4d3d2f4f03 | |
|
|
626675ea08 | |
|
|
71c2425b6e | |
|
|
2ca338068b | |
|
|
e1ec2fd1d2 | |
|
|
ce1c890cb0 | |
|
|
8c84316796 | |
|
|
ed6eb76670 | |
|
|
66bb36e336 | |
|
|
cd248c2638 | |
|
|
1a03f8c6e1 | |
|
|
284df7125d | |
|
|
3a350bf354 | |
|
|
c26c013b5a | |
|
|
0ffa81d3c4 | |
|
|
865c1d2ed7 | |
|
|
0417a52217 | |
|
|
89393e1b7c | |
|
|
ba10efcbe4 | |
|
|
2a815ff510 | |
|
|
24024424ef | |
|
|
d3c069a10d | |
|
|
ee1de0fdb9 | |
|
|
39531baac8 | |
|
|
bbc6238843 | |
|
|
18f1f65bbf | |
|
|
9a99df4a9d | |
|
|
737079e530 | |
|
|
68853c0f88 | |
|
|
47099e5943 | |
|
|
8c150b865c | |
|
|
38a644974d | |
|
|
0e80f3e740 | |
|
|
d309bc89ce | |
|
|
3c482672aa | |
|
|
e21cfa301d | |
|
|
f4aa383177 | |
|
|
90f9e19efe | |
|
|
b2f5a21d0f | |
|
|
0a743e6a1a | |
|
|
36b66946b8 | |
|
|
89ba13f977 | |
|
|
33bd58bbef | |
|
|
e652a7976a | |
|
|
3be4ffce37 | |
|
|
3567ba1456 | |
|
|
806e65f259 | |
|
|
a9a60b5a00 | |
|
|
92dc53c58a | |
|
|
b97c4b78c3 | |
|
|
93d5fecf1c | |
|
|
5103fb4eb7 | |
|
|
fad48f7305 | |
|
|
bdee2836df | |
|
|
39fe8b3a6d | |
|
|
61cf55efee | |
|
|
0cf9d434b6 | |
|
|
f06f6b7dcf | |
|
|
93d3356dd9 | |
|
|
561ec37dc6 | |
|
|
5c058a8c9b | |
|
|
b668fb4b5a | |
|
|
d7cfaccfa1 | |
|
|
316c455034 | |
|
|
7d4852a60f | |
|
|
6c4aeabb9d | |
|
|
6567d54ca3 | |
|
|
2a8aa908fa | |
|
|
9b3132a2cd | |
|
|
81e1650c78 | |
|
|
967aee62e9 | |
|
|
2046b32e80 | |
|
|
f09d4efc03 | |
|
|
0879232f8e | |
|
|
d297dd4e53 | |
|
|
8a026f7ec5 | |
|
|
05dd65609d | |
|
|
2e087bc108 | |
|
|
f40f4a8629 | |
|
|
5ebcf81952 | |
|
|
70ebce80ff | |
|
|
bd6a4ca392 | |
|
|
449ba102eb | |
|
|
3988fe2009 | |
|
|
f56a295dd2 | |
|
|
e1bfc585f7 | |
|
|
0b073d1249 | |
|
|
c8110a71eb | |
|
|
0f2aa39b62 | |
|
|
ba19fbd67d | |
|
|
65c797ab44 | |
|
|
a9e0eeec8f | |
|
|
dc422a7531 | |
|
|
e73cf18c12 | |
|
|
25aa21635a | |
|
|
bc29da5ee3 | |
|
|
a137e76807 | |
|
|
d99baac07f | |
|
|
8c94773841 | |
|
|
1fc69dc279 | |
|
|
74dd1678e4 | |
|
|
e2979aa0f2 | |
|
|
d5f5b7b4f0 | |
|
|
fa724ed0ed | |
|
|
82e9d4e5b9 | |
|
|
4d615a31b6 | |
|
|
5a3dbda022 | |
|
|
6a47eb77e4 | |
|
|
e36f71e2a7 | |
|
|
55dcfcfb46 | |
|
|
a9e46362aa | |
|
|
876db072d8 | |
|
|
8ebeb13896 | |
|
|
f25a684c95 | |
|
|
3382ac0d18 | |
|
|
707375e780 | |
|
|
1d62c37822 | |
|
|
4a6d766d8c | |
|
|
f8c9340c1c | |
|
|
5b6df813f5 | |
|
|
2532df1eaf | |
|
|
f41b5b60f7 | |
|
|
f758f57b6a | |
|
|
5c7abdd617 | |
|
|
32973ffa12 | |
|
|
883233d15d | |
|
|
708efa82b5 | |
|
|
260af72d6e | |
|
|
294c3e0b88 | |
|
|
6a65d677e3 | |
|
|
b871b81d57 | |
|
|
29715e44a4 | |
|
|
f4a02aeaef | |
|
|
f69ad03ef8 | |
|
|
a366725c85 | |
|
|
1c45ed834c | |
|
|
375681748d | |
|
|
81bb832333 | |
|
|
a74945062c | |
|
|
e5049d4b03 | |
|
|
1bd923b393 | |
|
|
c677355de2 | |
|
|
0f528545c7 | |
|
|
35721db0b9 | |
|
|
d41efe0330 | |
|
|
bf1bc2fc85 | |
|
|
25b1f95449 | |
|
|
0a3d8084ea | |
|
|
c9038d7c73 | |
|
|
556e6b9993 | |
|
|
dcf954f72a | |
|
|
babe5e421a | |
|
|
20051d4e7e | |
|
|
67f8c1f6e6 | |
|
|
6dd570be9c | |
|
|
6616a6a4e4 | |
|
|
6eb52494c6 | |
|
|
3b24522834 | |
|
|
30e041c966 | |
|
|
d9766a2279 | |
|
|
beee32e945 | |
|
|
750b099594 | |
|
|
4157771db4 | |
|
|
33e2cd51d4 | |
|
|
9092a603ce | |
|
|
e20cfc56b5 | |
|
|
9a5280076a | |
|
|
cc19bd4a80 | |
|
|
3d56370164 | |
|
|
39141d7dcf | |
|
|
dabe5675b6 | |
|
|
eca5afe6ee | |
|
|
464c591b5a | |
|
|
e0634c4ab1 | |
|
|
1a59d8cd3c | |
|
|
029fb1b6b3 | |
|
|
7e4791ffb2 | |
|
|
96b1e77987 | |
|
|
3413272070 | |
|
|
7063e4e261 | |
|
|
7471dc847d | |
|
|
c37745641a | |
|
|
09365799e9 | |
|
|
b3657277d7 | |
|
|
fb9afae4ac | |
|
|
616931594a | |
|
|
e70cf9fa17 | |
|
|
30b9a29ee9 | |
|
|
e187dc03cb | |
|
|
99aeb5f80a | |
|
|
ac7b7f62bd | |
|
|
cd1951be26 | |
|
|
3f90d36604 | |
|
|
ad20fa497a | |
|
|
4cfd48ba76 | |
|
|
094651581f | |
|
|
0ff050c414 | |
|
|
35f66f80b6 | |
|
|
2caff8f2d8 | |
|
|
559833c00b | |
|
|
bdbe99276c | |
|
|
b66c3743ec | |
|
|
5b2887240c | |
|
|
5171477b26 | |
|
|
05014378d6 | |
|
|
0e27e7632c | |
|
|
7ab9468594 | |
|
|
a316b67548 | |
|
|
ba87b5c2e5 | |
|
|
a08388c4e3 | |
|
|
969062e3df | |
|
|
cfcc90d649 | |
|
|
c5a688590a | |
|
|
710666a51b | |
|
|
c58286d716 | |
|
|
6cba601ff3 | |
|
|
fe86a79bdc | |
|
|
7a984104fa | |
|
|
d876fbab69 | |
|
|
5eb93449c5 | |
|
|
40dee7d2a0 | |
|
|
2d72f21107 |
|
|
@ -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
|
||||
...
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.,
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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>`.
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
/// @}
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
/// @}
|
||||
}
|
||||
|
|
@ -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 */
|
||||
|
||||
}
|
||||
|
|
@ -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 */
|
||||
|
||||
}
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
/// @{
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -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() << ") ";
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
// Copyright (c) 2006,2007,2009,2010,2011,2025 Tel-Aviv University (Israel).
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of CGAL (www.cgal.org).
|
||||
//
|
||||
// $URL$
|
||||
// $Id$
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
//
|
||||
// Author(s) : Efi Fogel <efif@post.tau.ac.il>
|
||||
|
||||
#ifndef CGAL_DO_INTERSECT_ARR_OVERLAY_SS_VISITOR_H
|
||||
#define CGAL_DO_INTERSECT_ARR_OVERLAY_SS_VISITOR_H
|
||||
|
||||
#include <CGAL/license/Arrangement_on_surface_2.h>
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* Definition of the Arr_do_intersect_overlay_ss_visitor class-template.
|
||||
*/
|
||||
|
||||
#include <CGAL/Default.h>
|
||||
#include <CGAL/Surface_sweep_2/Arr_overlay_ss_visitor.h>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
/*! \class Arr_do_intersect_overlay_ss_visitor
|
||||
*
|
||||
* A sweep-line visitor for overlaying a "red" arrangement and a "blue"
|
||||
* arrangement as long as the edges do not intersect in their interiors. If
|
||||
* there are no intersections, the overlay arrangement is constructed. All three
|
||||
* arrangements are embedded on the same type of surface and use the same
|
||||
* geometry traits. Otherwise, the process is terminated without any delay (that
|
||||
* is, once an intersection is detected).
|
||||
*/
|
||||
template <typename OverlayHelper, typename OverlayTraits, typename Visitor_ = Default>
|
||||
class Arr_do_intersect_overlay_ss_visitor :
|
||||
public Arr_overlay_ss_visitor<
|
||||
OverlayHelper, OverlayTraits,
|
||||
typename Default::Get<Visitor_,
|
||||
Arr_do_intersect_overlay_ss_visitor<OverlayHelper, OverlayTraits, Visitor_> >::type> {
|
||||
private:
|
||||
using Overlay_helper = OverlayHelper;
|
||||
using Overlay_traits = OverlayTraits;
|
||||
|
||||
using Self = Arr_do_intersect_overlay_ss_visitor<Overlay_helper, Overlay_traits, Visitor_>;
|
||||
using Visitor = typename Default::Get<Visitor_, Self>::type;
|
||||
using Base = Arr_overlay_ss_visitor<Overlay_helper, Overlay_traits, Visitor>;
|
||||
|
||||
protected:
|
||||
bool m_found_x;
|
||||
|
||||
public:
|
||||
using Arrangement_red_2 = typename Base::Arrangement_red_2;
|
||||
using Arrangement_blue_2 = typename Base::Arrangement_blue_2;
|
||||
using Arrangement_2 = typename Base::Arrangement_2;
|
||||
using Event = typename Base::Event;
|
||||
using Subcurve = typename Base::Subcurve;
|
||||
using Status_line_iterator = typename Base::Status_line_iterator;
|
||||
using X_monotone_curve_2 = typename Base::X_monotone_curve_2;
|
||||
using Point_2 = typename Base::Point_2;
|
||||
using Multiplicity = typename Base::Multiplicity;
|
||||
|
||||
/*! Constructor */
|
||||
Arr_do_intersect_overlay_ss_visitor(const Arrangement_red_2* red_arr,
|
||||
const Arrangement_blue_2* blue_arr,
|
||||
Arrangement_2* res_arr,
|
||||
Overlay_traits* overlay_traits) :
|
||||
Base(red_arr, blue_arr, res_arr, overlay_traits),
|
||||
m_found_x(false)
|
||||
{}
|
||||
|
||||
/*! Destructor */
|
||||
virtual ~Arr_do_intersect_overlay_ss_visitor() {}
|
||||
|
||||
/*! Update an event that corresponds to a curve endpoint. */
|
||||
void update_event(Event* e, const Point_2& end_point, const X_monotone_curve_2& cv, Arr_curve_end cv_end, bool is_new)
|
||||
{ return Base::update_event(e, end_point, cv, cv_end, is_new); }
|
||||
|
||||
/*! Update an event that corresponds to a curve endpoint */
|
||||
void update_event(Event* e, const X_monotone_curve_2& cv, Arr_curve_end cv_end, bool is_new )
|
||||
{ return Base::update_event(e, cv, cv_end, is_new); }
|
||||
|
||||
/*! Update an event that corresponds to a curve endpoint */
|
||||
void update_event(Event* e, const Point_2& p, bool is_new)
|
||||
{ return Base::update_event(e, p, is_new); }
|
||||
|
||||
/*! Update an event that corresponds to an intersection */
|
||||
void update_event(Event* e, Subcurve* sc) { return Base::update_event(e, sc); }
|
||||
|
||||
/*! Update an event that corresponds to an intersection between curves */
|
||||
void update_event(Event* e, Subcurve* sc1, Subcurve* sc2, bool is_new, Multiplicity multiplicity) {
|
||||
if ((multiplicity % 2) == 1) m_found_x = true;
|
||||
Base::update_event(e, sc1, sc2, is_new, multiplicity);
|
||||
}
|
||||
|
||||
bool after_handle_event(Event* e, Status_line_iterator iter, bool flag) {
|
||||
auto res = Base::after_handle_event(e, iter, flag);
|
||||
if (m_found_x) this->surface_sweep()->stop_sweep();
|
||||
return res;
|
||||
}
|
||||
|
||||
/*! Getter */
|
||||
bool found_intersection() { return m_found_x; }
|
||||
};
|
||||
|
||||
} // namespace CGAL
|
||||
|
||||
#endif
|
||||
|
|
@ -8,9 +8,9 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
//
|
||||
// Author(s): Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ron Wein <wein@post.tau.ac.il>
|
||||
// Efi Fogel <efif@post.tau.ac.il>
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ron Wein <wein@post.tau.ac.il>
|
||||
// Efi Fogel <efif@post.tau.ac.il>
|
||||
|
||||
#ifndef CGAL_ARR_NO_INTERSECTION_INSERTION_SS_VISITOR_H
|
||||
#define CGAL_ARR_NO_INTERSECTION_INSERTION_SS_VISITOR_H
|
||||
|
|
@ -42,35 +42,33 @@ class Arr_no_intersection_insertion_ss_visitor :
|
|||
public Arr_construction_ss_visitor<
|
||||
Helper_,
|
||||
typename Default::Get<Visitor_, Arr_no_intersection_insertion_ss_visitor<
|
||||
Helper_, Visitor_> >::type>
|
||||
{
|
||||
Helper_, Visitor_> >::type> {
|
||||
public:
|
||||
typedef Helper_ Helper;
|
||||
using Helper = Helper_;
|
||||
|
||||
typedef typename Helper::Geometry_traits_2 Geometry_traits_2;
|
||||
typedef typename Helper::Event Event;
|
||||
typedef typename Helper::Subcurve Subcurve;
|
||||
using Geometry_traits_2 = typename Helper::Geometry_traits_2;
|
||||
using Event = typename Helper::Event;
|
||||
using Subcurve = typename Helper::Subcurve;
|
||||
|
||||
private:
|
||||
typedef Geometry_traits_2 Gt2;
|
||||
typedef Arr_no_intersection_insertion_ss_visitor<Helper, Visitor_>
|
||||
Self;
|
||||
typedef typename Default::Get<Visitor_, Self>::type Visitor;
|
||||
typedef Arr_construction_ss_visitor<Helper, Visitor> Base;
|
||||
using Gt2 = Geometry_traits_2;
|
||||
using Self = Arr_no_intersection_insertion_ss_visitor<Helper, Visitor_>;
|
||||
using Visitor = typename Default::Get<Visitor_, Self>::type;
|
||||
using Base = Arr_construction_ss_visitor<Helper, Visitor>;
|
||||
|
||||
public:
|
||||
typedef typename Gt2::X_monotone_curve_2 X_monotone_curve_2;
|
||||
typedef typename Gt2::Point_2 Point_2;
|
||||
using X_monotone_curve_2 = typename Gt2::X_monotone_curve_2;
|
||||
using Point_2 = typename Gt2::Point_2;
|
||||
using Multiplicity = typename Gt2::Multiplicity;
|
||||
|
||||
protected:
|
||||
typedef typename Subcurve::Status_line_iterator Status_line_iterator;
|
||||
typedef typename Base::Event_subcurve_reverse_iterator
|
||||
Event_subcurve_reverse_iterator;
|
||||
using Status_line_iterator = typename Subcurve::Status_line_iterator;
|
||||
using Event_subcurve_reverse_iterator = typename Base::Event_subcurve_reverse_iterator;
|
||||
|
||||
typedef typename Helper::Arrangement_2 Arrangement_2;
|
||||
typedef typename Arrangement_2::Vertex_handle Vertex_handle;
|
||||
typedef typename Arrangement_2::Halfedge_handle Halfedge_handle;
|
||||
typedef typename Arrangement_2::Face_handle Face_handle;
|
||||
using Arrangement_2 = typename Helper::Arrangement_2;
|
||||
using Vertex_handle = typename Arrangement_2::Vertex_handle;
|
||||
using Halfedge_handle = typename Arrangement_2::Halfedge_handle;
|
||||
using Face_handle = typename Arrangement_2::Face_handle;
|
||||
|
||||
public:
|
||||
/*! Constructor. */
|
||||
|
|
@ -103,13 +101,12 @@ public:
|
|||
{}
|
||||
|
||||
void update_event(Event* /* e */, Subcurve* /* sc1 */, Subcurve* /* sc2 */,
|
||||
bool /* is_new */)
|
||||
bool /* is_new */, Multiplicity /* multiplicity */)
|
||||
{}
|
||||
|
||||
void update_event(Event* /* e */, Subcurve* /* sc1 */) {}
|
||||
|
||||
void update_event(Event* e, const Point_2& pt, bool /* is_new */)
|
||||
{
|
||||
void update_event(Event* e, const Point_2& pt, bool /* is_new */) {
|
||||
Vertex_handle invalid_v;
|
||||
if (e->point().vertex_handle() == invalid_v)
|
||||
e->point().set_vertex_handle(pt.vertex_handle());
|
||||
|
|
@ -241,8 +238,7 @@ void Arr_no_intersection_insertion_ss_visitor<Hlpr, Vis>::before_sweep()
|
|||
//
|
||||
template <typename Hlpr, typename Vis>
|
||||
void Arr_no_intersection_insertion_ss_visitor<Hlpr, Vis>::
|
||||
before_handle_event(Event* event)
|
||||
{
|
||||
before_handle_event(Event* event) {
|
||||
// First we notify the helper class on the event.
|
||||
this->m_helper.before_handle_event(event);
|
||||
|
||||
|
|
@ -330,8 +326,7 @@ before_handle_event(Event* event)
|
|||
//
|
||||
template <typename Hlpr, typename Vis>
|
||||
bool Arr_no_intersection_insertion_ss_visitor<Hlpr, Vis>::
|
||||
add_subcurve_(const X_monotone_curve_2& cv, Subcurve* sc)
|
||||
{
|
||||
add_subcurve_(const X_monotone_curve_2& cv, Subcurve* sc) {
|
||||
const Halfedge_handle invalid_he;
|
||||
if (cv.halfedge_handle() != invalid_he) return false;
|
||||
// Insert the curve into the arrangement
|
||||
|
|
@ -344,8 +339,7 @@ add_subcurve_(const X_monotone_curve_2& cv, Subcurve* sc)
|
|||
//
|
||||
template <typename Hlpr, typename Vis>
|
||||
void Arr_no_intersection_insertion_ss_visitor<Hlpr, Vis>::
|
||||
add_subcurve(const X_monotone_curve_2& cv, Subcurve* sc)
|
||||
{
|
||||
add_subcurve(const X_monotone_curve_2& cv, Subcurve* sc) {
|
||||
if (add_subcurve_(cv, sc)) return;
|
||||
|
||||
Halfedge_handle next_ccw_he =
|
||||
|
|
@ -359,8 +353,7 @@ add_subcurve(const X_monotone_curve_2& cv, Subcurve* sc)
|
|||
template <typename Hlpr, typename Vis>
|
||||
typename Arr_no_intersection_insertion_ss_visitor<Hlpr, Vis>::Halfedge_handle
|
||||
Arr_no_intersection_insertion_ss_visitor<Hlpr, Vis>::
|
||||
insert_in_face_interior(const X_monotone_curve_2& cv, Subcurve* sc)
|
||||
{
|
||||
insert_in_face_interior(const X_monotone_curve_2& cv, Subcurve* sc) {
|
||||
Event* last_event = this->last_event_on_subcurve(sc);
|
||||
Vertex_handle last_v = last_event->point().vertex_handle();
|
||||
Vertex_handle curr_v = this->current_event()->point().vertex_handle();
|
||||
|
|
@ -385,8 +378,7 @@ template <typename Hlpr, typename Vis>
|
|||
typename Arr_no_intersection_insertion_ss_visitor<Hlpr, Vis>::Halfedge_handle
|
||||
Arr_no_intersection_insertion_ss_visitor<Hlpr, Vis>::
|
||||
insert_from_left_vertex(const X_monotone_curve_2& cv, Halfedge_handle he,
|
||||
Subcurve* sc)
|
||||
{
|
||||
Subcurve* sc) {
|
||||
Vertex_handle curr_v = this->current_event()->point().vertex_handle();
|
||||
if (curr_v != Vertex_handle())
|
||||
return (this->m_arr->insert_at_vertices(cv.base(), he, curr_v));
|
||||
|
|
@ -400,8 +392,7 @@ template <typename Hlpr, typename Vis>
|
|||
typename Arr_no_intersection_insertion_ss_visitor<Hlpr, Vis>::Halfedge_handle
|
||||
Arr_no_intersection_insertion_ss_visitor<Hlpr, Vis>::
|
||||
insert_from_right_vertex(const X_monotone_curve_2& cv, Halfedge_handle he,
|
||||
Subcurve* sc)
|
||||
{
|
||||
Subcurve* sc) {
|
||||
Event* last_event = this->last_event_on_subcurve(sc);
|
||||
Vertex_handle last_v = last_event->point().vertex_handle();
|
||||
if (last_v != Vertex_handle())
|
||||
|
|
@ -426,8 +417,7 @@ insert_at_vertices(const X_monotone_curve_2& cv,
|
|||
template <typename Hlpr, typename Vis>
|
||||
typename Arr_no_intersection_insertion_ss_visitor<Hlpr, Vis>::Vertex_handle
|
||||
Arr_no_intersection_insertion_ss_visitor<Hlpr, Vis>::
|
||||
insert_isolated_vertex(const Point_2& pt, Status_line_iterator iter)
|
||||
{
|
||||
insert_isolated_vertex(const Point_2& pt, Status_line_iterator iter) {
|
||||
// If the isolated vertex is already at the arrangement, return:
|
||||
if (pt.vertex_handle() != Vertex_handle()) return Vertex_handle();
|
||||
|
||||
|
|
@ -443,8 +433,7 @@ insert_isolated_vertex(const Point_2& pt, Status_line_iterator iter)
|
|||
template <typename Hlpr, typename Vis>
|
||||
typename Arr_no_intersection_insertion_ss_visitor<Hlpr, Vis>::Halfedge_handle
|
||||
Arr_no_intersection_insertion_ss_visitor<Hlpr, Vis>::
|
||||
_insert_in_face_interior(const X_monotone_curve_2& cv, Subcurve* sc)
|
||||
{
|
||||
_insert_in_face_interior(const X_monotone_curve_2& cv, Subcurve* sc) {
|
||||
// Check if the vertex to be associated with the left end of the curve has
|
||||
// already been created.
|
||||
Event* last_event = this->last_event_on_subcurve(sc);
|
||||
|
|
@ -514,8 +503,7 @@ template <typename Hlpr, typename Vis>
|
|||
typename Arr_no_intersection_insertion_ss_visitor<Hlpr, Vis>::Halfedge_handle
|
||||
Arr_no_intersection_insertion_ss_visitor<Hlpr, Vis>::
|
||||
_insert_from_left_vertex(const X_monotone_curve_2& cv,
|
||||
Halfedge_handle prev, Subcurve* sc)
|
||||
{
|
||||
Halfedge_handle prev, Subcurve* sc) {
|
||||
// Check if the vertex to be associated with the right end of the curve has
|
||||
// already been created.
|
||||
Event* curr_event = this->current_event();
|
||||
|
|
@ -551,8 +539,7 @@ template <typename Hlpr, typename Vis>
|
|||
typename Arr_no_intersection_insertion_ss_visitor<Hlpr, Vis>::Halfedge_handle
|
||||
Arr_no_intersection_insertion_ss_visitor<Hlpr, Vis>::
|
||||
_insert_from_right_vertex(const X_monotone_curve_2& cv, Halfedge_handle prev,
|
||||
Subcurve* sc)
|
||||
{
|
||||
Subcurve* sc) {
|
||||
// Check if the vertex to be associated with the left end of the curve has
|
||||
// already been created.
|
||||
Event* last_event = this->last_event_on_subcurve(sc);
|
||||
|
|
@ -589,8 +576,7 @@ typename Arr_no_intersection_insertion_ss_visitor<Hlpr, Vis>::Halfedge_handle
|
|||
Arr_no_intersection_insertion_ss_visitor<Hlpr, Vis>::
|
||||
_insert_at_vertices(const X_monotone_curve_2& cv,
|
||||
Halfedge_handle prev1, Halfedge_handle prev2,
|
||||
Subcurve* sc, bool& new_face_created)
|
||||
{
|
||||
Subcurve* sc, bool& new_face_created) {
|
||||
// Perform the insertion.
|
||||
new_face_created = false;
|
||||
bool swapped_predecessors = false;
|
||||
|
|
@ -632,8 +618,7 @@ _insert_at_vertices(const X_monotone_curve_2& cv,
|
|||
template <typename Hlpr, typename Vis>
|
||||
typename Arr_no_intersection_insertion_ss_visitor<Hlpr, Vis>::Face_handle
|
||||
Arr_no_intersection_insertion_ss_visitor<Hlpr, Vis>::
|
||||
_ray_shoot_up(Status_line_iterator iter)
|
||||
{
|
||||
_ray_shoot_up(Status_line_iterator iter) {
|
||||
// Go up the status line and try to locate a curve which is associated
|
||||
// with a valid arrangement halfedge.
|
||||
const Halfedge_handle invalid_he;
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
//
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ron Wein <wein@post.tau.ac.il>
|
||||
// Efi Fogel <efif@post.tau.ac.il>
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ron Wein <wein@post.tau.ac.il>
|
||||
// Efi Fogel <efif@post.tau.ac.il>
|
||||
|
||||
#ifndef CGAL_ARR_OVERLAY_SS_VISITOR_H
|
||||
#define CGAL_ARR_OVERLAY_SS_VISITOR_H
|
||||
|
|
@ -40,92 +40,80 @@ namespace CGAL {
|
|||
* arrangement, creating a result arrangement. All three arrangements are
|
||||
* embedded on the same type of surface and use the same geometry traits.
|
||||
*/
|
||||
template <typename OverlayHelper, typename OverlayTraits,
|
||||
typename Visitor_ = Default>
|
||||
template <typename OverlayHelper, typename OverlayTraits, typename Visitor_ = Default>
|
||||
class Arr_overlay_ss_visitor :
|
||||
public Arr_construction_ss_visitor<
|
||||
typename OverlayHelper::Construction_helper,
|
||||
typename Default::Get<Visitor_,
|
||||
Arr_overlay_ss_visitor<OverlayHelper, OverlayTraits,
|
||||
Visitor_> >::type>
|
||||
{
|
||||
Arr_overlay_ss_visitor<OverlayHelper, OverlayTraits, Visitor_> >::type> {
|
||||
public:
|
||||
typedef OverlayHelper Overlay_helper;
|
||||
typedef OverlayTraits Overlay_traits;
|
||||
using Overlay_helper = OverlayHelper;
|
||||
using Overlay_traits = OverlayTraits;
|
||||
|
||||
typedef typename Overlay_helper::Geometry_traits_2 Geometry_traits_2;
|
||||
typedef typename Overlay_helper::Event Event;
|
||||
typedef typename Overlay_helper::Subcurve Subcurve;
|
||||
using Geometry_traits_2 = typename Overlay_helper::Geometry_traits_2;
|
||||
using Event = typename Overlay_helper::Event;
|
||||
using Subcurve = typename Overlay_helper::Subcurve;
|
||||
|
||||
typedef typename Overlay_helper::Arrangement_red_2 Arrangement_red_2;
|
||||
typedef typename Overlay_helper::Arrangement_blue_2 Arrangement_blue_2;
|
||||
|
||||
typedef typename Overlay_helper::Construction_helper Construction_helper;
|
||||
using Arrangement_red_2 = typename Overlay_helper::Arrangement_red_2;
|
||||
using Arrangement_blue_2 = typename Overlay_helper::Arrangement_blue_2;
|
||||
|
||||
using Construction_helper = typename Overlay_helper::Construction_helper;
|
||||
|
||||
private:
|
||||
typedef Geometry_traits_2 Gt2;
|
||||
typedef Arrangement_red_2 Ar2;
|
||||
typedef Arrangement_blue_2 Ab2;
|
||||
using Gt2 = Geometry_traits_2;
|
||||
using Ar2 = Arrangement_red_2;
|
||||
using Ab2 = Arrangement_blue_2;
|
||||
|
||||
typedef Arr_overlay_ss_visitor<Overlay_helper, Overlay_traits, Visitor_>
|
||||
Self;
|
||||
typedef typename Default::Get<Visitor_, Self>::type Visitor;
|
||||
typedef Arr_construction_ss_visitor<Construction_helper, Visitor>
|
||||
Base;
|
||||
using Self = Arr_overlay_ss_visitor<Overlay_helper, Overlay_traits, Visitor_>;
|
||||
using Visitor = typename Default::Get<Visitor_, Self>::type;
|
||||
using Base = Arr_construction_ss_visitor<Construction_helper, Visitor>;
|
||||
|
||||
public:
|
||||
typedef typename Gt2::X_monotone_curve_2 X_monotone_curve_2;
|
||||
typedef typename Gt2::Point_2 Point_2;
|
||||
using X_monotone_curve_2 = typename Gt2::X_monotone_curve_2;
|
||||
using Point_2 = typename Gt2::Point_2;
|
||||
using Multiplicity = typename Gt2::Multiplicity;
|
||||
|
||||
// The input arrangements (the "red" and the "blue" one):
|
||||
typedef typename Ar2::Halfedge_const_handle Halfedge_handle_red;
|
||||
typedef typename Ar2::Face_const_handle Face_handle_red;
|
||||
typedef typename Ar2::Vertex_const_handle Vertex_handle_red;
|
||||
using Halfedge_handle_red = typename Ar2::Halfedge_const_handle;
|
||||
using Face_handle_red = typename Ar2::Face_const_handle;
|
||||
using Vertex_handle_red = typename Ar2::Vertex_const_handle;
|
||||
|
||||
typedef typename Ab2::Halfedge_const_handle Halfedge_handle_blue;
|
||||
typedef typename Ab2::Face_const_handle Face_handle_blue;
|
||||
typedef typename Ab2::Vertex_const_handle Vertex_handle_blue;
|
||||
using Halfedge_handle_blue = typename Ab2::Halfedge_const_handle;
|
||||
using Face_handle_blue = typename Ab2::Face_const_handle;
|
||||
using Vertex_handle_blue = typename Ab2::Vertex_const_handle;
|
||||
|
||||
// The resulting arrangement:
|
||||
typedef typename Overlay_helper::Arrangement_2 Arrangement_2;
|
||||
typedef typename Arrangement_2::Halfedge_handle Halfedge_handle;
|
||||
typedef typename Arrangement_2::Face_handle Face_handle;
|
||||
typedef typename Arrangement_2::Vertex_handle Vertex_handle;
|
||||
typedef typename Arrangement_2::Ccb_halfedge_circulator
|
||||
Ccb_halfedge_circulator;
|
||||
typedef typename Arrangement_2::Outer_ccb_iterator Outer_ccb_iterator;
|
||||
using Arrangement_2 = typename Overlay_helper::Arrangement_2;
|
||||
using Halfedge_handle = typename Arrangement_2::Halfedge_handle;
|
||||
using Face_handle = typename Arrangement_2::Face_handle;
|
||||
using Vertex_handle = typename Arrangement_2::Vertex_handle;
|
||||
using Ccb_halfedge_circulator = typename Arrangement_2::Ccb_halfedge_circulator;
|
||||
using Outer_ccb_iterator = typename Arrangement_2::Outer_ccb_iterator;
|
||||
|
||||
typedef typename Base::Event_subcurve_iterator
|
||||
Event_subcurve_iterator;
|
||||
typedef typename Base::Event_subcurve_reverse_iterator
|
||||
Event_subcurve_reverse_iterator;
|
||||
typedef typename Base::Status_line_iterator Status_line_iterator;
|
||||
using Event_subcurve_iterator = typename Base::Event_subcurve_iterator;
|
||||
using Event_subcurve_reverse_iterator = typename Base::Event_subcurve_reverse_iterator;
|
||||
using Status_line_iterator = typename Base::Status_line_iterator;
|
||||
|
||||
protected:
|
||||
typedef typename Gt2::Cell_handle_red Cell_handle_red;
|
||||
typedef typename Gt2::Optional_cell_red Optional_cell_red;
|
||||
typedef typename Gt2::Cell_handle_blue Cell_handle_blue;
|
||||
typedef typename Gt2::Optional_cell_blue Optional_cell_blue;
|
||||
using Cell_handle_red = typename Gt2::Cell_handle_red;
|
||||
using Optional_cell_red = typename Gt2::Optional_cell_red;
|
||||
using Cell_handle_blue = typename Gt2::Cell_handle_blue;
|
||||
using Optional_cell_blue = typename Gt2::Optional_cell_blue;
|
||||
|
||||
typedef std::pair<Halfedge_handle_red, Halfedge_handle_blue>
|
||||
Halfedge_info;
|
||||
typedef Unique_hash_map<Halfedge_handle, Halfedge_info>
|
||||
Halfedge_map;
|
||||
using Halfedge_info = std::pair<Halfedge_handle_red, Halfedge_handle_blue>;
|
||||
using Halfedge_map = Unique_hash_map<Halfedge_handle, Halfedge_info>;
|
||||
|
||||
typedef std::pair<Cell_handle_red, Cell_handle_blue> Handle_info;
|
||||
typedef std::unordered_map<Vertex_handle, Handle_info, Handle_hash_function>
|
||||
Vertex_map;
|
||||
using Handle_info = std::pair<Cell_handle_red, Cell_handle_blue>;
|
||||
using Vertex_map = std::unordered_map<Vertex_handle, Handle_info, Handle_hash_function>;
|
||||
|
||||
// Side categoties:
|
||||
typedef typename Gt2::Left_side_category Left_side_category;
|
||||
typedef typename Gt2::Bottom_side_category Bottom_side_category;
|
||||
typedef typename Gt2::Top_side_category Top_side_category;
|
||||
typedef typename Gt2::Right_side_category Right_side_category;
|
||||
using Left_side_category = typename Gt2::Left_side_category;
|
||||
using Bottom_side_category = typename Gt2::Bottom_side_category;
|
||||
using Top_side_category = typename Gt2::Top_side_category;
|
||||
using Right_side_category = typename Gt2::Right_side_category;
|
||||
|
||||
typedef typename Arr_has_identified_sides<Left_side_category,
|
||||
Bottom_side_category>::result
|
||||
Has_identified_sides_category;
|
||||
using Has_identified_sides_category =
|
||||
typename Arr_has_identified_sides<Left_side_category, Bottom_side_category>::result;
|
||||
|
||||
// Data members:
|
||||
Overlay_traits* m_overlay_traits; // The overlay traits object.
|
||||
|
|
@ -195,10 +183,9 @@ public:
|
|||
void update_event(Event* /* e */,
|
||||
Subcurve* /* c1 */,
|
||||
Subcurve* /* c2 */,
|
||||
bool CGAL_assertion_code(is_new))
|
||||
{
|
||||
CGAL_assertion(is_new == true);
|
||||
}
|
||||
bool CGAL_assertion_code(is_new),
|
||||
Multiplicity /* multiplicity */)
|
||||
{ CGAL_assertion(is_new == true); }
|
||||
|
||||
/*! Update an event. */
|
||||
void update_event(Event* e, Subcurve* sc);
|
||||
|
|
@ -407,9 +394,8 @@ protected:
|
|||
//-----------------------------------------------------------------------------
|
||||
// A notification issued before the sweep process starts.
|
||||
//
|
||||
template <typename OvlHlpr, typename OvlTr, typename Vis>
|
||||
void Arr_overlay_ss_visitor<OvlHlpr, OvlTr, Vis>::before_sweep()
|
||||
{
|
||||
template <typename OvlHlpr, typename OvlTr, typename Vis>
|
||||
void Arr_overlay_ss_visitor<OvlHlpr, OvlTr, Vis>::before_sweep() {
|
||||
// Initialize the necessary fields in the base construction visitor.
|
||||
// Note that the construction visitor also informs its helper class that
|
||||
// the sweep process is about to start.
|
||||
|
|
@ -425,8 +411,7 @@ protected:
|
|||
//
|
||||
template <typename OvlHlpr, typename OvlTr, typename Vis>
|
||||
void
|
||||
Arr_overlay_ss_visitor<OvlHlpr, OvlTr, Vis>::before_handle_event(Event* event)
|
||||
{
|
||||
Arr_overlay_ss_visitor<OvlHlpr, OvlTr, Vis>::before_handle_event(Event* event) {
|
||||
// Let the base construction visitor do the work (and also inform its helper
|
||||
// class on the event).
|
||||
Base::before_handle_event(event);
|
||||
|
|
@ -441,8 +426,7 @@ Arr_overlay_ss_visitor<OvlHlpr, OvlTr, Vis>::before_handle_event(Event* event)
|
|||
//
|
||||
template <typename OvlHlpr, typename OvlTr, typename Vis>
|
||||
bool Arr_overlay_ss_visitor<OvlHlpr, OvlTr, Vis>::
|
||||
after_handle_event(Event* event, Status_line_iterator iter, bool flag)
|
||||
{
|
||||
after_handle_event(Event* event, Status_line_iterator iter, bool flag) {
|
||||
// Let the base construction visitor handle the event.
|
||||
bool res = Base::after_handle_event(event, iter, flag);
|
||||
|
||||
|
|
@ -497,8 +481,7 @@ update_event(Event* e,
|
|||
const Point_2& end_point,
|
||||
const X_monotone_curve_2& /* cv */,
|
||||
Arr_curve_end /* cv_end */,
|
||||
bool /* is_new */)
|
||||
{
|
||||
bool /* is_new */) {
|
||||
// Nothing to do in case of an event at infinity.
|
||||
CGAL_assertion(e->is_closed());
|
||||
|
||||
|
|
@ -513,8 +496,7 @@ update_event(Event* e,
|
|||
//
|
||||
template <typename OvlHlpr, typename OvlTr, typename Vis>
|
||||
void Arr_overlay_ss_visitor<OvlHlpr, OvlTr, Vis>::update_event(Event* e,
|
||||
Subcurve* sc)
|
||||
{
|
||||
Subcurve* sc) {
|
||||
// Update the red and blue halfedges associated with the point as necessary.
|
||||
Point_2& pt = e->point();
|
||||
|
||||
|
|
@ -538,8 +520,7 @@ template <typename OvlHlpr, typename OvlTr, typename Vis>
|
|||
void
|
||||
Arr_overlay_ss_visitor<OvlHlpr, OvlTr, Vis>::update_event(Event* e,
|
||||
const Point_2& p,
|
||||
bool /* is_new */)
|
||||
{
|
||||
bool /* is_new */) {
|
||||
// Update the red and blue objects associated with the point as necessary.
|
||||
Point_2& pt = e->point();
|
||||
if (pt.is_red_cell_empty()) pt.set_red_cell(p.red_cell());
|
||||
|
|
@ -550,8 +531,7 @@ Arr_overlay_ss_visitor<OvlHlpr, OvlTr, Vis>::update_event(Event* e,
|
|||
// A notification issued when the sweep process has ended.
|
||||
//
|
||||
template <typename OvlHlpr, typename OvlTr, typename Vis>
|
||||
void Arr_overlay_ss_visitor<OvlHlpr, OvlTr, Vis>::after_sweep()
|
||||
{
|
||||
void Arr_overlay_ss_visitor<OvlHlpr, OvlTr, Vis>::after_sweep() {
|
||||
Base::after_sweep();
|
||||
|
||||
// Notify boundary vertices:
|
||||
|
|
@ -580,8 +560,7 @@ void Arr_overlay_ss_visitor<OvlHlpr, OvlTr, Vis>::after_sweep()
|
|||
template <typename OvlHlpr, typename OvlTr, typename Vis>
|
||||
typename Arr_overlay_ss_visitor<OvlHlpr, OvlTr, Vis>::Halfedge_handle
|
||||
Arr_overlay_ss_visitor<OvlHlpr, OvlTr, Vis>::
|
||||
insert_in_face_interior(const X_monotone_curve_2& cv, Subcurve* sc)
|
||||
{
|
||||
insert_in_face_interior(const X_monotone_curve_2& cv, Subcurve* sc) {
|
||||
// Insert the halfedge using the base construction visitor.
|
||||
Halfedge_handle new_he = Base::insert_in_face_interior(cv, sc);
|
||||
_map_halfedge_and_twin(new_he,
|
||||
|
|
@ -615,8 +594,7 @@ typename Arr_overlay_ss_visitor<OvlHlpr, OvlTr, Vis>::Halfedge_handle
|
|||
Arr_overlay_ss_visitor<OvlHlpr, OvlTr, Vis>::
|
||||
insert_from_left_vertex(const X_monotone_curve_2& cv,
|
||||
Halfedge_handle prev,
|
||||
Subcurve* sc)
|
||||
{
|
||||
Subcurve* sc) {
|
||||
_map_boundary_vertices(this->last_event_on_subcurve(sc), prev->target(),
|
||||
Has_identified_sides_category());
|
||||
|
||||
|
|
@ -647,8 +625,7 @@ typename Arr_overlay_ss_visitor<OvlHlpr, OvlTr, Vis>::Halfedge_handle
|
|||
Arr_overlay_ss_visitor<OvlHlpr, OvlTr, Vis>::
|
||||
insert_from_right_vertex(const X_monotone_curve_2& cv,
|
||||
Halfedge_handle prev,
|
||||
Subcurve* sc)
|
||||
{
|
||||
Subcurve* sc) {
|
||||
_map_boundary_vertices(this->current_event(), prev->target(),
|
||||
Has_identified_sides_category());
|
||||
|
||||
|
|
@ -680,8 +657,7 @@ insert_at_vertices(const X_monotone_curve_2& cv,
|
|||
Halfedge_handle prev1,
|
||||
Halfedge_handle prev2,
|
||||
Subcurve* sc,
|
||||
bool& new_face_created)
|
||||
{
|
||||
bool& new_face_created) {
|
||||
// Insert the halfedge using the base construction visitor. Note that the
|
||||
// resulting halfedge is always incident to the new face (if one created).
|
||||
Halfedge_handle new_he =
|
||||
|
|
@ -795,8 +771,7 @@ template <typename OvlHlpr, typename OvlTr, typename Vis>
|
|||
typename Arr_overlay_ss_visitor<OvlHlpr, OvlTr, Vis>::Vertex_handle
|
||||
Arr_overlay_ss_visitor<OvlHlpr, OvlTr, Vis>::
|
||||
insert_isolated_vertex(const Point_2& pt,
|
||||
Status_line_iterator iter)
|
||||
{
|
||||
Status_line_iterator iter) {
|
||||
// Insert the isolated vertex using the base construction visitor.
|
||||
Vertex_handle new_v = Base::insert_isolated_vertex(pt, iter);
|
||||
|
||||
|
|
@ -897,14 +872,13 @@ template <typename OvlHlpr, typename OvlTr, typename Vis>
|
|||
void Arr_overlay_ss_visitor<OvlHlpr, OvlTr, Vis>::
|
||||
_map_halfedge_and_twin(Halfedge_handle he,
|
||||
Halfedge_handle_red red_he,
|
||||
Halfedge_handle_blue blue_he)
|
||||
{
|
||||
Halfedge_handle_blue blue_he) {
|
||||
if (he->direction() == ARR_LEFT_TO_RIGHT) he = he->twin();
|
||||
|
||||
// Obtain the twin red and blue halfedges (if they are valid). Note that
|
||||
// the original halfedges are always directed from right to left.
|
||||
Halfedge_handle_red red_he_twin;
|
||||
Halfedge_handle_blue blue_he_twin;
|
||||
Halfedge_handle_red red_he_twin;
|
||||
Halfedge_handle_blue blue_he_twin;
|
||||
|
||||
if (red_he != Halfedge_handle_red()) red_he_twin = red_he->twin();
|
||||
if (blue_he != Halfedge_handle_blue()) blue_he_twin = blue_he->twin();
|
||||
|
|
@ -922,8 +896,7 @@ _map_halfedge_and_twin(Halfedge_handle he,
|
|||
//
|
||||
template <typename OvlHlpr, typename OvlTr, typename Vis>
|
||||
void Arr_overlay_ss_visitor<OvlHlpr, OvlTr, Vis>::
|
||||
_map_boundary_vertices(Event* event, Vertex_handle v, std::bool_constant<true>)
|
||||
{
|
||||
_map_boundary_vertices(Event* event, Vertex_handle v, std::bool_constant<true>) {
|
||||
// Update the red and blue object if the last event on sc is on the boundary.
|
||||
if ((event->parameter_space_in_x() != ARR_INTERIOR) ||
|
||||
(event->parameter_space_in_y() != ARR_INTERIOR))
|
||||
|
|
@ -938,8 +911,7 @@ _map_boundary_vertices(Event* event, Vertex_handle v, std::bool_constant<true>)
|
|||
if (red_handle_p) info.first = *red_handle_p;
|
||||
|
||||
if (!std::get_if<Face_handle_red>(&(info.first)) &&
|
||||
!std::get_if<Face_handle_blue>(&(info.second)))
|
||||
{
|
||||
!std::get_if<Face_handle_blue>(&(info.second))) {
|
||||
// If both, the red and blue, variants do not represent face handles,
|
||||
// they must represt either vertex or edge handles. In this case it is
|
||||
// safe to apply the call to the overlay traits and erase the record,
|
||||
|
|
@ -974,8 +946,7 @@ void Arr_overlay_ss_visitor<OvlHlpr, OvlTr, Vis>::
|
|||
_create_vertex(Event* event,
|
||||
Vertex_handle new_v,
|
||||
Subcurve* sc,
|
||||
std::bool_constant<true>)
|
||||
{
|
||||
std::bool_constant<true>) {
|
||||
const Point_2& pt = event->point();
|
||||
const Cell_handle_red* red_handle = pt.red_cell_handle();
|
||||
const Cell_handle_blue* blue_handle = pt.blue_cell_handle();
|
||||
|
|
@ -983,8 +954,7 @@ _create_vertex(Event* event,
|
|||
// If the vertex is on the boundary, postpone the notification, but
|
||||
// update the red and objects in case they are empty.
|
||||
if ((event->parameter_space_in_x() != ARR_INTERIOR) ||
|
||||
(event->parameter_space_in_y() != ARR_INTERIOR))
|
||||
{
|
||||
(event->parameter_space_in_y() != ARR_INTERIOR)) {
|
||||
if (!red_handle) {
|
||||
CGAL_assertion(blue_handle != nullptr);
|
||||
// Obtain the red face by looking for a subcurve above.
|
||||
|
|
@ -1020,8 +990,7 @@ void Arr_overlay_ss_visitor<OvlHlpr, OvlTr, Vis>::
|
|||
_create_vertex(Event* event,
|
||||
Vertex_handle new_v,
|
||||
Subcurve* sc,
|
||||
std::bool_constant<false>)
|
||||
{
|
||||
std::bool_constant<false>) {
|
||||
const Point_2& pt = event->point();
|
||||
const Cell_handle_red* red_handle = pt.red_cell_handle();
|
||||
const Cell_handle_blue* blue_handle = pt.blue_cell_handle();
|
||||
|
|
@ -1063,8 +1032,7 @@ _create_vertex(Event* event,
|
|||
template <typename OvlHlpr, typename OvlTr, typename Vis>
|
||||
void Arr_overlay_ss_visitor<OvlHlpr, OvlTr, Vis>::
|
||||
_create_edge(Subcurve* sc,
|
||||
Halfedge_handle new_he)
|
||||
{
|
||||
Halfedge_handle new_he) {
|
||||
// Note that the "red" and "blue" halfedges are always directed from right
|
||||
// to left, so we make sure the overlaid halfedge is also directed from
|
||||
// right to left.
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -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()
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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`.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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`
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
@ -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>();
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -700,15 +700,29 @@ swap its source and target points).
|
|||
The traits classes `Arr_segment_traits_2`,
|
||||
`Arr_non_caching_segment_traits_2`, `Arr_circle_segment_traits_2`,
|
||||
`Arr_conic_traits_2` and `Arr_rational_function_traits_2`, which are
|
||||
bundled in the `Arrangement_2` package and distributed with \cgal,
|
||||
are all models of the refined concept
|
||||
`AosDirectionalXMonotoneTraits_2`.\cgalFootnote{The \cgalFootnoteCode{Arr_polyline_traits_2} class is <I>not</I> a model of the, \cgalFootnoteCode{AosDirectionalXMonotoneTraits_2} concept, as the \f$ x\f$-monotone curve it defines is always directed from left to right. Thus, an opposite curve cannot be constructed. However, it is not very useful to construct a polygon whose edges are polylines, as an ordinary polygon with linear edges can represent the same entity.}
|
||||
bundled in the `Arrangement_2` package and distributed with \cgal, are
|
||||
all models of the refined concept
|
||||
`AosDirectionalXMonotoneTraits_2`.\cgalFootnote{The
|
||||
\cgalFootnoteCode{Arr_polyline_traits_2} class is <I>not</I> a model
|
||||
of the, \cgalFootnoteCode{AosDirectionalXMonotoneTraits_2} concept, as
|
||||
the \f$ x\f$-monotone curve it defines is always directed from left to
|
||||
right. Thus, an opposite curve cannot be constructed. However, it is
|
||||
not very useful to construct a polygon whose edges are polylines, as
|
||||
an ordinary polygon with linear edges can represent the same entity.}
|
||||
|
||||
Just as with the case of computations using models of the
|
||||
`AosXMonotoneTraits_2` concept, operations are robust only
|
||||
when exact arithmetic is used. When inexact arithmetic is used,
|
||||
(nearly) degenerate configurations may result in abnormal termination
|
||||
of the program or even incorrect results.
|
||||
Operations on polygons (or general polygons) are guaranteed to be
|
||||
robust only if the operations of the geometry traits used to carry out
|
||||
the high-level operations are robust. Most operations on polygons use
|
||||
geometry traits constructors, as they generate new polygons; such
|
||||
constructors are guaranteed to be robust only if the kernel in use
|
||||
supports exact constructions, such as the EPEC (Exact Predicate Exact
|
||||
Construction) kernel. The `do_intersect()` overloaded predicates that
|
||||
operate on (linear) polygons are exceptions, as they only use geometry
|
||||
traits predicates; such predicates are guaranteed to be robust only if
|
||||
the kernel in use supports exact predicates, such as the EPIC (Exact
|
||||
Predicate Inexact Construction) kernel. When inexact arithmetic is
|
||||
used, (nearly) degenerate configurations may result in abnormal
|
||||
termination of the program or even incorrect results.
|
||||
|
||||
\subsection bso_sseccirc_seg Operating on Polygons with Circular Arcs
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,10 @@ namespace CGAL {
|
|||
* <tr><td align="right"><b>2.</b></td><td>`void complement(const Type1& pgn, Type2& res, const GpsTraits& traits);`</td></tr>
|
||||
* </table>
|
||||
*
|
||||
* \tparam Kernel a model of the concept `PolygonTraits_2`.
|
||||
* \tparam Container a model of the concept `Container`; defaults to `std::vector<Kernel::Point_2`>.
|
||||
* \tparam ArrTraits a model of the concept `AosDirectionalXMonotoneTraits_2`.
|
||||
* \tparam GpsTraits a model of the concept `GeneralPolygonSetTraits_2`, which must be convertible to `ArrTraits`.
|
||||
* \tparam UsePolylines determines whether the boundary of the input polygon is
|
||||
* treated as a cyclic sequence of single (\f$x\f$-monotone) segments or as a
|
||||
* cyclic sequence of (\f$x\f$-monotone) polylines. If substituted with
|
||||
|
|
@ -28,7 +32,7 @@ namespace CGAL {
|
|||
* to a standard polygon. If substituted with `CGAL::Tag_false`, the input
|
||||
* polygon is used as is. Refer to \ref bso_ssectraits_sel for more information.
|
||||
*
|
||||
* - The types `Type` and `Type2` of the parameters must be convertible to the
|
||||
* - The types `Type1` and `Type2` of the parameters must be convertible to the
|
||||
* types specified in a row in the table below, respectively.
|
||||
* - The types that apply to signature (<b>1.1.</b>) above are restricted to those
|
||||
* listed in rows <b>1</b> and <b>2</b> in the table below.
|
||||
|
|
@ -54,6 +58,8 @@ namespace CGAL {
|
|||
* \sa \link boolean_join `CGAL::join()` \endlink
|
||||
* \sa \link boolean_difference `CGAL::difference()` \endlink
|
||||
* \sa \link boolean_symmetric_difference `CGAL::symmetric_difference()` \endlink
|
||||
* \sa Polygon_2<Kernel, Container>
|
||||
* \sa Polygon_with_holes_2<Kernel, Container>
|
||||
*/
|
||||
|
||||
/// @{
|
||||
|
|
@ -224,6 +230,10 @@ namespace CGAL {
|
|||
* <tr><td align="right"><b>2.</b></td><td>`OutputIterator difference(const Type1& pgn1, const Type2& pgn2, OutputIterator oi, const GpsTraits& traits);`</td></tr>
|
||||
* </table>
|
||||
*
|
||||
* \tparam Kernel a model of the concept `PolygonTraits_2`
|
||||
* \tparam Container a model of the concept `Container`; defaults to `std::vector<Kernel::Point_2`>.
|
||||
* \tparam ArrTraits a model of the concept `AosDirectionalXMonotoneTraits_2`
|
||||
* \tparam GpsTraits a model of the concept `GeneralPolygonSetTraits_2`, which must be convertible to `ArrTraits`.
|
||||
* \tparam UsePolylines determines whether the boundaries of the input polygons
|
||||
* are treated as cyclic sequences of single (\f$x\f$-monotone) segments or as
|
||||
* cyclic sequences of (\f$x\f$-monotone) polylines. If substituted with
|
||||
|
|
@ -264,6 +274,8 @@ namespace CGAL {
|
|||
* \sa \link boolean_intersection `CGAL::intersection()` \endlink
|
||||
* \sa \link boolean_join `CGAL::join()` \endlink
|
||||
* \sa \link boolean_symmetric_difference `CGAL::symmetric_difference()` \endlink
|
||||
* \sa Polygon_2<Kernel, Container>
|
||||
* \sa Polygon_with_holes_2<Kernel, Container>
|
||||
*/
|
||||
|
||||
/// @{
|
||||
|
|
@ -660,48 +672,22 @@ namespace CGAL {
|
|||
* A function template in this group that accepts two input polygons has one of
|
||||
* the following signatures:
|
||||
* <table cellpadding=3 border="0">
|
||||
* <tr><td align="right"><b>1.1.</b></td><td>`bool do_intersect(const Type1& pgn1, const Type2& pgn2, UsePolylines = Tag_true());`</td></tr>
|
||||
* <tr><td align="right"><b>1.2.</b></td><td>`bool do_intersect(const Type1& pgn1, const Type2& pgn2);`</td></tr>
|
||||
* <tr><td align="right"><b> 2.</b></td><td>`bool do_intersect(const Type1& pgn1, const Type2& pgn2, const GpsTraits& traits);`</td></tr>
|
||||
* <tr><td align="right"><b>1.</b></td><td>`bool do_intersect(const Type1& pgn1, const Type2& pgn2);`</td></tr>
|
||||
* <tr><td align="right"><b>2.</b></td><td>`bool do_intersect(const Type1& pgn1, const Type2& pgn2, const GpsTraits& traits);`</td></tr>
|
||||
* </table>
|
||||
*
|
||||
* There are also function templates that accept one or two ranges of input polygons:
|
||||
* <table cellpadding=3 border="0">
|
||||
* <tr><td align="right"><b>3.1.</b></td><td>`bool do_intersect(InputIterator begin, InputIterator end, UsePolylines = Tag_true());`</td></tr>
|
||||
* <tr><td align="right"><b>3.2.</b></td><td>`bool do_intersect(InputIterator begin, InputIterator end);`</td></tr>
|
||||
* <tr><td align="right"><b> 4.</b></td><td>`bool do_intersect(InputIterator begin, InputIterator end, const GpsTraits& traits);`</td></tr>
|
||||
* <tr><td align="right"><b>5.1.</b></td><td>`bool do_intersect(InputIterator1 begin1, InputIterator1 end1, InputIterator2 begin2, InputIterator2 end2, UsePolylines = Tag_true());`</td></tr>
|
||||
* <tr><td align="right"><b>5.2.</b></td><td>`bool do_intersect(InputIterator1 begin1, InputIterator1 end1, InputIterator2 begin2, InputIterator2 end2);`</td></tr>
|
||||
* <tr><td align="right"><b> 6.</b></td><td>`bool do_intersect(InputIterator1 begin1, InputIterator1 end1, InputIterator2 begin2, InputIterator2 end2, const GpsTraits& traits);`</td></tr>
|
||||
* <tr><td align="right"><b>3.</b></td><td>`bool do_intersect(InputIterator begin, InputIterator end);`</td></tr>
|
||||
* <tr><td align="right"><b>4.</b></td><td>`bool do_intersect(InputIterator begin, InputIterator end, const GpsTraits& traits);`</td></tr>
|
||||
* <tr><td align="right"><b>5.</b></td><td>`bool do_intersect(InputIterator1 begin1, InputIterator1 end1, InputIterator2 begin2, InputIterator2 end2);`</td></tr>
|
||||
* <tr><td align="right"><b>6.</b></td><td>`bool do_intersect(InputIterator1 begin1, InputIterator1 end1, InputIterator2 begin2, InputIterator2 end2, const GpsTraits& traits);`</td></tr>
|
||||
* </table>
|
||||
*
|
||||
* \tparam UsePolylines determines whether the boundary of the input polygons
|
||||
* are treated as a cyclic sequence of single (\f$x\f$-monotone) segments or as
|
||||
* a cyclic sequence of (\f$x\f$-monotone) polylines. If substituted with
|
||||
* `CGAL::Tag_true`, which is the default, the input polygons are converted to
|
||||
* general polygons bounded by polylines before the operation is actually
|
||||
* performed. If substituted with `CGAL::Tag_false`, the input polygons are used
|
||||
* as is. Refer to \ref bso_ssectraits_sel for more information.
|
||||
*
|
||||
* - The types `Type1` and `Type2` of the parameters of
|
||||
* `InputIterator1::value_type` and `InputIterator2::value_type` must be
|
||||
* convertible to the types specified in a row in the table below,
|
||||
* respectively.
|
||||
*
|
||||
* - The types that apply to signatures (<b>1.1.</b>) and (<b>5.1.</b>) above
|
||||
* are restricted to those listed in rows <b>1–4</b> in the table
|
||||
* below.
|
||||
*
|
||||
* - The types that apply to signatures (<b>1.2.</b>) and (<b>5.2.</b>) above
|
||||
* are restricted to those listed in rows <b>5–8</b> in the table
|
||||
* below.
|
||||
*
|
||||
* - The type of `InputIterator::value_type` in (<b>3.1.</b>) above
|
||||
* must be convertible to either `Polygon_2` or `Polygon_with_holes_2`.
|
||||
*
|
||||
* - The type of `InputIterator::value_type` in (<b>3.2.</b>) above must be
|
||||
* convertible to either `General_polygon_2` or
|
||||
* `General_polygon_with_holes_2`.
|
||||
* \tparam Kernel a model of the concept `PolygonTraits_2`.
|
||||
* \tparam Container a model of the concept `Container`; defaults to `std::vector<Kernel::Point_2`>.
|
||||
* \tparam ArrTraits a model of the concept `AosDirectionalXMonotoneTraits_2`.
|
||||
* \tparam GpsTraits a model of the concept `GeneralPolygonSetTraits_2`, which must be convertible to `ArrTraits`.
|
||||
*
|
||||
* <div align="left">
|
||||
* <table cellpadding=3 border="1">
|
||||
|
|
@ -728,6 +714,8 @@ namespace CGAL {
|
|||
* \sa \link boolean_join `CGAL::join()` \endlink
|
||||
* \sa \link boolean_difference `CGAL::difference()` \endlink
|
||||
* \sa \link boolean_symmetric_difference `CGAL::symmetric_difference()` \endlink
|
||||
* \sa Polygon_2<Kernel, Container>
|
||||
* \sa Polygon_with_holes_2<Kernel, Container>
|
||||
*/
|
||||
|
||||
/// @{
|
||||
|
|
@ -735,6 +723,11 @@ namespace CGAL {
|
|||
//////// Traits-less
|
||||
|
||||
/*! determines whether two polygons intersect in their interior.
|
||||
*
|
||||
* The kernel used to instantiate the type of the input polygons must support
|
||||
* exact predicates to guarantee correct results; however, inexact constructions
|
||||
* are tolerated.
|
||||
*
|
||||
* \param pgn1 the 1st input polygon.
|
||||
* \param pgn2 the 2nd input polygon.
|
||||
* \return `true` if `pgn1` and `pgn2` intersect in their interior and `false`
|
||||
|
|
@ -745,25 +738,11 @@ bool do_intersect(const Polygon_2<Kernel, Container>& pgn1,
|
|||
const Polygon_2<Kernel, Container>& pgn2);
|
||||
|
||||
/*! determines whether two polygons intersect in their interior.
|
||||
* \tparam UsePolylines determines whether the boundaries of `pgn1` and `pgn2`
|
||||
* are treated as cyclic sequences of single (\f$x\f$-monotone) segments
|
||||
* or as a cyclic sequences of (\f$x\f$-monotone) polylines. If
|
||||
* substituted with `CGAL::Tag_true`, which is the default, `pgn1` and
|
||||
* `pgn2` are converted to general polygons, bounded by polylines
|
||||
* before the operation is actually performed. If substituted with
|
||||
* `CGAL::Tag_false`, `pgn1` and `pgn2` are used as is. Refer to \ref
|
||||
* bso_ssectraits_sel for more information.
|
||||
* \param pgn1 the 1st input polygon.
|
||||
* \param pgn2 the 2nd input polygon.
|
||||
* \return `true` if `pgn1` and `pgn2` intersect in their interior and `false`
|
||||
* otherwise.
|
||||
*/
|
||||
template <typename Kernel, typename Container, typename UsePolylines>
|
||||
bool do_intersect(const Polygon_2<Kernel, Container>& pgn1,
|
||||
const Polygon_2<Kernel, Container>& pgn2,
|
||||
UsePolylines = Tag_true());
|
||||
|
||||
/*! determines whether two polygons intersect in their interior.
|
||||
*
|
||||
* The kernel used to instantiate the type of the input polygons must support
|
||||
* exact predicates to guarantee correct results; however, inexact constructions
|
||||
* are tolerated.
|
||||
*
|
||||
* \param pgn1 the 1st input polygon.
|
||||
* \param pgn2 the 2nd input polygon.
|
||||
* \return `true` if `pgn1` and `pgn2` intersect in their interior and `false`
|
||||
|
|
@ -774,26 +753,11 @@ bool do_intersect(const Polygon_2<Kernel, Container>& pgn1,
|
|||
const Polygon_with_holes_2<Kernel, Container>& pgn2);
|
||||
|
||||
/*! determines whether two polygons intersect in their interior.
|
||||
* \tparam UsePolylines determines whether the boundaries of `pgn1` and `pgn2`
|
||||
* are treated as cyclic sequences of single (\f$x\f$-monotone) segments
|
||||
* or as a cyclic sequences of (\f$x\f$-monotone) polylines. If
|
||||
* substituted with `CGAL::Tag_true`, which is the default, `pgn1` and
|
||||
* `pgn2` are converted to a general polygon and a general polygon
|
||||
* with holes, respectively, bounded by polylines before the operation
|
||||
* is actually performed. If substituted with `CGAL::Tag_false`, `pgn1`
|
||||
* and `pgn2` are used as is. Refer to \ref bso_ssectraits_sel for more
|
||||
* information.
|
||||
* \param pgn1 the 1st input polygon.
|
||||
* \param pgn2 the 2nd input polygon.
|
||||
* \return `true` if `pgn1` and `pgn2` intersect in their interior and `false`
|
||||
* otherwise.
|
||||
*/
|
||||
template <typename Kernel, typename Container, typename UsePolylines>
|
||||
bool do_intersect(const Polygon_2<Kernel, Container>& pgn1,
|
||||
const Polygon_with_holes_2<Kernel, Container>& pgn2,
|
||||
UsePolylines = Tag_true());
|
||||
|
||||
/*! determines whether two polygons intersect in their interior.
|
||||
*
|
||||
* The kernel used to instantiate the type of the input polygons must support
|
||||
* exact predicates to guarantee correct results; however, inexact constructions
|
||||
* are tolerated.
|
||||
*
|
||||
* \param pgn1 the 1st input polygon.
|
||||
* \param pgn2 the 2nd input polygon.
|
||||
* \return `true` if `pgn1` and `pgn2` intersect in their interior and `false`
|
||||
|
|
@ -803,27 +767,12 @@ template <typename Kernel, typename Container>
|
|||
bool do_intersect(const Polygon_with_holes_2<Kernel, Container>& pgn1,
|
||||
const Polygon_2<Kernel, Container>& pgn2);
|
||||
|
||||
/*! determines whether two polygons intersect in their interior.
|
||||
* \tparam UsePolylines determines whether the boundaries of `pgn1` and `pgn2`
|
||||
* are treated as cyclic sequences of single (\f$x\f$-monotone) segments
|
||||
* or as a cyclic sequences of (\f$x\f$-monotone) polylines. If
|
||||
* substituted with `CGAL::Tag_true`, which is the default, `pgn1` and
|
||||
* `pgn2` are converted to a general polygon with holes and a general
|
||||
* polygon, respectively, bounded by polylines before the operation
|
||||
* is actually performed. If substituted with `CGAL::Tag_false`, `pgn1`
|
||||
* and `pgn2` are used as is. Refer to \ref bso_ssectraits_sel for more
|
||||
* information.
|
||||
* \param pgn1 the 1st input polygon.
|
||||
* \param pgn2 the 2nd input polygon.
|
||||
* \return `true` if `pgn1` and `pgn2` intersect in their interior and `false`
|
||||
* otherwise.
|
||||
*/
|
||||
template <typename Kernel, typename Container, typename UsePolylines>
|
||||
bool do_intersect(const Polygon_with_holes_2<Kernel, Container>& pgn1,
|
||||
const Polygon_2<Kernel, Container>& pgn2,
|
||||
UsePolylines = Tag_true());
|
||||
|
||||
/*! determines whether two polygons with holes intersect in their interior.
|
||||
*
|
||||
* The kernel used to instantiate the type of the input polygons must support
|
||||
* exact predicates to guarantee correct results; however, inexact constructions
|
||||
* are tolerated.
|
||||
*
|
||||
* \param pgn1 the 1st input polygon.
|
||||
* \param pgn2 the 2nd input polygon.
|
||||
* \return `true` if `pgn1` and `pgn2` intersect in their interior and `false`
|
||||
|
|
@ -833,25 +782,6 @@ template <typename Kernel, typename Container>
|
|||
bool do_intersect(const Polygon_with_holes_2<Kernel, Container>& pgn1,
|
||||
const Polygon_with_holes_2<Kernel, Container>& pgn2);
|
||||
|
||||
/*! determines whether two polygons with holes intersect in their interior.
|
||||
* \tparam UsePolylines determines whether the boundaries of `pgn1` and `pgn2`
|
||||
* are treated as cyclic sequences of single (\f$x\f$-monotone) segments
|
||||
* or as a cyclic sequences of (\f$x\f$-monotone) polylines. If
|
||||
* substituted with `CGAL::Tag_true`, which is the default, `pgn1` and
|
||||
* `pgn2` are converted to general polygon with holes , bounded by
|
||||
* polylines before the operation is actually performed. If substituted
|
||||
* with `CGAL::Tag_false`, `pgn1` and `pgn2` are used as is. Refer to
|
||||
* \ref bso_ssectraits_sel for more information.
|
||||
* \param pgn1 the 1st input polygon.
|
||||
* \param pgn2 the 2nd input polygon.
|
||||
* \return `true` if `pgn1` and `pgn2` intersect in their interior and `false`
|
||||
* otherwise.
|
||||
*/
|
||||
template <typename Kernel, typename Container, typename UsePolylines>
|
||||
bool do_intersect(const Polygon_with_holes_2<Kernel, Container>& pgn1,
|
||||
const Polygon_with_holes_2<Kernel, Container>& pgn2,
|
||||
UsePolylines = Tag_true());
|
||||
|
||||
/*! determines whether two general polygons intersect in their interior.
|
||||
* \param pgn1 the 1st input polygon.
|
||||
* \param pgn2 the 2nd input polygon.
|
||||
|
|
@ -904,6 +834,13 @@ bool do_intersect(const General_polygon_with_holes_2<Polygon>& pgn1,
|
|||
* of general polygons or a range of general polygons with holes) determines
|
||||
* whether the open polygons (respectively general polygons) in the range have a common
|
||||
* point.
|
||||
*
|
||||
* When the operation is applied to linear polygons (that is, the value type of
|
||||
* the input iterator is either `Polygon_2` or `Polygon_with_holes_2`), the
|
||||
* kernel used to instantiate the type of the input polygons must support exact
|
||||
* predicates to guarantee correct results; however, inexact constructions are
|
||||
* tolerated.
|
||||
*
|
||||
* \param begin the first iterator of the input range. Its value type is
|
||||
* either `Polygon_2` (respectively `General_polygon_2`) or
|
||||
* `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
|
||||
|
|
@ -917,36 +854,16 @@ bool do_intersect(const General_polygon_with_holes_2<Polygon>& pgn1,
|
|||
template <typename InputIterator>
|
||||
bool do_intersect(InputIterator begin, InputIterator end);
|
||||
|
||||
/*! Given a range of polygons or a range of polygons with holes (respectively a range
|
||||
* of general polygons or a range of general polygons with holes) determines
|
||||
* whether the open polygons (respectively general polygons) in the range have a common
|
||||
* point.
|
||||
* \tparam UsePolylines determines whether the boundaries of the polygons in the
|
||||
* input range are treated as cyclic sequences of single
|
||||
* (\f$x\f$-monotone) segments or as a cyclic sequences of
|
||||
* (\f$x\f$-monotone) polylines. If substituted with `CGAL::Tag_true`,
|
||||
* which is the default, the input polygons are converted to general
|
||||
* polygon with holes , bounded by polylines before the operation is
|
||||
* actually performed. If substituted with `CGAL::Tag_false`, `pgn1` and
|
||||
* `pgn2` are used as is. Refer to \ref bso_ssectraits_sel for more
|
||||
* information.
|
||||
* \param begin the first iterator of the input range. Its value type is
|
||||
* either `Polygon_2` (respectively `General_polygon_2`) or
|
||||
* `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
|
||||
* \param end the past-the-end iterator of the input range. Its value type is
|
||||
* either `Polygon_2` (respectively `General_polygon_2`) or
|
||||
* `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
|
||||
* \return `true` if the pairwise intersections of all open polygons or polygons
|
||||
* with holes (respectively general polygons or general polygons with holes) in
|
||||
* the range [*begin,*end) overlap, and `false` otherwise.
|
||||
*/
|
||||
template <typename InputIterator, typename UsePolylines>
|
||||
bool do_intersect(InputIterator begin, InputIterator end,
|
||||
UsePolylines = Tag_true());
|
||||
|
||||
/*! Given a range of polygons (respectively general polygons) and a range of polygons
|
||||
* with holes (respectively general polygons with holes) determines whether the open
|
||||
* polygons (respectively general polygons) in the two ranges have a common point.
|
||||
*
|
||||
* When the operation is applied to linear polygons (that is, the value type of
|
||||
* any input iterator is either `Polygon_2` or `Polygon_with_holes_2`), the
|
||||
* kernel used to instantiate the type of the input polygons must support exact
|
||||
* predicates to guarantee correct results; however, inexact constructions are
|
||||
* tolerated.
|
||||
*
|
||||
* \param begin1 the first iterator of the 1st input range. Its value type is
|
||||
* `Polygon_2` (respectively `General_polygon_2`).
|
||||
* \param end1 the past-the-end iterator of the 1st input range. Its value
|
||||
|
|
@ -964,40 +881,14 @@ template <typename InputIterator1, typename InputIterator2>
|
|||
bool do_intersect(InputIterator1 begin1, InputIterator1 end1,
|
||||
InputIterator2 begin2, InputIterator2 end2);
|
||||
|
||||
/*! Given a range of polygons (respectively general polygons) and a range of polygons
|
||||
* with holes (respectively general polygons with holes) determines whether the open
|
||||
* polygons (respectively general polygons) in the two ranges have a common point.
|
||||
* \tparam UsePolylines determines whether the boundaries of the polygons in the
|
||||
* input ranges are treated as cyclic sequences of single
|
||||
* (\f$x\f$-monotone) segments or as a cyclic sequences of
|
||||
* (\f$x\f$-monotone) polylines. If substituted with `CGAL::Tag_true`,
|
||||
* which is the default, the input polygons are converted to general
|
||||
* polygon with holes , bounded by polylines before the operation is
|
||||
* actually performed. If substituted with `CGAL::Tag_false`, `pgn1` and
|
||||
* `pgn2` are used as is. Refer to \ref bso_ssectraits_sel for more
|
||||
* information.
|
||||
* \param begin1 the first iterator of the 1st input range. Its value type is
|
||||
* `Polygon_2` (respectively `General_polygon_2`).
|
||||
* \param end1 the past-the-end iterator of the 1st input range. Its value
|
||||
* type is `Polygon_2` (respectively `General_polygon_2`).
|
||||
* \param begin2 the first iterator of the 2nd input range. Its value type
|
||||
* is `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
|
||||
* \param end2 the past-the-end iterator of the 2nd input range. Its value
|
||||
* type is `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
|
||||
* \return `true` if the pairwise intersections of all open polygons (respectively
|
||||
* general polygons) and polygons with holes (respectively general polygons with
|
||||
* holes) in the ranges [*begin1,*end1) and [*begin2,*end2),
|
||||
* respectively, overlap, and `false` otherwise.
|
||||
*/
|
||||
template <typename InputIterator1, typename InputIterator2,
|
||||
typename UsePolylines>
|
||||
bool do_intersect(InputIterator1 begin1, InputIterator1 end1,
|
||||
InputIterator2 begin2, InputIterator2 end2,
|
||||
UsePolylines = Tag_true());
|
||||
|
||||
//////// With Traits
|
||||
|
||||
/*! determines whether two polygons intersect in their interior.
|
||||
*
|
||||
* The kernel used to instantiate the type of the input polygons must support
|
||||
* exact predicates to guarantee correct results; however, inexact constructions
|
||||
* are tolerated.
|
||||
*
|
||||
* \param pgn1 the 1st input polygon.
|
||||
* \param pgn2 the 2nd input polygon.
|
||||
* \param traits a traits object.
|
||||
|
|
@ -1011,6 +902,11 @@ bool do_intersect(const Polygon_2<Kernel, Container>& pgn1,
|
|||
const GpsTraits& traits);
|
||||
|
||||
/*! determines whether two polygons intersect in their interior.
|
||||
*
|
||||
* The kernel used to instantiate the type of the input polygons must support
|
||||
* exact predicates to guarantee correct results; however, inexact constructions
|
||||
* are tolerated.
|
||||
*
|
||||
* \param pgn1 the 1st input polygon.
|
||||
* \param pgn2 the 2nd input polygon.
|
||||
* \param traits a traits object.
|
||||
|
|
@ -1021,10 +917,14 @@ bool do_intersect(const Polygon_2<Kernel, Container>& pgn1,
|
|||
template <typename Kernel, typename Container, typename GpsTraits>
|
||||
bool do_intersect(const Polygon_2<Kernel, Container>& pgn1,
|
||||
const Polygon_with_holes_2<Kernel, Container>& pgn2,
|
||||
const GpsTraits& traits,
|
||||
const GpsTraits& traits);
|
||||
|
||||
/*! determines whether two polygons intersect in their interior.
|
||||
*
|
||||
* The kernel used to instantiate the type of the input polygons must support
|
||||
* exact predicates to guarantee correct results; however, inexact constructions
|
||||
* are tolerated.
|
||||
*
|
||||
* \param pgn1 the 1st input polygon.
|
||||
* \param pgn2 the 2nd input polygon.
|
||||
* \param traits a traits object.
|
||||
|
|
@ -1038,6 +938,11 @@ bool do_intersect(const Polygon_with_holes_2<Kernel, Container>& pgn1,
|
|||
const GpsTraits& traits);
|
||||
|
||||
/*! determines whether two polygons with holes intersect in their interior.
|
||||
*
|
||||
* The kernel used to instantiate the type of the input polygons must support
|
||||
* exact predicates to guarantee correct results; however, inexact constructions
|
||||
* are tolerated.
|
||||
*
|
||||
* \param pgn1 the 1st input polygon.
|
||||
* \param pgn2 the 2nd input polygon.
|
||||
* \param traits a traits object.
|
||||
|
|
@ -1116,6 +1021,12 @@ bool do_intersect(const General_polygon_with_holes_2<Polygon>& pgn1,
|
|||
* of general polygons or a range of general polygons with holes) determines
|
||||
* whether the open polygons (respectively general polygons) in the range have a common
|
||||
* point.
|
||||
*
|
||||
* When the operation is applied to linear polygons (that is, the value type of
|
||||
* the input iterator is either `Polygon_2` or `Polygon_with_holes_2`), the
|
||||
* traits parameter `GpsTraits` must support exact predicates to guarantee
|
||||
* correct results; however, inexact constructions are tolerated.
|
||||
*
|
||||
* \param begin the first iterator of the input range. Its value type is
|
||||
* either `Polygon_2` (respectively `General_polygon_2`) or
|
||||
* `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
|
||||
|
|
@ -1135,6 +1046,12 @@ bool do_intersect(InputIterator begin, InputIterator end,
|
|||
/*! Given a range of polygons (respectively general polygons) and a range of polygons
|
||||
* with holes (respectively general polygons with holes) determines whether the open
|
||||
* polygons (respectively general polygons) in the two ranges have a common point.
|
||||
*
|
||||
* When the operation is applied to linear polygons (that is, the value type of
|
||||
* any input iterator is either `Polygon_2` or `Polygon_with_holes_2`), the
|
||||
* traits parameter `GpsTraits` must support exact predicates to guarantee
|
||||
* correct results; however, inexact constructions are tolerated.
|
||||
*
|
||||
* \param begin1 the first iterator of the 1st input range. Its value type is
|
||||
* `Polygon_2` (respectively `General_polygon_2`).
|
||||
* \param end1 the past-the-end iterator of the 1st input range. Its value
|
||||
|
|
@ -1186,6 +1103,10 @@ namespace CGAL {
|
|||
* <tr><td align="right"><b>6.</b></td><td>`OutputIterator intersection(InputIterator1 begin1, InputIterator1 end1, InputIterator2 begin2, InputIterator2 end2, OutputIterator oi, const GpsTraits& traits);`</td></tr>
|
||||
* </table>
|
||||
*
|
||||
* \tparam Kernel a model of the concept `PolygonTraits_2`.
|
||||
* \tparam Container a model of the concept `Container`; defaults to `std::vector<Kernel::Point_2`>.
|
||||
* \tparam ArrTraits a model of the concept `AosDirectionalXMonotoneTraits_2`.
|
||||
* \tparam GpsTraits a model of the concept `GeneralPolygonSetTraits_2`, which must be convertible to `ArrTraits`.
|
||||
* \tparam UsePolylines determines whether the boundaries of the input polygons
|
||||
* are treated as cyclic sequences of single (\f$x\f$-monotone) segments or as
|
||||
* cyclic sequences of (\f$x\f$-monotone) polylines. If substituted with
|
||||
|
|
@ -1244,6 +1165,8 @@ namespace CGAL {
|
|||
* \sa \link boolean_join `CGAL::join()` \endlink
|
||||
* \sa \link boolean_difference `CGAL::difference()` \endlink
|
||||
* \sa \link boolean_symmetric_difference `CGAL::symmetric_difference()` \endlink
|
||||
* \sa Polygon_2<Kernel, Container>
|
||||
* \sa Polygon_with_holes_2<Kernel, Container>
|
||||
*/
|
||||
|
||||
/// @{
|
||||
|
|
@ -1825,6 +1748,10 @@ namespace CGAL {
|
|||
* <tr><td align="right"><b>6.</b></td><td>`OutputIterator join(InputIterator1 begin1, InputIterator1 end1, InputIterator2 begin2, InputIterator2 end2, OutputIterator oi, const GpsTraits& traits);`</td></tr>
|
||||
* </table>
|
||||
*
|
||||
* \tparam Kernel a model of the concept `PolygonTraits_2`.
|
||||
* \tparam Container a model of the concept `Container`; defaults to `std::vector<Kernel::Point_2`>.
|
||||
* \tparam ArrTraits a model of the concept `AosDirectionalXMonotoneTraits_2`.
|
||||
* \tparam GpsTraits a model of the concept `GeneralPolygonSetTraits_2`, which must be convertible to `ArrTraits`.
|
||||
* \tparam UsePolylines determines whether the boundaries of the input polygons
|
||||
* are treated as cyclic sequences of single (\f$x\f$-monotone) segments or as
|
||||
* cyclic sequences of (\f$x\f$-monotone) polylines. If substituted with
|
||||
|
|
@ -1882,6 +1809,8 @@ namespace CGAL {
|
|||
* \sa \link boolean_intersection `CGAL::intersection()` \endlink
|
||||
* \sa \link boolean_difference `CGAL::difference()` \endlink
|
||||
* \sa \link boolean_symmetric_difference `CGAL::symmetric_difference()` \endlink
|
||||
* \sa Polygon_2<Kernel, Container>
|
||||
* \sa Polygon_with_holes_2<Kernel, Container>
|
||||
*/
|
||||
|
||||
/// @{
|
||||
|
|
@ -2407,6 +2336,10 @@ namespace CGAL {
|
|||
* <tr><td align="right"><b> 4.</b></td><td>`Oriented_side oriented_side(const Point_2& p, const Type& pgn, const GpsTraits& traits);`</td></tr>
|
||||
* </table>
|
||||
*
|
||||
* \tparam Kernel a model of the concept `PolygonTraits_2`.
|
||||
* \tparam Container a model of the concept `Container`; defaults to `std::vector<Kernel::Point_2`>.
|
||||
* \tparam ArrTraits a model of the concept `AosDirectionalXMonotoneTraits_2`.
|
||||
* \tparam GpsTraits a model of the concept `GeneralPolygonSetTraits_2`, which must be convertible to `ArrTraits`.
|
||||
* \tparam UsePolylines determines whether the boundaries of the input polygons
|
||||
* are treated as cyclic sequences of single (\f$x\f$-monotone) segments or as
|
||||
* cyclic sequences of (\f$x\f$-monotone) polylines. If substituted with
|
||||
|
|
@ -2446,6 +2379,8 @@ namespace CGAL {
|
|||
* \param traits an optional traits object.
|
||||
*
|
||||
* \sa \link boolean_do_intersect `CGAL::do_intersect()` \endlink
|
||||
* \sa Polygon_2<Kernel, Container>
|
||||
* \sa Polygon_with_holes_2<Kernel, Container>
|
||||
*/
|
||||
|
||||
/// @{
|
||||
|
|
@ -2823,6 +2758,10 @@ namespace CGAL {
|
|||
* <tr><td align="right"><b>6.</b></td><td>`OutputIterator symmetric_difference(InputIterator1 begin1, InputIterator1 end1, InputIterator2 begin2, InputIterator2 end2, OutputIterator oi, const GpsTraits& traits);`</td></tr>
|
||||
* </table>
|
||||
*
|
||||
* \tparam Kernel a model of the concept `PolygonTraits_2`.
|
||||
* \tparam Container a model of the concept `Container`; defaults to `std::vector<Kernel::Point_2`>.
|
||||
* \tparam ArrTraits a model of the concept `AosDirectionalXMonotoneTraits_2`.
|
||||
* \tparam GpsTraits a model of the concept `GeneralPolygonSetTraits_2`, which must be convertible to `ArrTraits`.
|
||||
* \tparam UsePolylines determines whether the boundaries of the input polygons
|
||||
* are treated as cyclic sequences of single (\f$x\f$-monotone) segments or as
|
||||
* cyclic sequences of (\f$x\f$-monotone) polylines. If substituted with
|
||||
|
|
@ -2879,6 +2818,8 @@ namespace CGAL {
|
|||
* \sa \link boolean_intersection `CGAL::intersection()` \endlink
|
||||
* \sa \link boolean_join `CGAL::join()` \endlink
|
||||
* \sa \link boolean_difference `CGAL::difference()` \endlink
|
||||
* \sa Polygon_2<Kernel, Container>
|
||||
* \sa Polygon_with_holes_2<Kernel, Container>
|
||||
*/
|
||||
|
||||
/// @{
|
||||
|
|
|
|||
|
|
@ -5,27 +5,26 @@
|
|||
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
|
||||
#include <CGAL/Boolean_set_operations_2.h>
|
||||
|
||||
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
|
||||
typedef Kernel::Point_2 Point_2;
|
||||
typedef CGAL::Polygon_2<Kernel> Polygon_2;
|
||||
using Kernel = CGAL::Exact_predicates_exact_constructions_kernel;
|
||||
using Point_2 = Kernel::Point_2;
|
||||
using Polygon_2 = CGAL::Polygon_2<Kernel>;
|
||||
|
||||
#include "print_utils.h"
|
||||
|
||||
int main ()
|
||||
{
|
||||
int main() {
|
||||
Polygon_2 P;
|
||||
P.push_back (Point_2 (-1,1));
|
||||
P.push_back (Point_2 (0,-1));
|
||||
P.push_back (Point_2 (1,1));
|
||||
std::cout << "P = "; print_polygon (P);
|
||||
P.push_back(Point_2(-1, 1));
|
||||
P.push_back(Point_2(0, -1));
|
||||
P.push_back(Point_2(1, 1));
|
||||
std::cout << "P = "; print_polygon(P);
|
||||
|
||||
Polygon_2 Q;
|
||||
Q.push_back(Point_2 (-1,-1));
|
||||
Q.push_back(Point_2 (1,-1));
|
||||
Q.push_back(Point_2 (0,1));
|
||||
std::cout << "Q = "; print_polygon (Q);
|
||||
Q.push_back(Point_2(-1, -1));
|
||||
Q.push_back(Point_2(1, -1));
|
||||
Q.push_back(Point_2(0, 1));
|
||||
std::cout << "Q = "; print_polygon(Q);
|
||||
|
||||
if ((CGAL::do_intersect (P, Q)))
|
||||
if ((CGAL::do_intersect(P, Q)))
|
||||
std::cout << "The two polygons intersect in their interior." << std::endl;
|
||||
else
|
||||
std::cout << "The two polygons do not intersect." << std::endl;
|
||||
|
|
|
|||
|
|
@ -8,10 +8,10 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
//
|
||||
// Author(s): Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ron Wein <wein@post.tau.ac.il>
|
||||
// Efi Fogel <efif@post.tau.ac.il>
|
||||
// Simon Giraudot <simon.giraudot@geometryfactory.com>
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ron Wein <wein@post.tau.ac.il>
|
||||
// Efi Fogel <efif@post.tau.ac.il>
|
||||
// Simon Giraudot <simon.giraudot@geometryfactory.com>
|
||||
|
||||
#ifndef CGAL_BSO_INTERNAL_FUNCTIONS_H
|
||||
#define CGAL_BSO_INTERNAL_FUNCTIONS_H
|
||||
|
|
@ -33,7 +33,7 @@ namespace CGAL {
|
|||
|
||||
// Single
|
||||
// With Traits
|
||||
template <typename Pgn1, class Pgn2, typename Traits>
|
||||
template <typename Pgn1, typename Pgn2, typename Traits>
|
||||
inline bool s_do_intersect(const Pgn1& pgn1, const Pgn2& pgn2, Traits& traits) {
|
||||
General_polygon_set_2<Traits> gps(pgn1, traits);
|
||||
return gps.do_intersect(pgn2);
|
||||
|
|
@ -52,7 +52,7 @@ inline bool s_do_intersect(const Pgn1& pgn1, const Pgn2& pgn2) {
|
|||
// With Traits
|
||||
template <typename InputIterator, typename Traits>
|
||||
inline bool r_do_intersect(InputIterator begin, InputIterator end,
|
||||
Traits& traits, unsigned int k=5) {
|
||||
Traits& traits, std::size_t k = 5) {
|
||||
if (begin == end) return false;
|
||||
General_polygon_set_2<Traits> gps(*begin, traits);
|
||||
return gps.do_intersect(std::next(begin), end, k);
|
||||
|
|
@ -61,8 +61,8 @@ inline bool r_do_intersect(InputIterator begin, InputIterator end,
|
|||
// Without Traits
|
||||
template <typename InputIterator>
|
||||
inline bool r_do_intersect(InputIterator begin, InputIterator end,
|
||||
unsigned int k=5) {
|
||||
typedef typename std::iterator_traits<InputIterator>::value_type Pgn;
|
||||
std::size_t k = 5) {
|
||||
using Pgn = typename std::iterator_traits<InputIterator>::value_type;
|
||||
typename Gps_polyline_traits<Pgn>::Traits traits;
|
||||
const typename Gps_polyline_traits<Pgn>::Polyline_traits& ptraits(traits);
|
||||
return r_do_intersect(convert_polygon_iterator(begin, ptraits),
|
||||
|
|
@ -74,7 +74,7 @@ inline bool r_do_intersect(InputIterator begin, InputIterator end,
|
|||
template <typename InputIterator1, typename InputIterator2, typename Traits>
|
||||
inline bool r_do_intersect(InputIterator1 begin1, InputIterator1 end1,
|
||||
InputIterator2 begin2, InputIterator2 end2,
|
||||
Traits& traits, unsigned int k=5) {
|
||||
Traits& traits, std::size_t k = 5) {
|
||||
if (begin1 == end1) return do_intersect(begin2, end2, traits, k);
|
||||
General_polygon_set_2<Traits> gps(*begin1, traits);
|
||||
return gps.do_intersect(std::next(begin1), end1, begin2, end2, k);
|
||||
|
|
@ -84,8 +84,8 @@ inline bool r_do_intersect(InputIterator1 begin1, InputIterator1 end1,
|
|||
template <typename InputIterator1, typename InputIterator2>
|
||||
inline bool r_do_intersect (InputIterator1 begin1, InputIterator1 end1,
|
||||
InputIterator2 begin2, InputIterator2 end2,
|
||||
unsigned int k=5) {
|
||||
typedef typename std::iterator_traits<InputIterator1>::value_type Pgn;
|
||||
std::size_t k = 5) {
|
||||
using Pgn = typename std::iterator_traits<InputIterator1>::value_type;
|
||||
typename Gps_polyline_traits<Pgn>::Traits traits;
|
||||
const typename Gps_polyline_traits<Pgn>::Polyline_traits& ptraits(traits);
|
||||
return r_do_intersect(convert_polygon_iterator(begin1, ptraits),
|
||||
|
|
@ -119,8 +119,7 @@ inline Oriented_side _oriented_side(const Point_2<Kernel>& point,
|
|||
|
||||
// Without Traits (polygon, polygon)
|
||||
template <typename Pgn1, typename Pgn2>
|
||||
inline Oriented_side _oriented_side(const Pgn1& pgn1, const Pgn2& pgn2)
|
||||
{
|
||||
inline Oriented_side _oriented_side(const Pgn1& pgn1, const Pgn2& pgn2) {
|
||||
// Use the first polygon to determine the (default) traits
|
||||
typename Gps_polyline_traits<Pgn1>::Traits traits;
|
||||
const typename Gps_polyline_traits<Pgn1>::Polyline_traits& ptraits(traits);
|
||||
|
|
@ -149,7 +148,7 @@ template <typename Kernel, typename Container,
|
|||
inline OutputIterator s_intersection(const Pgn1& pgn1, const Pgn2& pgn2,
|
||||
OutputIterator oi) {
|
||||
// Use the first polygon to determine the (default) traits
|
||||
typedef typename Gps_polyline_traits<Pgn1>::Polyline_traits Polyline_traits;
|
||||
using Polyline_traits = typename Gps_polyline_traits<Pgn1>::Polyline_traits;
|
||||
|
||||
typename Gps_polyline_traits<Pgn1>::Traits traits;
|
||||
const Polyline_traits& ptraits(traits);
|
||||
|
|
@ -163,7 +162,7 @@ inline OutputIterator s_intersection(const Pgn1& pgn1, const Pgn2& pgn2,
|
|||
template <typename InputIterator, typename OutputIterator, typename Traits>
|
||||
inline OutputIterator r_intersection(InputIterator begin, InputIterator end,
|
||||
OutputIterator oi, Traits& traits,
|
||||
unsigned int k=5) {
|
||||
std::size_t k = 5) {
|
||||
if (begin == end) return (oi);
|
||||
General_polygon_set_2<Traits> gps(*begin, traits);
|
||||
gps.intersection(std::next(begin), end, k);
|
||||
|
|
@ -173,8 +172,8 @@ inline OutputIterator r_intersection(InputIterator begin, InputIterator end,
|
|||
// Without Traits
|
||||
template <typename InputIterator, typename OutputIterator>
|
||||
inline OutputIterator r_intersection(InputIterator begin, InputIterator end,
|
||||
OutputIterator oi, unsigned int k=5) {
|
||||
typedef typename std::iterator_traits<InputIterator>::value_type Pgn;
|
||||
OutputIterator oi, std::size_t k = 5) {
|
||||
using Pgn = typename std::iterator_traits<InputIterator>::value_type;
|
||||
typename Gps_polyline_traits<Pgn>::Traits traits;
|
||||
const typename Gps_polyline_traits<Pgn>::Polyline_traits& ptraits(traits);
|
||||
if (begin == end) return (oi);
|
||||
|
|
@ -190,7 +189,7 @@ template <typename InputIterator1, typename InputIterator2,
|
|||
inline OutputIterator r_intersection(InputIterator1 begin1, InputIterator1 end1,
|
||||
InputIterator2 begin2, InputIterator2 end2,
|
||||
OutputIterator oi, Traits& traits,
|
||||
unsigned int k=5) {
|
||||
std::size_t k = 5) {
|
||||
if (begin1 == end1) return r_intersection(begin2, end2, oi, traits, k);
|
||||
General_polygon_set_2<Traits> gps(*begin1, traits);
|
||||
gps.intersection(std::next(begin1), end1, begin2, end2, k);
|
||||
|
|
@ -203,8 +202,8 @@ template <typename InputIterator1, typename InputIterator2,
|
|||
inline OutputIterator
|
||||
r_intersection(InputIterator1 begin1, InputIterator1 end1,
|
||||
InputIterator2 begin2, InputIterator2 end2,
|
||||
OutputIterator oi, unsigned int k=5) {
|
||||
typedef typename std::iterator_traits<InputIterator1>::value_type Pgn;
|
||||
OutputIterator oi, std::size_t k = 5) {
|
||||
using Pgn = typename std::iterator_traits<InputIterator1>::value_type;
|
||||
typename Gps_polyline_traits<Pgn>::Traits traits;
|
||||
const typename Gps_polyline_traits<Pgn>::Polyline_traits& ptraits(traits);
|
||||
if (begin1 == end1) {
|
||||
|
|
@ -228,7 +227,7 @@ r_intersection(InputIterator1 begin1, InputIterator1 end1,
|
|||
// Polygon_2
|
||||
template <typename Traits>
|
||||
inline bool _is_empty(const typename Traits::Polygon_2& pgn, Traits& traits) {
|
||||
typedef typename Traits::Curve_const_iterator Curve_const_iterator;
|
||||
using Curve_const_iterator = typename Traits::Curve_const_iterator;
|
||||
const std::pair<Curve_const_iterator, Curve_const_iterator>& itr_pair =
|
||||
traits.construct_curves_2_object()(pgn);
|
||||
return (itr_pair.first == itr_pair.second);
|
||||
|
|
@ -268,9 +267,9 @@ template <typename Kernel, typename Container,
|
|||
typename Pgn1, typename Pgn2, typename Pwh>
|
||||
inline bool s_join(const Pgn1& pgn1, const Pgn2& pgn2, Pwh& pwh) {
|
||||
// Use the first polygon to determine the (default) traits
|
||||
typedef typename Gps_polyline_traits<Pgn1>::Polyline_traits Polyline_traits;
|
||||
typedef General_polygon_2<Polyline_traits> General_pgn;
|
||||
typedef General_polygon_with_holes_2<General_pgn> General_pwh;
|
||||
using Polyline_traits = typename Gps_polyline_traits<Pgn1>::Polyline_traits;
|
||||
using General_pgn = General_polygon_2<Polyline_traits>;
|
||||
using General_pwh = General_polygon_with_holes_2<General_pgn>;
|
||||
|
||||
General_pwh general_pwh;
|
||||
typename Gps_polyline_traits<Pgn1>::Traits traits;
|
||||
|
|
@ -287,7 +286,7 @@ inline bool s_join(const Pgn1& pgn1, const Pgn2& pgn2, Pwh& pwh) {
|
|||
template <typename InputIterator, typename OutputIterator, typename Traits>
|
||||
inline OutputIterator r_join(InputIterator begin, InputIterator end,
|
||||
OutputIterator oi, Traits& traits,
|
||||
unsigned int k=5) {
|
||||
std::size_t k = 5) {
|
||||
if (begin == end) return oi;
|
||||
General_polygon_set_2<Traits> gps(*begin, traits);
|
||||
gps.join(std::next(begin), end, k);
|
||||
|
|
@ -297,8 +296,8 @@ inline OutputIterator r_join(InputIterator begin, InputIterator end,
|
|||
// Without traits
|
||||
template <typename InputIterator, typename OutputIterator>
|
||||
inline OutputIterator r_join(InputIterator begin, InputIterator end,
|
||||
OutputIterator oi, unsigned int k=5) {
|
||||
typedef typename std::iterator_traits<InputIterator>::value_type Pgn;
|
||||
OutputIterator oi, std::size_t k = 5) {
|
||||
using Pgn = typename std::iterator_traits<InputIterator>::value_type;
|
||||
typename Gps_polyline_traits<Pgn>::Traits traits;
|
||||
const typename Gps_polyline_traits<Pgn>::Polyline_traits& ptraits(traits);
|
||||
|
||||
|
|
@ -316,7 +315,7 @@ template <typename InputIterator1, typename InputIterator2,
|
|||
inline OutputIterator r_join(InputIterator1 begin1, InputIterator1 end1,
|
||||
InputIterator2 begin2, InputIterator2 end2,
|
||||
OutputIterator oi, Traits& traits,
|
||||
unsigned int k=5) {
|
||||
std::size_t k = 5) {
|
||||
if (begin1 == end1) return r_join(begin2, end2, oi, traits, k);
|
||||
General_polygon_set_2<Traits> gps(*begin1, traits);
|
||||
gps.join(std::next(begin1), end1, begin2, end2, k);
|
||||
|
|
@ -328,8 +327,8 @@ template <typename InputIterator1, typename InputIterator2,
|
|||
typename OutputIterator>
|
||||
inline OutputIterator r_join(InputIterator1 begin1, InputIterator1 end1,
|
||||
InputIterator2 begin2, InputIterator2 end2,
|
||||
OutputIterator oi, unsigned int k=5) {
|
||||
typedef typename std::iterator_traits<InputIterator1>::value_type Pgn;
|
||||
OutputIterator oi, std::size_t k = 5) {
|
||||
using Pgn = typename std::iterator_traits<InputIterator1>::value_type;
|
||||
typename Gps_polyline_traits<Pgn>::Traits traits;
|
||||
const typename Gps_polyline_traits<Pgn>::Polyline_traits& ptraits(traits);
|
||||
if (begin1 == end1) {
|
||||
|
|
@ -361,10 +360,9 @@ inline OutputIterator _difference(const Pgn1& pgn1, const Pgn2& pgn2,
|
|||
template <typename Kernel, typename Container,
|
||||
typename Pgn1, typename Pgn2, typename OutputIterator>
|
||||
inline OutputIterator _difference(const Pgn1& pgn1, const Pgn2& pgn2,
|
||||
OutputIterator oi)
|
||||
{
|
||||
OutputIterator oi) {
|
||||
// Use the first polygon to determine the (default) traits
|
||||
typedef typename Gps_polyline_traits<Pgn1>::Polyline_traits Polyline_traits;
|
||||
using Polyline_traits = typename Gps_polyline_traits<Pgn1>::Polyline_traits;
|
||||
|
||||
typename Gps_polyline_traits<Pgn1>::Traits traits;
|
||||
const Polyline_traits& ptraits(traits);
|
||||
|
|
@ -394,7 +392,7 @@ template <typename Kernel, typename Container,
|
|||
inline OutputIterator s_symmetric_difference(const Pgn1& pgn1, const Pgn2& pgn2,
|
||||
OutputIterator oi) {
|
||||
// Use the first polygon to determine the (default) traits
|
||||
typedef typename Gps_polyline_traits<Pgn1>::Polyline_traits Polyline_traits;
|
||||
using Polyline_traits = typename Gps_polyline_traits<Pgn1>::Polyline_traits;
|
||||
typename Gps_polyline_traits<Pgn1>::Traits traits;
|
||||
const Polyline_traits& ptraits(traits);
|
||||
s_symmetric_difference(convert_polygon(pgn1, ptraits),
|
||||
|
|
@ -409,7 +407,7 @@ template <typename InputIterator, typename OutputIterator, typename Traits>
|
|||
inline
|
||||
OutputIterator r_symmetric_difference(InputIterator begin, InputIterator end,
|
||||
OutputIterator oi, Traits& traits,
|
||||
unsigned int k=5) {
|
||||
std::size_t k = 5) {
|
||||
if (begin == end) return (oi);
|
||||
General_polygon_set_2<Traits> gps(*begin, traits);
|
||||
gps.symmetric_difference(std::next(begin), end, k);
|
||||
|
|
@ -421,9 +419,8 @@ template <typename InputIterator, typename OutputIterator>
|
|||
inline OutputIterator r_symmetric_difference(InputIterator begin,
|
||||
InputIterator end,
|
||||
OutputIterator oi,
|
||||
unsigned int k=5)
|
||||
{
|
||||
typedef typename std::iterator_traits<InputIterator>::value_type Pgn;
|
||||
std::size_t k = 5) {
|
||||
using Pgn = typename std::iterator_traits<InputIterator>::value_type;
|
||||
typename Gps_polyline_traits<Pgn>::Traits traits;
|
||||
const typename Gps_polyline_traits<Pgn>::Polyline_traits& ptraits(traits);
|
||||
if (begin == end) return (oi);
|
||||
|
|
@ -441,8 +438,7 @@ inline OutputIterator r_symmetric_difference(InputIterator1 begin1,
|
|||
InputIterator2 begin2,
|
||||
InputIterator2 end2,
|
||||
OutputIterator oi, Traits& traits,
|
||||
unsigned int k=5)
|
||||
{
|
||||
std::size_t k = 5) {
|
||||
if (begin1 == end1) return r_symmetric_difference(begin2, end2, oi, traits, k);
|
||||
General_polygon_set_2<Traits> gps(*begin1, traits);
|
||||
gps.symmetric_difference(std::next(begin1), end1, begin2, end2, k);
|
||||
|
|
@ -457,8 +453,8 @@ inline OutputIterator r_symmetric_difference(InputIterator1 begin1,
|
|||
InputIterator2 begin2,
|
||||
InputIterator2 end2,
|
||||
OutputIterator oi,
|
||||
unsigned int k=5) {
|
||||
typedef typename std::iterator_traits<InputIterator1>::value_type Pgn;
|
||||
std::size_t k = 5) {
|
||||
using Pgn = typename std::iterator_traits<InputIterator1>::value_type;
|
||||
typename Gps_polyline_traits<Pgn>::Traits traits;
|
||||
const typename Gps_polyline_traits<Pgn>::Polyline_traits& ptraits(traits);
|
||||
if (begin1 == end1){
|
||||
|
|
@ -522,10 +518,10 @@ OutputIterator _complement(const General_polygon_with_holes_2<Pgn>& pgn,
|
|||
template <typename Kernel, typename Container, typename Pwh>
|
||||
void _complement(const Polygon_2<Kernel, Container>& pgn, Pwh& pwh) {
|
||||
// Use the polygon to determine the (default) traits
|
||||
typedef Polygon_2<Kernel, Container> Pgn;
|
||||
typedef typename Gps_polyline_traits<Pgn>::Polyline_traits Polyline_traits;
|
||||
typedef General_polygon_2<Polyline_traits> General_pgn;
|
||||
typedef General_polygon_with_holes_2<General_pgn> General_pwh;
|
||||
using Pgn = Polygon_2<Kernel, Container>;
|
||||
using Polyline_traits = typename Gps_polyline_traits<Pgn>::Polyline_traits;
|
||||
using General_pgn = General_polygon_2<Polyline_traits>;
|
||||
using General_pwh = General_polygon_with_holes_2<General_pgn>;
|
||||
|
||||
General_pwh general_pwh;
|
||||
typename Gps_polyline_traits<Pgn>::Traits traits;
|
||||
|
|
@ -539,8 +535,8 @@ template <typename Kernel, typename Container, typename OutputIterator>
|
|||
OutputIterator _complement(const Polygon_with_holes_2<Kernel, Container>& pgn,
|
||||
OutputIterator oi) {
|
||||
// Use the polygon with holes to determine the (default) traits
|
||||
typedef Polygon_with_holes_2<Kernel, Container> Pgn;
|
||||
typedef typename Gps_polyline_traits<Pgn>::Polyline_traits Polyline_traits;
|
||||
using Pgn = Polygon_with_holes_2<Kernel, Container>;
|
||||
using Polyline_traits = typename Gps_polyline_traits<Pgn>::Polyline_traits;
|
||||
|
||||
typename Gps_polyline_traits<Pgn>::Traits traits;
|
||||
const Polyline_traits& ptraits(traits);
|
||||
|
|
|
|||
|
|
@ -7,12 +7,11 @@
|
|||
// $Id$
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
//
|
||||
// Author(s): Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Efi Fogel <efifogel@gmail.com>
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Efi Fogel <efifogel@gmail.com>
|
||||
|
||||
#ifndef CGAL_BSO_2_GPS_AGG_META_TRAITS_H
|
||||
#define CGAL_BSO_2_GPS_AGG_META_TRAITS_H
|
||||
#ifndef CGAL_GPS_AGG_META_TRAITS_H
|
||||
#define CGAL_GPS_AGG_META_TRAITS_H
|
||||
|
||||
#include <CGAL/license/Boolean_set_operations_2.h>
|
||||
|
||||
|
|
@ -24,18 +23,17 @@
|
|||
namespace CGAL {
|
||||
|
||||
template <typename Arrangement_>
|
||||
class Gps_agg_curve_data : public Curve_with_halfedge<Arrangement_>
|
||||
{
|
||||
class Gps_agg_curve_data : public Curve_with_halfedge<Arrangement_> {
|
||||
protected:
|
||||
typedef Arrangement_ Arrangement;
|
||||
typedef typename Arrangement::Halfedge_handle Halfedge_handle;
|
||||
typedef Curve_with_halfedge<Arrangement_> Base;
|
||||
using Arrangement = Arrangement_;
|
||||
using Halfedge_handle = typename Arrangement::Halfedge_handle;
|
||||
using Base = Curve_with_halfedge<Arrangement_>;
|
||||
|
||||
const Arrangement* m_arr; // pointer to the arrangement containing the edge.
|
||||
unsigned int m_bc; // the boundary counter of the halfedge with the same
|
||||
std::size_t m_bc; // the boundary counter of the halfedge with the same
|
||||
// direction as the curve
|
||||
|
||||
unsigned int m_twin_bc; // the boundary counter of the halfedge with the same
|
||||
std::size_t m_twin_bc; // the boundary counter of the halfedge with the same
|
||||
// direction as the curve
|
||||
|
||||
public:
|
||||
|
|
@ -47,24 +45,24 @@ public:
|
|||
{}
|
||||
|
||||
Gps_agg_curve_data(const Arrangement* arr, Halfedge_handle he,
|
||||
unsigned int bc, unsigned int twin_bc) :
|
||||
std::size_t bc, std::size_t twin_bc) :
|
||||
Base(he),
|
||||
m_arr(arr),
|
||||
m_bc(bc),
|
||||
m_twin_bc(twin_bc)
|
||||
{}
|
||||
|
||||
unsigned int bc() const { return m_bc; }
|
||||
std::size_t bc() const { return m_bc; }
|
||||
|
||||
unsigned int twin_bc() const { return m_twin_bc; }
|
||||
std::size_t twin_bc() const { return m_twin_bc; }
|
||||
|
||||
unsigned int& bc() { return m_bc; }
|
||||
std::size_t& bc() { return m_bc; }
|
||||
|
||||
unsigned int& twin_bc() { return m_twin_bc; }
|
||||
std::size_t& twin_bc() { return m_twin_bc; }
|
||||
|
||||
void set_bc(unsigned int bc) { m_bc = bc; }
|
||||
void set_bc(std::size_t bc) { m_bc = bc; }
|
||||
|
||||
void set_twin_bc(unsigned int twin_bc) { m_twin_bc = twin_bc; }
|
||||
void set_twin_bc(std::size_t twin_bc) { m_twin_bc = twin_bc; }
|
||||
|
||||
const Arrangement* arr() const { return m_arr; }
|
||||
};
|
||||
|
|
@ -73,54 +71,50 @@ template <typename Arrangement_>
|
|||
class Gps_agg_meta_traits :
|
||||
public Gps_traits_decorator<typename Arrangement_::Traits_adaptor_2,
|
||||
Gps_agg_curve_data<Arrangement_>,
|
||||
Point_with_vertex<Arrangement_> >
|
||||
{
|
||||
typedef Arrangement_ Arrangement;
|
||||
typedef Arrangement Arr;
|
||||
Point_with_vertex<Arrangement_>> {
|
||||
using Arrangement = Arrangement_;
|
||||
using Arr = Arrangement;
|
||||
|
||||
typedef typename Arr::Traits_adaptor_2 Traits;
|
||||
typedef Traits Gt2;
|
||||
using Traits = typename Arr::Traits_adaptor_2;
|
||||
using Gt2 = Traits;
|
||||
|
||||
typedef typename Gt2::X_monotone_curve_2 Base_x_monotone_curve_2;
|
||||
typedef typename Gt2::Point_2 Base_point_2;
|
||||
typedef typename Gt2::Construct_min_vertex_2 Base_Construct_min_vertex_2;
|
||||
typedef typename Gt2::Construct_max_vertex_2 Base_Construct_max_vertex_2;
|
||||
typedef typename Gt2::Compare_endpoints_xy_2 Base_Compare_endpoints_xy_2;
|
||||
typedef typename Gt2::Compare_xy_2 Base_Compare_xy_2;
|
||||
typedef typename Gt2::Compare_y_at_x_right_2 Base_Compare_y_at_x_right_2;
|
||||
typedef typename Gt2::Compare_y_at_x_2 Base_Compare_y_at_x_2;
|
||||
typedef typename Gt2::Intersect_2 Base_Intersect_2;
|
||||
typedef typename Gt2::Split_2 Base_Split_2;
|
||||
using Base_x_monotone_curve_2 = typename Gt2::X_monotone_curve_2;
|
||||
using Base_point_2 = typename Gt2::Point_2;
|
||||
using Base_Construct_min_vertex_2 = typename Gt2::Construct_min_vertex_2;
|
||||
using Base_Construct_max_vertex_2 = typename Gt2::Construct_max_vertex_2;
|
||||
using Base_Compare_endpoints_xy_2 = typename Gt2::Compare_endpoints_xy_2;
|
||||
using Base_Compare_xy_2 = typename Gt2::Compare_xy_2;
|
||||
using Base_Compare_y_at_x_right_2 = typename Gt2::Compare_y_at_x_right_2;
|
||||
using Base_Compare_y_at_x_2 = typename Gt2::Compare_y_at_x_2;
|
||||
using Base_Intersect_2 = typename Gt2::Intersect_2;
|
||||
using Base_Split_2 = typename Gt2::Split_2;
|
||||
|
||||
typedef typename Gt2::Parameter_space_in_x_2 Base_Parameter_space_in_x_2;
|
||||
typedef typename Gt2::Compare_y_near_boundary_2
|
||||
Base_Compare_y_near_boundary_2;
|
||||
using Base_Parameter_space_in_x_2 = typename Gt2::Parameter_space_in_x_2;
|
||||
using Base_Compare_y_near_boundary_2 = typename Gt2::Compare_y_near_boundary_2;
|
||||
|
||||
typedef typename Gt2::Parameter_space_in_y_2 Base_Parameter_space_in_y_2;
|
||||
typedef typename Gt2::Compare_x_near_boundary_2
|
||||
Base_Compare_x_near_boundary_2;
|
||||
using Base_Parameter_space_in_y_2 = typename Gt2::Parameter_space_in_y_2;
|
||||
using Base_Compare_x_near_boundary_2 = typename Gt2::Compare_x_near_boundary_2;
|
||||
|
||||
public:
|
||||
typedef typename Gt2::Multiplicity Multiplicity;
|
||||
typedef Gps_agg_curve_data<Arr> Curve_data;
|
||||
typedef Point_with_vertex<Arr> Point_data;
|
||||
using Multiplicity = typename Gt2::Multiplicity;
|
||||
using Curve_data = Gps_agg_curve_data<Arr>;
|
||||
using Point_data = Point_with_vertex<Arr>;
|
||||
|
||||
private:
|
||||
typedef Gps_agg_meta_traits<Arrangement> Self;
|
||||
typedef Gps_traits_decorator<Gt2, Curve_data, Point_data> Base;
|
||||
using Self = Gps_agg_meta_traits<Arrangement>;
|
||||
using Base = Gps_traits_decorator<Gt2, Curve_data, Point_data>;
|
||||
|
||||
public:
|
||||
typedef typename Base::X_monotone_curve_2 X_monotone_curve_2;
|
||||
typedef typename Base::Point_2 Point_2;
|
||||
typedef typename Gt2::Has_left_category Has_left_category;
|
||||
typedef typename Gt2::Has_merge_category Has_merge_category;
|
||||
typedef typename Gt2::Has_do_intersect_category
|
||||
Has_do_intersect_category;
|
||||
using X_monotone_curve_2 = typename Base::X_monotone_curve_2;
|
||||
using Point_2 = typename Base::Point_2;
|
||||
using Has_left_category = typename Gt2::Has_left_category;
|
||||
using Has_merge_category = typename Gt2::Has_merge_category;
|
||||
using Has_do_intersect_category = typename Gt2::Has_do_intersect_category;
|
||||
|
||||
typedef typename Arr::Left_side_category Left_side_category;
|
||||
typedef typename Arr::Bottom_side_category Bottom_side_category;
|
||||
typedef typename Arr::Top_side_category Top_side_category;
|
||||
typedef typename Arr::Right_side_category Right_side_category;
|
||||
using Left_side_category = typename Arr::Left_side_category;
|
||||
using Bottom_side_category = typename Arr::Bottom_side_category;
|
||||
using Top_side_category = typename Arr::Top_side_category;
|
||||
using Right_side_category = typename Arr::Right_side_category;
|
||||
|
||||
// a side is either oblivious or open (unbounded)
|
||||
static_assert(std::is_same<Left_side_category, Arr_oblivious_side_tag>::value ||
|
||||
|
|
@ -132,8 +126,8 @@ public:
|
|||
static_assert(std::is_same<Right_side_category, Arr_oblivious_side_tag>::value ||
|
||||
std::is_same<Right_side_category, Arr_open_side_tag>::value);
|
||||
|
||||
typedef typename Arr::Halfedge_handle Halfedge_handle;
|
||||
typedef typename Arr::Vertex_handle Vertex_handle;
|
||||
using Halfedge_handle = typename Arr::Halfedge_handle;
|
||||
using Vertex_handle = typename Arr::Vertex_handle;
|
||||
|
||||
Gps_agg_meta_traits() {}
|
||||
|
||||
|
|
@ -152,16 +146,13 @@ public:
|
|||
template <typename OutputIterator>
|
||||
OutputIterator operator()(const X_monotone_curve_2& cv1,
|
||||
const X_monotone_curve_2& cv2,
|
||||
OutputIterator oi) const
|
||||
{
|
||||
OutputIterator oi) const {
|
||||
// Check whether the curves are already in the same arrangement, and thus
|
||||
// must be interior-disjoint
|
||||
if (cv1.data().arr() == cv2.data().arr()) return oi;
|
||||
|
||||
typedef const std::pair<Base_point_2, Multiplicity>
|
||||
Intersection_base_point;
|
||||
typedef std::variant<Intersection_base_point, Base_x_monotone_curve_2>
|
||||
Intersection_base_result;
|
||||
using Intersection_base_point = const std::pair<Base_point_2, Multiplicity>;
|
||||
using Intersection_base_result = std::variant<Intersection_base_point, Base_x_monotone_curve_2>;
|
||||
|
||||
const auto* base_traits = m_traits.m_base_traits;
|
||||
auto base_cmp_xy = base_traits->compare_xy_2_object();
|
||||
|
|
@ -191,8 +182,8 @@ public:
|
|||
const Base_x_monotone_curve_2* overlap_cv =
|
||||
std::get_if<Base_x_monotone_curve_2>(&xection);
|
||||
CGAL_assertion(overlap_cv != nullptr);
|
||||
unsigned int ov_bc;
|
||||
unsigned int ov_twin_bc;
|
||||
std::size_t ov_bc;
|
||||
std::size_t ov_twin_bc;
|
||||
if (base_cmp_endpoints(cv1) == base_cmp_endpoints(cv2)) {
|
||||
// cv1 and cv2 have the same directions
|
||||
ov_bc = cv1.data().bc() + cv2.data().bc();
|
||||
|
|
@ -230,8 +221,7 @@ public:
|
|||
Split_2(const Base_Split_2& base) : m_base_split(base) {}
|
||||
|
||||
void operator()(const X_monotone_curve_2& cv, const Point_2 & p,
|
||||
X_monotone_curve_2& c1, X_monotone_curve_2& c2) const
|
||||
{
|
||||
X_monotone_curve_2& c1, X_monotone_curve_2& c2) const {
|
||||
m_base_split(cv.base(), p.base(), c1.base(), c2.base());
|
||||
const Curve_data& cv_data = cv.data();
|
||||
c1.set_data(Curve_data(cv_data.arr(), Halfedge_handle(), cv_data.bc(),
|
||||
|
|
@ -259,8 +249,7 @@ public:
|
|||
* \param cv The curve.
|
||||
* \return The left endpoint.
|
||||
*/
|
||||
Point_2 operator()(const X_monotone_curve_2 & cv) const
|
||||
{
|
||||
Point_2 operator()(const X_monotone_curve_2 & cv) const {
|
||||
if (cv.data().halfedge() == Halfedge_handle())
|
||||
return (Point_2(m_base(cv.base())));
|
||||
|
||||
|
|
@ -272,8 +261,7 @@ public:
|
|||
};
|
||||
|
||||
/*! Get a Construct_min_vertex_2 functor object. */
|
||||
Construct_min_vertex_2 construct_min_vertex_2_object() const
|
||||
{
|
||||
Construct_min_vertex_2 construct_min_vertex_2_object() const {
|
||||
return Construct_min_vertex_2(this->m_base_traits->
|
||||
construct_min_vertex_2_object());
|
||||
}
|
||||
|
|
@ -285,15 +273,14 @@ public:
|
|||
|
||||
public:
|
||||
Construct_max_vertex_2(const Base_Construct_max_vertex_2& base) :
|
||||
m_base(base)
|
||||
m_base(base)
|
||||
{}
|
||||
|
||||
/*! Obtain the right endpoint of the x-monotone curve (segment).
|
||||
* \param cv The curve.
|
||||
* \return The right endpoint.
|
||||
*/
|
||||
Point_2 operator()(const X_monotone_curve_2& cv) const
|
||||
{
|
||||
Point_2 operator()(const X_monotone_curve_2& cv) const {
|
||||
if (cv.data().halfedge() == Halfedge_handle())
|
||||
return (Point_2(m_base(cv.base())));
|
||||
|
||||
|
|
@ -304,8 +291,7 @@ public:
|
|||
};
|
||||
|
||||
/*! Get a Construct_min_vertex_2 functor object. */
|
||||
Construct_max_vertex_2 construct_max_vertex_2_object() const
|
||||
{
|
||||
Construct_max_vertex_2 construct_max_vertex_2_object() const {
|
||||
return Construct_max_vertex_2(this->m_base_traits->
|
||||
construct_max_vertex_2_object());
|
||||
}
|
||||
|
|
@ -321,8 +307,7 @@ public:
|
|||
* \param cv The curve.
|
||||
* \return The left endpoint.
|
||||
*/
|
||||
Comparison_result operator()(const Point_2& p1, const Point_2& p2) const
|
||||
{
|
||||
Comparison_result operator()(const Point_2& p1, const Point_2& p2) const {
|
||||
const Point_data& inf1 = p1.data();
|
||||
const Point_data& inf2 = p2.data();
|
||||
|
||||
|
|
@ -390,8 +375,7 @@ public:
|
|||
};
|
||||
|
||||
/*! Obtain a Construct_min_vertex_2 functor object. */
|
||||
Compare_y_near_boundary_2 compare_y_near_boundary_2_object() const
|
||||
{
|
||||
Compare_y_near_boundary_2 compare_y_near_boundary_2_object() const {
|
||||
return Compare_y_near_boundary_2(this->m_base_traits->
|
||||
compare_y_near_boundary_2_object()
|
||||
);
|
||||
|
|
@ -429,8 +413,7 @@ public:
|
|||
};
|
||||
|
||||
/*! Obtain a Construct_min_vertex_2 functor object. */
|
||||
Parameter_space_in_y_2 parameter_space_in_y_2_object() const
|
||||
{
|
||||
Parameter_space_in_y_2 parameter_space_in_y_2_object() const {
|
||||
return Parameter_space_in_y_2(this->m_base_traits->
|
||||
parameter_space_in_y_2_object());
|
||||
}
|
||||
|
|
@ -462,8 +445,7 @@ public:
|
|||
};
|
||||
|
||||
/*! Obtain a Construct_min_vertex_2 functor object. */
|
||||
Compare_x_near_boundary_2 compare_x_near_boundary_2_object() const
|
||||
{
|
||||
Compare_x_near_boundary_2 compare_x_near_boundary_2_object() const {
|
||||
return Compare_x_near_boundary_2(this->m_base_traits->
|
||||
compare_x_near_boundary_2_object());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,11 +7,12 @@
|
|||
// $Id$
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ophir Setter <ophir.setter@cs.tau.ac.il>
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ophir Setter <ophir.setter@cs.tau.ac.il>
|
||||
// Efi Fogel <efifogel@gmail.com>
|
||||
|
||||
#ifndef CGAL_BSO_2_GPS_AGG_OP_H
|
||||
#define CGAL_BSO_2_GPS_AGG_OP_H
|
||||
#ifndef CGAL_GPS_AGG_OP_H
|
||||
#define CGAL_GPS_AGG_OP_H
|
||||
|
||||
#include <CGAL/license/Boolean_set_operations_2.h>
|
||||
|
||||
|
|
@ -19,8 +20,8 @@
|
|||
*
|
||||
* The class Gps_agg_op is responsible for aggregated Boolean set operations
|
||||
* depending on a visitor template parameter. It uses the surface-sweep
|
||||
* algorithm from the arrangement packages to overlay all the polygon sets, and
|
||||
* then it uses a BFS that determines which of the faces is contained in the
|
||||
* algorithm from the surface-sweep package to overlay all the polygon sets, and
|
||||
* then it uses a BFS that determines which of the faces are contained in the
|
||||
* result using the visitor.
|
||||
*/
|
||||
|
||||
|
|
@ -37,31 +38,31 @@
|
|||
|
||||
namespace CGAL {
|
||||
|
||||
template <typename Arrangement_, typename BfsVisitor>
|
||||
template <typename Arrangement_, typename BfsVisitor, template <typename, typename, typename> class SweepVisitor>
|
||||
class Gps_agg_op {
|
||||
typedef Arrangement_ Arrangement_2;
|
||||
typedef BfsVisitor Bfs_visitor;
|
||||
using Arrangement_2 = Arrangement_;
|
||||
using Bfs_visitor = BfsVisitor;
|
||||
|
||||
typedef typename Arrangement_2::Traits_adaptor_2 Geometry_traits_2;
|
||||
typedef typename Arrangement_2::Topology_traits Topology_traits;
|
||||
using Geometry_traits_2 = typename Arrangement_2::Traits_adaptor_2;
|
||||
using Topology_traits = typename Arrangement_2::Topology_traits;
|
||||
|
||||
typedef Arrangement_2 Arr;
|
||||
typedef Geometry_traits_2 Gt2;
|
||||
typedef Topology_traits Tt;
|
||||
using Arr = Arrangement_2;
|
||||
using Gt2 = Geometry_traits_2;
|
||||
using Tt = Topology_traits;
|
||||
|
||||
typedef typename Gt2::Curve_const_iterator Curve_const_iterator;
|
||||
typedef Gps_agg_meta_traits<Arr> Mgt2;
|
||||
typedef typename Mgt2::Curve_data Curve_data;
|
||||
typedef typename Mgt2::X_monotone_curve_2 Meta_X_monotone_curve_2;
|
||||
using Curve_const_iterator = typename Gt2::Curve_const_iterator;
|
||||
using Mgt2 = Gps_agg_meta_traits<Arr>;
|
||||
using Curve_data = typename Mgt2::Curve_data;
|
||||
using Meta_X_monotone_curve_2 = typename Mgt2::X_monotone_curve_2;
|
||||
|
||||
typedef typename Arr::Halfedge_handle Halfedge_handle;
|
||||
typedef typename Arr::Halfedge_iterator Halfedge_iterator;
|
||||
typedef typename Arr::Face_handle Face_handle;
|
||||
typedef typename Arr::Edge_iterator Edge_iterator;
|
||||
typedef typename Arr::Vertex_handle Vertex_handle;
|
||||
typedef typename Arr::Allocator Allocator;
|
||||
using Halfedge_handle = typename Arr::Halfedge_handle;
|
||||
using Halfedge_iterator = typename Arr::Halfedge_iterator;
|
||||
using Face_handle = typename Arr::Face_handle;
|
||||
using Edge_iterator = typename Arr::Edge_iterator;
|
||||
using Vertex_handle = typename Arr::Vertex_handle;
|
||||
using Allocator = typename Arr::Allocator;
|
||||
|
||||
typedef std::pair<Arr*, std::vector<Vertex_handle> *> Arr_entry;
|
||||
using Arr_entry = std::pair<Arr*, std::vector<Vertex_handle> *>;
|
||||
|
||||
// We obtain a proper helper type from the topology traits of the arrangement.
|
||||
// However, the arrangement is parametrized with the Gt2 geometry traits,
|
||||
|
|
@ -70,21 +71,16 @@ class Gps_agg_op {
|
|||
// We cannot parameterized the arrangement with the Mgt2 geometry
|
||||
// traits to start with, because it extends the curve type with arrangement
|
||||
// dependent types. (It is parameterized with the arrangement type.)
|
||||
typedef Indexed_event<Mgt2, Arr, Allocator> Event;
|
||||
typedef Arr_construction_subcurve<Mgt2, Event, Allocator>
|
||||
Subcurve;
|
||||
typedef typename Tt::template Construction_helper<Event, Subcurve>
|
||||
Helper_tmp;
|
||||
typedef typename Helper_tmp::template rebind<Mgt2, Arr, Event, Subcurve>::other
|
||||
Helper;
|
||||
typedef Gps_agg_op_visitor<Helper, Arr> Visitor;
|
||||
typedef Gps_agg_op_surface_sweep_2<Arr, Visitor> Surface_sweep_2;
|
||||
using Event = Indexed_event<Mgt2, Arr, Allocator>;
|
||||
using Subcurve = Arr_construction_subcurve<Mgt2, Event, Allocator>;
|
||||
using Helper_tmp = typename Tt::template Construction_helper<Event, Subcurve>;
|
||||
using Helper = typename Helper_tmp::template rebind<Mgt2, Arr, Event, Subcurve>::other;
|
||||
using Visitor = SweepVisitor<Helper, Arr, Default>;
|
||||
using Surface_sweep_2 = Gps_agg_op_surface_sweep_2<Arr, Visitor>;
|
||||
|
||||
typedef Unique_hash_map<Halfedge_handle, unsigned int>
|
||||
Edges_hash;
|
||||
|
||||
typedef Unique_hash_map<Face_handle, unsigned int> Faces_hash;
|
||||
typedef Gps_bfs_scanner<Arr, Bfs_visitor> Bfs_scanner;
|
||||
using Edges_hash = Unique_hash_map<Halfedge_handle, std::size_t>;
|
||||
using Faces_hash = Unique_hash_map<Face_handle, std::size_t>;
|
||||
using Bfs_scanner = Gps_bfs_scanner<Arr, Bfs_visitor>;
|
||||
|
||||
protected:
|
||||
Arr* m_arr;
|
||||
|
|
@ -95,7 +91,7 @@ protected:
|
|||
Faces_hash m_faces_hash; // maps face to its IC (inside count)
|
||||
|
||||
public:
|
||||
/*! Constructor. */
|
||||
/*! constructs. */
|
||||
Gps_agg_op(Arr& arr, std::vector<Vertex_handle>& vert_vec, const Gt2& tr) :
|
||||
m_arr(&arr),
|
||||
m_traits(new Mgt2(tr)),
|
||||
|
|
@ -103,40 +99,40 @@ public:
|
|||
m_surface_sweep(m_traits, &m_visitor)
|
||||
{}
|
||||
|
||||
void sweep_arrangements(unsigned int lower, unsigned int upper,
|
||||
unsigned int jump, std::vector<Arr_entry>& arr_vec)
|
||||
{
|
||||
std::list<Meta_X_monotone_curve_2> curves_list;
|
||||
|
||||
unsigned int n_inf_pgn = 0; // number of infinite polygons (arrangement
|
||||
std::pair<std::size_t, std::size_t>
|
||||
prepare(std::size_t lower, std::size_t upper, std::size_t jump,
|
||||
std::vector<Arr_entry>& arr_vec, std::list<Meta_X_monotone_curve_2>& curves_list) {
|
||||
std::size_t n_inf_pgn = 0; // number of infinite polygons (arrangement
|
||||
// with a contained unbounded face
|
||||
unsigned int n_pgn = 0; // number of polygons (arrangements)
|
||||
unsigned int i;
|
||||
|
||||
for (i = lower; i <= upper; i += jump, ++n_pgn) {
|
||||
std::size_t n_pgn = 0; // number of polygons (arrangements)
|
||||
for (auto i = lower; i <= upper; i += jump, ++n_pgn) {
|
||||
// The BFS scan (after the loop) starts in the reference face,
|
||||
// so we count the number of polygons that contain the reference face.
|
||||
Arr* arr = (arr_vec[i]).first;
|
||||
if (arr->reference_face()->contained()) ++n_inf_pgn;
|
||||
|
||||
Edge_iterator itr = arr->edges_begin();
|
||||
for(; itr != arr->edges_end(); ++itr) {
|
||||
for (auto itr = arr->edges_begin(); itr != arr->edges_end(); ++itr) {
|
||||
// take only relevant edges (which separate between contained and
|
||||
// non-contained faces.
|
||||
Halfedge_iterator he = itr;
|
||||
if(he->face()->contained() == he->twin()->face()->contained())
|
||||
continue;
|
||||
if ((Arr_halfedge_direction)he->direction() == ARR_RIGHT_TO_LEFT)
|
||||
he = he->twin();
|
||||
Halfedge_handle he = itr;
|
||||
if (he->face()->contained() == he->twin()->face()->contained()) continue;
|
||||
if ((Arr_halfedge_direction)he->direction() == ARR_RIGHT_TO_LEFT) he = he->twin();
|
||||
|
||||
Curve_data cv_data(arr, he, 1, 0);
|
||||
curves_list.push_back(Meta_X_monotone_curve_2(he->curve(), cv_data));
|
||||
}
|
||||
}
|
||||
return std::make_pair(n_inf_pgn, n_pgn);
|
||||
}
|
||||
|
||||
m_surface_sweep.sweep(curves_list.begin(), curves_list.end(),
|
||||
lower, upper, jump, arr_vec);
|
||||
|
||||
/*! sweeps the plane without interceptions.
|
||||
*/
|
||||
void sweep_arrangements(std::size_t lower, std::size_t upper, std::size_t jump,
|
||||
std::vector<Arr_entry>& arr_vec) {
|
||||
std::size_t n_inf_pgn, n_pgn;
|
||||
std::list<Meta_X_monotone_curve_2> curves_list;
|
||||
std::tie(n_inf_pgn, n_pgn) = prepare(lower, upper, jump, arr_vec, curves_list);
|
||||
m_surface_sweep.sweep(curves_list.begin(), curves_list.end(), lower, upper, jump, arr_vec);
|
||||
m_faces_hash[m_arr->reference_face()] = n_inf_pgn;
|
||||
Bfs_visitor visitor(&m_edges_hash, &m_faces_hash, n_pgn);
|
||||
visitor.visit_ubf(m_arr->faces_begin(), n_inf_pgn);
|
||||
|
|
@ -145,7 +141,69 @@ public:
|
|||
visitor.after_scan(*m_arr);
|
||||
}
|
||||
|
||||
/*! Destruct.
|
||||
/*! sweeps the plane without interceptions, but stop when an intersection occurs.
|
||||
*/
|
||||
bool sweep_intercept_arrangements(std::size_t lower, std::size_t upper, std::size_t jump,
|
||||
std::vector<Arr_entry>& arr_vec) {
|
||||
std::size_t n_inf_pgn, n_pgn;
|
||||
std::list<Meta_X_monotone_curve_2> curves_list;
|
||||
std::tie(n_inf_pgn, n_pgn) = prepare(lower, upper, jump, arr_vec, curves_list);
|
||||
auto res = m_surface_sweep.sweep_intercept(curves_list.begin(), curves_list.end(), lower, upper, jump, arr_vec);
|
||||
if (res) return true;
|
||||
|
||||
m_faces_hash[m_arr->reference_face()] = n_inf_pgn;
|
||||
Bfs_visitor visitor(&m_edges_hash, &m_faces_hash, n_pgn);
|
||||
visitor.visit_ubf(m_arr->faces_begin(), n_inf_pgn);
|
||||
Bfs_scanner scanner(visitor);
|
||||
scanner.scan(*m_arr);
|
||||
visitor.after_scan(*m_arr);
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename InputIterator>
|
||||
std::size_t prepare2(InputIterator begin, InputIterator end, std::list<Meta_X_monotone_curve_2>& curves_list) {
|
||||
std::size_t n_inf_pgn = 0; // number of infinite polygons (arrangement
|
||||
// with a contained unbounded face
|
||||
for (auto it = begin; it != end; ++it) {
|
||||
// The BFS scan (after the loop) starts in the reference face,
|
||||
// so we count the number of polygons that contain the reference face.
|
||||
Arr* arr = it->first;
|
||||
if (arr->reference_face()->contained()) ++n_inf_pgn;
|
||||
|
||||
for (auto ite = arr->edges_begin(); ite != arr->edges_end(); ++ite) {
|
||||
// take only relevant edges (which separate between contained and
|
||||
// non-contained faces.
|
||||
Halfedge_handle he = ite;
|
||||
if (he->face()->contained() == he->twin()->face()->contained()) continue;
|
||||
if ((Arr_halfedge_direction)he->direction() == ARR_RIGHT_TO_LEFT) he = he->twin();
|
||||
|
||||
Curve_data cv_data(arr, he, 1, 0);
|
||||
curves_list.push_back(Meta_X_monotone_curve_2(he->curve(), cv_data));
|
||||
}
|
||||
}
|
||||
return n_inf_pgn;
|
||||
}
|
||||
|
||||
/*! sweeps the plane without interceptions, but stop when an intersection occurs.
|
||||
*/
|
||||
template <typename InputIterator>
|
||||
bool sweep_intercept_arrangements2(InputIterator begin, InputIterator end) {
|
||||
std::list<Meta_X_monotone_curve_2> curves_list;
|
||||
auto n_inf_pgn = prepare2(begin, end, curves_list);
|
||||
auto res = m_surface_sweep.sweep_intercept2(curves_list.begin(), curves_list.end(), begin, end);
|
||||
if (res) return true;
|
||||
|
||||
m_faces_hash[m_arr->reference_face()] = n_inf_pgn;
|
||||
std::size_t n_pgn = std::distance(begin, end); // number of polygons (arrangements)
|
||||
Bfs_visitor visitor(&m_edges_hash, &m_faces_hash, n_pgn);
|
||||
visitor.visit_ubf(m_arr->faces_begin(), n_inf_pgn);
|
||||
Bfs_scanner scanner(visitor);
|
||||
scanner.scan(*m_arr);
|
||||
visitor.after_scan(*m_arr);
|
||||
return false;
|
||||
}
|
||||
|
||||
/*! destructs.
|
||||
*/
|
||||
~Gps_agg_op() { delete m_traits; }
|
||||
};
|
||||
|
|
|
|||
|
|
@ -7,11 +7,12 @@
|
|||
// $Id$
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ron Wein <wein@post.tau.ac.il>
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ron Wein <wein@post.tau.ac.il>
|
||||
// Efi Fogel <efifogel@gmail.com>
|
||||
|
||||
#ifndef CGAL_BSO_2_GSP_AGG_OP_SURFACE_SWEEP_2_H
|
||||
#define CGAL_BSO_2_GSP_AGG_OP_SURFACE_SWEEP_2_H
|
||||
#ifndef CGAL_GSP_AGG_OP_SURFACE_SWEEP_2_H
|
||||
#define CGAL_GSP_AGG_OP_SURFACE_SWEEP_2_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
|
@ -27,34 +28,34 @@ namespace Ss2 = Surface_sweep_2;
|
|||
template <typename Arrangement_, typename Visitor_>
|
||||
class Gps_agg_op_surface_sweep_2 : public Ss2::Surface_sweep_2<Visitor_> {
|
||||
public:
|
||||
typedef Arrangement_ Arrangement_2;
|
||||
typedef Visitor_ Visitor;
|
||||
using Arrangement_2 = Arrangement_;
|
||||
using Visitor = Visitor_;
|
||||
|
||||
typedef typename Visitor::Geometry_traits_2 Geometry_traits_2;
|
||||
using Geometry_traits_2 = typename Visitor::Geometry_traits_2;
|
||||
|
||||
typedef Arrangement_2 Arr;
|
||||
typedef Geometry_traits_2 Gt2;
|
||||
using Arr = Arrangement_2;
|
||||
using Gt2 = Geometry_traits_2;
|
||||
|
||||
typedef typename Gt2::Point_2 Point_2;
|
||||
typedef typename Gt2::X_monotone_curve_2 X_monotone_curve_2;
|
||||
using Point_2 = typename Gt2::Point_2;
|
||||
using X_monotone_curve_2 = typename Gt2::X_monotone_curve_2;
|
||||
|
||||
typedef typename Arr::Vertex_handle Vertex_handle;
|
||||
typedef typename Arr::Halfedge_handle Halfedge_handle;
|
||||
using Vertex_handle = typename Arr::Vertex_handle;
|
||||
using Halfedge_handle = typename Arr::Halfedge_handle;
|
||||
|
||||
typedef std::pair<Arr*, std::vector<Vertex_handle> *> Arr_entry;
|
||||
using Arr_entry = std::pair<Arr*, std::vector<Vertex_handle> *>;
|
||||
|
||||
typedef Ss2::Surface_sweep_2<Visitor> Base;
|
||||
using Base = Ss2::Surface_sweep_2<Visitor>;
|
||||
|
||||
typedef typename Visitor::Event Event;
|
||||
typedef typename Visitor::Subcurve Subcurve;
|
||||
using Event = typename Visitor::Event;
|
||||
using Subcurve = typename Visitor::Subcurve;
|
||||
|
||||
typedef typename Base::Event_queue_iterator EventQueueIter;
|
||||
typedef typename Event::Subcurve_iterator EventCurveIter;
|
||||
using EventQueueIter = typename Base::Event_queue_iterator;
|
||||
using EventCurveIter = typename Event::Subcurve_iterator;
|
||||
|
||||
typedef typename Event::Attribute Attribute;
|
||||
using Attribute = typename Event::Attribute;
|
||||
|
||||
typedef std::list<Subcurve*> SubCurveList;
|
||||
typedef typename SubCurveList::iterator SubCurveListIter;
|
||||
using SubCurveList = std::list<Subcurve*>;
|
||||
using SubCurveListIter = typename SubCurveList::iterator;
|
||||
|
||||
public:
|
||||
/*! Constructor.
|
||||
|
|
@ -70,21 +71,17 @@ public:
|
|||
Base(traits, visitor)
|
||||
{}
|
||||
|
||||
/*! Perform the sweep. */
|
||||
template <class CurveInputIterator>
|
||||
void sweep(CurveInputIterator curves_begin, CurveInputIterator curves_end,
|
||||
unsigned int lower, unsigned int upper, unsigned int jump,
|
||||
std::vector<Arr_entry>& arr_vec)
|
||||
{
|
||||
template <typename CurveInputIterator>
|
||||
void pre_process(CurveInputIterator curves_begin, CurveInputIterator curves_end,
|
||||
std::size_t lower, std::size_t upper, std::size_t jump,
|
||||
std::vector<Arr_entry>& arr_vec) {
|
||||
CGAL_assertion(this->m_queue->empty() && this->m_statusLine.size() == 0);
|
||||
|
||||
typedef Unique_hash_map<Vertex_handle, Event*> Vertices_map;
|
||||
typedef typename Gt2::Compare_xy_2 Compare_xy_2;
|
||||
using Vertices_map = Unique_hash_map<Vertex_handle, Event*>;
|
||||
using Compare_xy_2 = typename Gt2::Compare_xy_2;
|
||||
|
||||
this->m_visitor->before_sweep();
|
||||
// Allocate all of the Subcurve objects as one block.
|
||||
this->m_num_of_subCurves =
|
||||
static_cast<unsigned int>(std::distance(curves_begin, curves_end));
|
||||
this->m_num_of_subCurves = static_cast<unsigned int>(std::distance(curves_begin, curves_end));
|
||||
if (this->m_num_of_subCurves > 0)
|
||||
this->m_subCurves =
|
||||
this->m_subCurveAlloc.allocate(this->m_num_of_subCurves);
|
||||
|
|
@ -95,9 +92,9 @@ public:
|
|||
Vertices_map vert_map;
|
||||
Vertex_handle vh;
|
||||
Vertex_handle invalid_v;
|
||||
unsigned int i = lower;
|
||||
unsigned int n = static_cast<unsigned int>((arr_vec[i].second)->size());
|
||||
unsigned int j;
|
||||
std::size_t i = lower;
|
||||
auto n = (arr_vec[i].second)->size();
|
||||
std::size_t j;
|
||||
EventQueueIter q_iter;
|
||||
bool first = true;
|
||||
Attribute event_type;
|
||||
|
|
@ -135,7 +132,7 @@ public:
|
|||
for (i += jump; i <= upper; i += jump) {
|
||||
// Merge the vertices of the other vectors into the existing queue.
|
||||
q_iter = this->m_queue->begin();
|
||||
n = static_cast<unsigned int>((arr_vec[i].second)->size());
|
||||
n = (arr_vec[i].second)->size();
|
||||
|
||||
for (j = 0; j < n && (vh = (*(arr_vec[i].second))[j]) != invalid_v; j++) {
|
||||
event_type = _type_of_vertex(vh);
|
||||
|
|
@ -170,7 +167,7 @@ public:
|
|||
|
||||
// Go over all curves (which are associated with halfedges) and associate
|
||||
// them with the events we have just created.
|
||||
unsigned int index = 0;
|
||||
std::size_t index = 0;
|
||||
CurveInputIterator iter;
|
||||
Halfedge_handle he;
|
||||
Event* e_left;
|
||||
|
|
@ -194,9 +191,10 @@ public:
|
|||
}
|
||||
|
||||
// Create the subcurve object.
|
||||
typedef decltype(this->m_subCurveAlloc) Subcurve_alloc;
|
||||
std::allocator_traits<Subcurve_alloc>::construct(this->m_subCurveAlloc, this->m_subCurves + index,
|
||||
this->m_masterSubcurve);
|
||||
using Subcurve_alloc = decltype(this->m_subCurveAlloc);
|
||||
std::allocator_traits<Subcurve_alloc>::construct(this->m_subCurveAlloc,
|
||||
this->m_subCurves + index,
|
||||
this->m_masterSubcurve);
|
||||
(this->m_subCurves + index)->init(*iter);
|
||||
(this->m_subCurves + index)->set_left_event(e_left);
|
||||
(this->m_subCurves + index)->set_right_event(e_right);
|
||||
|
|
@ -204,13 +202,174 @@ public:
|
|||
e_right->add_curve_to_left(this->m_subCurves + index);
|
||||
this->_add_curve_to_right(e_left, this->m_subCurves + index);
|
||||
}
|
||||
}
|
||||
|
||||
// Perform the sweep:
|
||||
template <typename CurveInputIterator, typename InputIterator>
|
||||
void pre_process2(CurveInputIterator curves_begin, CurveInputIterator curves_end,
|
||||
InputIterator begin, InputIterator end) {
|
||||
CGAL_assertion(this->m_queue->empty() && this->m_statusLine.size() == 0);
|
||||
|
||||
using Vertices_map = Unique_hash_map<Vertex_handle, Event*>;
|
||||
using Compare_xy_2 = typename Gt2::Compare_xy_2;
|
||||
|
||||
// Allocate all of the Subcurve objects as one block.
|
||||
this->m_num_of_subCurves = std::distance(curves_begin, curves_end);
|
||||
if (this->m_num_of_subCurves > 0)
|
||||
this->m_subCurves =
|
||||
this->m_subCurveAlloc.allocate(this->m_num_of_subCurves);
|
||||
|
||||
|
||||
// Initialize the event queue using the vertices vectors. Note that these
|
||||
// vertices are already sorted, we simply have to merge them
|
||||
Vertices_map vert_map;
|
||||
Vertex_handle vh;
|
||||
Vertex_handle invalid_v;
|
||||
// std::size_t i = lower;
|
||||
auto it = begin;
|
||||
auto n = it->second->size();
|
||||
std::size_t j;
|
||||
EventQueueIter q_iter;
|
||||
bool first = true;
|
||||
Attribute event_type;
|
||||
Event* event;
|
||||
|
||||
for (j = 0; j < n && (vh = (*(it->second))[j]) != invalid_v; j++) {
|
||||
// Insert the vertices of the first vector one after the other.
|
||||
event_type = _type_of_vertex(vh);
|
||||
if (event_type == Event::DEFAULT) continue;
|
||||
|
||||
event = this->_allocate_event(vh->point(), event_type,
|
||||
ARR_INTERIOR, ARR_INTERIOR);
|
||||
// \todo When the boolean set operations are extended to support
|
||||
// unbounded curves, we will need here a special treatment.
|
||||
|
||||
#ifndef CGAL_ARRANGEMENT_ON_SURFACE_2_H
|
||||
event->set_finite();
|
||||
#endif
|
||||
|
||||
if (! first) {
|
||||
q_iter = this->m_queue->insert_after(q_iter, event);
|
||||
}
|
||||
else {
|
||||
q_iter = this->m_queue->insert(event);
|
||||
first = false;
|
||||
}
|
||||
|
||||
vert_map[vh] = event;
|
||||
}
|
||||
|
||||
Comparison_result res = LARGER;
|
||||
Compare_xy_2 comp_xy = this->m_traits->compare_xy_2_object();
|
||||
EventQueueIter q_end = this->m_queue->end();
|
||||
|
||||
for (++it; it != end; ++it) {
|
||||
// Merge the vertices of the other vectors into the existing queue.
|
||||
q_iter = this->m_queue->begin();
|
||||
n = it->second->size();
|
||||
|
||||
for (j = 0; j < n && (vh = (*(it->second))[j]) != invalid_v; j++) {
|
||||
event_type = _type_of_vertex(vh);
|
||||
if (event_type == Event::DEFAULT) continue;
|
||||
|
||||
while ((q_iter != q_end) &&
|
||||
(res = comp_xy(vh->point(), (*q_iter)->point())) == LARGER)
|
||||
{
|
||||
++q_iter;
|
||||
}
|
||||
|
||||
if (res == SMALLER || q_iter == q_end) {
|
||||
event = this->_allocate_event(vh->point(), event_type,
|
||||
ARR_INTERIOR, ARR_INTERIOR);
|
||||
// \todo When the boolean set operations are extended to support
|
||||
// unbounded curves, we will need here a special treatment.
|
||||
|
||||
#ifndef CGAL_ARRANGEMENT_ON_SURFACE_2_H
|
||||
event->set_finite();
|
||||
#endif
|
||||
|
||||
this->m_queue->insert_before(q_iter, event);
|
||||
vert_map[vh] = event;
|
||||
}
|
||||
else if (res == EQUAL) {
|
||||
// In this case q_iter points to an event already associated with
|
||||
// the vertex, so we just update the map:
|
||||
vert_map[vh] = *q_iter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Go over all curves (which are associated with halfedges) and associate
|
||||
// them with the events we have just created.
|
||||
std::size_t index = 0;
|
||||
CurveInputIterator iter;
|
||||
Halfedge_handle he;
|
||||
Event* e_left;
|
||||
Event* e_right;
|
||||
|
||||
for (iter = curves_begin; iter != curves_end; ++iter, index++) {
|
||||
// Get the events associated with the end-vertices of the current
|
||||
// halfedge.
|
||||
he = iter->data().halfedge();
|
||||
|
||||
CGAL_assertion(vert_map.is_defined(he->source()));
|
||||
CGAL_assertion(vert_map.is_defined(he->target()));
|
||||
|
||||
if ((Arr_halfedge_direction)he->direction() == ARR_LEFT_TO_RIGHT) {
|
||||
e_left = vert_map[he->source()];
|
||||
e_right = vert_map[he->target()];
|
||||
}
|
||||
else {
|
||||
e_left = vert_map[he->target()];
|
||||
e_right = vert_map[he->source()];
|
||||
}
|
||||
|
||||
// Create the subcurve object.
|
||||
using Subcurve_alloc = decltype(this->m_subCurveAlloc);
|
||||
std::allocator_traits<Subcurve_alloc>::construct(this->m_subCurveAlloc,
|
||||
this->m_subCurves + index,
|
||||
this->m_masterSubcurve);
|
||||
(this->m_subCurves + index)->init(*iter);
|
||||
(this->m_subCurves + index)->set_left_event(e_left);
|
||||
(this->m_subCurves + index)->set_right_event(e_right);
|
||||
|
||||
e_right->add_curve_to_left(this->m_subCurves + index);
|
||||
this->_add_curve_to_right(e_left, this->m_subCurves + index);
|
||||
}
|
||||
}
|
||||
|
||||
/*! Perform the sweep. */
|
||||
template <typename CurveInputIterator>
|
||||
void sweep(CurveInputIterator curves_begin, CurveInputIterator curves_end,
|
||||
std::size_t lower, std::size_t upper, std::size_t jump, std::vector<Arr_entry>& arr_vec) {
|
||||
this->m_visitor->before_sweep();
|
||||
pre_process(curves_begin, curves_end,lower, upper, jump, arr_vec);
|
||||
this->_sweep();
|
||||
this->_complete_sweep();
|
||||
this->m_visitor->after_sweep();
|
||||
}
|
||||
|
||||
return;
|
||||
/*! Perform the sweep. */
|
||||
template <typename CurveInputIterator>
|
||||
bool sweep_intercept(CurveInputIterator curves_begin, CurveInputIterator curves_end,
|
||||
std::size_t lower, std::size_t upper, std::size_t jump, std::vector<Arr_entry>& arr_vec) {
|
||||
this->m_visitor->before_sweep();
|
||||
pre_process(curves_begin, curves_end,lower, upper, jump, arr_vec);
|
||||
this->_sweep();
|
||||
this->_complete_sweep();
|
||||
this->m_visitor->after_sweep();
|
||||
return this->m_visitor->found_intersection();
|
||||
}
|
||||
|
||||
/*! Perform the sweep. */
|
||||
template <typename CurveInputIterator, typename InputIterator>
|
||||
bool sweep_intercept2(CurveInputIterator curves_begin, CurveInputIterator curves_end,
|
||||
InputIterator begin, InputIterator end) {
|
||||
this->m_visitor->before_sweep();
|
||||
pre_process2(curves_begin, curves_end, begin, end);
|
||||
this->_sweep();
|
||||
this->_complete_sweep();
|
||||
this->m_visitor->after_sweep();
|
||||
return this->m_visitor->found_intersection();
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
@ -218,8 +377,7 @@ private:
|
|||
* Check if the given vertex is an endpoint of an edge we are going
|
||||
* to use in the sweep.
|
||||
*/
|
||||
Attribute _type_of_vertex(Vertex_handle v)
|
||||
{
|
||||
Attribute _type_of_vertex(Vertex_handle v) {
|
||||
typename Arr::Halfedge_around_vertex_circulator first, circ;
|
||||
|
||||
circ = first = v->incident_halfedges();
|
||||
|
|
@ -232,7 +390,6 @@ private:
|
|||
else return (Event::LEFT_END);
|
||||
}
|
||||
++circ;
|
||||
|
||||
} while (circ != first);
|
||||
|
||||
// If we reached here, we should not keep this vertex.
|
||||
|
|
|
|||
|
|
@ -7,12 +7,12 @@
|
|||
// $Id$
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
//
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ron Wein <wein@post.tau.ac.il>
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ron Wein <wein@post.tau.ac.il>
|
||||
// Efi Fogel <efifogel@gmail.com>
|
||||
|
||||
#ifndef CGAL_BSO_2_GSP_AGG_OP_VISITOR_H
|
||||
#define CGAL_BSO_2_GSP_AGG_OP_VISITOR_H
|
||||
#ifndef CGAL_GSP_AGG_OP_VISITOR_H
|
||||
#define CGAL_GSP_AGG_OP_VISITOR_H
|
||||
|
||||
#include <CGAL/license/Boolean_set_operations_2.h>
|
||||
|
||||
|
|
@ -31,33 +31,29 @@ class Gps_agg_op_base_visitor :
|
|||
Helper_,
|
||||
typename Default::Get<Visitor_, Gps_agg_op_base_visitor<Helper_,
|
||||
Arrangement_,
|
||||
Visitor_> >::type>
|
||||
{
|
||||
Visitor_>>::type> {
|
||||
public:
|
||||
typedef Helper_ Helper;
|
||||
typedef Arrangement_ Arrangement_2;
|
||||
using Helper = Helper_;
|
||||
using Arrangement_2 = Arrangement_;
|
||||
|
||||
typedef typename Helper::Geometry_traits_2 Geometry_traits_2;
|
||||
typedef typename Helper::Event Event;
|
||||
typedef typename Helper::Subcurve Subcurve;
|
||||
using Geometry_traits_2 = typename Helper::Geometry_traits_2;
|
||||
using Event = typename Helper::Event;
|
||||
using Subcurve = typename Helper::Subcurve;
|
||||
|
||||
private:
|
||||
typedef Geometry_traits_2 Gt2;
|
||||
typedef Arrangement_2 Arr;
|
||||
|
||||
typedef Gps_agg_op_base_visitor<Helper, Arr, Visitor_>
|
||||
Self;
|
||||
typedef typename Default::Get<Visitor_, Self>::type Visitor;
|
||||
typedef Arr_construction_ss_visitor<Helper, Visitor> Base;
|
||||
using Gt2 = Geometry_traits_2;
|
||||
using Arr = Arrangement_2;
|
||||
using Self = Gps_agg_op_base_visitor<Helper, Arr, Visitor_>;
|
||||
using Visitor = typename Default::Get<Visitor_, Self>::type;
|
||||
using Base = Arr_construction_ss_visitor<Helper, Visitor>;
|
||||
|
||||
public:
|
||||
typedef typename Arr::Halfedge_handle Halfedge_handle;
|
||||
typedef typename Arr::Vertex_handle Vertex_handle;
|
||||
typedef typename Gt2::X_monotone_curve_2 X_monotone_curve_2;
|
||||
typedef typename Gt2::Point_2 Point_2;
|
||||
using Halfedge_handle = typename Arr::Halfedge_handle;
|
||||
using Vertex_handle = typename Arr::Vertex_handle;
|
||||
using X_monotone_curve_2 = typename Gt2::X_monotone_curve_2;
|
||||
using Point_2 = typename Gt2::Point_2;
|
||||
|
||||
typedef Unique_hash_map<Halfedge_handle, unsigned int>
|
||||
Edges_hash;
|
||||
using Edges_hash = Unique_hash_map<Halfedge_handle, std::size_t>;
|
||||
|
||||
protected:
|
||||
Edges_hash* m_edges_hash; // maps halfedges to their BC (coundary counter)
|
||||
|
|
@ -72,8 +68,7 @@ public:
|
|||
// TODO add mpl-warning
|
||||
|
||||
virtual Halfedge_handle insert_in_face_interior(const X_monotone_curve_2& cv,
|
||||
Subcurve* sc)
|
||||
{
|
||||
Subcurve* sc) {
|
||||
Halfedge_handle he = Base::insert_in_face_interior(cv, sc);
|
||||
insert_edge_to_hash(he, cv);
|
||||
return he;
|
||||
|
|
@ -83,8 +78,7 @@ public:
|
|||
Halfedge_handle hhandle,
|
||||
Halfedge_handle prev,
|
||||
Subcurve* sc,
|
||||
bool& new_face_created)
|
||||
{
|
||||
bool& new_face_created) {
|
||||
Halfedge_handle res_he =
|
||||
Base::insert_at_vertices(cv, hhandle, prev, sc, new_face_created);
|
||||
insert_edge_to_hash(res_he, cv);
|
||||
|
|
@ -93,8 +87,7 @@ public:
|
|||
|
||||
virtual Halfedge_handle insert_from_right_vertex(const X_monotone_curve_2& cv,
|
||||
Halfedge_handle he,
|
||||
Subcurve* sc)
|
||||
{
|
||||
Subcurve* sc) {
|
||||
Halfedge_handle res_he = Base::insert_from_right_vertex(cv, he, sc);
|
||||
insert_edge_to_hash(res_he, cv);
|
||||
return res_he;
|
||||
|
|
@ -102,16 +95,14 @@ public:
|
|||
|
||||
virtual Halfedge_handle insert_from_left_vertex(const X_monotone_curve_2& cv,
|
||||
Halfedge_handle he,
|
||||
Subcurve* sc)
|
||||
{
|
||||
Subcurve* sc) {
|
||||
Halfedge_handle res_he = Base::insert_from_left_vertex(cv, he, sc);
|
||||
insert_edge_to_hash(res_he, cv);
|
||||
return res_he;
|
||||
}
|
||||
|
||||
private:
|
||||
void insert_edge_to_hash(Halfedge_handle he, const X_monotone_curve_2& cv)
|
||||
{
|
||||
void insert_edge_to_hash(Halfedge_handle he, const X_monotone_curve_2& cv) {
|
||||
const Comparison_result he_dir =
|
||||
((Arr_halfedge_direction)he->direction() == ARR_LEFT_TO_RIGHT) ?
|
||||
SMALLER : LARGER;
|
||||
|
|
@ -133,54 +124,53 @@ private:
|
|||
|
||||
template <typename Helper_, typename Arrangement_, typename Visitor_ = Default>
|
||||
class Gps_agg_op_visitor :
|
||||
public Gps_agg_op_base_visitor<Helper_, Arrangement_,
|
||||
Gps_agg_op_visitor<Helper_, Arrangement_,
|
||||
Visitor_> >
|
||||
{
|
||||
public Gps_agg_op_base_visitor<
|
||||
Helper_, Arrangement_,
|
||||
typename Default::Get<Visitor_,
|
||||
Gps_agg_op_visitor<Helper_, Arrangement_, Visitor_>>::type> {
|
||||
public:
|
||||
typedef Helper_ Helper;
|
||||
typedef Arrangement_ Arrangement_2;
|
||||
using Helper = Helper_;
|
||||
using Arrangement_2 = Arrangement_;
|
||||
|
||||
typedef typename Helper::Geometry_traits_2 Geometry_traits_2;
|
||||
typedef typename Helper::Event Event;
|
||||
typedef typename Helper::Subcurve Subcurve;
|
||||
using Geometry_traits_2 = typename Helper::Geometry_traits_2;
|
||||
using Event = typename Helper::Event;
|
||||
using Subcurve = typename Helper::Subcurve;
|
||||
|
||||
private:
|
||||
typedef Geometry_traits_2 Gt2;
|
||||
typedef Arrangement_2 Arr;
|
||||
using Gt2 = Geometry_traits_2;
|
||||
using Arr = Arrangement_2;
|
||||
|
||||
typedef Gps_agg_op_visitor<Helper, Arr, Visitor_> Self;
|
||||
typedef typename Default::Get<Visitor_, Self>::type Visitor;
|
||||
typedef Gps_agg_op_base_visitor<Helper, Arr, Visitor> Base;
|
||||
using Self = Gps_agg_op_visitor<Helper, Arr, Visitor_>;
|
||||
using Visitor = typename Default::Get<Visitor_, Self>::type;
|
||||
using Base = Gps_agg_op_base_visitor<Helper, Arr, Visitor>;
|
||||
|
||||
public:
|
||||
typedef typename Base::Halfedge_handle Halfedge_handle;
|
||||
typedef typename Base::Vertex_handle Vertex_handle;
|
||||
typedef typename Gt2::X_monotone_curve_2 X_monotone_curve_2;
|
||||
typedef typename Gt2::Point_2 Point_2;
|
||||
using Edges_hash = typename Base::Edges_hash;
|
||||
using Halfedge_handle = typename Base::Halfedge_handle;
|
||||
using Vertex_handle = typename Base::Vertex_handle;
|
||||
using X_monotone_curve_2 = typename Gt2::X_monotone_curve_2;
|
||||
using Point_2 = typename Gt2::Point_2;
|
||||
|
||||
protected:
|
||||
unsigned int m_event_count; // The number of events so far.
|
||||
std::size_t m_event_count; // The number of events so far.
|
||||
std::vector<Vertex_handle>* m_vertices_vec; // The vertices, sorted in
|
||||
// ascending order.
|
||||
|
||||
public:
|
||||
Gps_agg_op_visitor(Arr* arr, typename Base::Edges_hash* hash,
|
||||
Gps_agg_op_visitor(Arr* arr, Edges_hash* hash,
|
||||
std::vector<Vertex_handle>* vertices_vec) :
|
||||
Base(arr, hash),
|
||||
m_event_count(0),
|
||||
m_vertices_vec(vertices_vec)
|
||||
{}
|
||||
|
||||
void before_handle_event(Event* event)
|
||||
{
|
||||
void before_handle_event(Event* event) {
|
||||
event->set_index(m_event_count);
|
||||
m_event_count++;
|
||||
}
|
||||
|
||||
virtual Halfedge_handle
|
||||
insert_in_face_interior(const X_monotone_curve_2& cv, Subcurve* sc)
|
||||
{
|
||||
insert_in_face_interior(const X_monotone_curve_2& cv, Subcurve* sc) {
|
||||
Halfedge_handle res_he = Base::insert_in_face_interior(cv, sc);
|
||||
|
||||
// We now have a halfedge whose source vertex is associated with the
|
||||
|
|
@ -198,8 +188,7 @@ public:
|
|||
|
||||
virtual Halfedge_handle insert_from_right_vertex(const X_monotone_curve_2& cv,
|
||||
Halfedge_handle he,
|
||||
Subcurve* sc)
|
||||
{
|
||||
Subcurve* sc) {
|
||||
Halfedge_handle res_he = Base::insert_from_right_vertex(cv, he, sc);
|
||||
|
||||
// We now have a halfedge whose target vertex is associated with the
|
||||
|
|
@ -213,9 +202,8 @@ public:
|
|||
|
||||
virtual Halfedge_handle insert_from_left_vertex(const X_monotone_curve_2& cv,
|
||||
Halfedge_handle he,
|
||||
Subcurve* sc)
|
||||
{
|
||||
Halfedge_handle res_he = Base::insert_from_left_vertex(cv, he, sc);
|
||||
Subcurve* sc) {
|
||||
Halfedge_handle res_he = Base::insert_from_left_vertex(cv, he, sc);
|
||||
|
||||
// We now have a halfedge whose target vertex is associated with the
|
||||
// current event(we have already dealt with its source vertex).
|
||||
|
|
@ -223,18 +211,16 @@ public:
|
|||
|
||||
CGAL_assertion((Arr_halfedge_direction)res_he->direction() ==
|
||||
ARR_LEFT_TO_RIGHT);
|
||||
_insert_vertex (curr_event, res_he->target());
|
||||
_insert_vertex(curr_event, res_he->target());
|
||||
return res_he;
|
||||
}
|
||||
|
||||
private:
|
||||
void _insert_vertex(const Event* event, Vertex_handle v)
|
||||
{
|
||||
const unsigned int index = event->index();
|
||||
void _insert_vertex(const Event* event, Vertex_handle v) {
|
||||
const auto index = event->index();
|
||||
if (index >= m_vertices_vec->size()) m_vertices_vec->resize(2 * (index + 1));
|
||||
(*m_vertices_vec)[index] = v;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // namespace CGAL
|
||||
|
|
|
|||
|
|
@ -8,90 +8,83 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
//
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ophir Setter <ophir.setter@cs.tau.ac.il>
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ophir Setter <ophir.setter@cs.tau.ac.il>
|
||||
|
||||
#ifndef CGAL_GPS_BPS_BASE_VISITOR_H
|
||||
#define CGAL_GPS_BPS_BASE_VISITOR_H
|
||||
|
||||
#include <CGAL/license/Boolean_set_operations_2.h>
|
||||
|
||||
|
||||
#include <CGAL/Unique_hash_map.h>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
//! Gps_bfs_base_visitor
|
||||
/*! This is a base class for all visitors that are responsible for merging
|
||||
polygon sets.
|
||||
We use DerivedVisitor for static polymorphism for using contained_criteria
|
||||
which determines if we should mark the face as contained given the inside
|
||||
count of the face.
|
||||
*/
|
||||
template <class Arrangement_, class DerivedVisitor>
|
||||
class Gps_bfs_base_visitor
|
||||
{
|
||||
typedef Arrangement_ Arrangement;
|
||||
typedef typename Arrangement::Face_iterator Face_iterator;
|
||||
typedef typename Arrangement::Halfedge_iterator Halfedge_iterator;
|
||||
* polygon sets.
|
||||
* We use DerivedVisitor for static polymorphism for using contained_criteria
|
||||
* which determines if we should mark the face as contained given the inside
|
||||
* count of the face.
|
||||
*/
|
||||
template <typename Arrangement_, typename DerivedVisitor>
|
||||
class Gps_bfs_base_visitor {
|
||||
using Arrangement = Arrangement_;
|
||||
using Face_iterator = typename Arrangement::Face_iterator;
|
||||
using Halfedge_iterator = typename Arrangement::Halfedge_iterator;
|
||||
|
||||
public:
|
||||
typedef Unique_hash_map<Halfedge_iterator, unsigned int> Edges_hash;
|
||||
typedef Unique_hash_map<Face_iterator, unsigned int> Faces_hash;
|
||||
using Edges_hash = Unique_hash_map<Halfedge_iterator, std::size_t>;
|
||||
using Faces_hash = Unique_hash_map<Face_iterator, std::size_t>;
|
||||
|
||||
protected:
|
||||
Edges_hash* m_edges_hash;
|
||||
Faces_hash* m_faces_hash;
|
||||
unsigned int m_num_of_polygons; // number of polygons
|
||||
Edges_hash* m_edges_hash;
|
||||
Faces_hash* m_faces_hash;
|
||||
std::size_t m_num_of_polygons; // number of polygons
|
||||
|
||||
public:
|
||||
|
||||
Gps_bfs_base_visitor(Edges_hash* edges_hash,
|
||||
Faces_hash* faces_hash,
|
||||
unsigned int n_pgn):
|
||||
std::size_t n_pgn):
|
||||
m_edges_hash(edges_hash),
|
||||
m_faces_hash(faces_hash),
|
||||
m_num_of_polygons(n_pgn)
|
||||
{}
|
||||
|
||||
|
||||
//! discovered_face
|
||||
/*! discovered_face is called by Gps_bfs_scanner when it reveals a new face
|
||||
during a BFS scan. In the BFS traversal we are going from old_face to
|
||||
new_face through the half-edge he.
|
||||
\param old_face The face that was already revealed
|
||||
\param new_face The face that we have just now revealed
|
||||
\param he The half-edge that is used to traverse between them.
|
||||
*/
|
||||
//! discovered_face
|
||||
/*! discovered_face is called by Gps_bfs_scanner when it reveals a new face
|
||||
* during a BFS scan. In the BFS traversal we are going from old_face to
|
||||
* new_face through the half-edge he.
|
||||
* \param old_face The face that was already revealed
|
||||
* \param new_face The face that we have just now revealed
|
||||
* \param he The half-edge that is used to traverse between them.
|
||||
*/
|
||||
void discovered_face(Face_iterator old_face,
|
||||
Face_iterator new_face,
|
||||
Halfedge_iterator he)
|
||||
{
|
||||
unsigned int ic = compute_ic(old_face, new_face, he);
|
||||
Halfedge_iterator he) {
|
||||
std::size_t ic = compute_ic(old_face, new_face, he);
|
||||
|
||||
if (static_cast<DerivedVisitor*>(this)->contained_criteria(ic))
|
||||
new_face->set_contained(true);
|
||||
}
|
||||
|
||||
// mark the unbounded_face (true iff contained)
|
||||
void visit_ubf(Face_iterator ubf, unsigned int ubf_ic)
|
||||
{
|
||||
void visit_ubf(Face_iterator ubf, std::size_t ubf_ic) {
|
||||
CGAL_assertion(ubf->is_unbounded());
|
||||
if(static_cast<DerivedVisitor*>(this)->contained_criteria(ubf_ic))
|
||||
if (static_cast<DerivedVisitor*>(this)->contained_criteria(ubf_ic))
|
||||
ubf->set_contained(true);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
// compute the inside count of a face
|
||||
unsigned int compute_ic(Face_iterator f1,
|
||||
Face_iterator f2,
|
||||
Halfedge_iterator he)
|
||||
{
|
||||
std::size_t compute_ic(Face_iterator f1,
|
||||
Face_iterator f2,
|
||||
Halfedge_iterator he) {
|
||||
CGAL_assertion(m_edges_hash->is_defined(he) &&
|
||||
m_edges_hash->is_defined(he->twin()) &&
|
||||
m_faces_hash->is_defined(f1) &&
|
||||
!m_faces_hash->is_defined(f2));
|
||||
unsigned int ic_f2 =
|
||||
! m_faces_hash->is_defined(f2));
|
||||
std::size_t ic_f2 =
|
||||
(*m_faces_hash)[f1] - (*m_edges_hash)[he] + (*m_edges_hash)[he->twin()];
|
||||
(*m_faces_hash)[f2] = ic_f2;
|
||||
|
||||
|
|
|
|||
|
|
@ -7,59 +7,50 @@
|
|||
// $Id$
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
//
|
||||
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ophir Setter <ophir.setter@cs.tau.ac.il>
|
||||
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ophir Setter <ophir.setter@cs.tau.ac.il>
|
||||
// Efi Fogel <efifogel@gmail.com>
|
||||
|
||||
#ifndef CGAL_GPS_BFS_INTERSECTION_VISITOR_H
|
||||
#define CGAL_GPS_BFS_INTERSECTION_VISITOR_H
|
||||
|
||||
#include <CGAL/license/Boolean_set_operations_2.h>
|
||||
|
||||
|
||||
#include <CGAL/Boolean_set_operations_2/Gps_bfs_base_visitor.h>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
template <class Arrangement_>
|
||||
template <typename Arrangement_>
|
||||
class Gps_bfs_intersection_visitor :
|
||||
public Gps_bfs_base_visitor<Arrangement_, Gps_bfs_intersection_visitor<Arrangement_> >
|
||||
{
|
||||
typedef Arrangement_ Arrangement;
|
||||
typedef typename Arrangement::Face_iterator Face_iterator;
|
||||
typedef typename Arrangement::Halfedge_iterator Halfedge_iterator;
|
||||
typedef Gps_bfs_intersection_visitor<Arrangement> Self;
|
||||
typedef Gps_bfs_base_visitor<Arrangement, Self> Base;
|
||||
typedef typename Base::Edges_hash Edges_hash;
|
||||
typedef typename Base::Faces_hash Faces_hash;
|
||||
|
||||
public Gps_bfs_base_visitor<Arrangement_, Gps_bfs_intersection_visitor<Arrangement_>> {
|
||||
using Arrangement = Arrangement_;
|
||||
using Face_iterator = typename Arrangement::Face_iterator;
|
||||
using Halfedge_iterator = typename Arrangement::Halfedge_iterator;
|
||||
using Self = Gps_bfs_intersection_visitor<Arrangement>;
|
||||
using Base = Gps_bfs_base_visitor<Arrangement, Self>;
|
||||
using Edges_hash = typename Base::Edges_hash;
|
||||
using Faces_hash = typename Base::Faces_hash;
|
||||
|
||||
public:
|
||||
|
||||
Gps_bfs_intersection_visitor(Edges_hash* edges_hash,
|
||||
Faces_hash* faces_hash,
|
||||
unsigned int n_polygons):
|
||||
std::size_t n_polygons):
|
||||
Base(edges_hash, faces_hash, n_polygons)
|
||||
{}
|
||||
|
||||
|
||||
//! contained_criteria
|
||||
/*! contained_criteria is used to the determine if the face which has
|
||||
inside count should be marked as contained.
|
||||
\param ic the inner count of the talked-about face.
|
||||
\return true if the face of ic, otherwise false.
|
||||
*/
|
||||
bool contained_criteria(unsigned int ic)
|
||||
{
|
||||
//! contained_criteria
|
||||
/*! contained_criteria is used to the determine if the face which has
|
||||
* inside count should be marked as contained.
|
||||
* \param ic the inner count of the talked-about face.
|
||||
* \return true if the face of ic, otherwise false.
|
||||
*/
|
||||
bool contained_criteria(std::size_t ic) {
|
||||
// intersection means that all polygons contain the face.
|
||||
CGAL_assertion(ic <= this->m_num_of_polygons);
|
||||
return (ic == this->m_num_of_polygons);
|
||||
}
|
||||
|
||||
void after_scan(Arrangement&)
|
||||
{}
|
||||
void after_scan(Arrangement&) {}
|
||||
};
|
||||
|
||||
} //namespace CGAL
|
||||
|
|
|
|||
|
|
@ -8,52 +8,46 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
//
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ophir Setter <ophir.setter@cs.tau.ac.il>
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ophir Setter <ophir.setter@cs.tau.ac.il>
|
||||
|
||||
#ifndef CGAL_GPS_BFS_JOIN_VISITOR_H
|
||||
#define CGAL_GPS_BFS_JOIN_VISITOR_H
|
||||
|
||||
#include <CGAL/license/Boolean_set_operations_2.h>
|
||||
|
||||
|
||||
#include <CGAL/Boolean_set_operations_2/Gps_bfs_base_visitor.h>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
template <class Arrangement_>
|
||||
template <typename Arrangement_>
|
||||
class Gps_bfs_join_visitor :
|
||||
public Gps_bfs_base_visitor<Arrangement_, Gps_bfs_join_visitor<Arrangement_> >
|
||||
{
|
||||
typedef Arrangement_ Arrangement;
|
||||
typedef typename Arrangement::Face_iterator Face_iterator;
|
||||
typedef typename Arrangement::Halfedge_iterator Halfedge_iterator;
|
||||
typedef Gps_bfs_join_visitor<Arrangement> Self;
|
||||
typedef Gps_bfs_base_visitor<Arrangement, Self> Base;
|
||||
typedef typename Base::Edges_hash Edges_hash;
|
||||
typedef typename Base::Faces_hash Faces_hash;
|
||||
public Gps_bfs_base_visitor<Arrangement_, Gps_bfs_join_visitor<Arrangement_>> {
|
||||
using Arrangement = Arrangement_;
|
||||
using Face_iterator = typename Arrangement::Face_iterator;
|
||||
using Halfedge_iterator = typename Arrangement::Halfedge_iterator;
|
||||
using Self = Gps_bfs_join_visitor<Arrangement>;
|
||||
using Base = Gps_bfs_base_visitor<Arrangement, Self>;
|
||||
using Edges_hash = typename Base::Edges_hash;
|
||||
using Faces_hash = typename Base::Faces_hash;
|
||||
|
||||
public:
|
||||
|
||||
Gps_bfs_join_visitor(Edges_hash* edges_hash, Faces_hash* faces_hash, unsigned int n_pgn):
|
||||
Gps_bfs_join_visitor(Edges_hash* edges_hash, Faces_hash* faces_hash, std::size_t n_pgn):
|
||||
Base(edges_hash, faces_hash, n_pgn)
|
||||
{}
|
||||
|
||||
//! contained_criteria
|
||||
/*! contained_criteria is used to the determine if the face which has
|
||||
inside count should be marked as contained.
|
||||
\param ic the inner count of the talked-about face.
|
||||
\return true if the face of ic, otherwise false.
|
||||
*/
|
||||
bool contained_criteria(unsigned int ic)
|
||||
{
|
||||
//! contained_criteria
|
||||
/*! contained_criteria is used to the determine if the face which has
|
||||
* inside count should be marked as contained.
|
||||
* \param ic the inner count of the talked-about face.
|
||||
* \return true if the face of ic, otherwise false.
|
||||
*/
|
||||
bool contained_criteria(std::size_t ic) {
|
||||
// at least one polygon contains the face.
|
||||
return (ic > 0);
|
||||
}
|
||||
|
||||
void after_scan(Arrangement&)
|
||||
{}
|
||||
|
||||
void after_scan(Arrangement&) {}
|
||||
};
|
||||
|
||||
} //namespace CGAL
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
//
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ophir Setter <ophir.setter@cs.tau.ac.il>
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ophir Setter <ophir.setter@cs.tau.ac.il>
|
||||
|
||||
#ifndef CGAL_GPS_BFS_XOR_VISITOR_H
|
||||
#define CGAL_GPS_BFS_XOR_VISITOR_H
|
||||
|
|
@ -21,73 +21,61 @@
|
|||
|
||||
namespace CGAL {
|
||||
|
||||
template <class Arrangement_>
|
||||
template <typename Arrangement_>
|
||||
class Gps_bfs_xor_visitor :
|
||||
public Gps_bfs_base_visitor<Arrangement_, Gps_bfs_xor_visitor<Arrangement_> >
|
||||
{
|
||||
typedef Arrangement_ Arrangement;
|
||||
typedef typename Arrangement::Face_iterator Face_iterator;
|
||||
typedef typename Arrangement::Halfedge_iterator Halfedge_iterator;
|
||||
typedef Gps_bfs_xor_visitor<Arrangement> Self;
|
||||
typedef Gps_bfs_base_visitor<Arrangement, Self> Base;
|
||||
typedef typename Base::Edges_hash Edges_hash;
|
||||
typedef typename Base::Faces_hash Faces_hash;
|
||||
public Gps_bfs_base_visitor<Arrangement_, Gps_bfs_xor_visitor<Arrangement_>> {
|
||||
using Arrangement = Arrangement_;
|
||||
using Face_iterator = typename Arrangement::Face_iterator;
|
||||
using Halfedge_iterator = typename Arrangement::Halfedge_iterator;
|
||||
using Self = Gps_bfs_xor_visitor<Arrangement>;
|
||||
using Base = Gps_bfs_base_visitor<Arrangement, Self>;
|
||||
using Edges_hash = typename Base::Edges_hash;
|
||||
using Faces_hash = typename Base::Faces_hash;
|
||||
|
||||
public:
|
||||
|
||||
Gps_bfs_xor_visitor(Edges_hash* edges_hash, Faces_hash* faces_hash,
|
||||
unsigned int n_pgn) :
|
||||
std::size_t n_pgn) :
|
||||
Base(edges_hash, faces_hash, n_pgn)
|
||||
{}
|
||||
|
||||
//! contained_criteria
|
||||
//! contained_criteria
|
||||
/*! contained_criteria is used to the determine if the face which has
|
||||
inside count should be marked as contained.
|
||||
\param ic the inner count of the talked-about face.
|
||||
\return true if the face of ic, otherwise false.
|
||||
*/
|
||||
bool contained_criteria(unsigned int ic)
|
||||
{
|
||||
bool contained_criteria(std::size_t ic) {
|
||||
// xor means odd number of polygons.
|
||||
return (ic % 2) == 1;
|
||||
}
|
||||
|
||||
//! after_scan postprocessing after bfs scan.
|
||||
/*! The function fixes some of the curves, to be in the same direction as the
|
||||
half-edges.
|
||||
|
||||
\param arr The given arrangement.
|
||||
*/
|
||||
void after_scan(Arrangement& arr)
|
||||
{
|
||||
typedef typename Arrangement::Geometry_traits_2 Traits;
|
||||
typedef typename Traits::Compare_endpoints_xy_2 Compare_endpoints_xy_2;
|
||||
typedef typename Traits::Construct_opposite_2 Construct_opposite_2;
|
||||
typedef typename Traits::X_monotone_curve_2 X_monotone_curve_2;
|
||||
typedef typename Arrangement::Edge_iterator Edge_iterator;
|
||||
/*! The function fixes some of the curves, to be in the same direction as the
|
||||
* half-edges.
|
||||
*
|
||||
* \param arr The given arrangement.
|
||||
*/
|
||||
void after_scan(Arrangement& arr) {
|
||||
using Traits = typename Arrangement::Geometry_traits_2;
|
||||
using X_monotone_curve_2 = typename Traits::X_monotone_curve_2;
|
||||
|
||||
Traits tr;
|
||||
Compare_endpoints_xy_2 cmp_endpoints =
|
||||
tr.compare_endpoints_xy_2_object();
|
||||
Construct_opposite_2 ctr_opp = tr.construct_opposite_2_object();
|
||||
auto cmp_endpoints = tr.compare_endpoints_xy_2_object();
|
||||
auto ctr_opp = tr.construct_opposite_2_object();
|
||||
|
||||
for(Edge_iterator eit = arr.edges_begin();
|
||||
eit != arr.edges_end();
|
||||
++eit)
|
||||
{
|
||||
Halfedge_iterator he = eit;
|
||||
for (auto eit = arr.edges_begin(); eit != arr.edges_end(); ++eit) {
|
||||
Halfedge_iterator he = eit;
|
||||
const X_monotone_curve_2& cv = he->curve();
|
||||
const bool is_cont = he->face()->contained();
|
||||
const Comparison_result he_res =
|
||||
const bool is_cont = he->face()->contained();
|
||||
const Comparison_result he_res =
|
||||
((Arr_halfedge_direction)he->direction() == ARR_LEFT_TO_RIGHT) ?
|
||||
SMALLER : LARGER;
|
||||
SMALLER : LARGER;
|
||||
const bool has_same_dir = (cmp_endpoints(cv) == he_res);
|
||||
|
||||
if ((is_cont && !has_same_dir) || (!is_cont && has_same_dir))
|
||||
arr.modify_edge(he, ctr_opp(cv));
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} //namespace CGAL
|
||||
|
|
|
|||
|
|
@ -0,0 +1,93 @@
|
|||
// Copyright (c) 2005 Tel-Aviv University (Israel).
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of CGAL (www.cgal.org).
|
||||
//
|
||||
// $URL$
|
||||
// $Id$
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
// Author(s) : Efi Fogel <efifogel@gmail.com>
|
||||
|
||||
#ifndef CGAL_GSP_DO_INTERSECT_AGG_OP_VISITOR_H
|
||||
#define CGAL_GSP_DO_INTERSECT_AGG_OP_VISITOR_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <CGAL/license/Boolean_set_operations_2.h>
|
||||
#include <CGAL/Boolean_set_operations_2/Gps_agg_op_visitor.h>
|
||||
#include <CGAL/Default.h>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
template <typename Helper_, typename Arrangement_, typename Visitor_ = Default>
|
||||
class Gps_do_intersect_agg_op_visitor :
|
||||
public Gps_agg_op_visitor<
|
||||
Helper_, Arrangement_,
|
||||
typename Default::Get<Visitor_, Gps_do_intersect_agg_op_visitor<Helper_, Arrangement_, Visitor_>>::type> {
|
||||
public:
|
||||
using Helper = Helper_;
|
||||
using Arrangement_2 = Arrangement_;
|
||||
using Geometry_traits_2 = typename Helper::Geometry_traits_2;
|
||||
using Event = typename Helper::Event;
|
||||
using Subcurve = typename Helper::Subcurve;
|
||||
|
||||
private:
|
||||
using Gt2 = Geometry_traits_2;
|
||||
using Arr = Arrangement_2;
|
||||
using Self = Gps_do_intersect_agg_op_visitor<Helper, Arr, Visitor_>;
|
||||
using Visitor = typename Default::Get<Visitor_, Self>::type;
|
||||
using Base = Gps_agg_op_visitor<Helper, Arr, Visitor>;
|
||||
|
||||
protected:
|
||||
bool m_found_x;
|
||||
|
||||
public:
|
||||
using Edges_hash = typename Base::Edges_hash;
|
||||
using Vertex_handle = typename Base::Vertex_handle;
|
||||
using Status_line_iterator = typename Base::Status_line_iterator;
|
||||
using X_monotone_curve_2 = typename Base::X_monotone_curve_2;
|
||||
using Point_2 = typename Base::Point_2;
|
||||
using Multiplicity = typename Base::Multiplicity;
|
||||
|
||||
Gps_do_intersect_agg_op_visitor(Arr* arr, Edges_hash* hash,
|
||||
std::vector<Vertex_handle>* vertices_vec) :
|
||||
Base(arr, hash, vertices_vec),
|
||||
m_found_x(false)
|
||||
{}
|
||||
|
||||
/*! Update an event that corresponds to a curve endpoint. */
|
||||
void update_event(Event* e, const Point_2& end_point, const X_monotone_curve_2& cv, Arr_curve_end cv_end, bool is_new)
|
||||
{ Base::update_event(e, end_point, cv, cv_end, is_new); }
|
||||
|
||||
/*! Update an event that corresponds to a curve endpoint */
|
||||
void update_event(Event* e, const X_monotone_curve_2& cv, Arr_curve_end cv_end, bool is_new )
|
||||
{ Base::update_event(e, cv, cv_end, is_new); }
|
||||
|
||||
/*! Update an event that corresponds to a curve endpoint */
|
||||
void update_event(Event* e, const Point_2& p, bool is_new)
|
||||
{ Base::update_event(e, p, is_new); }
|
||||
|
||||
/*! Update an event that corresponds to an intersection */
|
||||
void update_event(Event* e, Subcurve* sc) { Base::update_event(e, sc); }
|
||||
|
||||
/*! Update an event that corresponds to an intersection between curves */
|
||||
void update_event(Event* e, Subcurve* sc1, Subcurve* sc2, bool is_new, Multiplicity multiplicity) {
|
||||
if ((multiplicity % 2) == 1) m_found_x = true;
|
||||
Base::update_event(e, sc1, sc2, is_new, multiplicity);
|
||||
}
|
||||
|
||||
//!
|
||||
bool after_handle_event(Event* e, Status_line_iterator iter, bool flag) {
|
||||
auto res = Base::after_handle_event(e, iter, flag);
|
||||
if (m_found_x) this->surface_sweep()->stop_sweep();
|
||||
return res;
|
||||
}
|
||||
|
||||
/*! Getter */
|
||||
bool found_intersection() { return m_found_x; }
|
||||
};
|
||||
|
||||
} // namespace CGAL
|
||||
|
||||
#endif
|
||||
|
|
@ -15,112 +15,61 @@
|
|||
|
||||
#include <CGAL/license/Boolean_set_operations_2.h>
|
||||
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
template <class Arrangement_>
|
||||
class Gps_do_intersect_functor
|
||||
{
|
||||
template <typename Arrangement_>
|
||||
class Gps_do_intersect_functor {
|
||||
public:
|
||||
using Arrangement_2 = Arrangement_;
|
||||
|
||||
typedef Arrangement_ Arrangement_2;
|
||||
using Face_const_handle = typename Arrangement_2::Face_const_handle;
|
||||
using Vertex_const_handle = typename Arrangement_2::Vertex_const_handle;
|
||||
using Halfedge_const_handle = typename Arrangement_2::Halfedge_const_handle;
|
||||
|
||||
typedef typename Arrangement_2::Face_const_handle Face_const_handle;
|
||||
typedef typename Arrangement_2::Vertex_const_handle Vertex_const_handle;
|
||||
typedef typename Arrangement_2::Halfedge_const_handle Halfedge_const_handle;
|
||||
|
||||
typedef typename Arrangement_2::Face_handle Face_handle;
|
||||
typedef typename Arrangement_2::Halfedge_handle Halfedge_handle;
|
||||
typedef typename Arrangement_2::Vertex_handle Vertex_handle;
|
||||
using Face_handle = typename Arrangement_2::Face_handle;
|
||||
using Halfedge_handle = typename Arrangement_2::Halfedge_handle;
|
||||
using Vertex_handle = typename Arrangement_2::Vertex_handle;
|
||||
|
||||
// default constructor
|
||||
Gps_do_intersect_functor() : m_found_reg_intersection(false),
|
||||
m_found_boudary_intersection(false)
|
||||
|
||||
Gps_do_intersect_functor() :
|
||||
m_found_reg_intersection(false),
|
||||
m_found_boudary_intersection(false)
|
||||
{}
|
||||
|
||||
void create_face (Face_const_handle f1,
|
||||
Face_const_handle f2,
|
||||
Face_handle )
|
||||
{
|
||||
if(f1->contained() && f2->contained())
|
||||
// found intersection
|
||||
m_found_reg_intersection = true;
|
||||
}
|
||||
void create_face(Face_const_handle f1, Face_const_handle f2, Face_handle)
|
||||
{ if (f1->contained() && f2->contained()) m_found_reg_intersection = true; }
|
||||
|
||||
void create_vertex(Vertex_const_handle, Vertex_const_handle, Vertex_handle)
|
||||
{ m_found_boudary_intersection = true; }
|
||||
|
||||
void create_vertex(Vertex_const_handle ,
|
||||
Vertex_const_handle ,
|
||||
Vertex_handle )
|
||||
{
|
||||
m_found_boudary_intersection = true;
|
||||
}
|
||||
void create_vertex(Vertex_const_handle, Halfedge_const_handle, Vertex_handle)
|
||||
{ m_found_boudary_intersection = true; }
|
||||
|
||||
void create_vertex(Vertex_const_handle ,
|
||||
Halfedge_const_handle ,
|
||||
Vertex_handle )
|
||||
{
|
||||
m_found_boudary_intersection = true;
|
||||
}
|
||||
void create_vertex(Halfedge_const_handle, Vertex_const_handle, Vertex_handle)
|
||||
{ m_found_boudary_intersection = true; }
|
||||
|
||||
void create_vertex(Halfedge_const_handle ,
|
||||
Vertex_const_handle ,
|
||||
Vertex_handle )
|
||||
{
|
||||
m_found_boudary_intersection = true;
|
||||
}
|
||||
void create_vertex(Halfedge_const_handle, Halfedge_const_handle, Vertex_handle) {}
|
||||
|
||||
void create_vertex(Halfedge_const_handle ,
|
||||
Halfedge_const_handle ,
|
||||
Vertex_handle )
|
||||
{}
|
||||
void create_vertex(Face_const_handle, Vertex_const_handle, Vertex_handle) {}
|
||||
|
||||
void create_vertex(Vertex_const_handle, Face_const_handle, Vertex_handle) {}
|
||||
|
||||
void create_vertex(Face_const_handle ,
|
||||
Vertex_const_handle ,
|
||||
Vertex_handle )
|
||||
{}
|
||||
void create_edge(Halfedge_const_handle, Halfedge_const_handle, Halfedge_handle)
|
||||
{ m_found_boudary_intersection = true; }
|
||||
|
||||
void create_vertex(Vertex_const_handle ,
|
||||
Face_const_handle ,
|
||||
Vertex_handle )
|
||||
{}
|
||||
void create_edge(Halfedge_const_handle, Face_const_handle, Halfedge_handle) {}
|
||||
|
||||
void create_edge(Halfedge_const_handle ,
|
||||
Halfedge_const_handle ,
|
||||
Halfedge_handle )
|
||||
{
|
||||
m_found_boudary_intersection = true;
|
||||
}
|
||||
void create_edge(Face_const_handle, Halfedge_const_handle, Halfedge_handle) {}
|
||||
|
||||
void create_edge(Halfedge_const_handle ,
|
||||
Face_const_handle ,
|
||||
Halfedge_handle )
|
||||
{}
|
||||
bool found_reg_intersection() const { return m_found_reg_intersection; }
|
||||
|
||||
void create_edge(Face_const_handle ,
|
||||
Halfedge_const_handle ,
|
||||
Halfedge_handle )
|
||||
{}
|
||||
bool found_boundary_intersection() const { return m_found_boudary_intersection; }
|
||||
|
||||
|
||||
bool found_reg_intersection() const
|
||||
{
|
||||
return m_found_reg_intersection;
|
||||
}
|
||||
|
||||
bool found_boundary_intersection() const
|
||||
{
|
||||
return m_found_boudary_intersection;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
bool m_found_reg_intersection;
|
||||
bool m_found_boudary_intersection;
|
||||
protected:
|
||||
bool m_found_reg_intersection;
|
||||
bool m_found_boudary_intersection;
|
||||
};
|
||||
|
||||
|
||||
} //namespace CGAL
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -7,15 +7,17 @@
|
|||
// $Id$
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Efi Fogel <efifogel@gmail.com>
|
||||
|
||||
#ifndef CGAL_GPS_MERGE_H
|
||||
#define CGAL_GPS_MERGE_H
|
||||
|
||||
#include <CGAL/license/Boolean_set_operations_2.h>
|
||||
|
||||
|
||||
#include <CGAL/Boolean_set_operations_2/Gps_agg_op.h>
|
||||
#include <CGAL/Boolean_set_operations_2/Gps_agg_op_visitor.h>
|
||||
#include <CGAL/Boolean_set_operations_2/Gps_do_intersect_agg_op_visitor.h>
|
||||
#include <CGAL/Boolean_set_operations_2/Gps_bfs_join_visitor.h>
|
||||
#include <CGAL/Boolean_set_operations_2/Gps_bfs_xor_visitor.h>
|
||||
#include <CGAL/Boolean_set_operations_2/Gps_bfs_intersection_visitor.h>
|
||||
|
|
@ -23,50 +25,40 @@
|
|||
|
||||
namespace CGAL {
|
||||
|
||||
/*!
|
||||
\file Gps_merge.h
|
||||
\brief This file contains classes that are responsible for merging
|
||||
two sets of polygons in the divide-and-conquer algorithm.
|
||||
The file contains 3 mergers: Join_merge, Intersection_merge and
|
||||
Xor_merge. Join_merge is used when we want to merge the two sets,
|
||||
Intersection_merge is used for intersection, and Xor_merge is used
|
||||
for symmetric difference.
|
||||
*/
|
||||
|
||||
//! Base_merge
|
||||
/*! Base_merge is the base class for all merger classes.
|
||||
All merges used BFS algorithm with a different visitor when discovering
|
||||
a new face.
|
||||
/*! \file Gps_merge.h
|
||||
*
|
||||
* This file contains classes that are responsible for merging two sets of
|
||||
* polygons in the divide-and-conquer algorithm. The file contains 3 mergers:
|
||||
* Join_merge, Intersection_merge and Xor_merge. Join_merge is used when we want
|
||||
* to merge the two sets, Intersection_merge is used for intersection, and
|
||||
* Xor_merge is used for symmetric difference.
|
||||
*/
|
||||
template <class Arrangement_, class Visitor_>
|
||||
class Base_merge
|
||||
{
|
||||
typedef Arrangement_ Arrangement_2;
|
||||
typedef Visitor_ Visitor;
|
||||
typedef typename Arrangement_2::Vertex_handle Vertex_handle;
|
||||
typedef std::pair<Arrangement_2 *,
|
||||
std::vector<Vertex_handle> *> Arr_entry;
|
||||
|
||||
/*! Base_merge
|
||||
* Base_merge is the base class for all merger classes.
|
||||
* All merges used BFS algorithm with a different visitor when discovering
|
||||
* a new face.
|
||||
*/
|
||||
template <typename Arrangement_, typename Visitor_>
|
||||
class Base_merge {
|
||||
using Arrangement_2 = Arrangement_;
|
||||
using Visitor = Visitor_;
|
||||
using Vertex_handle = typename Arrangement_2::Vertex_handle;
|
||||
using Arr_entry = std::pair<Arrangement_2*, std::vector<Vertex_handle>*>;
|
||||
|
||||
public:
|
||||
void operator()(unsigned int i,
|
||||
unsigned int j,
|
||||
unsigned int jump,
|
||||
std::vector<Arr_entry>& arr_vec)
|
||||
{
|
||||
if(i==j)
|
||||
return;
|
||||
void operator()(std::size_t i, std::size_t j, std::size_t jump, std::vector<Arr_entry>& arr_vec) {
|
||||
if (i == j) return;
|
||||
|
||||
const typename Arrangement_2::Geometry_traits_2 * tr =
|
||||
arr_vec[i].first->geometry_traits();
|
||||
Arrangement_2 *res = new Arrangement_2(tr);
|
||||
std::vector<Vertex_handle> *verts = new std::vector<Vertex_handle>;
|
||||
const auto* tr = arr_vec[i].first->geometry_traits();
|
||||
Arrangement_2* res = new Arrangement_2(tr);
|
||||
std::vector<Vertex_handle>* verts = new std::vector<Vertex_handle>;
|
||||
|
||||
Gps_agg_op<Arrangement_2, Visitor>
|
||||
agg_op(*res, *verts, *(res->traits_adaptor()));
|
||||
using Agg_op = Gps_agg_op<Arrangement_2, Visitor, Gps_agg_op_visitor>;
|
||||
Agg_op agg_op(*res, *verts, *(res->traits_adaptor()));
|
||||
agg_op.sweep_arrangements(i, j, jump, arr_vec);
|
||||
|
||||
for(unsigned int count=i; count<=j; count+=jump)
|
||||
{
|
||||
for (std::size_t count = i; count <= j; count += jump) {
|
||||
delete (arr_vec[count].first);
|
||||
delete (arr_vec[count].second);
|
||||
}
|
||||
|
|
@ -74,38 +66,92 @@ public:
|
|||
arr_vec[i].first = res;
|
||||
arr_vec[i].second = verts;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
//! Join_merge
|
||||
/*! Join_merge is used to join two sets of polygons together in the D&C
|
||||
algorithm. It is a base merge with a visitor that joins faces.
|
||||
/*! Base_intercepted_merge
|
||||
* Base_intercepted_merge is the base class for all merger classes that can be
|
||||
* interceted (e.g., when an intersection is detected). All merges used BFS
|
||||
* algorithm with a different visitor when discovering a new face.
|
||||
*/
|
||||
template <class Arrangement_>
|
||||
class Join_merge : public Base_merge<Arrangement_,
|
||||
Gps_bfs_join_visitor<Arrangement_> >
|
||||
{};
|
||||
template <typename Arrangement_, typename Visitor_>
|
||||
class Base_intercepted_merge {
|
||||
using Arrangement_2 = Arrangement_;
|
||||
using Visitor = Visitor_;
|
||||
using Vertex_handle = typename Arrangement_2::Vertex_handle;
|
||||
using Arr_entry = std::pair<Arrangement_2*, std::vector<Vertex_handle>*>;
|
||||
|
||||
public:
|
||||
template <typename InputIterator>
|
||||
bool operator()(InputIterator begin, InputIterator end) {
|
||||
CGAL_assertion(begin != end);
|
||||
|
||||
//! Intersection_merge
|
||||
/*! Intersection_merge is used to merge two sets of polygons creating their
|
||||
intersection.
|
||||
*/
|
||||
template <class Arrangement_>
|
||||
class Intersection_merge : public Base_merge<Arrangement_,
|
||||
Gps_bfs_intersection_visitor<Arrangement_> >
|
||||
{};
|
||||
const auto* tr = begin->first->geometry_traits();
|
||||
Arrangement_2* arr = new Arrangement_2(tr);
|
||||
std::vector<Vertex_handle>* verts = new std::vector<Vertex_handle>;
|
||||
|
||||
//! Xor_merge
|
||||
/*! Xor_merge is used to merge two sets of polygons creating their
|
||||
symmetric difference.
|
||||
*/
|
||||
template <class Arrangement_>
|
||||
class Xor_merge : public Base_merge<Arrangement_,
|
||||
Gps_bfs_xor_visitor<Arrangement_> >
|
||||
{
|
||||
using Agg_op = Gps_agg_op<Arrangement_2, Visitor, Gps_do_intersect_agg_op_visitor>;
|
||||
Agg_op agg_op(*arr, *verts, *(arr->traits_adaptor()));
|
||||
auto res = agg_op.sweep_intercept_arrangements2(begin, end);
|
||||
|
||||
begin->first = arr;
|
||||
begin->second = verts;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
bool operator()(std::size_t i, std::size_t j, std::size_t jump, std::vector<Arr_entry>& arr_vec) {
|
||||
if (i == j) return false;
|
||||
|
||||
const auto* tr = arr_vec[i].first->geometry_traits();
|
||||
Arrangement_2* arr = new Arrangement_2(tr);
|
||||
std::vector<Vertex_handle>* verts = new std::vector<Vertex_handle>;
|
||||
|
||||
using Agg_op = Gps_agg_op<Arrangement_2, Visitor, Gps_do_intersect_agg_op_visitor>;
|
||||
Agg_op agg_op(*arr, *verts, *(arr->traits_adaptor()));
|
||||
auto res = agg_op.sweep_intercept_arrangements(i, j, jump, arr_vec);
|
||||
|
||||
for (auto count = i; count <= j; count += jump) {
|
||||
delete (arr_vec[count].first);
|
||||
arr_vec[count].first = nullptr;
|
||||
delete (arr_vec[count].second);
|
||||
arr_vec[count].second = nullptr;
|
||||
}
|
||||
|
||||
arr_vec[i].first = arr;
|
||||
arr_vec[i].second = verts;
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
/*! Join_merge
|
||||
* Join_merge is used to join two sets of polygons together in the D&C
|
||||
* algorithm. It is a base merge with a visitor that joins faces.
|
||||
*/
|
||||
template <typename Arrangement_>
|
||||
class Join_merge : public Base_merge<Arrangement_, Gps_bfs_join_visitor<Arrangement_>>{};
|
||||
|
||||
/*! Intersection_merge
|
||||
* Intersection_merge is used to merge two sets of polygons creating their
|
||||
* intersection.
|
||||
*/
|
||||
template <typename Arrangement_>
|
||||
class Intersection_merge : public Base_merge<Arrangement_, Gps_bfs_intersection_visitor<Arrangement_>>{};
|
||||
|
||||
/*! Do_intersect_merge
|
||||
* Do_intersect_merge is used to merge two sets of polygons creating their
|
||||
* intersection. When an intersection in the interior of the boundary curves
|
||||
* is detected, the sweep is intercepted.
|
||||
*/
|
||||
template <typename Arrangement_>
|
||||
class Do_intersect_merge : public Base_intercepted_merge<Arrangement_, Gps_bfs_intersection_visitor<Arrangement_>>{};
|
||||
|
||||
/*! Xor_merge
|
||||
* Xor_merge is used to merge two sets of polygons creating their
|
||||
* symmetric difference.
|
||||
*/
|
||||
template <typename Arrangement_>
|
||||
class Xor_merge : public Base_merge<Arrangement_, Gps_bfs_xor_visitor<Arrangement_>>{};
|
||||
|
||||
} //namespace CGAL
|
||||
|
||||
#endif
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -7,11 +7,10 @@
|
|||
// $Id$
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
//
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
|
||||
#ifndef CGAL_BSO_2_GPS_POLYGON_SIMPILFIER_H
|
||||
#define CGAL_BSO_2_GPS_POLYGON_SIMPILFIER_H
|
||||
#ifndef CGAL_GPS_POLYGON_SIMPILFIER_H
|
||||
#define CGAL_GPS_POLYGON_SIMPILFIER_H
|
||||
|
||||
#include <CGAL/license/Boolean_set_operations_2.h>
|
||||
|
||||
|
|
@ -31,34 +30,33 @@ namespace Ss2 = Surface_sweep_2;
|
|||
|
||||
template <typename Arrangement_>
|
||||
class Gps_polygon_simplifier {
|
||||
typedef Arrangement_ Arrangement_2;
|
||||
using Arrangement_2 = Arrangement_;
|
||||
|
||||
typedef typename Arrangement_2::Geometry_traits_2 Geometry_traits_2;
|
||||
typedef typename Arrangement_2::Topology_traits Topology_traits;
|
||||
using Geometry_traits_2 = typename Arrangement_2::Geometry_traits_2;
|
||||
using Topology_traits = typename Arrangement_2::Topology_traits;
|
||||
|
||||
typedef Arrangement_2 Arr;
|
||||
typedef Geometry_traits_2 Gt2;
|
||||
typedef Topology_traits Tt;
|
||||
using Arr = Arrangement_2;
|
||||
using Gt2 = Geometry_traits_2;
|
||||
using Tt = Topology_traits;
|
||||
|
||||
typedef typename Gt2::Curve_const_iterator Curve_const_iterator;
|
||||
typedef typename Gt2::Polygon_2 Polygon_2;
|
||||
typedef typename Gt2::Polygon_with_holes_2 Polygon_with_holes_2;
|
||||
typedef typename Gt2::Construct_curves_2 Construct_curves_2;
|
||||
using Curve_const_iterator = typename Gt2::Curve_const_iterator;
|
||||
using Polygon_2 = typename Gt2::Polygon_2;
|
||||
using Polygon_with_holes_2 = typename Gt2::Polygon_with_holes_2;
|
||||
using Construct_curves_2 = typename Gt2::Construct_curves_2;
|
||||
|
||||
typedef Gps_simplifier_traits<Gt2> Mgt2;
|
||||
typedef typename Mgt2::Curve_data Curve_data;
|
||||
typedef typename Mgt2::X_monotone_curve_2 Meta_X_monotone_curve_2;
|
||||
using Mgt2 = Gps_simplifier_traits<Gt2>;
|
||||
using Curve_data = typename Mgt2::Curve_data;
|
||||
using Meta_X_monotone_curve_2 = typename Mgt2::X_monotone_curve_2;
|
||||
|
||||
typedef typename Arr::Halfedge_handle Halfedge_handle;
|
||||
typedef typename Arr::Halfedge_iterator Halfedge_iterator;
|
||||
typedef typename Arr::Face_handle Face_handle;
|
||||
typedef typename Arr::Face_iterator Face_iterator;
|
||||
typedef typename Arr::Edge_iterator Edge_iterator;
|
||||
typedef typename Arr::Vertex_handle Vertex_handle;
|
||||
typedef typename Arr::Ccb_halfedge_const_circulator
|
||||
Ccb_halfedge_const_circulator;
|
||||
typedef typename Arr::Ccb_halfedge_circulator Ccb_halfedge_circulator;
|
||||
typedef typename Arr::Allocator Allocator;
|
||||
using Halfedge_handle = typename Arr::Halfedge_handle;
|
||||
using Halfedge_iterator = typename Arr::Halfedge_iterator;
|
||||
using Face_handle = typename Arr::Face_handle;
|
||||
using Face_iterator = typename Arr::Face_iterator;
|
||||
using Edge_iterator = typename Arr::Edge_iterator;
|
||||
using Vertex_handle = typename Arr::Vertex_handle;
|
||||
using Ccb_halfedge_const_circulator = typename Arr::Ccb_halfedge_const_circulator;
|
||||
using Ccb_halfedge_circulator = typename Arr::Ccb_halfedge_circulator;
|
||||
using Allocator = typename Arr::Allocator;
|
||||
|
||||
// We obtain a proper helper type from the topology traits of the arrangement.
|
||||
// However, the arrangement is parametrized with the Gt2 geometry traits,
|
||||
|
|
@ -67,22 +65,18 @@ class Gps_polygon_simplifier {
|
|||
// We cannot parameterized the arrangement with the Mgt2 geometry
|
||||
// traits to start with, because it extends the curve type with arrangement
|
||||
// dependent types. (It is parameterized with the arrangement type.)
|
||||
typedef Indexed_event<Mgt2, Arr, Allocator> Event;
|
||||
typedef Arr_construction_subcurve<Mgt2, Event, Allocator>
|
||||
Subcurve;
|
||||
typedef typename Tt::template Construction_helper<Event, Subcurve>
|
||||
Helper_tmp;
|
||||
typedef typename Helper_tmp::template rebind<Mgt2, Arr, Event, Subcurve>::other
|
||||
Helper;
|
||||
typedef Gps_agg_op_base_visitor<Helper, Arr> Visitor;
|
||||
typedef Ss2::Surface_sweep_2<Visitor> Surface_sweep_2;
|
||||
using Event = Indexed_event<Mgt2, Arr, Allocator>;
|
||||
using Subcurve = Arr_construction_subcurve<Mgt2, Event, Allocator>;
|
||||
using Helper_tmp = typename Tt::template Construction_helper<Event, Subcurve>;
|
||||
using Helper = typename Helper_tmp::template rebind<Mgt2, Arr, Event, Subcurve>::other;
|
||||
using Visitor = Gps_agg_op_base_visitor<Helper, Arr>;
|
||||
using Surface_sweep_2 = Ss2::Surface_sweep_2<Visitor>;
|
||||
|
||||
typedef Unique_hash_map<Halfedge_handle, unsigned int>
|
||||
Edges_hash;
|
||||
using Edges_hash = Unique_hash_map<Halfedge_handle, std::size_t>;
|
||||
|
||||
typedef Unique_hash_map<Face_handle, unsigned int> Faces_hash;
|
||||
typedef Gps_bfs_join_visitor<Arr> Bfs_visitor;
|
||||
typedef Gps_bfs_scanner<Arr, Bfs_visitor> Bfs_scanner;
|
||||
using Faces_hash = Unique_hash_map<Face_handle, std::size_t>;
|
||||
using Bfs_visitor = Gps_bfs_join_visitor<Arr>;
|
||||
using Bfs_scanner = Gps_bfs_scanner<Arr, Bfs_visitor>;
|
||||
|
||||
protected:
|
||||
Arr* m_arr;
|
||||
|
|
@ -104,16 +98,14 @@ public:
|
|||
{}
|
||||
|
||||
/*! Destructor. */
|
||||
~Gps_polygon_simplifier()
|
||||
{
|
||||
~Gps_polygon_simplifier() {
|
||||
if (m_own_traits && (m_traits != nullptr)) {
|
||||
delete m_traits;
|
||||
m_traits = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void simplify(const Polygon_2& pgn)
|
||||
{
|
||||
void simplify(const Polygon_2& pgn) {
|
||||
Construct_curves_2 ctr_curves =
|
||||
reinterpret_cast<const Gt2*>(m_traits)->construct_curves_2_object();
|
||||
|
||||
|
|
@ -122,14 +114,13 @@ public:
|
|||
std::pair<Curve_const_iterator, Curve_const_iterator> itr_pair =
|
||||
ctr_curves(pgn);
|
||||
|
||||
unsigned int index = 0;
|
||||
std::size_t index = 0;
|
||||
for (Curve_const_iterator itr = itr_pair.first; itr != itr_pair.second;
|
||||
++itr, ++index)
|
||||
{
|
||||
++itr, ++index) {
|
||||
Curve_data cv_data(1, 0, index);
|
||||
curves_list.push_back(Meta_X_monotone_curve_2(*itr, cv_data));
|
||||
}
|
||||
m_traits->set_polygon_size(static_cast<unsigned int>(curves_list.size()));
|
||||
m_traits->set_polygon_size(curves_list.size());
|
||||
|
||||
m_surface_sweep.sweep(curves_list.begin(), curves_list.end());
|
||||
|
||||
|
|
|
|||
|
|
@ -7,14 +7,13 @@
|
|||
// $Id$
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
//
|
||||
// Author(s): Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ron Wein <wein@post.tau.ac.il>
|
||||
// Boris Kozorovitzky <boriskoz@post.tau.ac.il>
|
||||
// Guy Zucker <guyzucke@post.tau.ac.il>
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ron Wein <wein@post.tau.ac.il>
|
||||
// Boris Kozorovitzky <boriskoz@post.tau.ac.il>
|
||||
// Guy Zucker <guyzucke@post.tau.ac.il>
|
||||
|
||||
#ifndef CGAL_BSO_2_GPS_POLYGON_VALIDATION_2_H
|
||||
#define CGAL_BSO_2_GPS_POLYGON_VALIDATION_2_H
|
||||
#ifndef CGAL_GPS_POLYGON_VALIDATION_2_H
|
||||
#define CGAL_GPS_POLYGON_VALIDATION_2_H
|
||||
|
||||
#include <CGAL/license/Boolean_set_operations_2.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -7,9 +7,8 @@
|
|||
// $Id$
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
//
|
||||
// Author(s): Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Efi Fogel <efifogel@gmail.com>
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Efi Fogel <efifogel@gmail.com>
|
||||
|
||||
#ifndef CGAL_GPS_SIMPLIFIER_TRAITS_H
|
||||
#define CGAL_GPS_SIMPLIFIER_TRAITS_H
|
||||
|
|
@ -23,97 +22,94 @@ namespace CGAL {
|
|||
|
||||
class Gps_simplifier_curve_data {
|
||||
protected:
|
||||
unsigned int m_bc;
|
||||
unsigned int m_twin_bc;
|
||||
unsigned int m_index;
|
||||
std::size_t m_bc;
|
||||
std::size_t m_twin_bc;
|
||||
std::size_t m_index;
|
||||
|
||||
public:
|
||||
Gps_simplifier_curve_data() {}
|
||||
|
||||
Gps_simplifier_curve_data(unsigned int bc, unsigned int twin_bc,
|
||||
unsigned int index):
|
||||
Gps_simplifier_curve_data(std::size_t bc, std::size_t twin_bc,
|
||||
std::size_t index):
|
||||
m_bc(bc),
|
||||
m_twin_bc(twin_bc),
|
||||
m_index(index)
|
||||
{}
|
||||
|
||||
unsigned int bc() const { return m_bc; }
|
||||
std::size_t bc() const { return m_bc; }
|
||||
|
||||
unsigned int twin_bc() const { return m_twin_bc; }
|
||||
std::size_t twin_bc() const { return m_twin_bc; }
|
||||
|
||||
unsigned int index() const { return m_index; }
|
||||
std::size_t index() const { return m_index; }
|
||||
|
||||
unsigned int& index() { return m_index; }
|
||||
std::size_t& index() { return m_index; }
|
||||
|
||||
unsigned int& twin_bc() { return m_twin_bc; }
|
||||
std::size_t& twin_bc() { return m_twin_bc; }
|
||||
|
||||
void set_bc(unsigned int bc) { m_bc = bc; }
|
||||
void set_bc(std::size_t bc) { m_bc = bc; }
|
||||
|
||||
void set_twin_bc(unsigned int twin_bc) { m_twin_bc = twin_bc; }
|
||||
void set_twin_bc(std::size_t twin_bc) { m_twin_bc = twin_bc; }
|
||||
|
||||
void set_index(unsigned int index) { m_index = index; }
|
||||
void set_index(std::size_t index) { m_index = index; }
|
||||
};
|
||||
|
||||
struct Gps_simplifier_point_data {
|
||||
protected:
|
||||
unsigned int m_index;
|
||||
std::size_t m_index;
|
||||
|
||||
public:
|
||||
Gps_simplifier_point_data() {}
|
||||
|
||||
Gps_simplifier_point_data(unsigned int index) : m_index(index) {}
|
||||
Gps_simplifier_point_data(std::size_t index) : m_index(index) {}
|
||||
|
||||
unsigned int index() const { return m_index; }
|
||||
std::size_t index() const { return m_index; }
|
||||
|
||||
void set_index(unsigned int index) { m_index = index; }
|
||||
void set_index(std::size_t index) { m_index = index; }
|
||||
};
|
||||
|
||||
template <typename Traits_>
|
||||
class Gps_simplifier_traits :
|
||||
public Gps_traits_decorator<Traits_,
|
||||
Gps_simplifier_curve_data,
|
||||
Gps_simplifier_point_data>
|
||||
{
|
||||
Gps_simplifier_point_data> {
|
||||
public:
|
||||
typedef Traits_ Traits;
|
||||
typedef Gps_traits_decorator<Traits_,
|
||||
Gps_simplifier_curve_data,
|
||||
Gps_simplifier_point_data> Base;
|
||||
typedef Gps_simplifier_traits<Traits> Self;
|
||||
typedef typename Traits::X_monotone_curve_2 Base_x_monotone_curve_2;
|
||||
typedef typename Traits::Point_2 Base_point_2;
|
||||
typedef typename Traits::Construct_min_vertex_2 Base_Construct_min_vertex_2;
|
||||
typedef typename Traits::Construct_max_vertex_2 Base_Construct_max_vertex_2;
|
||||
typedef typename Traits::Compare_endpoints_xy_2 Base_Compare_endpoints_xy_2;
|
||||
typedef typename Traits::Compare_xy_2 Base_Compare_xy_2;
|
||||
typedef typename Traits::Compare_y_at_x_right_2 Base_Compare_y_at_x_right_2;
|
||||
typedef typename Traits::Compare_y_at_x_2 Base_Compare_y_at_x_2;
|
||||
typedef typename Traits::Intersect_2 Base_Intersect_2;
|
||||
typedef typename Traits::Split_2 Base_Split_2;
|
||||
using Traits = Traits_;
|
||||
using Base = Gps_traits_decorator<Traits_, Gps_simplifier_curve_data, Gps_simplifier_point_data>;
|
||||
using Self = Gps_simplifier_traits<Traits>;
|
||||
using Base_x_monotone_curve_2 = typename Traits::X_monotone_curve_2;
|
||||
using Base_point_2 = typename Traits::Point_2;
|
||||
using Base_Construct_min_vertex_2 = typename Traits::Construct_min_vertex_2;
|
||||
using Base_Construct_max_vertex_2 = typename Traits::Construct_max_vertex_2;
|
||||
using Base_Compare_endpoints_xy_2 = typename Traits::Compare_endpoints_xy_2;
|
||||
using Base_Compare_xy_2 = typename Traits::Compare_xy_2;
|
||||
using Base_Compare_y_at_x_right_2 = typename Traits::Compare_y_at_x_right_2;
|
||||
using Base_Compare_y_at_x_2 = typename Traits::Compare_y_at_x_2;
|
||||
using Base_Intersect_2 = typename Traits::Intersect_2;
|
||||
using Base_Split_2 = typename Traits::Split_2;
|
||||
|
||||
protected:
|
||||
mutable unsigned int m_pgn_size;
|
||||
mutable std::size_t m_pgn_size;
|
||||
|
||||
public:
|
||||
typedef typename Base::X_monotone_curve_2 X_monotone_curve_2;
|
||||
typedef typename Base::Point_2 Point_2;
|
||||
typedef typename Base::Multiplicity Multiplicity;
|
||||
using X_monotone_curve_2 = typename Base::X_monotone_curve_2;
|
||||
using Point_2 = typename Base::Point_2;
|
||||
using Multiplicity = typename Base::Multiplicity;
|
||||
|
||||
typedef typename Base::Curve_data Curve_data;
|
||||
typedef typename Base::Point_data Point_data;
|
||||
using Curve_data = typename Base::Curve_data;
|
||||
using Point_data = typename Base::Point_data;
|
||||
|
||||
Gps_simplifier_traits() {}
|
||||
|
||||
Gps_simplifier_traits(const Traits& tr) : Base(tr) {}
|
||||
|
||||
unsigned int polygon_size() const { return m_pgn_size; }
|
||||
std::size_t polygon_size() const { return m_pgn_size; }
|
||||
|
||||
void set_polygon_size(unsigned int pgn_size) const { m_pgn_size = pgn_size; }
|
||||
void set_polygon_size(std::size_t pgn_size) const { m_pgn_size = pgn_size; }
|
||||
|
||||
bool is_valid_index(unsigned int index) const
|
||||
bool is_valid_index(std::size_t index) const
|
||||
{ return (index < m_pgn_size); }
|
||||
|
||||
unsigned int invalid_index() const { return (m_pgn_size); }
|
||||
std::size_t invalid_index() const { return (m_pgn_size); }
|
||||
|
||||
class Intersect_2 {
|
||||
private:
|
||||
|
|
@ -129,12 +125,9 @@ public:
|
|||
template <typename OutputIterator>
|
||||
OutputIterator operator()(const X_monotone_curve_2& cv1,
|
||||
const X_monotone_curve_2& cv2,
|
||||
OutputIterator oi) const
|
||||
{
|
||||
typedef const std::pair<Base_point_2, Multiplicity>
|
||||
Intersection_base_point;
|
||||
typedef std::variant<Intersection_base_point, Base_x_monotone_curve_2>
|
||||
Intersection_base_result;
|
||||
OutputIterator oi) const {
|
||||
using Intersection_base_point = const std::pair<Base_point_2, Multiplicity>;
|
||||
using Intersection_base_result = std::variant<Intersection_base_point, Base_x_monotone_curve_2>;
|
||||
|
||||
const auto* base_traits = m_traits.m_base_traits;
|
||||
auto base_cmp_xy = base_traits->compare_xy_2_object();
|
||||
|
|
@ -146,7 +139,7 @@ public:
|
|||
//if (m_traits.is_valid_index(cv1.data().index()) &&
|
||||
// m_traits.is_valid_index(cv2.data().index()))
|
||||
//{
|
||||
// unsigned int index_diff =
|
||||
// std::size_t index_diff =
|
||||
// (cv1.data().index() > cv2.data().index()) ?
|
||||
// (cv1.data().index() - cv2.data().index()):
|
||||
// (cv2.data().index() - cv1.data().index());
|
||||
|
|
@ -180,8 +173,8 @@ public:
|
|||
std::get_if<Base_x_monotone_curve_2>(&xection);
|
||||
|
||||
CGAL_assertion(overlap_cv != nullptr);
|
||||
unsigned int ov_bc;
|
||||
unsigned int ov_twin_bc;
|
||||
std::size_t ov_bc;
|
||||
std::size_t ov_twin_bc;
|
||||
if (base_cmp_endpoints(cv1) == base_cmp_endpoints(cv2)) {
|
||||
// cv1 and cv2 have the same directions
|
||||
ov_bc = cv1.data().bc() + cv2.data().bc();
|
||||
|
|
@ -207,7 +200,7 @@ public:
|
|||
};
|
||||
|
||||
/*! Obtain an Intersect_2 functor object. */
|
||||
Intersect_2 intersect_2_object () const { return Intersect_2(*this); }
|
||||
Intersect_2 intersect_2_object() const { return Intersect_2(*this); }
|
||||
|
||||
class Split_2 {
|
||||
private:
|
||||
|
|
@ -220,8 +213,7 @@ public:
|
|||
|
||||
public:
|
||||
void operator()(const X_monotone_curve_2& cv, const Point_2 & p,
|
||||
X_monotone_curve_2& c1, X_monotone_curve_2& c2) const
|
||||
{
|
||||
X_monotone_curve_2& c1, X_monotone_curve_2& c2) const {
|
||||
const auto* base_traits = m_traits.m_base_traits;
|
||||
auto base_split = base_traits->split_2_object();
|
||||
base_split(cv.base(), p.base(), c1.base(), c2.base());
|
||||
|
|
@ -250,8 +242,7 @@ public:
|
|||
* \param cv The curve.
|
||||
* \return The left endpoint.
|
||||
*/
|
||||
Point_2 operator()(const X_monotone_curve_2 & cv) const
|
||||
{
|
||||
Point_2 operator()(const X_monotone_curve_2 & cv) const {
|
||||
const auto* base_traits = m_traits.m_base_traits;
|
||||
auto base_ctr_min_vertex = base_traits->construct_min_vertex_2_object();
|
||||
|
||||
|
|
@ -290,8 +281,7 @@ public:
|
|||
* \param cv The curve.
|
||||
* \return The left endpoint.
|
||||
*/
|
||||
Point_2 operator() (const X_monotone_curve_2 & cv) const
|
||||
{
|
||||
Point_2 operator() (const X_monotone_curve_2 & cv) const {
|
||||
const auto* base_traits = m_traits.m_base_traits;
|
||||
auto base_ctr_max_vertex = base_traits->construct_max_vertex_2_object();
|
||||
if (! m_traits.is_valid_index(cv.data().index()))
|
||||
|
|
@ -329,8 +319,7 @@ public:
|
|||
* \param cv The curve.
|
||||
* \return The left endpoint.
|
||||
*/
|
||||
Comparison_result operator()(const Point_2& p1, const Point_2& p2) const
|
||||
{
|
||||
Comparison_result operator()(const Point_2& p1, const Point_2& p2) const {
|
||||
const auto* base_traits = m_traits.m_base_traits;
|
||||
auto base_cmp_xy = base_traits->compare_xy_2_object();
|
||||
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@
|
|||
// Ron Wein <wein@post.tau.ac.il>
|
||||
// Efi Fogel <efifogel@gmail.com>
|
||||
|
||||
#ifndef CGAL_BSO_2_INDEXED_VISITOR_H
|
||||
#define CGAL_BSO_2_INDEXED_VISITOR_H
|
||||
#ifndef CGAL_INDEXED_VISITOR_H
|
||||
#define CGAL_INDEXED_VISITOR_H
|
||||
|
||||
#include <CGAL/license/Boolean_set_operations_2.h>
|
||||
|
||||
|
|
@ -32,17 +32,16 @@ class Indexed_event :
|
|||
Arrangement_,
|
||||
Allocator_>,
|
||||
Allocator_>,
|
||||
Arrangement_>
|
||||
{
|
||||
Arrangement_> {
|
||||
private:
|
||||
unsigned int m_index;
|
||||
std::size_t m_index;
|
||||
|
||||
public:
|
||||
Indexed_event() : m_index (0) {}
|
||||
|
||||
unsigned int index() const { return (m_index); }
|
||||
std::size_t index() const { return (m_index); }
|
||||
|
||||
void set_index(unsigned int index) { m_index = index; }
|
||||
void set_index(std::size_t index) { m_index = index; }
|
||||
};
|
||||
|
||||
} // namespace CGAL
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue