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/src/geomerative/RPath.java
CHANGED
|
@@ -28,495 +28,494 @@ import processing.core.PGraphics;
|
|
|
28
28
|
* Paths are ordered lists of commands (RCommand) which define the outlines of
|
|
29
29
|
* shapes. Paths can be self-intersecting.
|
|
30
30
|
*
|
|
31
|
-
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
|
|
31
|
+
RPath
|
|
32
|
+
* Geometry
|
|
33
|
+
* RCommand
|
|
34
|
+
* RPolygon
|
|
35
|
+
|
|
36
36
|
*
|
|
37
37
|
*/
|
|
38
38
|
public class RPath extends RGeomElem {
|
|
39
39
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}
|
|
84
|
-
this.lastPoint = points[0];
|
|
85
|
-
|
|
86
|
-
for (int i = 1; i < points.length; i++) {
|
|
87
|
-
this.addLineTo(points[i]);
|
|
88
|
-
}
|
|
89
|
-
|
|
40
|
+
/**
|
|
41
|
+
*
|
|
42
|
+
*/
|
|
43
|
+
public int type = RGeomElem.SUBSHAPE;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Array of RCommand objects holding the commands of the path.
|
|
47
|
+
*
|
|
48
|
+
commands
|
|
49
|
+
* RCommand
|
|
50
|
+
* countCommands ( )
|
|
51
|
+
*/
|
|
52
|
+
public RCommand[] commands;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Last point from where to add the next command. Initialized to (0, 0).
|
|
56
|
+
*
|
|
57
|
+
lastPoint
|
|
58
|
+
* RPoint
|
|
59
|
+
*
|
|
60
|
+
*/
|
|
61
|
+
public RPoint lastPoint;
|
|
62
|
+
|
|
63
|
+
boolean closed = false;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Create a new empty path.
|
|
67
|
+
*
|
|
68
|
+
RPath
|
|
69
|
+
*/
|
|
70
|
+
public RPath() {
|
|
71
|
+
this.lastPoint = new RPoint();
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Create a new path, given an array of points.
|
|
76
|
+
*
|
|
77
|
+
RPath
|
|
78
|
+
* @param points the points of the new path
|
|
79
|
+
*/
|
|
80
|
+
public RPath(RPoint[] points) {
|
|
81
|
+
if (points == null) {
|
|
82
|
+
return;
|
|
90
83
|
}
|
|
84
|
+
this.lastPoint = points[0];
|
|
91
85
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
*
|
|
95
|
-
* @eexample RPath
|
|
96
|
-
* @param x x coordinate of the first point of the new path
|
|
97
|
-
* @param y y coordinate of the first point of the new path
|
|
98
|
-
*/
|
|
99
|
-
public RPath(float x, float y) {
|
|
100
|
-
this.lastPoint = new RPoint(x, y);
|
|
86
|
+
for (int i = 1; i < points.length; i++) {
|
|
87
|
+
this.addLineTo(points[i]);
|
|
101
88
|
}
|
|
102
89
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Create a new path, given the coordinates of the first point.
|
|
94
|
+
*
|
|
95
|
+
RPath
|
|
96
|
+
* @param x x coordinate of the first point of the new path
|
|
97
|
+
* @param y y coordinate of the first point of the new path
|
|
98
|
+
*/
|
|
99
|
+
public RPath(float x, float y) {
|
|
100
|
+
this.lastPoint = new RPoint(x, y);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Create a new path, given the first point.
|
|
105
|
+
*
|
|
106
|
+
RPath
|
|
107
|
+
* @param p first point of the new path
|
|
108
|
+
*/
|
|
109
|
+
public RPath(RPoint p) {
|
|
110
|
+
this.lastPoint = p;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Copy a path.
|
|
115
|
+
*
|
|
116
|
+
RPath
|
|
117
|
+
* @param s path to be copied
|
|
118
|
+
*/
|
|
119
|
+
public RPath(RPath s) {
|
|
120
|
+
int numCommands = s.countCommands();
|
|
121
|
+
if (numCommands != 0) {
|
|
122
|
+
lastPoint = new RPoint(s.commands[0].startPoint);
|
|
123
|
+
for (int i = 0; i < numCommands; i++) {
|
|
124
|
+
this.append(new RCommand(s.commands[i], lastPoint));
|
|
125
|
+
lastPoint = commands[i].endPoint;
|
|
126
|
+
}
|
|
111
127
|
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
setStyle(s);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
public RPath(RCommand c) {
|
|
134
|
-
this();
|
|
135
|
-
this.addCommand(c);
|
|
128
|
+
closed = s.closed;
|
|
129
|
+
setStyle(s);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
public RPath(RCommand c) {
|
|
133
|
+
this();
|
|
134
|
+
this.addCommand(c);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Use this method to count the number of commands in the contour.
|
|
139
|
+
*
|
|
140
|
+
countCommands
|
|
141
|
+
* @return int, the number commands in the contour
|
|
142
|
+
*/
|
|
143
|
+
public int countCommands() {
|
|
144
|
+
if (this.commands == null) {
|
|
145
|
+
return 0;
|
|
136
146
|
}
|
|
137
147
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
148
|
+
return this.commands.length;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Use this to return the start, control and end points of the path. It
|
|
153
|
+
* returns the points in the way of an array of RPoint.
|
|
154
|
+
*
|
|
155
|
+
getHandles
|
|
156
|
+
* @return RPoint[], the start, control and end points returned in an array.
|
|
157
|
+
*
|
|
158
|
+
*/
|
|
159
|
+
@Override
|
|
160
|
+
public RPoint[] getHandles() {
|
|
161
|
+
int numCommands = countCommands();
|
|
162
|
+
|
|
163
|
+
RPoint[] result = null;
|
|
164
|
+
RPoint[] newresult;
|
|
165
|
+
for (int i = 0; i < numCommands; i++) {
|
|
166
|
+
RPoint[] newPoints = commands[i].getHandles();
|
|
167
|
+
if (newPoints != null) {
|
|
168
|
+
if (result == null) {
|
|
169
|
+
result = new RPoint[newPoints.length];
|
|
170
|
+
System.arraycopy(newPoints, 0, result, 0, newPoints.length);
|
|
171
|
+
} else {
|
|
172
|
+
int overlap = 0;
|
|
173
|
+
if (newPoints[0] == result[result.length - 1]) {
|
|
174
|
+
overlap = 1;
|
|
175
|
+
}
|
|
176
|
+
newresult = new RPoint[result.length + newPoints.length - overlap];
|
|
177
|
+
System.arraycopy(result, 0, newresult, 0, result.length);
|
|
178
|
+
System.arraycopy(newPoints, overlap, newresult, result.length, newPoints.length - overlap);
|
|
179
|
+
result = newresult;
|
|
147
180
|
}
|
|
148
|
-
|
|
149
|
-
return this.commands.length;
|
|
181
|
+
}
|
|
150
182
|
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
RPoint[] newPoints = commands[i].getHandles();
|
|
168
|
-
if (newPoints != null) {
|
|
169
|
-
if (result == null) {
|
|
170
|
-
result = new RPoint[newPoints.length];
|
|
171
|
-
System.arraycopy(newPoints, 0, result, 0, newPoints.length);
|
|
172
|
-
} else {
|
|
173
|
-
int overlap = 0;
|
|
174
|
-
if (newPoints[0] == result[result.length - 1]) {
|
|
175
|
-
overlap = 1;
|
|
176
|
-
}
|
|
177
|
-
newresult = new RPoint[result.length + newPoints.length - overlap];
|
|
178
|
-
System.arraycopy(result, 0, newresult, 0, result.length);
|
|
179
|
-
System.arraycopy(newPoints, overlap, newresult, result.length, newPoints.length - overlap);
|
|
180
|
-
result = newresult;
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
return result;
|
|
183
|
+
return result;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Use this to return the points on the curve. It returns the points in the
|
|
188
|
+
* way of an array of RPoint.
|
|
189
|
+
*
|
|
190
|
+
getPoints
|
|
191
|
+
* @return RPoint[], the vertices returned in an array.
|
|
192
|
+
*
|
|
193
|
+
*/
|
|
194
|
+
@Override
|
|
195
|
+
public RPoint[] getPoints() {
|
|
196
|
+
int numCommands = countCommands();
|
|
197
|
+
if (numCommands == 0) {
|
|
198
|
+
return null;
|
|
185
199
|
}
|
|
186
200
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
@Override
|
|
196
|
-
public RPoint[] getPoints() {
|
|
197
|
-
int numCommands = countCommands();
|
|
198
|
-
if (numCommands == 0) {
|
|
199
|
-
return null;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
// Add the curve points of each command
|
|
203
|
-
// First set the accumulated offset to the value of the inital offset
|
|
204
|
-
RCommand.segmentAccOffset = RCommand.segmentOffset;
|
|
205
|
-
RPoint[] result = null;
|
|
206
|
-
RPoint[] newresult;
|
|
207
|
-
for (int i = 0; i < numCommands; i++) {
|
|
208
|
-
RPoint[] newPoints = commands[i].getPoints(false);
|
|
209
|
-
if (newPoints != null) {
|
|
210
|
-
if (result == null) {
|
|
211
|
-
result = new RPoint[newPoints.length];
|
|
212
|
-
System.arraycopy(newPoints, 0, result, 0, newPoints.length);
|
|
213
|
-
} else {
|
|
214
|
-
// Check for overlapping
|
|
215
|
-
// Overlapping happens when the last point of the last command
|
|
216
|
-
// is the same as the first point of the current command
|
|
217
|
-
RPoint lastp = result[result.length - 1];
|
|
218
|
-
RPoint firstp = newPoints[0];
|
|
219
|
-
int overlap = 0;
|
|
220
|
-
if ((lastp.x == firstp.x) && (lastp.y == firstp.y)) {
|
|
221
|
-
overlap = 1;
|
|
222
|
-
}
|
|
223
|
-
newresult = new RPoint[result.length + newPoints.length - overlap];
|
|
224
|
-
System.arraycopy(result, 0, newresult, 0, result.length);
|
|
225
|
-
System.arraycopy(newPoints, overlap, newresult, result.length, newPoints.length - overlap);
|
|
226
|
-
result = newresult;
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
// Always add last point
|
|
201
|
+
// Add the curve points of each command
|
|
202
|
+
// First set the accumulated offset to the value of the inital offset
|
|
203
|
+
RCommand.segmentAccOffset = RCommand.segmentOffset;
|
|
204
|
+
RPoint[] result = null;
|
|
205
|
+
RPoint[] newresult;
|
|
206
|
+
for (int i = 0; i < numCommands; i++) {
|
|
207
|
+
RPoint[] newPoints = commands[i].getPoints(false);
|
|
208
|
+
if (newPoints != null) {
|
|
231
209
|
if (result == null) {
|
|
232
|
-
|
|
210
|
+
result = new RPoint[newPoints.length];
|
|
211
|
+
System.arraycopy(newPoints, 0, result, 0, newPoints.length);
|
|
212
|
+
} else {
|
|
213
|
+
// Check for overlapping
|
|
214
|
+
// Overlapping happens when the last point of the last command
|
|
215
|
+
// is the same as the first point of the current command
|
|
216
|
+
RPoint lastp = result[result.length - 1];
|
|
217
|
+
RPoint firstp = newPoints[0];
|
|
218
|
+
int overlap = 0;
|
|
219
|
+
if ((lastp.x == firstp.x) && (lastp.y == firstp.y)) {
|
|
220
|
+
overlap = 1;
|
|
221
|
+
}
|
|
222
|
+
newresult = new RPoint[result.length + newPoints.length - overlap];
|
|
223
|
+
System.arraycopy(result, 0, newresult, 0, result.length);
|
|
224
|
+
System.arraycopy(newPoints, overlap, newresult, result.length, newPoints.length - overlap);
|
|
225
|
+
result = newresult;
|
|
233
226
|
}
|
|
234
|
-
|
|
235
|
-
System.arraycopy(result, 0, newresult, 0, result.length);
|
|
236
|
-
newresult[newresult.length - 1] = new RPoint(commands[numCommands - 1].endPoint);
|
|
237
|
-
return newresult;
|
|
227
|
+
}
|
|
238
228
|
}
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
* points in the way of an array of array of RPoint.
|
|
243
|
-
*
|
|
244
|
-
* @eexample RGroup_getPoints
|
|
245
|
-
* @return RPoint[], the points returned in an array.
|
|
246
|
-
*
|
|
247
|
-
*/
|
|
248
|
-
@Override
|
|
249
|
-
public RPoint[][] getPointsInPaths() {
|
|
250
|
-
RPoint[][] result = {this.getPoints()};
|
|
251
|
-
return result;
|
|
229
|
+
// Always add last point
|
|
230
|
+
if (result == null) {
|
|
231
|
+
return result;
|
|
252
232
|
}
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
233
|
+
newresult = new RPoint[result.length + 1];
|
|
234
|
+
System.arraycopy(result, 0, newresult, 0, result.length);
|
|
235
|
+
newresult[newresult.length - 1] = new RPoint(commands[numCommands - 1].endPoint);
|
|
236
|
+
return newresult;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Use this to return the points of each path of the path. It returns the
|
|
241
|
+
* points in the way of an array of array of RPoint.
|
|
242
|
+
*
|
|
243
|
+
RGroup_getPoints
|
|
244
|
+
* @return RPoint[], the points returned in an array.
|
|
245
|
+
*
|
|
246
|
+
*/
|
|
247
|
+
@Override
|
|
248
|
+
public RPoint[][] getPointsInPaths() {
|
|
249
|
+
RPoint[][] result = {this.getPoints()};
|
|
250
|
+
return result;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Use this to return the handles of each path of the path. It returns the
|
|
255
|
+
* handles in the way of an array of array of RPoint.
|
|
256
|
+
*
|
|
257
|
+
RGroup_getHandles
|
|
258
|
+
* @return RPoint[], the handles returned in an array.
|
|
259
|
+
*
|
|
260
|
+
*/
|
|
261
|
+
@Override
|
|
262
|
+
public RPoint[][] getHandlesInPaths() {
|
|
263
|
+
RPoint[][] result = {this.getHandles()};
|
|
264
|
+
return result;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Use this to return the tangents of each path of the path. It returns the
|
|
269
|
+
* tangents in the way of an array of array of RPoint.
|
|
270
|
+
*
|
|
271
|
+
RGroup_getTangents
|
|
272
|
+
* @return RPoint[], the tangents returned in an array.
|
|
273
|
+
*
|
|
274
|
+
*/
|
|
275
|
+
@Override
|
|
276
|
+
public RPoint[][] getTangentsInPaths() {
|
|
277
|
+
RPoint[][] result = {this.getTangents()};
|
|
278
|
+
return result;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
@Override
|
|
282
|
+
protected void calculateCurveLengths() {
|
|
283
|
+
lenCurves = new float[countCommands()];
|
|
284
|
+
lenCurve = 0F;
|
|
285
|
+
for (int i = 0; i < countCommands(); i++) {
|
|
286
|
+
lenCurves[i] = commands[i].getCurveLength();
|
|
287
|
+
lenCurve += lenCurves[i];
|
|
266
288
|
}
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Use this to return the tangents on the curve. It returns the vectors in the
|
|
293
|
+
* way of an array of RPoint.
|
|
294
|
+
*
|
|
295
|
+
getTangents
|
|
296
|
+
* @return RPoint[], the tangent vectors returned in an array.
|
|
297
|
+
*
|
|
298
|
+
*/
|
|
299
|
+
@Override
|
|
300
|
+
public RPoint[] getTangents() {
|
|
301
|
+
int numCommands = countCommands();
|
|
302
|
+
if (numCommands == 0) {
|
|
303
|
+
return null;
|
|
280
304
|
}
|
|
281
305
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
306
|
+
RPoint[] result = null;
|
|
307
|
+
RPoint[] newresult;
|
|
308
|
+
for (int i = 0; i < numCommands; i++) {
|
|
309
|
+
RPoint[] newTangents = commands[i].getTangents();
|
|
310
|
+
if (newTangents != null) {
|
|
311
|
+
if (newTangents.length != 1) {
|
|
312
|
+
int overlap = 1;
|
|
313
|
+
if (result == null) {
|
|
314
|
+
result = new RPoint[newTangents.length];
|
|
315
|
+
System.arraycopy(newTangents, 0, result, 0, newTangents.length);
|
|
316
|
+
} else {
|
|
317
|
+
newresult = new RPoint[result.length + newTangents.length - overlap];
|
|
318
|
+
System.arraycopy(result, 0, newresult, 0, result.length);
|
|
319
|
+
System.arraycopy(newTangents, overlap, newresult, result.length, newTangents.length - overlap);
|
|
320
|
+
result = newresult;
|
|
321
|
+
}
|
|
289
322
|
}
|
|
323
|
+
}
|
|
290
324
|
}
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
RPoint[] result = null;
|
|
308
|
-
RPoint[] newresult;
|
|
309
|
-
for (int i = 0; i < numCommands; i++) {
|
|
310
|
-
RPoint[] newTangents = commands[i].getTangents();
|
|
311
|
-
if (newTangents != null) {
|
|
312
|
-
if (newTangents.length != 1) {
|
|
313
|
-
int overlap = 1;
|
|
314
|
-
if (result == null) {
|
|
315
|
-
result = new RPoint[newTangents.length];
|
|
316
|
-
System.arraycopy(newTangents, 0, result, 0, newTangents.length);
|
|
317
|
-
} else {
|
|
318
|
-
newresult = new RPoint[result.length + newTangents.length - overlap];
|
|
319
|
-
System.arraycopy(result, 0, newresult, 0, result.length);
|
|
320
|
-
System.arraycopy(newTangents, overlap, newresult, result.length, newTangents.length - overlap);
|
|
321
|
-
result = newresult;
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
return result;
|
|
325
|
+
return result;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* Use this to return the intersection points between this path and a command.
|
|
330
|
+
* Returns null if no intersection exists.
|
|
331
|
+
*
|
|
332
|
+
* @param other
|
|
333
|
+
* @return RPoint[], the intersection points returned in an array.
|
|
334
|
+
*
|
|
335
|
+
*/
|
|
336
|
+
public RPoint[] intersectionPoints(RCommand other) {
|
|
337
|
+
int numCommands = countCommands();
|
|
338
|
+
if (numCommands == 0) {
|
|
339
|
+
return null;
|
|
327
340
|
}
|
|
328
341
|
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
RPoint[] result = null;
|
|
344
|
-
RPoint[] newresult;
|
|
345
|
-
for (int i = 0; i < numCommands; i++) {
|
|
346
|
-
RPoint[] newPoints = commands[i].intersectionPoints(other);
|
|
347
|
-
if (newPoints != null) {
|
|
348
|
-
if (result == null) {
|
|
349
|
-
result = new RPoint[newPoints.length];
|
|
350
|
-
System.arraycopy(newPoints, 0, result, 0, newPoints.length);
|
|
351
|
-
} else {
|
|
352
|
-
newresult = new RPoint[result.length + newPoints.length];
|
|
353
|
-
System.arraycopy(result, 0, newresult, 0, result.length);
|
|
354
|
-
System.arraycopy(newPoints, 0, newresult, result.length, newPoints.length);
|
|
355
|
-
result = newresult;
|
|
356
|
-
}
|
|
357
|
-
}
|
|
342
|
+
RPoint[] result = null;
|
|
343
|
+
RPoint[] newresult;
|
|
344
|
+
for (int i = 0; i < numCommands; i++) {
|
|
345
|
+
RPoint[] newPoints = commands[i].intersectionPoints(other);
|
|
346
|
+
if (newPoints != null) {
|
|
347
|
+
if (result == null) {
|
|
348
|
+
result = new RPoint[newPoints.length];
|
|
349
|
+
System.arraycopy(newPoints, 0, result, 0, newPoints.length);
|
|
350
|
+
} else {
|
|
351
|
+
newresult = new RPoint[result.length + newPoints.length];
|
|
352
|
+
System.arraycopy(result, 0, newresult, 0, result.length);
|
|
353
|
+
System.arraycopy(newPoints, 0, newresult, result.length, newPoints.length);
|
|
354
|
+
result = newresult;
|
|
358
355
|
}
|
|
359
|
-
|
|
356
|
+
}
|
|
360
357
|
}
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
RPoint[] result = null;
|
|
379
|
-
RPoint[] newresult;
|
|
380
|
-
|
|
381
|
-
for (int j = 0; j < numOtherCommands; j++) {
|
|
382
|
-
for (int i = 0; i < numCommands; i++) {
|
|
383
|
-
RPoint[] newPoints = commands[i].intersectionPoints(other.commands[j]);
|
|
384
|
-
if (newPoints != null) {
|
|
385
|
-
if (result == null) {
|
|
386
|
-
result = new RPoint[newPoints.length];
|
|
387
|
-
System.arraycopy(newPoints, 0, result, 0, newPoints.length);
|
|
388
|
-
} else {
|
|
389
|
-
newresult = new RPoint[result.length + newPoints.length];
|
|
390
|
-
System.arraycopy(result, 0, newresult, 0, result.length);
|
|
391
|
-
System.arraycopy(newPoints, 0, newresult, result.length, newPoints.length);
|
|
392
|
-
result = newresult;
|
|
393
|
-
}
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
return result;
|
|
358
|
+
return result;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* Use this to return the intersection points between two paths. Returns null
|
|
363
|
+
* if no intersection exists.
|
|
364
|
+
*
|
|
365
|
+
* @param other
|
|
366
|
+
* @return RPoint[], the intersection points returned in an array.
|
|
367
|
+
*
|
|
368
|
+
*/
|
|
369
|
+
public RPoint[] intersectionPoints(RPath other) {
|
|
370
|
+
int numCommands = countCommands();
|
|
371
|
+
int numOtherCommands = other.countCommands();
|
|
372
|
+
|
|
373
|
+
if (numCommands == 0) {
|
|
374
|
+
return null;
|
|
399
375
|
}
|
|
400
376
|
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
377
|
+
RPoint[] result = null;
|
|
378
|
+
RPoint[] newresult;
|
|
379
|
+
|
|
380
|
+
for (int j = 0; j < numOtherCommands; j++) {
|
|
381
|
+
for (int i = 0; i < numCommands; i++) {
|
|
382
|
+
RPoint[] newPoints = commands[i].intersectionPoints(other.commands[j]);
|
|
383
|
+
if (newPoints != null) {
|
|
384
|
+
if (result == null) {
|
|
385
|
+
result = new RPoint[newPoints.length];
|
|
386
|
+
System.arraycopy(newPoints, 0, result, 0, newPoints.length);
|
|
387
|
+
} else {
|
|
388
|
+
newresult = new RPoint[result.length + newPoints.length];
|
|
389
|
+
System.arraycopy(result, 0, newresult, 0, result.length);
|
|
390
|
+
System.arraycopy(newPoints, 0, newresult, result.length, newPoints.length);
|
|
391
|
+
result = newresult;
|
|
392
|
+
}
|
|
413
393
|
}
|
|
394
|
+
}
|
|
395
|
+
}
|
|
414
396
|
|
|
415
|
-
|
|
416
|
-
|
|
397
|
+
return result;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
/**
|
|
401
|
+
* Use this to find the closest or intersection points between this path and a
|
|
402
|
+
* command.
|
|
403
|
+
*
|
|
404
|
+
* @param other
|
|
405
|
+
* @return RPoint[], the intersection points returned in an array.
|
|
406
|
+
*
|
|
407
|
+
*/
|
|
408
|
+
public RClosest closestPoints(RCommand other) {
|
|
409
|
+
int numCommands = countCommands();
|
|
410
|
+
if (numCommands == 0) {
|
|
411
|
+
return null;
|
|
412
|
+
}
|
|
417
413
|
|
|
418
|
-
|
|
414
|
+
// TODO: get here the max value of an integer
|
|
415
|
+
float minDist = 100000;
|
|
419
416
|
|
|
420
|
-
|
|
421
|
-
RClosest currResult = commands[i].closestPoints(other);
|
|
417
|
+
RClosest result = new RClosest();
|
|
422
418
|
|
|
423
|
-
|
|
424
|
-
|
|
419
|
+
for (int i = 0; i < numCommands; i++) {
|
|
420
|
+
RClosest currResult = commands[i].closestPoints(other);
|
|
425
421
|
|
|
426
|
-
|
|
422
|
+
result.update(currResult);
|
|
427
423
|
}
|
|
428
424
|
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
425
|
+
return result;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
/**
|
|
429
|
+
* Use this to return the intersection points between two paths. Returns null
|
|
430
|
+
* if no intersection exists.
|
|
431
|
+
*
|
|
432
|
+
* @param other
|
|
433
|
+
* @return RPoint[], the intersection points returned in an array.
|
|
434
|
+
*
|
|
435
|
+
*/
|
|
436
|
+
public RClosest closestPoints(RPath other) {
|
|
437
|
+
int numCommands = countCommands();
|
|
438
|
+
int numOtherCommands = other.countCommands();
|
|
439
|
+
|
|
440
|
+
if (numCommands == 0) {
|
|
441
|
+
return null;
|
|
442
|
+
}
|
|
447
443
|
|
|
448
|
-
|
|
444
|
+
// TODO: get here the max value of an integer
|
|
445
|
+
float minDist = 100000;
|
|
449
446
|
|
|
450
|
-
|
|
451
|
-
for (int i = 0; i < numCommands; i++) {
|
|
452
|
-
RClosest currResult = commands[i].closestPoints(other.commands[j]);
|
|
453
|
-
result.update(currResult);
|
|
454
|
-
}
|
|
455
|
-
}
|
|
447
|
+
RClosest result = new RClosest();
|
|
456
448
|
|
|
457
|
-
|
|
449
|
+
for (int j = 0; j < numOtherCommands; j++) {
|
|
450
|
+
for (int i = 0; i < numCommands; i++) {
|
|
451
|
+
RClosest currResult = commands[i].closestPoints(other.commands[j]);
|
|
452
|
+
result.update(currResult);
|
|
453
|
+
}
|
|
458
454
|
}
|
|
459
455
|
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
}
|
|
480
|
-
if (t == 1.0F) {
|
|
481
|
-
return commands[numCommands - 1].getPoint(1F);
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
float[] indAndAdv = indAndAdvAt(t);
|
|
485
|
-
int indOfElement = (int) (indAndAdv[0]);
|
|
486
|
-
float advOfElement = indAndAdv[1];
|
|
456
|
+
return result;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
/**
|
|
460
|
+
* Return a specific point on the curve. It returns the RPoint for a given
|
|
461
|
+
* advancement parameter t on the curve.
|
|
462
|
+
*
|
|
463
|
+
getPoint
|
|
464
|
+
* @param t the parameter of advancement on the curve. t must have values
|
|
465
|
+
* between 0 and 1.
|
|
466
|
+
* @return RPoint, the vertice returned.
|
|
467
|
+
*
|
|
468
|
+
*/
|
|
469
|
+
@Override
|
|
470
|
+
public RPoint getPoint(float t) {
|
|
471
|
+
int numCommands = countCommands();
|
|
472
|
+
if (numCommands == 0) {
|
|
473
|
+
return new RPoint();
|
|
474
|
+
}
|
|
487
475
|
|
|
488
|
-
|
|
476
|
+
if (t == 0.0F) {
|
|
477
|
+
return commands[0].getPoint(0F);
|
|
478
|
+
}
|
|
479
|
+
if (t == 1.0F) {
|
|
480
|
+
return commands[numCommands - 1].getPoint(1F);
|
|
489
481
|
}
|
|
490
482
|
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
483
|
+
float[] indAndAdv = indAndAdvAt(t);
|
|
484
|
+
int indOfElement = (int) (indAndAdv[0]);
|
|
485
|
+
float advOfElement = indAndAdv[1];
|
|
486
|
+
|
|
487
|
+
return commands[indOfElement].getPoint(advOfElement);
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
/**
|
|
491
|
+
* Use this to return a specific tangent on the curve. It returns the RPoint
|
|
492
|
+
* tangent for a given advancement parameter t on the curve.
|
|
493
|
+
*
|
|
494
|
+
getPoint
|
|
495
|
+
* @param t float, the parameter of advancement on the curve. t must have
|
|
496
|
+
* values between 0 and 1.
|
|
497
|
+
* @return RPoint, the vertice returned.
|
|
498
|
+
*
|
|
499
|
+
*/
|
|
500
|
+
@Override
|
|
501
|
+
public RPoint getTangent(float t) {
|
|
502
|
+
int numCommands = countCommands();
|
|
503
|
+
if (numCommands == 0) {
|
|
504
|
+
return new RPoint();
|
|
505
|
+
}
|
|
507
506
|
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
507
|
+
if (t == 0.0F) {
|
|
508
|
+
return commands[0].getTangent(0F);
|
|
509
|
+
}
|
|
510
|
+
if (t == 1.0F) {
|
|
511
|
+
return commands[numCommands - 1].getTangent(1F);
|
|
512
|
+
}
|
|
514
513
|
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
514
|
+
float[] indAndAdv = indAndAdvAt(t);
|
|
515
|
+
int indOfElement = (int) (indAndAdv[0]);
|
|
516
|
+
float advOfElement = indAndAdv[1];
|
|
518
517
|
|
|
519
|
-
|
|
518
|
+
/* This takes the medium between two intersecting commands, sometimes this is not wanted
|
|
520
519
|
if(advOfElement==1.0F){
|
|
521
520
|
int indNextCommand = (indOfElement + 1) % numCommands;
|
|
522
521
|
result = commands[indOfElement].getTangent(advOfElement);
|
|
@@ -532,453 +531,452 @@ public class RPath extends RGeomElem {
|
|
|
532
531
|
}else{
|
|
533
532
|
result = commands[indOfElement].getTangent(advOfElement);
|
|
534
533
|
}
|
|
535
|
-
*/
|
|
536
|
-
return commands[indOfElement].getTangent(advOfElement);
|
|
537
|
-
}
|
|
538
|
-
|
|
539
|
-
/**
|
|
540
|
-
* Use this to return a specific tangent on the curve. It returns true if
|
|
541
|
-
* the point passed as a parameter is inside the path. Implementation taken
|
|
542
|
-
* from:
|
|
543
|
-
* http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
|
|
544
|
-
*
|
|
545
|
-
* @param p the point for which to test containement..
|
|
546
|
-
* @return boolean, true if the point is in the path.
|
|
547
|
-
*
|
|
548
534
|
*/
|
|
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
|
-
boolean c = false;
|
|
577
|
-
for (i = 0, j = nvert - 1; i < nvert; j = i++) {
|
|
578
|
-
if (((verts[i].y > testy) != (verts[j].y > testy))
|
|
579
|
-
&& (testx < (verts[j].x - verts[i].x) * (testy - verts[i].y) / (verts[j].y - verts[i].y) + verts[i].x)) {
|
|
580
|
-
c = !c;
|
|
581
|
-
}
|
|
582
|
-
}
|
|
583
|
-
return c;
|
|
535
|
+
return commands[indOfElement].getTangent(advOfElement);
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
/**
|
|
539
|
+
* Use this to return a specific tangent on the curve. It returns true if the
|
|
540
|
+
* point passed as a parameter is inside the path. Implementation taken from:
|
|
541
|
+
* http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
|
|
542
|
+
*
|
|
543
|
+
* @param p the point for which to test containement..
|
|
544
|
+
* @return boolean, true if the point is in the path.
|
|
545
|
+
*
|
|
546
|
+
*/
|
|
547
|
+
@Override
|
|
548
|
+
public boolean contains(RPoint p) {
|
|
549
|
+
float testx = p.x;
|
|
550
|
+
float testy = p.y;
|
|
551
|
+
|
|
552
|
+
// Test for containment in bounding box
|
|
553
|
+
RRectangle bbox = getBounds();
|
|
554
|
+
float xmin = bbox.getMinX();
|
|
555
|
+
float xmax = bbox.getMaxX();
|
|
556
|
+
|
|
557
|
+
float ymin = bbox.getMinY();
|
|
558
|
+
float ymax = bbox.getMaxY();
|
|
559
|
+
|
|
560
|
+
if ((testx < xmin) || (testx > xmax) || (testy < ymin) || (testy > ymax)) {
|
|
561
|
+
return false;
|
|
584
562
|
}
|
|
585
563
|
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
*
|
|
589
|
-
* @eexample insertHandle
|
|
590
|
-
* @param t float, the parameter of advancement on the curve. t must have
|
|
591
|
-
* values between 0 and 1.
|
|
592
|
-
*
|
|
593
|
-
*/
|
|
594
|
-
public void insertHandle(float t) {
|
|
595
|
-
if ((t == 0F) || (t == 1F)) {
|
|
596
|
-
return;
|
|
597
|
-
}
|
|
598
|
-
|
|
599
|
-
float[] indAndAdv = indAndAdvAt(t);
|
|
600
|
-
int indOfElement = (int) (indAndAdv[0]);
|
|
601
|
-
float advOfElement = indAndAdv[1];
|
|
602
|
-
|
|
603
|
-
// Split the affected command and reconstruct each of the shapes
|
|
604
|
-
RCommand[] splittedCommands = commands[indOfElement].split(advOfElement);
|
|
605
|
-
|
|
606
|
-
if (splittedCommands[0] == null || splittedCommands[1] == null) {
|
|
607
|
-
return;
|
|
608
|
-
}
|
|
609
|
-
|
|
610
|
-
// Extract the splitted command
|
|
611
|
-
extract(indOfElement);
|
|
612
|
-
|
|
613
|
-
// Insert the splittedCommands
|
|
614
|
-
insert(splittedCommands[1], indOfElement);
|
|
615
|
-
insert(splittedCommands[0], indOfElement);
|
|
564
|
+
// Test for containment in path
|
|
565
|
+
RPoint[] verts = getPoints();
|
|
616
566
|
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
lenCurve = -1F;
|
|
567
|
+
if (verts == null) {
|
|
568
|
+
return false;
|
|
620
569
|
}
|
|
621
570
|
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
extract(i);
|
|
647
|
-
|
|
648
|
-
// Insert the splittedCommands
|
|
649
|
-
insert(splittedCommands[1], i);
|
|
650
|
-
insert(splittedCommands[0], i);
|
|
651
|
-
}
|
|
652
|
-
|
|
653
|
-
// Clear the cache
|
|
654
|
-
lenCurves = null;
|
|
655
|
-
lenCurve = -1F;
|
|
571
|
+
int nvert = verts.length;
|
|
572
|
+
int i;
|
|
573
|
+
int j;
|
|
574
|
+
boolean c = false;
|
|
575
|
+
for (i = 0, j = nvert - 1; i < nvert; j = i++) {
|
|
576
|
+
if (((verts[i].y > testy) != (verts[j].y > testy))
|
|
577
|
+
&& (testx < (verts[j].x - verts[i].x) * (testy - verts[i].y) / (verts[j].y - verts[i].y) + verts[i].x)) {
|
|
578
|
+
c = !c;
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
return c;
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
/**
|
|
585
|
+
* Use this to insert a split point into the path.
|
|
586
|
+
*
|
|
587
|
+
insertHandle
|
|
588
|
+
* @param t float, the parameter of advancement on the curve. t must have
|
|
589
|
+
* values between 0 and 1.
|
|
590
|
+
*
|
|
591
|
+
*/
|
|
592
|
+
public void insertHandle(float t) {
|
|
593
|
+
if ((t == 0F) || (t == 1F)) {
|
|
594
|
+
return;
|
|
656
595
|
}
|
|
657
596
|
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
* @eexample split
|
|
662
|
-
* @param t float, the parameter of advancement on the curve. t must have
|
|
663
|
-
* values between 0 and 1.
|
|
664
|
-
* @return RPath[], an array of two RPath.
|
|
665
|
-
*
|
|
666
|
-
*/
|
|
667
|
-
public RPath[] split(float t) {
|
|
668
|
-
RPath[] result = new RPath[2];
|
|
669
|
-
|
|
670
|
-
int numCommands = countCommands();
|
|
671
|
-
if (numCommands == 0) {
|
|
672
|
-
return null;
|
|
673
|
-
}
|
|
674
|
-
|
|
675
|
-
if (t == 0.0F) {
|
|
676
|
-
result[0] = new RPath();
|
|
677
|
-
result[1] = new RPath(this);
|
|
678
|
-
result[0].setStyle(this);
|
|
679
|
-
result[1].setStyle(this);
|
|
680
|
-
|
|
681
|
-
return result;
|
|
682
|
-
}
|
|
683
|
-
|
|
684
|
-
if (t == 1.0F) {
|
|
685
|
-
result[0] = new RPath(this);
|
|
686
|
-
result[1] = new RPath();
|
|
687
|
-
result[0].setStyle(this);
|
|
688
|
-
result[1].setStyle(this);
|
|
689
|
-
|
|
690
|
-
return result;
|
|
691
|
-
}
|
|
692
|
-
|
|
693
|
-
float[] indAndAdv = indAndAdvAt(t);
|
|
694
|
-
int indOfElement = (int) (indAndAdv[0]);
|
|
695
|
-
float advOfElement = indAndAdv[1];
|
|
696
|
-
|
|
697
|
-
// Split the affected command and reconstruct each of the shapes
|
|
698
|
-
RCommand[] splittedCommands = commands[indOfElement].split(advOfElement);
|
|
699
|
-
|
|
700
|
-
result[0] = new RPath();
|
|
701
|
-
for (int i = 0; i < indOfElement; i++) {
|
|
702
|
-
result[0].addCommand(new RCommand(commands[i]));
|
|
703
|
-
}
|
|
704
|
-
result[0].addCommand(new RCommand(splittedCommands[0]));
|
|
705
|
-
result[0].setStyle(this);
|
|
597
|
+
float[] indAndAdv = indAndAdvAt(t);
|
|
598
|
+
int indOfElement = (int) (indAndAdv[0]);
|
|
599
|
+
float advOfElement = indAndAdv[1];
|
|
706
600
|
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
result[1].addCommand(new RCommand(commands[i]));
|
|
710
|
-
}
|
|
711
|
-
result[1].addCommand(new RCommand(splittedCommands[1]));
|
|
712
|
-
result[1].setStyle(this);
|
|
601
|
+
// Split the affected command and reconstruct each of the shapes
|
|
602
|
+
RCommand[] splittedCommands = commands[indOfElement].split(advOfElement);
|
|
713
603
|
|
|
714
|
-
|
|
604
|
+
if (splittedCommands[0] == null || splittedCommands[1] == null) {
|
|
605
|
+
return;
|
|
715
606
|
}
|
|
716
607
|
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
608
|
+
// Extract the splitted command
|
|
609
|
+
extract(indOfElement);
|
|
610
|
+
|
|
611
|
+
// Insert the splittedCommands
|
|
612
|
+
insert(splittedCommands[1], indOfElement);
|
|
613
|
+
insert(splittedCommands[0], indOfElement);
|
|
614
|
+
|
|
615
|
+
// Clear the cache
|
|
616
|
+
lenCurves = null;
|
|
617
|
+
lenCurve = -1F;
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
/**
|
|
621
|
+
* Use this to insert a split point into each command of the path.
|
|
622
|
+
*
|
|
623
|
+
insertHandleInPaths
|
|
624
|
+
* @param t float, the parameter of advancement on the curve. t must have
|
|
625
|
+
* values between 0 and 1.
|
|
626
|
+
*
|
|
627
|
+
*/
|
|
628
|
+
public void insertHandleInPaths(float t) {
|
|
629
|
+
if ((t == 0F) || (t == 1F)) {
|
|
630
|
+
return;
|
|
729
631
|
}
|
|
730
632
|
|
|
731
|
-
|
|
732
|
-
* Use this method to draw the path.
|
|
733
|
-
*
|
|
734
|
-
* @eexample drawPath
|
|
735
|
-
* @param g PGraphics, the graphics object on which to draw the path
|
|
736
|
-
*/
|
|
737
|
-
@Override
|
|
738
|
-
public void draw(PGraphics g) {
|
|
739
|
-
countCommands();
|
|
633
|
+
int numCommands = countCommands();
|
|
740
634
|
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
635
|
+
for (int i = 0; i < numCommands * 2; i += 2) {
|
|
636
|
+
// Split the affected command and reconstruct each of the shapes
|
|
637
|
+
RCommand[] splittedCommands = commands[i].split(t);
|
|
744
638
|
|
|
745
|
-
|
|
639
|
+
if (splittedCommands[0] == null || splittedCommands[1] == null) {
|
|
640
|
+
return;
|
|
641
|
+
}
|
|
746
642
|
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
}
|
|
750
|
-
|
|
751
|
-
g.beginShape();
|
|
752
|
-
for (RPoint point : points) {
|
|
753
|
-
g.vertex(point.x, point.y);
|
|
754
|
-
}
|
|
755
|
-
g.endShape(closed ? PConstants.CLOSE : PConstants.OPEN);
|
|
643
|
+
// Extract the splitted command
|
|
644
|
+
extract(i);
|
|
756
645
|
|
|
757
|
-
|
|
758
|
-
|
|
646
|
+
// Insert the splittedCommands
|
|
647
|
+
insert(splittedCommands[1], i);
|
|
648
|
+
insert(splittedCommands[0], i);
|
|
759
649
|
}
|
|
760
650
|
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
}
|
|
782
|
-
g.endShape(closed ? PConstants.CLOSE : PConstants.OPEN);
|
|
783
|
-
|
|
784
|
-
// Restore the user set segmentator
|
|
785
|
-
RCommand.setSegmentator(lastSegmentator);
|
|
651
|
+
// Clear the cache
|
|
652
|
+
lenCurves = null;
|
|
653
|
+
lenCurve = -1F;
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
/**
|
|
657
|
+
* Use this to split a path into two separate new paths.
|
|
658
|
+
*
|
|
659
|
+
split
|
|
660
|
+
* @param t float, the parameter of advancement on the curve. t must have
|
|
661
|
+
* values between 0 and 1.
|
|
662
|
+
* @return RPath[], an array of two RPath.
|
|
663
|
+
*
|
|
664
|
+
*/
|
|
665
|
+
public RPath[] split(float t) {
|
|
666
|
+
RPath[] result = new RPath[2];
|
|
667
|
+
|
|
668
|
+
int numCommands = countCommands();
|
|
669
|
+
if (numCommands == 0) {
|
|
670
|
+
return null;
|
|
786
671
|
}
|
|
787
672
|
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
* @invisible
|
|
794
|
-
*/
|
|
795
|
-
public final void addCommand(RCommand p) {
|
|
796
|
-
this.append(p);
|
|
673
|
+
if (t == 0.0F) {
|
|
674
|
+
result[0] = new RPath();
|
|
675
|
+
result[1] = new RPath(this);
|
|
676
|
+
result[0].setStyle(this);
|
|
677
|
+
result[1].setStyle(this);
|
|
797
678
|
|
|
798
|
-
|
|
679
|
+
return result;
|
|
799
680
|
}
|
|
800
681
|
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
* @param cp1 first control point
|
|
807
|
-
* @param cp2 second control point
|
|
808
|
-
* @param end end point
|
|
809
|
-
*/
|
|
810
|
-
public void addBezierTo(RPoint cp1, RPoint cp2, RPoint end) {
|
|
811
|
-
this.addCommand(RCommand.createBezier4(lastPoint, cp1, cp2, end));
|
|
812
|
-
}
|
|
813
|
-
|
|
814
|
-
/**
|
|
815
|
-
* Add a new cubic bezier to the path. The first point of the bezier will be
|
|
816
|
-
* the last point added to the path.
|
|
817
|
-
*
|
|
818
|
-
* @eexample addBezierTo
|
|
819
|
-
* @param cp1x the x coordinate of the first control point
|
|
820
|
-
* @param cp1y the y coordinate of the first control point
|
|
821
|
-
* @param cp2x the x coordinate of the second control point
|
|
822
|
-
* @param cp2y the y coordinate of the second control point
|
|
823
|
-
* @param endx the x coordinate of the end point
|
|
824
|
-
* @param endy the y coordinate of the end point
|
|
825
|
-
*/
|
|
826
|
-
public void addBezierTo(float cp1x, float cp1y, float cp2x, float cp2y, float endx, float endy) {
|
|
827
|
-
RPoint cp1 = new RPoint(cp1x, cp1y);
|
|
828
|
-
RPoint cp2 = new RPoint(cp2x, cp2y);
|
|
829
|
-
RPoint end = new RPoint(endx, endy);
|
|
682
|
+
if (t == 1.0F) {
|
|
683
|
+
result[0] = new RPath(this);
|
|
684
|
+
result[1] = new RPath();
|
|
685
|
+
result[0].setStyle(this);
|
|
686
|
+
result[1].setStyle(this);
|
|
830
687
|
|
|
831
|
-
|
|
688
|
+
return result;
|
|
832
689
|
}
|
|
833
690
|
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
*
|
|
838
|
-
* @eexample addQuadTo
|
|
839
|
-
* @param cp1 first control point
|
|
840
|
-
* @param end end point
|
|
841
|
-
*/
|
|
842
|
-
public void addQuadTo(RPoint cp1, RPoint end) {
|
|
843
|
-
this.addCommand(RCommand.createBezier3(lastPoint, cp1, end));
|
|
844
|
-
}
|
|
691
|
+
float[] indAndAdv = indAndAdvAt(t);
|
|
692
|
+
int indOfElement = (int) (indAndAdv[0]);
|
|
693
|
+
float advOfElement = indAndAdv[1];
|
|
845
694
|
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
* will be the last point added to the path.
|
|
849
|
-
*
|
|
850
|
-
* @eexample addQuadTo
|
|
851
|
-
* @param cp1x the x coordinate of the first control point
|
|
852
|
-
* @param cp1y the y coordinate of the first control point
|
|
853
|
-
* @param endx the x coordinate of the end point
|
|
854
|
-
* @param endy the y coordinate of the end point
|
|
855
|
-
*/
|
|
856
|
-
public void addQuadTo(float cp1x, float cp1y, float endx, float endy) {
|
|
857
|
-
RPoint cp1 = new RPoint(cp1x, cp1y);
|
|
858
|
-
RPoint end = new RPoint(endx, endy);
|
|
695
|
+
// Split the affected command and reconstruct each of the shapes
|
|
696
|
+
RCommand[] splittedCommands = commands[indOfElement].split(advOfElement);
|
|
859
697
|
|
|
860
|
-
|
|
698
|
+
result[0] = new RPath();
|
|
699
|
+
for (int i = 0; i < indOfElement; i++) {
|
|
700
|
+
result[0].addCommand(new RCommand(commands[i]));
|
|
861
701
|
}
|
|
702
|
+
result[0].addCommand(new RCommand(splittedCommands[0]));
|
|
703
|
+
result[0].setStyle(this);
|
|
862
704
|
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
*
|
|
867
|
-
* @eexample addLineTo
|
|
868
|
-
* @param end end point
|
|
869
|
-
*/
|
|
870
|
-
public final void addLineTo(RPoint end) {
|
|
871
|
-
this.addCommand(RCommand.createLine(lastPoint, end));
|
|
705
|
+
result[1] = new RPath();
|
|
706
|
+
for (int i = indOfElement + 1; i < countCommands(); i++) {
|
|
707
|
+
result[1].addCommand(new RCommand(commands[i]));
|
|
872
708
|
}
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
709
|
+
result[1].addCommand(new RCommand(splittedCommands[1]));
|
|
710
|
+
result[1].setStyle(this);
|
|
711
|
+
|
|
712
|
+
return result;
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
public void polygonize() {
|
|
716
|
+
RPoint[] points = getPoints();
|
|
717
|
+
|
|
718
|
+
if (points == null) {
|
|
719
|
+
this.commands = null;
|
|
720
|
+
} else {
|
|
721
|
+
RPath result = new RPath(points[0]);
|
|
722
|
+
for (int i = 1; i < points.length; i++) {
|
|
723
|
+
result.addLineTo(points[i]);
|
|
724
|
+
}
|
|
725
|
+
this.commands = result.commands;
|
|
885
726
|
}
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
/**
|
|
730
|
+
* Use this method to draw the path.
|
|
731
|
+
*
|
|
732
|
+
drawPath
|
|
733
|
+
* @param g PGraphics, the graphics object on which to draw the path
|
|
734
|
+
*/
|
|
735
|
+
@Override
|
|
736
|
+
public void draw(PGraphics g) {
|
|
737
|
+
countCommands();
|
|
738
|
+
|
|
739
|
+
// By default always draw with an adaptative segmentator
|
|
740
|
+
int lastSegmentator = RCommand.segmentType;
|
|
741
|
+
RCommand.setSegmentator(RCommand.ADAPTATIVE);
|
|
742
|
+
|
|
743
|
+
RPoint[] points = getPoints();
|
|
744
|
+
|
|
745
|
+
if (points == null) {
|
|
746
|
+
return;
|
|
900
747
|
}
|
|
901
748
|
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
@Override
|
|
906
|
-
public RPolygon toPolygon() {
|
|
907
|
-
return this.toShape().toPolygon();
|
|
749
|
+
g.beginShape();
|
|
750
|
+
for (RPoint point : points) {
|
|
751
|
+
g.vertex(point.x, point.y);
|
|
908
752
|
}
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
753
|
+
g.endShape(closed ? PConstants.CLOSE : PConstants.OPEN);
|
|
754
|
+
|
|
755
|
+
// Restore the user set segmentator
|
|
756
|
+
RCommand.setSegmentator(lastSegmentator);
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
/**
|
|
760
|
+
*
|
|
761
|
+
* @param g
|
|
762
|
+
*/
|
|
763
|
+
@Override
|
|
764
|
+
public void draw(PApplet g) {
|
|
765
|
+
countCommands();
|
|
766
|
+
|
|
767
|
+
// By default always draw with an adaptative segmentator
|
|
768
|
+
int lastSegmentator = RCommand.segmentType;
|
|
769
|
+
RCommand.setSegmentator(RCommand.ADAPTATIVE);
|
|
770
|
+
|
|
771
|
+
RPoint[] points = getPoints();
|
|
772
|
+
RCommand.setSegmentator(lastSegmentator);
|
|
773
|
+
if (points == null) {
|
|
774
|
+
return;
|
|
916
775
|
}
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
776
|
+
g.beginShape();
|
|
777
|
+
for (RPoint point : points) {
|
|
778
|
+
g.vertex(point.x, point.y);
|
|
779
|
+
}
|
|
780
|
+
g.endShape(closed ? PConstants.CLOSE : PConstants.OPEN);
|
|
781
|
+
|
|
782
|
+
// Restore the user set segmentator
|
|
783
|
+
RCommand.setSegmentator(lastSegmentator);
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
/**
|
|
787
|
+
* Use this method to add new commands to the contour.
|
|
788
|
+
*
|
|
789
|
+
* @param p
|
|
790
|
+
addCommand
|
|
791
|
+
*
|
|
792
|
+
*/
|
|
793
|
+
public final void addCommand(RCommand p) {
|
|
794
|
+
this.append(p);
|
|
795
|
+
|
|
796
|
+
lastPoint = commands[commands.length - 1].endPoint;
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
/**
|
|
800
|
+
* Add a new cubic bezier to the path. The first point of the bezier will be
|
|
801
|
+
* the last point added to the path.
|
|
802
|
+
*
|
|
803
|
+
addBezierTo
|
|
804
|
+
* @param cp1 first control point
|
|
805
|
+
* @param cp2 second control point
|
|
806
|
+
* @param end end point
|
|
807
|
+
*/
|
|
808
|
+
public void addBezierTo(RPoint cp1, RPoint cp2, RPoint end) {
|
|
809
|
+
this.addCommand(RCommand.createBezier4(lastPoint, cp1, cp2, end));
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
/**
|
|
813
|
+
* Add a new cubic bezier to the path. The first point of the bezier will be
|
|
814
|
+
* the last point added to the path.
|
|
815
|
+
*
|
|
816
|
+
addBezierTo
|
|
817
|
+
* @param cp1x the x coordinate of the first control point
|
|
818
|
+
* @param cp1y the y coordinate of the first control point
|
|
819
|
+
* @param cp2x the x coordinate of the second control point
|
|
820
|
+
* @param cp2y the y coordinate of the second control point
|
|
821
|
+
* @param endx the x coordinate of the end point
|
|
822
|
+
* @param endy the y coordinate of the end point
|
|
823
|
+
*/
|
|
824
|
+
public void addBezierTo(float cp1x, float cp1y, float cp2x, float cp2y, float endx, float endy) {
|
|
825
|
+
RPoint cp1 = new RPoint(cp1x, cp1y);
|
|
826
|
+
RPoint cp2 = new RPoint(cp2x, cp2y);
|
|
827
|
+
RPoint end = new RPoint(endx, endy);
|
|
828
|
+
|
|
829
|
+
addBezierTo(cp1, cp2, end);
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
/**
|
|
833
|
+
* Add a new quadratic bezier to the path. The first point of the bezier will
|
|
834
|
+
* be the last point added to the path.
|
|
835
|
+
*
|
|
836
|
+
addQuadTo
|
|
837
|
+
* @param cp1 first control point
|
|
838
|
+
* @param end end point
|
|
839
|
+
*/
|
|
840
|
+
public void addQuadTo(RPoint cp1, RPoint end) {
|
|
841
|
+
this.addCommand(RCommand.createBezier3(lastPoint, cp1, end));
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
/**
|
|
845
|
+
* Add a new quadratic bezier to the path. The first point of the bezier will
|
|
846
|
+
* be the last point added to the path.
|
|
847
|
+
*
|
|
848
|
+
addQuadTo
|
|
849
|
+
* @param cp1x the x coordinate of the first control point
|
|
850
|
+
* @param cp1y the y coordinate of the first control point
|
|
851
|
+
* @param endx the x coordinate of the end point
|
|
852
|
+
* @param endy the y coordinate of the end point
|
|
853
|
+
*/
|
|
854
|
+
public void addQuadTo(float cp1x, float cp1y, float endx, float endy) {
|
|
855
|
+
RPoint cp1 = new RPoint(cp1x, cp1y);
|
|
856
|
+
RPoint end = new RPoint(endx, endy);
|
|
857
|
+
|
|
858
|
+
addQuadTo(cp1, end);
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
/**
|
|
862
|
+
* Add a new line to the path. The first point of the line will be the last
|
|
863
|
+
* point added to the path.
|
|
864
|
+
*
|
|
865
|
+
addLineTo
|
|
866
|
+
* @param end end point
|
|
867
|
+
*/
|
|
868
|
+
public final void addLineTo(RPoint end) {
|
|
869
|
+
this.addCommand(RCommand.createLine(lastPoint, end));
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
/**
|
|
873
|
+
* Add a new line to the path. The first point of the line will be the last
|
|
874
|
+
* point added to the path.
|
|
875
|
+
*
|
|
876
|
+
addLineTo
|
|
877
|
+
* @param endx the x coordinate of the end point
|
|
878
|
+
* @param endy the y coordinate of the end point
|
|
879
|
+
*/
|
|
880
|
+
public void addLineTo(float endx, float endy) {
|
|
881
|
+
RPoint end = new RPoint(endx, endy);
|
|
882
|
+
addLineTo(end);
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
public void addClose() {
|
|
886
|
+
if (commands == null) {
|
|
887
|
+
return;
|
|
924
888
|
}
|
|
925
889
|
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
*/
|
|
932
|
-
@Override
|
|
933
|
-
public int getType() {
|
|
934
|
-
return type;
|
|
890
|
+
if ((commands[commands.length - 1].endPoint.x == commands[0].startPoint.x) && (commands[commands.length - 1].endPoint.y == commands[0].startPoint.y)) {
|
|
891
|
+
commands[commands.length - 1].endPoint = new RPoint(commands[0].startPoint.x, commands[0].startPoint.y);
|
|
892
|
+
lastPoint = commands[commands.length - 1].endPoint;
|
|
893
|
+
} else {
|
|
894
|
+
addLineTo(new RPoint(commands[0].startPoint.x, commands[0].startPoint.y));
|
|
935
895
|
}
|
|
936
896
|
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
897
|
+
closed = true;
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
/**
|
|
901
|
+
* @return
|
|
902
|
+
*/
|
|
903
|
+
@Override
|
|
904
|
+
public RPolygon toPolygon() {
|
|
905
|
+
return this.toShape().toPolygon();
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
/**
|
|
909
|
+
* @return
|
|
910
|
+
*/
|
|
911
|
+
@Override
|
|
912
|
+
public RShape toShape() {
|
|
913
|
+
return new RShape(this);
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
/**
|
|
917
|
+
* @return
|
|
918
|
+
*/
|
|
919
|
+
@Override
|
|
920
|
+
public RMesh toMesh() {
|
|
921
|
+
return this.toPolygon().toMesh();
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
/**
|
|
925
|
+
* Use this method to get the type of element this is.
|
|
926
|
+
*
|
|
927
|
+
RPolygon_getType
|
|
928
|
+
* @return int, will allways return RGeomElem.POLYGON
|
|
929
|
+
*/
|
|
930
|
+
@Override
|
|
931
|
+
public int getType() {
|
|
932
|
+
return type;
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
@Override
|
|
936
|
+
public void print() {
|
|
937
|
+
for (int i = 0; i < countCommands(); i++) {
|
|
938
|
+
String commandType = "";
|
|
939
|
+
switch (commands[i].commandType) {
|
|
940
|
+
case RCommand.LINETO:
|
|
941
|
+
commandType = "LINETO";
|
|
942
|
+
break;
|
|
943
|
+
|
|
944
|
+
case RCommand.CUBICBEZIERTO:
|
|
945
|
+
commandType = "BEZIERTO";
|
|
946
|
+
break;
|
|
947
|
+
|
|
948
|
+
case RCommand.QUADBEZIERTO:
|
|
949
|
+
commandType = "QUADBEZIERTO";
|
|
950
|
+
break;
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
System.out.println("cmd type: " + commandType);
|
|
954
|
+
System.out.print("start point: ");
|
|
955
|
+
commands[i].startPoint.print();
|
|
956
|
+
System.out.print("\n");
|
|
957
|
+
System.out.print("end point: ");
|
|
958
|
+
commands[i].endPoint.print();
|
|
959
|
+
System.out.print("\n");
|
|
960
|
+
if (commands[i].controlPoints != null) {
|
|
961
|
+
System.out.println("control points: ");
|
|
962
|
+
for (RPoint controlPoint : commands[i].controlPoints) {
|
|
963
|
+
controlPoint.print();
|
|
964
|
+
System.out.print(" ");
|
|
965
|
+
System.out.print("\n");
|
|
971
966
|
}
|
|
967
|
+
}
|
|
968
|
+
System.out.print("\n");
|
|
972
969
|
}
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
/**
|
|
973
|
+
* Use this method to transform the shape.
|
|
974
|
+
*
|
|
975
|
+
RPath_transform
|
|
976
|
+
* @param m RMatrix, the matrix defining the affine transformation
|
|
977
|
+
* draw ( )
|
|
978
|
+
*/
|
|
979
|
+
// OPT: not transform the EndPoint since it's equal to the next StartPoint
|
|
982
980
|
/*
|
|
983
981
|
public void transform(RMatrix m){
|
|
984
982
|
RPoint[] ps = getHandles();
|
|
@@ -1000,101 +998,101 @@ public class RPath extends RGeomElem {
|
|
|
1000
998
|
}
|
|
1001
999
|
|
|
1002
1000
|
}
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1001
|
+
*/
|
|
1002
|
+
private float[] indAndAdvAt(float t) {
|
|
1003
|
+
int indOfElement = 0;
|
|
1004
|
+
float[] lengthsCurves = getCurveLengths();
|
|
1005
|
+
float lengthCurve = getCurveLength();
|
|
1006
|
+
|
|
1007
|
+
/* Calculate the amount of advancement t mapped to each command */
|
|
1008
|
+
/* We use a simple algorithm where we give to each command the same amount of advancement */
|
|
1009
|
+
/* A more useful way would be to give to each command an advancement proportional to the length of the command */
|
|
1010
|
+
/* Old method with uniform advancement per command
|
|
1013
1011
|
float advPerCommand;
|
|
1014
1012
|
advPerCommand = 1F / numPaths;
|
|
1015
1013
|
indOfElement = (int)(Math.floor(t / advPerCommand)) % numPaths;
|
|
1016
1014
|
advOfElement = (t*numPaths - indOfElement);
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1015
|
+
*/
|
|
1016
|
+
float accumulatedAdvancement = lengthsCurves[indOfElement] / lengthCurve;
|
|
1017
|
+
float prevAccumulatedAdvancement = 0F;
|
|
1018
|
+
|
|
1019
|
+
/* Find in what command the advancement point is */
|
|
1020
|
+
while (t > accumulatedAdvancement) {
|
|
1021
|
+
indOfElement++;
|
|
1022
|
+
prevAccumulatedAdvancement = accumulatedAdvancement;
|
|
1023
|
+
accumulatedAdvancement += (lengthsCurves[indOfElement] / lengthCurve);
|
|
1024
|
+
}
|
|
1027
1025
|
|
|
1028
|
-
|
|
1026
|
+
float advOfElement = (t - prevAccumulatedAdvancement) / (lengthsCurves[indOfElement] / lengthCurve);
|
|
1029
1027
|
|
|
1030
|
-
|
|
1028
|
+
float[] indAndAdv = new float[2];
|
|
1031
1029
|
|
|
1032
|
-
|
|
1033
|
-
|
|
1030
|
+
indAndAdv[0] = indOfElement;
|
|
1031
|
+
indAndAdv[1] = advOfElement;
|
|
1034
1032
|
|
|
1035
|
-
|
|
1036
|
-
|
|
1033
|
+
return indAndAdv;
|
|
1034
|
+
}
|
|
1037
1035
|
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
}
|
|
1048
|
-
this.commands = newcommands;
|
|
1036
|
+
private void append(RCommand nextcommand) {
|
|
1037
|
+
RCommand[] newcommands;
|
|
1038
|
+
if (commands == null) {
|
|
1039
|
+
newcommands = new RCommand[1];
|
|
1040
|
+
newcommands[0] = nextcommand;
|
|
1041
|
+
} else {
|
|
1042
|
+
newcommands = new RCommand[this.commands.length + 1];
|
|
1043
|
+
System.arraycopy(this.commands, 0, newcommands, 0, this.commands.length);
|
|
1044
|
+
newcommands[this.commands.length] = nextcommand;
|
|
1049
1045
|
}
|
|
1046
|
+
this.commands = newcommands;
|
|
1047
|
+
}
|
|
1050
1048
|
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
}
|
|
1055
|
-
|
|
1056
|
-
RCommand[] newcommands;
|
|
1057
|
-
if (commands == null) {
|
|
1058
|
-
newcommands = new RCommand[1];
|
|
1059
|
-
newcommands[0] = newcommand;
|
|
1060
|
-
} else {
|
|
1061
|
-
if (i > commands.length) {
|
|
1062
|
-
throw new RuntimeException("Index out of the bounds. You are trying to insert an element with an index higher than the number of commands in the group.");
|
|
1063
|
-
}
|
|
1064
|
-
|
|
1065
|
-
newcommands = new RCommand[this.commands.length + 1];
|
|
1066
|
-
System.arraycopy(this.commands, 0, newcommands, 0, i);
|
|
1067
|
-
newcommands[i] = newcommand;
|
|
1068
|
-
System.arraycopy(this.commands, i, newcommands, i + 1, this.commands.length - i);
|
|
1069
|
-
}
|
|
1070
|
-
this.commands = newcommands;
|
|
1049
|
+
private void insert(RCommand newcommand, int i) throws RuntimeException {
|
|
1050
|
+
if (i < 0) {
|
|
1051
|
+
throw new RuntimeException("Negative values for indexes are not valid.");
|
|
1071
1052
|
}
|
|
1072
1053
|
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1054
|
+
RCommand[] newcommands;
|
|
1055
|
+
if (commands == null) {
|
|
1056
|
+
newcommands = new RCommand[1];
|
|
1057
|
+
newcommands[0] = newcommand;
|
|
1058
|
+
} else {
|
|
1059
|
+
if (i > commands.length) {
|
|
1060
|
+
throw new RuntimeException("Index out of the bounds. You are trying to insert an element with an index higher than the number of commands in the group.");
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1063
|
+
newcommands = new RCommand[this.commands.length + 1];
|
|
1064
|
+
System.arraycopy(this.commands, 0, newcommands, 0, i);
|
|
1065
|
+
newcommands[i] = newcommand;
|
|
1066
|
+
System.arraycopy(this.commands, i, newcommands, i + 1, this.commands.length - i);
|
|
1067
|
+
}
|
|
1068
|
+
this.commands = newcommands;
|
|
1069
|
+
}
|
|
1070
|
+
|
|
1071
|
+
private void extract(int i) throws RuntimeException {
|
|
1072
|
+
RCommand[] newcommands;
|
|
1073
|
+
if (commands == null) {
|
|
1074
|
+
throw new RuntimeException("The group is empty. No commands to remove.");
|
|
1075
|
+
} else {
|
|
1076
|
+
if (i < 0) {
|
|
1077
|
+
throw new RuntimeException("Negative values for indexes are not valid.");
|
|
1078
|
+
}
|
|
1079
|
+
if (i > commands.length - 1) {
|
|
1080
|
+
throw new RuntimeException("Index out of the bounds of the group. You are trying to erase an element with an index higher than the number of commands in the group.");
|
|
1081
|
+
}
|
|
1082
|
+
if (commands.length == 1) {
|
|
1083
|
+
newcommands = null;
|
|
1084
|
+
} else if (i == 0) {
|
|
1085
|
+
newcommands = new RCommand[this.commands.length - 1];
|
|
1086
|
+
System.arraycopy(this.commands, 1, newcommands, 0, this.commands.length - 1);
|
|
1087
|
+
} else if (i == commands.length - 1) {
|
|
1088
|
+
newcommands = new RCommand[this.commands.length - 1];
|
|
1089
|
+
System.arraycopy(this.commands, 0, newcommands, 0, this.commands.length - 1);
|
|
1090
|
+
} else {
|
|
1091
|
+
newcommands = new RCommand[this.commands.length - 1];
|
|
1092
|
+
System.arraycopy(this.commands, 0, newcommands, 0, i);
|
|
1093
|
+
System.arraycopy(this.commands, i + 1, newcommands, i, this.commands.length - i - 1);
|
|
1094
|
+
}
|
|
1099
1095
|
}
|
|
1096
|
+
this.commands = newcommands;
|
|
1097
|
+
}
|
|
1100
1098
|
}
|