geomerative 0.4.3-java → 2.1.0-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +19 -1
- data/COPYING.md +1 -1
- data/README.md +2 -2
- data/Rakefile +2 -15
- data/docs/_config.yml +8 -0
- data/docs/_includes/head.html +7 -6
- data/docs/_includes/header.html +6 -6
- data/docs/_includes/icon-github.svg +3 -1
- data/docs/_includes/icon-twitter.svg +3 -1
- data/docs/_includes/navigation.html +24 -0
- data/docs/_sass/_base.scss +79 -79
- data/docs/_sass/_layout.scss +137 -137
- data/docs/_sass/_syntax-highlighting.scss +64 -64
- data/docs/index.html +18 -18
- 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/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 -6
- data/lib/geomerative/version.rb +1 -1
- data/lib/geomerative.jar +0 -0
- data/lib/geomerative.rb +10 -10
- data/mvnw +234 -0
- data/mvnw.cmd +145 -0
- data/pom.rb +14 -16
- data/pom.xml +13 -19
- 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/module-info.java +4 -0
- 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 +18 -19
- data/.travis.yml +0 -10
- data/calculate_torsional_angle.rb +0 -17
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Copyright 2004-2008 Ricard Marxer <email@ricardmarxer.com>
|
|
3
3
|
*
|
|
4
|
-
|
|
4
|
+
* This file is part of Geomerative.
|
|
5
5
|
*
|
|
6
6
|
* Geomerative is free software: you can redistribute it and/or modify it under
|
|
7
7
|
* the terms of the GNU General Public License as published by the Free Software
|
|
@@ -22,1684 +22,1676 @@ import processing.core.PApplet;
|
|
|
22
22
|
import processing.core.PGraphics;
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
|
-
|
|
25
|
+
|
|
26
26
|
*/
|
|
27
27
|
public class RCommand extends RGeomElem {
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
29
|
+
/**
|
|
30
|
+
*
|
|
31
|
+
*/
|
|
32
|
+
public int type = RGeomElem.COMMAND;
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
34
|
+
public RPoint[] controlPoints;
|
|
35
|
+
public RPoint startPoint;
|
|
36
|
+
public RPoint endPoint;
|
|
37
|
+
int commandType;
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
RPoint[] curvePoints;
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
* @invisible
|
|
41
|
+
/**
|
|
43
42
|
*
|
|
44
|
-
*/
|
|
45
|
-
public static final int LINETO = 0;
|
|
46
|
-
/**
|
|
47
|
-
* @invisible
|
|
48
43
|
*
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
* @invisible
|
|
44
|
+
*/
|
|
45
|
+
public static final int LINETO = 0;
|
|
46
|
+
/**
|
|
53
47
|
*
|
|
54
|
-
|
|
55
|
-
|
|
48
|
+
*
|
|
49
|
+
*/
|
|
50
|
+
public static final int QUADBEZIERTO = 1;
|
|
51
|
+
/**
|
|
52
|
+
*
|
|
53
|
+
*
|
|
54
|
+
*/
|
|
55
|
+
public static final int CUBICBEZIERTO = 2;
|
|
56
56
|
|
|
57
|
-
|
|
58
|
-
* @invisible
|
|
57
|
+
/**
|
|
59
58
|
*
|
|
60
|
-
*/
|
|
61
|
-
public static final int ADAPTATIVE = 0;
|
|
62
|
-
/**
|
|
63
|
-
* @invisible
|
|
64
59
|
*
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
* @invisible
|
|
60
|
+
*/
|
|
61
|
+
public static final int ADAPTATIVE = 0;
|
|
62
|
+
/**
|
|
69
63
|
*
|
|
70
|
-
|
|
71
|
-
|
|
64
|
+
*
|
|
65
|
+
*/
|
|
66
|
+
public static final int UNIFORMLENGTH = 1;
|
|
67
|
+
/**
|
|
68
|
+
*
|
|
69
|
+
*
|
|
70
|
+
*/
|
|
71
|
+
public static final int UNIFORMSTEP = 2;
|
|
72
|
+
|
|
73
|
+
public static int segmentType = UNIFORMLENGTH;
|
|
74
|
+
|
|
75
|
+
/* Parameters for ADAPTATIVE (dependent of the PGraphics on which drawing) */
|
|
76
|
+
static final int SEGMENT_RECURSION_LIMIT = 32;
|
|
77
|
+
static final float SEGMENT_DISTANCE_EPSILON = 1.192092896e-07F;
|
|
78
|
+
static final float SEGMENT_COLLINEARITY_EPSILON = 1.192092896e-07F;
|
|
79
|
+
static final float SEGMENT_ANGLE_TOL_EPSILON = 0.01F;
|
|
80
|
+
|
|
81
|
+
static float segmentGfxStrokeWeight = 1.0F;
|
|
82
|
+
static float segmentGfxScale = 1.0F;
|
|
83
|
+
static float segmentApproxScale = 1.0F;
|
|
84
|
+
static float segmentDistTolSqr = 0.25F;
|
|
85
|
+
static float segmentDistTolMnhttn = 4.0F;
|
|
86
|
+
public static float segmentAngleTol = 0.0F;
|
|
87
|
+
static float segmentCuspLimit = 0.0F;
|
|
88
|
+
|
|
89
|
+
/* Parameters for UNIFORMLENGTH (dependent of the PGraphics on which drawing) */
|
|
90
|
+
static float segmentLength = 4.0F;
|
|
91
|
+
static float segmentOffset = 0.0F;
|
|
92
|
+
static float segmentAccOffset = 0.0F;
|
|
93
|
+
|
|
94
|
+
/* Parameters for UNIFORMSTEP */
|
|
95
|
+
static int segmentSteps = 0;
|
|
96
|
+
static boolean segmentLines = false;
|
|
97
|
+
|
|
98
|
+
int oldSegmentType = UNIFORMLENGTH;
|
|
99
|
+
|
|
100
|
+
/* Parameters for ADAPTATIVE (dependent of the PGraphics on which drawing) */
|
|
101
|
+
float oldSegmentCollinearityEpsilon = 1.192092896e-07F;
|
|
102
|
+
float oldSegmentAngleTolEpsilon = 0.01F;
|
|
103
|
+
|
|
104
|
+
float oldSegmentGfxStrokeWeight = 1.0F;
|
|
105
|
+
float oldSegmentGfxScale = 1.0F;
|
|
106
|
+
float oldSegmentApproxScale = 1.0F;
|
|
107
|
+
float oldSegmentDistTolSqr = 0.25F;
|
|
108
|
+
float oldSegmentDistTolMnhttn = 4.0F;
|
|
109
|
+
float oldSegmentAngleTol = 0.0F;
|
|
110
|
+
float oldSegmentCuspLimit = 0.0F;
|
|
111
|
+
|
|
112
|
+
/* Parameters for UNIFORMLENGTH (dependent of the PGraphics on which drawing) */
|
|
113
|
+
float oldSegmentLength = 4.0F;
|
|
114
|
+
float oldSegmentOffset = 0.0F;
|
|
115
|
+
float oldSegmentAccOffset = 0.0F;
|
|
116
|
+
|
|
117
|
+
/* Parameters for UNIFORMSTEP */
|
|
118
|
+
int oldSegmentSteps = 0;
|
|
119
|
+
boolean oldSegmentLines = false;
|
|
120
|
+
|
|
121
|
+
static RCommand createLine(RPoint start, RPoint end) {
|
|
122
|
+
RCommand result = new RCommand();
|
|
123
|
+
result.startPoint = start;
|
|
124
|
+
result.endPoint = end;
|
|
125
|
+
result.commandType = LINETO;
|
|
126
|
+
return result;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
static RCommand createLine(float startx, float starty, float endx, float endy) {
|
|
130
|
+
return createLine(new RPoint(startx, starty), new RPoint(endx, endy));
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
static RCommand createBezier3(RPoint start, RPoint cp1, RPoint end) {
|
|
134
|
+
RCommand result = new RCommand();
|
|
135
|
+
result.startPoint = start;
|
|
136
|
+
result.append(cp1);
|
|
137
|
+
result.endPoint = end;
|
|
138
|
+
result.commandType = QUADBEZIERTO;
|
|
139
|
+
return result;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
static RCommand createBezier3(float startx, float starty, float cp1x, float cp1y, float endx, float endy) {
|
|
143
|
+
return createBezier3(new RPoint(startx, starty), new RPoint(cp1x, cp1y), new RPoint(endx, endy));
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
static RCommand createBezier4(RPoint start, RPoint cp1, RPoint cp2, RPoint end) {
|
|
147
|
+
RCommand result = new RCommand();
|
|
148
|
+
result.startPoint = start;
|
|
149
|
+
result.append(cp1);
|
|
150
|
+
result.append(cp2);
|
|
151
|
+
result.endPoint = end;
|
|
152
|
+
result.commandType = CUBICBEZIERTO;
|
|
153
|
+
return result;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
static RCommand createBezier4(float startx, float starty, float cp1x, float cp1y, float cp2x, float cp2y, float endx, float endy) {
|
|
157
|
+
return createBezier4(new RPoint(startx, starty), new RPoint(cp1x, cp1y), new RPoint(cp2x, cp2y), new RPoint(endx, endy));
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Create an empty command
|
|
162
|
+
*
|
|
163
|
+
*
|
|
164
|
+
*/
|
|
165
|
+
public RCommand() {
|
|
166
|
+
controlPoints = null;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Make a copy of another RCommand object. This can be useful when wanting to
|
|
171
|
+
* transform one but at the same time keep the original.
|
|
172
|
+
*
|
|
173
|
+
* @param c the object of which to make the copy
|
|
174
|
+
*
|
|
175
|
+
*/
|
|
176
|
+
public RCommand(RCommand c) {
|
|
177
|
+
this.startPoint = new RPoint(c.startPoint);
|
|
178
|
+
for (int i = 0; i < c.countControlPoints(); i++) {
|
|
179
|
+
this.append(new RPoint(c.controlPoints[i]));
|
|
180
|
+
}
|
|
181
|
+
this.endPoint = new RPoint(c.endPoint);
|
|
182
|
+
this.commandType = c.commandType;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Make a copy of another RCommand object with a specific start point.
|
|
187
|
+
*
|
|
188
|
+
* @param c the object of which to make the copy
|
|
189
|
+
* @param sp the start point of the command to be created
|
|
190
|
+
*/
|
|
191
|
+
public RCommand(RCommand c, RPoint sp) {
|
|
192
|
+
this.startPoint = sp;
|
|
193
|
+
for (int i = 0; i < c.countControlPoints(); i++) {
|
|
194
|
+
this.append(new RPoint(c.controlPoints[i]));
|
|
195
|
+
}
|
|
196
|
+
this.endPoint = new RPoint(c.endPoint);
|
|
197
|
+
this.commandType = c.commandType;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Create a LINETO command object with specific start and end points.
|
|
202
|
+
*
|
|
203
|
+
* @param sp the start point of the command to be created
|
|
204
|
+
* @param ep the end point of the command to be created
|
|
205
|
+
*/
|
|
206
|
+
public RCommand(RPoint sp, RPoint ep) {
|
|
207
|
+
this.startPoint = sp;
|
|
208
|
+
this.endPoint = ep;
|
|
209
|
+
this.commandType = LINETO;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Create a LINETO command object with specific start and end point
|
|
214
|
+
* coordinates.
|
|
215
|
+
*
|
|
216
|
+
* @param spx the x coordinate of the start point of the command to be created
|
|
217
|
+
* @param spy the y coordinate of the start point of the command to be created
|
|
218
|
+
* @param epx the x coordinate of the end point of the command to be created
|
|
219
|
+
* @param epy the y coordinate of the end point of the command to be created
|
|
220
|
+
*/
|
|
221
|
+
public RCommand(float spx, float spy, float epx, float epy) {
|
|
222
|
+
this(new RPoint(spx, spy), new RPoint(epx, epy));
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Create a QUADBEZIERTO command object with specific start, control and end
|
|
227
|
+
* point coordinates.
|
|
228
|
+
*
|
|
229
|
+
* @param sp the start point of the command to be created
|
|
230
|
+
* @param cp1 the first control point of the command to be created
|
|
231
|
+
* @param ep the end point of the command to be created
|
|
232
|
+
*/
|
|
233
|
+
public RCommand(RPoint sp, RPoint cp1, RPoint ep) {
|
|
234
|
+
this.startPoint = sp;
|
|
235
|
+
this.append(cp1);
|
|
236
|
+
this.endPoint = ep;
|
|
237
|
+
this.commandType = QUADBEZIERTO;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Create a QUADBEZIERTO command object with specific start, control and end
|
|
242
|
+
* point coordinates.
|
|
243
|
+
*
|
|
244
|
+
* @param spx the x coordinate of the start point of the command to be created
|
|
245
|
+
* @param spy the y coordinate of the start point of the command to be created
|
|
246
|
+
* @param cp1x the x coordinate of the first control point of the command to
|
|
247
|
+
* be created
|
|
248
|
+
* @param cp1y the y coordinate of the first control point of the command to
|
|
249
|
+
* be created
|
|
250
|
+
* @param epx the x coordinate of the end point of the command to be created
|
|
251
|
+
* @param epy the y coordinate of the end point of the command to be created
|
|
252
|
+
*/
|
|
253
|
+
public RCommand(float spx, float spy, float cp1x, float cp1y, float epx, float epy) {
|
|
254
|
+
this(new RPoint(spx, spy), new RPoint(cp1x, cp1y), new RPoint(epx, epy));
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Create a CUBICBEZIERTO command object with specific start, control and end
|
|
259
|
+
* point coordinates.
|
|
260
|
+
*
|
|
261
|
+
* @param sp the start point of the command to be created
|
|
262
|
+
* @param cp1 the first control point of the command to be created
|
|
263
|
+
* @param cp2 the second control point of the command to be created
|
|
264
|
+
* @param ep the end point of the command to be created
|
|
265
|
+
*/
|
|
266
|
+
public RCommand(RPoint sp, RPoint cp1, RPoint cp2, RPoint ep) {
|
|
267
|
+
this.startPoint = sp;
|
|
268
|
+
this.append(cp1);
|
|
269
|
+
this.append(cp2);
|
|
270
|
+
this.endPoint = ep;
|
|
271
|
+
this.commandType = CUBICBEZIERTO;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Create a CUBICBEZIERTO command object with specific start, control and end
|
|
276
|
+
* point coordinates.
|
|
277
|
+
*
|
|
278
|
+
* @param spx the x coordinate of the start point of the command to be created
|
|
279
|
+
* @param spy the y coordinate of the start point of the command to be created
|
|
280
|
+
* @param cp1x the x coordinate of the first control point of the command to
|
|
281
|
+
* be created
|
|
282
|
+
* @param cp1y the y coordinate of the first control point of the command to
|
|
283
|
+
* be created
|
|
284
|
+
* @param cp2x the x coordinate of the second control point of the command to
|
|
285
|
+
* be created
|
|
286
|
+
* @param cp2y the y coordinate of the second control point of the command to
|
|
287
|
+
* be created
|
|
288
|
+
* @param epx the x coordinate of the end point of the command to be created
|
|
289
|
+
* @param epy the y coordinate of the end point of the command to be created
|
|
290
|
+
*/
|
|
291
|
+
public RCommand(float spx, float spy, float cp1x, float cp1y, float cp2x, float cp2y, float epx, float epy) {
|
|
292
|
+
this(new RPoint(spx, spy), new RPoint(cp1x, cp1y), new RPoint(cp2x, cp2y), new RPoint(epx, epy));
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* @return
|
|
297
|
+
*/
|
|
298
|
+
@Override
|
|
299
|
+
public RShape toShape() {
|
|
300
|
+
return new RShape(new RPath(this));
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
@Override
|
|
304
|
+
public int getType() {
|
|
305
|
+
return this.type;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Use this to set the segmentator type. ADAPTATIVE segmentator minimizes the
|
|
310
|
+
* number of segments avoiding perceptual artifacts like angles or cusps. Use
|
|
311
|
+
* this in order to have Polygons and Meshes with the fewest possible
|
|
312
|
+
* vertices. This can be useful when using or drawing a lot the same Polygon
|
|
313
|
+
* or Mesh deriving from this Shape. UNIFORMLENGTH segmentator is the slowest
|
|
314
|
+
* segmentator and it segments the curve on segments of equal length. This can
|
|
315
|
+
* be useful for very specific applications when for example drawing
|
|
316
|
+
* incrementaly a shape with a uniform speed. UNIFORMSTEP segmentator is the
|
|
317
|
+
* fastest segmentator and it segments the curve based on a constant value of
|
|
318
|
+
* the step of the curve parameter, or on the number of segments wanted. This
|
|
319
|
+
* can be useful when segmpointsentating very often a Shape or when we know
|
|
320
|
+
* the amount of segments necessary for our specific application.
|
|
321
|
+
*
|
|
322
|
+
* @param segmentatorType
|
|
323
|
+
setSegment
|
|
324
|
+
*
|
|
325
|
+
*/
|
|
326
|
+
public static void setSegmentator(int segmentatorType) {
|
|
327
|
+
segmentType = segmentatorType;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* Use this to set the segmentator graphic context.
|
|
332
|
+
*
|
|
333
|
+
setSegmentGraphic
|
|
334
|
+
* @param g graphics object too which to adapt the segmentation of the
|
|
335
|
+
* command.
|
|
336
|
+
*
|
|
337
|
+
*/
|
|
338
|
+
public static void setSegmentGraphic(PGraphics g) {
|
|
339
|
+
// Set the segmentApproxScale from the graphic context g
|
|
340
|
+
segmentApproxScale = 1.0F;
|
|
341
|
+
|
|
342
|
+
// Set all the gfx-context dependent parameters for all segmentators
|
|
343
|
+
segmentDistTolSqr = 0.5F / segmentApproxScale;
|
|
344
|
+
segmentDistTolSqr *= segmentDistTolSqr;
|
|
345
|
+
segmentDistTolMnhttn = 4.0F / segmentApproxScale;
|
|
346
|
+
segmentAngleTol = 0.0F;
|
|
347
|
+
|
|
348
|
+
if (g.stroke && (g.strokeWeight * segmentApproxScale > 1.0F)) {
|
|
349
|
+
segmentAngleTol = 0.1F;
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* Use this to set the segmentator angle tolerance for the ADAPTATIVE
|
|
355
|
+
* segmentator and set the segmentator to ADAPTATIVE.
|
|
356
|
+
*
|
|
357
|
+
setSegmentAngle
|
|
358
|
+
* @param segmentAngleTolerance an angle from 0 to PI/2 it defines the maximum
|
|
359
|
+
* angle between segments.
|
|
360
|
+
*
|
|
361
|
+
*/
|
|
362
|
+
public static void setSegmentAngle(float segmentAngleTolerance) {
|
|
363
|
+
//segmentType = ADAPTATIVE;
|
|
364
|
+
|
|
365
|
+
segmentAngleTol = segmentAngleTolerance;
|
|
366
|
+
}
|
|
72
367
|
|
|
73
|
-
|
|
368
|
+
/**
|
|
369
|
+
* Use this to set the segmentator length for the UNIFORMLENGTH segmentator
|
|
370
|
+
* and set the segmentator to UNIFORMLENGTH.
|
|
371
|
+
*
|
|
372
|
+
setSegmentLength
|
|
373
|
+
* @param segmentLngth the length of each resulting segment.
|
|
374
|
+
*
|
|
375
|
+
*/
|
|
376
|
+
public static void setSegmentLength(float segmentLngth) {
|
|
377
|
+
//segmentType = UNIFORMLENGTH;
|
|
378
|
+
if (segmentLngth >= 1) {
|
|
379
|
+
segmentLength = segmentLngth;
|
|
380
|
+
} else {
|
|
381
|
+
segmentLength = 4;
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* Use this to set the segmentator offset for the UNIFORMLENGTH segmentator
|
|
387
|
+
* and set the segmentator to UNIFORMLENGTH.
|
|
388
|
+
*
|
|
389
|
+
setSegmentOffset
|
|
390
|
+
* @param segmentOffst the offset of the first point on the path.
|
|
391
|
+
*
|
|
392
|
+
*/
|
|
393
|
+
public static void setSegmentOffset(float segmentOffst) {
|
|
394
|
+
//segmentType = UNIFORMLENGTH;
|
|
395
|
+
if (segmentOffst >= 0) {
|
|
396
|
+
segmentOffset = segmentOffst;
|
|
397
|
+
} else {
|
|
398
|
+
segmentOffset = 0;
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* Use this to set the segmentator step for the UNIFORMSTEP segmentator and
|
|
404
|
+
* set the segmentator to UNIFORMSTEP.
|
|
405
|
+
*
|
|
406
|
+
setSegmentStep
|
|
407
|
+
* @param segmentStps if a float from +0.0 to 1.0 is passed it's considered as
|
|
408
|
+
* the step, else it's considered as the number of steps. When a value of 0.0
|
|
409
|
+
* is used the steps will be calculated automatically depending on an
|
|
410
|
+
* estimation of the length of the curve. The special value -1 is the same as
|
|
411
|
+
* 0.0 but also turning of the segmentation of lines (faster segmentation).
|
|
412
|
+
*
|
|
413
|
+
*/
|
|
414
|
+
public static void setSegmentStep(float segmentStps) {
|
|
415
|
+
//segmentType = UNIFORMSTEP;
|
|
416
|
+
if (segmentStps == -1F) {
|
|
417
|
+
segmentLines = false;
|
|
418
|
+
segmentStps = 0F;
|
|
419
|
+
} else {
|
|
420
|
+
segmentLines = true;
|
|
421
|
+
}
|
|
422
|
+
// Set the parameters
|
|
423
|
+
segmentStps = Math.abs(segmentStps);
|
|
424
|
+
if (segmentStps > 0.0F && segmentStps < 1.0F) {
|
|
425
|
+
segmentSteps = (int) (1F / segmentStps);
|
|
426
|
+
} else {
|
|
427
|
+
segmentSteps = (int) segmentStps;
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
protected void saveSegmentatorContext() {
|
|
432
|
+
oldSegmentType = RCommand.segmentType;
|
|
74
433
|
|
|
75
434
|
/* Parameters for ADAPTATIVE (dependent of the PGraphics on which drawing) */
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
static float segmentApproxScale = 1.0F;
|
|
84
|
-
static float segmentDistTolSqr = 0.25F;
|
|
85
|
-
static float segmentDistTolMnhttn = 4.0F;
|
|
86
|
-
public static float segmentAngleTol = 0.0F;
|
|
87
|
-
static float segmentCuspLimit = 0.0F;
|
|
435
|
+
oldSegmentGfxStrokeWeight = RCommand.segmentGfxStrokeWeight;
|
|
436
|
+
oldSegmentGfxScale = RCommand.segmentGfxScale;
|
|
437
|
+
oldSegmentApproxScale = RCommand.segmentApproxScale;
|
|
438
|
+
oldSegmentDistTolSqr = RCommand.segmentDistTolSqr;
|
|
439
|
+
oldSegmentDistTolMnhttn = RCommand.segmentDistTolMnhttn;
|
|
440
|
+
oldSegmentAngleTol = RCommand.segmentAngleTol;
|
|
441
|
+
oldSegmentCuspLimit = RCommand.segmentCuspLimit;
|
|
88
442
|
|
|
89
443
|
/* Parameters for UNIFORMLENGTH (dependent of the PGraphics on which drawing) */
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
444
|
+
oldSegmentLength = RCommand.segmentLength;
|
|
445
|
+
oldSegmentOffset = RCommand.segmentOffset;
|
|
446
|
+
oldSegmentAccOffset = RCommand.segmentAccOffset;
|
|
93
447
|
|
|
94
448
|
/* Parameters for UNIFORMSTEP */
|
|
95
|
-
|
|
96
|
-
|
|
449
|
+
oldSegmentSteps = RCommand.segmentSteps;
|
|
450
|
+
oldSegmentLines = RCommand.segmentLines;
|
|
451
|
+
}
|
|
97
452
|
|
|
98
|
-
|
|
453
|
+
protected void restoreSegmentatorContext() {
|
|
454
|
+
RCommand.segmentType = oldSegmentType;
|
|
99
455
|
|
|
100
456
|
/* Parameters for ADAPTATIVE (dependent of the PGraphics on which drawing) */
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
float oldSegmentDistTolMnhttn = 4.0F;
|
|
109
|
-
float oldSegmentAngleTol = 0.0F;
|
|
110
|
-
float oldSegmentCuspLimit = 0.0F;
|
|
457
|
+
RCommand.segmentGfxStrokeWeight = oldSegmentGfxStrokeWeight;
|
|
458
|
+
RCommand.segmentGfxScale = oldSegmentGfxScale;
|
|
459
|
+
RCommand.segmentApproxScale = oldSegmentApproxScale;
|
|
460
|
+
RCommand.segmentDistTolSqr = oldSegmentDistTolSqr;
|
|
461
|
+
RCommand.segmentDistTolMnhttn = oldSegmentDistTolMnhttn;
|
|
462
|
+
RCommand.segmentAngleTol = oldSegmentAngleTol;
|
|
463
|
+
RCommand.segmentCuspLimit = oldSegmentCuspLimit;
|
|
111
464
|
|
|
112
465
|
/* Parameters for UNIFORMLENGTH (dependent of the PGraphics on which drawing) */
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
466
|
+
RCommand.segmentLength = oldSegmentLength;
|
|
467
|
+
RCommand.segmentOffset = oldSegmentOffset;
|
|
468
|
+
RCommand.segmentAccOffset = oldSegmentAccOffset;
|
|
116
469
|
|
|
117
470
|
/* Parameters for UNIFORMSTEP */
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
static RCommand createLine(RPoint start, RPoint end) {
|
|
122
|
-
RCommand result = new RCommand();
|
|
123
|
-
result.startPoint = start;
|
|
124
|
-
result.endPoint = end;
|
|
125
|
-
result.commandType = LINETO;
|
|
126
|
-
return result;
|
|
127
|
-
}
|
|
471
|
+
RCommand.segmentSteps = oldSegmentSteps;
|
|
472
|
+
RCommand.segmentLines = oldSegmentLines;
|
|
473
|
+
}
|
|
128
474
|
|
|
129
|
-
|
|
130
|
-
|
|
475
|
+
/**
|
|
476
|
+
* Use this to return the number of control points of the curve.
|
|
477
|
+
*
|
|
478
|
+
countControlPoints
|
|
479
|
+
* @return int, the number of control points.
|
|
480
|
+
*
|
|
481
|
+
*/
|
|
482
|
+
public int countControlPoints() {
|
|
483
|
+
if (controlPoints == null) {
|
|
484
|
+
return 0;
|
|
131
485
|
}
|
|
486
|
+
return controlPoints.length;
|
|
487
|
+
}
|
|
132
488
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
489
|
+
/**
|
|
490
|
+
* Use this to return the command type.
|
|
491
|
+
*
|
|
492
|
+
getCommandType
|
|
493
|
+
* @return int, an integer which can take the following values:
|
|
494
|
+
* RCommand.LINETO, RCommand.QUADBEZIERTO, RCommand.CUBICBEZIERTO.
|
|
495
|
+
*
|
|
496
|
+
*/
|
|
497
|
+
public int getCommandType() {
|
|
498
|
+
return commandType;
|
|
499
|
+
}
|
|
141
500
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
501
|
+
/**
|
|
502
|
+
* Use this to return the start point of the curve.
|
|
503
|
+
*
|
|
504
|
+
getStartPoint
|
|
505
|
+
* @return RPoint, the start point of the curve.
|
|
506
|
+
*
|
|
507
|
+
*
|
|
508
|
+
*/
|
|
509
|
+
RPoint getStartPoint() {
|
|
510
|
+
return startPoint;
|
|
511
|
+
}
|
|
145
512
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
513
|
+
/**
|
|
514
|
+
* Use this to return the end point of the curve.
|
|
515
|
+
*
|
|
516
|
+
getEndPoint
|
|
517
|
+
* @return RPoint, the end point of the curve.
|
|
518
|
+
*
|
|
519
|
+
*
|
|
520
|
+
*/
|
|
521
|
+
RPoint getEndPoint() {
|
|
522
|
+
return endPoint;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
/**
|
|
526
|
+
* Use this to return the control points of the curve. It returns the points
|
|
527
|
+
* in the way of an array of RPoint.
|
|
528
|
+
*
|
|
529
|
+
getControlPoints
|
|
530
|
+
* @return RPoint[], the control points returned in an array.
|
|
531
|
+
*
|
|
532
|
+
*
|
|
533
|
+
*/
|
|
534
|
+
RPoint[] getControlPoints() {
|
|
535
|
+
return controlPoints;
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
/**
|
|
539
|
+
* Use this to return the points on the curve. It returns the points in the
|
|
540
|
+
* way of an array of RPoint.
|
|
541
|
+
*
|
|
542
|
+
getPoints
|
|
543
|
+
* @return RPoint[], the vertices returned in an array.
|
|
544
|
+
*
|
|
545
|
+
*/
|
|
546
|
+
@Override
|
|
547
|
+
public RPoint[] getPoints() {
|
|
548
|
+
return getPoints(true);
|
|
549
|
+
}
|
|
155
550
|
|
|
156
|
-
|
|
157
|
-
return createBezier4(new RPoint(startx, starty), new RPoint(cp1x, cp1y), new RPoint(cp2x, cp2y), new RPoint(endx, endy));
|
|
158
|
-
}
|
|
551
|
+
protected RPoint[] getPoints(boolean resetSegmentator) {
|
|
159
552
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
*/
|
|
165
|
-
public RCommand() {
|
|
166
|
-
controlPoints = null;
|
|
553
|
+
if (resetSegmentator) {
|
|
554
|
+
saveSegmentatorContext();
|
|
555
|
+
RCommand.segmentOffset = 0F;
|
|
556
|
+
RCommand.segmentAccOffset = 0F;
|
|
167
557
|
}
|
|
168
558
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
559
|
+
RPoint[] result = null;
|
|
560
|
+
switch (segmentType) {
|
|
561
|
+
case ADAPTATIVE:
|
|
562
|
+
switch (commandType) {
|
|
563
|
+
case LINETO:
|
|
564
|
+
result = new RPoint[2];
|
|
565
|
+
result[0] = startPoint;
|
|
566
|
+
result[1] = endPoint;
|
|
567
|
+
break;
|
|
568
|
+
|
|
569
|
+
case QUADBEZIERTO:
|
|
570
|
+
quadBezierAdaptative();
|
|
571
|
+
result = curvePoints;
|
|
572
|
+
curvePoints = null;
|
|
573
|
+
break;
|
|
574
|
+
|
|
575
|
+
case CUBICBEZIERTO:
|
|
576
|
+
cubicBezierAdaptative();
|
|
577
|
+
result = curvePoints;
|
|
578
|
+
curvePoints = null;
|
|
579
|
+
break;
|
|
180
580
|
}
|
|
181
|
-
|
|
182
|
-
this.commandType = c.commandType;
|
|
183
|
-
}
|
|
581
|
+
break;
|
|
184
582
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
583
|
+
case UNIFORMLENGTH:
|
|
584
|
+
switch (commandType) {
|
|
585
|
+
case LINETO:
|
|
586
|
+
lineUniformLength();
|
|
587
|
+
result = curvePoints;
|
|
588
|
+
curvePoints = null;
|
|
589
|
+
break;
|
|
590
|
+
|
|
591
|
+
case QUADBEZIERTO:
|
|
592
|
+
quadBezierUniformLength();
|
|
593
|
+
result = curvePoints;
|
|
594
|
+
curvePoints = null;
|
|
595
|
+
break;
|
|
596
|
+
|
|
597
|
+
case CUBICBEZIERTO:
|
|
598
|
+
cubicBezierUniformLength();
|
|
599
|
+
result = curvePoints;
|
|
600
|
+
curvePoints = null;
|
|
601
|
+
break;
|
|
195
602
|
}
|
|
196
|
-
|
|
197
|
-
this.commandType = c.commandType;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
/**
|
|
201
|
-
* Create a LINETO command object with specific start and end points.
|
|
202
|
-
*
|
|
203
|
-
* @param sp the start point of the command to be created
|
|
204
|
-
* @param ep the end point of the command to be created
|
|
205
|
-
*/
|
|
206
|
-
public RCommand(RPoint sp, RPoint ep) {
|
|
207
|
-
this.startPoint = sp;
|
|
208
|
-
this.endPoint = ep;
|
|
209
|
-
this.commandType = LINETO;
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
/**
|
|
213
|
-
* Create a LINETO command object with specific start and end point
|
|
214
|
-
* coordinates.
|
|
215
|
-
*
|
|
216
|
-
* @param spx the x coordinate of the start point of the command to be
|
|
217
|
-
* created
|
|
218
|
-
* @param spy the y coordinate of the start point of the command to be
|
|
219
|
-
* created
|
|
220
|
-
* @param epx the x coordinate of the end point of the command to be created
|
|
221
|
-
* @param epy the y coordinate of the end point of the command to be created
|
|
222
|
-
*/
|
|
223
|
-
public RCommand(float spx, float spy, float epx, float epy) {
|
|
224
|
-
this(new RPoint(spx, spy), new RPoint(epx, epy));
|
|
225
|
-
}
|
|
603
|
+
break;
|
|
226
604
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
* @param epx the x coordinate of the end point of the command to be created
|
|
255
|
-
* @param epy the y coordinate of the end point of the command to be created
|
|
256
|
-
*/
|
|
257
|
-
public RCommand(float spx, float spy, float cp1x, float cp1y, float epx, float epy) {
|
|
258
|
-
this(new RPoint(spx, spy), new RPoint(cp1x, cp1y), new RPoint(epx, epy));
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
/**
|
|
262
|
-
* Create a CUBICBEZIERTO command object with specific start, control and
|
|
263
|
-
* end point coordinates.
|
|
264
|
-
*
|
|
265
|
-
* @param sp the start point of the command to be created
|
|
266
|
-
* @param cp1 the first control point of the command to be created
|
|
267
|
-
* @param cp2 the second control point of the command to be created
|
|
268
|
-
* @param ep the end point of the command to be created
|
|
269
|
-
*/
|
|
270
|
-
public RCommand(RPoint sp, RPoint cp1, RPoint cp2, RPoint ep) {
|
|
271
|
-
this.startPoint = sp;
|
|
272
|
-
this.append(cp1);
|
|
273
|
-
this.append(cp2);
|
|
274
|
-
this.endPoint = ep;
|
|
275
|
-
this.commandType = CUBICBEZIERTO;
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
/**
|
|
279
|
-
* Create a CUBICBEZIERTO command object with specific start, control and
|
|
280
|
-
* end point coordinates.
|
|
281
|
-
*
|
|
282
|
-
* @param spx the x coordinate of the start point of the command to be
|
|
283
|
-
* created
|
|
284
|
-
* @param spy the y coordinate of the start point of the command to be
|
|
285
|
-
* created
|
|
286
|
-
* @param cp1x the x coordinate of the first control point of the command to
|
|
287
|
-
* be created
|
|
288
|
-
* @param cp1y the y coordinate of the first control point of the command to
|
|
289
|
-
* be created
|
|
290
|
-
* @param cp2x the x coordinate of the second control point of the command
|
|
291
|
-
* to be created
|
|
292
|
-
* @param cp2y the y coordinate of the second control point of the command
|
|
293
|
-
* to be created
|
|
294
|
-
* @param epx the x coordinate of the end point of the command to be created
|
|
295
|
-
* @param epy the y coordinate of the end point of the command to be created
|
|
296
|
-
*/
|
|
297
|
-
public RCommand(float spx, float spy, float cp1x, float cp1y, float cp2x, float cp2y, float epx, float epy) {
|
|
298
|
-
this(new RPoint(spx, spy), new RPoint(cp1x, cp1y), new RPoint(cp2x, cp2y), new RPoint(epx, epy));
|
|
605
|
+
case UNIFORMSTEP:
|
|
606
|
+
switch (commandType) {
|
|
607
|
+
case LINETO:
|
|
608
|
+
if (segmentLines) {
|
|
609
|
+
lineUniformStep();
|
|
610
|
+
result = curvePoints;
|
|
611
|
+
curvePoints = null;
|
|
612
|
+
} else {
|
|
613
|
+
result = new RPoint[2];
|
|
614
|
+
result[0] = startPoint;
|
|
615
|
+
result[1] = endPoint;
|
|
616
|
+
}
|
|
617
|
+
break;
|
|
618
|
+
|
|
619
|
+
case QUADBEZIERTO:
|
|
620
|
+
quadBezierUniformStep();
|
|
621
|
+
result = curvePoints;
|
|
622
|
+
curvePoints = null;
|
|
623
|
+
break;
|
|
624
|
+
|
|
625
|
+
case CUBICBEZIERTO:
|
|
626
|
+
cubicBezierUniformStep();
|
|
627
|
+
result = curvePoints;
|
|
628
|
+
curvePoints = null;
|
|
629
|
+
break;
|
|
630
|
+
}
|
|
631
|
+
break;
|
|
299
632
|
}
|
|
300
633
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
*/
|
|
304
|
-
@Override
|
|
305
|
-
public RShape toShape() {
|
|
306
|
-
return new RShape(new RPath(this));
|
|
634
|
+
if (resetSegmentator) {
|
|
635
|
+
restoreSegmentatorContext();
|
|
307
636
|
}
|
|
308
637
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
return this.type;
|
|
312
|
-
}
|
|
638
|
+
return result;
|
|
639
|
+
}
|
|
313
640
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
* cusps. Use this in order to have Polygons and Meshes with the fewest
|
|
318
|
-
* possible vertices. This can be useful when using or drawing a lot the
|
|
319
|
-
* same Polygon or Mesh deriving from this Shape. UNIFORMLENGTH segmentator
|
|
320
|
-
* is the slowest segmentator and it segments the curve on segments of equal
|
|
321
|
-
* length. This can be useful for very specific applications when for
|
|
322
|
-
* example drawing incrementaly a shape with a uniform speed. UNIFORMSTEP
|
|
323
|
-
* segmentator is the fastest segmentator and it segments the curve based on
|
|
324
|
-
* a constant value of the step of the curve parameter, or on the number of
|
|
325
|
-
* segments wanted. This can be useful when segmpointsentating very often a
|
|
326
|
-
* Shape or when we know the amount of segments necessary for our specific
|
|
327
|
-
* application.
|
|
328
|
-
*
|
|
329
|
-
* @param segmentatorType
|
|
330
|
-
* @eexample setSegment
|
|
641
|
+
/**
|
|
642
|
+
* Use this to return a specific point on the curve. It returns the RPoint for
|
|
643
|
+
* a given advancement parameter t on the curve.
|
|
331
644
|
*
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
/**
|
|
338
|
-
* Use this to set the segmentator graphic context.
|
|
339
|
-
*
|
|
340
|
-
* @eexample setSegmentGraphic
|
|
341
|
-
* @param g graphics object too which to adapt the segmentation of the
|
|
342
|
-
* command.
|
|
645
|
+
getPoint
|
|
646
|
+
* @param t float, the parameter of advancement on the curve. t must have
|
|
647
|
+
* values between 0 and 1.
|
|
648
|
+
* @return RPoint, the vertice returned.
|
|
343
649
|
*
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
650
|
+
*/
|
|
651
|
+
@Override
|
|
652
|
+
public RPoint getPoint(float t) {
|
|
653
|
+
/* limit the value of t between 0 and 1 */
|
|
654
|
+
t = (t > 1F) ? 1F : t;
|
|
655
|
+
t = (t < 0F) ? 0F : t;
|
|
656
|
+
float ax, bx, cx;
|
|
657
|
+
float ay, by, cy;
|
|
658
|
+
float tSquared, tDoubled, tCubed;
|
|
659
|
+
float dx, dy;
|
|
660
|
+
|
|
661
|
+
switch (commandType) {
|
|
662
|
+
case LINETO:
|
|
663
|
+
dx = endPoint.x - startPoint.x;
|
|
664
|
+
dy = endPoint.y - startPoint.y;
|
|
665
|
+
return new RPoint(startPoint.x + dx * t, startPoint.y + dy * t);
|
|
666
|
+
|
|
667
|
+
case QUADBEZIERTO:
|
|
668
|
+
/* calculate the polynomial coefficients */
|
|
669
|
+
bx = controlPoints[0].x - startPoint.x;
|
|
670
|
+
ax = endPoint.x - controlPoints[0].x - bx;
|
|
671
|
+
by = controlPoints[0].y - startPoint.y;
|
|
672
|
+
ay = endPoint.y - controlPoints[0].y - by;
|
|
673
|
+
|
|
674
|
+
/* calculate the curve point at parameter value t */
|
|
675
|
+
tSquared = t * t;
|
|
676
|
+
tDoubled = 2F * t;
|
|
677
|
+
return new RPoint((ax * tSquared) + (bx * tDoubled) + startPoint.x, (ay * tSquared) + (by * tDoubled) + startPoint.y);
|
|
678
|
+
|
|
679
|
+
case CUBICBEZIERTO:
|
|
680
|
+
/* calculate the polynomial coefficients */
|
|
681
|
+
cx = 3F * (controlPoints[0].x - startPoint.x);
|
|
682
|
+
bx = 3F * (controlPoints[1].x - controlPoints[0].x) - cx;
|
|
683
|
+
ax = endPoint.x - startPoint.x - cx - bx;
|
|
684
|
+
cy = 3F * (controlPoints[0].y - startPoint.y);
|
|
685
|
+
by = 3F * (controlPoints[1].y - controlPoints[0].y) - cy;
|
|
686
|
+
ay = endPoint.y - startPoint.y - cy - by;
|
|
687
|
+
|
|
688
|
+
/* calculate the curve point at parameter value t */
|
|
689
|
+
tSquared = t * t;
|
|
690
|
+
tCubed = tSquared * t;
|
|
691
|
+
return new RPoint((ax * tCubed) + (bx * tSquared) + (cx * t) + startPoint.x, (ay * tCubed) + (by * tSquared) + (cy * t) + startPoint.y);
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
return new RPoint();
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
/**
|
|
698
|
+
* Use this to return the tangents on the curve. It returns the vectors in the
|
|
699
|
+
* form of an array of RPoint.
|
|
700
|
+
*
|
|
701
|
+
getTangents
|
|
702
|
+
* @param segments int, the number of segments in which to divide the curve.
|
|
703
|
+
* @return RPoint[], the tangent vectors returned in an array.
|
|
704
|
+
*
|
|
705
|
+
*/
|
|
706
|
+
public RPoint[] getTangents(int segments) {
|
|
707
|
+
RPoint[] result;
|
|
708
|
+
float dt, t;
|
|
709
|
+
switch (commandType) {
|
|
710
|
+
case LINETO:
|
|
711
|
+
result = new RPoint[2];
|
|
712
|
+
result[0] = startPoint;
|
|
713
|
+
result[1] = endPoint;
|
|
714
|
+
return result;
|
|
715
|
+
case QUADBEZIERTO:
|
|
716
|
+
case CUBICBEZIERTO:
|
|
717
|
+
result = new RPoint[segments];
|
|
718
|
+
dt = 1F / segments;
|
|
719
|
+
t = 0F;
|
|
720
|
+
for (int i = 0; i < segments; i++) {
|
|
721
|
+
result[i] = getTangent(t);
|
|
722
|
+
t += dt;
|
|
357
723
|
}
|
|
724
|
+
return result;
|
|
358
725
|
}
|
|
726
|
+
return null;
|
|
727
|
+
}
|
|
359
728
|
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
* segmentator and set the segmentator to ADAPTATIVE.
|
|
363
|
-
*
|
|
364
|
-
* @eexample setSegmentAngle
|
|
365
|
-
* @param segmentAngleTolerance an angle from 0 to PI/2 it defines the
|
|
366
|
-
* maximum angle between segments.
|
|
367
|
-
*
|
|
368
|
-
*/
|
|
369
|
-
public static void setSegmentAngle(float segmentAngleTolerance) {
|
|
370
|
-
//segmentType = ADAPTATIVE;
|
|
729
|
+
@Override
|
|
730
|
+
public RPoint[] getTangents() {
|
|
371
731
|
|
|
372
|
-
|
|
373
|
-
|
|
732
|
+
return getTangents(100);
|
|
733
|
+
}
|
|
374
734
|
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
* @eexample setSegmentLength
|
|
380
|
-
* @param segmentLngth the length of each resulting segment.
|
|
735
|
+
/**
|
|
736
|
+
* Use this to return a specific tangent on the curve. It returns the RPoint
|
|
737
|
+
* representing the tangent vector for a given value of the advancement
|
|
738
|
+
* parameter t on the curve.
|
|
381
739
|
*
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
segmentLength = segmentLngth;
|
|
387
|
-
} else {
|
|
388
|
-
segmentLength = 4;
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
/**
|
|
393
|
-
* Use this to set the segmentator offset for the UNIFORMLENGTH segmentator
|
|
394
|
-
* and set the segmentator to UNIFORMLENGTH.
|
|
395
|
-
*
|
|
396
|
-
* @eexample setSegmentOffset
|
|
397
|
-
* @param segmentOffst the offset of the first point on the path.
|
|
740
|
+
getTangent
|
|
741
|
+
* @param t float, the parameter of advancement on the curve. t must have
|
|
742
|
+
* values between 0 and 1.
|
|
743
|
+
* @return RPoint, the vertice returned.
|
|
398
744
|
*
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
745
|
+
*/
|
|
746
|
+
@Override
|
|
747
|
+
public RPoint getTangent(float t) {
|
|
748
|
+
/* limit the value of t between 0 and 1 */
|
|
749
|
+
t = (t > 1F) ? 1F : t;
|
|
750
|
+
t = (t < 0F) ? 0F : t;
|
|
751
|
+
|
|
752
|
+
float dx, dy, tx, ty, t2, t_1, t_12;
|
|
753
|
+
|
|
754
|
+
switch (commandType) {
|
|
755
|
+
case LINETO:
|
|
756
|
+
dx = endPoint.x - startPoint.x;
|
|
757
|
+
dy = endPoint.y - startPoint.y;
|
|
758
|
+
return new RPoint(dx, dy);
|
|
759
|
+
|
|
760
|
+
case QUADBEZIERTO:
|
|
761
|
+
/* calculate the curve point at parameter value t */
|
|
762
|
+
tx = 2F * ((startPoint.x - 2 * controlPoints[0].x + endPoint.x) * t + (controlPoints[0].x - startPoint.x));
|
|
763
|
+
ty = 2F * ((startPoint.y - 2 * controlPoints[0].y + endPoint.y) * t + (controlPoints[0].y - startPoint.y));
|
|
764
|
+
//float norm = (float)Math.sqrt(tx*tx + ty*ty);
|
|
765
|
+
//return new RPoint(tx/norm,ty/norm);
|
|
766
|
+
return new RPoint(tx, ty);
|
|
767
|
+
|
|
768
|
+
case CUBICBEZIERTO:
|
|
769
|
+
/* calculate the curve point at parameter value t */
|
|
770
|
+
t2 = t * t;
|
|
771
|
+
t_1 = 1 - t;
|
|
772
|
+
t_12 = t_1 * t_1;
|
|
773
|
+
|
|
774
|
+
return new RPoint(-3F * t_12 * startPoint.x + 3F * (3F * t2 - 4F * t + 1F) * controlPoints[0].x + 3F * t * (2F - 3F * t) * controlPoints[1].x + 3F * t2 * endPoint.x, -3F * t_12 * startPoint.y + 3F * (3F * t2 - 4F * t + 1F) * controlPoints[0].y + 3F * t * (2F - 3F * t) * controlPoints[1].y + 3F * t2 * endPoint.y);
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
return new RPoint();
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
/**
|
|
781
|
+
* Use this to return arc length of a curve. It returns the float representing
|
|
782
|
+
* the length given the value of the advancement parameter t on the curve. The
|
|
783
|
+
* current implementation of this function is very slow, not recommended for
|
|
784
|
+
* using during frame draw.
|
|
420
785
|
*
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
segmentLines = false;
|
|
426
|
-
segmentStps = 0F;
|
|
427
|
-
} else {
|
|
428
|
-
segmentLines = true;
|
|
429
|
-
}
|
|
430
|
-
// Set the parameters
|
|
431
|
-
segmentStps = Math.abs(segmentStps);
|
|
432
|
-
if (segmentStps > 0.0F && segmentStps < 1.0F) {
|
|
433
|
-
segmentSteps = (int) (1F / segmentStps);
|
|
434
|
-
} else {
|
|
435
|
-
segmentSteps = (int) segmentStps;
|
|
436
|
-
}
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
protected void saveSegmentatorContext() {
|
|
440
|
-
oldSegmentType = RCommand.segmentType;
|
|
441
|
-
|
|
442
|
-
/* Parameters for ADAPTATIVE (dependent of the PGraphics on which drawing) */
|
|
443
|
-
oldSegmentGfxStrokeWeight = RCommand.segmentGfxStrokeWeight;
|
|
444
|
-
oldSegmentGfxScale = RCommand.segmentGfxScale;
|
|
445
|
-
oldSegmentApproxScale = RCommand.segmentApproxScale;
|
|
446
|
-
oldSegmentDistTolSqr = RCommand.segmentDistTolSqr;
|
|
447
|
-
oldSegmentDistTolMnhttn = RCommand.segmentDistTolMnhttn;
|
|
448
|
-
oldSegmentAngleTol = RCommand.segmentAngleTol;
|
|
449
|
-
oldSegmentCuspLimit = RCommand.segmentCuspLimit;
|
|
450
|
-
|
|
451
|
-
/* Parameters for UNIFORMLENGTH (dependent of the PGraphics on which drawing) */
|
|
452
|
-
oldSegmentLength = RCommand.segmentLength;
|
|
453
|
-
oldSegmentOffset = RCommand.segmentOffset;
|
|
454
|
-
oldSegmentAccOffset = RCommand.segmentAccOffset;
|
|
455
|
-
|
|
456
|
-
/* Parameters for UNIFORMSTEP */
|
|
457
|
-
oldSegmentSteps = RCommand.segmentSteps;
|
|
458
|
-
oldSegmentLines = RCommand.segmentLines;
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
protected void restoreSegmentatorContext() {
|
|
462
|
-
RCommand.segmentType = oldSegmentType;
|
|
463
|
-
|
|
464
|
-
/* Parameters for ADAPTATIVE (dependent of the PGraphics on which drawing) */
|
|
465
|
-
RCommand.segmentGfxStrokeWeight = oldSegmentGfxStrokeWeight;
|
|
466
|
-
RCommand.segmentGfxScale = oldSegmentGfxScale;
|
|
467
|
-
RCommand.segmentApproxScale = oldSegmentApproxScale;
|
|
468
|
-
RCommand.segmentDistTolSqr = oldSegmentDistTolSqr;
|
|
469
|
-
RCommand.segmentDistTolMnhttn = oldSegmentDistTolMnhttn;
|
|
470
|
-
RCommand.segmentAngleTol = oldSegmentAngleTol;
|
|
471
|
-
RCommand.segmentCuspLimit = oldSegmentCuspLimit;
|
|
472
|
-
|
|
473
|
-
/* Parameters for UNIFORMLENGTH (dependent of the PGraphics on which drawing) */
|
|
474
|
-
RCommand.segmentLength = oldSegmentLength;
|
|
475
|
-
RCommand.segmentOffset = oldSegmentOffset;
|
|
476
|
-
RCommand.segmentAccOffset = oldSegmentAccOffset;
|
|
477
|
-
|
|
478
|
-
/* Parameters for UNIFORMSTEP */
|
|
479
|
-
RCommand.segmentSteps = oldSegmentSteps;
|
|
480
|
-
RCommand.segmentLines = oldSegmentLines;
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
/**
|
|
484
|
-
* Use this to return the number of control points of the curve.
|
|
485
|
-
*
|
|
486
|
-
* @eexample countControlPoints
|
|
487
|
-
* @return int, the number of control points.
|
|
786
|
+
RCommand_getCurveLength
|
|
787
|
+
* @param t float, the parameter of advancement on the curve. t must have
|
|
788
|
+
* values between 0 and 1.
|
|
789
|
+
* @return float, the length returned.
|
|
488
790
|
*
|
|
489
|
-
*/
|
|
490
|
-
public int countControlPoints() {
|
|
491
|
-
if (controlPoints == null) {
|
|
492
|
-
return 0;
|
|
493
|
-
}
|
|
494
|
-
return controlPoints.length;
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
/**
|
|
498
|
-
* Use this to return the command type.
|
|
499
|
-
*
|
|
500
|
-
* @eexample getCommandType
|
|
501
|
-
* @return int, an integer which can take the following values:
|
|
502
|
-
* RCommand.LINETO, RCommand.QUADBEZIERTO, RCommand.CUBICBEZIERTO.
|
|
503
791
|
*
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
792
|
+
*/
|
|
793
|
+
public float getCurveLength(float t) {
|
|
794
|
+
|
|
795
|
+
/* limit the value of t between 0 and 1 */
|
|
796
|
+
t = (t > 1F) ? 1F : t;
|
|
797
|
+
t = (t < 0F) ? 0F : t;
|
|
798
|
+
|
|
799
|
+
float dx, dy, dx2, dy2, t2;
|
|
800
|
+
|
|
801
|
+
switch (commandType) {
|
|
802
|
+
case LINETO:
|
|
803
|
+
dx = endPoint.x - startPoint.x;
|
|
804
|
+
dy = endPoint.y - startPoint.y;
|
|
805
|
+
dx2 = dx * dx;
|
|
806
|
+
dy2 = dy * dy;
|
|
807
|
+
t2 = t * t;
|
|
808
|
+
//RG.parent().println("RCommand/LINETO::: getCurveLength: " + (float)Math.sqrt(dx2*t2 + dy2*t2));
|
|
809
|
+
return (float) Math.sqrt(dx2 * t2 + dy2 * t2);
|
|
810
|
+
|
|
811
|
+
case QUADBEZIERTO:
|
|
812
|
+
/* calculate the curve point at parameter value t */
|
|
813
|
+
return quadBezierLength();
|
|
814
|
+
|
|
815
|
+
case CUBICBEZIERTO:
|
|
816
|
+
/* calculate the curve point at parameter value t */
|
|
817
|
+
return cubicBezierLength();
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
return -1F;
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
/**
|
|
824
|
+
* Use this to return arc length of a curve. It returns the float representing
|
|
825
|
+
* the length given the value of the advancement parameter t on the curve. The
|
|
826
|
+
* current implementation of this function is very slow, not recommended for
|
|
827
|
+
* using during frame draw.
|
|
515
828
|
*
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
return startPoint;
|
|
519
|
-
}
|
|
520
|
-
|
|
521
|
-
/**
|
|
522
|
-
* Use this to return the end point of the curve.
|
|
523
|
-
*
|
|
524
|
-
* @eexample getEndPoint
|
|
525
|
-
* @return RPoint, the end point of the curve.
|
|
526
|
-
* @invisible
|
|
829
|
+
RCommand_getCurveLength
|
|
830
|
+
* @return float, the length returned.
|
|
527
831
|
*
|
|
528
|
-
*/
|
|
529
|
-
RPoint getEndPoint() {
|
|
530
|
-
return endPoint;
|
|
531
|
-
}
|
|
532
|
-
|
|
533
|
-
/**
|
|
534
|
-
* Use this to return the control points of the curve. It returns the points
|
|
535
|
-
* in the way of an array of RPoint.
|
|
536
|
-
*
|
|
537
|
-
* @eexample getControlPoints
|
|
538
|
-
* @return RPoint[], the control points returned in an array.
|
|
539
|
-
* @invisible
|
|
540
832
|
*
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
833
|
+
*/
|
|
834
|
+
@Override
|
|
835
|
+
public float getCurveLength() {
|
|
836
|
+
return getCurveLength(1F);
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
@Override
|
|
840
|
+
public RPoint[][] getPointsInPaths() {
|
|
841
|
+
PApplet.println("Feature not yet implemented for this class.");
|
|
842
|
+
return null;
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
@Override
|
|
846
|
+
public RPoint[][] getHandlesInPaths() {
|
|
847
|
+
PApplet.println("Feature not yet implemented for this class.");
|
|
848
|
+
return null;
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
@Override
|
|
852
|
+
public RPoint[][] getTangentsInPaths() {
|
|
853
|
+
PApplet.println("Feature not yet implemented for this class.");
|
|
854
|
+
return null;
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
@Override
|
|
858
|
+
public boolean contains(RPoint p) {
|
|
859
|
+
PApplet.println("Feature not yet implemented for this class.");
|
|
860
|
+
return false;
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
/**
|
|
864
|
+
* Use this method to draw the command.
|
|
552
865
|
*
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
866
|
+
drawCommand
|
|
867
|
+
* @param g PGraphics, the graphics object on which to draw the command
|
|
868
|
+
*/
|
|
869
|
+
@Override
|
|
870
|
+
public void draw(PGraphics g) {
|
|
871
|
+
RPoint[] points = getPoints();
|
|
872
|
+
if (points == null) {
|
|
873
|
+
return;
|
|
874
|
+
}
|
|
875
|
+
g.beginShape();
|
|
876
|
+
for (RPoint point : points) {
|
|
877
|
+
g.vertex(point.x, point.y);
|
|
878
|
+
}
|
|
879
|
+
g.endShape();
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
/**
|
|
883
|
+
* Use this method to draw the command.
|
|
884
|
+
*
|
|
885
|
+
drawCommand
|
|
886
|
+
* @param a the applet object on which to draw the command
|
|
887
|
+
*/
|
|
888
|
+
@Override
|
|
889
|
+
public void draw(PApplet a) {
|
|
890
|
+
RPoint[] points = getPoints();
|
|
891
|
+
if (points == null) {
|
|
892
|
+
return;
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
a.beginShape();
|
|
896
|
+
for (RPoint point : points) {
|
|
897
|
+
a.vertex(point.x, point.y);
|
|
898
|
+
}
|
|
899
|
+
a.endShape();
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
/**
|
|
903
|
+
* Use this to return the start, control and end points of the curve. It
|
|
904
|
+
* returns the points in the way of an array of RPoint.
|
|
905
|
+
*
|
|
906
|
+
getHandles
|
|
907
|
+
* @return RPoint[], the vertices returned in an array.
|
|
908
|
+
*
|
|
909
|
+
*/
|
|
910
|
+
@Override
|
|
911
|
+
public RPoint[] getHandles() {
|
|
912
|
+
RPoint[] result;
|
|
913
|
+
if (controlPoints == null) {
|
|
914
|
+
result = new RPoint[2];
|
|
915
|
+
result[0] = startPoint;
|
|
916
|
+
result[1] = endPoint;
|
|
917
|
+
} else {
|
|
918
|
+
result = new RPoint[controlPoints.length + 2];
|
|
919
|
+
result[0] = startPoint;
|
|
920
|
+
System.arraycopy(controlPoints, 0, result, 1, controlPoints.length);
|
|
921
|
+
result[result.length - 1] = endPoint;
|
|
922
|
+
}
|
|
923
|
+
return result;
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
/**
|
|
927
|
+
* Returns two commands resulting of splitting the command.
|
|
928
|
+
*
|
|
929
|
+
split
|
|
930
|
+
* @param t the advancement on the curve where command should be split.
|
|
931
|
+
* @return RPoint[], the tangent vectors returned in an array.
|
|
932
|
+
*
|
|
933
|
+
*/
|
|
934
|
+
public RCommand[] split(float t) {
|
|
560
935
|
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
RCommand.segmentAccOffset = 0F;
|
|
565
|
-
}
|
|
936
|
+
switch (commandType) {
|
|
937
|
+
case LINETO:
|
|
938
|
+
return splitLine(t);
|
|
566
939
|
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
case ADAPTATIVE:
|
|
570
|
-
switch (commandType) {
|
|
571
|
-
case LINETO:
|
|
572
|
-
result = new RPoint[2];
|
|
573
|
-
result[0] = startPoint;
|
|
574
|
-
result[1] = endPoint;
|
|
575
|
-
break;
|
|
576
|
-
|
|
577
|
-
case QUADBEZIERTO:
|
|
578
|
-
quadBezierAdaptative();
|
|
579
|
-
result = curvePoints;
|
|
580
|
-
curvePoints = null;
|
|
581
|
-
break;
|
|
582
|
-
|
|
583
|
-
case CUBICBEZIERTO:
|
|
584
|
-
cubicBezierAdaptative();
|
|
585
|
-
result = curvePoints;
|
|
586
|
-
curvePoints = null;
|
|
587
|
-
break;
|
|
588
|
-
}
|
|
589
|
-
break;
|
|
590
|
-
|
|
591
|
-
case UNIFORMLENGTH:
|
|
592
|
-
switch (commandType) {
|
|
593
|
-
case LINETO:
|
|
594
|
-
lineUniformLength();
|
|
595
|
-
result = curvePoints;
|
|
596
|
-
curvePoints = null;
|
|
597
|
-
break;
|
|
598
|
-
|
|
599
|
-
case QUADBEZIERTO:
|
|
600
|
-
quadBezierUniformLength();
|
|
601
|
-
result = curvePoints;
|
|
602
|
-
curvePoints = null;
|
|
603
|
-
break;
|
|
604
|
-
|
|
605
|
-
case CUBICBEZIERTO:
|
|
606
|
-
cubicBezierUniformLength();
|
|
607
|
-
result = curvePoints;
|
|
608
|
-
curvePoints = null;
|
|
609
|
-
break;
|
|
610
|
-
}
|
|
611
|
-
break;
|
|
612
|
-
|
|
613
|
-
case UNIFORMSTEP:
|
|
614
|
-
switch (commandType) {
|
|
615
|
-
case LINETO:
|
|
616
|
-
if (segmentLines) {
|
|
617
|
-
lineUniformStep();
|
|
618
|
-
result = curvePoints;
|
|
619
|
-
curvePoints = null;
|
|
620
|
-
} else {
|
|
621
|
-
result = new RPoint[2];
|
|
622
|
-
result[0] = startPoint;
|
|
623
|
-
result[1] = endPoint;
|
|
624
|
-
}
|
|
625
|
-
break;
|
|
626
|
-
|
|
627
|
-
case QUADBEZIERTO:
|
|
628
|
-
quadBezierUniformStep();
|
|
629
|
-
result = curvePoints;
|
|
630
|
-
curvePoints = null;
|
|
631
|
-
break;
|
|
632
|
-
|
|
633
|
-
case CUBICBEZIERTO:
|
|
634
|
-
cubicBezierUniformStep();
|
|
635
|
-
result = curvePoints;
|
|
636
|
-
curvePoints = null;
|
|
637
|
-
break;
|
|
638
|
-
}
|
|
639
|
-
break;
|
|
640
|
-
}
|
|
940
|
+
case QUADBEZIERTO:
|
|
941
|
+
return splitQuadBezier(t);
|
|
641
942
|
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
}
|
|
943
|
+
case CUBICBEZIERTO:
|
|
944
|
+
return splitCubicBezier(t);
|
|
645
945
|
|
|
646
|
-
return result;
|
|
647
946
|
}
|
|
947
|
+
return null;
|
|
948
|
+
}
|
|
648
949
|
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
* for a given advancement parameter t on the curve.
|
|
652
|
-
*
|
|
653
|
-
* @eexample getPoint
|
|
654
|
-
* @param t float, the parameter of advancement on the curve. t must have
|
|
655
|
-
* values between 0 and 1.
|
|
656
|
-
* @return RPoint, the vertice returned.
|
|
950
|
+
/**
|
|
951
|
+
* Taken from: http://steve.hollasch.net/cgindex/curves/cbezarclen.html
|
|
657
952
|
*
|
|
658
|
-
|
|
659
|
-
@Override
|
|
660
|
-
public RPoint getPoint(float t) {
|
|
661
|
-
/* limit the value of t between 0 and 1 */
|
|
662
|
-
t = (t > 1F) ? 1F : t;
|
|
663
|
-
t = (t < 0F) ? 0F : t;
|
|
664
|
-
float ax, bx, cx;
|
|
665
|
-
float ay, by, cy;
|
|
666
|
-
float tSquared, tDoubled, tCubed;
|
|
667
|
-
float dx, dy;
|
|
668
|
-
|
|
669
|
-
switch (commandType) {
|
|
670
|
-
case LINETO:
|
|
671
|
-
dx = endPoint.x - startPoint.x;
|
|
672
|
-
dy = endPoint.y - startPoint.y;
|
|
673
|
-
return new RPoint(startPoint.x + dx * t, startPoint.y + dy * t);
|
|
674
|
-
|
|
675
|
-
case QUADBEZIERTO:
|
|
676
|
-
/* calculate the polynomial coefficients */
|
|
677
|
-
bx = controlPoints[0].x - startPoint.x;
|
|
678
|
-
ax = endPoint.x - controlPoints[0].x - bx;
|
|
679
|
-
by = controlPoints[0].y - startPoint.y;
|
|
680
|
-
ay = endPoint.y - controlPoints[0].y - by;
|
|
681
|
-
|
|
682
|
-
/* calculate the curve point at parameter value t */
|
|
683
|
-
tSquared = t * t;
|
|
684
|
-
tDoubled = 2F * t;
|
|
685
|
-
return new RPoint((ax * tSquared) + (bx * tDoubled) + startPoint.x, (ay * tSquared) + (by * tDoubled) + startPoint.y);
|
|
686
|
-
|
|
687
|
-
case CUBICBEZIERTO:
|
|
688
|
-
/* calculate the polynomial coefficients */
|
|
689
|
-
cx = 3F * (controlPoints[0].x - startPoint.x);
|
|
690
|
-
bx = 3F * (controlPoints[1].x - controlPoints[0].x) - cx;
|
|
691
|
-
ax = endPoint.x - startPoint.x - cx - bx;
|
|
692
|
-
cy = 3F * (controlPoints[0].y - startPoint.y);
|
|
693
|
-
by = 3F * (controlPoints[1].y - controlPoints[0].y) - cy;
|
|
694
|
-
ay = endPoint.y - startPoint.y - cy - by;
|
|
695
|
-
|
|
696
|
-
/* calculate the curve point at parameter value t */
|
|
697
|
-
tSquared = t * t;
|
|
698
|
-
tCubed = tSquared * t;
|
|
699
|
-
return new RPoint((ax * tCubed) + (bx * tSquared) + (cx * t) + startPoint.x, (ay * tCubed) + (by * tSquared) + (cy * t) + startPoint.y);
|
|
700
|
-
}
|
|
701
|
-
|
|
702
|
-
return new RPoint();
|
|
703
|
-
}
|
|
704
|
-
|
|
705
|
-
/**
|
|
706
|
-
* Use this to return the tangents on the curve. It returns the vectors in
|
|
707
|
-
* the form of an array of RPoint.
|
|
708
|
-
*
|
|
709
|
-
* @eexample getTangents
|
|
710
|
-
* @param segments int, the number of segments in which to divide the curve.
|
|
711
|
-
* @return RPoint[], the tangent vectors returned in an array.
|
|
953
|
+
* who took it from: Schneider's Bezier curve-fitter
|
|
712
954
|
*
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
result[0] = startPoint;
|
|
721
|
-
result[1] = endPoint;
|
|
722
|
-
return result;
|
|
723
|
-
case QUADBEZIERTO:
|
|
724
|
-
case CUBICBEZIERTO:
|
|
725
|
-
result = new RPoint[segments];
|
|
726
|
-
dt = 1F / segments;
|
|
727
|
-
t = 0F;
|
|
728
|
-
for (int i = 0; i < segments; i++) {
|
|
729
|
-
result[i] = getTangent(t);
|
|
730
|
-
t += dt;
|
|
731
|
-
}
|
|
732
|
-
return result;
|
|
733
|
-
}
|
|
734
|
-
return null;
|
|
955
|
+
*/
|
|
956
|
+
private RCommand[] splitCubicBezier(float t) {
|
|
957
|
+
RPoint[][] triangleMatrix = new RPoint[4][4];
|
|
958
|
+
for (int i = 0; i <= 3; i++) {
|
|
959
|
+
for (int j = 0; j <= 3; j++) {
|
|
960
|
+
triangleMatrix[i][j] = new RPoint();
|
|
961
|
+
}
|
|
735
962
|
}
|
|
736
963
|
|
|
737
|
-
|
|
738
|
-
public RPoint[] getTangents() {
|
|
964
|
+
RPoint[] ctrlPoints = this.getHandles();
|
|
739
965
|
|
|
740
|
-
|
|
966
|
+
// Copy control points to triangle matrix
|
|
967
|
+
for (int i = 0; i <= 3; i++) {
|
|
968
|
+
triangleMatrix[0][i].x = ctrlPoints[i].x;
|
|
969
|
+
triangleMatrix[0][i].y = ctrlPoints[i].y;
|
|
741
970
|
}
|
|
742
971
|
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
* @param t float, the parameter of advancement on the curve. t must have
|
|
750
|
-
* values between 0 and 1.
|
|
751
|
-
* @return RPoint, the vertice returned.
|
|
752
|
-
*
|
|
753
|
-
*/
|
|
754
|
-
@Override
|
|
755
|
-
public RPoint getTangent(float t) {
|
|
756
|
-
/* limit the value of t between 0 and 1 */
|
|
757
|
-
t = (t > 1F) ? 1F : t;
|
|
758
|
-
t = (t < 0F) ? 0F : t;
|
|
759
|
-
|
|
760
|
-
float dx, dy, tx, ty, t2, t_1, t_12;
|
|
761
|
-
|
|
762
|
-
switch (commandType) {
|
|
763
|
-
case LINETO:
|
|
764
|
-
dx = endPoint.x - startPoint.x;
|
|
765
|
-
dy = endPoint.y - startPoint.y;
|
|
766
|
-
return new RPoint(dx, dy);
|
|
767
|
-
|
|
768
|
-
case QUADBEZIERTO:
|
|
769
|
-
/* calculate the curve point at parameter value t */
|
|
770
|
-
tx = 2F * ((startPoint.x - 2 * controlPoints[0].x + endPoint.x) * t + (controlPoints[0].x - startPoint.x));
|
|
771
|
-
ty = 2F * ((startPoint.y - 2 * controlPoints[0].y + endPoint.y) * t + (controlPoints[0].y - startPoint.y));
|
|
772
|
-
//float norm = (float)Math.sqrt(tx*tx + ty*ty);
|
|
773
|
-
//return new RPoint(tx/norm,ty/norm);
|
|
774
|
-
return new RPoint(tx, ty);
|
|
775
|
-
|
|
776
|
-
case CUBICBEZIERTO:
|
|
777
|
-
/* calculate the curve point at parameter value t */
|
|
778
|
-
t2 = t * t;
|
|
779
|
-
t_1 = 1 - t;
|
|
780
|
-
t_12 = t_1 * t_1;
|
|
781
|
-
|
|
782
|
-
return new RPoint(-3F * t_12 * startPoint.x + 3F * (3F * t2 - 4F * t + 1F) * controlPoints[0].x + 3F * t * (2F - 3F * t) * controlPoints[1].x + 3F * t2 * endPoint.x, -3F * t_12 * startPoint.y + 3F * (3F * t2 - 4F * t + 1F) * controlPoints[0].y + 3F * t * (2F - 3F * t) * controlPoints[1].y + 3F * t2 * endPoint.y);
|
|
783
|
-
}
|
|
784
|
-
|
|
785
|
-
return new RPoint();
|
|
972
|
+
// Triangle computation
|
|
973
|
+
for (int i = 1; i <= 3; i++) {
|
|
974
|
+
for (int j = 0; j <= 3 - i; j++) {
|
|
975
|
+
triangleMatrix[i][j].x = (1 - t) * triangleMatrix[i - 1][j].x + t * triangleMatrix[i - 1][j + 1].x;
|
|
976
|
+
triangleMatrix[i][j].y = (1 - t) * triangleMatrix[i - 1][j].y + t * triangleMatrix[i - 1][j + 1].y;
|
|
977
|
+
}
|
|
786
978
|
}
|
|
787
979
|
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
*
|
|
794
|
-
* @eexample RCommand_getCurveLength
|
|
795
|
-
* @param t float, the parameter of advancement on the curve. t must have
|
|
796
|
-
* values between 0 and 1.
|
|
797
|
-
* @return float, the length returned.
|
|
798
|
-
* @invisible
|
|
799
|
-
*
|
|
800
|
-
*/
|
|
801
|
-
public float getCurveLength(float t) {
|
|
802
|
-
|
|
803
|
-
/* limit the value of t between 0 and 1 */
|
|
804
|
-
t = (t > 1F) ? 1F : t;
|
|
805
|
-
t = (t < 0F) ? 0F : t;
|
|
806
|
-
|
|
807
|
-
float dx, dy, dx2, dy2, t2;
|
|
808
|
-
|
|
809
|
-
switch (commandType) {
|
|
810
|
-
case LINETO:
|
|
811
|
-
dx = endPoint.x - startPoint.x;
|
|
812
|
-
dy = endPoint.y - startPoint.y;
|
|
813
|
-
dx2 = dx * dx;
|
|
814
|
-
dy2 = dy * dy;
|
|
815
|
-
t2 = t * t;
|
|
816
|
-
//RG.parent().println("RCommand/LINETO::: getCurveLength: " + (float)Math.sqrt(dx2*t2 + dy2*t2));
|
|
817
|
-
return (float) Math.sqrt(dx2 * t2 + dy2 * t2);
|
|
818
|
-
|
|
819
|
-
case QUADBEZIERTO:
|
|
820
|
-
/* calculate the curve point at parameter value t */
|
|
821
|
-
return quadBezierLength();
|
|
822
|
-
|
|
823
|
-
case CUBICBEZIERTO:
|
|
824
|
-
/* calculate the curve point at parameter value t */
|
|
825
|
-
return cubicBezierLength();
|
|
826
|
-
}
|
|
980
|
+
RCommand[] result = new RCommand[2];
|
|
981
|
+
result[0] = createBezier4(startPoint, triangleMatrix[1][0], triangleMatrix[2][0], triangleMatrix[3][0]);
|
|
982
|
+
result[1] = createBezier4(triangleMatrix[3][0], triangleMatrix[2][1], triangleMatrix[1][2], endPoint);
|
|
983
|
+
return result;
|
|
984
|
+
}
|
|
827
985
|
|
|
828
|
-
|
|
986
|
+
private RCommand[] splitQuadBezier(float t) {
|
|
987
|
+
RPoint[][] triangleMatrix = new RPoint[3][3];
|
|
988
|
+
for (int i = 0; i <= 2; i++) {
|
|
989
|
+
for (int j = 0; j <= 2; j++) {
|
|
990
|
+
triangleMatrix[i][j] = new RPoint();
|
|
991
|
+
}
|
|
829
992
|
}
|
|
830
993
|
|
|
831
|
-
|
|
832
|
-
* Use this to return arc length of a curve. It returns the float
|
|
833
|
-
* representing the length given the value of the advancement parameter t on
|
|
834
|
-
* the curve. The current implementation of this function is very slow, not
|
|
835
|
-
* recommended for using during frame draw.
|
|
836
|
-
*
|
|
837
|
-
* @eexample RCommand_getCurveLength
|
|
838
|
-
* @return float, the length returned.
|
|
839
|
-
* @invisible
|
|
840
|
-
*
|
|
841
|
-
*/
|
|
842
|
-
@Override
|
|
843
|
-
public float getCurveLength() {
|
|
844
|
-
return getCurveLength(1F);
|
|
845
|
-
}
|
|
994
|
+
RPoint[] ctrlPoints = this.getHandles();
|
|
846
995
|
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
return null;
|
|
996
|
+
// Copy control points to triangle matrix
|
|
997
|
+
for (int i = 0; i <= 2; i++) {
|
|
998
|
+
triangleMatrix[0][i] = ctrlPoints[i];
|
|
851
999
|
}
|
|
852
1000
|
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
1001
|
+
// Triangle computation
|
|
1002
|
+
for (int i = 1; i <= 2; i++) {
|
|
1003
|
+
for (int j = 0; j <= 2 - i; j++) {
|
|
1004
|
+
triangleMatrix[i][j].x = (1 - t) * triangleMatrix[i - 1][j].x + t * triangleMatrix[i - 1][j + 1].x;
|
|
1005
|
+
triangleMatrix[i][j].y = (1 - t) * triangleMatrix[i - 1][j].y + t * triangleMatrix[i - 1][j + 1].y;
|
|
1006
|
+
}
|
|
857
1007
|
}
|
|
858
1008
|
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
1009
|
+
RCommand[] result = new RCommand[2];
|
|
1010
|
+
result[0] = createBezier3(startPoint, triangleMatrix[1][0], triangleMatrix[2][0]);
|
|
1011
|
+
result[1] = createBezier3(triangleMatrix[2][0], triangleMatrix[1][1], endPoint);
|
|
1012
|
+
return result;
|
|
1013
|
+
}
|
|
864
1014
|
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
1015
|
+
private RCommand[] splitLine(float t) {
|
|
1016
|
+
RPoint[][] triangleMatrix = new RPoint[2][2];
|
|
1017
|
+
for (int i = 0; i <= 1; i++) {
|
|
1018
|
+
for (int j = 0; j <= 1; j++) {
|
|
1019
|
+
triangleMatrix[i][j] = new RPoint();
|
|
1020
|
+
}
|
|
869
1021
|
}
|
|
870
1022
|
|
|
871
|
-
|
|
872
|
-
* Use this method to draw the command.
|
|
873
|
-
*
|
|
874
|
-
* @eexample drawCommand
|
|
875
|
-
* @param g PGraphics, the graphics object on which to draw the command
|
|
876
|
-
*/
|
|
877
|
-
@Override
|
|
878
|
-
public void draw(PGraphics g) {
|
|
879
|
-
RPoint[] points = getPoints();
|
|
880
|
-
if (points == null) {
|
|
881
|
-
return;
|
|
882
|
-
}
|
|
883
|
-
g.beginShape();
|
|
884
|
-
for (RPoint point : points) {
|
|
885
|
-
g.vertex(point.x, point.y);
|
|
886
|
-
}
|
|
887
|
-
g.endShape();
|
|
888
|
-
}
|
|
1023
|
+
RPoint[] ctrlPoints = this.getHandles();
|
|
889
1024
|
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
* @eexample drawCommand
|
|
894
|
-
* @param a the applet object on which to draw the command
|
|
895
|
-
*/
|
|
896
|
-
@Override
|
|
897
|
-
public void draw(PApplet a) {
|
|
898
|
-
RPoint[] points = getPoints();
|
|
899
|
-
if (points == null) {
|
|
900
|
-
return;
|
|
901
|
-
}
|
|
902
|
-
|
|
903
|
-
a.beginShape();
|
|
904
|
-
for (RPoint point : points) {
|
|
905
|
-
a.vertex(point.x, point.y);
|
|
906
|
-
}
|
|
907
|
-
a.endShape();
|
|
1025
|
+
// Copy control points to triangle matrix
|
|
1026
|
+
for (int i = 0; i <= 1; i++) {
|
|
1027
|
+
triangleMatrix[0][i] = ctrlPoints[i];
|
|
908
1028
|
}
|
|
909
1029
|
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
*
|
|
917
|
-
*/
|
|
918
|
-
@Override
|
|
919
|
-
public RPoint[] getHandles() {
|
|
920
|
-
RPoint[] result;
|
|
921
|
-
if (controlPoints == null) {
|
|
922
|
-
result = new RPoint[2];
|
|
923
|
-
result[0] = startPoint;
|
|
924
|
-
result[1] = endPoint;
|
|
925
|
-
} else {
|
|
926
|
-
result = new RPoint[controlPoints.length + 2];
|
|
927
|
-
result[0] = startPoint;
|
|
928
|
-
System.arraycopy(controlPoints, 0, result, 1, controlPoints.length);
|
|
929
|
-
result[result.length - 1] = endPoint;
|
|
930
|
-
}
|
|
931
|
-
return result;
|
|
1030
|
+
// Triangle computation
|
|
1031
|
+
for (int i = 1; i <= 1; i++) {
|
|
1032
|
+
for (int j = 0; j <= 1 - i; j++) {
|
|
1033
|
+
triangleMatrix[i][j].x = (1 - t) * triangleMatrix[i - 1][j].x + t * triangleMatrix[i - 1][j + 1].x;
|
|
1034
|
+
triangleMatrix[i][j].y = (1 - t) * triangleMatrix[i - 1][j].y + t * triangleMatrix[i - 1][j + 1].y;
|
|
1035
|
+
}
|
|
932
1036
|
}
|
|
933
1037
|
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
* @return RPoint[], the tangent vectors returned in an array.
|
|
940
|
-
*
|
|
941
|
-
*/
|
|
942
|
-
public RCommand[] split(float t) {
|
|
943
|
-
|
|
944
|
-
switch (commandType) {
|
|
945
|
-
case LINETO:
|
|
946
|
-
return splitLine(t);
|
|
1038
|
+
RCommand[] result = new RCommand[2];
|
|
1039
|
+
result[0] = createLine(startPoint, triangleMatrix[1][0]);
|
|
1040
|
+
result[1] = createLine(triangleMatrix[1][0], endPoint);
|
|
1041
|
+
return result;
|
|
1042
|
+
}
|
|
947
1043
|
|
|
948
|
-
|
|
949
|
-
|
|
1044
|
+
private void quadBezierAdaptative() {
|
|
1045
|
+
addCurvePoint(new RPoint(startPoint));
|
|
1046
|
+
quadBezierAdaptativeRecursive(startPoint.x, startPoint.y, controlPoints[0].x, controlPoints[0].y, endPoint.x, endPoint.y, 0);
|
|
1047
|
+
addCurvePoint(new RPoint(endPoint));
|
|
1048
|
+
}
|
|
950
1049
|
|
|
951
|
-
|
|
952
|
-
return splitCubicBezier(t);
|
|
1050
|
+
private void quadBezierAdaptativeRecursive(float x1, float y1, float x2, float y2, float x3, float y3, int level) {
|
|
953
1051
|
|
|
954
|
-
|
|
955
|
-
|
|
1052
|
+
if (level > SEGMENT_RECURSION_LIMIT) {
|
|
1053
|
+
return;
|
|
956
1054
|
}
|
|
957
1055
|
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
1056
|
+
// Calculate all the mid-points of the line segments
|
|
1057
|
+
//----------------------
|
|
1058
|
+
float x12 = (x1 + x2) / 2;
|
|
1059
|
+
float y12 = (y1 + y2) / 2;
|
|
1060
|
+
float x23 = (x2 + x3) / 2;
|
|
1061
|
+
float y23 = (y2 + y3) / 2;
|
|
1062
|
+
float x123 = (x12 + x23) / 2;
|
|
1063
|
+
float y123 = (y12 + y23) / 2;
|
|
1064
|
+
|
|
1065
|
+
float dx = x3 - x1;
|
|
1066
|
+
float dy = y3 - y1;
|
|
1067
|
+
float d = Math.abs(((x2 - x3) * dy - (y2 - y3) * dx));
|
|
1068
|
+
|
|
1069
|
+
if (d > SEGMENT_COLLINEARITY_EPSILON) {
|
|
1070
|
+
// Regular care
|
|
1071
|
+
//-----------------
|
|
1072
|
+
if (d * d <= segmentDistTolSqr * (dx * dx + dy * dy)) {
|
|
1073
|
+
// If the curvature doesn't exceed the distance_tolerance value
|
|
1074
|
+
// we tend to finish subdivisions.
|
|
1075
|
+
//----------------------
|
|
1076
|
+
if (segmentAngleTol < SEGMENT_ANGLE_TOL_EPSILON) {
|
|
1077
|
+
addCurvePoint(new RPoint(x123, y123));
|
|
1078
|
+
return;
|
|
970
1079
|
}
|
|
971
1080
|
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
triangleMatrix[0][i].y = ctrlPoints[i].y;
|
|
1081
|
+
// Angle & Cusp Condition
|
|
1082
|
+
//----------------------
|
|
1083
|
+
float da = Math.abs((float) Math.atan2(y3 - y2, x3 - x2) - (float) Math.atan2(y2 - y1, x2 - x1));
|
|
1084
|
+
if (da >= Math.PI) {
|
|
1085
|
+
da = 2 * (float) Math.PI - da;
|
|
978
1086
|
}
|
|
979
1087
|
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
}
|
|
1088
|
+
if (da < segmentAngleTol) {
|
|
1089
|
+
// Finally we can stop the recursion
|
|
1090
|
+
//----------------------
|
|
1091
|
+
addCurvePoint(new RPoint(x123, y123));
|
|
1092
|
+
return;
|
|
986
1093
|
}
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
return
|
|
1094
|
+
}
|
|
1095
|
+
} else {
|
|
1096
|
+
if (Math.abs(x1 + x3 - x2 - x2) + Math.abs(y1 + y3 - y2 - y2) <= segmentDistTolMnhttn) {
|
|
1097
|
+
addCurvePoint(new RPoint(x123, y123));
|
|
1098
|
+
return;
|
|
1099
|
+
}
|
|
992
1100
|
}
|
|
993
1101
|
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
}
|
|
1000
|
-
}
|
|
1102
|
+
// Continue subdivision
|
|
1103
|
+
//----------------------
|
|
1104
|
+
quadBezierAdaptativeRecursive(x1, y1, x12, y12, x123, y123, level + 1);
|
|
1105
|
+
quadBezierAdaptativeRecursive(x123, y123, x23, y23, x3, y3, level + 1);
|
|
1106
|
+
}
|
|
1001
1107
|
|
|
1002
|
-
|
|
1108
|
+
private void cubicBezierAdaptative() {
|
|
1109
|
+
addCurvePoint(new RPoint(startPoint));
|
|
1110
|
+
cubicBezierAdaptativeRecursive(startPoint.x, startPoint.y, controlPoints[0].x, controlPoints[0].y, controlPoints[1].x, controlPoints[1].y, endPoint.x, endPoint.y, 0);
|
|
1111
|
+
addCurvePoint(new RPoint(endPoint));
|
|
1112
|
+
}
|
|
1003
1113
|
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1114
|
+
private void cubicBezierAdaptativeRecursive(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, int level) {
|
|
1115
|
+
if (level > SEGMENT_RECURSION_LIMIT) {
|
|
1116
|
+
return;
|
|
1117
|
+
}
|
|
1008
1118
|
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1119
|
+
// Calculate all the mid-points of the line segments
|
|
1120
|
+
//----------------------
|
|
1121
|
+
float x12 = (x1 + x2) / 2;
|
|
1122
|
+
float y12 = (y1 + y2) / 2;
|
|
1123
|
+
float x23 = (x2 + x3) / 2;
|
|
1124
|
+
float y23 = (y2 + y3) / 2;
|
|
1125
|
+
float x34 = (x3 + x4) / 2;
|
|
1126
|
+
float y34 = (y3 + y4) / 2;
|
|
1127
|
+
float x123 = (x12 + x23) / 2;
|
|
1128
|
+
float y123 = (y12 + y23) / 2;
|
|
1129
|
+
float x234 = (x23 + x34) / 2;
|
|
1130
|
+
float y234 = (y23 + y34) / 2;
|
|
1131
|
+
float x1234 = (x123 + x234) / 2;
|
|
1132
|
+
float y1234 = (y123 + y234) / 2;
|
|
1133
|
+
|
|
1134
|
+
// Try to approximate the full cubic curve by a single straight line
|
|
1135
|
+
//------------------
|
|
1136
|
+
float dx = x4 - x1;
|
|
1137
|
+
float dy = y4 - y1;
|
|
1138
|
+
|
|
1139
|
+
float d2 = Math.abs(((x2 - x4) * dy - (y2 - y4) * dx));
|
|
1140
|
+
float d3 = Math.abs(((x3 - x4) * dy - (y3 - y4) * dx));
|
|
1141
|
+
float da1, da2;
|
|
1142
|
+
|
|
1143
|
+
int d2b = (d2 > SEGMENT_COLLINEARITY_EPSILON) ? 1 : 0;
|
|
1144
|
+
int d3b = (d3 > SEGMENT_COLLINEARITY_EPSILON) ? 1 : 0;
|
|
1145
|
+
switch ((d2b << 1) + d3b) {
|
|
1146
|
+
case 0:
|
|
1147
|
+
// All collinear OR p1==p4
|
|
1148
|
+
//----------------------
|
|
1149
|
+
if (Math.abs(x1 + x3 - x2 - x2)
|
|
1150
|
+
+ Math.abs(y1 + y3 - y2 - y2)
|
|
1151
|
+
+ Math.abs(x2 + x4 - x3 - x3)
|
|
1152
|
+
+ Math.abs(y2 + y4 - y3 - y3) <= segmentDistTolMnhttn) {
|
|
1153
|
+
addCurvePoint(new RPoint(x1234, y1234));
|
|
1154
|
+
return;
|
|
1015
1155
|
}
|
|
1156
|
+
break;
|
|
1016
1157
|
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1158
|
+
case 1:
|
|
1159
|
+
// p1,p2,p4 are collinear, p3 is considerable
|
|
1160
|
+
//----------------------
|
|
1161
|
+
if (d3 * d3 <= segmentDistTolSqr * (dx * dx + dy * dy)) {
|
|
1162
|
+
if (segmentAngleTol < SEGMENT_ANGLE_TOL_EPSILON) {
|
|
1163
|
+
addCurvePoint(new RPoint(x23, y23));
|
|
1164
|
+
return;
|
|
1165
|
+
}
|
|
1166
|
+
|
|
1167
|
+
// Angle Condition
|
|
1168
|
+
//----------------------
|
|
1169
|
+
da1 = Math.abs((float) Math.atan2(y4 - y3, x4 - x3) - (float) Math.atan2(y3 - y2, x3 - x2));
|
|
1170
|
+
if (da1 >= (float) Math.PI) {
|
|
1171
|
+
da1 = 2 * (float) Math.PI - da1;
|
|
1172
|
+
}
|
|
1173
|
+
|
|
1174
|
+
if (da1 < segmentAngleTol) {
|
|
1175
|
+
addCurvePoint(new RPoint(x2, y2));
|
|
1176
|
+
addCurvePoint(new RPoint(x3, y3));
|
|
1177
|
+
return;
|
|
1178
|
+
}
|
|
1022
1179
|
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
triangleMatrix[i][j] = new RPoint();
|
|
1180
|
+
if (segmentCuspLimit != 0.0) {
|
|
1181
|
+
if (da1 > segmentCuspLimit) {
|
|
1182
|
+
addCurvePoint(new RPoint(x3, y3));
|
|
1183
|
+
return;
|
|
1028
1184
|
}
|
|
1185
|
+
}
|
|
1029
1186
|
}
|
|
1187
|
+
break;
|
|
1030
1188
|
|
|
1031
|
-
|
|
1189
|
+
case 2:
|
|
1190
|
+
// p1,p3,p4 are collinear, p2 is considerable
|
|
1191
|
+
//----------------------
|
|
1192
|
+
if (d2 * d2 <= segmentDistTolSqr * (dx * dx + dy * dy)) {
|
|
1193
|
+
if (segmentAngleTol < SEGMENT_ANGLE_TOL_EPSILON) {
|
|
1194
|
+
addCurvePoint(new RPoint(x23, y23));
|
|
1195
|
+
return;
|
|
1196
|
+
}
|
|
1032
1197
|
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1198
|
+
// Angle Condition
|
|
1199
|
+
//----------------------
|
|
1200
|
+
da1 = Math.abs((float) Math.atan2(y3 - y2, x3 - x2) - (float) Math.atan2(y2 - y1, x2 - x1));
|
|
1201
|
+
if (da1 >= (float) Math.PI) {
|
|
1202
|
+
da1 = 2 * (float) Math.PI - da1;
|
|
1203
|
+
}
|
|
1204
|
+
|
|
1205
|
+
if (da1 < segmentAngleTol) {
|
|
1206
|
+
addCurvePoint(new RPoint(x2, y2));
|
|
1207
|
+
addCurvePoint(new RPoint(x3, y3));
|
|
1208
|
+
return;
|
|
1209
|
+
}
|
|
1037
1210
|
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
triangleMatrix[i][j].y = (1 - t) * triangleMatrix[i - 1][j].y + t * triangleMatrix[i - 1][j + 1].y;
|
|
1211
|
+
if (segmentCuspLimit != 0.0) {
|
|
1212
|
+
if (da1 > segmentCuspLimit) {
|
|
1213
|
+
addCurvePoint(new RPoint(x2, y2));
|
|
1214
|
+
return;
|
|
1043
1215
|
}
|
|
1216
|
+
}
|
|
1044
1217
|
}
|
|
1218
|
+
break;
|
|
1045
1219
|
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
private void quadBezierAdaptativeRecursive(float x1, float y1, float x2, float y2, float x3, float y3, int level) {
|
|
1220
|
+
case 3:
|
|
1221
|
+
// Regular care
|
|
1222
|
+
//-----------------
|
|
1223
|
+
if ((d2 + d3) * (d2 + d3) <= segmentDistTolSqr * (dx * dx + dy * dy)) {
|
|
1224
|
+
// If the curvature doesn't exceed the distance_tolerance value
|
|
1225
|
+
// we tend to finish subdivisions.
|
|
1226
|
+
//----------------------
|
|
1227
|
+
if (segmentAngleTol < SEGMENT_ANGLE_TOL_EPSILON) {
|
|
1228
|
+
addCurvePoint(new RPoint(x23, y23));
|
|
1229
|
+
return;
|
|
1230
|
+
}
|
|
1059
1231
|
|
|
1060
|
-
|
|
1232
|
+
// Angle & Cusp Condition
|
|
1233
|
+
//----------------------
|
|
1234
|
+
float a23 = (float) Math.atan2(y3 - y2, x3 - x2);
|
|
1235
|
+
da1 = Math.abs(a23 - (float) Math.atan2(y2 - y1, x2 - x1));
|
|
1236
|
+
da2 = Math.abs((float) Math.atan2(y4 - y3, x4 - x3) - a23);
|
|
1237
|
+
if (da1 >= (float) Math.PI) {
|
|
1238
|
+
da1 = 2 * (float) Math.PI - da1;
|
|
1239
|
+
}
|
|
1240
|
+
if (da2 >= (float) Math.PI) {
|
|
1241
|
+
da2 = 2 * (float) Math.PI - da2;
|
|
1242
|
+
}
|
|
1243
|
+
|
|
1244
|
+
if (da1 + da2 < segmentAngleTol) {
|
|
1245
|
+
// Finally we can stop the recursion
|
|
1246
|
+
//----------------------
|
|
1247
|
+
addCurvePoint(new RPoint(x23, y23));
|
|
1061
1248
|
return;
|
|
1062
|
-
|
|
1249
|
+
}
|
|
1063
1250
|
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
float x23 = (x2 + x3) / 2;
|
|
1069
|
-
float y23 = (y2 + y3) / 2;
|
|
1070
|
-
float x123 = (x12 + x23) / 2;
|
|
1071
|
-
float y123 = (y12 + y23) / 2;
|
|
1072
|
-
|
|
1073
|
-
float dx = x3 - x1;
|
|
1074
|
-
float dy = y3 - y1;
|
|
1075
|
-
float d = Math.abs(((x2 - x3) * dy - (y2 - y3) * dx));
|
|
1076
|
-
|
|
1077
|
-
if (d > SEGMENT_COLLINEARITY_EPSILON) {
|
|
1078
|
-
// Regular care
|
|
1079
|
-
//-----------------
|
|
1080
|
-
if (d * d <= segmentDistTolSqr * (dx * dx + dy * dy)) {
|
|
1081
|
-
// If the curvature doesn't exceed the distance_tolerance value
|
|
1082
|
-
// we tend to finish subdivisions.
|
|
1083
|
-
//----------------------
|
|
1084
|
-
if (segmentAngleTol < SEGMENT_ANGLE_TOL_EPSILON) {
|
|
1085
|
-
addCurvePoint(new RPoint(x123, y123));
|
|
1086
|
-
return;
|
|
1087
|
-
}
|
|
1088
|
-
|
|
1089
|
-
// Angle & Cusp Condition
|
|
1090
|
-
//----------------------
|
|
1091
|
-
float da = Math.abs((float) Math.atan2(y3 - y2, x3 - x2) - (float) Math.atan2(y2 - y1, x2 - x1));
|
|
1092
|
-
if (da >= Math.PI) {
|
|
1093
|
-
da = 2 * (float) Math.PI - da;
|
|
1094
|
-
}
|
|
1095
|
-
|
|
1096
|
-
if (da < segmentAngleTol) {
|
|
1097
|
-
// Finally we can stop the recursion
|
|
1098
|
-
//----------------------
|
|
1099
|
-
addCurvePoint(new RPoint(x123, y123));
|
|
1100
|
-
return;
|
|
1101
|
-
}
|
|
1251
|
+
if (segmentCuspLimit != 0.0) {
|
|
1252
|
+
if (da1 > segmentCuspLimit) {
|
|
1253
|
+
addCurvePoint(new RPoint(x2, y2));
|
|
1254
|
+
return;
|
|
1102
1255
|
}
|
|
1103
|
-
|
|
1104
|
-
if (
|
|
1105
|
-
|
|
1106
|
-
|
|
1256
|
+
|
|
1257
|
+
if (da2 > segmentCuspLimit) {
|
|
1258
|
+
addCurvePoint(new RPoint(x3, y3));
|
|
1259
|
+
return;
|
|
1107
1260
|
}
|
|
1261
|
+
}
|
|
1108
1262
|
}
|
|
1109
|
-
|
|
1110
|
-
// Continue subdivision
|
|
1111
|
-
//----------------------
|
|
1112
|
-
quadBezierAdaptativeRecursive(x1, y1, x12, y12, x123, y123, level + 1);
|
|
1113
|
-
quadBezierAdaptativeRecursive(x123, y123, x23, y23, x3, y3, level + 1);
|
|
1263
|
+
break;
|
|
1114
1264
|
}
|
|
1115
1265
|
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
private void cubicBezierAdaptativeRecursive(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, int level) {
|
|
1123
|
-
if (level > SEGMENT_RECURSION_LIMIT) {
|
|
1124
|
-
return;
|
|
1125
|
-
}
|
|
1126
|
-
|
|
1127
|
-
// Calculate all the mid-points of the line segments
|
|
1128
|
-
//----------------------
|
|
1129
|
-
float x12 = (x1 + x2) / 2;
|
|
1130
|
-
float y12 = (y1 + y2) / 2;
|
|
1131
|
-
float x23 = (x2 + x3) / 2;
|
|
1132
|
-
float y23 = (y2 + y3) / 2;
|
|
1133
|
-
float x34 = (x3 + x4) / 2;
|
|
1134
|
-
float y34 = (y3 + y4) / 2;
|
|
1135
|
-
float x123 = (x12 + x23) / 2;
|
|
1136
|
-
float y123 = (y12 + y23) / 2;
|
|
1137
|
-
float x234 = (x23 + x34) / 2;
|
|
1138
|
-
float y234 = (y23 + y34) / 2;
|
|
1139
|
-
float x1234 = (x123 + x234) / 2;
|
|
1140
|
-
float y1234 = (y123 + y234) / 2;
|
|
1266
|
+
// Continue subdivision
|
|
1267
|
+
//----------------------
|
|
1268
|
+
cubicBezierAdaptativeRecursive(x1, y1, x12, y12, x123, y123, x1234, y1234, level + 1);
|
|
1269
|
+
cubicBezierAdaptativeRecursive(x1234, y1234, x234, y234, x34, y34, x4, y4, level + 1);
|
|
1270
|
+
}
|
|
1141
1271
|
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
float d3 = Math.abs(((x3 - x4) * dy - (y3 - y4) * dx));
|
|
1149
|
-
float da1, da2;
|
|
1150
|
-
|
|
1151
|
-
int d2b = (d2 > SEGMENT_COLLINEARITY_EPSILON) ? 1 : 0;
|
|
1152
|
-
int d3b = (d3 > SEGMENT_COLLINEARITY_EPSILON) ? 1 : 0;
|
|
1153
|
-
switch ((d2b << 1) + d3b) {
|
|
1154
|
-
case 0:
|
|
1155
|
-
// All collinear OR p1==p4
|
|
1156
|
-
//----------------------
|
|
1157
|
-
if (Math.abs(x1 + x3 - x2 - x2)
|
|
1158
|
-
+ Math.abs(y1 + y3 - y2 - y2)
|
|
1159
|
-
+ Math.abs(x2 + x4 - x3 - x3)
|
|
1160
|
-
+ Math.abs(y2 + y4 - y3 - y3) <= segmentDistTolMnhttn) {
|
|
1161
|
-
addCurvePoint(new RPoint(x1234, y1234));
|
|
1162
|
-
return;
|
|
1163
|
-
}
|
|
1164
|
-
break;
|
|
1165
|
-
|
|
1166
|
-
case 1:
|
|
1167
|
-
// p1,p2,p4 are collinear, p3 is considerable
|
|
1168
|
-
//----------------------
|
|
1169
|
-
if (d3 * d3 <= segmentDistTolSqr * (dx * dx + dy * dy)) {
|
|
1170
|
-
if (segmentAngleTol < SEGMENT_ANGLE_TOL_EPSILON) {
|
|
1171
|
-
addCurvePoint(new RPoint(x23, y23));
|
|
1172
|
-
return;
|
|
1173
|
-
}
|
|
1272
|
+
private void lineUniformStep() {
|
|
1273
|
+
// If the number of steps is equal to 0 then choose a number of steps adapted to the curve
|
|
1274
|
+
int steps = segmentSteps;
|
|
1275
|
+
if (segmentSteps == 0.0F) {
|
|
1276
|
+
float dx = endPoint.x - startPoint.x;
|
|
1277
|
+
float dy = endPoint.y - startPoint.y;
|
|
1174
1278
|
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
da1 = Math.abs((float) Math.atan2(y4 - y3, x4 - x3) - (float) Math.atan2(y3 - y2, x3 - x2));
|
|
1178
|
-
if (da1 >= (float) Math.PI) {
|
|
1179
|
-
da1 = 2 * (float) Math.PI - da1;
|
|
1180
|
-
}
|
|
1181
|
-
|
|
1182
|
-
if (da1 < segmentAngleTol) {
|
|
1183
|
-
addCurvePoint(new RPoint(x2, y2));
|
|
1184
|
-
addCurvePoint(new RPoint(x3, y3));
|
|
1185
|
-
return;
|
|
1186
|
-
}
|
|
1187
|
-
|
|
1188
|
-
if (segmentCuspLimit != 0.0) {
|
|
1189
|
-
if (da1 > segmentCuspLimit) {
|
|
1190
|
-
addCurvePoint(new RPoint(x3, y3));
|
|
1191
|
-
return;
|
|
1192
|
-
}
|
|
1193
|
-
}
|
|
1194
|
-
}
|
|
1195
|
-
break;
|
|
1196
|
-
|
|
1197
|
-
case 2:
|
|
1198
|
-
// p1,p3,p4 are collinear, p2 is considerable
|
|
1199
|
-
//----------------------
|
|
1200
|
-
if (d2 * d2 <= segmentDistTolSqr * (dx * dx + dy * dy)) {
|
|
1201
|
-
if (segmentAngleTol < SEGMENT_ANGLE_TOL_EPSILON) {
|
|
1202
|
-
addCurvePoint(new RPoint(x23, y23));
|
|
1203
|
-
return;
|
|
1204
|
-
}
|
|
1279
|
+
float len = (float) Math.sqrt(dx * dx + dy * dy);
|
|
1280
|
+
steps = (int) (len * 0.25);
|
|
1205
1281
|
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
da1 = 2 * (float) Math.PI - da1;
|
|
1211
|
-
}
|
|
1212
|
-
|
|
1213
|
-
if (da1 < segmentAngleTol) {
|
|
1214
|
-
addCurvePoint(new RPoint(x2, y2));
|
|
1215
|
-
addCurvePoint(new RPoint(x3, y3));
|
|
1216
|
-
return;
|
|
1217
|
-
}
|
|
1218
|
-
|
|
1219
|
-
if (segmentCuspLimit != 0.0) {
|
|
1220
|
-
if (da1 > segmentCuspLimit) {
|
|
1221
|
-
addCurvePoint(new RPoint(x2, y2));
|
|
1222
|
-
return;
|
|
1223
|
-
}
|
|
1224
|
-
}
|
|
1225
|
-
}
|
|
1226
|
-
break;
|
|
1227
|
-
|
|
1228
|
-
case 3:
|
|
1229
|
-
// Regular care
|
|
1230
|
-
//-----------------
|
|
1231
|
-
if ((d2 + d3) * (d2 + d3) <= segmentDistTolSqr * (dx * dx + dy * dy)) {
|
|
1232
|
-
// If the curvature doesn't exceed the distance_tolerance value
|
|
1233
|
-
// we tend to finish subdivisions.
|
|
1234
|
-
//----------------------
|
|
1235
|
-
if (segmentAngleTol < SEGMENT_ANGLE_TOL_EPSILON) {
|
|
1236
|
-
addCurvePoint(new RPoint(x23, y23));
|
|
1237
|
-
return;
|
|
1238
|
-
}
|
|
1282
|
+
if (steps < 4) {
|
|
1283
|
+
steps = 4;
|
|
1284
|
+
}
|
|
1285
|
+
}
|
|
1239
1286
|
|
|
1240
|
-
|
|
1241
|
-
//----------------------
|
|
1242
|
-
float a23 = (float) Math.atan2(y3 - y2, x3 - x2);
|
|
1243
|
-
da1 = Math.abs(a23 - (float) Math.atan2(y2 - y1, x2 - x1));
|
|
1244
|
-
da2 = Math.abs((float) Math.atan2(y4 - y3, x4 - x3) - a23);
|
|
1245
|
-
if (da1 >= (float) Math.PI) {
|
|
1246
|
-
da1 = 2 * (float) Math.PI - da1;
|
|
1247
|
-
}
|
|
1248
|
-
if (da2 >= (float) Math.PI) {
|
|
1249
|
-
da2 = 2 * (float) Math.PI - da2;
|
|
1250
|
-
}
|
|
1251
|
-
|
|
1252
|
-
if (da1 + da2 < segmentAngleTol) {
|
|
1253
|
-
// Finally we can stop the recursion
|
|
1254
|
-
//----------------------
|
|
1255
|
-
addCurvePoint(new RPoint(x23, y23));
|
|
1256
|
-
return;
|
|
1257
|
-
}
|
|
1258
|
-
|
|
1259
|
-
if (segmentCuspLimit != 0.0) {
|
|
1260
|
-
if (da1 > segmentCuspLimit) {
|
|
1261
|
-
addCurvePoint(new RPoint(x2, y2));
|
|
1262
|
-
return;
|
|
1263
|
-
}
|
|
1264
|
-
|
|
1265
|
-
if (da2 > segmentCuspLimit) {
|
|
1266
|
-
addCurvePoint(new RPoint(x3, y3));
|
|
1267
|
-
return;
|
|
1268
|
-
}
|
|
1269
|
-
}
|
|
1270
|
-
}
|
|
1271
|
-
break;
|
|
1272
|
-
}
|
|
1287
|
+
float dt = 1F / steps;
|
|
1273
1288
|
|
|
1274
|
-
|
|
1275
|
-
//----------------------
|
|
1276
|
-
cubicBezierAdaptativeRecursive(x1, y1, x12, y12, x123, y123, x1234, y1234, level + 1);
|
|
1277
|
-
cubicBezierAdaptativeRecursive(x1234, y1234, x234, y234, x34, y34, x4, y4, level + 1);
|
|
1278
|
-
}
|
|
1289
|
+
float fx, fy, fdx, fdy;
|
|
1279
1290
|
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
int steps = segmentSteps;
|
|
1283
|
-
if (segmentSteps == 0.0F) {
|
|
1284
|
-
float dx = endPoint.x - startPoint.x;
|
|
1285
|
-
float dy = endPoint.y - startPoint.y;
|
|
1291
|
+
fx = startPoint.x;
|
|
1292
|
+
fdx = (endPoint.x - startPoint.x) * dt;
|
|
1286
1293
|
|
|
1287
|
-
|
|
1288
|
-
|
|
1294
|
+
fy = startPoint.y;
|
|
1295
|
+
fdy = (endPoint.y - startPoint.y) * dt;
|
|
1289
1296
|
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
}
|
|
1293
|
-
}
|
|
1297
|
+
for (int loop = 0; loop < steps; loop++) {
|
|
1298
|
+
addCurvePoint(new RPoint(fx, fy));
|
|
1294
1299
|
|
|
1295
|
-
|
|
1300
|
+
fx = fx + fdx;
|
|
1296
1301
|
|
|
1297
|
-
|
|
1302
|
+
fy = fy + fdy;
|
|
1303
|
+
}
|
|
1304
|
+
addCurvePoint(new RPoint(endPoint));
|
|
1305
|
+
}
|
|
1298
1306
|
|
|
1299
|
-
|
|
1300
|
-
fdx = (endPoint.x - startPoint.x) * dt;
|
|
1307
|
+
private void cubicBezierUniformStep() {
|
|
1301
1308
|
|
|
1302
|
-
|
|
1303
|
-
|
|
1309
|
+
// If the number of steps is equal to 0 then choose a number of steps adapted to the curve
|
|
1310
|
+
int steps = segmentSteps;
|
|
1311
|
+
if (segmentSteps == 0.0F) {
|
|
1312
|
+
float dx1 = controlPoints[0].x - startPoint.x;
|
|
1313
|
+
float dy1 = controlPoints[0].y - startPoint.y;
|
|
1314
|
+
float dx2 = controlPoints[1].x - controlPoints[0].x;
|
|
1315
|
+
float dy2 = controlPoints[1].y - controlPoints[0].y;
|
|
1316
|
+
float dx3 = endPoint.x - controlPoints[1].x;
|
|
1317
|
+
float dy3 = endPoint.y - controlPoints[1].y;
|
|
1304
1318
|
|
|
1305
|
-
|
|
1306
|
-
|
|
1319
|
+
float len = (float) Math.sqrt(dx1 * dx1 + dy1 * dy1)
|
|
1320
|
+
+ (float) Math.sqrt(dx2 * dx2 + dy2 * dy2)
|
|
1321
|
+
+ (float) Math.sqrt(dx3 * dx3 + dy3 * dy3);
|
|
1307
1322
|
|
|
1308
|
-
|
|
1323
|
+
steps = (int) (len * 0.25);
|
|
1309
1324
|
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1325
|
+
if (steps < 4) {
|
|
1326
|
+
steps = 4;
|
|
1327
|
+
}
|
|
1313
1328
|
}
|
|
1314
1329
|
|
|
1315
|
-
|
|
1330
|
+
float dt = 1F / steps;
|
|
1316
1331
|
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
if (segmentSteps == 0.0F) {
|
|
1320
|
-
float dx1 = controlPoints[0].x - startPoint.x;
|
|
1321
|
-
float dy1 = controlPoints[0].y - startPoint.y;
|
|
1322
|
-
float dx2 = controlPoints[1].x - controlPoints[0].x;
|
|
1323
|
-
float dy2 = controlPoints[1].y - controlPoints[0].y;
|
|
1324
|
-
float dx3 = endPoint.x - controlPoints[1].x;
|
|
1325
|
-
float dy3 = endPoint.y - controlPoints[1].y;
|
|
1332
|
+
float fx, fy, fdx, fdy, fddx, fddy, fdddx, fdddy, fdd_per_2x, fdd_per_2y, fddd_per_2x, fddd_per_2y, fddd_per_6x, fddd_per_6y;
|
|
1333
|
+
float temp = dt * dt;
|
|
1326
1334
|
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1335
|
+
fx = startPoint.x;
|
|
1336
|
+
fdx = 3F * (controlPoints[0].x - startPoint.x) * dt;
|
|
1337
|
+
fdd_per_2x = 3F * (startPoint.x - 2F * controlPoints[0].x + controlPoints[1].x) * temp;
|
|
1338
|
+
fddd_per_2x = 3F * (3F * (controlPoints[0].x - controlPoints[1].x) + endPoint.x - startPoint.x) * temp * dt;
|
|
1339
|
+
fdddx = fddd_per_2x + fddd_per_2x;
|
|
1340
|
+
fddx = fdd_per_2x + fdd_per_2x;
|
|
1341
|
+
fddd_per_6x = fddd_per_2x * (1.0F / 3F);
|
|
1330
1342
|
|
|
1331
|
-
|
|
1343
|
+
fy = startPoint.y;
|
|
1344
|
+
fdy = 3F * (controlPoints[0].y - startPoint.y) * dt;
|
|
1345
|
+
fdd_per_2y = 3F * (startPoint.y - 2F * controlPoints[0].y + controlPoints[1].y) * temp;
|
|
1346
|
+
fddd_per_2y = 3F * (3F * (controlPoints[0].y - controlPoints[1].y) + endPoint.y - startPoint.y) * temp * dt;
|
|
1347
|
+
fdddy = fddd_per_2y + fddd_per_2y;
|
|
1348
|
+
fddy = fdd_per_2y + fdd_per_2y;
|
|
1349
|
+
fddd_per_6y = fddd_per_2y * (1.0F / 3F);
|
|
1332
1350
|
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
}
|
|
1336
|
-
}
|
|
1351
|
+
for (int loop = 0; loop < steps; loop++) {
|
|
1352
|
+
addCurvePoint(new RPoint(fx, fy));
|
|
1337
1353
|
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
fdddx = fddd_per_2x + fddd_per_2x;
|
|
1348
|
-
fddx = fdd_per_2x + fdd_per_2x;
|
|
1349
|
-
fddd_per_6x = fddd_per_2x * (1.0F / 3F);
|
|
1350
|
-
|
|
1351
|
-
fy = startPoint.y;
|
|
1352
|
-
fdy = 3F * (controlPoints[0].y - startPoint.y) * dt;
|
|
1353
|
-
fdd_per_2y = 3F * (startPoint.y - 2F * controlPoints[0].y + controlPoints[1].y) * temp;
|
|
1354
|
-
fddd_per_2y = 3F * (3F * (controlPoints[0].y - controlPoints[1].y) + endPoint.y - startPoint.y) * temp * dt;
|
|
1355
|
-
fdddy = fddd_per_2y + fddd_per_2y;
|
|
1356
|
-
fddy = fdd_per_2y + fdd_per_2y;
|
|
1357
|
-
fddd_per_6y = fddd_per_2y * (1.0F / 3F);
|
|
1358
|
-
|
|
1359
|
-
for (int loop = 0; loop < steps; loop++) {
|
|
1360
|
-
addCurvePoint(new RPoint(fx, fy));
|
|
1361
|
-
|
|
1362
|
-
fx = fx + fdx + fdd_per_2x + fddd_per_6x;
|
|
1363
|
-
fdx = fdx + fddx + fddd_per_2x;
|
|
1364
|
-
fddx = fddx + fdddx;
|
|
1365
|
-
fdd_per_2x = fdd_per_2x + fddd_per_2x;
|
|
1366
|
-
|
|
1367
|
-
fy = fy + fdy + fdd_per_2y + fddd_per_6y;
|
|
1368
|
-
fdy = fdy + fddy + fddd_per_2y;
|
|
1369
|
-
fddy = fddy + fdddy;
|
|
1370
|
-
fdd_per_2y = fdd_per_2y + fddd_per_2y;
|
|
1371
|
-
}
|
|
1372
|
-
addCurvePoint(new RPoint(endPoint));
|
|
1354
|
+
fx = fx + fdx + fdd_per_2x + fddd_per_6x;
|
|
1355
|
+
fdx = fdx + fddx + fddd_per_2x;
|
|
1356
|
+
fddx = fddx + fdddx;
|
|
1357
|
+
fdd_per_2x = fdd_per_2x + fddd_per_2x;
|
|
1358
|
+
|
|
1359
|
+
fy = fy + fdy + fdd_per_2y + fddd_per_6y;
|
|
1360
|
+
fdy = fdy + fddy + fddd_per_2y;
|
|
1361
|
+
fddy = fddy + fdddy;
|
|
1362
|
+
fdd_per_2y = fdd_per_2y + fddd_per_2y;
|
|
1373
1363
|
}
|
|
1364
|
+
addCurvePoint(new RPoint(endPoint));
|
|
1365
|
+
}
|
|
1374
1366
|
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1367
|
+
private void quadBezierUniformStep() {
|
|
1368
|
+
// If the number of steps is equal to 0 then choose a number of steps adapted to the curve
|
|
1369
|
+
int steps = segmentSteps;
|
|
1370
|
+
if (segmentSteps == 0.0F) {
|
|
1371
|
+
float dx1 = controlPoints[0].x - startPoint.x;
|
|
1372
|
+
float dy1 = controlPoints[0].y - startPoint.y;
|
|
1373
|
+
float dx2 = endPoint.x - controlPoints[0].x;
|
|
1374
|
+
float dy2 = endPoint.y - controlPoints[0].y;
|
|
1383
1375
|
|
|
1384
|
-
|
|
1385
|
-
|
|
1376
|
+
float len = (float) Math.sqrt(dx1 * dx1 + dy1 * dy1) + (float) Math.sqrt(dx2 * dx2 + dy2 * dy2);
|
|
1377
|
+
steps = (int) (len * 0.25);
|
|
1386
1378
|
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1379
|
+
if (steps < 4) {
|
|
1380
|
+
steps = 4;
|
|
1381
|
+
}
|
|
1382
|
+
}
|
|
1391
1383
|
|
|
1392
|
-
|
|
1384
|
+
float dt = 1F / steps;
|
|
1393
1385
|
|
|
1394
|
-
|
|
1395
|
-
|
|
1386
|
+
float fx, fy, fdx, fdy, fddx, fddy, fdd_per_2x, fdd_per_2y;
|
|
1387
|
+
float temp = dt * dt;
|
|
1396
1388
|
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1389
|
+
fx = startPoint.x;
|
|
1390
|
+
fdx = 2F * (controlPoints[0].x - startPoint.x) * dt;
|
|
1391
|
+
fdd_per_2x = (startPoint.x - 2F * controlPoints[0].x + endPoint.x) * temp;
|
|
1392
|
+
fddx = fdd_per_2x + fdd_per_2x;
|
|
1401
1393
|
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1394
|
+
fy = startPoint.y;
|
|
1395
|
+
fdy = 2F * (controlPoints[0].y - startPoint.y) * dt;
|
|
1396
|
+
fdd_per_2y = (startPoint.y - 2F * controlPoints[0].y + endPoint.y) * temp;
|
|
1397
|
+
fddy = fdd_per_2y + fdd_per_2y;
|
|
1406
1398
|
|
|
1407
|
-
|
|
1408
|
-
|
|
1399
|
+
for (int loop = 0; loop < steps; loop++) {
|
|
1400
|
+
addCurvePoint(new RPoint(fx, fy));
|
|
1409
1401
|
|
|
1410
|
-
|
|
1411
|
-
|
|
1402
|
+
fx = fx + fdx + fdd_per_2x;
|
|
1403
|
+
fdx = fdx + fddx;
|
|
1412
1404
|
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
}
|
|
1416
|
-
addCurvePoint(new RPoint(endPoint));
|
|
1405
|
+
fy = fy + fdy + fdd_per_2y;
|
|
1406
|
+
fdy = fdy + fddy;
|
|
1417
1407
|
}
|
|
1408
|
+
addCurvePoint(new RPoint(endPoint));
|
|
1409
|
+
}
|
|
1418
1410
|
|
|
1419
1411
|
// Use Horner's method to advance
|
|
1420
|
-
|
|
1421
|
-
|
|
1412
|
+
//----------------------
|
|
1413
|
+
private void lineUniformLength() {
|
|
1422
1414
|
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1415
|
+
// If the number of steps is equal to 0 then choose a number of steps adapted to the curve
|
|
1416
|
+
float dx1 = endPoint.x - startPoint.x;
|
|
1417
|
+
float dy1 = endPoint.y - startPoint.y;
|
|
1426
1418
|
|
|
1427
|
-
|
|
1428
|
-
|
|
1419
|
+
float len = (float) Math.sqrt(dx1 * dx1 + dy1 * dy1);
|
|
1420
|
+
float steps = (int) (len * 2);
|
|
1429
1421
|
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
// This holds the amount of steps used to calculate segment lengths
|
|
1435
|
-
float dt = 1F / steps;
|
|
1422
|
+
if (steps < 4) {
|
|
1423
|
+
steps = 4;
|
|
1424
|
+
}
|
|
1436
1425
|
|
|
1437
|
-
|
|
1438
|
-
|
|
1426
|
+
// This holds the amount of steps used to calculate segment lengths
|
|
1427
|
+
float dt = 1F / steps;
|
|
1439
1428
|
|
|
1440
|
-
|
|
1429
|
+
// This holds how much length has to bee advanced until adding a point
|
|
1430
|
+
float untilPoint = RCommand.segmentAccOffset;
|
|
1441
1431
|
|
|
1442
|
-
|
|
1443
|
-
fdx = (endPoint.x - startPoint.x) * dt;
|
|
1432
|
+
float fx, fy, fdx, fdy;
|
|
1444
1433
|
|
|
1445
|
-
|
|
1446
|
-
|
|
1434
|
+
fx = startPoint.x;
|
|
1435
|
+
fdx = (endPoint.x - startPoint.x) * dt;
|
|
1447
1436
|
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
if (untilPoint <= 0) {
|
|
1451
|
-
addCurvePoint(new RPoint(fx, fy));
|
|
1452
|
-
untilPoint += RCommand.segmentLength;
|
|
1453
|
-
}
|
|
1437
|
+
fy = startPoint.y;
|
|
1438
|
+
fdy = (endPoint.y - startPoint.y) * dt;
|
|
1454
1439
|
|
|
1455
|
-
|
|
1456
|
-
|
|
1440
|
+
for (int loop = 0; loop <= steps; loop++) {
|
|
1441
|
+
/* Add point to curve if segment length is reached */
|
|
1442
|
+
if (untilPoint <= 0) {
|
|
1443
|
+
addCurvePoint(new RPoint(fx, fy));
|
|
1444
|
+
untilPoint += RCommand.segmentLength;
|
|
1445
|
+
}
|
|
1457
1446
|
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
}
|
|
1447
|
+
/* Add segment differential to segment length */
|
|
1448
|
+
untilPoint -= (float) Math.sqrt(fdx * fdx + fdy * fdy); // Eventually try other distance measures
|
|
1461
1449
|
|
|
1462
|
-
|
|
1463
|
-
|
|
1450
|
+
fx = fx + fdx;
|
|
1451
|
+
fy = fy + fdy;
|
|
1464
1452
|
}
|
|
1465
1453
|
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1454
|
+
//addCurvePoint(new RPoint(endPoint));
|
|
1455
|
+
RCommand.segmentAccOffset = untilPoint;
|
|
1456
|
+
}
|
|
1469
1457
|
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
float dy2 = endPoint.y - controlPoints[0].y;
|
|
1474
|
-
float len = (float) Math.sqrt(dx1 * dx1 + dy1 * dy1) + (float) Math.sqrt(dx2 * dx2 + dy2 * dy2);
|
|
1475
|
-
float steps = (int) (len * 2);
|
|
1458
|
+
// Use Horner's method to advance
|
|
1459
|
+
//----------------------
|
|
1460
|
+
private void quadBezierUniformLength() {
|
|
1476
1461
|
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1462
|
+
float dx1 = controlPoints[0].x - startPoint.x;
|
|
1463
|
+
float dy1 = controlPoints[0].y - startPoint.y;
|
|
1464
|
+
float dx2 = endPoint.x - controlPoints[0].x;
|
|
1465
|
+
float dy2 = endPoint.y - controlPoints[0].y;
|
|
1466
|
+
float len = (float) Math.sqrt(dx1 * dx1 + dy1 * dy1) + (float) Math.sqrt(dx2 * dx2 + dy2 * dy2);
|
|
1467
|
+
float steps = (int) (len * 2);
|
|
1480
1468
|
|
|
1481
|
-
|
|
1482
|
-
|
|
1469
|
+
if (steps < 4) {
|
|
1470
|
+
steps = 4;
|
|
1471
|
+
}
|
|
1483
1472
|
|
|
1484
|
-
|
|
1485
|
-
|
|
1473
|
+
float dt = 1F / steps;
|
|
1474
|
+
float untilPoint = RCommand.segmentAccOffset;
|
|
1486
1475
|
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
fdd_per_2x = (startPoint.x - 2F * controlPoints[0].x + endPoint.x) * temp;
|
|
1490
|
-
fddx = fdd_per_2x + fdd_per_2x;
|
|
1476
|
+
float fx, fy, fdx, fdy, fddx, fddy, fdd_per_2x, fdd_per_2y, fix, fiy;
|
|
1477
|
+
float temp = dt * dt;
|
|
1491
1478
|
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1479
|
+
fx = startPoint.x;
|
|
1480
|
+
fdx = 2F * (controlPoints[0].x - startPoint.x) * dt;
|
|
1481
|
+
fdd_per_2x = (startPoint.x - 2F * controlPoints[0].x + endPoint.x) * temp;
|
|
1482
|
+
fddx = fdd_per_2x + fdd_per_2x;
|
|
1496
1483
|
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
untilPoint += RCommand.segmentLength;
|
|
1502
|
-
}
|
|
1484
|
+
fy = startPoint.y;
|
|
1485
|
+
fdy = 2F * (controlPoints[0].y - startPoint.y) * dt;
|
|
1486
|
+
fdd_per_2y = (startPoint.y - 2F * controlPoints[0].y + endPoint.y) * temp;
|
|
1487
|
+
fddy = fdd_per_2y + fdd_per_2y;
|
|
1503
1488
|
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1489
|
+
for (int loop = 0; loop <= steps; loop++) {
|
|
1490
|
+
/* Add point to curve if segment length is reached */
|
|
1491
|
+
if (untilPoint <= 0) {
|
|
1492
|
+
addCurvePoint(new RPoint(fx, fy));
|
|
1493
|
+
untilPoint += RCommand.segmentLength;
|
|
1494
|
+
}
|
|
1508
1495
|
|
|
1509
|
-
|
|
1510
|
-
|
|
1496
|
+
/* Add segment differential to segment length */
|
|
1497
|
+
fix = fdx + fdd_per_2x;
|
|
1498
|
+
fiy = fdy + fdd_per_2y;
|
|
1499
|
+
untilPoint -= (float) Math.sqrt(fix * fix + fiy * fiy); // Eventually try other distance measures
|
|
1511
1500
|
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
}
|
|
1501
|
+
fx = fx + fix;
|
|
1502
|
+
fdx = fdx + fddx;
|
|
1515
1503
|
|
|
1516
|
-
|
|
1517
|
-
|
|
1504
|
+
fy = fy + fiy;
|
|
1505
|
+
fdy = fdy + fddy;
|
|
1518
1506
|
}
|
|
1519
1507
|
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
float dx1 = controlPoints[0].x - startPoint.x;
|
|
1525
|
-
float dy1 = controlPoints[0].y - startPoint.y;
|
|
1526
|
-
float dx2 = controlPoints[1].x - controlPoints[0].x;
|
|
1527
|
-
float dy2 = controlPoints[1].y - controlPoints[0].y;
|
|
1528
|
-
float dx3 = endPoint.x - controlPoints[1].x;
|
|
1529
|
-
float dy3 = endPoint.y - controlPoints[1].y;
|
|
1530
|
-
|
|
1531
|
-
float len = (float) Math.sqrt(dx1 * dx1 + dy1 * dy1)
|
|
1532
|
-
+ (float) Math.sqrt(dx2 * dx2 + dy2 * dy2)
|
|
1533
|
-
+ (float) Math.sqrt(dx3 * dx3 + dy3 * dy3);
|
|
1534
|
-
float steps = (int) (len * 2);
|
|
1535
|
-
|
|
1536
|
-
if (steps < 4) {
|
|
1537
|
-
steps = 4;
|
|
1538
|
-
}
|
|
1539
|
-
|
|
1540
|
-
float dt = 1F / steps;
|
|
1541
|
-
float untilPoint = RCommand.segmentAccOffset;
|
|
1542
|
-
|
|
1543
|
-
float fx, fy, fdx, fdy, fddx, fddy, fdddx, fdddy, fdd_per_2x, fdd_per_2y, fddd_per_2x, fddd_per_2y, fddd_per_6x, fddd_per_6y, fix, fiy;
|
|
1544
|
-
float temp = dt * dt;
|
|
1545
|
-
|
|
1546
|
-
fx = startPoint.x;
|
|
1547
|
-
fdx = 3F * (controlPoints[0].x - startPoint.x) * dt;
|
|
1548
|
-
fdd_per_2x = 3F * (startPoint.x - 2F * controlPoints[0].x + controlPoints[1].x) * temp;
|
|
1549
|
-
fddd_per_2x = 3F * (3F * (controlPoints[0].x - controlPoints[1].x) + endPoint.x - startPoint.x) * temp * dt;
|
|
1550
|
-
fdddx = fddd_per_2x + fddd_per_2x;
|
|
1551
|
-
fddx = fdd_per_2x + fdd_per_2x;
|
|
1552
|
-
fddd_per_6x = fddd_per_2x * (1.0F / 3F);
|
|
1553
|
-
|
|
1554
|
-
fy = startPoint.y;
|
|
1555
|
-
fdy = 3F * (controlPoints[0].y - startPoint.y) * dt;
|
|
1556
|
-
fdd_per_2y = 3F * (startPoint.y - 2F * controlPoints[0].y + controlPoints[1].y) * temp;
|
|
1557
|
-
fddd_per_2y = 3F * (3F * (controlPoints[0].y - controlPoints[1].y) + endPoint.y - startPoint.y) * temp * dt;
|
|
1558
|
-
fdddy = fddd_per_2y + fddd_per_2y;
|
|
1559
|
-
fddy = fdd_per_2y + fdd_per_2y;
|
|
1560
|
-
fddd_per_6y = fddd_per_2y * (1.0F / 3F);
|
|
1561
|
-
|
|
1562
|
-
for (int loop = 0; loop < steps; loop++) {
|
|
1563
|
-
/* Add point to curve if segment length is reached */
|
|
1564
|
-
if (untilPoint <= 0) {
|
|
1565
|
-
addCurvePoint(new RPoint(fx, fy));
|
|
1566
|
-
untilPoint += RCommand.segmentLength;
|
|
1567
|
-
}
|
|
1568
|
-
|
|
1569
|
-
/* Add segment differential to segment length */
|
|
1570
|
-
fix = fdx + fdd_per_2x + fddd_per_6x;
|
|
1571
|
-
fiy = fdy + fdd_per_2y + fddd_per_6y;
|
|
1572
|
-
untilPoint -= (float) Math.sqrt(fix * fix + fiy * fiy); // Eventually try other distance measures
|
|
1508
|
+
//addCurvePoint(new RPoint(endPoint));
|
|
1509
|
+
RCommand.segmentAccOffset = untilPoint;
|
|
1510
|
+
}
|
|
1573
1511
|
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1512
|
+
// Use Horner's method to advance
|
|
1513
|
+
//----------------------
|
|
1514
|
+
private void cubicBezierUniformLength() {
|
|
1515
|
+
|
|
1516
|
+
float dx1 = controlPoints[0].x - startPoint.x;
|
|
1517
|
+
float dy1 = controlPoints[0].y - startPoint.y;
|
|
1518
|
+
float dx2 = controlPoints[1].x - controlPoints[0].x;
|
|
1519
|
+
float dy2 = controlPoints[1].y - controlPoints[0].y;
|
|
1520
|
+
float dx3 = endPoint.x - controlPoints[1].x;
|
|
1521
|
+
float dy3 = endPoint.y - controlPoints[1].y;
|
|
1578
1522
|
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
}
|
|
1523
|
+
float len = (float) Math.sqrt(dx1 * dx1 + dy1 * dy1)
|
|
1524
|
+
+ (float) Math.sqrt(dx2 * dx2 + dy2 * dy2)
|
|
1525
|
+
+ (float) Math.sqrt(dx3 * dx3 + dy3 * dy3);
|
|
1526
|
+
float steps = (int) (len * 2);
|
|
1584
1527
|
|
|
1585
|
-
|
|
1586
|
-
|
|
1528
|
+
if (steps < 4) {
|
|
1529
|
+
steps = 4;
|
|
1587
1530
|
}
|
|
1588
1531
|
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
float dx1 = controlPoints[0].x - startPoint.x;
|
|
1592
|
-
float dy1 = controlPoints[0].y - startPoint.y;
|
|
1593
|
-
float dx2 = endPoint.x - controlPoints[0].x;
|
|
1594
|
-
float dy2 = endPoint.y - controlPoints[0].y;
|
|
1595
|
-
float len = (float) Math.sqrt(dx1 * dx1 + dy1 * dy1) + (float) Math.sqrt(dx2 * dx2 + dy2 * dy2);
|
|
1596
|
-
float steps = (int) (len * 2);
|
|
1532
|
+
float dt = 1F / steps;
|
|
1533
|
+
float untilPoint = RCommand.segmentAccOffset;
|
|
1597
1534
|
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1535
|
+
float fx, fy, fdx, fdy, fddx, fddy, fdddx, fdddy, fdd_per_2x, fdd_per_2y, fddd_per_2x, fddd_per_2y, fddd_per_6x, fddd_per_6y, fix, fiy;
|
|
1536
|
+
float temp = dt * dt;
|
|
1537
|
+
|
|
1538
|
+
fx = startPoint.x;
|
|
1539
|
+
fdx = 3F * (controlPoints[0].x - startPoint.x) * dt;
|
|
1540
|
+
fdd_per_2x = 3F * (startPoint.x - 2F * controlPoints[0].x + controlPoints[1].x) * temp;
|
|
1541
|
+
fddd_per_2x = 3F * (3F * (controlPoints[0].x - controlPoints[1].x) + endPoint.x - startPoint.x) * temp * dt;
|
|
1542
|
+
fdddx = fddd_per_2x + fddd_per_2x;
|
|
1543
|
+
fddx = fdd_per_2x + fdd_per_2x;
|
|
1544
|
+
fddd_per_6x = fddd_per_2x * (1.0F / 3F);
|
|
1601
1545
|
|
|
1602
|
-
|
|
1546
|
+
fy = startPoint.y;
|
|
1547
|
+
fdy = 3F * (controlPoints[0].y - startPoint.y) * dt;
|
|
1548
|
+
fdd_per_2y = 3F * (startPoint.y - 2F * controlPoints[0].y + controlPoints[1].y) * temp;
|
|
1549
|
+
fddd_per_2y = 3F * (3F * (controlPoints[0].y - controlPoints[1].y) + endPoint.y - startPoint.y) * temp * dt;
|
|
1550
|
+
fdddy = fddd_per_2y + fddd_per_2y;
|
|
1551
|
+
fddy = fdd_per_2y + fdd_per_2y;
|
|
1552
|
+
fddd_per_6y = fddd_per_2y * (1.0F / 3F);
|
|
1603
1553
|
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1554
|
+
for (int loop = 0; loop < steps; loop++) {
|
|
1555
|
+
/* Add point to curve if segment length is reached */
|
|
1556
|
+
if (untilPoint <= 0) {
|
|
1557
|
+
addCurvePoint(new RPoint(fx, fy));
|
|
1558
|
+
untilPoint += RCommand.segmentLength;
|
|
1559
|
+
}
|
|
1560
|
+
|
|
1561
|
+
/* Add segment differential to segment length */
|
|
1562
|
+
fix = fdx + fdd_per_2x + fddd_per_6x;
|
|
1563
|
+
fiy = fdy + fdd_per_2y + fddd_per_6y;
|
|
1564
|
+
untilPoint -= (float) Math.sqrt(fix * fix + fiy * fiy); // Eventually try other distance measures
|
|
1565
|
+
|
|
1566
|
+
fx = fx + fix;
|
|
1567
|
+
fdx = fdx + fddx + fddd_per_2x;
|
|
1568
|
+
fddx = fddx + fdddx;
|
|
1569
|
+
fdd_per_2x = fdd_per_2x + fddd_per_2x;
|
|
1570
|
+
|
|
1571
|
+
fy = fy + fiy;
|
|
1572
|
+
fdy = fdy + fddy + fddd_per_2y;
|
|
1573
|
+
fddy = fddy + fdddy;
|
|
1574
|
+
fdd_per_2y = fdd_per_2y + fddd_per_2y;
|
|
1575
|
+
}
|
|
1576
|
+
|
|
1577
|
+
//addCurvePoint(new RPoint(endPoint));
|
|
1578
|
+
RCommand.segmentAccOffset = untilPoint;
|
|
1579
|
+
}
|
|
1580
|
+
|
|
1581
|
+
private float quadBezierLength() {
|
|
1582
|
+
|
|
1583
|
+
float dx1 = controlPoints[0].x - startPoint.x;
|
|
1584
|
+
float dy1 = controlPoints[0].y - startPoint.y;
|
|
1585
|
+
float dx2 = endPoint.x - controlPoints[0].x;
|
|
1586
|
+
float dy2 = endPoint.y - controlPoints[0].y;
|
|
1587
|
+
float len = (float) Math.sqrt(dx1 * dx1 + dy1 * dy1) + (float) Math.sqrt(dx2 * dx2 + dy2 * dy2);
|
|
1588
|
+
float steps = (int) (len * 2);
|
|
1589
|
+
|
|
1590
|
+
if (steps < 4) {
|
|
1591
|
+
steps = 4;
|
|
1592
|
+
}
|
|
1593
|
+
|
|
1594
|
+
float dt = 1F / steps;
|
|
1595
|
+
|
|
1596
|
+
float fx, fy, fdx, fdy, fddx, fddy, fdd_per_2x, fdd_per_2y, fix, fiy;
|
|
1597
|
+
float temp = dt * dt;
|
|
1598
|
+
float totallen = 0F;
|
|
1599
|
+
|
|
1600
|
+
fx = startPoint.x;
|
|
1601
|
+
fdx = 2F * (controlPoints[0].x - startPoint.x) * dt;
|
|
1602
|
+
fdd_per_2x = (startPoint.x - 2F * controlPoints[0].x + endPoint.x) * temp;
|
|
1603
|
+
fddx = fdd_per_2x + fdd_per_2x;
|
|
1604
|
+
|
|
1605
|
+
fy = startPoint.y;
|
|
1606
|
+
fdy = 2F * (controlPoints[0].y - startPoint.y) * dt;
|
|
1607
|
+
fdd_per_2y = (startPoint.y - 2F * controlPoints[0].y + endPoint.y) * temp;
|
|
1608
|
+
fddy = fdd_per_2y + fdd_per_2y;
|
|
1609
|
+
|
|
1610
|
+
for (int loop = 0; loop <= steps; loop++) {
|
|
1611
|
+
/* Add segment differential to segment length */
|
|
1612
|
+
fix = fdx + fdd_per_2x;
|
|
1613
|
+
fiy = fdy + fdd_per_2y;
|
|
1614
|
+
totallen += (float) Math.sqrt(fix * fix + fiy * fiy); // Eventually try other distance measures
|
|
1607
1615
|
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
fdd_per_2x = (startPoint.x - 2F * controlPoints[0].x + endPoint.x) * temp;
|
|
1611
|
-
fddx = fdd_per_2x + fdd_per_2x;
|
|
1616
|
+
fx = fx + fix;
|
|
1617
|
+
fdx = fdx + fddx;
|
|
1612
1618
|
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
fddy = fdd_per_2y + fdd_per_2y;
|
|
1619
|
+
fy = fy + fiy;
|
|
1620
|
+
fdy = fdy + fddy;
|
|
1621
|
+
}
|
|
1617
1622
|
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
fix = fdx + fdd_per_2x;
|
|
1621
|
-
fiy = fdy + fdd_per_2y;
|
|
1622
|
-
totallen += (float) Math.sqrt(fix * fix + fiy * fiy); // Eventually try other distance measures
|
|
1623
|
+
return totallen;
|
|
1624
|
+
}
|
|
1623
1625
|
|
|
1624
|
-
|
|
1625
|
-
fdx = fdx + fddx;
|
|
1626
|
+
private float cubicBezierLength() {
|
|
1626
1627
|
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1628
|
+
float dx1 = controlPoints[0].x - startPoint.x;
|
|
1629
|
+
float dy1 = controlPoints[0].y - startPoint.y;
|
|
1630
|
+
float dx2 = controlPoints[1].x - controlPoints[0].x;
|
|
1631
|
+
float dy2 = controlPoints[1].y - controlPoints[0].y;
|
|
1632
|
+
float dx3 = endPoint.x - controlPoints[1].x;
|
|
1633
|
+
float dy3 = endPoint.y - controlPoints[1].y;
|
|
1630
1634
|
|
|
1631
|
-
|
|
1635
|
+
float len = (float) Math.sqrt(dx1 * dx1 + dy1 * dy1)
|
|
1636
|
+
+ (float) Math.sqrt(dx2 * dx2 + dy2 * dy2)
|
|
1637
|
+
+ (float) Math.sqrt(dx3 * dx3 + dy3 * dy3);
|
|
1638
|
+
float steps = (int) (len * 2);
|
|
1639
|
+
|
|
1640
|
+
if (steps < 4) {
|
|
1641
|
+
steps = 4;
|
|
1632
1642
|
}
|
|
1633
1643
|
|
|
1634
|
-
|
|
1644
|
+
float dt = 1F / steps;
|
|
1635
1645
|
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
float dy2 = controlPoints[1].y - controlPoints[0].y;
|
|
1640
|
-
float dx3 = endPoint.x - controlPoints[1].x;
|
|
1641
|
-
float dy3 = endPoint.y - controlPoints[1].y;
|
|
1646
|
+
float fx, fy, fdx, fdy, fddx, fddy, fdddx, fdddy, fdd_per_2x, fdd_per_2y, fddd_per_2x, fddd_per_2y, fddd_per_6x, fddd_per_6y, fix, fiy;
|
|
1647
|
+
float temp = dt * dt;
|
|
1648
|
+
float totallen = 0F;
|
|
1642
1649
|
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1650
|
+
fx = startPoint.x;
|
|
1651
|
+
fdx = 3F * (controlPoints[0].x - startPoint.x) * dt;
|
|
1652
|
+
fdd_per_2x = 3F * (startPoint.x - 2F * controlPoints[0].x + controlPoints[1].x) * temp;
|
|
1653
|
+
fddd_per_2x = 3F * (3F * (controlPoints[0].x - controlPoints[1].x) + endPoint.x - startPoint.x) * temp * dt;
|
|
1654
|
+
fdddx = fddd_per_2x + fddd_per_2x;
|
|
1655
|
+
fddx = fdd_per_2x + fdd_per_2x;
|
|
1656
|
+
fddd_per_6x = fddd_per_2x * (1.0F / 3F);
|
|
1647
1657
|
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1658
|
+
fy = startPoint.y;
|
|
1659
|
+
fdy = 3F * (controlPoints[0].y - startPoint.y) * dt;
|
|
1660
|
+
fdd_per_2y = 3F * (startPoint.y - 2F * controlPoints[0].y + controlPoints[1].y) * temp;
|
|
1661
|
+
fddd_per_2y = 3F * (3F * (controlPoints[0].y - controlPoints[1].y) + endPoint.y - startPoint.y) * temp * dt;
|
|
1651
1662
|
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
fddd_per_2x = 3F * (3F * (controlPoints[0].x - controlPoints[1].x) + endPoint.x - startPoint.x) * temp * dt;
|
|
1662
|
-
fdddx = fddd_per_2x + fddd_per_2x;
|
|
1663
|
-
fddx = fdd_per_2x + fdd_per_2x;
|
|
1664
|
-
fddd_per_6x = fddd_per_2x * (1.0F / 3F);
|
|
1665
|
-
|
|
1666
|
-
fy = startPoint.y;
|
|
1667
|
-
fdy = 3F * (controlPoints[0].y - startPoint.y) * dt;
|
|
1668
|
-
fdd_per_2y = 3F * (startPoint.y - 2F * controlPoints[0].y + controlPoints[1].y) * temp;
|
|
1669
|
-
fddd_per_2y = 3F * (3F * (controlPoints[0].y - controlPoints[1].y) + endPoint.y - startPoint.y) * temp * dt;
|
|
1670
|
-
|
|
1671
|
-
fdddy = fddd_per_2y + fddd_per_2y;
|
|
1672
|
-
fddy = fdd_per_2y + fdd_per_2y;
|
|
1673
|
-
fddd_per_6y = fddd_per_2y * (1.0F / 3F);
|
|
1674
|
-
|
|
1675
|
-
for (int loop = 0; loop < steps; loop++) {
|
|
1676
|
-
/* Add segment differential to segment length */
|
|
1677
|
-
fix = fdx + fdd_per_2x + fddd_per_6x;
|
|
1678
|
-
fiy = fdy + fdd_per_2y + fddd_per_6y;
|
|
1679
|
-
totallen += (float) Math.sqrt(fix * fix + fiy * fiy); // Eventually try other distance measures
|
|
1680
|
-
|
|
1681
|
-
fx = fx + fix;
|
|
1682
|
-
fdx = fdx + fddx + fddd_per_2x;
|
|
1683
|
-
fddx = fddx + fdddx;
|
|
1684
|
-
fdd_per_2x = fdd_per_2x + fddd_per_2x;
|
|
1685
|
-
|
|
1686
|
-
fy = fy + fiy;
|
|
1687
|
-
fdy = fdy + fddy + fddd_per_2y;
|
|
1688
|
-
fddy = fddy + fdddy;
|
|
1689
|
-
fdd_per_2y = fdd_per_2y + fddd_per_2y;
|
|
1690
|
-
}
|
|
1663
|
+
fdddy = fddd_per_2y + fddd_per_2y;
|
|
1664
|
+
fddy = fdd_per_2y + fdd_per_2y;
|
|
1665
|
+
fddd_per_6y = fddd_per_2y * (1.0F / 3F);
|
|
1666
|
+
|
|
1667
|
+
for (int loop = 0; loop < steps; loop++) {
|
|
1668
|
+
/* Add segment differential to segment length */
|
|
1669
|
+
fix = fdx + fdd_per_2x + fddd_per_6x;
|
|
1670
|
+
fiy = fdy + fdd_per_2y + fddd_per_6y;
|
|
1671
|
+
totallen += (float) Math.sqrt(fix * fix + fiy * fiy); // Eventually try other distance measures
|
|
1691
1672
|
|
|
1692
|
-
|
|
1673
|
+
fx = fx + fix;
|
|
1674
|
+
fdx = fdx + fddx + fddd_per_2x;
|
|
1675
|
+
fddx = fddx + fdddx;
|
|
1676
|
+
fdd_per_2x = fdd_per_2x + fddd_per_2x;
|
|
1677
|
+
|
|
1678
|
+
fy = fy + fiy;
|
|
1679
|
+
fdy = fdy + fddy + fddd_per_2y;
|
|
1680
|
+
fddy = fddy + fdddy;
|
|
1681
|
+
fdd_per_2y = fdd_per_2y + fddd_per_2y;
|
|
1693
1682
|
}
|
|
1694
1683
|
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1684
|
+
return totallen;
|
|
1685
|
+
}
|
|
1686
|
+
|
|
1687
|
+
/**
|
|
1688
|
+
* Use this method to transform the command.
|
|
1689
|
+
*
|
|
1690
|
+
transformCommand
|
|
1691
|
+
* @param g PGraphics, the graphics object on which to apply an affine
|
|
1692
|
+
* transformation to the command
|
|
1693
|
+
*/
|
|
1694
|
+
/*
|
|
1703
1695
|
public void transform(RMatrix m){
|
|
1704
1696
|
int numControlPoints = countControlPoints();
|
|
1705
1697
|
if(numControlPoints!=0){
|
|
@@ -1710,319 +1702,319 @@ public class RCommand extends RGeomElem {
|
|
|
1710
1702
|
startPoint.transform(m);
|
|
1711
1703
|
endPoint.transform(m);
|
|
1712
1704
|
}
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1705
|
+
*/
|
|
1706
|
+
private void append(RPoint nextcontrolpoint) {
|
|
1707
|
+
RPoint[] newcontrolPoints;
|
|
1708
|
+
if (controlPoints == null) {
|
|
1709
|
+
newcontrolPoints = new RPoint[1];
|
|
1710
|
+
newcontrolPoints[0] = nextcontrolpoint;
|
|
1711
|
+
} else {
|
|
1712
|
+
newcontrolPoints = new RPoint[controlPoints.length + 1];
|
|
1713
|
+
System.arraycopy(controlPoints, 0, newcontrolPoints, 0, controlPoints.length);
|
|
1714
|
+
newcontrolPoints[controlPoints.length] = nextcontrolpoint;
|
|
1715
|
+
}
|
|
1716
|
+
this.controlPoints = newcontrolPoints;
|
|
1717
|
+
}
|
|
1718
|
+
|
|
1719
|
+
private void addCurvePoint(RPoint nextcurvepoint) {
|
|
1720
|
+
RPoint[] newcurvePoints;
|
|
1721
|
+
if (curvePoints == null) {
|
|
1722
|
+
newcurvePoints = new RPoint[1];
|
|
1723
|
+
newcurvePoints[0] = nextcurvepoint;
|
|
1724
|
+
} else {
|
|
1725
|
+
newcurvePoints = new RPoint[curvePoints.length + 1];
|
|
1726
|
+
System.arraycopy(curvePoints, 0, newcurvePoints, 0, curvePoints.length);
|
|
1727
|
+
newcurvePoints[curvePoints.length] = nextcurvepoint;
|
|
1728
|
+
}
|
|
1729
|
+
this.curvePoints = newcurvePoints;
|
|
1730
|
+
}
|
|
1731
|
+
|
|
1732
|
+
public RPoint[] intersectionPoints(RCommand other) {
|
|
1733
|
+
RPoint[] result = null;
|
|
1734
|
+
|
|
1735
|
+
switch (commandType) {
|
|
1736
|
+
case LINETO:
|
|
1737
|
+
switch (other.getCommandType()) {
|
|
1738
|
+
case LINETO:
|
|
1739
|
+
result = lineLineIntersection(this, other);
|
|
1740
|
+
break;
|
|
1741
|
+
|
|
1742
|
+
case QUADBEZIERTO:
|
|
1743
|
+
result = lineQuadIntersection(this, other);
|
|
1744
|
+
break;
|
|
1745
|
+
|
|
1746
|
+
case CUBICBEZIERTO:
|
|
1747
|
+
result = lineCubicIntersection(this, other);
|
|
1748
|
+
break;
|
|
1723
1749
|
}
|
|
1724
|
-
|
|
1725
|
-
|
|
1750
|
+
break;
|
|
1751
|
+
|
|
1752
|
+
case QUADBEZIERTO:
|
|
1753
|
+
switch (other.getCommandType()) {
|
|
1754
|
+
case LINETO:
|
|
1755
|
+
result = lineQuadIntersection(other, this);
|
|
1756
|
+
break;
|
|
1757
|
+
|
|
1758
|
+
case QUADBEZIERTO:
|
|
1759
|
+
result = quadQuadIntersection(this, other);
|
|
1760
|
+
break;
|
|
1726
1761
|
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
newcurvePoints = new RPoint[1];
|
|
1731
|
-
newcurvePoints[0] = nextcurvepoint;
|
|
1732
|
-
} else {
|
|
1733
|
-
newcurvePoints = new RPoint[curvePoints.length + 1];
|
|
1734
|
-
System.arraycopy(curvePoints, 0, newcurvePoints, 0, curvePoints.length);
|
|
1735
|
-
newcurvePoints[curvePoints.length] = nextcurvepoint;
|
|
1762
|
+
case CUBICBEZIERTO:
|
|
1763
|
+
result = quadCubicIntersection(this, other);
|
|
1764
|
+
break;
|
|
1736
1765
|
}
|
|
1737
|
-
|
|
1738
|
-
}
|
|
1766
|
+
break;
|
|
1739
1767
|
|
|
1740
|
-
|
|
1741
|
-
|
|
1768
|
+
case CUBICBEZIERTO:
|
|
1769
|
+
switch (other.getCommandType()) {
|
|
1770
|
+
case LINETO:
|
|
1771
|
+
result = lineCubicIntersection(other, this);
|
|
1772
|
+
break;
|
|
1742
1773
|
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
case QUADBEZIERTO:
|
|
1751
|
-
result = lineQuadIntersection(this, other);
|
|
1752
|
-
break;
|
|
1753
|
-
|
|
1754
|
-
case CUBICBEZIERTO:
|
|
1755
|
-
result = lineCubicIntersection(this, other);
|
|
1756
|
-
break;
|
|
1757
|
-
}
|
|
1758
|
-
break;
|
|
1759
|
-
|
|
1760
|
-
case QUADBEZIERTO:
|
|
1761
|
-
switch (other.getCommandType()) {
|
|
1762
|
-
case LINETO:
|
|
1763
|
-
result = lineQuadIntersection(other, this);
|
|
1764
|
-
break;
|
|
1765
|
-
|
|
1766
|
-
case QUADBEZIERTO:
|
|
1767
|
-
result = quadQuadIntersection(this, other);
|
|
1768
|
-
break;
|
|
1769
|
-
|
|
1770
|
-
case CUBICBEZIERTO:
|
|
1771
|
-
result = quadCubicIntersection(this, other);
|
|
1772
|
-
break;
|
|
1773
|
-
}
|
|
1774
|
-
break;
|
|
1775
|
-
|
|
1776
|
-
case CUBICBEZIERTO:
|
|
1777
|
-
switch (other.getCommandType()) {
|
|
1778
|
-
case LINETO:
|
|
1779
|
-
result = lineCubicIntersection(other, this);
|
|
1780
|
-
break;
|
|
1781
|
-
|
|
1782
|
-
case QUADBEZIERTO:
|
|
1783
|
-
result = quadCubicIntersection(other, this);
|
|
1784
|
-
break;
|
|
1785
|
-
|
|
1786
|
-
case CUBICBEZIERTO:
|
|
1787
|
-
result = cubicCubicIntersection(this, other);
|
|
1788
|
-
break;
|
|
1789
|
-
}
|
|
1790
|
-
break;
|
|
1774
|
+
case QUADBEZIERTO:
|
|
1775
|
+
result = quadCubicIntersection(other, this);
|
|
1776
|
+
break;
|
|
1777
|
+
|
|
1778
|
+
case CUBICBEZIERTO:
|
|
1779
|
+
result = cubicCubicIntersection(this, other);
|
|
1780
|
+
break;
|
|
1791
1781
|
}
|
|
1782
|
+
break;
|
|
1783
|
+
}
|
|
1792
1784
|
|
|
1793
|
-
|
|
1785
|
+
return result;
|
|
1786
|
+
}
|
|
1787
|
+
|
|
1788
|
+
public static RPoint[] lineLineIntersection(RCommand c1, RCommand c2) {
|
|
1789
|
+
RPoint a = new RPoint(c1.startPoint);
|
|
1790
|
+
RPoint b = new RPoint(c1.endPoint);
|
|
1791
|
+
|
|
1792
|
+
RPoint c = new RPoint(c2.startPoint);
|
|
1793
|
+
RPoint d = new RPoint(c2.endPoint);
|
|
1794
|
+
|
|
1795
|
+
float epsilon = 1e-9f;
|
|
1796
|
+
|
|
1797
|
+
//test for parallel case
|
|
1798
|
+
float denom = (d.y - c.y) * (b.x - a.x) - (d.x - c.x) * (b.y - a.y);
|
|
1799
|
+
if (Math.abs(denom) < epsilon) {
|
|
1800
|
+
return null;
|
|
1801
|
+
}
|
|
1802
|
+
|
|
1803
|
+
//calculate segment parameter and ensure its within bounds
|
|
1804
|
+
float t1 = ((d.x - c.x) * (a.y - c.y) - (d.y - c.y) * (a.x - c.x)) / denom;
|
|
1805
|
+
float t2 = ((b.x - a.x) * (a.y - c.y) - (b.y - a.y) * (a.x - c.x)) / denom;
|
|
1806
|
+
|
|
1807
|
+
if (t1 < 0.0f || t1 > 1.0f || t2 < 0.0f || t2 > 1.0f) {
|
|
1808
|
+
return null;
|
|
1794
1809
|
}
|
|
1795
1810
|
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1811
|
+
//store actual intersection
|
|
1812
|
+
RPoint[] result = new RPoint[1];
|
|
1813
|
+
|
|
1814
|
+
RPoint temp = new RPoint(b);
|
|
1815
|
+
temp.sub(a);
|
|
1816
|
+
temp.scale(t1);
|
|
1817
|
+
|
|
1818
|
+
result[0] = new RPoint(a);
|
|
1819
|
+
result[0].add(temp);
|
|
1820
|
+
|
|
1821
|
+
return result;
|
|
1822
|
+
}
|
|
1823
|
+
|
|
1824
|
+
public static RPoint[] lineQuadIntersection(RCommand c1, RCommand c2) {
|
|
1825
|
+
return null;
|
|
1826
|
+
}
|
|
1827
|
+
|
|
1828
|
+
public static RPoint[] lineCubicIntersection(RCommand c1, RCommand c2) {
|
|
1829
|
+
return null;
|
|
1830
|
+
}
|
|
1831
|
+
|
|
1832
|
+
public static RPoint[] quadQuadIntersection(RCommand c1, RCommand c2) {
|
|
1833
|
+
return null;
|
|
1834
|
+
}
|
|
1799
1835
|
|
|
1800
|
-
|
|
1801
|
-
|
|
1836
|
+
public static RPoint[] quadCubicIntersection(RCommand c1, RCommand c2) {
|
|
1837
|
+
return null;
|
|
1838
|
+
}
|
|
1802
1839
|
|
|
1803
|
-
|
|
1840
|
+
public static RPoint[] cubicCubicIntersection(RCommand c1, RCommand c2) {
|
|
1841
|
+
return null;
|
|
1842
|
+
}
|
|
1804
1843
|
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1844
|
+
public RClosest closestPoints(RCommand other) {
|
|
1845
|
+
RClosest result = new RClosest();
|
|
1846
|
+
result.distance = 0;
|
|
1847
|
+
RPoint temp;
|
|
1848
|
+
|
|
1849
|
+
switch (commandType) {
|
|
1850
|
+
case LINETO:
|
|
1851
|
+
switch (other.getCommandType()) {
|
|
1852
|
+
case LINETO:
|
|
1853
|
+
result.intersects = lineLineIntersection(this, other);
|
|
1854
|
+
if (result.intersects == null) {
|
|
1855
|
+
result = lineLineClosest(this, other);
|
|
1856
|
+
}
|
|
1857
|
+
break;
|
|
1858
|
+
|
|
1859
|
+
case QUADBEZIERTO:
|
|
1860
|
+
result.intersects = lineQuadIntersection(this, other);
|
|
1861
|
+
if (result.intersects == null) {
|
|
1862
|
+
result = lineQuadClosest(this, other);
|
|
1863
|
+
}
|
|
1864
|
+
break;
|
|
1865
|
+
|
|
1866
|
+
case CUBICBEZIERTO:
|
|
1867
|
+
result.intersects = lineCubicIntersection(this, other);
|
|
1868
|
+
if (result.intersects == null) {
|
|
1869
|
+
result = lineCubicClosest(this, other);
|
|
1870
|
+
}
|
|
1871
|
+
break;
|
|
1809
1872
|
}
|
|
1873
|
+
break;
|
|
1874
|
+
|
|
1875
|
+
case QUADBEZIERTO:
|
|
1876
|
+
switch (other.getCommandType()) {
|
|
1877
|
+
case LINETO:
|
|
1878
|
+
result.intersects = lineQuadIntersection(other, this);
|
|
1879
|
+
if (result.intersects == null) {
|
|
1880
|
+
result = lineQuadClosest(other, this);
|
|
1881
|
+
temp = result.closest[0];
|
|
1882
|
+
result.closest[0] = result.closest[1];
|
|
1883
|
+
result.closest[1] = temp;
|
|
1884
|
+
}
|
|
1885
|
+
break;
|
|
1810
1886
|
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1887
|
+
case QUADBEZIERTO:
|
|
1888
|
+
result.intersects = quadQuadIntersection(this, other);
|
|
1889
|
+
if (result.intersects == null) {
|
|
1890
|
+
result = quadQuadClosest(this, other);
|
|
1891
|
+
}
|
|
1892
|
+
break;
|
|
1814
1893
|
|
|
1815
|
-
|
|
1816
|
-
|
|
1894
|
+
case CUBICBEZIERTO:
|
|
1895
|
+
result.intersects = quadCubicIntersection(this, other);
|
|
1896
|
+
if (result.intersects == null) {
|
|
1897
|
+
result = quadCubicClosest(this, other);
|
|
1898
|
+
}
|
|
1899
|
+
break;
|
|
1817
1900
|
}
|
|
1901
|
+
break;
|
|
1902
|
+
|
|
1903
|
+
case CUBICBEZIERTO:
|
|
1904
|
+
switch (other.getCommandType()) {
|
|
1905
|
+
case LINETO:
|
|
1906
|
+
result.intersects = lineCubicIntersection(other, this);
|
|
1907
|
+
if (result.intersects == null) {
|
|
1908
|
+
result = lineCubicClosest(other, this);
|
|
1909
|
+
temp = result.closest[0];
|
|
1910
|
+
result.closest[0] = result.closest[1];
|
|
1911
|
+
result.closest[1] = temp;
|
|
1912
|
+
}
|
|
1913
|
+
break;
|
|
1914
|
+
|
|
1915
|
+
case QUADBEZIERTO:
|
|
1916
|
+
result.intersects = quadCubicIntersection(other, this);
|
|
1917
|
+
if (result.intersects == null) {
|
|
1918
|
+
result = quadCubicClosest(other, this);
|
|
1919
|
+
temp = result.closest[0];
|
|
1920
|
+
result.closest[0] = result.closest[1];
|
|
1921
|
+
result.closest[1] = temp;
|
|
1922
|
+
}
|
|
1923
|
+
break;
|
|
1818
1924
|
|
|
1819
|
-
|
|
1820
|
-
|
|
1925
|
+
case CUBICBEZIERTO:
|
|
1926
|
+
result.intersects = cubicCubicIntersection(this, other);
|
|
1927
|
+
if (result.intersects == null) {
|
|
1928
|
+
result = cubicCubicClosest(this, other);
|
|
1929
|
+
}
|
|
1930
|
+
break;
|
|
1931
|
+
}
|
|
1932
|
+
break;
|
|
1933
|
+
}
|
|
1821
1934
|
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
temp.scale(t1);
|
|
1935
|
+
return result;
|
|
1936
|
+
}
|
|
1825
1937
|
|
|
1826
|
-
|
|
1827
|
-
|
|
1938
|
+
public static float closestAdvFrom(RCommand c, RPoint p) {
|
|
1939
|
+
RPoint a = new RPoint(c.startPoint);
|
|
1940
|
+
RPoint b = new RPoint(c.endPoint);
|
|
1828
1941
|
|
|
1829
|
-
|
|
1830
|
-
|
|
1942
|
+
RPoint ap = new RPoint(p);
|
|
1943
|
+
ap.sub(a);
|
|
1831
1944
|
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
}
|
|
1945
|
+
RPoint ab = new RPoint(b);
|
|
1946
|
+
ab.sub(a);
|
|
1835
1947
|
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
}
|
|
1948
|
+
float denom = ab.sqrnorm();
|
|
1949
|
+
float epsilon = 1e-19f;
|
|
1839
1950
|
|
|
1840
|
-
|
|
1841
|
-
|
|
1951
|
+
if (denom < epsilon) {
|
|
1952
|
+
return 0.5f;
|
|
1842
1953
|
}
|
|
1843
1954
|
|
|
1844
|
-
|
|
1845
|
-
return null;
|
|
1846
|
-
}
|
|
1955
|
+
float t = (ab.x * ap.x + ab.y * ap.y) / denom;
|
|
1847
1956
|
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
}
|
|
1957
|
+
t = t > 0.0f ? t : 0.0f;
|
|
1958
|
+
t = t < 1.0f ? t : 1.0f;
|
|
1851
1959
|
|
|
1852
|
-
|
|
1853
|
-
RClosest result = new RClosest();
|
|
1854
|
-
result.distance = 0;
|
|
1855
|
-
RPoint temp;
|
|
1960
|
+
return t;
|
|
1856
1961
|
|
|
1857
|
-
|
|
1858
|
-
case LINETO:
|
|
1859
|
-
switch (other.getCommandType()) {
|
|
1860
|
-
case LINETO:
|
|
1861
|
-
result.intersects = lineLineIntersection(this, other);
|
|
1862
|
-
if (result.intersects == null) {
|
|
1863
|
-
result = lineLineClosest(this, other);
|
|
1864
|
-
}
|
|
1865
|
-
break;
|
|
1866
|
-
|
|
1867
|
-
case QUADBEZIERTO:
|
|
1868
|
-
result.intersects = lineQuadIntersection(this, other);
|
|
1869
|
-
if (result.intersects == null) {
|
|
1870
|
-
result = lineQuadClosest(this, other);
|
|
1871
|
-
}
|
|
1872
|
-
break;
|
|
1873
|
-
|
|
1874
|
-
case CUBICBEZIERTO:
|
|
1875
|
-
result.intersects = lineCubicIntersection(this, other);
|
|
1876
|
-
if (result.intersects == null) {
|
|
1877
|
-
result = lineCubicClosest(this, other);
|
|
1878
|
-
}
|
|
1879
|
-
break;
|
|
1880
|
-
}
|
|
1881
|
-
break;
|
|
1882
|
-
|
|
1883
|
-
case QUADBEZIERTO:
|
|
1884
|
-
switch (other.getCommandType()) {
|
|
1885
|
-
case LINETO:
|
|
1886
|
-
result.intersects = lineQuadIntersection(other, this);
|
|
1887
|
-
if (result.intersects == null) {
|
|
1888
|
-
result = lineQuadClosest(other, this);
|
|
1889
|
-
temp = result.closest[0];
|
|
1890
|
-
result.closest[0] = result.closest[1];
|
|
1891
|
-
result.closest[1] = temp;
|
|
1892
|
-
}
|
|
1893
|
-
break;
|
|
1894
|
-
|
|
1895
|
-
case QUADBEZIERTO:
|
|
1896
|
-
result.intersects = quadQuadIntersection(this, other);
|
|
1897
|
-
if (result.intersects == null) {
|
|
1898
|
-
result = quadQuadClosest(this, other);
|
|
1899
|
-
}
|
|
1900
|
-
break;
|
|
1901
|
-
|
|
1902
|
-
case CUBICBEZIERTO:
|
|
1903
|
-
result.intersects = quadCubicIntersection(this, other);
|
|
1904
|
-
if (result.intersects == null) {
|
|
1905
|
-
result = quadCubicClosest(this, other);
|
|
1906
|
-
}
|
|
1907
|
-
break;
|
|
1908
|
-
}
|
|
1909
|
-
break;
|
|
1910
|
-
|
|
1911
|
-
case CUBICBEZIERTO:
|
|
1912
|
-
switch (other.getCommandType()) {
|
|
1913
|
-
case LINETO:
|
|
1914
|
-
result.intersects = lineCubicIntersection(other, this);
|
|
1915
|
-
if (result.intersects == null) {
|
|
1916
|
-
result = lineCubicClosest(other, this);
|
|
1917
|
-
temp = result.closest[0];
|
|
1918
|
-
result.closest[0] = result.closest[1];
|
|
1919
|
-
result.closest[1] = temp;
|
|
1920
|
-
}
|
|
1921
|
-
break;
|
|
1922
|
-
|
|
1923
|
-
case QUADBEZIERTO:
|
|
1924
|
-
result.intersects = quadCubicIntersection(other, this);
|
|
1925
|
-
if (result.intersects == null) {
|
|
1926
|
-
result = quadCubicClosest(other, this);
|
|
1927
|
-
temp = result.closest[0];
|
|
1928
|
-
result.closest[0] = result.closest[1];
|
|
1929
|
-
result.closest[1] = temp;
|
|
1930
|
-
}
|
|
1931
|
-
break;
|
|
1932
|
-
|
|
1933
|
-
case CUBICBEZIERTO:
|
|
1934
|
-
result.intersects = cubicCubicIntersection(this, other);
|
|
1935
|
-
if (result.intersects == null) {
|
|
1936
|
-
result = cubicCubicClosest(this, other);
|
|
1937
|
-
}
|
|
1938
|
-
break;
|
|
1939
|
-
}
|
|
1940
|
-
break;
|
|
1941
|
-
}
|
|
1962
|
+
}
|
|
1942
1963
|
|
|
1943
|
-
|
|
1944
|
-
|
|
1964
|
+
public static RClosest lineLineClosest(RCommand c1, RCommand c2) {
|
|
1965
|
+
RPoint c1b = new RPoint(c1.startPoint);
|
|
1966
|
+
RPoint c1e = new RPoint(c1.endPoint);
|
|
1945
1967
|
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
RPoint b = new RPoint(c.endPoint);
|
|
1968
|
+
float c2t1 = closestAdvFrom(c2, c1b);
|
|
1969
|
+
float c2t2 = closestAdvFrom(c2, c1e);
|
|
1949
1970
|
|
|
1950
|
-
|
|
1951
|
-
|
|
1971
|
+
RPoint c2p1 = c2.getPoint(c2t1);
|
|
1972
|
+
RPoint c2p2 = c2.getPoint(c2t2);
|
|
1952
1973
|
|
|
1953
|
-
|
|
1954
|
-
|
|
1974
|
+
float dist1c2 = c2p1.dist(c1b);
|
|
1975
|
+
float dist2c2 = c2p2.dist(c1e);
|
|
1955
1976
|
|
|
1956
|
-
|
|
1957
|
-
|
|
1977
|
+
RPoint c2b = new RPoint(c2.startPoint);
|
|
1978
|
+
RPoint c2e = new RPoint(c2.endPoint);
|
|
1958
1979
|
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
}
|
|
1980
|
+
float c1t1 = closestAdvFrom(c1, c2b);
|
|
1981
|
+
float c1t2 = closestAdvFrom(c1, c2e);
|
|
1962
1982
|
|
|
1963
|
-
|
|
1983
|
+
RPoint c1p1 = c1.getPoint(c1t1);
|
|
1984
|
+
RPoint c1p2 = c1.getPoint(c1t2);
|
|
1964
1985
|
|
|
1965
|
-
|
|
1966
|
-
|
|
1986
|
+
float dist1c1 = c1p1.dist(c2b);
|
|
1987
|
+
float dist2c1 = c1p2.dist(c2e);
|
|
1967
1988
|
|
|
1968
|
-
|
|
1989
|
+
RClosest result = new RClosest();
|
|
1990
|
+
result.distance = Math.min(Math.min(dist1c2, dist2c2), Math.min(dist1c1, dist2c1));
|
|
1991
|
+
result.closest = new RPoint[2];
|
|
1992
|
+
result.advancements = new float[2];
|
|
1969
1993
|
|
|
1994
|
+
if (result.distance == dist1c2) {
|
|
1995
|
+
result.closest[0] = c1b;
|
|
1996
|
+
result.closest[1] = c2p1;
|
|
1997
|
+
result.advancements[0] = 0;
|
|
1998
|
+
result.advancements[1] = c2t1;
|
|
1999
|
+
} else if (result.distance == dist2c2) {
|
|
2000
|
+
result.closest[0] = c1e;
|
|
2001
|
+
result.closest[1] = c2p2;
|
|
2002
|
+
result.advancements[0] = 1;
|
|
2003
|
+
result.advancements[1] = c2t2;
|
|
2004
|
+
} else if (result.distance == dist1c1) {
|
|
2005
|
+
result.closest[0] = c2b;
|
|
2006
|
+
result.closest[1] = c1p1;
|
|
2007
|
+
result.advancements[0] = 0;
|
|
2008
|
+
result.advancements[1] = c1t1;
|
|
2009
|
+
} else /*if (result.distance == dist2c1)*/ {
|
|
2010
|
+
result.closest[0] = c2e;
|
|
2011
|
+
result.closest[1] = c1p2;
|
|
2012
|
+
result.advancements[0] = 1;
|
|
2013
|
+
result.advancements[1] = c1t2;
|
|
1970
2014
|
}
|
|
1971
2015
|
|
|
1972
|
-
public static RClosest lineLineClosest(RCommand c1, RCommand c2) {
|
|
1973
|
-
RPoint c1b = new RPoint(c1.startPoint);
|
|
1974
|
-
RPoint c1e = new RPoint(c1.endPoint);
|
|
1975
|
-
|
|
1976
|
-
float c2t1 = closestAdvFrom(c2, c1b);
|
|
1977
|
-
float c2t2 = closestAdvFrom(c2, c1e);
|
|
1978
|
-
|
|
1979
|
-
RPoint c2p1 = c2.getPoint(c2t1);
|
|
1980
|
-
RPoint c2p2 = c2.getPoint(c2t2);
|
|
1981
|
-
|
|
1982
|
-
float dist1c2 = c2p1.dist(c1b);
|
|
1983
|
-
float dist2c2 = c2p2.dist(c1e);
|
|
1984
|
-
|
|
1985
|
-
RPoint c2b = new RPoint(c2.startPoint);
|
|
1986
|
-
RPoint c2e = new RPoint(c2.endPoint);
|
|
1987
|
-
|
|
1988
|
-
float c1t1 = closestAdvFrom(c1, c2b);
|
|
1989
|
-
float c1t2 = closestAdvFrom(c1, c2e);
|
|
1990
|
-
|
|
1991
|
-
RPoint c1p1 = c1.getPoint(c1t1);
|
|
1992
|
-
RPoint c1p2 = c1.getPoint(c1t2);
|
|
1993
|
-
|
|
1994
|
-
float dist1c1 = c1p1.dist(c2b);
|
|
1995
|
-
float dist2c1 = c1p2.dist(c2e);
|
|
1996
|
-
|
|
1997
|
-
RClosest result = new RClosest();
|
|
1998
|
-
result.distance = Math.min(Math.min(dist1c2, dist2c2), Math.min(dist1c1, dist2c1));
|
|
1999
|
-
result.closest = new RPoint[2];
|
|
2000
|
-
result.advancements = new float[2];
|
|
2001
|
-
|
|
2002
|
-
if (result.distance == dist1c2) {
|
|
2003
|
-
result.closest[0] = c1b;
|
|
2004
|
-
result.closest[1] = c2p1;
|
|
2005
|
-
result.advancements[0] = 0;
|
|
2006
|
-
result.advancements[1] = c2t1;
|
|
2007
|
-
} else if (result.distance == dist2c2) {
|
|
2008
|
-
result.closest[0] = c1e;
|
|
2009
|
-
result.closest[1] = c2p2;
|
|
2010
|
-
result.advancements[0] = 1;
|
|
2011
|
-
result.advancements[1] = c2t2;
|
|
2012
|
-
} else if (result.distance == dist1c1) {
|
|
2013
|
-
result.closest[0] = c2b;
|
|
2014
|
-
result.closest[1] = c1p1;
|
|
2015
|
-
result.advancements[0] = 0;
|
|
2016
|
-
result.advancements[1] = c1t1;
|
|
2017
|
-
} else /*if (result.distance == dist2c1)*/ {
|
|
2018
|
-
result.closest[0] = c2e;
|
|
2019
|
-
result.closest[1] = c1p2;
|
|
2020
|
-
result.advancements[0] = 1;
|
|
2021
|
-
result.advancements[1] = c1t2;
|
|
2022
|
-
}
|
|
2023
|
-
|
|
2024
2016
|
|
|
2025
|
-
|
|
2017
|
+
/*
|
|
2026
2018
|
RPoint c = new RPoint(c2.startPoint);
|
|
2027
2019
|
RPoint d = new RPoint(c2.endPoint);
|
|
2028
2020
|
|
|
@@ -2051,27 +2043,27 @@ public class RCommand extends RGeomElem {
|
|
|
2051
2043
|
result.advancements[0] = t1;
|
|
2052
2044
|
result.advancements[1] = t2;
|
|
2053
2045
|
}
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2046
|
+
*/
|
|
2047
|
+
return result;
|
|
2048
|
+
}
|
|
2057
2049
|
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2050
|
+
public static RClosest lineQuadClosest(RCommand c1, RCommand c2) {
|
|
2051
|
+
return null;
|
|
2052
|
+
}
|
|
2061
2053
|
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2054
|
+
public static RClosest lineCubicClosest(RCommand c1, RCommand c2) {
|
|
2055
|
+
return null;
|
|
2056
|
+
}
|
|
2065
2057
|
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2058
|
+
public static RClosest quadQuadClosest(RCommand c1, RCommand c2) {
|
|
2059
|
+
return null;
|
|
2060
|
+
}
|
|
2069
2061
|
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2062
|
+
public static RClosest quadCubicClosest(RCommand c1, RCommand c2) {
|
|
2063
|
+
return null;
|
|
2064
|
+
}
|
|
2073
2065
|
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2066
|
+
public static RClosest cubicCubicClosest(RCommand c1, RCommand c2) {
|
|
2067
|
+
return null;
|
|
2068
|
+
}
|
|
2077
2069
|
}
|