geomerative 1.1.0-java → 2.0.0-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (116) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -1
  3. data/.mvn/extensions.xml +1 -1
  4. data/.mvn/wrapper/maven-wrapper.properties +1 -1
  5. data/CHANGELOG.md +3 -0
  6. data/COPYING.md +1 -1
  7. data/README.md +0 -1
  8. data/Rakefile +2 -15
  9. data/docs/_includes/header.html +6 -6
  10. data/docs/_includes/icon-github.svg +3 -1
  11. data/docs/_includes/icon-twitter.svg +3 -1
  12. data/docs/_includes/navigation.html +18 -18
  13. data/docs/_sass/_base.scss +79 -79
  14. data/docs/_sass/_layout.scss +137 -137
  15. data/docs/_sass/_syntax-highlighting.scss +64 -64
  16. data/docs/index.html +18 -18
  17. data/examples/data/bot1.svg +1 -1
  18. data/examples/data/lion.svg +156 -156
  19. data/examples/data/ruby.svg +1 -1
  20. data/geomerative.gemspec +1 -2
  21. data/lib/geomerative/version.rb +1 -1
  22. data/mvnw +234 -0
  23. data/mvnw.cmd +145 -0
  24. data/pom.rb +14 -13
  25. data/pom.xml +14 -13
  26. data/src/geomerative/FastRClip.java +2149 -2156
  27. data/src/geomerative/RClip.java +2237 -2539
  28. data/src/geomerative/RClosest.java +33 -31
  29. data/src/geomerative/RCommand.java +1750 -1758
  30. data/src/geomerative/RContour.java +290 -292
  31. data/src/geomerative/RFont.java +277 -246
  32. data/src/geomerative/RG.java +722 -727
  33. data/src/geomerative/RGeomElem.java +967 -960
  34. data/src/geomerative/RGroup.java +508 -467
  35. data/src/geomerative/RMatrix.java +304 -289
  36. data/src/geomerative/RMesh.java +241 -229
  37. data/src/geomerative/RPath.java +924 -925
  38. data/src/geomerative/RPoint.java +391 -391
  39. data/src/geomerative/RPolygon.java +998 -988
  40. data/src/geomerative/RRectangle.java +43 -52
  41. data/src/geomerative/RSVG.java +480 -516
  42. data/src/geomerative/RShape.java +1767 -1777
  43. data/src/geomerative/RStrip.java +173 -176
  44. data/src/geomerative/RStyle.java +197 -194
  45. data/src/org/apache/batik/svggen/font/Font.java +141 -142
  46. data/src/org/apache/batik/svggen/font/Glyph.java +102 -71
  47. data/src/org/apache/batik/svggen/font/Point.java +12 -12
  48. data/src/org/apache/batik/svggen/font/RandomAccessFileEmulator.java +14 -12
  49. data/src/org/apache/batik/svggen/font/table/ClassDef.java +12 -12
  50. data/src/org/apache/batik/svggen/font/table/ClassDefFormat1.java +27 -24
  51. data/src/org/apache/batik/svggen/font/table/ClassDefFormat2.java +20 -17
  52. data/src/org/apache/batik/svggen/font/table/CmapFormat.java +43 -43
  53. data/src/org/apache/batik/svggen/font/table/CmapFormat0.java +33 -26
  54. data/src/org/apache/batik/svggen/font/table/CmapFormat2.java +25 -20
  55. data/src/org/apache/batik/svggen/font/table/CmapFormat4.java +106 -96
  56. data/src/org/apache/batik/svggen/font/table/CmapFormat6.java +36 -32
  57. data/src/org/apache/batik/svggen/font/table/CmapIndexEntry.java +69 -49
  58. data/src/org/apache/batik/svggen/font/table/CmapTable.java +50 -50
  59. data/src/org/apache/batik/svggen/font/table/Coverage.java +19 -19
  60. data/src/org/apache/batik/svggen/font/table/CoverageFormat1.java +30 -27
  61. data/src/org/apache/batik/svggen/font/table/CoverageFormat2.java +26 -24
  62. data/src/org/apache/batik/svggen/font/table/CvtTable.java +16 -16
  63. data/src/org/apache/batik/svggen/font/table/Device.java +32 -32
  64. data/src/org/apache/batik/svggen/font/table/DirectoryEntry.java +39 -39
  65. data/src/org/apache/batik/svggen/font/table/Feature.java +26 -23
  66. data/src/org/apache/batik/svggen/font/table/FeatureList.java +37 -35
  67. data/src/org/apache/batik/svggen/font/table/FeatureRecord.java +22 -22
  68. data/src/org/apache/batik/svggen/font/table/FeatureTags.java +4 -3
  69. data/src/org/apache/batik/svggen/font/table/FpgmTable.java +9 -9
  70. data/src/org/apache/batik/svggen/font/table/GlyfCompositeComp.java +134 -132
  71. data/src/org/apache/batik/svggen/font/table/GlyfCompositeDescript.java +123 -122
  72. data/src/org/apache/batik/svggen/font/table/GlyfDescript.java +44 -44
  73. data/src/org/apache/batik/svggen/font/table/GlyfSimpleDescript.java +110 -109
  74. data/src/org/apache/batik/svggen/font/table/GlyfTable.java +46 -46
  75. data/src/org/apache/batik/svggen/font/table/GlyphDescription.java +25 -13
  76. data/src/org/apache/batik/svggen/font/table/GposTable.java +26 -23
  77. data/src/org/apache/batik/svggen/font/table/GsubTable.java +85 -82
  78. data/src/org/apache/batik/svggen/font/table/HeadTable.java +131 -131
  79. data/src/org/apache/batik/svggen/font/table/HheaTable.java +80 -80
  80. data/src/org/apache/batik/svggen/font/table/HmtxTable.java +50 -49
  81. data/src/org/apache/batik/svggen/font/table/KernSubtable.java +29 -27
  82. data/src/org/apache/batik/svggen/font/table/KernSubtableFormat0.java +35 -32
  83. data/src/org/apache/batik/svggen/font/table/KernSubtableFormat2.java +28 -26
  84. data/src/org/apache/batik/svggen/font/table/KernTable.java +36 -31
  85. data/src/org/apache/batik/svggen/font/table/KerningPair.java +27 -23
  86. data/src/org/apache/batik/svggen/font/table/LangSys.java +28 -26
  87. data/src/org/apache/batik/svggen/font/table/LangSysRecord.java +22 -22
  88. data/src/org/apache/batik/svggen/font/table/Ligature.java +24 -24
  89. data/src/org/apache/batik/svggen/font/table/LigatureSet.java +24 -24
  90. data/src/org/apache/batik/svggen/font/table/LigatureSubst.java +9 -9
  91. data/src/org/apache/batik/svggen/font/table/LigatureSubstFormat1.java +30 -30
  92. data/src/org/apache/batik/svggen/font/table/LocaTable.java +37 -37
  93. data/src/org/apache/batik/svggen/font/table/Lookup.java +41 -40
  94. data/src/org/apache/batik/svggen/font/table/LookupList.java +34 -34
  95. data/src/org/apache/batik/svggen/font/table/LookupSubtableFactory.java +7 -5
  96. data/src/org/apache/batik/svggen/font/table/MaxpTable.java +96 -96
  97. data/src/org/apache/batik/svggen/font/table/NameRecord.java +64 -65
  98. data/src/org/apache/batik/svggen/font/table/NameTable.java +33 -33
  99. data/src/org/apache/batik/svggen/font/table/Os2Table.java +196 -196
  100. data/src/org/apache/batik/svggen/font/table/Panose.java +14 -12
  101. data/src/org/apache/batik/svggen/font/table/PostTable.java +338 -338
  102. data/src/org/apache/batik/svggen/font/table/PrepTable.java +9 -9
  103. data/src/org/apache/batik/svggen/font/table/Program.java +15 -15
  104. data/src/org/apache/batik/svggen/font/table/RangeRecord.java +26 -25
  105. data/src/org/apache/batik/svggen/font/table/Script.java +38 -38
  106. data/src/org/apache/batik/svggen/font/table/ScriptList.java +42 -42
  107. data/src/org/apache/batik/svggen/font/table/ScriptRecord.java +22 -22
  108. data/src/org/apache/batik/svggen/font/table/ScriptTags.java +2 -1
  109. data/src/org/apache/batik/svggen/font/table/SingleSubst.java +15 -16
  110. data/src/org/apache/batik/svggen/font/table/SingleSubstFormat1.java +33 -33
  111. data/src/org/apache/batik/svggen/font/table/SingleSubstFormat2.java +32 -32
  112. data/src/org/apache/batik/svggen/font/table/Table.java +171 -170
  113. data/src/org/apache/batik/svggen/font/table/TableDirectory.java +55 -55
  114. data/src/org/apache/batik/svggen/font/table/TableFactory.java +92 -93
  115. metadata +10 -11
  116. data/.travis.yml +0 -9
data/pom.xml CHANGED
@@ -6,12 +6,12 @@ DO NOT MODIFIY - GENERATED CODE
6
6
 
7
7
 
8
8
  -->
9
- <project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
9
+ <project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
10
10
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
11
11
  <modelVersion>4.0.0</modelVersion>
12
12
  <groupId>ruby-processing</groupId>
13
13
  <artifactId>geomerative</artifactId>
14
- <version>1.1.0</version>
14
+ <version>2.0.0</version>
15
15
  <name>geomerative</name>
16
16
  <description>geomerative-library for JRubyArt</description>
17
17
  <organization>
@@ -44,16 +44,16 @@ DO NOT MODIFIY - GENERATED CODE
44
44
  <url>https://github.com/ruby-processing/geomerative/issues</url>
45
45
  </issueManagement>
46
46
  <properties>
47
+ <maven.compiler.source>1.8</maven.compiler.source>
48
+ <maven.compiler.target>12</maven.compiler.target>
47
49
  <polyglot.dump.pom>pom.xml</polyglot.dump.pom>
48
50
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
49
- <maven.compiler.source>1.8</maven.compiler.source>
50
- <maven.compiler.target>1.8</maven.compiler.target>
51
51
  </properties>
52
52
  <dependencies>
53
53
  <dependency>
54
54
  <groupId>org.processing</groupId>
55
55
  <artifactId>core</artifactId>
56
- <version>3.3.6</version>
56
+ <version>4.0.0</version>
57
57
  </dependency>
58
58
  </dependencies>
59
59
  <build>
@@ -63,24 +63,25 @@ DO NOT MODIFIY - GENERATED CODE
63
63
  <plugins>
64
64
  <plugin>
65
65
  <artifactId>maven-compiler-plugin</artifactId>
66
- <version>3.8.0</version>
66
+ <version>3.8.1</version>
67
67
  <configuration>
68
- <source>${maven.compiler.source}</source>
69
- <target>${maven.compiler.target}</target>
68
+ <release>11</release>
70
69
  </configuration>
71
70
  </plugin>
72
71
  <plugin>
73
72
  <artifactId>maven-jar-plugin</artifactId>
74
- <version>3.0.2</version>
73
+ <version>3.2.0</version>
75
74
  <configuration>
76
75
  <archive>
77
- <manifestFile>MANIFEST.MF</manifestFile>
76
+ <manifestEntries>
77
+ <Automatic-Module-Name>geomerative.gem</Automatic-Module-Name>
78
+ </manifestEntries>
78
79
  </archive>
79
80
  </configuration>
80
81
  </plugin>
81
82
  <plugin>
82
83
  <artifactId>maven-resources-plugin</artifactId>
83
- <version>2.6</version>
84
+ <version>2.7</version>
84
85
  </plugin>
85
86
  </plugins>
86
87
  </build>
@@ -88,7 +89,7 @@ DO NOT MODIFIY - GENERATED CODE
88
89
  <plugins>
89
90
  <plugin>
90
91
  <artifactId>maven-pmd-plugin</artifactId>
91
- <version>3.6</version>
92
+ <version>3.12</version>
92
93
  <configuration>
93
94
  <linkXRef>true</linkXRef>
94
95
  <sourceEncoding>utf-8</sourceEncoding>
@@ -98,7 +99,7 @@ DO NOT MODIFIY - GENERATED CODE
98
99
  </plugin>
99
100
  <plugin>
100
101
  <artifactId>maven-checkstyle-plugin</artifactId>
101
- <version>2.17</version>
102
+ <version>3.1.0</version>
102
103
  <configuration>
103
104
  <configLocation>config/sun_checks.xml</configLocation>
104
105
  </configuration>
@@ -43,6 +43,7 @@ package geomerative;
43
43
  import java.util.ArrayList;
44
44
  import java.util.List;
45
45
  import geomerative.RClip.OperationType;
46
+ import java.lang.reflect.InvocationTargetException;
46
47
 
47
48
  /**
48
49
  * <code>Clip</code> is a Java version of the <i>General RPolygon Clipper</i>
@@ -66,1216 +67,1217 @@ import geomerative.RClip.OperationType;
66
67
  * @author Dan Bridenbecker, Solution Engineering, Inc.
67
68
  */
68
69
  class FastRClip {
69
- // -----------------
70
- // --- Constants ---
71
- // -----------------
72
-
73
- // Maximum precision for floats
74
- private static final double GPC_EPSILON = 2.2204460492503131e-016;
75
- //private static final float GPC_EPSILON = 1.192092896e-07F;
76
- static final String GPC_VERSION = "2.31";
77
-
78
- private static final int LEFT = 0;
79
- private static final int RIGHT = 1;
80
-
81
- private static final int ABOVE = 0;
82
- private static final int BELOW = 1;
83
-
84
- private static final int CLIP = 0;
85
- private static final int SUBJ = 1;
86
-
87
- private static final boolean INVERT_TRISTRIPS = false;
88
-
89
- // ------------------------
90
- // --- Member Variables ---
91
- // ------------------------
92
- // --------------------
93
- // --- Constructors ---
94
- // --------------------
95
- /**
96
- * Creates a new instance of Clip
97
- */
98
- private FastRClip() {
99
- }
100
-
101
- // ----------------------
102
- // --- Static Methods ---
103
- // ----------------------
104
- // -----------------------
105
- // --- Private Methods ---
106
- // -----------------------
107
- /**
108
- * Create a new <code>RPolygon</code> type object using
109
- * <code>polyClass</code>.
110
- */
111
- private static RPolygon createNewPoly(Class polyClass) {
112
- try {
113
- return (RPolygon) polyClass.newInstance();
114
- } catch (InstantiationException | IllegalAccessException e) {
115
- throw new RuntimeException(e);
116
- }
70
+ // -----------------
71
+ // --- Constants ---
72
+ // -----------------
73
+
74
+ // Maximum precision for floats
75
+ private static final double GPC_EPSILON = 2.2204460492503131e-016;
76
+ //private static final float GPC_EPSILON = 1.192092896e-07F;
77
+ static final String GPC_VERSION = "2.31";
78
+
79
+ private static final int LEFT = 0;
80
+ private static final int RIGHT = 1;
81
+
82
+ private static final int ABOVE = 0;
83
+ private static final int BELOW = 1;
84
+
85
+ private static final int CLIP = 0;
86
+ private static final int SUBJ = 1;
87
+
88
+ private static final boolean INVERT_TRISTRIPS = false;
89
+
90
+ // ------------------------
91
+ // --- Member Variables ---
92
+ // ------------------------
93
+ // --------------------
94
+ // --- Constructors ---
95
+ // --------------------
96
+ /**
97
+ * Creates a new instance of Clip
98
+ */
99
+ private FastRClip() {
100
+ }
101
+
102
+ // ----------------------
103
+ // --- Static Methods ---
104
+ // ----------------------
105
+ // -----------------------
106
+ // --- Private Methods ---
107
+ // -----------------------
108
+ /**
109
+ * Create a new <code>RPolygon</code> type object using
110
+ * <code>polyClass</code>.
111
+ */
112
+ private static RPolygon createNewPoly(Class polyClass) {
113
+ try {
114
+ return (RPolygon)polyClass.getConstructor().newInstance();
115
+ } catch (IllegalAccessException | IllegalArgumentException | InstantiationException | NoSuchMethodException | SecurityException | InvocationTargetException ex) {
116
+ return null;
117
+ }
118
+ }
119
+
120
+
121
+ /**
122
+ * <code>clip()</code> is the main method of the clipper algorithm. This is
123
+ * where the conversion from really begins.
124
+ */
125
+ static RPolygon clip(OperationType op, RPolygon subj, RPolygon clip, Class polyClass) {
126
+ RPolygon result = createNewPoly(polyClass);
127
+ TopPolygonNode out_poly = new TopPolygonNode(); // used to create resulting RPolygon
128
+
129
+ /* Test for trivial NULL result cases */
130
+ if ((subj.isEmpty() && clip.isEmpty())
131
+ || (subj.isEmpty() && ((op == OperationType.GPC_INT) || (op == OperationType.GPC_DIFF)))
132
+ || (clip.isEmpty() && (op == OperationType.GPC_INT))) {
133
+ return null;
117
134
  }
118
135
 
119
- /**
120
- * <code>clip()</code> is the main method of the clipper algorithm. This is
121
- * where the conversion from really begins.
122
- */
123
- static RPolygon clip(OperationType op, RPolygon subj, RPolygon clip, Class polyClass) {
124
- RPolygon result = createNewPoly(polyClass);
125
- TopPolygonNode out_poly = new TopPolygonNode(); // used to create resulting RPolygon
126
-
127
- /* Test for trivial NULL result cases */
128
- if ((subj.isEmpty() && clip.isEmpty())
129
- || (subj.isEmpty() && ((op == OperationType.GPC_INT) || (op == OperationType.GPC_DIFF)))
130
- || (clip.isEmpty() && (op == OperationType.GPC_INT))) {
131
- return null;
132
- }
133
-
134
- /* Identify potentialy contributing contours */
135
- if (((op == OperationType.GPC_INT) || (op == OperationType.GPC_DIFF))
136
- && !subj.isEmpty() && !clip.isEmpty()) {
137
- minimax_test(subj, clip, op);
138
- }
136
+ /* Identify potentialy contributing contours */
137
+ if (((op == OperationType.GPC_INT) || (op == OperationType.GPC_DIFF))
138
+ && !subj.isEmpty() && !clip.isEmpty()) {
139
+ minimax_test(subj, clip, op);
140
+ }
139
141
 
140
- /* Build LMT */
141
- LmtTable lmt_table = new LmtTable();
142
- ScanBeamTreeEntries sbte = new ScanBeamTreeEntries();
143
- if (!subj.isEmpty()) {
144
- build_lmt(lmt_table, sbte, subj, SUBJ, op);
145
- }
146
- if (!clip.isEmpty()) {
147
- build_lmt(lmt_table, sbte, clip, CLIP, op);
148
- }
142
+ /* Build LMT */
143
+ LmtTable lmt_table = new LmtTable();
144
+ ScanBeamTreeEntries sbte = new ScanBeamTreeEntries();
145
+ if (!subj.isEmpty()) {
146
+ build_lmt(lmt_table, sbte, subj, SUBJ, op);
147
+ }
148
+ if (!clip.isEmpty()) {
149
+ build_lmt(lmt_table, sbte, clip, CLIP, op);
150
+ }
149
151
 
150
- /* Return a NULL result if no contours contribute */
151
- if (lmt_table.top_node == null) {
152
- return null;
153
- }
152
+ /* Return a NULL result if no contours contribute */
153
+ if (lmt_table.top_node == null) {
154
+ return null;
155
+ }
154
156
 
155
- /* Build scanbeam table from scanbeam tree */
156
- float[] sbt = sbte.build_sbt();
157
+ /* Build scanbeam table from scanbeam tree */
158
+ float[] sbt = sbte.build_sbt();
157
159
 
158
- int parity_clip = LEFT;
159
- int parity_subj = LEFT;
160
+ int parity_clip = LEFT;
161
+ int parity_subj = LEFT;
160
162
 
161
- /* Invert clip polygon for difference operation */
162
- if (op == OperationType.GPC_DIFF) {
163
- parity_clip = RIGHT;
164
- }
163
+ /* Invert clip polygon for difference operation */
164
+ if (op == OperationType.GPC_DIFF) {
165
+ parity_clip = RIGHT;
166
+ }
165
167
 
166
- LmtNode local_min = lmt_table.top_node;
168
+ LmtNode local_min = lmt_table.top_node;
167
169
 
168
- AetTree aet = new AetTree();
169
- int scanbeam = 0;
170
+ AetTree aet = new AetTree();
171
+ int scanbeam = 0;
170
172
 
171
- /* Process each scanbeam */
172
- while (scanbeam < sbt.length) {
173
- /* Set yb and yt to the bottom and top of the scanbeam */
174
- float yb = sbt[scanbeam++];
175
- float yt = 0.0F;
176
- float dy = 0.0F;
177
- if (scanbeam < sbt.length) {
178
- yt = sbt[scanbeam];
179
- dy = yt - yb;
180
- }
173
+ /* Process each scanbeam */
174
+ while (scanbeam < sbt.length) {
175
+ /* Set yb and yt to the bottom and top of the scanbeam */
176
+ float yb = sbt[scanbeam++];
177
+ float yt = 0.0F;
178
+ float dy = 0.0F;
179
+ if (scanbeam < sbt.length) {
180
+ yt = sbt[scanbeam];
181
+ dy = yt - yb;
182
+ }
181
183
 
182
- /* === SCANBEAM BOUNDARY PROCESSING ================================ */
184
+ /* === SCANBEAM BOUNDARY PROCESSING ================================ */
183
185
  /* If LMT node corresponding to yb exists */
184
- if (local_min != null) {
185
- if (local_min.y == yb) {
186
- /* Add edges starting at this local minimum to the AET */
187
- for (EdgeNode edge = local_min.first_bound; (edge != null); edge = edge.next_bound) {
188
- add_edge_to_aet(aet, edge);
189
- }
186
+ if (local_min != null) {
187
+ if (local_min.y == yb) {
188
+ /* Add edges starting at this local minimum to the AET */
189
+ for (EdgeNode edge = local_min.first_bound; (edge != null); edge = edge.next_bound) {
190
+ add_edge_to_aet(aet, edge);
191
+ }
190
192
 
191
- local_min = local_min.next;
192
- }
193
- }
193
+ local_min = local_min.next;
194
+ }
195
+ }
194
196
 
195
- /* Set dummy previous x value */
196
- float px = -Float.MAX_VALUE;
197
-
198
- /* Create bundles within AET */
199
- EdgeNode e0 = aet.top_node;
200
- EdgeNode e1 = aet.top_node;
201
-
202
- /* Set up bundle fields of first edge */
203
- aet.top_node.bundle_above[aet.top_node.type] = (aet.top_node.top_y != yb) ? 1 : 0;
204
- aet.top_node.bundle_above[((aet.top_node.type == 0) ? 1 : 0)] = 0;
205
- aet.top_node.bstate_above = BundleState.UNBUNDLED;
206
-
207
- for (EdgeNode next_edge = aet.top_node.next; (next_edge != null); next_edge = next_edge.next) {
208
- int ne_type = next_edge.type;
209
- int ne_type_opp = ((next_edge.type == 0) ? 1 : 0); //next edge type opposite
210
-
211
- /* Set up bundle fields of next edge */
212
- next_edge.bundle_above[ne_type] = (next_edge.top_y != yb) ? 1 : 0;
213
- next_edge.bundle_above[ne_type_opp] = 0;
214
- next_edge.bstate_above = BundleState.UNBUNDLED;
215
-
216
- /* Bundle edges above the scanbeam boundary if they coincide */
217
- if (next_edge.bundle_above[ne_type] == 1) {
218
- if (EQ(e0.xb, next_edge.xb) && EQ(e0.dx, next_edge.dx) && (e0.top_y != yb)) {
219
- next_edge.bundle_above[ne_type] ^= e0.bundle_above[ne_type];
220
- next_edge.bundle_above[ne_type_opp] = e0.bundle_above[ne_type_opp];
221
- next_edge.bstate_above = BundleState.BUNDLE_HEAD;
222
- e0.bundle_above[CLIP] = 0;
223
- e0.bundle_above[SUBJ] = 0;
224
- e0.bstate_above = BundleState.BUNDLE_TAIL;
225
- }
226
- e0 = next_edge;
227
- }
228
- }
197
+ /* Set dummy previous x value */
198
+ float px = -Float.MAX_VALUE;
199
+
200
+ /* Create bundles within AET */
201
+ EdgeNode e0 = aet.top_node;
202
+ EdgeNode e1 = aet.top_node;
203
+
204
+ /* Set up bundle fields of first edge */
205
+ aet.top_node.bundle_above[aet.top_node.type] = (aet.top_node.top_y != yb) ? 1 : 0;
206
+ aet.top_node.bundle_above[((aet.top_node.type == 0) ? 1 : 0)] = 0;
207
+ aet.top_node.bstate_above = BundleState.UNBUNDLED;
208
+
209
+ for (EdgeNode next_edge = aet.top_node.next; (next_edge != null); next_edge = next_edge.next) {
210
+ int ne_type = next_edge.type;
211
+ int ne_type_opp = ((next_edge.type == 0) ? 1 : 0); //next edge type opposite
212
+
213
+ /* Set up bundle fields of next edge */
214
+ next_edge.bundle_above[ne_type] = (next_edge.top_y != yb) ? 1 : 0;
215
+ next_edge.bundle_above[ne_type_opp] = 0;
216
+ next_edge.bstate_above = BundleState.UNBUNDLED;
217
+
218
+ /* Bundle edges above the scanbeam boundary if they coincide */
219
+ if (next_edge.bundle_above[ne_type] == 1) {
220
+ if (EQ(e0.xb, next_edge.xb) && EQ(e0.dx, next_edge.dx) && (e0.top_y != yb)) {
221
+ next_edge.bundle_above[ne_type] ^= e0.bundle_above[ne_type];
222
+ next_edge.bundle_above[ne_type_opp] = e0.bundle_above[ne_type_opp];
223
+ next_edge.bstate_above = BundleState.BUNDLE_HEAD;
224
+ e0.bundle_above[CLIP] = 0;
225
+ e0.bundle_above[SUBJ] = 0;
226
+ e0.bstate_above = BundleState.BUNDLE_TAIL;
227
+ }
228
+ e0 = next_edge;
229
+ }
230
+ }
229
231
 
230
- int horiz_clip = HState.NH;
231
- int horiz_subj = HState.NH;
232
-
233
- int exists_clip = 0;
234
- int exists_subj = 0;
235
-
236
- PolygonNode cf = null;
237
-
238
- /* Process each edge at this scanbeam boundary */
239
- for (EdgeNode edge = aet.top_node; (edge != null); edge = edge.next) {
240
- exists_clip = edge.bundle_above[CLIP] + (edge.bundle_below_clip << 1);
241
- exists_subj = edge.bundle_above[SUBJ] + (edge.bundle_below_subj << 1);
242
-
243
- if ((exists_clip != 0) || (exists_subj != 0)) {
244
- /* Set bundle side */
245
- edge.bside_clip = parity_clip;
246
- edge.bside_subj = parity_subj;
247
-
248
- boolean contributing = false;
249
- int br = 0, bl = 0, tr = 0, tl = 0;
250
- /* Determine contributing status and quadrant occupancies */
251
- if ((op == OperationType.GPC_DIFF) || (op == OperationType.GPC_INT)) {
252
- contributing = ((exists_clip != 0) && ((parity_subj != 0) || (horiz_subj != 0)))
253
- || ((exists_subj != 0) && ((parity_clip != 0) || (horiz_clip != 0)))
254
- || ((exists_clip != 0) && (exists_subj != 0) && (parity_clip == parity_subj));
255
- br = ((parity_clip != 0) && (parity_subj != 0)) ? 1 : 0;
256
- bl = (((parity_clip ^ edge.bundle_above[CLIP]) != 0)
257
- && ((parity_subj ^ edge.bundle_above[SUBJ]) != 0)) ? 1 : 0;
258
- tr = (((parity_clip ^ ((horiz_clip != HState.NH) ? 1 : 0)) != 0)
259
- && ((parity_subj ^ ((horiz_subj != HState.NH) ? 1 : 0)) != 0)) ? 1 : 0;
260
- tl = (((parity_clip ^ ((horiz_clip != HState.NH) ? 1 : 0) ^ edge.bundle_below_clip) != 0)
261
- && ((parity_subj ^ ((horiz_subj != HState.NH) ? 1 : 0) ^ edge.bundle_below_subj) != 0)) ? 1 : 0;
262
- } else if (op == OperationType.GPC_XOR) {
263
- contributing = (exists_clip != 0) || (exists_subj != 0);
264
- br = (parity_clip) ^ (parity_subj);
265
- bl = (parity_clip ^ edge.bundle_above[CLIP]) ^ (parity_subj ^ edge.bundle_above[SUBJ]);
266
- tr = (parity_clip ^ ((horiz_clip != HState.NH) ? 1 : 0)) ^ (parity_subj ^ ((horiz_subj != HState.NH) ? 1 : 0));
267
- tl = (parity_clip ^ ((horiz_clip != HState.NH) ? 1 : 0) ^ edge.bundle_below_clip)
268
- ^ (parity_subj ^ ((horiz_subj != HState.NH) ? 1 : 0) ^ edge.bundle_below_subj);
269
- } else if (op == OperationType.GPC_UNION) {
270
- contributing = ((exists_clip != 0) && (!(parity_subj != 0) || (horiz_subj != 0)))
271
- || ((exists_subj != 0) && (!(parity_clip != 0) || (horiz_clip != 0)))
272
- || ((exists_clip != 0) && (exists_subj != 0) && (parity_clip == parity_subj));
273
- br = ((parity_clip != 0) || (parity_subj != 0)) ? 1 : 0;
274
- bl = (((parity_clip ^ edge.bundle_above[CLIP]) != 0) || ((parity_subj ^ edge.bundle_above[SUBJ]) != 0)) ? 1 : 0;
275
- tr = (((parity_clip ^ ((horiz_clip != HState.NH) ? 1 : 0)) != 0)
276
- || ((parity_subj ^ ((horiz_subj != HState.NH) ? 1 : 0)) != 0)) ? 1 : 0;
277
- tl = (((parity_clip ^ ((horiz_clip != HState.NH) ? 1 : 0) ^ edge.bundle_below_clip) != 0)
278
- || ((parity_subj ^ ((horiz_subj != HState.NH) ? 1 : 0) ^ edge.bundle_below_subj) != 0)) ? 1 : 0;
279
- } else {
280
- throw new IllegalStateException("Unknown op");
281
- }
232
+ int horiz_clip = HState.NH;
233
+ int horiz_subj = HState.NH;
234
+
235
+ int exists_clip = 0;
236
+ int exists_subj = 0;
237
+
238
+ PolygonNode cf = null;
239
+
240
+ /* Process each edge at this scanbeam boundary */
241
+ for (EdgeNode edge = aet.top_node; (edge != null); edge = edge.next) {
242
+ exists_clip = edge.bundle_above[CLIP] + (edge.bundle_below_clip << 1);
243
+ exists_subj = edge.bundle_above[SUBJ] + (edge.bundle_below_subj << 1);
244
+
245
+ if ((exists_clip != 0) || (exists_subj != 0)) {
246
+ /* Set bundle side */
247
+ edge.bside_clip = parity_clip;
248
+ edge.bside_subj = parity_subj;
249
+
250
+ boolean contributing = false;
251
+ int br = 0, bl = 0, tr = 0, tl = 0;
252
+ /* Determine contributing status and quadrant occupancies */
253
+ if ((op == OperationType.GPC_DIFF) || (op == OperationType.GPC_INT)) {
254
+ contributing = ((exists_clip != 0) && ((parity_subj != 0) || (horiz_subj != 0)))
255
+ || ((exists_subj != 0) && ((parity_clip != 0) || (horiz_clip != 0)))
256
+ || ((exists_clip != 0) && (exists_subj != 0) && (parity_clip == parity_subj));
257
+ br = ((parity_clip != 0) && (parity_subj != 0)) ? 1 : 0;
258
+ bl = (((parity_clip ^ edge.bundle_above[CLIP]) != 0)
259
+ && ((parity_subj ^ edge.bundle_above[SUBJ]) != 0)) ? 1 : 0;
260
+ tr = (((parity_clip ^ ((horiz_clip != HState.NH) ? 1 : 0)) != 0)
261
+ && ((parity_subj ^ ((horiz_subj != HState.NH) ? 1 : 0)) != 0)) ? 1 : 0;
262
+ tl = (((parity_clip ^ ((horiz_clip != HState.NH) ? 1 : 0) ^ edge.bundle_below_clip) != 0)
263
+ && ((parity_subj ^ ((horiz_subj != HState.NH) ? 1 : 0) ^ edge.bundle_below_subj) != 0)) ? 1 : 0;
264
+ } else if (op == OperationType.GPC_XOR) {
265
+ contributing = (exists_clip != 0) || (exists_subj != 0);
266
+ br = (parity_clip) ^ (parity_subj);
267
+ bl = (parity_clip ^ edge.bundle_above[CLIP]) ^ (parity_subj ^ edge.bundle_above[SUBJ]);
268
+ tr = (parity_clip ^ ((horiz_clip != HState.NH) ? 1 : 0)) ^ (parity_subj ^ ((horiz_subj != HState.NH) ? 1 : 0));
269
+ tl = (parity_clip ^ ((horiz_clip != HState.NH) ? 1 : 0) ^ edge.bundle_below_clip)
270
+ ^ (parity_subj ^ ((horiz_subj != HState.NH) ? 1 : 0) ^ edge.bundle_below_subj);
271
+ } else if (op == OperationType.GPC_UNION) {
272
+ contributing = ((exists_clip != 0) && (!(parity_subj != 0) || (horiz_subj != 0)))
273
+ || ((exists_subj != 0) && (!(parity_clip != 0) || (horiz_clip != 0)))
274
+ || ((exists_clip != 0) && (exists_subj != 0) && (parity_clip == parity_subj));
275
+ br = ((parity_clip != 0) || (parity_subj != 0)) ? 1 : 0;
276
+ bl = (((parity_clip ^ edge.bundle_above[CLIP]) != 0) || ((parity_subj ^ edge.bundle_above[SUBJ]) != 0)) ? 1 : 0;
277
+ tr = (((parity_clip ^ ((horiz_clip != HState.NH) ? 1 : 0)) != 0)
278
+ || ((parity_subj ^ ((horiz_subj != HState.NH) ? 1 : 0)) != 0)) ? 1 : 0;
279
+ tl = (((parity_clip ^ ((horiz_clip != HState.NH) ? 1 : 0) ^ edge.bundle_below_clip) != 0)
280
+ || ((parity_subj ^ ((horiz_subj != HState.NH) ? 1 : 0) ^ edge.bundle_below_subj) != 0)) ? 1 : 0;
281
+ } else {
282
+ throw new IllegalStateException("Unknown op");
283
+ }
282
284
 
283
- /* Update parity */
284
- parity_clip ^= edge.bundle_above[CLIP];
285
- parity_subj ^= edge.bundle_above[SUBJ];
285
+ /* Update parity */
286
+ parity_clip ^= edge.bundle_above[CLIP];
287
+ parity_subj ^= edge.bundle_above[SUBJ];
286
288
 
287
- /* Update horizontal state */
288
- if (exists_clip != 0) {
289
- horiz_clip = HState.next_h_state[horiz_clip][((exists_clip - 1) << 1) + parity_clip];
290
- }
291
- if (exists_subj != 0) {
292
- horiz_subj = HState.next_h_state[horiz_subj][((exists_subj - 1) << 1) + parity_subj];
293
- }
289
+ /* Update horizontal state */
290
+ if (exists_clip != 0) {
291
+ horiz_clip = HState.NEXT_H_STATE[horiz_clip][((exists_clip - 1) << 1) + parity_clip];
292
+ }
293
+ if (exists_subj != 0) {
294
+ horiz_subj = HState.NEXT_H_STATE[horiz_subj][((exists_subj - 1) << 1) + parity_subj];
295
+ }
294
296
 
295
- if (contributing) // DIFFERENT!
296
- {
297
- float xb = edge.xb;
298
-
299
- int vclass = VertexType.getType(tr, tl, br, bl);
300
- switch (vclass) {
301
- case VertexType.EMN:
302
- case VertexType.IMN:
303
- edge.outp_above = out_poly.add_local_min(xb, yb);
304
- px = xb;
305
- cf = edge.outp_above;
306
- break;
307
- case VertexType.ERI:
308
- if (xb != px) {
309
- cf.add_right(xb, yb);
310
- px = xb;
311
- }
312
- edge.outp_above = cf;
313
- cf = null;
314
- break;
315
- case VertexType.ELI:
316
- edge.outp_below.add_left(xb, yb);
317
- px = xb;
318
- cf = edge.outp_below;
319
- break;
320
- case VertexType.EMX:
321
- if (xb != px) {
322
- cf.add_left(xb, yb);
323
- px = xb;
324
- }
325
- out_poly.merge_right(cf, edge.outp_below);
326
- cf = null;
327
- break;
328
- case VertexType.ILI:
329
- if (xb != px) {
330
- cf.add_left(xb, yb);
331
- px = xb;
332
- }
333
- edge.outp_above = cf;
334
- cf = null;
335
- break;
336
- case VertexType.IRI:
337
- edge.outp_below.add_right(xb, yb);
338
- px = xb;
339
- cf = edge.outp_below;
340
- edge.outp_below = null;
341
- break;
342
- case VertexType.IMX:
343
- if (xb != px) {
344
- cf.add_right(xb, yb);
345
- px = xb;
346
- }
347
- out_poly.merge_left(cf, edge.outp_below);
348
- cf = null;
349
- edge.outp_below = null;
350
- break;
351
- case VertexType.IMM:
352
- if (xb != px) {
353
- cf.add_right(xb, yb);
354
- px = xb;
355
- }
356
- out_poly.merge_left(cf, edge.outp_below);
357
- edge.outp_below = null;
358
- edge.outp_above = out_poly.add_local_min(xb, yb);
359
- cf = edge.outp_above;
360
- break;
361
- case VertexType.EMM:
362
- if (xb != px) {
363
- cf.add_left(xb, yb);
364
- px = xb;
365
- }
366
- out_poly.merge_right(cf, edge.outp_below);
367
- edge.outp_below = null;
368
- edge.outp_above = out_poly.add_local_min(xb, yb);
369
- cf = edge.outp_above;
370
- break;
371
- case VertexType.LED:
372
- if (edge.bot_y == yb) {
373
- edge.outp_below.add_left(xb, yb);
374
- }
375
- edge.outp_above = edge.outp_below;
376
- px = xb;
377
- break;
378
- case VertexType.RED:
379
- if (edge.bot_y == yb) {
380
- edge.outp_below.add_right(xb, yb);
381
- }
382
- edge.outp_above = edge.outp_below;
383
- px = xb;
384
- break;
385
- default:
386
- break;
387
- }
388
- /* End of switch */
389
- }
390
- /* End of contributing conditional */
297
+ if (contributing) // DIFFERENT!
298
+ {
299
+ float xb = edge.xb;
300
+
301
+ int vclass = VertexType.getType(tr, tl, br, bl);
302
+ switch (vclass) {
303
+ case VertexType.EMN:
304
+ case VertexType.IMN:
305
+ edge.outp_above = out_poly.add_local_min(xb, yb);
306
+ px = xb;
307
+ cf = edge.outp_above;
308
+ break;
309
+ case VertexType.ERI:
310
+ if (xb != px) {
311
+ cf.add_right(xb, yb);
312
+ px = xb;
313
+ }
314
+ edge.outp_above = cf;
315
+ cf = null;
316
+ break;
317
+ case VertexType.ELI:
318
+ edge.outp_below.add_left(xb, yb);
319
+ px = xb;
320
+ cf = edge.outp_below;
321
+ break;
322
+ case VertexType.EMX:
323
+ if (xb != px) {
324
+ cf.add_left(xb, yb);
325
+ px = xb;
326
+ }
327
+ out_poly.merge_right(cf, edge.outp_below);
328
+ cf = null;
329
+ break;
330
+ case VertexType.ILI:
331
+ if (xb != px) {
332
+ cf.add_left(xb, yb);
333
+ px = xb;
334
+ }
335
+ edge.outp_above = cf;
336
+ cf = null;
337
+ break;
338
+ case VertexType.IRI:
339
+ edge.outp_below.add_right(xb, yb);
340
+ px = xb;
341
+ cf = edge.outp_below;
342
+ edge.outp_below = null;
343
+ break;
344
+ case VertexType.IMX:
345
+ if (xb != px) {
346
+ cf.add_right(xb, yb);
347
+ px = xb;
391
348
  }
392
- /* End of edge exists conditional */
349
+ out_poly.merge_left(cf, edge.outp_below);
350
+ cf = null;
351
+ edge.outp_below = null;
352
+ break;
353
+ case VertexType.IMM:
354
+ if (xb != px) {
355
+ cf.add_right(xb, yb);
356
+ px = xb;
357
+ }
358
+ out_poly.merge_left(cf, edge.outp_below);
359
+ edge.outp_below = null;
360
+ edge.outp_above = out_poly.add_local_min(xb, yb);
361
+ cf = edge.outp_above;
362
+ break;
363
+ case VertexType.EMM:
364
+ if (xb != px) {
365
+ cf.add_left(xb, yb);
366
+ px = xb;
367
+ }
368
+ out_poly.merge_right(cf, edge.outp_below);
369
+ edge.outp_below = null;
370
+ edge.outp_above = out_poly.add_local_min(xb, yb);
371
+ cf = edge.outp_above;
372
+ break;
373
+ case VertexType.LED:
374
+ if (edge.bot_y == yb) {
375
+ edge.outp_below.add_left(xb, yb);
376
+ }
377
+ edge.outp_above = edge.outp_below;
378
+ px = xb;
379
+ break;
380
+ case VertexType.RED:
381
+ if (edge.bot_y == yb) {
382
+ edge.outp_below.add_right(xb, yb);
383
+ }
384
+ edge.outp_above = edge.outp_below;
385
+ px = xb;
386
+ break;
387
+ default:
388
+ break;
393
389
  }
394
- /* End of AET loop */
390
+ /* End of switch */
391
+ }
392
+ /* End of contributing conditional */
393
+ }
394
+ /* End of edge exists conditional */
395
+ }
396
+ /* End of AET loop */
395
397
 
396
398
  /* Delete terminating edges from the AET, otherwise compute xt */
397
- for (EdgeNode edge = aet.top_node; (edge != null); edge = edge.next) {
398
- if (edge.top_y == yb) {
399
- EdgeNode prev_edge = edge.prev;
400
- EdgeNode next_edge = edge.next;
401
-
402
- if (prev_edge != null) {
403
- prev_edge.next = next_edge;
404
- } else {
405
- aet.top_node = next_edge;
406
- }
399
+ for (EdgeNode edge = aet.top_node; (edge != null); edge = edge.next) {
400
+ if (edge.top_y == yb) {
401
+ EdgeNode prev_edge = edge.prev;
402
+ EdgeNode next_edge = edge.next;
403
+
404
+ if (prev_edge != null) {
405
+ prev_edge.next = next_edge;
406
+ } else {
407
+ aet.top_node = next_edge;
408
+ }
407
409
 
408
- if (next_edge != null) {
409
- next_edge.prev = prev_edge;
410
- }
410
+ if (next_edge != null) {
411
+ next_edge.prev = prev_edge;
412
+ }
411
413
 
412
- /* Copy bundle head state to the adjacent tail edge if required */
413
- if ((edge.bstate_below == BundleState.BUNDLE_HEAD) && (prev_edge != null)) {
414
- if (prev_edge.bstate_below == BundleState.BUNDLE_TAIL) {
415
- prev_edge.outp_below = edge.outp_below;
416
- prev_edge.bstate_below = BundleState.UNBUNDLED;
417
- if (prev_edge.prev != null) {
418
- if (prev_edge.prev.bstate_below == BundleState.BUNDLE_TAIL) {
419
- prev_edge.bstate_below = BundleState.BUNDLE_HEAD;
420
- }
421
- }
422
- }
423
- }
424
- } else {
425
- if (edge.top_y == yt) {
426
- edge.xt = edge.top_x;
427
- } else {
428
- edge.xt = edge.bot_x + edge.dx * (yt - edge.bot_y);
429
- }
414
+ /* Copy bundle head state to the adjacent tail edge if required */
415
+ if ((edge.bstate_below == BundleState.BUNDLE_HEAD) && (prev_edge != null)) {
416
+ if (prev_edge.bstate_below == BundleState.BUNDLE_TAIL) {
417
+ prev_edge.outp_below = edge.outp_below;
418
+ prev_edge.bstate_below = BundleState.UNBUNDLED;
419
+ if (prev_edge.prev != null) {
420
+ if (prev_edge.prev.bstate_below == BundleState.BUNDLE_TAIL) {
421
+ prev_edge.bstate_below = BundleState.BUNDLE_HEAD;
430
422
  }
423
+ }
431
424
  }
425
+ }
426
+ } else {
427
+ if (edge.top_y == yt) {
428
+ edge.xt = edge.top_x;
429
+ } else {
430
+ edge.xt = edge.bot_x + edge.dx * (yt - edge.bot_y);
431
+ }
432
+ }
433
+ }
432
434
 
433
- if (scanbeam < sbte.sbt_entries) {
434
- /* === SCANBEAM INTERIOR PROCESSING ============================== */
435
+ if (scanbeam < sbte.sbt_entries) {
436
+ /* === SCANBEAM INTERIOR PROCESSING ============================== */
435
437
 
436
438
  /* Build intersection table for the current scanbeam */
437
- ItNodeTable it_table = new ItNodeTable();
438
- it_table.build_intersection_table(aet, dy);
439
-
440
- /* Process each node in the intersection table */
441
- for (ItNode intersect = it_table.top_node; (intersect != null); intersect = intersect.next) {
442
- e0 = intersect.ie0;
443
- e1 = intersect.ie1;
444
-
445
- /* Only generate output for contributing intersections */
446
- if (((e0.bundle_above[CLIP] != 0) || (e0.bundle_above[SUBJ] != 0))
447
- && ((e1.bundle_above[CLIP] != 0) || (e1.bundle_above[SUBJ] != 0))) {
448
- PolygonNode p = e0.outp_above;
449
- PolygonNode q = e1.outp_above;
450
- float ix = intersect.point_x;
451
- float iy = intersect.point_y + yb;
452
-
453
- int in_clip = (((e0.bundle_above[CLIP] != 0) && !(e0.bside_clip != 0))
454
- || ((e1.bundle_above[CLIP] != 0) && (e1.bside_clip != 0))
455
- || (!(e0.bundle_above[CLIP] != 0) && !(e1.bundle_above[CLIP] != 0)
456
- && (e0.bside_clip != 0) && (e1.bside_clip != 0))) ? 1 : 0;
457
-
458
- int in_subj = (((e0.bundle_above[SUBJ] != 0) && !(e0.bside_subj != 0))
459
- || ((e1.bundle_above[SUBJ] != 0) && (e1.bside_subj != 0))
460
- || (!(e0.bundle_above[SUBJ] != 0) && !(e1.bundle_above[SUBJ] != 0)
461
- && (e0.bside_subj != 0) && (e1.bside_subj != 0))) ? 1 : 0;
462
-
463
- int tr = 0, tl = 0, br = 0, bl = 0;
464
- /* Determine quadrant occupancies */
465
- if ((op == OperationType.GPC_DIFF) || (op == OperationType.GPC_INT)) {
466
- tr = ((in_clip != 0) && (in_subj != 0)) ? 1 : 0;
467
- tl = (((in_clip ^ e1.bundle_above[CLIP]) != 0) && ((in_subj ^ e1.bundle_above[SUBJ]) != 0)) ? 1 : 0;
468
- br = (((in_clip ^ e0.bundle_above[CLIP]) != 0) && ((in_subj ^ e0.bundle_above[SUBJ]) != 0)) ? 1 : 0;
469
- bl = (((in_clip ^ e1.bundle_above[CLIP] ^ e0.bundle_above[CLIP]) != 0)
470
- && ((in_subj ^ e1.bundle_above[SUBJ] ^ e0.bundle_above[SUBJ]) != 0)) ? 1 : 0;
471
- } else if (op == OperationType.GPC_XOR) {
472
- tr = (in_clip) ^ (in_subj);
473
- tl = (in_clip ^ e1.bundle_above[CLIP]) ^ (in_subj ^ e1.bundle_above[SUBJ]);
474
- br = (in_clip ^ e0.bundle_above[CLIP]) ^ (in_subj ^ e0.bundle_above[SUBJ]);
475
- bl = (in_clip ^ e1.bundle_above[CLIP] ^ e0.bundle_above[CLIP])
476
- ^ (in_subj ^ e1.bundle_above[SUBJ] ^ e0.bundle_above[SUBJ]);
477
- } else if (op == OperationType.GPC_UNION) {
478
- tr = ((in_clip != 0) || (in_subj != 0)) ? 1 : 0;
479
- tl = (((in_clip ^ e1.bundle_above[CLIP]) != 0) || ((in_subj ^ e1.bundle_above[SUBJ]) != 0)) ? 1 : 0;
480
- br = (((in_clip ^ e0.bundle_above[CLIP]) != 0) || ((in_subj ^ e0.bundle_above[SUBJ]) != 0)) ? 1 : 0;
481
- bl = (((in_clip ^ e1.bundle_above[CLIP] ^ e0.bundle_above[CLIP]) != 0)
482
- || ((in_subj ^ e1.bundle_above[SUBJ] ^ e0.bundle_above[SUBJ]) != 0)) ? 1 : 0;
483
- } else {
484
- throw new IllegalStateException("Unknown op type, " + op);
485
- }
486
-
487
- int vclass = VertexType.getType(tr, tl, br, bl);
488
- switch (vclass) {
489
- case VertexType.EMN:
490
- e0.outp_above = out_poly.add_local_min(ix, iy);
491
- e1.outp_above = e0.outp_above;
492
- break;
493
- case VertexType.ERI:
494
- if (p != null) {
495
- p.add_right(ix, iy);
496
- e1.outp_above = p;
497
- e0.outp_above = null;
498
- }
499
- break;
500
- case VertexType.ELI:
501
- if (q != null) {
502
- q.add_left(ix, iy);
503
- e0.outp_above = q;
504
- e1.outp_above = null;
505
- }
506
- break;
507
- case VertexType.EMX:
508
- if ((p != null) && (q != null)) {
509
- p.add_left(ix, iy);
510
- out_poly.merge_right(p, q);
511
- e0.outp_above = null;
512
- e1.outp_above = null;
513
- }
514
- break;
515
- case VertexType.IMN:
516
- e0.outp_above = out_poly.add_local_min(ix, iy);
517
- e1.outp_above = e0.outp_above;
518
- break;
519
- case VertexType.ILI:
520
- if (p != null) {
521
- p.add_left(ix, iy);
522
- e1.outp_above = p;
523
- e0.outp_above = null;
524
- }
525
- break;
526
- case VertexType.IRI:
527
- if (q != null) {
528
- q.add_right(ix, iy);
529
- e0.outp_above = q;
530
- e1.outp_above = null;
531
- }
532
- break;
533
- case VertexType.IMX:
534
- if ((p != null) && (q != null)) {
535
- p.add_right(ix, iy);
536
- out_poly.merge_left(p, q);
537
- e0.outp_above = null;
538
- e1.outp_above = null;
539
- }
540
- break;
541
- case VertexType.IMM:
542
- if ((p != null) && (q != null)) {
543
- p.add_right(ix, iy);
544
- out_poly.merge_left(p, q);
545
- e0.outp_above = out_poly.add_local_min(ix, iy);
546
- e1.outp_above = e0.outp_above;
547
- }
548
- break;
549
- case VertexType.EMM:
550
- if ((p != null) && (q != null)) {
551
- p.add_left(ix, iy);
552
- out_poly.merge_right(p, q);
553
- e0.outp_above = out_poly.add_local_min(ix, iy);
554
- e1.outp_above = e0.outp_above;
555
- }
556
- break;
557
- default:
558
- break;
559
- }
560
- /* End of switch */
561
- }
562
- /* End of contributing intersection conditional */
439
+ ItNodeTable it_table = new ItNodeTable();
440
+ it_table.build_intersection_table(aet, dy);
441
+
442
+ /* Process each node in the intersection table */
443
+ for (ItNode intersect = it_table.top_node; (intersect != null); intersect = intersect.next) {
444
+ e0 = intersect.ie0;
445
+ e1 = intersect.ie1;
446
+
447
+ /* Only generate output for contributing intersections */
448
+ if (((e0.bundle_above[CLIP] != 0) || (e0.bundle_above[SUBJ] != 0))
449
+ && ((e1.bundle_above[CLIP] != 0) || (e1.bundle_above[SUBJ] != 0))) {
450
+ PolygonNode p = e0.outp_above;
451
+ PolygonNode q = e1.outp_above;
452
+ float ix = intersect.point_x;
453
+ float iy = intersect.point_y + yb;
454
+
455
+ int in_clip = (((e0.bundle_above[CLIP] != 0) && !(e0.bside_clip != 0))
456
+ || ((e1.bundle_above[CLIP] != 0) && (e1.bside_clip != 0))
457
+ || (!(e0.bundle_above[CLIP] != 0) && !(e1.bundle_above[CLIP] != 0)
458
+ && (e0.bside_clip != 0) && (e1.bside_clip != 0))) ? 1 : 0;
459
+
460
+ int in_subj = (((e0.bundle_above[SUBJ] != 0) && !(e0.bside_subj != 0))
461
+ || ((e1.bundle_above[SUBJ] != 0) && (e1.bside_subj != 0))
462
+ || (!(e0.bundle_above[SUBJ] != 0) && !(e1.bundle_above[SUBJ] != 0)
463
+ && (e0.bside_subj != 0) && (e1.bside_subj != 0))) ? 1 : 0;
464
+
465
+ int tr = 0, tl = 0, br = 0, bl = 0;
466
+ /* Determine quadrant occupancies */
467
+ if ((op == OperationType.GPC_DIFF) || (op == OperationType.GPC_INT)) {
468
+ tr = ((in_clip != 0) && (in_subj != 0)) ? 1 : 0;
469
+ tl = (((in_clip ^ e1.bundle_above[CLIP]) != 0) && ((in_subj ^ e1.bundle_above[SUBJ]) != 0)) ? 1 : 0;
470
+ br = (((in_clip ^ e0.bundle_above[CLIP]) != 0) && ((in_subj ^ e0.bundle_above[SUBJ]) != 0)) ? 1 : 0;
471
+ bl = (((in_clip ^ e1.bundle_above[CLIP] ^ e0.bundle_above[CLIP]) != 0)
472
+ && ((in_subj ^ e1.bundle_above[SUBJ] ^ e0.bundle_above[SUBJ]) != 0)) ? 1 : 0;
473
+ } else if (op == OperationType.GPC_XOR) {
474
+ tr = (in_clip) ^ (in_subj);
475
+ tl = (in_clip ^ e1.bundle_above[CLIP]) ^ (in_subj ^ e1.bundle_above[SUBJ]);
476
+ br = (in_clip ^ e0.bundle_above[CLIP]) ^ (in_subj ^ e0.bundle_above[SUBJ]);
477
+ bl = (in_clip ^ e1.bundle_above[CLIP] ^ e0.bundle_above[CLIP])
478
+ ^ (in_subj ^ e1.bundle_above[SUBJ] ^ e0.bundle_above[SUBJ]);
479
+ } else if (op == OperationType.GPC_UNION) {
480
+ tr = ((in_clip != 0) || (in_subj != 0)) ? 1 : 0;
481
+ tl = (((in_clip ^ e1.bundle_above[CLIP]) != 0) || ((in_subj ^ e1.bundle_above[SUBJ]) != 0)) ? 1 : 0;
482
+ br = (((in_clip ^ e0.bundle_above[CLIP]) != 0) || ((in_subj ^ e0.bundle_above[SUBJ]) != 0)) ? 1 : 0;
483
+ bl = (((in_clip ^ e1.bundle_above[CLIP] ^ e0.bundle_above[CLIP]) != 0)
484
+ || ((in_subj ^ e1.bundle_above[SUBJ] ^ e0.bundle_above[SUBJ]) != 0)) ? 1 : 0;
485
+ } else {
486
+ throw new IllegalStateException("Unknown op type, " + op);
487
+ }
488
+
489
+ int vclass = VertexType.getType(tr, tl, br, bl);
490
+ switch (vclass) {
491
+ case VertexType.EMN:
492
+ e0.outp_above = out_poly.add_local_min(ix, iy);
493
+ e1.outp_above = e0.outp_above;
494
+ break;
495
+ case VertexType.ERI:
496
+ if (p != null) {
497
+ p.add_right(ix, iy);
498
+ e1.outp_above = p;
499
+ e0.outp_above = null;
500
+ }
501
+ break;
502
+ case VertexType.ELI:
503
+ if (q != null) {
504
+ q.add_left(ix, iy);
505
+ e0.outp_above = q;
506
+ e1.outp_above = null;
507
+ }
508
+ break;
509
+ case VertexType.EMX:
510
+ if ((p != null) && (q != null)) {
511
+ p.add_left(ix, iy);
512
+ out_poly.merge_right(p, q);
513
+ e0.outp_above = null;
514
+ e1.outp_above = null;
515
+ }
516
+ break;
517
+ case VertexType.IMN:
518
+ e0.outp_above = out_poly.add_local_min(ix, iy);
519
+ e1.outp_above = e0.outp_above;
520
+ break;
521
+ case VertexType.ILI:
522
+ if (p != null) {
523
+ p.add_left(ix, iy);
524
+ e1.outp_above = p;
525
+ e0.outp_above = null;
526
+ }
527
+ break;
528
+ case VertexType.IRI:
529
+ if (q != null) {
530
+ q.add_right(ix, iy);
531
+ e0.outp_above = q;
532
+ e1.outp_above = null;
533
+ }
534
+ break;
535
+ case VertexType.IMX:
536
+ if ((p != null) && (q != null)) {
537
+ p.add_right(ix, iy);
538
+ out_poly.merge_left(p, q);
539
+ e0.outp_above = null;
540
+ e1.outp_above = null;
541
+ }
542
+ break;
543
+ case VertexType.IMM:
544
+ if ((p != null) && (q != null)) {
545
+ p.add_right(ix, iy);
546
+ out_poly.merge_left(p, q);
547
+ e0.outp_above = out_poly.add_local_min(ix, iy);
548
+ e1.outp_above = e0.outp_above;
549
+ }
550
+ break;
551
+ case VertexType.EMM:
552
+ if ((p != null) && (q != null)) {
553
+ p.add_left(ix, iy);
554
+ out_poly.merge_right(p, q);
555
+ e0.outp_above = out_poly.add_local_min(ix, iy);
556
+ e1.outp_above = e0.outp_above;
557
+ }
558
+ break;
559
+ default:
560
+ break;
561
+ }
562
+ /* End of switch */
563
+ }
564
+ /* End of contributing intersection conditional */
563
565
 
564
566
  /* Swap bundle sides in response to edge crossing */
565
- if (e0.bundle_above[CLIP] != 0) {
566
- e1.bside_clip = (e1.bside_clip == 0) ? 1 : 0;
567
- }
568
- if (e1.bundle_above[CLIP] != 0) {
569
- e0.bside_clip = (e0.bside_clip == 0) ? 1 : 0;
570
- }
571
- if (e0.bundle_above[SUBJ] != 0) {
572
- e1.bside_subj = (e1.bside_subj == 0) ? 1 : 0;
573
- }
574
- if (e1.bundle_above[SUBJ] != 0) {
575
- e0.bside_subj = (e0.bside_subj == 0) ? 1 : 0;
576
- }
567
+ if (e0.bundle_above[CLIP] != 0) {
568
+ e1.bside_clip = (e1.bside_clip == 0) ? 1 : 0;
569
+ }
570
+ if (e1.bundle_above[CLIP] != 0) {
571
+ e0.bside_clip = (e0.bside_clip == 0) ? 1 : 0;
572
+ }
573
+ if (e0.bundle_above[SUBJ] != 0) {
574
+ e1.bside_subj = (e1.bside_subj == 0) ? 1 : 0;
575
+ }
576
+ if (e1.bundle_above[SUBJ] != 0) {
577
+ e0.bside_subj = (e0.bside_subj == 0) ? 1 : 0;
578
+ }
577
579
 
578
- /* Swap e0 and e1 bundles in the AET */
579
- EdgeNode prev_edge = e0.prev;
580
- EdgeNode next_edge = e1.next;
581
- if (next_edge != null) {
582
- next_edge.prev = e0;
583
- }
580
+ /* Swap e0 and e1 bundles in the AET */
581
+ EdgeNode prev_edge = e0.prev;
582
+ EdgeNode next_edge = e1.next;
583
+ if (next_edge != null) {
584
+ next_edge.prev = e0;
585
+ }
584
586
 
585
- if (e0.bstate_above == BundleState.BUNDLE_HEAD) {
586
- boolean search = true;
587
- while (search) {
588
- prev_edge = prev_edge.prev;
589
- if (prev_edge != null) {
590
- if (prev_edge.bstate_above != BundleState.BUNDLE_TAIL) {
591
- search = false;
592
- }
593
- } else {
594
- search = false;
595
- }
596
- }
597
- }
598
- if (prev_edge == null) {
599
- aet.top_node.prev = e1;
600
- e1.next = aet.top_node;
601
- aet.top_node = e0.next;
602
- } else {
603
- prev_edge.next.prev = e1;
604
- e1.next = prev_edge.next;
605
- prev_edge.next = e0.next;
606
- }
607
- e0.next.prev = prev_edge;
608
- e1.next.prev = e1;
609
- e0.next = next_edge;
587
+ if (e0.bstate_above == BundleState.BUNDLE_HEAD) {
588
+ boolean search = true;
589
+ while (search) {
590
+ prev_edge = prev_edge.prev;
591
+ if (prev_edge != null) {
592
+ if (prev_edge.bstate_above != BundleState.BUNDLE_TAIL) {
593
+ search = false;
610
594
  }
611
- /* End of IT loop*/
595
+ } else {
596
+ search = false;
597
+ }
598
+ }
599
+ }
600
+ if (prev_edge == null) {
601
+ aet.top_node.prev = e1;
602
+ e1.next = aet.top_node;
603
+ aet.top_node = e0.next;
604
+ } else {
605
+ prev_edge.next.prev = e1;
606
+ e1.next = prev_edge.next;
607
+ prev_edge.next = e0.next;
608
+ }
609
+ e0.next.prev = prev_edge;
610
+ e1.next.prev = e1;
611
+ e0.next = next_edge;
612
+ }
613
+ /* End of IT loop*/
612
614
 
613
615
  /* Prepare for next scanbeam */
614
- for (EdgeNode edge = aet.top_node; (edge != null); edge = edge.next) {
615
- EdgeNode next_edge = edge.next;
616
- EdgeNode succ_edge = edge.succ;
617
- if ((edge.top_y == yt) && (succ_edge != null)) {
618
- /* Replace AET edge by its successor */
619
- succ_edge.outp_below = edge.outp_above;
620
- succ_edge.bstate_below = edge.bstate_above;
621
- succ_edge.bundle_below_clip = edge.bundle_above[CLIP];
622
- succ_edge.bundle_below_subj = edge.bundle_above[SUBJ];
623
- EdgeNode prev_edge = edge.prev;
624
- if (prev_edge != null) {
625
- prev_edge.next = succ_edge;
626
- } else {
627
- aet.top_node = succ_edge;
628
- }
629
- if (next_edge != null) {
630
- next_edge.prev = succ_edge;
631
- }
632
- succ_edge.prev = prev_edge;
633
- succ_edge.next = next_edge;
634
- } else {
635
- /* Update this edge */
636
- edge.outp_below = edge.outp_above;
637
- edge.bstate_below = edge.bstate_above;
638
- edge.bundle_below_clip = edge.bundle_above[CLIP];
639
- edge.bundle_below_subj = edge.bundle_above[SUBJ];
640
- edge.xb = edge.xt;
641
- }
642
- edge.outp_above = null;
643
- }
616
+ for (EdgeNode edge = aet.top_node; (edge != null); edge = edge.next) {
617
+ EdgeNode next_edge = edge.next;
618
+ EdgeNode succ_edge = edge.succ;
619
+ if ((edge.top_y == yt) && (succ_edge != null)) {
620
+ /* Replace AET edge by its successor */
621
+ succ_edge.outp_below = edge.outp_above;
622
+ succ_edge.bstate_below = edge.bstate_above;
623
+ succ_edge.bundle_below_clip = edge.bundle_above[CLIP];
624
+ succ_edge.bundle_below_subj = edge.bundle_above[SUBJ];
625
+ EdgeNode prev_edge = edge.prev;
626
+ if (prev_edge != null) {
627
+ prev_edge.next = succ_edge;
628
+ } else {
629
+ aet.top_node = succ_edge;
630
+ }
631
+ if (next_edge != null) {
632
+ next_edge.prev = succ_edge;
644
633
  }
634
+ succ_edge.prev = prev_edge;
635
+ succ_edge.next = next_edge;
636
+ } else {
637
+ /* Update this edge */
638
+ edge.outp_below = edge.outp_above;
639
+ edge.bstate_below = edge.bstate_above;
640
+ edge.bundle_below_clip = edge.bundle_above[CLIP];
641
+ edge.bundle_below_subj = edge.bundle_above[SUBJ];
642
+ edge.xb = edge.xt;
643
+ }
644
+ edge.outp_above = null;
645
645
  }
646
- /* === END OF SCANBEAM PROCESSING ================================== */
646
+ }
647
+ }
648
+ /* === END OF SCANBEAM PROCESSING ================================== */
647
649
 
648
650
  /* Generate result polygon from out_poly */
649
- result = out_poly.getResult(polyClass);
650
-
651
- return result;
651
+ result = out_poly.getResult(polyClass);
652
+
653
+ return result;
654
+ }
655
+
656
+ /**
657
+ * Clipper to output tristrips
658
+ */
659
+ static RMesh clip(OperationType op, RPolygon subj, RPolygon clip) {
660
+ PolygonNode tlist = null;
661
+ float nx = 0;
662
+
663
+ /* Test for trivial NULL result cases */
664
+ if ((subj.isEmpty() && clip.isEmpty())
665
+ || (subj.isEmpty() && ((op == OperationType.GPC_INT) || (op == OperationType.GPC_DIFF)))
666
+ || (clip.isEmpty() && (op == OperationType.GPC_INT))) {
667
+ return null;
652
668
  }
653
669
 
654
- /**
655
- * Clipper to output tristrips
656
- */
657
- static RMesh clip(OperationType op, RPolygon subj, RPolygon clip) {
658
- PolygonNode tlist = null;
659
- float nx = 0;
660
-
661
- /* Test for trivial NULL result cases */
662
- if ((subj.isEmpty() && clip.isEmpty())
663
- || (subj.isEmpty() && ((op == OperationType.GPC_INT) || (op == OperationType.GPC_DIFF)))
664
- || (clip.isEmpty() && (op == OperationType.GPC_INT))) {
665
- return null;
666
- }
667
-
668
- /* Identify potentialy contributing contours */
669
- if (((op == OperationType.GPC_INT) || (op == OperationType.GPC_DIFF))
670
- && !subj.isEmpty() && !clip.isEmpty()) {
671
- minimax_test(subj, clip, op);
672
- }
670
+ /* Identify potentialy contributing contours */
671
+ if (((op == OperationType.GPC_INT) || (op == OperationType.GPC_DIFF))
672
+ && !subj.isEmpty() && !clip.isEmpty()) {
673
+ minimax_test(subj, clip, op);
674
+ }
673
675
 
674
- /* Build LMT */
675
- LmtTable lmt_table = new LmtTable();
676
- ScanBeamTreeEntries sbte = new ScanBeamTreeEntries();
677
- if (!subj.isEmpty()) {
678
- build_lmt(lmt_table, sbte, subj, SUBJ, op);
679
- }
680
- if (!clip.isEmpty()) {
681
- build_lmt(lmt_table, sbte, clip, CLIP, op);
682
- }
676
+ /* Build LMT */
677
+ LmtTable lmt_table = new LmtTable();
678
+ ScanBeamTreeEntries sbte = new ScanBeamTreeEntries();
679
+ if (!subj.isEmpty()) {
680
+ build_lmt(lmt_table, sbte, subj, SUBJ, op);
681
+ }
682
+ if (!clip.isEmpty()) {
683
+ build_lmt(lmt_table, sbte, clip, CLIP, op);
684
+ }
683
685
 
684
- /* Return a NULL result if no contours contribute */
685
- if (lmt_table.top_node == null) {
686
- return null;
687
- }
686
+ /* Return a NULL result if no contours contribute */
687
+ if (lmt_table.top_node == null) {
688
+ return null;
689
+ }
688
690
 
689
- /* Build scanbeam table from scanbeam tree */
690
- float[] sbt = sbte.build_sbt();
691
+ /* Build scanbeam table from scanbeam tree */
692
+ float[] sbt = sbte.build_sbt();
691
693
 
692
- int parity_clip = LEFT;
693
- int parity_subj = LEFT;
694
+ int parity_clip = LEFT;
695
+ int parity_subj = LEFT;
694
696
 
695
- /* Invert clip polygon for difference operation */
696
- if (op == OperationType.GPC_DIFF) {
697
- parity_clip = RIGHT;
698
- }
697
+ /* Invert clip polygon for difference operation */
698
+ if (op == OperationType.GPC_DIFF) {
699
+ parity_clip = RIGHT;
700
+ }
699
701
 
700
- LmtNode local_min = lmt_table.top_node;
702
+ LmtNode local_min = lmt_table.top_node;
701
703
 
702
- AetTree aet = new AetTree();
703
- int scanbeam = 0;
704
+ AetTree aet = new AetTree();
705
+ int scanbeam = 0;
704
706
 
705
- /* Process each scanbeam */
706
- while (scanbeam < sbt.length) {
707
- /* Set yb and yt to the bottom and top of the scanbeam */
708
- float yb = sbt[scanbeam++];
709
- float yt = 0.0F;
710
- float dy = 0.0F;
711
- if (scanbeam < sbt.length) {
712
- yt = sbt[scanbeam];
713
- dy = yt - yb;
714
- }
707
+ /* Process each scanbeam */
708
+ while (scanbeam < sbt.length) {
709
+ /* Set yb and yt to the bottom and top of the scanbeam */
710
+ float yb = sbt[scanbeam++];
711
+ float yt = 0.0F;
712
+ float dy = 0.0F;
713
+ if (scanbeam < sbt.length) {
714
+ yt = sbt[scanbeam];
715
+ dy = yt - yb;
716
+ }
715
717
 
716
- /* === SCANBEAM BOUNDARY PROCESSING ================================ */
718
+ /* === SCANBEAM BOUNDARY PROCESSING ================================ */
717
719
  /* If LMT node corresponding to yb exists */
718
- if (local_min != null) {
719
- if (local_min.y == yb) {
720
- /* Add edges starting at this local minimum to the AET */
721
- for (EdgeNode edge = local_min.first_bound; (edge != null); edge = edge.next_bound) {
722
- add_edge_to_aet(aet, edge);
723
- }
720
+ if (local_min != null) {
721
+ if (local_min.y == yb) {
722
+ /* Add edges starting at this local minimum to the AET */
723
+ for (EdgeNode edge = local_min.first_bound; (edge != null); edge = edge.next_bound) {
724
+ add_edge_to_aet(aet, edge);
725
+ }
724
726
 
725
- local_min = local_min.next;
726
- }
727
- }
727
+ local_min = local_min.next;
728
+ }
729
+ }
728
730
 
729
- /* Set dummy previous x value */
730
- float px = -Float.MAX_VALUE;
731
-
732
- /* Create bundles within AET */
733
- EdgeNode e0 = aet.top_node;
734
- EdgeNode e1 = aet.top_node;
735
-
736
- /* Set up bundle fields of first edge */
737
- aet.top_node.bundle_above[aet.top_node.type] = (aet.top_node.top_y != yb) ? 1 : 0;
738
- aet.top_node.bundle_above[((aet.top_node.type == 0) ? 1 : 0)] = 0;
739
- aet.top_node.bstate_above = BundleState.UNBUNDLED;
740
-
741
- for (EdgeNode next_edge = aet.top_node.next; (next_edge != null); next_edge = next_edge.next) {
742
- int ne_type = next_edge.type;
743
- int ne_type_opp = ((next_edge.type == 0) ? 1 : 0); //next edge type opposite
744
-
745
- /* Set up bundle fields of next edge */
746
- next_edge.bundle_above[ne_type] = (next_edge.top_y != yb) ? 1 : 0;
747
- next_edge.bundle_above[ne_type_opp] = 0;
748
- next_edge.bstate_above = BundleState.UNBUNDLED;
749
-
750
- /* Bundle edges above the scanbeam boundary if they coincide */
751
- if (next_edge.bundle_above[ne_type] == 1) {
752
- if (EQ(e0.xb, next_edge.xb) && EQ(e0.dx, next_edge.dx) && (e0.top_y != yb)) {
753
- next_edge.bundle_above[ne_type] ^= e0.bundle_above[ne_type];
754
- next_edge.bundle_above[ne_type_opp] = e0.bundle_above[ne_type_opp];
755
- next_edge.bstate_above = BundleState.BUNDLE_HEAD;
756
- e0.bundle_above[CLIP] = 0;
757
- e0.bundle_above[SUBJ] = 0;
758
- e0.bstate_above = BundleState.BUNDLE_TAIL;
759
- }
760
- e0 = next_edge;
761
- }
762
- }
731
+ /* Set dummy previous x value */
732
+ float px = -Float.MAX_VALUE;
733
+
734
+ /* Create bundles within AET */
735
+ EdgeNode e0 = aet.top_node;
736
+ EdgeNode e1 = aet.top_node;
737
+
738
+ /* Set up bundle fields of first edge */
739
+ aet.top_node.bundle_above[aet.top_node.type] = (aet.top_node.top_y != yb) ? 1 : 0;
740
+ aet.top_node.bundle_above[((aet.top_node.type == 0) ? 1 : 0)] = 0;
741
+ aet.top_node.bstate_above = BundleState.UNBUNDLED;
742
+
743
+ for (EdgeNode next_edge = aet.top_node.next; (next_edge != null); next_edge = next_edge.next) {
744
+ int ne_type = next_edge.type;
745
+ int ne_type_opp = ((next_edge.type == 0) ? 1 : 0); //next edge type opposite
746
+
747
+ /* Set up bundle fields of next edge */
748
+ next_edge.bundle_above[ne_type] = (next_edge.top_y != yb) ? 1 : 0;
749
+ next_edge.bundle_above[ne_type_opp] = 0;
750
+ next_edge.bstate_above = BundleState.UNBUNDLED;
751
+
752
+ /* Bundle edges above the scanbeam boundary if they coincide */
753
+ if (next_edge.bundle_above[ne_type] == 1) {
754
+ if (EQ(e0.xb, next_edge.xb) && EQ(e0.dx, next_edge.dx) && (e0.top_y != yb)) {
755
+ next_edge.bundle_above[ne_type] ^= e0.bundle_above[ne_type];
756
+ next_edge.bundle_above[ne_type_opp] = e0.bundle_above[ne_type_opp];
757
+ next_edge.bstate_above = BundleState.BUNDLE_HEAD;
758
+ e0.bundle_above[CLIP] = 0;
759
+ e0.bundle_above[SUBJ] = 0;
760
+ e0.bstate_above = BundleState.BUNDLE_TAIL;
761
+ }
762
+ e0 = next_edge;
763
+ }
764
+ }
763
765
 
764
- int horiz_clip = HState.NH;
765
- int horiz_subj = HState.NH;
766
-
767
- int exists_clip = 0;
768
- int exists_subj = 0;
769
-
770
- EdgeNode cf = null;
771
- int cft = VertexType.LED;
772
-
773
- /* Process each edge at this scanbeam boundary */
774
- for (EdgeNode edge = aet.top_node; (edge != null); edge = edge.next) {
775
- exists_clip = edge.bundle_above[CLIP] + (edge.bundle_below_clip << 1);
776
- exists_subj = edge.bundle_above[SUBJ] + (edge.bundle_below_subj << 1);
777
-
778
- if ((exists_clip != 0) || (exists_subj != 0)) {
779
- /* Set bundle side */
780
- edge.bside_clip = parity_clip;
781
- edge.bside_subj = parity_subj;
782
-
783
- boolean contributing = false;
784
- int br = 0, bl = 0, tr = 0, tl = 0;
785
- /* Determine contributing status and quadrant occupancies */
786
- if ((op == OperationType.GPC_DIFF) || (op == OperationType.GPC_INT)) {
787
- contributing = ((exists_clip != 0) && ((parity_subj != 0) || (horiz_subj != 0)))
788
- || ((exists_subj != 0) && ((parity_clip != 0) || (horiz_clip != 0)))
789
- || ((exists_clip != 0) && (exists_subj != 0) && (parity_clip == parity_subj));
790
- br = ((parity_clip != 0) && (parity_subj != 0)) ? 1 : 0;
791
- bl = (((parity_clip ^ edge.bundle_above[CLIP]) != 0)
792
- && ((parity_subj ^ edge.bundle_above[SUBJ]) != 0)) ? 1 : 0;
793
- tr = (((parity_clip ^ ((horiz_clip != HState.NH) ? 1 : 0)) != 0)
794
- && ((parity_subj ^ ((horiz_subj != HState.NH) ? 1 : 0)) != 0)) ? 1 : 0;
795
- tl = (((parity_clip ^ ((horiz_clip != HState.NH) ? 1 : 0) ^ edge.bundle_below_clip) != 0)
796
- && ((parity_subj ^ ((horiz_subj != HState.NH) ? 1 : 0) ^ edge.bundle_below_subj) != 0)) ? 1 : 0;
797
- } else if (op == OperationType.GPC_XOR) {
798
- contributing = (exists_clip != 0) || (exists_subj != 0);
799
- br = (parity_clip) ^ (parity_subj);
800
- bl = (parity_clip ^ edge.bundle_above[CLIP]) ^ (parity_subj ^ edge.bundle_above[SUBJ]);
801
- tr = (parity_clip ^ ((horiz_clip != HState.NH) ? 1 : 0)) ^ (parity_subj ^ ((horiz_subj != HState.NH) ? 1 : 0));
802
- tl = (parity_clip ^ ((horiz_clip != HState.NH) ? 1 : 0) ^ edge.bundle_below_clip)
803
- ^ (parity_subj ^ ((horiz_subj != HState.NH) ? 1 : 0) ^ edge.bundle_below_subj);
804
- } else if (op == OperationType.GPC_UNION) {
805
- contributing = ((exists_clip != 0) && (!(parity_subj != 0) || (horiz_subj != 0)))
806
- || ((exists_subj != 0) && (!(parity_clip != 0) || (horiz_clip != 0)))
807
- || ((exists_clip != 0) && (exists_subj != 0) && (parity_clip == parity_subj));
808
- br = ((parity_clip != 0) || (parity_subj != 0)) ? 1 : 0;
809
- bl = (((parity_clip ^ edge.bundle_above[CLIP]) != 0) || ((parity_subj ^ edge.bundle_above[SUBJ]) != 0)) ? 1 : 0;
810
- tr = (((parity_clip ^ ((horiz_clip != HState.NH) ? 1 : 0)) != 0)
811
- || ((parity_subj ^ ((horiz_subj != HState.NH) ? 1 : 0)) != 0)) ? 1 : 0;
812
- tl = (((parity_clip ^ ((horiz_clip != HState.NH) ? 1 : 0) ^ edge.bundle_below_clip) != 0)
813
- || ((parity_subj ^ ((horiz_subj != HState.NH) ? 1 : 0) ^ edge.bundle_below_subj) != 0)) ? 1 : 0;
814
- } else {
815
- throw new IllegalStateException("Unknown op");
816
- }
766
+ int horiz_clip = HState.NH;
767
+ int horiz_subj = HState.NH;
768
+
769
+ int exists_clip = 0;
770
+ int exists_subj = 0;
771
+
772
+ EdgeNode cf = null;
773
+ int cft = VertexType.LED;
774
+
775
+ /* Process each edge at this scanbeam boundary */
776
+ for (EdgeNode edge = aet.top_node; (edge != null); edge = edge.next) {
777
+ exists_clip = edge.bundle_above[CLIP] + (edge.bundle_below_clip << 1);
778
+ exists_subj = edge.bundle_above[SUBJ] + (edge.bundle_below_subj << 1);
779
+
780
+ if ((exists_clip != 0) || (exists_subj != 0)) {
781
+ /* Set bundle side */
782
+ edge.bside_clip = parity_clip;
783
+ edge.bside_subj = parity_subj;
784
+
785
+ boolean contributing = false;
786
+ int br = 0, bl = 0, tr = 0, tl = 0;
787
+ /* Determine contributing status and quadrant occupancies */
788
+ if ((op == OperationType.GPC_DIFF) || (op == OperationType.GPC_INT)) {
789
+ contributing = ((exists_clip != 0) && ((parity_subj != 0) || (horiz_subj != 0)))
790
+ || ((exists_subj != 0) && ((parity_clip != 0) || (horiz_clip != 0)))
791
+ || ((exists_clip != 0) && (exists_subj != 0) && (parity_clip == parity_subj));
792
+ br = ((parity_clip != 0) && (parity_subj != 0)) ? 1 : 0;
793
+ bl = (((parity_clip ^ edge.bundle_above[CLIP]) != 0)
794
+ && ((parity_subj ^ edge.bundle_above[SUBJ]) != 0)) ? 1 : 0;
795
+ tr = (((parity_clip ^ ((horiz_clip != HState.NH) ? 1 : 0)) != 0)
796
+ && ((parity_subj ^ ((horiz_subj != HState.NH) ? 1 : 0)) != 0)) ? 1 : 0;
797
+ tl = (((parity_clip ^ ((horiz_clip != HState.NH) ? 1 : 0) ^ edge.bundle_below_clip) != 0)
798
+ && ((parity_subj ^ ((horiz_subj != HState.NH) ? 1 : 0) ^ edge.bundle_below_subj) != 0)) ? 1 : 0;
799
+ } else if (op == OperationType.GPC_XOR) {
800
+ contributing = (exists_clip != 0) || (exists_subj != 0);
801
+ br = (parity_clip) ^ (parity_subj);
802
+ bl = (parity_clip ^ edge.bundle_above[CLIP]) ^ (parity_subj ^ edge.bundle_above[SUBJ]);
803
+ tr = (parity_clip ^ ((horiz_clip != HState.NH) ? 1 : 0)) ^ (parity_subj ^ ((horiz_subj != HState.NH) ? 1 : 0));
804
+ tl = (parity_clip ^ ((horiz_clip != HState.NH) ? 1 : 0) ^ edge.bundle_below_clip)
805
+ ^ (parity_subj ^ ((horiz_subj != HState.NH) ? 1 : 0) ^ edge.bundle_below_subj);
806
+ } else if (op == OperationType.GPC_UNION) {
807
+ contributing = ((exists_clip != 0) && (!(parity_subj != 0) || (horiz_subj != 0)))
808
+ || ((exists_subj != 0) && (!(parity_clip != 0) || (horiz_clip != 0)))
809
+ || ((exists_clip != 0) && (exists_subj != 0) && (parity_clip == parity_subj));
810
+ br = ((parity_clip != 0) || (parity_subj != 0)) ? 1 : 0;
811
+ bl = (((parity_clip ^ edge.bundle_above[CLIP]) != 0) || ((parity_subj ^ edge.bundle_above[SUBJ]) != 0)) ? 1 : 0;
812
+ tr = (((parity_clip ^ ((horiz_clip != HState.NH) ? 1 : 0)) != 0)
813
+ || ((parity_subj ^ ((horiz_subj != HState.NH) ? 1 : 0)) != 0)) ? 1 : 0;
814
+ tl = (((parity_clip ^ ((horiz_clip != HState.NH) ? 1 : 0) ^ edge.bundle_below_clip) != 0)
815
+ || ((parity_subj ^ ((horiz_subj != HState.NH) ? 1 : 0) ^ edge.bundle_below_subj) != 0)) ? 1 : 0;
816
+ } else {
817
+ throw new IllegalStateException("Unknown op");
818
+ }
817
819
 
818
- /* Update parity */
819
- parity_clip ^= edge.bundle_above[CLIP];
820
- parity_subj ^= edge.bundle_above[SUBJ];
820
+ /* Update parity */
821
+ parity_clip ^= edge.bundle_above[CLIP];
822
+ parity_subj ^= edge.bundle_above[SUBJ];
821
823
 
822
- /* Update horizontal state */
823
- if (exists_clip != 0) {
824
- horiz_clip = HState.next_h_state[horiz_clip][((exists_clip - 1) << 1) + parity_clip];
825
- }
826
- if (exists_subj != 0) {
827
- horiz_subj = HState.next_h_state[horiz_subj][((exists_subj - 1) << 1) + parity_subj];
828
- }
824
+ /* Update horizontal state */
825
+ if (exists_clip != 0) {
826
+ horiz_clip = HState.NEXT_H_STATE[horiz_clip][((exists_clip - 1) << 1) + parity_clip];
827
+ }
828
+ if (exists_subj != 0) {
829
+ horiz_subj = HState.NEXT_H_STATE[horiz_subj][((exists_subj - 1) << 1) + parity_subj];
830
+ }
831
+
832
+ if (contributing) // DIFFERENT!
833
+ {
834
+ float xb = edge.xb;
829
835
 
830
- if (contributing) // DIFFERENT!
831
- {
832
- float xb = edge.xb;
833
-
834
- int vclass = VertexType.getType(tr, tl, br, bl);
835
- switch (vclass) {
836
- case VertexType.EMN:
837
- tlist = new_tristrip(tlist, edge, xb, yb);
838
- cf = edge;
839
- break;
840
- case VertexType.ERI:
841
- edge.outp_above = cf.outp_above;
842
- if (xb != cf.xb) {
843
- VERTEX(edge, ABOVE, RIGHT, xb, yb);
844
- }
845
- cf = null;
846
- break;
847
- case VertexType.ELI:
848
- VERTEX(edge, BELOW, LEFT, xb, yb);
849
- edge.outp_above = null;
850
- cf = edge;
851
- break;
852
- case VertexType.EMX:
853
- if (xb != cf.xb) {
854
- VERTEX(edge, BELOW, RIGHT, xb, yb);
855
- }
856
- edge.outp_above = null;
857
- cf = null;
858
- break;
859
- case VertexType.IMN:
860
- if (cft == VertexType.LED) {
861
- if (cf.bot_y != yb) {
862
- VERTEX(cf, BELOW, LEFT, cf.xb, yb);
863
- }
864
- tlist = new_tristrip(tlist, cf, cf.xb, yb);
865
- }
866
- edge.outp_above = cf.outp_above;
867
- VERTEX(edge, ABOVE, RIGHT, xb, yb);
868
- break;
869
- case VertexType.ILI:
870
- tlist = new_tristrip(tlist, edge, xb, yb);
871
- cf = edge;
872
- cft = VertexType.ILI;
873
- break;
874
- case VertexType.IRI:
875
- if (cft == VertexType.LED) {
876
- if (cf.bot_y != yb) {
877
- VERTEX(cf, BELOW, LEFT, cf.xb, yb);
878
- }
879
- tlist = new_tristrip(tlist, cf, cf.xb, yb);
880
- }
881
- VERTEX(edge, BELOW, RIGHT, xb, yb);
882
- edge.outp_above = null;
883
- break;
884
- case VertexType.IMX:
885
- VERTEX(edge, BELOW, LEFT, xb, yb);
886
- edge.outp_above = null;
887
- cft = VertexType.IMX;
888
- break;
889
- case VertexType.IMM:
890
- VERTEX(edge, BELOW, LEFT, xb, yb);
891
- edge.outp_above = cf.outp_above;
892
- if (xb != cf.xb) {
893
- VERTEX(cf, ABOVE, RIGHT, xb, yb);
894
- }
895
- cf = edge;
896
- break;
897
- case VertexType.EMM:
898
- VERTEX(edge, BELOW, RIGHT, xb, yb);
899
- edge.outp_above = null;
900
- tlist = new_tristrip(tlist, edge, xb, yb);
901
- cf = edge;
902
- break;
903
- case VertexType.LED:
904
- if (edge.bot_y == yb) {
905
- VERTEX(edge, BELOW, LEFT, xb, yb);
906
- }
907
- edge.outp_above = edge.outp_below;
908
- cf = edge;
909
- cft = VertexType.LED;
910
- break;
911
- case VertexType.RED:
912
- edge.outp_above = cf.outp_above;
913
- if (cft == VertexType.LED) {
914
- if (cf.bot_y == yb) {
915
- VERTEX(edge, BELOW, RIGHT, xb, yb);
916
- } else {
917
- if (edge.bot_y == yb) {
918
- VERTEX(cf, BELOW, LEFT, cf.xb, yb);
919
- VERTEX(edge, BELOW, RIGHT, xb, yb);
920
- }
921
- }
922
- } else {
923
- VERTEX(edge, BELOW, RIGHT, xb, yb);
924
- VERTEX(edge, ABOVE, RIGHT, xb, yb);
925
- }
926
- cf = null;
927
- break;
928
- default:
929
- break;
930
- }
931
- /* End of switch */
836
+ int vclass = VertexType.getType(tr, tl, br, bl);
837
+ switch (vclass) {
838
+ case VertexType.EMN:
839
+ tlist = new_tristrip(tlist, edge, xb, yb);
840
+ cf = edge;
841
+ break;
842
+ case VertexType.ERI:
843
+ edge.outp_above = cf.outp_above;
844
+ if (xb != cf.xb) {
845
+ VERTEX(edge, ABOVE, RIGHT, xb, yb);
846
+ }
847
+ cf = null;
848
+ break;
849
+ case VertexType.ELI:
850
+ VERTEX(edge, BELOW, LEFT, xb, yb);
851
+ edge.outp_above = null;
852
+ cf = edge;
853
+ break;
854
+ case VertexType.EMX:
855
+ if (xb != cf.xb) {
856
+ VERTEX(edge, BELOW, RIGHT, xb, yb);
857
+ }
858
+ edge.outp_above = null;
859
+ cf = null;
860
+ break;
861
+ case VertexType.IMN:
862
+ if (cft == VertexType.LED) {
863
+ if (cf.bot_y != yb) {
864
+ VERTEX(cf, BELOW, LEFT, cf.xb, yb);
865
+ }
866
+ tlist = new_tristrip(tlist, cf, cf.xb, yb);
867
+ }
868
+ edge.outp_above = cf.outp_above;
869
+ VERTEX(edge, ABOVE, RIGHT, xb, yb);
870
+ break;
871
+ case VertexType.ILI:
872
+ tlist = new_tristrip(tlist, edge, xb, yb);
873
+ cf = edge;
874
+ cft = VertexType.ILI;
875
+ break;
876
+ case VertexType.IRI:
877
+ if (cft == VertexType.LED) {
878
+ if (cf.bot_y != yb) {
879
+ VERTEX(cf, BELOW, LEFT, cf.xb, yb);
880
+ }
881
+ tlist = new_tristrip(tlist, cf, cf.xb, yb);
882
+ }
883
+ VERTEX(edge, BELOW, RIGHT, xb, yb);
884
+ edge.outp_above = null;
885
+ break;
886
+ case VertexType.IMX:
887
+ VERTEX(edge, BELOW, LEFT, xb, yb);
888
+ edge.outp_above = null;
889
+ cft = VertexType.IMX;
890
+ break;
891
+ case VertexType.IMM:
892
+ VERTEX(edge, BELOW, LEFT, xb, yb);
893
+ edge.outp_above = cf.outp_above;
894
+ if (xb != cf.xb) {
895
+ VERTEX(cf, ABOVE, RIGHT, xb, yb);
896
+ }
897
+ cf = edge;
898
+ break;
899
+ case VertexType.EMM:
900
+ VERTEX(edge, BELOW, RIGHT, xb, yb);
901
+ edge.outp_above = null;
902
+ tlist = new_tristrip(tlist, edge, xb, yb);
903
+ cf = edge;
904
+ break;
905
+ case VertexType.LED:
906
+ if (edge.bot_y == yb) {
907
+ VERTEX(edge, BELOW, LEFT, xb, yb);
908
+ }
909
+ edge.outp_above = edge.outp_below;
910
+ cf = edge;
911
+ cft = VertexType.LED;
912
+ break;
913
+ case VertexType.RED:
914
+ edge.outp_above = cf.outp_above;
915
+ if (cft == VertexType.LED) {
916
+ if (cf.bot_y == yb) {
917
+ VERTEX(edge, BELOW, RIGHT, xb, yb);
918
+ } else {
919
+ if (edge.bot_y == yb) {
920
+ VERTEX(cf, BELOW, LEFT, cf.xb, yb);
921
+ VERTEX(edge, BELOW, RIGHT, xb, yb);
932
922
  }
933
- /* End of contributing conditional */
923
+ }
924
+ } else {
925
+ VERTEX(edge, BELOW, RIGHT, xb, yb);
926
+ VERTEX(edge, ABOVE, RIGHT, xb, yb);
934
927
  }
935
- /* End of edge exists conditional */
928
+ cf = null;
929
+ break;
930
+ default:
931
+ break;
936
932
  }
937
- /* End of AET loop */
933
+ /* End of switch */
934
+ }
935
+ /* End of contributing conditional */
936
+ }
937
+ /* End of edge exists conditional */
938
+ }
939
+ /* End of AET loop */
938
940
 
939
941
  /* Delete terminating edges from the AET, otherwise compute xt */
940
- for (EdgeNode edge = aet.top_node; (edge != null); edge = edge.next) {
941
- if (edge.top_y == yb) {
942
- EdgeNode prev_edge = edge.prev;
943
- EdgeNode next_edge = edge.next;
944
-
945
- if (prev_edge != null) {
946
- prev_edge.next = next_edge;
947
- } else {
948
- aet.top_node = next_edge;
949
- }
942
+ for (EdgeNode edge = aet.top_node; (edge != null); edge = edge.next) {
943
+ if (edge.top_y == yb) {
944
+ EdgeNode prev_edge = edge.prev;
945
+ EdgeNode next_edge = edge.next;
946
+
947
+ if (prev_edge != null) {
948
+ prev_edge.next = next_edge;
949
+ } else {
950
+ aet.top_node = next_edge;
951
+ }
950
952
 
951
- if (next_edge != null) {
952
- next_edge.prev = prev_edge;
953
- }
953
+ if (next_edge != null) {
954
+ next_edge.prev = prev_edge;
955
+ }
954
956
 
955
- /* Copy bundle head state to the adjacent tail edge if required */
956
- if ((edge.bstate_below == BundleState.BUNDLE_HEAD) && (prev_edge != null)) {
957
- if (prev_edge.bstate_below == BundleState.BUNDLE_TAIL) {
958
- prev_edge.outp_below = edge.outp_below;
959
- prev_edge.bstate_below = BundleState.UNBUNDLED;
960
- if (prev_edge.prev != null) {
961
- if (prev_edge.prev.bstate_below == BundleState.BUNDLE_TAIL) {
962
- prev_edge.bstate_below = BundleState.BUNDLE_HEAD;
963
- }
964
- }
965
- }
966
- }
967
- } else {
968
- if (edge.top_y == yt) {
969
- edge.xt = edge.top_x;
970
- } else {
971
- edge.xt = edge.bot_x + edge.dx * (yt - edge.bot_y);
972
- }
957
+ /* Copy bundle head state to the adjacent tail edge if required */
958
+ if ((edge.bstate_below == BundleState.BUNDLE_HEAD) && (prev_edge != null)) {
959
+ if (prev_edge.bstate_below == BundleState.BUNDLE_TAIL) {
960
+ prev_edge.outp_below = edge.outp_below;
961
+ prev_edge.bstate_below = BundleState.UNBUNDLED;
962
+ if (prev_edge.prev != null) {
963
+ if (prev_edge.prev.bstate_below == BundleState.BUNDLE_TAIL) {
964
+ prev_edge.bstate_below = BundleState.BUNDLE_HEAD;
973
965
  }
966
+ }
974
967
  }
968
+ }
969
+ } else {
970
+ if (edge.top_y == yt) {
971
+ edge.xt = edge.top_x;
972
+ } else {
973
+ edge.xt = edge.bot_x + edge.dx * (yt - edge.bot_y);
974
+ }
975
+ }
976
+ }
975
977
 
976
- if (scanbeam < sbte.sbt_entries) {
977
- /* === SCANBEAM INTERIOR PROCESSING ============================== */
978
+ if (scanbeam < sbte.sbt_entries) {
979
+ /* === SCANBEAM INTERIOR PROCESSING ============================== */
978
980
 
979
981
  /* Build intersection table for the current scanbeam */
980
- ItNodeTable it_table = new ItNodeTable();
981
- it_table.build_intersection_table(aet, dy);
982
-
983
- /* Process each node in the intersection table */
984
- for (ItNode intersect = it_table.top_node; (intersect != null); intersect = intersect.next) {
985
- e0 = intersect.ie0;
986
- e1 = intersect.ie1;
987
-
988
- /* Only generate output for contributing intersections */
989
- if (((e0.bundle_above[CLIP] != 0) || (e0.bundle_above[SUBJ] != 0))
990
- && ((e1.bundle_above[CLIP] != 0) || (e1.bundle_above[SUBJ] != 0))) {
991
- PolygonNode p = e0.outp_above;
992
- PolygonNode q = e1.outp_above;
993
- float ix = intersect.point_x;
994
- float iy = intersect.point_y + yb;
995
-
996
- int in_clip = (((e0.bundle_above[CLIP] != 0) && !(e0.bside_clip != 0))
997
- || ((e1.bundle_above[CLIP] != 0) && (e1.bside_clip != 0))
998
- || (!(e0.bundle_above[CLIP] != 0) && !(e1.bundle_above[CLIP] != 0)
999
- && (e0.bside_clip != 0) && (e1.bside_clip != 0))) ? 1 : 0;
1000
-
1001
- int in_subj = (((e0.bundle_above[SUBJ] != 0) && !(e0.bside_subj != 0))
1002
- || ((e1.bundle_above[SUBJ] != 0) && (e1.bside_subj != 0))
1003
- || (!(e0.bundle_above[SUBJ] != 0) && !(e1.bundle_above[SUBJ] != 0)
1004
- && (e0.bside_subj != 0) && (e1.bside_subj != 0))) ? 1 : 0;
1005
-
1006
- int tr = 0, tl = 0, br = 0, bl = 0;
1007
- /* Determine quadrant occupancies */
1008
- if ((op == OperationType.GPC_DIFF) || (op == OperationType.GPC_INT)) {
1009
- tr = ((in_clip != 0) && (in_subj != 0)) ? 1 : 0;
1010
- tl = (((in_clip ^ e1.bundle_above[CLIP]) != 0) && ((in_subj ^ e1.bundle_above[SUBJ]) != 0)) ? 1 : 0;
1011
- br = (((in_clip ^ e0.bundle_above[CLIP]) != 0) && ((in_subj ^ e0.bundle_above[SUBJ]) != 0)) ? 1 : 0;
1012
- bl = (((in_clip ^ e1.bundle_above[CLIP] ^ e0.bundle_above[CLIP]) != 0)
1013
- && ((in_subj ^ e1.bundle_above[SUBJ] ^ e0.bundle_above[SUBJ]) != 0)) ? 1 : 0;
1014
- } else if (op == OperationType.GPC_XOR) {
1015
- tr = (in_clip) ^ (in_subj);
1016
- tl = (in_clip ^ e1.bundle_above[CLIP]) ^ (in_subj ^ e1.bundle_above[SUBJ]);
1017
- br = (in_clip ^ e0.bundle_above[CLIP]) ^ (in_subj ^ e0.bundle_above[SUBJ]);
1018
- bl = (in_clip ^ e1.bundle_above[CLIP] ^ e0.bundle_above[CLIP])
1019
- ^ (in_subj ^ e1.bundle_above[SUBJ] ^ e0.bundle_above[SUBJ]);
1020
- } else if (op == OperationType.GPC_UNION) {
1021
- tr = ((in_clip != 0) || (in_subj != 0)) ? 1 : 0;
1022
- tl = (((in_clip ^ e1.bundle_above[CLIP]) != 0) || ((in_subj ^ e1.bundle_above[SUBJ]) != 0)) ? 1 : 0;
1023
- br = (((in_clip ^ e0.bundle_above[CLIP]) != 0) || ((in_subj ^ e0.bundle_above[SUBJ]) != 0)) ? 1 : 0;
1024
- bl = (((in_clip ^ e1.bundle_above[CLIP] ^ e0.bundle_above[CLIP]) != 0)
1025
- || ((in_subj ^ e1.bundle_above[SUBJ] ^ e0.bundle_above[SUBJ]) != 0)) ? 1 : 0;
1026
- } else {
1027
- throw new IllegalStateException("Unknown op type, " + op);
1028
- }
1029
-
1030
- EdgeNode next_edge = e1.next;
1031
- EdgeNode prev_edge = e0.prev;
1032
-
1033
- int vclass = VertexType.getType(tr, tl, br, bl);
1034
- switch (vclass) {
1035
- case VertexType.EMN:
1036
- tlist = new_tristrip(tlist, e1, ix, iy);
1037
- e1.outp_above = e0.outp_above;
1038
- break;
1039
- case VertexType.ERI:
1040
- if (p != null) {
1041
- px = P_EDGE(prev_edge, e0, ABOVE, px, iy);
1042
- VERTEX(prev_edge, ABOVE, LEFT, px, iy);
1043
- VERTEX(e0, ABOVE, RIGHT, ix, iy);
1044
- e1.outp_above = e0.outp_above;
1045
- e0.outp_above = null;
1046
- }
1047
- break;
1048
- case VertexType.ELI:
1049
- if (q != null) {
1050
- nx = N_EDGE(next_edge, e1, ABOVE, nx, iy);
1051
- VERTEX(e1, ABOVE, LEFT, ix, iy);
1052
- VERTEX(next_edge, ABOVE, RIGHT, nx, iy);
1053
- e0.outp_above = e1.outp_above;
1054
- e1.outp_above = null;
1055
- }
1056
- break;
1057
- case VertexType.EMX:
1058
- if ((p != null) && (q != null)) {
1059
- VERTEX(e0, ABOVE, LEFT, ix, iy);
1060
- e0.outp_above = null;
1061
- e1.outp_above = null;
1062
- }
1063
- break;
1064
- case VertexType.IMN:
1065
- px = P_EDGE(prev_edge, e0, ABOVE, px, iy);
1066
- VERTEX(prev_edge, ABOVE, LEFT, px, iy);
1067
- nx = N_EDGE(next_edge, e1, ABOVE, nx, iy);
1068
- VERTEX(next_edge, ABOVE, RIGHT, nx, iy);
1069
- tlist = new_tristrip(tlist, prev_edge, px, iy);
1070
- e1.outp_above = prev_edge.outp_above;
1071
- VERTEX(e1, ABOVE, RIGHT, ix, iy);
1072
- tlist = new_tristrip(tlist, e0, ix, iy);
1073
- next_edge.outp_above = e0.outp_above;
1074
- VERTEX(next_edge, ABOVE, RIGHT, nx, iy);
1075
- break;
1076
- case VertexType.ILI:
1077
- if (p != null) {
1078
- VERTEX(e0, ABOVE, LEFT, ix, iy);
1079
- nx = N_EDGE(next_edge, e1, ABOVE, nx, iy);
1080
- VERTEX(next_edge, ABOVE, RIGHT, nx, iy);
1081
- e1.outp_above = e0.outp_above;
1082
- e0.outp_above = null;
1083
- }
1084
- break;
1085
- case VertexType.IRI:
1086
- if (q != null) {
1087
- VERTEX(e1, ABOVE, RIGHT, ix, iy);
1088
- px = P_EDGE(prev_edge, e0, ABOVE, px, iy);
1089
- VERTEX(prev_edge, ABOVE, LEFT, px, iy);
1090
- e0.outp_above = e1.outp_above;
1091
- e1.outp_above = null;
1092
- }
1093
- break;
1094
- case VertexType.IMX:
1095
- if ((p != null) && (q != null)) {
1096
- VERTEX(e0, ABOVE, RIGHT, ix, iy);
1097
- VERTEX(e1, ABOVE, LEFT, ix, iy);
1098
- e0.outp_above = null;
1099
- e1.outp_above = null;
1100
- px = P_EDGE(prev_edge, e0, ABOVE, px, iy);
1101
- VERTEX(prev_edge, ABOVE, LEFT, px, iy);
1102
- tlist = new_tristrip(tlist, prev_edge, px, iy);
1103
- nx = N_EDGE(next_edge, e1, ABOVE, nx, iy);
1104
- VERTEX(next_edge, ABOVE, RIGHT, nx, iy);
1105
- next_edge.outp_above = prev_edge.outp_above;
1106
- VERTEX(next_edge, ABOVE, RIGHT, nx, iy);
1107
- }
1108
- break;
1109
- case VertexType.IMM:
1110
- if ((p != null) && (q != null)) {
1111
- VERTEX(e0, ABOVE, RIGHT, ix, iy);
1112
- VERTEX(e1, ABOVE, LEFT, ix, iy);
1113
- px = P_EDGE(prev_edge, e0, ABOVE, px, iy);
1114
- VERTEX(prev_edge, ABOVE, LEFT, px, iy);
1115
- tlist = new_tristrip(tlist, prev_edge, px, iy);
1116
- nx = N_EDGE(next_edge, e1, ABOVE, nx, iy);
1117
- VERTEX(next_edge, ABOVE, RIGHT, nx, iy);
1118
- e1.outp_above = prev_edge.outp_above;
1119
- VERTEX(e1, ABOVE, RIGHT, ix, iy);
1120
- tlist = new_tristrip(tlist, e0, ix, iy);
1121
- next_edge.outp_above = e0.outp_above;
1122
- VERTEX(next_edge, ABOVE, RIGHT, nx, iy);
1123
- }
1124
- break;
1125
- case VertexType.EMM:
1126
- if ((p != null) && (q != null)) {
1127
- VERTEX(e0, ABOVE, LEFT, ix, iy);
1128
- tlist = new_tristrip(tlist, e1, ix, iy);
1129
- e1.outp_above = e0.outp_above;
1130
- }
1131
- break;
1132
- default:
1133
- break;
1134
- }
1135
- /* End of switch */
1136
- }
1137
- /* End of contributing intersection conditional */
982
+ ItNodeTable it_table = new ItNodeTable();
983
+ it_table.build_intersection_table(aet, dy);
984
+
985
+ /* Process each node in the intersection table */
986
+ for (ItNode intersect = it_table.top_node; (intersect != null); intersect = intersect.next) {
987
+ e0 = intersect.ie0;
988
+ e1 = intersect.ie1;
989
+
990
+ /* Only generate output for contributing intersections */
991
+ if (((e0.bundle_above[CLIP] != 0) || (e0.bundle_above[SUBJ] != 0))
992
+ && ((e1.bundle_above[CLIP] != 0) || (e1.bundle_above[SUBJ] != 0))) {
993
+ PolygonNode p = e0.outp_above;
994
+ PolygonNode q = e1.outp_above;
995
+ float ix = intersect.point_x;
996
+ float iy = intersect.point_y + yb;
997
+
998
+ int in_clip = (((e0.bundle_above[CLIP] != 0) && !(e0.bside_clip != 0))
999
+ || ((e1.bundle_above[CLIP] != 0) && (e1.bside_clip != 0))
1000
+ || (!(e0.bundle_above[CLIP] != 0) && !(e1.bundle_above[CLIP] != 0)
1001
+ && (e0.bside_clip != 0) && (e1.bside_clip != 0))) ? 1 : 0;
1002
+
1003
+ int in_subj = (((e0.bundle_above[SUBJ] != 0) && !(e0.bside_subj != 0))
1004
+ || ((e1.bundle_above[SUBJ] != 0) && (e1.bside_subj != 0))
1005
+ || (!(e0.bundle_above[SUBJ] != 0) && !(e1.bundle_above[SUBJ] != 0)
1006
+ && (e0.bside_subj != 0) && (e1.bside_subj != 0))) ? 1 : 0;
1007
+
1008
+ int tr = 0, tl = 0, br = 0, bl = 0;
1009
+ /* Determine quadrant occupancies */
1010
+ if ((op == OperationType.GPC_DIFF) || (op == OperationType.GPC_INT)) {
1011
+ tr = ((in_clip != 0) && (in_subj != 0)) ? 1 : 0;
1012
+ tl = (((in_clip ^ e1.bundle_above[CLIP]) != 0) && ((in_subj ^ e1.bundle_above[SUBJ]) != 0)) ? 1 : 0;
1013
+ br = (((in_clip ^ e0.bundle_above[CLIP]) != 0) && ((in_subj ^ e0.bundle_above[SUBJ]) != 0)) ? 1 : 0;
1014
+ bl = (((in_clip ^ e1.bundle_above[CLIP] ^ e0.bundle_above[CLIP]) != 0)
1015
+ && ((in_subj ^ e1.bundle_above[SUBJ] ^ e0.bundle_above[SUBJ]) != 0)) ? 1 : 0;
1016
+ } else if (op == OperationType.GPC_XOR) {
1017
+ tr = (in_clip) ^ (in_subj);
1018
+ tl = (in_clip ^ e1.bundle_above[CLIP]) ^ (in_subj ^ e1.bundle_above[SUBJ]);
1019
+ br = (in_clip ^ e0.bundle_above[CLIP]) ^ (in_subj ^ e0.bundle_above[SUBJ]);
1020
+ bl = (in_clip ^ e1.bundle_above[CLIP] ^ e0.bundle_above[CLIP])
1021
+ ^ (in_subj ^ e1.bundle_above[SUBJ] ^ e0.bundle_above[SUBJ]);
1022
+ } else if (op == OperationType.GPC_UNION) {
1023
+ tr = ((in_clip != 0) || (in_subj != 0)) ? 1 : 0;
1024
+ tl = (((in_clip ^ e1.bundle_above[CLIP]) != 0) || ((in_subj ^ e1.bundle_above[SUBJ]) != 0)) ? 1 : 0;
1025
+ br = (((in_clip ^ e0.bundle_above[CLIP]) != 0) || ((in_subj ^ e0.bundle_above[SUBJ]) != 0)) ? 1 : 0;
1026
+ bl = (((in_clip ^ e1.bundle_above[CLIP] ^ e0.bundle_above[CLIP]) != 0)
1027
+ || ((in_subj ^ e1.bundle_above[SUBJ] ^ e0.bundle_above[SUBJ]) != 0)) ? 1 : 0;
1028
+ } else {
1029
+ throw new IllegalStateException("Unknown op type, " + op);
1030
+ }
1031
+
1032
+ EdgeNode next_edge = e1.next;
1033
+ EdgeNode prev_edge = e0.prev;
1034
+
1035
+ int vclass = VertexType.getType(tr, tl, br, bl);
1036
+ switch (vclass) {
1037
+ case VertexType.EMN:
1038
+ tlist = new_tristrip(tlist, e1, ix, iy);
1039
+ e1.outp_above = e0.outp_above;
1040
+ break;
1041
+ case VertexType.ERI:
1042
+ if (p != null) {
1043
+ px = P_EDGE(prev_edge, e0, ABOVE, px, iy);
1044
+ VERTEX(prev_edge, ABOVE, LEFT, px, iy);
1045
+ VERTEX(e0, ABOVE, RIGHT, ix, iy);
1046
+ e1.outp_above = e0.outp_above;
1047
+ e0.outp_above = null;
1048
+ }
1049
+ break;
1050
+ case VertexType.ELI:
1051
+ if (q != null) {
1052
+ nx = N_EDGE(next_edge, e1, ABOVE, nx, iy);
1053
+ VERTEX(e1, ABOVE, LEFT, ix, iy);
1054
+ VERTEX(next_edge, ABOVE, RIGHT, nx, iy);
1055
+ e0.outp_above = e1.outp_above;
1056
+ e1.outp_above = null;
1057
+ }
1058
+ break;
1059
+ case VertexType.EMX:
1060
+ if ((p != null) && (q != null)) {
1061
+ VERTEX(e0, ABOVE, LEFT, ix, iy);
1062
+ e0.outp_above = null;
1063
+ e1.outp_above = null;
1064
+ }
1065
+ break;
1066
+ case VertexType.IMN:
1067
+ px = P_EDGE(prev_edge, e0, ABOVE, px, iy);
1068
+ VERTEX(prev_edge, ABOVE, LEFT, px, iy);
1069
+ nx = N_EDGE(next_edge, e1, ABOVE, nx, iy);
1070
+ VERTEX(next_edge, ABOVE, RIGHT, nx, iy);
1071
+ tlist = new_tristrip(tlist, prev_edge, px, iy);
1072
+ e1.outp_above = prev_edge.outp_above;
1073
+ VERTEX(e1, ABOVE, RIGHT, ix, iy);
1074
+ tlist = new_tristrip(tlist, e0, ix, iy);
1075
+ next_edge.outp_above = e0.outp_above;
1076
+ VERTEX(next_edge, ABOVE, RIGHT, nx, iy);
1077
+ break;
1078
+ case VertexType.ILI:
1079
+ if (p != null) {
1080
+ VERTEX(e0, ABOVE, LEFT, ix, iy);
1081
+ nx = N_EDGE(next_edge, e1, ABOVE, nx, iy);
1082
+ VERTEX(next_edge, ABOVE, RIGHT, nx, iy);
1083
+ e1.outp_above = e0.outp_above;
1084
+ e0.outp_above = null;
1085
+ }
1086
+ break;
1087
+ case VertexType.IRI:
1088
+ if (q != null) {
1089
+ VERTEX(e1, ABOVE, RIGHT, ix, iy);
1090
+ px = P_EDGE(prev_edge, e0, ABOVE, px, iy);
1091
+ VERTEX(prev_edge, ABOVE, LEFT, px, iy);
1092
+ e0.outp_above = e1.outp_above;
1093
+ e1.outp_above = null;
1094
+ }
1095
+ break;
1096
+ case VertexType.IMX:
1097
+ if ((p != null) && (q != null)) {
1098
+ VERTEX(e0, ABOVE, RIGHT, ix, iy);
1099
+ VERTEX(e1, ABOVE, LEFT, ix, iy);
1100
+ e0.outp_above = null;
1101
+ e1.outp_above = null;
1102
+ px = P_EDGE(prev_edge, e0, ABOVE, px, iy);
1103
+ VERTEX(prev_edge, ABOVE, LEFT, px, iy);
1104
+ tlist = new_tristrip(tlist, prev_edge, px, iy);
1105
+ nx = N_EDGE(next_edge, e1, ABOVE, nx, iy);
1106
+ VERTEX(next_edge, ABOVE, RIGHT, nx, iy);
1107
+ next_edge.outp_above = prev_edge.outp_above;
1108
+ VERTEX(next_edge, ABOVE, RIGHT, nx, iy);
1109
+ }
1110
+ break;
1111
+ case VertexType.IMM:
1112
+ if ((p != null) && (q != null)) {
1113
+ VERTEX(e0, ABOVE, RIGHT, ix, iy);
1114
+ VERTEX(e1, ABOVE, LEFT, ix, iy);
1115
+ px = P_EDGE(prev_edge, e0, ABOVE, px, iy);
1116
+ VERTEX(prev_edge, ABOVE, LEFT, px, iy);
1117
+ tlist = new_tristrip(tlist, prev_edge, px, iy);
1118
+ nx = N_EDGE(next_edge, e1, ABOVE, nx, iy);
1119
+ VERTEX(next_edge, ABOVE, RIGHT, nx, iy);
1120
+ e1.outp_above = prev_edge.outp_above;
1121
+ VERTEX(e1, ABOVE, RIGHT, ix, iy);
1122
+ tlist = new_tristrip(tlist, e0, ix, iy);
1123
+ next_edge.outp_above = e0.outp_above;
1124
+ VERTEX(next_edge, ABOVE, RIGHT, nx, iy);
1125
+ }
1126
+ break;
1127
+ case VertexType.EMM:
1128
+ if ((p != null) && (q != null)) {
1129
+ VERTEX(e0, ABOVE, LEFT, ix, iy);
1130
+ tlist = new_tristrip(tlist, e1, ix, iy);
1131
+ e1.outp_above = e0.outp_above;
1132
+ }
1133
+ break;
1134
+ default:
1135
+ break;
1136
+ }
1137
+ /* End of switch */
1138
+ }
1139
+ /* End of contributing intersection conditional */
1138
1140
 
1139
1141
  /* Swap bundle sides in response to edge crossing */
1140
- if (e0.bundle_above[CLIP] != 0) {
1141
- e1.bside_clip = (e1.bside_clip == 0) ? 1 : 0;
1142
- }
1143
- if (e1.bundle_above[CLIP] != 0) {
1144
- e0.bside_clip = (e0.bside_clip == 0) ? 1 : 0;
1145
- }
1146
- if (e0.bundle_above[SUBJ] != 0) {
1147
- e1.bside_subj = (e1.bside_subj == 0) ? 1 : 0;
1148
- }
1149
- if (e1.bundle_above[SUBJ] != 0) {
1150
- e0.bside_subj = (e0.bside_subj == 0) ? 1 : 0;
1151
- }
1142
+ if (e0.bundle_above[CLIP] != 0) {
1143
+ e1.bside_clip = (e1.bside_clip == 0) ? 1 : 0;
1144
+ }
1145
+ if (e1.bundle_above[CLIP] != 0) {
1146
+ e0.bside_clip = (e0.bside_clip == 0) ? 1 : 0;
1147
+ }
1148
+ if (e0.bundle_above[SUBJ] != 0) {
1149
+ e1.bside_subj = (e1.bside_subj == 0) ? 1 : 0;
1150
+ }
1151
+ if (e1.bundle_above[SUBJ] != 0) {
1152
+ e0.bside_subj = (e0.bside_subj == 0) ? 1 : 0;
1153
+ }
1152
1154
 
1153
- /* Swap e0 and e1 bundles in the AET */
1154
- EdgeNode prev_edge = e0.prev;
1155
- EdgeNode next_edge = e1.next;
1156
- if (next_edge != null) {
1157
- next_edge.prev = e0;
1158
- }
1155
+ /* Swap e0 and e1 bundles in the AET */
1156
+ EdgeNode prev_edge = e0.prev;
1157
+ EdgeNode next_edge = e1.next;
1158
+ if (next_edge != null) {
1159
+ next_edge.prev = e0;
1160
+ }
1159
1161
 
1160
- if (e0.bstate_above == BundleState.BUNDLE_HEAD) {
1161
- boolean search = true;
1162
- while (search) {
1163
- prev_edge = prev_edge.prev;
1164
- if (prev_edge != null) {
1165
- if (prev_edge.bundle_above[CLIP] != 0
1166
- || prev_edge.bundle_above[SUBJ] != 0
1167
- || (prev_edge.bstate_above == BundleState.BUNDLE_HEAD)) {
1168
- search = false;
1169
- }
1170
- } else {
1171
- search = false;
1172
- }
1173
- }
1174
- }
1175
- if (prev_edge == null) {
1176
- e1.next = aet.top_node;
1177
- aet.top_node = e0.next;
1178
- } else {
1179
- e1.next = prev_edge.next;
1180
- prev_edge.next = e0.next;
1181
- }
1182
- e0.next.prev = prev_edge;
1183
- e1.next.prev = e1;
1184
- e0.next = next_edge;
1162
+ if (e0.bstate_above == BundleState.BUNDLE_HEAD) {
1163
+ boolean search = true;
1164
+ while (search) {
1165
+ prev_edge = prev_edge.prev;
1166
+ if (prev_edge != null) {
1167
+ if (prev_edge.bundle_above[CLIP] != 0
1168
+ || prev_edge.bundle_above[SUBJ] != 0
1169
+ || (prev_edge.bstate_above == BundleState.BUNDLE_HEAD)) {
1170
+ search = false;
1185
1171
  }
1186
- /* End of IT loop*/
1172
+ } else {
1173
+ search = false;
1174
+ }
1175
+ }
1176
+ }
1177
+ if (prev_edge == null) {
1178
+ e1.next = aet.top_node;
1179
+ aet.top_node = e0.next;
1180
+ } else {
1181
+ e1.next = prev_edge.next;
1182
+ prev_edge.next = e0.next;
1183
+ }
1184
+ e0.next.prev = prev_edge;
1185
+ e1.next.prev = e1;
1186
+ e0.next = next_edge;
1187
+ }
1188
+ /* End of IT loop*/
1187
1189
 
1188
1190
  /* Prepare for next scanbeam */
1189
- for (EdgeNode edge = aet.top_node; (edge != null); edge = edge.next) {
1190
- EdgeNode next_edge = edge.next;
1191
- EdgeNode succ_edge = edge.succ;
1192
- if ((edge.top_y == yt) && (succ_edge != null)) {
1193
- /* Replace AET edge by its successor */
1194
- succ_edge.outp_below = edge.outp_above;
1195
- succ_edge.bstate_below = edge.bstate_above;
1196
- succ_edge.bundle_below_clip = edge.bundle_above[CLIP];
1197
- succ_edge.bundle_below_subj = edge.bundle_above[SUBJ];
1198
- EdgeNode prev_edge = edge.prev;
1199
- if (prev_edge != null) {
1200
- prev_edge.next = succ_edge;
1201
- } else {
1202
- aet.top_node = succ_edge;
1203
- }
1204
- if (next_edge != null) {
1205
- next_edge.prev = succ_edge;
1206
- }
1207
- succ_edge.prev = prev_edge;
1208
- succ_edge.next = next_edge;
1209
- } else {
1210
- /* Update this edge */
1211
- edge.outp_below = edge.outp_above;
1212
- edge.bstate_below = edge.bstate_above;
1213
- edge.bundle_below_clip = edge.bundle_above[CLIP];
1214
- edge.bundle_below_subj = edge.bundle_above[SUBJ];
1215
- edge.xb = edge.xt;
1216
- }
1217
- edge.outp_above = null;
1218
- }
1191
+ for (EdgeNode edge = aet.top_node; (edge != null); edge = edge.next) {
1192
+ EdgeNode next_edge = edge.next;
1193
+ EdgeNode succ_edge = edge.succ;
1194
+ if ((edge.top_y == yt) && (succ_edge != null)) {
1195
+ /* Replace AET edge by its successor */
1196
+ succ_edge.outp_below = edge.outp_above;
1197
+ succ_edge.bstate_below = edge.bstate_above;
1198
+ succ_edge.bundle_below_clip = edge.bundle_above[CLIP];
1199
+ succ_edge.bundle_below_subj = edge.bundle_above[SUBJ];
1200
+ EdgeNode prev_edge = edge.prev;
1201
+ if (prev_edge != null) {
1202
+ prev_edge.next = succ_edge;
1203
+ } else {
1204
+ aet.top_node = succ_edge;
1219
1205
  }
1206
+ if (next_edge != null) {
1207
+ next_edge.prev = succ_edge;
1208
+ }
1209
+ succ_edge.prev = prev_edge;
1210
+ succ_edge.next = next_edge;
1211
+ } else {
1212
+ /* Update this edge */
1213
+ edge.outp_below = edge.outp_above;
1214
+ edge.bstate_below = edge.bstate_above;
1215
+ edge.bundle_below_clip = edge.bundle_above[CLIP];
1216
+ edge.bundle_below_subj = edge.bundle_above[SUBJ];
1217
+ edge.xb = edge.xt;
1218
+ }
1219
+ edge.outp_above = null;
1220
1220
  }
1221
- /* === END OF SCANBEAM PROCESSING ================================== */
1221
+ }
1222
+ }
1223
+ /* === END OF SCANBEAM PROCESSING ================================== */
1222
1224
 
1223
1225
  /* Generate result tristrip from tlist */
1224
- VertexNode lt, ltn, rt, rtn;
1225
- PolygonNode tnn, tn;
1226
- RMesh result = new RMesh();
1227
- if (count_tristrips(tlist) > 0) {
1228
- int s, v;
1229
-
1230
- s = 0;
1231
- for (tn = tlist; tn != null; tn = tnn) {
1232
- tnn = tn.next;
1233
-
1234
- if (tn.active > 2) {
1235
- /* Valid tristrip: copy the vertices and free the heap */
1236
- RStrip strip = new RStrip();
1237
- v = 0;
1238
- if (INVERT_TRISTRIPS == true) {
1239
- lt = tn.v_right;
1240
- rt = tn.v_left;
1241
- } else {
1242
- lt = tn.v_left;
1243
- rt = tn.v_right;
1244
- }
1245
- while (lt != null || rt != null) {
1246
- if (lt != null) {
1247
- ltn = lt.next;
1248
- strip.add(lt.x, lt.y);
1249
- v++;
1250
- lt = ltn;
1251
- }
1252
- if (rt != null) {
1253
- rtn = rt.next;
1254
- strip.add(rt.x, rt.y);
1255
- v++;
1256
- rt = rtn;
1257
- }
1258
- }
1259
- result.addStrip(strip);
1260
- s++;
1261
- } else {
1262
- /* Invalid tristrip: just free the heap */
1263
- for (lt = tn.v_left; lt != null; lt = ltn) {
1264
- ltn = lt.next;
1265
- }
1266
- for (rt = tn.v_right; rt != null; rt = rtn) {
1267
- rtn = rt.next;
1268
- }
1269
- }
1226
+ VertexNode lt, ltn, rt, rtn;
1227
+ PolygonNode tnn, tn;
1228
+ RMesh result = new RMesh();
1229
+ if (count_tristrips(tlist) > 0) {
1230
+ int s, v;
1231
+
1232
+ s = 0;
1233
+ for (tn = tlist; tn != null; tn = tnn) {
1234
+ tnn = tn.next;
1235
+
1236
+ if (tn.active > 2) {
1237
+ /* Valid tristrip: copy the vertices and free the heap */
1238
+ RStrip strip = new RStrip();
1239
+ v = 0;
1240
+ if (INVERT_TRISTRIPS == true) {
1241
+ lt = tn.v_right;
1242
+ rt = tn.v_left;
1243
+ } else {
1244
+ lt = tn.v_left;
1245
+ rt = tn.v_right;
1246
+ }
1247
+ while (lt != null || rt != null) {
1248
+ if (lt != null) {
1249
+ ltn = lt.next;
1250
+ strip.add(lt.x, lt.y);
1251
+ v++;
1252
+ lt = ltn;
1253
+ }
1254
+ if (rt != null) {
1255
+ rtn = rt.next;
1256
+ strip.add(rt.x, rt.y);
1257
+ v++;
1258
+ rt = rtn;
1270
1259
  }
1260
+ }
1261
+ result.addStrip(strip);
1262
+ s++;
1263
+ } else {
1264
+ /* Invalid tristrip: just free the heap */
1265
+ for (lt = tn.v_left; lt != null; lt = ltn) {
1266
+ ltn = lt.next;
1267
+ }
1268
+ for (rt = tn.v_right; rt != null; rt = rtn) {
1269
+ rtn = rt.next;
1270
+ }
1271
1271
  }
1272
- return result;
1272
+ }
1273
1273
  }
1274
+ return result;
1275
+ }
1274
1276
 
1275
- public static RMesh polygonToMesh(RPolygon s) {
1276
- RPolygon c = new RPolygon();
1277
- RPolygon s_clean = s.removeOpenContours();
1278
- /*
1277
+ public static RMesh polygonToMesh(RPolygon s) {
1278
+ RPolygon c = new RPolygon();
1279
+ RPolygon s_clean = s.removeOpenContours();
1280
+ /*
1279
1281
  for(int i=0; i<s_clean.countContours(); i++)
1280
1282
  {
1281
1283
  System.out.println(" " + s_clean.contours[i]);
@@ -1285,1154 +1287,1145 @@ class FastRClip {
1285
1287
  System.out.println(" Point " + (j + 1) + "/" + s_clean.contours[i].countPoints() + ":" + "(" + s_clean.contours[i].points[j].x + ", " + s_clean.contours[i].points[j].y + ")");
1286
1288
  }
1287
1289
  }
1288
- */
1289
- return clip(OperationType.GPC_UNION, s_clean, c);
1290
- }
1291
-
1292
- private static boolean EQ(float a, float b) {
1293
- return (Math.abs(a - b) <= GPC_EPSILON);
1290
+ */
1291
+ return clip(OperationType.GPC_UNION, s_clean, c);
1292
+ }
1293
+
1294
+ private static boolean EQ(float a, float b) {
1295
+ return (Math.abs(a - b) <= GPC_EPSILON);
1296
+ }
1297
+
1298
+ private static int PREV_INDEX(int i, int n) {
1299
+ return ((i - 1 + n) % n);
1300
+ }
1301
+
1302
+ private static int NEXT_INDEX(int i, int n) {
1303
+ return ((i + 1) % n);
1304
+ }
1305
+
1306
+ private static boolean OPTIMAL(RPolygon p, int i) {
1307
+ return (p.getY(PREV_INDEX(i, p.getNumPoints())) != p.getY(i))
1308
+ || (p.getY(NEXT_INDEX(i, p.getNumPoints())) != p.getY(i));
1309
+ }
1310
+
1311
+ // TODO: demacro-ize this
1312
+ private static void VERTEX(EdgeNode e, int p, int s, float x, float y) {
1313
+ switch (p) {
1314
+ case ABOVE:
1315
+ switch (s) {
1316
+ case RIGHT:
1317
+ e.outp_above.v_right = add_vertex(e.outp_above.v_right, x, y);
1318
+ break;
1319
+ case LEFT:
1320
+ e.outp_above.v_left = add_vertex(e.outp_above.v_left, x, y);
1321
+ break;
1322
+ default:
1323
+ throw new IllegalStateException("bogus s value");
1324
+ }
1325
+ e.outp_above.active++;
1326
+ break;
1327
+ case BELOW:
1328
+ switch (s) {
1329
+ case RIGHT:
1330
+ e.outp_below.v_right = add_vertex(e.outp_below.v_right, x, y);
1331
+ break;
1332
+ case LEFT:
1333
+ e.outp_below.v_left = add_vertex(e.outp_below.v_left, x, y);
1334
+ break;
1335
+ default:
1336
+ throw new IllegalStateException("bogus s value");
1337
+ }
1338
+ e.outp_below.active++;
1339
+ break;
1340
+ default:
1341
+ throw new IllegalStateException("bogus p value");
1294
1342
  }
1295
-
1296
- private static int PREV_INDEX(int i, int n) {
1297
- return ((i - 1 + n) % n);
1343
+ }
1344
+
1345
+ private static float P_EDGE(EdgeNode d, EdgeNode e, int p, float i, float j) {
1346
+ switch (p) {
1347
+ case ABOVE:
1348
+ d = e;
1349
+ do {
1350
+ d = d.prev;
1351
+ } while (d.outp_above == null);
1352
+ return d.bot_x + d.dx * (j - d.bot_y);
1353
+ case BELOW:
1354
+ d = e;
1355
+ do {
1356
+ d = d.prev;
1357
+ } while (d.outp_below == null);
1358
+ return d.bot_x + d.dx * (j - d.bot_y);
1359
+ default:
1360
+ throw new IllegalStateException("bogus p value");
1298
1361
  }
1299
-
1300
- private static int NEXT_INDEX(int i, int n) {
1301
- return ((i + 1) % n);
1362
+ }
1363
+
1364
+ private static float N_EDGE(EdgeNode d, EdgeNode e, int p, float i, float j) {
1365
+ switch (p) {
1366
+ case ABOVE:
1367
+ d = e;
1368
+ do {
1369
+ d = d.next;
1370
+ } while (d.outp_above == null);
1371
+ return d.bot_x + d.dx * (j - d.bot_y);
1372
+ case BELOW:
1373
+ d = e;
1374
+ do {
1375
+ d = d.next;
1376
+ } while (d.outp_below == null);
1377
+ return d.bot_x + d.dx * (j - d.bot_y);
1378
+ default:
1379
+ throw new IllegalStateException("bogus p value");
1302
1380
  }
1381
+ }
1303
1382
 
1304
- private static boolean OPTIMAL(RPolygon p, int i) {
1305
- return (p.getY(PREV_INDEX(i, p.getNumPoints())) != p.getY(i))
1306
- || (p.getY(NEXT_INDEX(i, p.getNumPoints())) != p.getY(i));
1307
- }
1383
+ private static RRectangle[] create_contour_bboxes(RPolygon p) {
1384
+ RRectangle[] box = new RRectangle[p.getNumInnerPoly()];
1308
1385
 
1309
- // TODO: demacro-ize this
1310
- private static void VERTEX(EdgeNode e, int p, int s, float x, float y) {
1311
- switch (p) {
1312
- case ABOVE:
1313
- switch (s) {
1314
- case RIGHT:
1315
- e.outp_above.v_right = add_vertex(e.outp_above.v_right, x, y);
1316
- break;
1317
- case LEFT:
1318
- e.outp_above.v_left = add_vertex(e.outp_above.v_left, x, y);
1319
- break;
1320
- default:
1321
- throw new IllegalStateException("bogus s value");
1322
- }
1323
- e.outp_above.active++;
1324
- break;
1325
- case BELOW:
1326
- switch (s) {
1327
- case RIGHT:
1328
- e.outp_below.v_right = add_vertex(e.outp_below.v_right, x, y);
1329
- break;
1330
- case LEFT:
1331
- e.outp_below.v_left = add_vertex(e.outp_below.v_left, x, y);
1332
- break;
1333
- default:
1334
- throw new IllegalStateException("bogus s value");
1335
- }
1336
- e.outp_below.active++;
1337
- break;
1338
- default:
1339
- throw new IllegalStateException("bogus p value");
1340
- }
1386
+ /* Construct contour bounding boxes */
1387
+ for (int c = 0; c < p.getNumInnerPoly(); c++) {
1388
+ RPolygon inner_poly = p.getInnerPoly(c);
1389
+ box[c] = inner_poly.getBBox();
1341
1390
  }
1342
-
1343
- private static float P_EDGE(EdgeNode d, EdgeNode e, int p, float i, float j) {
1344
- if (p == ABOVE) {
1345
-
1346
- d = e;
1347
- do {
1348
- d = d.prev;
1349
- } while (d.outp_above == null);
1350
- return d.bot_x + d.dx * (j - d.bot_y);
1351
-
1352
- } else if (p == BELOW) {
1353
-
1354
- d = e;
1355
- do {
1356
- d = d.prev;
1357
- } while (d.outp_below == null);
1358
- return d.bot_x + d.dx * (j - d.bot_y);
1359
-
1360
- } else {
1361
- throw new IllegalStateException("bogus p value");
1362
- }
1391
+ return box;
1392
+ }
1393
+
1394
+ private static void minimax_test(RPolygon subj, RPolygon clip, OperationType op) {
1395
+ RRectangle[] s_bbox = create_contour_bboxes(subj);
1396
+ RRectangle[] c_bbox = create_contour_bboxes(clip);
1397
+
1398
+ int subj_num_poly = subj.getNumInnerPoly();
1399
+ int clip_num_poly = clip.getNumInnerPoly();
1400
+ boolean[][] o_table = new boolean[subj_num_poly][clip_num_poly];
1401
+
1402
+ /* Check all subject contour bounding boxes against clip boxes */
1403
+ for (int s = 0; s < subj_num_poly; s++) {
1404
+ for (int c = 0; c < clip_num_poly; c++) {
1405
+ o_table[s][c]
1406
+ = (!((s_bbox[s].getMaxX() < c_bbox[c].getMinX())
1407
+ || (s_bbox[s].getMinX() > c_bbox[c].getMaxX())))
1408
+ && (!((s_bbox[s].getMaxY() < c_bbox[c].getMinY())
1409
+ || (s_bbox[s].getMinY() > c_bbox[c].getMaxY())));
1410
+ }
1363
1411
  }
1364
1412
 
1365
- private static float N_EDGE(EdgeNode d, EdgeNode e, int p, float i, float j) {
1366
- switch (p) {
1367
- case ABOVE:
1368
- d = e;
1369
- do {
1370
- d = d.next;
1371
- } while (d.outp_above == null);
1372
- return d.bot_x + d.dx * (j - d.bot_y);
1373
- case BELOW:
1374
- d = e;
1375
- do {
1376
- d = d.next;
1377
- } while (d.outp_below == null);
1378
- return d.bot_x + d.dx * (j - d.bot_y);
1379
- default:
1380
- throw new IllegalStateException("bogus p value");
1381
- }
1413
+ /* For each clip contour, search for any subject contour overlaps */
1414
+ for (int c = 0; c < clip_num_poly; c++) {
1415
+ boolean overlap = false;
1416
+ for (int s = 0; !overlap && (s < subj_num_poly); s++) {
1417
+ overlap = o_table[s][c];
1418
+ }
1419
+ if (!overlap) {
1420
+ clip.setContributing(c, false); // Flag non contributing status
1421
+ }
1382
1422
  }
1383
1423
 
1384
- private static RRectangle[] create_contour_bboxes(RPolygon p) {
1385
- RRectangle[] box = new RRectangle[p.getNumInnerPoly()];
1386
-
1387
- /* Construct contour bounding boxes */
1388
- for (int c = 0; c < p.getNumInnerPoly(); c++) {
1389
- RPolygon inner_poly = p.getInnerPoly(c);
1390
- box[c] = inner_poly.getBBox();
1424
+ if (op == OperationType.GPC_INT) {
1425
+ /* For each subject contour, search for any clip contour overlaps */
1426
+ for (int s = 0; s < subj_num_poly; s++) {
1427
+ boolean overlap = false;
1428
+ for (int c = 0; !overlap && (c < clip_num_poly); c++) {
1429
+ overlap = o_table[s][c];
1391
1430
  }
1392
- return box;
1393
- }
1394
-
1395
- private static void minimax_test(RPolygon subj, RPolygon clip, OperationType op) {
1396
- RRectangle[] s_bbox = create_contour_bboxes(subj);
1397
- RRectangle[] c_bbox = create_contour_bboxes(clip);
1398
-
1399
- int subj_num_poly = subj.getNumInnerPoly();
1400
- int clip_num_poly = clip.getNumInnerPoly();
1401
- boolean[][] o_table = new boolean[subj_num_poly][clip_num_poly];
1402
-
1403
- /* Check all subject contour bounding boxes against clip boxes */
1404
- for (int s = 0; s < subj_num_poly; s++) {
1405
- for (int c = 0; c < clip_num_poly; c++) {
1406
- o_table[s][c]
1407
- = (!((s_bbox[s].getMaxX() < c_bbox[c].getMinX())
1408
- || (s_bbox[s].getMinX() > c_bbox[c].getMaxX())))
1409
- && (!((s_bbox[s].getMaxY() < c_bbox[c].getMinY())
1410
- || (s_bbox[s].getMinY() > c_bbox[c].getMaxY())));
1411
- }
1412
- }
1413
-
1414
- /* For each clip contour, search for any subject contour overlaps */
1415
- for (int c = 0; c < clip_num_poly; c++) {
1416
- boolean overlap = false;
1417
- for (int s = 0; !overlap && (s < subj_num_poly); s++) {
1418
- overlap = o_table[s][c];
1419
- }
1420
- if (!overlap) {
1421
- clip.setContributing(c, false); // Flag non contributing status
1422
- }
1423
- }
1424
-
1425
- if (op == OperationType.GPC_INT) {
1426
- /* For each subject contour, search for any clip contour overlaps */
1427
- for (int s = 0; s < subj_num_poly; s++) {
1428
- boolean overlap = false;
1429
- for (int c = 0; !overlap && (c < clip_num_poly); c++) {
1430
- overlap = o_table[s][c];
1431
- }
1432
- if (!overlap) {
1433
- subj.setContributing(s, false); // Flag non contributing status
1434
- }
1435
- }
1431
+ if (!overlap) {
1432
+ subj.setContributing(s, false); // Flag non contributing status
1436
1433
  }
1434
+ }
1437
1435
  }
1438
-
1439
- private static LmtNode bound_list(LmtTable lmt_table, float y) {
1440
- if (lmt_table.top_node == null) {
1441
- lmt_table.top_node = new LmtNode(y);
1442
- return lmt_table.top_node;
1436
+ }
1437
+
1438
+ private static LmtNode bound_list(LmtTable lmt_table, float y) {
1439
+ if (lmt_table.top_node == null) {
1440
+ lmt_table.top_node = new LmtNode(y);
1441
+ return lmt_table.top_node;
1442
+ } else {
1443
+ LmtNode prev = null;
1444
+ LmtNode node = lmt_table.top_node;
1445
+ boolean done = false;
1446
+ while (!done) {
1447
+ if (y < node.y) {
1448
+ /* Insert a new LMT node before the current node */
1449
+ LmtNode existing_node = node;
1450
+ node = new LmtNode(y);
1451
+ node.next = existing_node;
1452
+ if (prev == null) {
1453
+ lmt_table.top_node = node;
1454
+ } else {
1455
+ prev.next = node;
1456
+ }
1457
+ done = true;
1458
+ } else if (y > node.y) {
1459
+ /* Head further up the LMT */
1460
+ if (node.next == null) {
1461
+ node.next = new LmtNode(y);
1462
+ node = node.next;
1463
+ done = true;
1464
+ } else {
1465
+ prev = node;
1466
+ node = node.next;
1467
+ }
1443
1468
  } else {
1444
- LmtNode prev = null;
1445
- LmtNode node = lmt_table.top_node;
1446
- boolean done = false;
1447
- while (!done) {
1448
- if (y < node.y) {
1449
- /* Insert a new LMT node before the current node */
1450
- LmtNode existing_node = node;
1451
- node = new LmtNode(y);
1452
- node.next = existing_node;
1453
- if (prev == null) {
1454
- lmt_table.top_node = node;
1455
- } else {
1456
- prev.next = node;
1457
- }
1458
- done = true;
1459
- } else if (y > node.y) {
1460
- /* Head further up the LMT */
1461
- if (node.next == null) {
1462
- node.next = new LmtNode(y);
1463
- node = node.next;
1464
- done = true;
1465
- } else {
1466
- prev = node;
1467
- node = node.next;
1468
- }
1469
- } else {
1470
- /* Use this existing LMT node */
1471
- done = true;
1472
- }
1473
- }
1474
- return node;
1469
+ /* Use this existing LMT node */
1470
+ done = true;
1475
1471
  }
1472
+ }
1473
+ return node;
1476
1474
  }
1477
-
1478
- private static void insert_bound(LmtNode lmt_node, EdgeNode e) {
1479
- if (lmt_node.first_bound == null) {
1480
- /* Link node e to the tail of the list */
1475
+ }
1476
+
1477
+ private static void insert_bound(LmtNode lmt_node, EdgeNode e) {
1478
+ if (lmt_node.first_bound == null) {
1479
+ /* Link node e to the tail of the list */
1480
+ lmt_node.first_bound = e;
1481
+ } else {
1482
+ boolean done = false;
1483
+ EdgeNode prev_bound = null;
1484
+ EdgeNode current_bound = lmt_node.first_bound;
1485
+ while (!done) {
1486
+ /* Do primary sort on the x field */
1487
+ if (e.bot_x < current_bound.bot_x) {
1488
+ /* Insert a new node mid-list */
1489
+ if (prev_bound == null) {
1481
1490
  lmt_node.first_bound = e;
1482
- } else {
1483
- boolean done = false;
1484
- EdgeNode prev_bound = null;
1485
- EdgeNode current_bound = lmt_node.first_bound;
1486
- while (!done) {
1487
- /* Do primary sort on the x field */
1488
- if (e.bot_x < current_bound.bot_x) {
1489
- /* Insert a new node mid-list */
1490
- if (prev_bound == null) {
1491
- lmt_node.first_bound = e;
1492
- } else {
1493
- prev_bound.next_bound = e;
1494
- }
1495
- e.next_bound = current_bound;
1496
-
1497
- done = true;
1498
- } else if (e.bot_x == current_bound.bot_x) {
1499
- /* Do secondary sort on the dx field */
1500
- if (e.dx < current_bound.dx) {
1501
- /* Insert a new node mid-list */
1502
- if (prev_bound == null) {
1503
- lmt_node.first_bound = e;
1504
- } else {
1505
- prev_bound.next_bound = e;
1506
- }
1507
- e.next_bound = current_bound;
1508
- done = true;
1509
- } else {
1510
- /* Head further down the list */
1511
- if (current_bound.next_bound == null) {
1512
- current_bound.next_bound = e;
1513
- done = true;
1514
- } else {
1515
- prev_bound = current_bound;
1516
- current_bound = current_bound.next_bound;
1517
- }
1518
- }
1519
- } else {
1520
- /* Head further down the list */
1521
- if (current_bound.next_bound == null) {
1522
- current_bound.next_bound = e;
1523
- done = true;
1524
- } else {
1525
- prev_bound = current_bound;
1526
- current_bound = current_bound.next_bound;
1527
- }
1528
- }
1491
+ } else {
1492
+ prev_bound.next_bound = e;
1493
+ }
1494
+ e.next_bound = current_bound;
1495
+
1496
+ done = true;
1497
+ } else if (e.bot_x == current_bound.bot_x) {
1498
+ /* Do secondary sort on the dx field */
1499
+ if (e.dx < current_bound.dx) {
1500
+ /* Insert a new node mid-list */
1501
+ if (prev_bound == null) {
1502
+ lmt_node.first_bound = e;
1503
+ } else {
1504
+ prev_bound.next_bound = e;
1505
+ }
1506
+ e.next_bound = current_bound;
1507
+ done = true;
1508
+ } else {
1509
+ /* Head further down the list */
1510
+ if (current_bound.next_bound == null) {
1511
+ current_bound.next_bound = e;
1512
+ done = true;
1513
+ } else {
1514
+ prev_bound = current_bound;
1515
+ current_bound = current_bound.next_bound;
1529
1516
  }
1517
+ }
1518
+ } else {
1519
+ /* Head further down the list */
1520
+ if (current_bound.next_bound == null) {
1521
+ current_bound.next_bound = e;
1522
+ done = true;
1523
+ } else {
1524
+ prev_bound = current_bound;
1525
+ current_bound = current_bound.next_bound;
1526
+ }
1530
1527
  }
1528
+ }
1531
1529
  }
1532
-
1533
- private static void add_edge_to_aet(AetTree aet, EdgeNode edge) {
1534
- if (aet.top_node == null) {
1535
- /* Append edge onto the tail end of the AET */
1530
+ }
1531
+
1532
+ private static void add_edge_to_aet(AetTree aet, EdgeNode edge) {
1533
+ if (aet.top_node == null) {
1534
+ /* Append edge onto the tail end of the AET */
1535
+ aet.top_node = edge;
1536
+ edge.prev = null;
1537
+ edge.next = null;
1538
+ } else {
1539
+ EdgeNode current_edge = aet.top_node;
1540
+ EdgeNode prev = null;
1541
+ boolean done = false;
1542
+ while (!done) {
1543
+ /* Do primary sort on the xb field */
1544
+ if (edge.xb < current_edge.xb) {
1545
+ /* Insert edge here (before the AET edge) */
1546
+ edge.prev = prev;
1547
+ edge.next = current_edge;
1548
+ current_edge.prev = edge;
1549
+ if (prev == null) {
1536
1550
  aet.top_node = edge;
1537
- edge.prev = null;
1538
- edge.next = null;
1539
- } else {
1540
- EdgeNode current_edge = aet.top_node;
1541
- EdgeNode prev = null;
1542
- boolean done = false;
1543
- while (!done) {
1544
- /* Do primary sort on the xb field */
1545
- if (edge.xb < current_edge.xb) {
1546
- /* Insert edge here (before the AET edge) */
1547
- edge.prev = prev;
1548
- edge.next = current_edge;
1549
- current_edge.prev = edge;
1550
- if (prev == null) {
1551
- aet.top_node = edge;
1552
- } else {
1553
- prev.next = edge;
1554
- }
1555
- done = true;
1556
- } else if (edge.xb == current_edge.xb) {
1557
- /* Do secondary sort on the dx field */
1558
- if (edge.dx < current_edge.dx) {
1559
- /* Insert edge here (before the AET edge) */
1560
- edge.prev = prev;
1561
- edge.next = current_edge;
1562
- current_edge.prev = edge;
1563
- if (prev == null) {
1564
- aet.top_node = edge;
1565
- } else {
1566
- prev.next = edge;
1567
- }
1568
- done = true;
1569
- } else {
1570
- /* Head further into the AET */
1571
- prev = current_edge;
1572
- if (current_edge.next == null) {
1573
- current_edge.next = edge;
1574
- edge.prev = current_edge;
1575
- edge.next = null;
1576
- done = true;
1577
- } else {
1578
- current_edge = current_edge.next;
1579
- }
1580
- }
1581
- } else {
1582
- /* Head further into the AET */
1583
- prev = current_edge;
1584
- if (current_edge.next == null) {
1585
- current_edge.next = edge;
1586
- edge.prev = current_edge;
1587
- edge.next = null;
1588
- done = true;
1589
- } else {
1590
- current_edge = current_edge.next;
1591
- }
1592
- }
1551
+ } else {
1552
+ prev.next = edge;
1553
+ }
1554
+ done = true;
1555
+ } else if (edge.xb == current_edge.xb) {
1556
+ /* Do secondary sort on the dx field */
1557
+ if (edge.dx < current_edge.dx) {
1558
+ /* Insert edge here (before the AET edge) */
1559
+ edge.prev = prev;
1560
+ edge.next = current_edge;
1561
+ current_edge.prev = edge;
1562
+ if (prev == null) {
1563
+ aet.top_node = edge;
1564
+ } else {
1565
+ prev.next = edge;
1566
+ }
1567
+ done = true;
1568
+ } else {
1569
+ /* Head further into the AET */
1570
+ prev = current_edge;
1571
+ if (current_edge.next == null) {
1572
+ current_edge.next = edge;
1573
+ edge.prev = current_edge;
1574
+ edge.next = null;
1575
+ done = true;
1576
+ } else {
1577
+ current_edge = current_edge.next;
1593
1578
  }
1579
+ }
1580
+ } else {
1581
+ /* Head further into the AET */
1582
+ prev = current_edge;
1583
+ if (current_edge.next == null) {
1584
+ current_edge.next = edge;
1585
+ edge.prev = current_edge;
1586
+ edge.next = null;
1587
+ done = true;
1588
+ } else {
1589
+ current_edge = current_edge.next;
1590
+ }
1594
1591
  }
1592
+ }
1595
1593
  }
1596
-
1597
- private static void add_to_sbtree(ScanBeamTreeEntries sbte, float y) {
1598
- if (sbte.sb_tree == null) {
1599
- /* Add a new tree node here */
1600
- sbte.sb_tree = new ScanBeamTree(y);
1601
- sbte.sbt_entries++;
1602
- return;
1594
+ }
1595
+
1596
+ private static void add_to_sbtree(ScanBeamTreeEntries sbte, float y) {
1597
+ if (sbte.sb_tree == null) {
1598
+ /* Add a new tree node here */
1599
+ sbte.sb_tree = new ScanBeamTree(y);
1600
+ sbte.sbt_entries++;
1601
+ return;
1602
+ }
1603
+ ScanBeamTree tree_node = sbte.sb_tree;
1604
+ boolean done = false;
1605
+ while (!done) {
1606
+ if (tree_node.y > y) {
1607
+ if (tree_node.less == null) {
1608
+ tree_node.less = new ScanBeamTree(y);
1609
+ sbte.sbt_entries++;
1610
+ done = true;
1611
+ } else {
1612
+ tree_node = tree_node.less;
1603
1613
  }
1604
- ScanBeamTree tree_node = sbte.sb_tree;
1605
- boolean done = false;
1606
- while (!done) {
1607
- if (tree_node.y > y) {
1608
- if (tree_node.less == null) {
1609
- tree_node.less = new ScanBeamTree(y);
1610
- sbte.sbt_entries++;
1611
- done = true;
1612
- } else {
1613
- tree_node = tree_node.less;
1614
- }
1615
- } else if (tree_node.y < y) {
1616
- if (tree_node.more == null) {
1617
- tree_node.more = new ScanBeamTree(y);
1618
- sbte.sbt_entries++;
1619
- done = true;
1620
- } else {
1621
- tree_node = tree_node.more;
1622
- }
1623
- } else {
1624
- done = true;
1625
- }
1614
+ } else if (tree_node.y < y) {
1615
+ if (tree_node.more == null) {
1616
+ tree_node.more = new ScanBeamTree(y);
1617
+ sbte.sbt_entries++;
1618
+ done = true;
1619
+ } else {
1620
+ tree_node = tree_node.more;
1626
1621
  }
1622
+ } else {
1623
+ done = true;
1624
+ }
1627
1625
  }
1626
+ }
1627
+
1628
+ private static EdgeTable build_lmt(LmtTable lmt_table,
1629
+ ScanBeamTreeEntries sbte,
1630
+ RPolygon p,
1631
+ int type, //poly type SUBJ/CLIP
1632
+ OperationType op) {
1633
+ /* Create the entire input polygon edge table in one go */
1634
+ EdgeTable edge_table = new EdgeTable();
1635
+
1636
+ for (int c = 0; c < p.getNumInnerPoly(); c++) {
1637
+ RPolygon ip = p.getInnerPoly(c);
1638
+ if (!ip.isContributing(0)) {
1639
+ /* Ignore the non-contributing contour */
1640
+ ip.setContributing(0, true);
1641
+ } else {
1642
+ /* Perform contour optimisation */
1643
+ int num_vertices = 0;
1644
+ int e_index = 0;
1645
+ edge_table = new EdgeTable();
1646
+ for (int i = 0; i < ip.getNumPoints(); i++) {
1647
+ if (OPTIMAL(ip, i)) {
1648
+ float x = ip.getX(i);
1649
+ float y = ip.getY(i);
1650
+ edge_table.addNode(x, y);
1651
+
1652
+ /* Record vertex in the scanbeam table */
1653
+ add_to_sbtree(sbte, ip.getY(i));
1654
+
1655
+ num_vertices++;
1656
+ }
1657
+ }
1628
1658
 
1629
- private static EdgeTable build_lmt(LmtTable lmt_table,
1630
- ScanBeamTreeEntries sbte,
1631
- RPolygon p,
1632
- int type, //poly type SUBJ/CLIP
1633
- OperationType op) {
1634
- /* Create the entire input polygon edge table in one go */
1635
- EdgeTable edge_table = new EdgeTable();
1636
-
1637
- for (int c = 0; c < p.getNumInnerPoly(); c++) {
1638
- RPolygon ip = p.getInnerPoly(c);
1639
- if (!ip.isContributing(0)) {
1640
- /* Ignore the non-contributing contour */
1641
- ip.setContributing(0, true);
1642
- } else {
1643
- /* Perform contour optimisation */
1644
- int num_vertices = 0;
1645
- int e_index = 0;
1646
- edge_table = new EdgeTable();
1647
- for (int i = 0; i < ip.getNumPoints(); i++) {
1648
- if (OPTIMAL(ip, i)) {
1649
- float x = ip.getX(i);
1650
- float y = ip.getY(i);
1651
- edge_table.addNode(x, y);
1652
-
1653
- /* Record vertex in the scanbeam table */
1654
- add_to_sbtree(sbte, ip.getY(i));
1655
-
1656
- num_vertices++;
1657
- }
1658
- }
1659
-
1660
- /* Do the contour forward pass */
1661
- for (int min = 0; min < num_vertices; min++) {
1662
- /* If a forward local minimum... */
1663
- if (edge_table.FWD_MIN(min)) {
1664
- /* Search for the next local maximum... */
1665
- int num_edges = 1;
1666
- int max = NEXT_INDEX(min, num_vertices);
1667
- while (edge_table.NOT_FMAX(max)) {
1668
- num_edges++;
1669
- max = NEXT_INDEX(max, num_vertices);
1670
- }
1671
-
1672
- /* Build the next edge list */
1673
- int v = min;
1674
- EdgeNode e = edge_table.getNode(e_index);
1675
- e.bstate_below = BundleState.UNBUNDLED;
1676
- e.bundle_below_clip = 0;
1677
- e.bundle_below_subj = 0;
1678
-
1679
- for (int i = 0; i < num_edges; i++) {
1680
- EdgeNode ei = edge_table.getNode(e_index + i);
1681
- EdgeNode ev = edge_table.getNode(v);
1682
-
1683
- ei.xb = ev.vertex_x;
1684
- ei.bot_x = ev.vertex_x;
1685
- ei.bot_y = ev.vertex_y;
1686
-
1687
- v = NEXT_INDEX(v, num_vertices);
1688
- ev = edge_table.getNode(v);
1689
-
1690
- ei.top_x = ev.vertex_x;
1691
- ei.top_y = ev.vertex_y;
1692
- ei.dx = (ev.vertex_x - ei.bot_x) / (ei.top_y - ei.bot_y);
1693
- ei.type = type;
1694
- ei.outp_above = null;
1695
- ei.outp_below = null;
1696
- ei.next = null;
1697
- ei.prev = null;
1698
- ei.succ = ((num_edges > 1) && (i < (num_edges - 1))) ? edge_table.getNode(e_index + i + 1) : null;
1699
- ei.pred = ((num_edges > 1) && (i > 0)) ? edge_table.getNode(e_index + i - 1) : null;
1700
- ei.next_bound = null;
1701
- ei.bside_clip = (op == OperationType.GPC_DIFF) ? RIGHT : LEFT;
1702
- ei.bside_subj = LEFT;
1703
- }
1704
- insert_bound(bound_list(lmt_table, edge_table.getNode(min).vertex_y), e);
1705
- e_index += num_edges;
1706
- }
1707
- }
1659
+ /* Do the contour forward pass */
1660
+ for (int min = 0; min < num_vertices; min++) {
1661
+ /* If a forward local minimum... */
1662
+ if (edge_table.FWD_MIN(min)) {
1663
+ /* Search for the next local maximum... */
1664
+ int num_edges = 1;
1665
+ int max = NEXT_INDEX(min, num_vertices);
1666
+ while (edge_table.NOT_FMAX(max)) {
1667
+ num_edges++;
1668
+ max = NEXT_INDEX(max, num_vertices);
1669
+ }
1708
1670
 
1709
- /* Do the contour reverse pass */
1710
- for (int min = 0; min < num_vertices; min++) {
1711
- /* If a reverse local minimum... */
1712
- if (edge_table.REV_MIN(min)) {
1713
- /* Search for the previous local maximum... */
1714
- int num_edges = 1;
1715
- int max = PREV_INDEX(min, num_vertices);
1716
- while (edge_table.NOT_RMAX(max)) {
1717
- num_edges++;
1718
- max = PREV_INDEX(max, num_vertices);
1719
- }
1720
-
1721
- /* Build the previous edge list */
1722
- int v = min;
1723
- EdgeNode e = edge_table.getNode(e_index);
1724
- e.bstate_below = BundleState.UNBUNDLED;
1725
- e.bundle_below_clip = 0;
1726
- e.bundle_below_subj = 0;
1727
-
1728
- for (int i = 0; i < num_edges; i++) {
1729
- EdgeNode ei = edge_table.getNode(e_index + i);
1730
- EdgeNode ev = edge_table.getNode(v);
1731
-
1732
- ei.xb = ev.vertex_x;
1733
- ei.bot_x = ev.vertex_x;
1734
- ei.bot_y = ev.vertex_y;
1735
-
1736
- v = PREV_INDEX(v, num_vertices);
1737
- ev = edge_table.getNode(v);
1738
-
1739
- ei.top_x = ev.vertex_x;
1740
- ei.top_y = ev.vertex_y;
1741
- ei.dx = (ev.vertex_x - ei.bot_x) / (ei.top_y - ei.bot_y);
1742
- ei.type = type;
1743
- ei.outp_above = null;
1744
- ei.outp_below = null;
1745
- ei.next = null;
1746
- ei.prev = null;
1747
- ei.succ = ((num_edges > 1) && (i < (num_edges - 1))) ? edge_table.getNode(e_index + i + 1) : null;
1748
- ei.pred = ((num_edges > 1) && (i > 0)) ? edge_table.getNode(e_index + i - 1) : null;
1749
- ei.next_bound = null;
1750
- ei.bside_clip = (op == OperationType.GPC_DIFF) ? RIGHT : LEFT;
1751
- ei.bside_subj = LEFT;
1752
- }
1753
- insert_bound(bound_list(lmt_table, edge_table.getNode(min).vertex_y), e);
1754
- e_index += num_edges;
1755
- }
1756
- }
1671
+ /* Build the next edge list */
1672
+ int v = min;
1673
+ EdgeNode e = edge_table.getNode(e_index);
1674
+ e.bstate_below = BundleState.UNBUNDLED;
1675
+ e.bundle_below_clip = 0;
1676
+ e.bundle_below_subj = 0;
1677
+
1678
+ for (int i = 0; i < num_edges; i++) {
1679
+ EdgeNode ei = edge_table.getNode(e_index + i);
1680
+ EdgeNode ev = edge_table.getNode(v);
1681
+
1682
+ ei.xb = ev.vertex_x;
1683
+ ei.bot_x = ev.vertex_x;
1684
+ ei.bot_y = ev.vertex_y;
1685
+
1686
+ v = NEXT_INDEX(v, num_vertices);
1687
+ ev = edge_table.getNode(v);
1688
+
1689
+ ei.top_x = ev.vertex_x;
1690
+ ei.top_y = ev.vertex_y;
1691
+ ei.dx = (ev.vertex_x - ei.bot_x) / (ei.top_y - ei.bot_y);
1692
+ ei.type = type;
1693
+ ei.outp_above = null;
1694
+ ei.outp_below = null;
1695
+ ei.next = null;
1696
+ ei.prev = null;
1697
+ ei.succ = ((num_edges > 1) && (i < (num_edges - 1))) ? edge_table.getNode(e_index + i + 1) : null;
1698
+ ei.pred = ((num_edges > 1) && (i > 0)) ? edge_table.getNode(e_index + i - 1) : null;
1699
+ ei.next_bound = null;
1700
+ ei.bside_clip = (op == OperationType.GPC_DIFF) ? RIGHT : LEFT;
1701
+ ei.bside_subj = LEFT;
1757
1702
  }
1703
+ insert_bound(bound_list(lmt_table, edge_table.getNode(min).vertex_y), e);
1704
+ e_index += num_edges;
1705
+ }
1758
1706
  }
1759
- return edge_table;
1760
- }
1761
1707
 
1762
- private static StNode add_st_edge(StNode st, ItNodeTable it, EdgeNode edge, float dy) {
1763
- if (st == null) {
1764
- /* Append edge onto the tail end of the ST */
1765
- st = new StNode(edge, null);
1766
- } else {
1767
- float den = (st.xt - st.xb) - (edge.xt - edge.xb);
1768
-
1769
- /* If new edge and ST edge don't cross */
1770
- if ((edge.xt >= st.xt) || (edge.dx == st.dx) || (Math.abs(den) <= GPC_EPSILON)) {
1771
- /* No intersection - insert edge here (before the ST edge) */
1772
- StNode existing_node = st;
1773
- st = new StNode(edge, existing_node);
1774
- } else {
1775
- /* Compute intersection between new edge and ST edge */
1776
- float r = (edge.xb - st.xb) / den;
1777
- float x = st.xb + r * (st.xt - st.xb);
1778
- float y = r * dy;
1779
-
1780
- /* Insert the edge pointers and the intersection point in the IT */
1781
- it.top_node = add_intersection(it.top_node, st.edge, edge, x, y);
1782
-
1783
- /* Head further into the ST */
1784
- st.prev = add_st_edge(st.prev, it, edge, dy);
1708
+ /* Do the contour reverse pass */
1709
+ for (int min = 0; min < num_vertices; min++) {
1710
+ /* If a reverse local minimum... */
1711
+ if (edge_table.REV_MIN(min)) {
1712
+ /* Search for the previous local maximum... */
1713
+ int num_edges = 1;
1714
+ int max = PREV_INDEX(min, num_vertices);
1715
+ while (edge_table.NOT_RMAX(max)) {
1716
+ num_edges++;
1717
+ max = PREV_INDEX(max, num_vertices);
1785
1718
  }
1786
- }
1787
- return st;
1788
- }
1789
1719
 
1790
- private static ItNode add_intersection(ItNode it_node,
1791
- EdgeNode edge0,
1792
- EdgeNode edge1,
1793
- float x,
1794
- float y) {
1795
- if (it_node == null) {
1796
- /* Append a new node to the tail of the list */
1797
- it_node = new ItNode(edge0, edge1, x, y, null);
1798
- } else {
1799
- if (it_node.point_y > y) {
1800
- /* Insert a new node mid-list */
1801
- ItNode existing_node = it_node;
1802
- it_node = new ItNode(edge0, edge1, x, y, existing_node);
1803
- } else {
1804
- /* Head further down the list */
1805
- it_node.next = add_intersection(it_node.next, edge0, edge1, x, y);
1720
+ /* Build the previous edge list */
1721
+ int v = min;
1722
+ EdgeNode e = edge_table.getNode(e_index);
1723
+ e.bstate_below = BundleState.UNBUNDLED;
1724
+ e.bundle_below_clip = 0;
1725
+ e.bundle_below_subj = 0;
1726
+
1727
+ for (int i = 0; i < num_edges; i++) {
1728
+ EdgeNode ei = edge_table.getNode(e_index + i);
1729
+ EdgeNode ev = edge_table.getNode(v);
1730
+
1731
+ ei.xb = ev.vertex_x;
1732
+ ei.bot_x = ev.vertex_x;
1733
+ ei.bot_y = ev.vertex_y;
1734
+
1735
+ v = PREV_INDEX(v, num_vertices);
1736
+ ev = edge_table.getNode(v);
1737
+
1738
+ ei.top_x = ev.vertex_x;
1739
+ ei.top_y = ev.vertex_y;
1740
+ ei.dx = (ev.vertex_x - ei.bot_x) / (ei.top_y - ei.bot_y);
1741
+ ei.type = type;
1742
+ ei.outp_above = null;
1743
+ ei.outp_below = null;
1744
+ ei.next = null;
1745
+ ei.prev = null;
1746
+ ei.succ = ((num_edges > 1) && (i < (num_edges - 1))) ? edge_table.getNode(e_index + i + 1) : null;
1747
+ ei.pred = ((num_edges > 1) && (i > 0)) ? edge_table.getNode(e_index + i - 1) : null;
1748
+ ei.next_bound = null;
1749
+ ei.bside_clip = (op == OperationType.GPC_DIFF) ? RIGHT : LEFT;
1750
+ ei.bside_subj = LEFT;
1806
1751
  }
1752
+ insert_bound(bound_list(lmt_table, edge_table.getNode(min).vertex_y), e);
1753
+ e_index += num_edges;
1754
+ }
1807
1755
  }
1808
- return it_node;
1756
+ }
1757
+ }
1758
+ return edge_table;
1759
+ }
1760
+
1761
+ private static StNode add_st_edge(StNode st, ItNodeTable it, EdgeNode edge, float dy) {
1762
+ if (st == null) {
1763
+ /* Append edge onto the tail end of the ST */
1764
+ st = new StNode(edge, null);
1765
+ } else {
1766
+ float den = (st.xt - st.xb) - (edge.xt - edge.xb);
1767
+
1768
+ /* If new edge and ST edge don't cross */
1769
+ if ((edge.xt >= st.xt) || (edge.dx == st.dx) || (Math.abs(den) <= GPC_EPSILON)) {
1770
+ /* No intersection - insert edge here (before the ST edge) */
1771
+ StNode existing_node = st;
1772
+ st = new StNode(edge, existing_node);
1773
+ } else {
1774
+ /* Compute intersection between new edge and ST edge */
1775
+ float r = (edge.xb - st.xb) / den;
1776
+ float x = st.xb + r * (st.xt - st.xb);
1777
+ float y = r * dy;
1778
+
1779
+ /* Insert the edge pointers and the intersection point in the IT */
1780
+ it.top_node = add_intersection(it.top_node, st.edge, edge, x, y);
1781
+
1782
+ /* Head further into the ST */
1783
+ st.prev = add_st_edge(st.prev, it, edge, dy);
1784
+ }
1809
1785
  }
1786
+ return st;
1787
+ }
1788
+
1789
+ private static ItNode add_intersection(ItNode it_node,
1790
+ EdgeNode edge0,
1791
+ EdgeNode edge1,
1792
+ float x,
1793
+ float y) {
1794
+ if (it_node == null) {
1795
+ /* Append a new node to the tail of the list */
1796
+ it_node = new ItNode(edge0, edge1, x, y, null);
1797
+ } else {
1798
+ if (it_node.point_y > y) {
1799
+ /* Insert a new node mid-list */
1800
+ ItNode existing_node = it_node;
1801
+ it_node = new ItNode(edge0, edge1, x, y, existing_node);
1802
+ } else {
1803
+ /* Head further down the list */
1804
+ it_node.next = add_intersection(it_node.next, edge0, edge1, x, y);
1805
+ }
1806
+ }
1807
+ return it_node;
1808
+ }
1810
1809
 
1811
- private static int count_tristrips(PolygonNode tn) {
1812
- int total;
1810
+ private static int count_tristrips(PolygonNode tn) {
1811
+ int total;
1813
1812
 
1814
- for (total = 0; tn != null; tn = tn.next) {
1815
- if (tn.active > 2) {
1816
- total++;
1817
- }
1818
- }
1819
- return total;
1813
+ for (total = 0; tn != null; tn = tn.next) {
1814
+ if (tn.active > 2) {
1815
+ total++;
1816
+ }
1820
1817
  }
1821
-
1822
- private static VertexNode add_vertex(VertexNode ve_node, float x, float y) {
1823
- if (ve_node == null) {
1824
- /* Append a new node to the tail of the list */
1825
- ve_node = new VertexNode(x, y);
1826
- } else {
1827
- /* Head further down the list */
1828
- ve_node.next = add_vertex(ve_node.next, x, y);
1829
- }
1830
- return ve_node;
1818
+ return total;
1819
+ }
1820
+
1821
+ private static VertexNode add_vertex(VertexNode ve_node, float x, float y) {
1822
+ if (ve_node == null) {
1823
+ /* Append a new node to the tail of the list */
1824
+ ve_node = new VertexNode(x, y);
1825
+ } else {
1826
+ /* Head further down the list */
1827
+ ve_node.next = add_vertex(ve_node.next, x, y);
1831
1828
  }
1832
-
1833
- private static PolygonNode new_tristrip(PolygonNode po_node, EdgeNode edge, float x, float y) {
1834
- if (po_node == null) {
1835
- /* Append a new node to the tail of the list */
1836
- po_node = new PolygonNode();
1837
- po_node.v_left = add_vertex(po_node.v_left, x, y);
1838
- edge.outp_above = po_node;
1839
- } else {
1840
- /* Head further down the list */
1841
- po_node.next = new_tristrip(po_node.next, edge, x, y);
1842
- }
1843
- return po_node;
1829
+ return ve_node;
1830
+ }
1831
+
1832
+ private static PolygonNode new_tristrip(PolygonNode po_node, EdgeNode edge, float x, float y) {
1833
+ if (po_node == null) {
1834
+ /* Append a new node to the tail of the list */
1835
+ po_node = new PolygonNode();
1836
+ po_node.v_left = add_vertex(po_node.v_left, x, y);
1837
+ edge.outp_above = po_node;
1838
+ } else {
1839
+ /* Head further down the list */
1840
+ po_node.next = new_tristrip(po_node.next, edge, x, y);
1844
1841
  }
1845
-
1846
- // ---------------------
1847
- // --- Inner Classes ---
1848
- // ---------------------
1849
- /**
1850
- * Edge intersection classes
1851
- */
1852
- private static class VertexType {
1853
-
1854
- public static final int NUL = 0;
1855
- /* Empty non-intersection */
1856
- public static final int EMX = 1;
1857
- /* External maximum */
1858
- public static final int ELI = 2;
1859
- /* External left intermediate */
1860
- public static final int TED = 3;
1861
- /* Top edge */
1862
- public static final int ERI = 4;
1863
- /* External right intermediate */
1864
- public static final int RED = 5;
1865
- /* Right edge */
1866
- public static final int IMM = 6;
1867
- /* Internal maximum and minimum */
1868
- public static final int IMN = 7;
1869
- /* Internal minimum */
1870
- public static final int EMN = 8;
1871
- /* External minimum */
1872
- public static final int EMM = 9;
1873
- /* External maximum and minimum */
1874
- public static final int LED = 10;
1875
- /* Left edge */
1876
- public static final int ILI = 11;
1877
- /* Internal left intermediate */
1878
- public static final int BED = 12;
1879
- /* Bottom edge */
1880
- public static final int IRI = 13;
1881
- /* Internal right intermediate */
1882
- public static final int IMX = 14;
1883
- /* Internal maximum */
1884
- public static final int FUL = 15;
1885
-
1886
- /* Full non-intersection */
1887
-
1888
- public static int getType(int tr, int tl, int br, int bl) {
1889
- return tr + (tl << 1) + (br << 2) + (bl << 3);
1890
- }
1842
+ return po_node;
1843
+ }
1844
+
1845
+ // ---------------------
1846
+ // --- Inner Classes ---
1847
+ // ---------------------
1848
+ /**
1849
+ * Edge intersection classes
1850
+ */
1851
+ private static class VertexType {
1852
+
1853
+ public static final int NUL = 0;
1854
+ /* Empty non-intersection */
1855
+ public static final int EMX = 1;
1856
+ /* External maximum */
1857
+ public static final int ELI = 2;
1858
+ /* External left intermediate */
1859
+ public static final int TED = 3;
1860
+ /* Top edge */
1861
+ public static final int ERI = 4;
1862
+ /* External right intermediate */
1863
+ public static final int RED = 5;
1864
+ /* Right edge */
1865
+ public static final int IMM = 6;
1866
+ /* Internal maximum and minimum */
1867
+ public static final int IMN = 7;
1868
+ /* Internal minimum */
1869
+ public static final int EMN = 8;
1870
+ /* External minimum */
1871
+ public static final int EMM = 9;
1872
+ /* External maximum and minimum */
1873
+ public static final int LED = 10;
1874
+ /* Left edge */
1875
+ public static final int ILI = 11;
1876
+ /* Internal left intermediate */
1877
+ public static final int BED = 12;
1878
+ /* Bottom edge */
1879
+ public static final int IRI = 13;
1880
+ /* Internal right intermediate */
1881
+ public static final int IMX = 14;
1882
+ /* Internal maximum */
1883
+ public static final int FUL = 15;
1884
+
1885
+ /* Full non-intersection */
1886
+ public static int getType(int tr, int tl, int br, int bl) {
1887
+ return tr + (tl << 1) + (br << 2) + (bl << 3);
1891
1888
  }
1889
+ }
1892
1890
 
1893
- /**
1894
- * Horizontal edge states
1895
- */
1896
- private static class HState {
1891
+ /**
1892
+ * Horizontal edge states
1893
+ */
1894
+ private static class HState {
1897
1895
 
1898
- public static final int NH = 0;
1899
- /* No horizontal edge */
1900
- public static final int BH = 1;
1901
- /* Bottom horizontal edge */
1902
- public static final int TH = 2;
1903
- /* Top horizontal edge */
1896
+ public static final int NH = 0;
1897
+ /* No horizontal edge */
1898
+ public static final int BH = 1;
1899
+ /* Bottom horizontal edge */
1900
+ public static final int TH = 2;
1901
+ /* Top horizontal edge */
1904
1902
 
1905
1903
  /* Horizontal edge state transitions within scanbeam boundary */
1906
- public static final int[][] next_h_state
1907
- = {
1908
- /* ABOVE BELOW CROSS */
1909
- /* L R L R L R */
1910
- /* NH */{BH, TH, TH, BH, NH, NH},
1911
- /* BH */ {NH, NH, NH, NH, TH, TH},
1912
- /* TH */ {NH, NH, NH, NH, BH, BH}
1913
- };
1914
- }
1915
-
1916
- /**
1917
- * Edge bundle state
1918
- */
1919
- private static class BundleState {
1920
-
1921
- private String state;
1922
-
1923
- private BundleState(String state) {
1924
- this.state = state;
1925
- }
1904
+ public static final int[][] NEXT_H_STATE
1905
+ = {
1906
+ /* ABOVE BELOW CROSS */
1907
+ /* L R L R L R */
1908
+ /* NH */{BH, TH, TH, BH, NH, NH},
1909
+ /* BH */ {NH, NH, NH, NH, TH, TH},
1910
+ /* TH */ {NH, NH, NH, NH, BH, BH}
1911
+ };
1912
+ }
1913
+
1914
+ /**
1915
+ * Edge bundle state
1916
+ */
1917
+ private static class BundleState {
1918
+
1919
+ private String state;
1920
+
1921
+ private BundleState(String state) {
1922
+ this.state = state;
1923
+ }
1926
1924
 
1927
- public static final BundleState UNBUNDLED = new BundleState("UNBUNDLED"); // Isolated edge not within a bundle
1928
- public static final BundleState BUNDLE_HEAD = new BundleState("BUNDLE_HEAD"); // Bundle head node
1929
- public static final BundleState BUNDLE_TAIL = new BundleState("BUNDLE_TAIL"); // Passive bundle tail node
1925
+ public static final BundleState UNBUNDLED = new BundleState("UNBUNDLED"); // Isolated edge not within a bundle
1926
+ public static final BundleState BUNDLE_HEAD = new BundleState("BUNDLE_HEAD"); // Bundle head node
1927
+ public static final BundleState BUNDLE_TAIL = new BundleState("BUNDLE_TAIL"); // Passive bundle tail node
1930
1928
 
1931
- @Override
1932
- public String toString() {
1933
- return state;
1934
- }
1929
+ @Override
1930
+ public String toString() {
1931
+ return state;
1935
1932
  }
1933
+ }
1936
1934
 
1937
- /**
1938
- * Internal vertex list datatype
1939
- */
1940
- private static class VertexNode {
1935
+ /**
1936
+ * Internal vertex list datatype
1937
+ */
1938
+ private static class VertexNode {
1941
1939
 
1942
- float x; // X coordinate component
1943
- float y; // Y coordinate component
1944
- VertexNode next; // Pointer to next vertex in list
1940
+ float x; // X coordinate component
1941
+ float y; // Y coordinate component
1942
+ VertexNode next; // Pointer to next vertex in list
1945
1943
 
1946
- public VertexNode(float x, float y) {
1947
- this.x = x;
1948
- this.y = y;
1949
- this.next = null;
1950
- }
1944
+ public VertexNode(float x, float y) {
1945
+ this.x = x;
1946
+ this.y = y;
1947
+ this.next = null;
1948
+ }
1949
+ }
1950
+
1951
+ /**
1952
+ * Internal contour / tristrip type
1953
+ */
1954
+ private static class PolygonNode {
1955
+
1956
+ int active;
1957
+ /* Active flag / vertex count */
1958
+ boolean hole;
1959
+ /* Hole / external contour flag */
1960
+ VertexNode v_right, v_left;
1961
+ /* Left and right vertex list ptrs */
1962
+ PolygonNode next;
1963
+ /* Pointer to next polygon contour */
1964
+ PolygonNode proxy;
1965
+
1966
+ /* Pointer to actual structure used */
1967
+ public PolygonNode() {
1968
+ this.v_left = null;
1969
+ this.v_right = null;
1970
+ this.next = null;
1971
+ this.proxy = this;
1972
+ /* Initialise proxy to point to p itself */
1973
+ this.active = 1; //TRUE
1951
1974
  }
1952
1975
 
1953
- /**
1954
- * Internal contour / tristrip type
1955
- */
1956
- private static class PolygonNode {
1957
-
1958
- int active;
1959
- /* Active flag / vertex count */
1960
- boolean hole;
1961
- /* Hole / external contour flag */
1962
- VertexNode v_right, v_left;
1963
- /* Left and right vertex list ptrs */
1964
- PolygonNode next;
1965
- /* Pointer to next polygon contour */
1966
- PolygonNode proxy;
1967
-
1968
- /* Pointer to actual structure used */
1969
-
1970
- public PolygonNode() {
1971
- this.v_left = null;
1972
- this.v_right = null;
1973
- this.next = null;
1974
- this.proxy = this;
1975
- /* Initialise proxy to point to p itself */
1976
- this.active = 1; //TRUE
1977
- }
1978
-
1979
- public PolygonNode(PolygonNode next, float x, float y) {
1980
- VertexNode vn = new VertexNode(x, y);
1981
- this.v_left = vn;
1982
- this.v_right = vn;
1983
-
1984
- this.next = next;
1985
- this.proxy = this;
1986
- /* Initialise proxy to point to p itself */
1987
- this.active = 1; //TRUE
1988
- }
1976
+ public PolygonNode(PolygonNode next, float x, float y) {
1977
+ VertexNode vn = new VertexNode(x, y);
1978
+ this.v_left = vn;
1979
+ this.v_right = vn;
1989
1980
 
1990
- public void add_right(float x, float y) {
1991
- VertexNode nv = new VertexNode(x, y);
1981
+ this.next = next;
1982
+ this.proxy = this;
1983
+ /* Initialise proxy to point to p itself */
1984
+ this.active = 1; //TRUE
1985
+ }
1992
1986
 
1993
- /* Add vertex nv to the right end of the polygon's vertex list */
1994
- proxy.v_right.next = nv;
1987
+ public void add_right(float x, float y) {
1988
+ VertexNode nv = new VertexNode(x, y);
1995
1989
 
1996
- /* Update proxy->v[RIGHT] to point to nv */
1997
- proxy.v_right = nv;
1998
- }
1990
+ /* Add vertex nv to the right end of the polygon's vertex list */
1991
+ proxy.v_right.next = nv;
1999
1992
 
2000
- public void add_left(float x, float y) {
2001
- VertexNode nv = new VertexNode(x, y);
1993
+ /* Update proxy->v[RIGHT] to point to nv */
1994
+ proxy.v_right = nv;
1995
+ }
2002
1996
 
2003
- /* Add vertex nv to the left end of the polygon's vertex list */
2004
- nv.next = proxy.v_left;
1997
+ public void add_left(float x, float y) {
1998
+ VertexNode nv = new VertexNode(x, y);
2005
1999
 
2006
- /* Update proxy->[LEFT] to point to nv */
2007
- proxy.v_left = nv;
2008
- }
2000
+ /* Add vertex nv to the left end of the polygon's vertex list */
2001
+ nv.next = proxy.v_left;
2009
2002
 
2003
+ /* Update proxy->[LEFT] to point to nv */
2004
+ proxy.v_left = nv;
2010
2005
  }
2011
2006
 
2012
- private static class TopPolygonNode {
2007
+ }
2013
2008
 
2014
- PolygonNode top_node = null;
2009
+ private static class TopPolygonNode {
2015
2010
 
2016
- public PolygonNode add_local_min(float x, float y) {
2017
- PolygonNode existing_min = top_node;
2011
+ PolygonNode top_node = null;
2018
2012
 
2019
- top_node = new PolygonNode(existing_min, x, y);
2013
+ public PolygonNode add_local_min(float x, float y) {
2014
+ PolygonNode existing_min = top_node;
2020
2015
 
2021
- return top_node;
2022
- }
2016
+ top_node = new PolygonNode(existing_min, x, y);
2023
2017
 
2024
- public void merge_left(PolygonNode p, PolygonNode q) {
2025
- /* Label contour as a hole */
2026
- q.proxy.hole = true;
2027
-
2028
- if (p.proxy != q.proxy) {
2029
- /* Assign p's vertex list to the left end of q's list */
2030
- p.proxy.v_right.next = q.proxy.v_left;
2031
- q.proxy.v_left = p.proxy.v_left;
2032
-
2033
- /* Redirect any p.proxy references to q.proxy */
2034
- PolygonNode target = p.proxy;
2035
- for (PolygonNode node = top_node; (node != null); node = node.next) {
2036
- if (node.proxy == target) {
2037
- node.active = 0;
2038
- node.proxy = q.proxy;
2039
- }
2040
- }
2041
- }
2018
+ return top_node;
2019
+ }
2020
+
2021
+ public void merge_left(PolygonNode p, PolygonNode q) {
2022
+ /* Label contour as a hole */
2023
+ q.proxy.hole = true;
2024
+
2025
+ if (p.proxy != q.proxy) {
2026
+ /* Assign p's vertex list to the left end of q's list */
2027
+ p.proxy.v_right.next = q.proxy.v_left;
2028
+ q.proxy.v_left = p.proxy.v_left;
2029
+
2030
+ /* Redirect any p.proxy references to q.proxy */
2031
+ PolygonNode target = p.proxy;
2032
+ for (PolygonNode node = top_node; (node != null); node = node.next) {
2033
+ if (node.proxy == target) {
2034
+ node.active = 0;
2035
+ node.proxy = q.proxy;
2036
+ }
2042
2037
  }
2038
+ }
2039
+ }
2043
2040
 
2044
- public void merge_right(PolygonNode p, PolygonNode q) {
2045
- /* Label contour as external */
2046
- q.proxy.hole = false;
2047
-
2048
- if (p.proxy != q.proxy) {
2049
- /* Assign p's vertex list to the right end of q's list */
2050
- q.proxy.v_right.next = p.proxy.v_left;
2051
- q.proxy.v_right = p.proxy.v_right;
2052
-
2053
- /* Redirect any p->proxy references to q->proxy */
2054
- PolygonNode target = p.proxy;
2055
- for (PolygonNode node = top_node; (node != null); node = node.next) {
2056
- if (node.proxy == target) {
2057
- node.active = 0;
2058
- node.proxy = q.proxy;
2059
- }
2060
- }
2061
- }
2041
+ public void merge_right(PolygonNode p, PolygonNode q) {
2042
+ /* Label contour as external */
2043
+ q.proxy.hole = false;
2044
+
2045
+ if (p.proxy != q.proxy) {
2046
+ /* Assign p's vertex list to the right end of q's list */
2047
+ q.proxy.v_right.next = p.proxy.v_left;
2048
+ q.proxy.v_right = p.proxy.v_right;
2049
+
2050
+ /* Redirect any p->proxy references to q->proxy */
2051
+ PolygonNode target = p.proxy;
2052
+ for (PolygonNode node = top_node; (node != null); node = node.next) {
2053
+ if (node.proxy == target) {
2054
+ node.active = 0;
2055
+ node.proxy = q.proxy;
2056
+ }
2062
2057
  }
2058
+ }
2059
+ }
2063
2060
 
2064
- public int count_contours() {
2065
- int nc = 0;
2066
- for (PolygonNode polygon = top_node; (polygon != null); polygon = polygon.next) {
2067
- if (polygon.active != 0) {
2068
- /* Count the vertices in the current contour */
2069
- int nv = 0;
2070
- for (VertexNode v = polygon.proxy.v_left; (v != null); v = v.next) {
2071
- nv++;
2072
- }
2061
+ public int count_contours() {
2062
+ int nc = 0;
2063
+ for (PolygonNode polygon = top_node; (polygon != null); polygon = polygon.next) {
2064
+ if (polygon.active != 0) {
2065
+ /* Count the vertices in the current contour */
2066
+ int nv = 0;
2067
+ for (VertexNode v = polygon.proxy.v_left; (v != null); v = v.next) {
2068
+ nv++;
2069
+ }
2073
2070
 
2074
- /* Record valid vertex counts in the active field */
2075
- if (nv > 2) {
2076
- polygon.active = nv;
2077
- nc++;
2078
- } else {
2079
- /* Invalid contour: just free the heap */
2080
- // VertexNode nextv = null;
2081
- // for (VertexNode v= polygon.proxy.v_left; (v != null); v = nextv)
2082
- // {
2083
- // nextv= v.next;
2084
- // v = null;
2085
- // }
2086
- polygon.active = 0;
2087
- }
2088
- }
2089
- }
2090
- return nc;
2071
+ /* Record valid vertex counts in the active field */
2072
+ if (nv > 2) {
2073
+ polygon.active = nv;
2074
+ nc++;
2075
+ } else {
2076
+ /* Invalid contour: just free the heap */
2077
+ // VertexNode nextv = null;
2078
+ // for (VertexNode v= polygon.proxy.v_left; (v != null); v = nextv)
2079
+ // {
2080
+ // nextv= v.next;
2081
+ // v = null;
2082
+ // }
2083
+ polygon.active = 0;
2084
+ }
2091
2085
  }
2086
+ }
2087
+ return nc;
2088
+ }
2092
2089
 
2093
- public RPolygon getResult(Class polyClass) {
2094
- //RPolygon result = createNewPoly( polyClass );
2095
- RPolygon result = new RPolygon();
2096
- int num_contours = count_contours();
2090
+ public RPolygon getResult(Class polyClass) {
2091
+ //RPolygon result = createNewPoly( polyClass );
2092
+ RPolygon result = new RPolygon();
2093
+ int num_contours = count_contours();
2094
+ if (num_contours > 0) {
2095
+ int c = 0;
2096
+ PolygonNode npoly_node;
2097
+ for (PolygonNode poly_node = top_node; (poly_node != null); poly_node = npoly_node) {
2098
+ npoly_node = poly_node.next;
2099
+ if (poly_node.active != 0) {
2100
+ RContour contour;
2101
+ if (result.countContours() > 0) {
2102
+ contour = result.contours[0];
2103
+ } else {
2104
+ contour = new RContour();
2105
+ }
2106
+ //RPolygon poly = result;
2097
2107
  if (num_contours > 0) {
2098
- int c = 0;
2099
- PolygonNode npoly_node;
2100
- for (PolygonNode poly_node = top_node; (poly_node != null); poly_node = npoly_node) {
2101
- npoly_node = poly_node.next;
2102
- if (poly_node.active != 0) {
2103
- RContour contour;
2104
- if (result.countContours() > 0) {
2105
- contour = result.contours[0];
2106
- } else {
2107
- contour = new RContour();
2108
- }
2109
- //RPolygon poly = result;
2110
- if (num_contours > 0) {
2111
- contour = new RContour();
2112
- //poly = createNewPoly( polyClass );
2113
- }
2114
- if (poly_node.proxy.hole) {
2115
- contour.isHole = poly_node.proxy.hole;
2116
- //poly.setIsHole( poly_node.proxy.hole );
2117
- }
2118
-
2119
- // ------------------------------------------------------------------------
2120
- // --- This algorithm puts the verticies into the poly in reverse order ---
2121
- // ------------------------------------------------------------------------
2122
- for (VertexNode vtx = poly_node.proxy.v_left; (vtx != null); vtx = vtx.next) {
2123
- contour.addPoint(vtx.x, vtx.y);
2124
- //poly.add( vtx.x, vtx.y );
2125
- }
2126
- if (num_contours > 0) {
2127
- result.addContour(contour);
2128
- //result.add( poly );
2129
- }
2130
- c++;
2131
- }
2132
- }
2133
-
2134
- // -----------------------------------------
2135
- // --- Sort holes to the end of the list ---
2136
- // -----------------------------------------
2137
- RPolygon orig = new RPolygon(result);
2138
- result = new RPolygon();
2139
- //result = createNewPoly( polyClass );
2140
- for (int i = 0; i < orig.countContours(); i++) //for( int i = 0; i < orig.getNumInnerPoly(); i++ )
2141
- {
2142
- RContour inner = orig.contours[i];
2143
- //RPolygon inner = orig.getInnerPoly(i);
2144
- if (!inner.isHole()) {
2145
- result.addContour(inner);
2146
- //result.add(inner);
2147
- }
2148
- }
2149
-
2150
- for (int i = 0; i < orig.countContours(); i++) //for( int i = 0; i < orig.getNumInnerPoly(); i++ )
2151
- {
2152
- RContour inner = orig.contours[i];
2153
- //RPolygon inner = orig.getInnerPoly(i);
2154
- if (inner.isHole()) {
2155
- result.addContour(inner);
2156
- }
2157
- }
2108
+ contour = new RContour();
2109
+ //poly = createNewPoly( polyClass );
2158
2110
  }
2159
- return result;
2160
- }
2161
-
2162
- public void print() {
2163
- System.out.println("---- out_poly ----");
2164
- int c = 0;
2165
- PolygonNode npoly_node;
2166
- for (PolygonNode poly_node = top_node; (poly_node != null); poly_node = npoly_node) {
2167
- System.out.println("contour=" + c + " active=" + poly_node.active + " hole=" + poly_node.proxy.hole);
2168
- npoly_node = poly_node.next;
2169
- if (poly_node.active != 0) {
2170
- int v = 0;
2171
- for (VertexNode vtx = poly_node.proxy.v_left; (vtx != null); vtx = vtx.next) {
2172
- System.out.println("v=" + v + " vtx.x=" + vtx.x + " vtx.y=" + vtx.y);
2173
- }
2174
- c++;
2175
- }
2111
+ if (poly_node.proxy.hole) {
2112
+ contour.isHole = poly_node.proxy.hole;
2113
+ //poly.setIsHole( poly_node.proxy.hole );
2176
2114
  }
2177
- }
2178
- }
2179
2115
 
2180
- private static class EdgeNode {
2181
-
2182
- float vertex_x, vertex_y;
2183
- /* Piggy-backed contour vertex data */
2184
- float bot_x, bot_y;
2185
- /* Edge lower (x, y) coordinate */
2186
- float top_x, top_y;
2187
- /* Edge upper (x, y) coordinate */
2188
- float xb;
2189
- /* Scanbeam bottom x coordinate */
2190
- float xt;
2191
- /* Scanbeam top x coordinate */
2192
- float dx;
2193
- /* Change in x for a unit y increase */
2194
- int type;
2195
- /* Clip / subject edge flag */
2196
- //int[][] bundle = new int[2][2]; /* Bundle edge flags */
2197
- int[] bundle_above = new int[2];
2198
- int bundle_below_clip, bundle_below_subj;
2199
-
2200
- //int[] bside = new int[2]; /* Bundle left / right indicators */
2201
- int bside_clip, bside_subj;
2202
- /* Bundle left / right indicators */
2203
- //BundleState[] bstate = new BundleState[2]; /* Edge bundle state */
2204
- BundleState bstate_above, bstate_below;
2205
- PolygonNode outp_above, outp_below;
2206
- /* Output polygon / tristrip pointer */
2207
- EdgeNode prev;
2208
- /* Previous edge in the AET */
2209
- EdgeNode next;
2210
- /* Next edge in the AET */
2211
- EdgeNode pred;
2212
- /* Edge connected at the lower end */
2213
- EdgeNode succ;
2214
- /* Edge connected at the upper end */
2215
- EdgeNode next_bound;
2216
- /* Pointer to next bound in LMT */
2217
- }
2218
-
2219
- private static class AetTree {
2220
-
2221
- EdgeNode top_node;
2222
-
2223
- public void print() {
2224
- System.out.println("");
2225
- System.out.println("aet");
2226
- for (EdgeNode edge = top_node; (edge != null); edge = edge.next) {
2227
- System.out.println("edge.vertex_x=" + edge.vertex_x + " edge.vertex_y=" + edge.vertex_y);
2116
+ // ------------------------------------------------------------------------
2117
+ // --- This algorithm puts the verticies into the poly in reverse order ---
2118
+ // ------------------------------------------------------------------------
2119
+ for (VertexNode vtx = poly_node.proxy.v_left; (vtx != null); vtx = vtx.next) {
2120
+ contour.addPoint(vtx.x, vtx.y);
2121
+ //poly.add( vtx.x, vtx.y );
2228
2122
  }
2229
- }
2230
- }
2231
-
2232
- private static class EdgeTable {
2233
-
2234
- private final List<EdgeNode> edges = new ArrayList<>();
2235
-
2236
- public void addNode(float x, float y) {
2237
- EdgeNode node = new EdgeNode();
2238
- node.vertex_x = x;
2239
- node.vertex_y = y;
2240
- edges.add(node);
2241
- }
2242
-
2243
- public EdgeNode getNode(int index) {
2244
- return (EdgeNode) edges.get(index);
2245
- }
2246
-
2247
- public boolean FWD_MIN(int i) {
2248
- EdgeNode prev = (EdgeNode) edges.get(PREV_INDEX(i, edges.size()));
2249
- EdgeNode next = (EdgeNode) edges.get(NEXT_INDEX(i, edges.size()));
2250
- EdgeNode ith = (EdgeNode) edges.get(i);
2251
- return ((prev.vertex_y >= ith.vertex_y)
2252
- && (next.vertex_y > ith.vertex_y));
2123
+ if (num_contours > 0) {
2124
+ result.addContour(contour);
2125
+ //result.add( poly );
2126
+ }
2127
+ c++;
2128
+ }
2253
2129
  }
2254
2130
 
2255
- public boolean NOT_FMAX(int i) {
2256
- EdgeNode next = (EdgeNode) edges.get(NEXT_INDEX(i, edges.size()));
2257
- EdgeNode ith = (EdgeNode) edges.get(i);
2258
- return (next.vertex_y > ith.vertex_y);
2131
+ // -----------------------------------------
2132
+ // --- Sort holes to the end of the list ---
2133
+ // -----------------------------------------
2134
+ RPolygon orig = new RPolygon(result);
2135
+ result = new RPolygon();
2136
+ //result = createNewPoly( polyClass );
2137
+ for (int i = 0; i < orig.countContours(); i++) //for( int i = 0; i < orig.getNumInnerPoly(); i++ )
2138
+ {
2139
+ RContour inner = orig.contours[i];
2140
+ //RPolygon inner = orig.getInnerPoly(i);
2141
+ if (!inner.isHole()) {
2142
+ result.addContour(inner);
2143
+ //result.add(inner);
2144
+ }
2259
2145
  }
2260
2146
 
2261
- public boolean REV_MIN(int i) {
2262
- EdgeNode prev = (EdgeNode) edges.get(PREV_INDEX(i, edges.size()));
2263
- EdgeNode next = (EdgeNode) edges.get(NEXT_INDEX(i, edges.size()));
2264
- EdgeNode ith = (EdgeNode) edges.get(i);
2265
- return ((prev.vertex_y > ith.vertex_y)
2266
- && (next.vertex_y >= ith.vertex_y));
2147
+ for (int i = 0; i < orig.countContours(); i++) //for( int i = 0; i < orig.getNumInnerPoly(); i++ )
2148
+ {
2149
+ RContour inner = orig.contours[i];
2150
+ //RPolygon inner = orig.getInnerPoly(i);
2151
+ if (inner.isHole()) {
2152
+ result.addContour(inner);
2153
+ }
2267
2154
  }
2155
+ }
2156
+ return result;
2157
+ }
2268
2158
 
2269
- public boolean NOT_RMAX(int i) {
2270
- EdgeNode prev = (EdgeNode) edges.get(PREV_INDEX(i, edges.size()));
2271
- EdgeNode ith = (EdgeNode) edges.get(i);
2272
- return (prev.vertex_y > ith.vertex_y);
2159
+ public void print() {
2160
+ System.out.println("---- out_poly ----");
2161
+ int c = 0;
2162
+ PolygonNode npoly_node;
2163
+ for (PolygonNode poly_node = top_node; (poly_node != null); poly_node = npoly_node) {
2164
+ System.out.println("contour=" + c + " active=" + poly_node.active + " hole=" + poly_node.proxy.hole);
2165
+ npoly_node = poly_node.next;
2166
+ if (poly_node.active != 0) {
2167
+ int v = 0;
2168
+ for (VertexNode vtx = poly_node.proxy.v_left; (vtx != null); vtx = vtx.next) {
2169
+ System.out.println("v=" + v + " vtx.x=" + vtx.x + " vtx.y=" + vtx.y);
2170
+ }
2171
+ c++;
2273
2172
  }
2173
+ }
2174
+ }
2175
+ }
2176
+
2177
+ private static class EdgeNode {
2178
+
2179
+ float vertex_x, vertex_y;
2180
+ /* Piggy-backed contour vertex data */
2181
+ float bot_x, bot_y;
2182
+ /* Edge lower (x, y) coordinate */
2183
+ float top_x, top_y;
2184
+ /* Edge upper (x, y) coordinate */
2185
+ float xb;
2186
+ /* Scanbeam bottom x coordinate */
2187
+ float xt;
2188
+ /* Scanbeam top x coordinate */
2189
+ float dx;
2190
+ /* Change in x for a unit y increase */
2191
+ int type;
2192
+ /* Clip / subject edge flag */
2193
+ //int[][] bundle = new int[2][2]; /* Bundle edge flags */
2194
+ int[] bundle_above = new int[2];
2195
+ int bundle_below_clip, bundle_below_subj;
2196
+
2197
+ //int[] bside = new int[2]; /* Bundle left / right indicators */
2198
+ int bside_clip, bside_subj;
2199
+ /* Bundle left / right indicators */
2200
+ //BundleState[] bstate = new BundleState[2]; /* Edge bundle state */
2201
+ BundleState bstate_above, bstate_below;
2202
+ PolygonNode outp_above, outp_below;
2203
+ /* Output polygon / tristrip pointer */
2204
+ EdgeNode prev;
2205
+ /* Previous edge in the AET */
2206
+ EdgeNode next;
2207
+ /* Next edge in the AET */
2208
+ EdgeNode pred;
2209
+ /* Edge connected at the lower end */
2210
+ EdgeNode succ;
2211
+ /* Edge connected at the upper end */
2212
+ EdgeNode next_bound;
2213
+ /* Pointer to next bound in LMT */
2214
+ }
2215
+
2216
+ private static class AetTree {
2217
+
2218
+ EdgeNode top_node;
2219
+
2220
+ public void print() {
2221
+ System.out.println("");
2222
+ System.out.println("aet");
2223
+ for (EdgeNode edge = top_node; (edge != null); edge = edge.next) {
2224
+ System.out.println("edge.vertex_x=" + edge.vertex_x + " edge.vertex_y=" + edge.vertex_y);
2225
+ }
2274
2226
  }
2227
+ }
2275
2228
 
2276
- /**
2277
- * Local minima table
2278
- */
2279
- private static class LmtNode {
2229
+ private static class EdgeTable {
2280
2230
 
2281
- float y;
2282
- /* Y coordinate at local minimum */
2283
- EdgeNode first_bound;
2284
- /* Pointer to bound list */
2285
- LmtNode next;
2231
+ private final List<EdgeNode> edges = new ArrayList<>();
2286
2232
 
2287
- /* Pointer to next local minimum */
2233
+ public void addNode(float x, float y) {
2234
+ EdgeNode node = new EdgeNode();
2235
+ node.vertex_x = x;
2236
+ node.vertex_y = y;
2237
+ edges.add(node);
2238
+ }
2288
2239
 
2289
- public LmtNode(float yvalue) {
2290
- y = yvalue;
2291
- }
2240
+ public EdgeNode getNode(int index) {
2241
+ return (EdgeNode) edges.get(index);
2292
2242
  }
2293
2243
 
2294
- private static class LmtTable {
2244
+ public boolean FWD_MIN(int i) {
2245
+ EdgeNode prev = (EdgeNode) edges.get(PREV_INDEX(i, edges.size()));
2246
+ EdgeNode next = (EdgeNode) edges.get(NEXT_INDEX(i, edges.size()));
2247
+ EdgeNode ith = (EdgeNode) edges.get(i);
2248
+ return ((prev.vertex_y >= ith.vertex_y)
2249
+ && (next.vertex_y > ith.vertex_y));
2250
+ }
2295
2251
 
2296
- LmtNode top_node;
2252
+ public boolean NOT_FMAX(int i) {
2253
+ EdgeNode next = (EdgeNode) edges.get(NEXT_INDEX(i, edges.size()));
2254
+ EdgeNode ith = (EdgeNode) edges.get(i);
2255
+ return (next.vertex_y > ith.vertex_y);
2256
+ }
2297
2257
 
2298
- public void print() {
2299
- int n = 0;
2300
- LmtNode lmt = top_node;
2301
- while (lmt != null) {
2302
- System.out.println("lmt(" + n + ")");
2303
- for (EdgeNode edge = lmt.first_bound; (edge != null); edge = edge.next_bound) {
2304
- System.out.println("edge.vertex_x=" + edge.vertex_x + " edge.vertex_y=" + edge.vertex_y);
2305
- }
2306
- n++;
2307
- lmt = lmt.next;
2308
- }
2309
- }
2258
+ public boolean REV_MIN(int i) {
2259
+ EdgeNode prev = (EdgeNode) edges.get(PREV_INDEX(i, edges.size()));
2260
+ EdgeNode next = (EdgeNode) edges.get(NEXT_INDEX(i, edges.size()));
2261
+ EdgeNode ith = (EdgeNode) edges.get(i);
2262
+ return ((prev.vertex_y > ith.vertex_y)
2263
+ && (next.vertex_y >= ith.vertex_y));
2310
2264
  }
2311
2265
 
2312
- /**
2313
- * Scanbeam tree
2314
- */
2315
- private static class ScanBeamTree {
2266
+ public boolean NOT_RMAX(int i) {
2267
+ EdgeNode prev = (EdgeNode) edges.get(PREV_INDEX(i, edges.size()));
2268
+ EdgeNode ith = (EdgeNode) edges.get(i);
2269
+ return (prev.vertex_y > ith.vertex_y);
2270
+ }
2271
+ }
2272
+
2273
+ /**
2274
+ * Local minima table
2275
+ */
2276
+ private static class LmtNode {
2277
+
2278
+ float y;
2279
+ /* Y coordinate at local minimum */
2280
+ EdgeNode first_bound;
2281
+ /* Pointer to bound list */
2282
+ LmtNode next;
2283
+
2284
+ /* Pointer to next local minimum */
2285
+ public LmtNode(float yvalue) {
2286
+ y = yvalue;
2287
+ }
2288
+ }
2316
2289
 
2317
- float y;
2318
- /* Scanbeam node y value */
2319
- ScanBeamTree less;
2320
- /* Pointer to nodes with lower y */
2321
- ScanBeamTree more;
2290
+ private static class LmtTable {
2322
2291
 
2323
- /* Pointer to nodes with higher y */
2292
+ LmtNode top_node;
2324
2293
 
2325
- public ScanBeamTree(float yvalue) {
2326
- y = yvalue;
2294
+ public void print() {
2295
+ int n = 0;
2296
+ LmtNode lmt = top_node;
2297
+ while (lmt != null) {
2298
+ System.out.println("lmt(" + n + ")");
2299
+ for (EdgeNode edge = lmt.first_bound; (edge != null); edge = edge.next_bound) {
2300
+ System.out.println("edge.vertex_x=" + edge.vertex_x + " edge.vertex_y=" + edge.vertex_y);
2327
2301
  }
2302
+ n++;
2303
+ lmt = lmt.next;
2304
+ }
2328
2305
  }
2306
+ }
2307
+
2308
+ /**
2309
+ * Scanbeam tree
2310
+ */
2311
+ private static class ScanBeamTree {
2312
+
2313
+ float y;
2314
+ /* Scanbeam node y value */
2315
+ ScanBeamTree less;
2316
+ /* Pointer to nodes with lower y */
2317
+ ScanBeamTree more;
2318
+
2319
+ /* Pointer to nodes with higher y */
2320
+ public ScanBeamTree(float yvalue) {
2321
+ y = yvalue;
2322
+ }
2323
+ }
2329
2324
 
2330
- /**
2331
- *
2332
- */
2333
- private static class ScanBeamTreeEntries {
2334
-
2335
- int sbt_entries;
2336
- ScanBeamTree sb_tree;
2325
+ /**
2326
+ *
2327
+ */
2328
+ private static class ScanBeamTreeEntries {
2337
2329
 
2338
- public float[] build_sbt() {
2339
- float[] sbt = new float[sbt_entries];
2330
+ int sbt_entries;
2331
+ ScanBeamTree sb_tree;
2340
2332
 
2341
- int entries = 0;
2342
- entries = inner_build_sbt(entries, sbt, sb_tree);
2343
- if (entries != sbt_entries) {
2344
- throw new IllegalStateException("Something went wrong buildign sbt from tree.");
2345
- }
2346
- return sbt;
2347
- }
2333
+ public float[] build_sbt() {
2334
+ float[] sbt = new float[sbt_entries];
2348
2335
 
2349
- private int inner_build_sbt(int entries, float[] sbt, ScanBeamTree sbt_node) {
2350
- if (sbt_node.less != null) {
2351
- entries = inner_build_sbt(entries, sbt, sbt_node.less);
2352
- }
2353
- sbt[entries] = sbt_node.y;
2354
- entries++;
2355
- if (sbt_node.more != null) {
2356
- entries = inner_build_sbt(entries, sbt, sbt_node.more);
2357
- }
2358
- return entries;
2359
- }
2336
+ int entries = 0;
2337
+ entries = inner_build_sbt(entries, sbt, sb_tree);
2338
+ if (entries != sbt_entries) {
2339
+ throw new IllegalStateException("Something went wrong buildign sbt from tree.");
2340
+ }
2341
+ return sbt;
2360
2342
  }
2361
2343
 
2362
- /**
2363
- * Intersection table
2364
- */
2365
- private static class ItNode {
2366
-
2367
- EdgeNode ie0, ie1;
2368
- /* Intersecting edge (bundle) pair */
2369
- float point_x, point_y;
2370
- /* Point of intersection */
2371
- ItNode next;
2372
-
2373
- /* The next intersection table node */
2374
-
2375
- public ItNode(EdgeNode edge0, EdgeNode edge1, float x, float y, ItNode next) {
2376
- this.ie0 = edge0;
2377
- this.ie1 = edge1;
2378
- this.point_x = x;
2379
- this.point_y = y;
2380
- this.next = next;
2381
- }
2344
+ private int inner_build_sbt(int entries, float[] sbt, ScanBeamTree sbt_node) {
2345
+ if (sbt_node.less != null) {
2346
+ entries = inner_build_sbt(entries, sbt, sbt_node.less);
2347
+ }
2348
+ sbt[entries] = sbt_node.y;
2349
+ entries++;
2350
+ if (sbt_node.more != null) {
2351
+ entries = inner_build_sbt(entries, sbt, sbt_node.more);
2352
+ }
2353
+ return entries;
2382
2354
  }
2355
+ }
2356
+
2357
+ /**
2358
+ * Intersection table
2359
+ */
2360
+ private static class ItNode {
2361
+
2362
+ EdgeNode ie0, ie1;
2363
+ /* Intersecting edge (bundle) pair */
2364
+ float point_x, point_y;
2365
+ /* Point of intersection */
2366
+ ItNode next;
2367
+
2368
+ /* The next intersection table node */
2369
+ public ItNode(EdgeNode edge0, EdgeNode edge1, float x, float y, ItNode next) {
2370
+ this.ie0 = edge0;
2371
+ this.ie1 = edge1;
2372
+ this.point_x = x;
2373
+ this.point_y = y;
2374
+ this.next = next;
2375
+ }
2376
+ }
2383
2377
 
2384
- private static class ItNodeTable {
2378
+ private static class ItNodeTable {
2385
2379
 
2386
- ItNode top_node;
2380
+ ItNode top_node;
2387
2381
 
2388
- public void build_intersection_table(AetTree aet, float dy) {
2389
- StNode st = null;
2382
+ public void build_intersection_table(AetTree aet, float dy) {
2383
+ StNode st = null;
2390
2384
 
2391
- /* Process each AET edge */
2392
- for (EdgeNode edge = aet.top_node; (edge != null); edge = edge.next) {
2393
- if ((edge.bstate_above == BundleState.BUNDLE_HEAD)
2394
- || (edge.bundle_above[CLIP] != 0)
2395
- || (edge.bundle_above[SUBJ] != 0)) {
2396
- st = add_st_edge(st, this, edge, dy);
2397
- }
2398
- }
2385
+ /* Process each AET edge */
2386
+ for (EdgeNode edge = aet.top_node; (edge != null); edge = edge.next) {
2387
+ if ((edge.bstate_above == BundleState.BUNDLE_HEAD)
2388
+ || (edge.bundle_above[CLIP] != 0)
2389
+ || (edge.bundle_above[SUBJ] != 0)) {
2390
+ st = add_st_edge(st, this, edge, dy);
2399
2391
  }
2392
+ }
2400
2393
  }
2401
-
2402
- /**
2403
- * Sorted edge table
2404
- */
2405
- private static class StNode {
2406
-
2407
- EdgeNode edge;
2408
- /* Pointer to AET edge */
2409
- float xb;
2410
- /* Scanbeam bottom x coordinate */
2411
- float xt;
2412
- /* Scanbeam top x coordinate */
2413
- float dx;
2414
- /* Change in x for a unit y increase */
2415
- StNode prev;
2416
-
2417
- /* Previous edge in sorted list */
2418
-
2419
- public StNode(EdgeNode edge, StNode prev) {
2420
- this.edge = edge;
2421
- this.xb = edge.xb;
2422
- this.xt = edge.xt;
2423
- this.dx = edge.dx;
2424
- this.prev = prev;
2425
- }
2394
+ }
2395
+
2396
+ /**
2397
+ * Sorted edge table
2398
+ */
2399
+ private static class StNode {
2400
+
2401
+ EdgeNode edge;
2402
+ /* Pointer to AET edge */
2403
+ float xb;
2404
+ /* Scanbeam bottom x coordinate */
2405
+ float xt;
2406
+ /* Scanbeam top x coordinate */
2407
+ float dx;
2408
+ /* Change in x for a unit y increase */
2409
+ StNode prev;
2410
+
2411
+ /* Previous edge in sorted list */
2412
+ public StNode(EdgeNode edge, StNode prev) {
2413
+ this.edge = edge;
2414
+ this.xb = edge.xb;
2415
+ this.xt = edge.xt;
2416
+ this.dx = edge.dx;
2417
+ this.prev = prev;
2426
2418
  }
2427
-
2428
- // -------------
2429
- // --- DEBUG ---
2430
- // -------------
2431
- static void print_sbt(float[] sbt) {
2432
- System.out.println("");
2433
- System.out.println("sbt.length=" + sbt.length);
2434
- for (int i = 0; i < sbt.length; i++) {
2435
- System.out.println("sbt[" + i + "]=" + sbt[i]);
2436
- }
2419
+ }
2420
+
2421
+ // -------------
2422
+ // --- DEBUG ---
2423
+ // -------------
2424
+ static void print_sbt(float[] sbt) {
2425
+ System.out.println("");
2426
+ System.out.println("sbt.length=" + sbt.length);
2427
+ for (int i = 0; i < sbt.length; i++) {
2428
+ System.out.println("sbt[" + i + "]=" + sbt[i]);
2437
2429
  }
2430
+ }
2438
2431
  }