geomerative 1.1.0-java → 2.0.0-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
  }