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