geomerative 0.4.0-java → 2.0.0-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.gitignore +2 -0
- data/.mvn/extensions.xml +1 -1
- data/.mvn/wrapper/maven-wrapper.properties +1 -1
- data/CHANGELOG.md +25 -0
- data/COPYING.md +1 -1
- data/README.md +4 -2
- data/Rakefile +2 -15
- data/docs/.gitignore +6 -0
- data/docs/_config.yml +30 -0
- data/docs/_includes/footer.html +38 -0
- data/docs/_includes/head.html +16 -0
- data/docs/_includes/header.html +27 -0
- data/docs/_includes/icon-github.html +1 -0
- data/docs/_includes/icon-github.svg +3 -0
- data/docs/_includes/icon-twitter.html +1 -0
- data/docs/_includes/icon-twitter.svg +3 -0
- data/docs/_includes/navigation.html +24 -0
- data/docs/_layouts/default.html +20 -0
- data/docs/_layouts/page.html +14 -0
- data/docs/_layouts/post.html +15 -0
- data/docs/_posts/2015-11-21-getting_started.md +67 -0
- data/docs/_posts/2015-11-25-bubbles.md +111 -0
- data/docs/_posts/2015-11-26-extra_bright.md +103 -0
- data/docs/_posts/2015-11-26-text_merge.md +114 -0
- data/docs/_posts/2016-07-06-dymo.md +99 -0
- data/docs/_sass/_base.scss +206 -0
- data/docs/_sass/_layout.scss +242 -0
- data/docs/_sass/_syntax-highlighting.scss +71 -0
- data/docs/about.md +12 -0
- data/docs/assets/bright.png +0 -0
- data/docs/assets/bubbles.png +0 -0
- data/docs/assets/design.png +0 -0
- data/docs/assets/dymo.png +0 -0
- data/docs/assets/favicon.ico +0 -0
- data/docs/assets/fred.png +0 -0
- data/docs/assets/merge.png +0 -0
- data/docs/css/main.scss +38 -0
- data/docs/favicon.ico +0 -0
- data/docs/feed.xml +30 -0
- data/docs/index.html +38 -0
- data/examples/README.md +1 -1
- data/examples/data/bot1.svg +1 -1
- data/examples/data/lion.svg +156 -156
- data/examples/data/ruby.svg +1 -1
- data/examples/hello_svg_to_pdf.rb +1 -1
- data/examples/jruby_merge.rb +1 -1
- data/examples/{f_agent.rb → library/f_agent/f_agent.rb} +0 -0
- data/examples/{font_agent.rb → library/font_agent/font_agent.rb} +2 -1
- data/examples/text_on_geomerative_path.rb +3 -2
- data/examples/typo_deform.rb +2 -2
- data/examples/typo_extra_bright.rb +1 -1
- data/geomerative.gemspec +3 -7
- data/lib/geomerative.rb +5 -4
- data/lib/geomerative/version.rb +1 -1
- data/mvnw +234 -0
- data/mvnw.cmd +145 -0
- data/pom.rb +19 -18
- data/pom.xml +14 -13
- data/src/geomerative/FastRClip.java +2050 -2334
- data/src/geomerative/RClip.java +2237 -2539
- data/src/geomerative/RClosest.java +33 -31
- data/src/geomerative/RCommand.java +1750 -1758
- data/src/geomerative/RContour.java +290 -292
- data/src/geomerative/RFont.java +277 -246
- data/src/geomerative/RG.java +722 -727
- data/src/geomerative/RGeomElem.java +967 -962
- data/src/geomerative/RGroup.java +508 -467
- data/src/geomerative/RMatrix.java +304 -289
- data/src/geomerative/RMesh.java +241 -229
- data/src/geomerative/RPath.java +924 -926
- data/src/geomerative/RPoint.java +391 -391
- data/src/geomerative/RPolygon.java +1017 -1013
- data/src/geomerative/RRectangle.java +43 -52
- data/src/geomerative/RSVG.java +480 -516
- data/src/geomerative/RShape.java +1767 -1777
- data/src/geomerative/RStrip.java +173 -176
- data/src/geomerative/RStyle.java +197 -194
- data/src/org/apache/batik/svggen/font/Font.java +141 -142
- data/src/org/apache/batik/svggen/font/Glyph.java +102 -71
- data/src/org/apache/batik/svggen/font/Point.java +12 -12
- data/src/org/apache/batik/svggen/font/RandomAccessFileEmulator.java +14 -12
- data/src/org/apache/batik/svggen/font/table/ClassDef.java +12 -12
- data/src/org/apache/batik/svggen/font/table/ClassDefFormat1.java +27 -24
- data/src/org/apache/batik/svggen/font/table/ClassDefFormat2.java +20 -17
- data/src/org/apache/batik/svggen/font/table/CmapFormat.java +43 -43
- data/src/org/apache/batik/svggen/font/table/CmapFormat0.java +33 -26
- data/src/org/apache/batik/svggen/font/table/CmapFormat2.java +25 -20
- data/src/org/apache/batik/svggen/font/table/CmapFormat4.java +106 -96
- data/src/org/apache/batik/svggen/font/table/CmapFormat6.java +36 -32
- data/src/org/apache/batik/svggen/font/table/CmapIndexEntry.java +69 -49
- data/src/org/apache/batik/svggen/font/table/CmapTable.java +50 -50
- data/src/org/apache/batik/svggen/font/table/Coverage.java +19 -19
- data/src/org/apache/batik/svggen/font/table/CoverageFormat1.java +30 -27
- data/src/org/apache/batik/svggen/font/table/CoverageFormat2.java +26 -24
- data/src/org/apache/batik/svggen/font/table/CvtTable.java +16 -16
- data/src/org/apache/batik/svggen/font/table/Device.java +32 -32
- data/src/org/apache/batik/svggen/font/table/DirectoryEntry.java +39 -39
- data/src/org/apache/batik/svggen/font/table/Feature.java +26 -23
- data/src/org/apache/batik/svggen/font/table/FeatureList.java +37 -35
- data/src/org/apache/batik/svggen/font/table/FeatureRecord.java +22 -22
- data/src/org/apache/batik/svggen/font/table/FeatureTags.java +4 -3
- data/src/org/apache/batik/svggen/font/table/FpgmTable.java +9 -9
- data/src/org/apache/batik/svggen/font/table/GlyfCompositeComp.java +134 -132
- data/src/org/apache/batik/svggen/font/table/GlyfCompositeDescript.java +123 -122
- data/src/org/apache/batik/svggen/font/table/GlyfDescript.java +44 -44
- data/src/org/apache/batik/svggen/font/table/GlyfSimpleDescript.java +110 -109
- data/src/org/apache/batik/svggen/font/table/GlyfTable.java +46 -46
- data/src/org/apache/batik/svggen/font/table/GlyphDescription.java +25 -13
- data/src/org/apache/batik/svggen/font/table/GposTable.java +26 -23
- data/src/org/apache/batik/svggen/font/table/GsubTable.java +85 -82
- data/src/org/apache/batik/svggen/font/table/HeadTable.java +131 -131
- data/src/org/apache/batik/svggen/font/table/HheaTable.java +80 -80
- data/src/org/apache/batik/svggen/font/table/HmtxTable.java +50 -49
- data/src/org/apache/batik/svggen/font/table/KernSubtable.java +29 -27
- data/src/org/apache/batik/svggen/font/table/KernSubtableFormat0.java +35 -32
- data/src/org/apache/batik/svggen/font/table/KernSubtableFormat2.java +28 -26
- data/src/org/apache/batik/svggen/font/table/KernTable.java +36 -31
- data/src/org/apache/batik/svggen/font/table/KerningPair.java +27 -23
- data/src/org/apache/batik/svggen/font/table/LangSys.java +28 -26
- data/src/org/apache/batik/svggen/font/table/LangSysRecord.java +22 -22
- data/src/org/apache/batik/svggen/font/table/Ligature.java +24 -24
- data/src/org/apache/batik/svggen/font/table/LigatureSet.java +24 -24
- data/src/org/apache/batik/svggen/font/table/LigatureSubst.java +9 -9
- data/src/org/apache/batik/svggen/font/table/LigatureSubstFormat1.java +30 -30
- data/src/org/apache/batik/svggen/font/table/LocaTable.java +37 -37
- data/src/org/apache/batik/svggen/font/table/Lookup.java +41 -40
- data/src/org/apache/batik/svggen/font/table/LookupList.java +34 -34
- data/src/org/apache/batik/svggen/font/table/LookupSubtableFactory.java +7 -5
- data/src/org/apache/batik/svggen/font/table/MaxpTable.java +96 -96
- data/src/org/apache/batik/svggen/font/table/NameRecord.java +64 -65
- data/src/org/apache/batik/svggen/font/table/NameTable.java +33 -33
- data/src/org/apache/batik/svggen/font/table/Os2Table.java +196 -196
- data/src/org/apache/batik/svggen/font/table/Panose.java +14 -12
- data/src/org/apache/batik/svggen/font/table/PostTable.java +338 -338
- data/src/org/apache/batik/svggen/font/table/PrepTable.java +9 -9
- data/src/org/apache/batik/svggen/font/table/Program.java +15 -15
- data/src/org/apache/batik/svggen/font/table/RangeRecord.java +26 -25
- data/src/org/apache/batik/svggen/font/table/Script.java +38 -38
- data/src/org/apache/batik/svggen/font/table/ScriptList.java +42 -42
- data/src/org/apache/batik/svggen/font/table/ScriptRecord.java +22 -22
- data/src/org/apache/batik/svggen/font/table/ScriptTags.java +2 -1
- data/src/org/apache/batik/svggen/font/table/SingleSubst.java +15 -16
- data/src/org/apache/batik/svggen/font/table/SingleSubstFormat1.java +33 -33
- data/src/org/apache/batik/svggen/font/table/SingleSubstFormat2.java +32 -32
- data/src/org/apache/batik/svggen/font/table/Table.java +171 -170
- data/src/org/apache/batik/svggen/font/table/TableDirectory.java +55 -55
- data/src/org/apache/batik/svggen/font/table/TableFactory.java +92 -93
- metadata +47 -30
- data/.travis.yml +0 -14
data/pom.xml
CHANGED
|
@@ -6,12 +6,12 @@ DO NOT MODIFIY - GENERATED CODE
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
-->
|
|
9
|
-
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
|
|
9
|
+
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
|
10
10
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
|
11
11
|
<modelVersion>4.0.0</modelVersion>
|
|
12
12
|
<groupId>ruby-processing</groupId>
|
|
13
13
|
<artifactId>geomerative</artifactId>
|
|
14
|
-
<version>0.
|
|
14
|
+
<version>2.0.0</version>
|
|
15
15
|
<name>geomerative</name>
|
|
16
16
|
<description>geomerative-library for JRubyArt</description>
|
|
17
17
|
<organization>
|
|
@@ -44,16 +44,16 @@ DO NOT MODIFIY - GENERATED CODE
|
|
|
44
44
|
<url>https://github.com/ruby-processing/geomerative/issues</url>
|
|
45
45
|
</issueManagement>
|
|
46
46
|
<properties>
|
|
47
|
+
<maven.compiler.source>1.8</maven.compiler.source>
|
|
48
|
+
<maven.compiler.target>12</maven.compiler.target>
|
|
47
49
|
<polyglot.dump.pom>pom.xml</polyglot.dump.pom>
|
|
48
50
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
|
49
|
-
<maven.compiler.source>1.8</maven.compiler.source>
|
|
50
|
-
<maven.compiler.target>1.8</maven.compiler.target>
|
|
51
51
|
</properties>
|
|
52
52
|
<dependencies>
|
|
53
53
|
<dependency>
|
|
54
54
|
<groupId>org.processing</groupId>
|
|
55
55
|
<artifactId>core</artifactId>
|
|
56
|
-
<version>
|
|
56
|
+
<version>4.0.0</version>
|
|
57
57
|
</dependency>
|
|
58
58
|
</dependencies>
|
|
59
59
|
<build>
|
|
@@ -63,24 +63,25 @@ DO NOT MODIFIY - GENERATED CODE
|
|
|
63
63
|
<plugins>
|
|
64
64
|
<plugin>
|
|
65
65
|
<artifactId>maven-compiler-plugin</artifactId>
|
|
66
|
-
<version>3.
|
|
66
|
+
<version>3.8.1</version>
|
|
67
67
|
<configuration>
|
|
68
|
-
<
|
|
69
|
-
<target>${maven.compiler.target}</target>
|
|
68
|
+
<release>11</release>
|
|
70
69
|
</configuration>
|
|
71
70
|
</plugin>
|
|
72
71
|
<plugin>
|
|
73
72
|
<artifactId>maven-jar-plugin</artifactId>
|
|
74
|
-
<version>3.0
|
|
73
|
+
<version>3.2.0</version>
|
|
75
74
|
<configuration>
|
|
76
75
|
<archive>
|
|
77
|
-
<
|
|
76
|
+
<manifestEntries>
|
|
77
|
+
<Automatic-Module-Name>geomerative.gem</Automatic-Module-Name>
|
|
78
|
+
</manifestEntries>
|
|
78
79
|
</archive>
|
|
79
80
|
</configuration>
|
|
80
81
|
</plugin>
|
|
81
82
|
<plugin>
|
|
82
83
|
<artifactId>maven-resources-plugin</artifactId>
|
|
83
|
-
<version>2.
|
|
84
|
+
<version>2.7</version>
|
|
84
85
|
</plugin>
|
|
85
86
|
</plugins>
|
|
86
87
|
</build>
|
|
@@ -88,7 +89,7 @@ DO NOT MODIFIY - GENERATED CODE
|
|
|
88
89
|
<plugins>
|
|
89
90
|
<plugin>
|
|
90
91
|
<artifactId>maven-pmd-plugin</artifactId>
|
|
91
|
-
<version>3.
|
|
92
|
+
<version>3.12</version>
|
|
92
93
|
<configuration>
|
|
93
94
|
<linkXRef>true</linkXRef>
|
|
94
95
|
<sourceEncoding>utf-8</sourceEncoding>
|
|
@@ -98,7 +99,7 @@ DO NOT MODIFIY - GENERATED CODE
|
|
|
98
99
|
</plugin>
|
|
99
100
|
<plugin>
|
|
100
101
|
<artifactId>maven-checkstyle-plugin</artifactId>
|
|
101
|
-
<version>
|
|
102
|
+
<version>3.1.0</version>
|
|
102
103
|
<configuration>
|
|
103
104
|
<configLocation>config/sun_checks.xml</configLocation>
|
|
104
105
|
</configuration>
|
|
@@ -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>
|
|
50
|
-
* developed by Alan Murta (gpc@cs.man.ac.uk).
|
|
51
|
-
*
|
|
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
|
|
55
|
-
* argument.
|
|
56
|
-
* interface and have a no
|
|
57
|
-
*
|
|
58
|
-
*
|
|
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
|
|
61
|
-
*
|
|
62
|
-
*
|
|
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
|
|
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
|
|
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
|
-
/**
|
|
96
|
-
|
|
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
|
|
109
|
+
* Create a new <code>RPolygon</code> type object using
|
|
110
|
+
* <code>polyClass</code>.
|
|
111
111
|
*/
|
|
112
|
-
private static RPolygon createNewPoly(
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
{
|
|
116
|
-
return
|
|
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
|
-
*
|
|
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(
|
|
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
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
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
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
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
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
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
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
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
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
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
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
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
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
if (
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
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
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
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
|
-
|
|
708
|
-
|
|
709
|
-
|
|
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(
|
|
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
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
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
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
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
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
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
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
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
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
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
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
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
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
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
|
-
|
|
915
|
-
|
|
916
|
-
|
|
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
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
{
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
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
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
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
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
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(
|
|
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(
|
|
1449
|
-
|
|
1450
|
-
|
|
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(
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
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(
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
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(
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
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(
|
|
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 (
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
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(
|
|
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(
|
|
1554
|
-
{
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
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(
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
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
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
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
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
{
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
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
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
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
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
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
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
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
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
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 (
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
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
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
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(
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
{
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
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(
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
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
|
-
|
|
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
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
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
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
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 =
|
|
2134
|
-
|
|
2135
|
-
public static final int
|
|
2136
|
-
|
|
2137
|
-
public static final int
|
|
2138
|
-
|
|
2139
|
-
public static final int
|
|
2140
|
-
|
|
2141
|
-
public static final int
|
|
2142
|
-
|
|
2143
|
-
public static final int
|
|
2144
|
-
|
|
2145
|
-
public static final int
|
|
2146
|
-
|
|
2147
|
-
public static final int
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
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;
|
|
2162
|
-
|
|
2163
|
-
public static final int
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
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 */
|
|
2171
|
-
/* BH */ {NH, NH,
|
|
2172
|
-
/* TH */ {NH, NH,
|
|
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
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
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() {
|
|
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
|
|
2198
|
-
float
|
|
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(
|
|
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
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
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;
|
|
1971
|
+
this.proxy = this;
|
|
1972
|
+
/* Initialise proxy to point to p itself */
|
|
2226
1973
|
this.active = 1; //TRUE
|
|
2227
1974
|
}
|
|
2228
|
-
|
|
2229
|
-
public PolygonNode(
|
|
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;
|
|
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(
|
|
2241
|
-
|
|
2242
|
-
|
|
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(
|
|
2252
|
-
|
|
2253
|
-
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
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(
|
|
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
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
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 (
|
|
2329
|
-
{
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
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(
|
|
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
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
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
|
-
|
|
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
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
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
|
|
2447
|
-
for (PolygonNode poly_node= top_node; (poly_node != null); poly_node = npoly_node)
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
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;
|
|
2467
|
-
|
|
2468
|
-
float
|
|
2469
|
-
|
|
2470
|
-
float
|
|
2471
|
-
|
|
2472
|
-
|
|
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;
|
|
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;
|
|
2482
|
-
|
|
2483
|
-
EdgeNode
|
|
2484
|
-
|
|
2485
|
-
EdgeNode
|
|
2486
|
-
|
|
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(
|
|
2498
|
-
|
|
2499
|
-
|
|
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(
|
|
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(
|
|
2514
|
-
}
|
|
2515
|
-
|
|
2516
|
-
public EdgeNode getNode(
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
EdgeNode
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
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
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
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(
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
|
|
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
|
|
2596
|
-
|
|
2597
|
-
ScanBeamTree
|
|
2598
|
-
|
|
2599
|
-
|
|
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(
|
|
2619
|
-
if(
|
|
2620
|
-
|
|
2621
|
-
|
|
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(
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
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(
|
|
2635
|
-
|
|
2636
|
-
|
|
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;
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
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
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
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;
|
|
2688
|
-
|
|
2689
|
-
float
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
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(
|
|
2707
|
-
{
|
|
2424
|
+
static void print_sbt(float[] sbt) {
|
|
2708
2425
|
System.out.println("");
|
|
2709
|
-
System.out.println("sbt.length="+sbt.length);
|
|
2710
|
-
for(
|
|
2711
|
-
|
|
2712
|
-
|
|
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
|
}
|