geomerative 1.1.0-java → 2.0.0-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (116) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -1
  3. data/.mvn/extensions.xml +1 -1
  4. data/.mvn/wrapper/maven-wrapper.properties +1 -1
  5. data/CHANGELOG.md +3 -0
  6. data/COPYING.md +1 -1
  7. data/README.md +0 -1
  8. data/Rakefile +2 -15
  9. data/docs/_includes/header.html +6 -6
  10. data/docs/_includes/icon-github.svg +3 -1
  11. data/docs/_includes/icon-twitter.svg +3 -1
  12. data/docs/_includes/navigation.html +18 -18
  13. data/docs/_sass/_base.scss +79 -79
  14. data/docs/_sass/_layout.scss +137 -137
  15. data/docs/_sass/_syntax-highlighting.scss +64 -64
  16. data/docs/index.html +18 -18
  17. data/examples/data/bot1.svg +1 -1
  18. data/examples/data/lion.svg +156 -156
  19. data/examples/data/ruby.svg +1 -1
  20. data/geomerative.gemspec +1 -2
  21. data/lib/geomerative/version.rb +1 -1
  22. data/mvnw +234 -0
  23. data/mvnw.cmd +145 -0
  24. data/pom.rb +14 -13
  25. data/pom.xml +14 -13
  26. data/src/geomerative/FastRClip.java +2149 -2156
  27. data/src/geomerative/RClip.java +2237 -2539
  28. data/src/geomerative/RClosest.java +33 -31
  29. data/src/geomerative/RCommand.java +1750 -1758
  30. data/src/geomerative/RContour.java +290 -292
  31. data/src/geomerative/RFont.java +277 -246
  32. data/src/geomerative/RG.java +722 -727
  33. data/src/geomerative/RGeomElem.java +967 -960
  34. data/src/geomerative/RGroup.java +508 -467
  35. data/src/geomerative/RMatrix.java +304 -289
  36. data/src/geomerative/RMesh.java +241 -229
  37. data/src/geomerative/RPath.java +924 -925
  38. data/src/geomerative/RPoint.java +391 -391
  39. data/src/geomerative/RPolygon.java +998 -988
  40. data/src/geomerative/RRectangle.java +43 -52
  41. data/src/geomerative/RSVG.java +480 -516
  42. data/src/geomerative/RShape.java +1767 -1777
  43. data/src/geomerative/RStrip.java +173 -176
  44. data/src/geomerative/RStyle.java +197 -194
  45. data/src/org/apache/batik/svggen/font/Font.java +141 -142
  46. data/src/org/apache/batik/svggen/font/Glyph.java +102 -71
  47. data/src/org/apache/batik/svggen/font/Point.java +12 -12
  48. data/src/org/apache/batik/svggen/font/RandomAccessFileEmulator.java +14 -12
  49. data/src/org/apache/batik/svggen/font/table/ClassDef.java +12 -12
  50. data/src/org/apache/batik/svggen/font/table/ClassDefFormat1.java +27 -24
  51. data/src/org/apache/batik/svggen/font/table/ClassDefFormat2.java +20 -17
  52. data/src/org/apache/batik/svggen/font/table/CmapFormat.java +43 -43
  53. data/src/org/apache/batik/svggen/font/table/CmapFormat0.java +33 -26
  54. data/src/org/apache/batik/svggen/font/table/CmapFormat2.java +25 -20
  55. data/src/org/apache/batik/svggen/font/table/CmapFormat4.java +106 -96
  56. data/src/org/apache/batik/svggen/font/table/CmapFormat6.java +36 -32
  57. data/src/org/apache/batik/svggen/font/table/CmapIndexEntry.java +69 -49
  58. data/src/org/apache/batik/svggen/font/table/CmapTable.java +50 -50
  59. data/src/org/apache/batik/svggen/font/table/Coverage.java +19 -19
  60. data/src/org/apache/batik/svggen/font/table/CoverageFormat1.java +30 -27
  61. data/src/org/apache/batik/svggen/font/table/CoverageFormat2.java +26 -24
  62. data/src/org/apache/batik/svggen/font/table/CvtTable.java +16 -16
  63. data/src/org/apache/batik/svggen/font/table/Device.java +32 -32
  64. data/src/org/apache/batik/svggen/font/table/DirectoryEntry.java +39 -39
  65. data/src/org/apache/batik/svggen/font/table/Feature.java +26 -23
  66. data/src/org/apache/batik/svggen/font/table/FeatureList.java +37 -35
  67. data/src/org/apache/batik/svggen/font/table/FeatureRecord.java +22 -22
  68. data/src/org/apache/batik/svggen/font/table/FeatureTags.java +4 -3
  69. data/src/org/apache/batik/svggen/font/table/FpgmTable.java +9 -9
  70. data/src/org/apache/batik/svggen/font/table/GlyfCompositeComp.java +134 -132
  71. data/src/org/apache/batik/svggen/font/table/GlyfCompositeDescript.java +123 -122
  72. data/src/org/apache/batik/svggen/font/table/GlyfDescript.java +44 -44
  73. data/src/org/apache/batik/svggen/font/table/GlyfSimpleDescript.java +110 -109
  74. data/src/org/apache/batik/svggen/font/table/GlyfTable.java +46 -46
  75. data/src/org/apache/batik/svggen/font/table/GlyphDescription.java +25 -13
  76. data/src/org/apache/batik/svggen/font/table/GposTable.java +26 -23
  77. data/src/org/apache/batik/svggen/font/table/GsubTable.java +85 -82
  78. data/src/org/apache/batik/svggen/font/table/HeadTable.java +131 -131
  79. data/src/org/apache/batik/svggen/font/table/HheaTable.java +80 -80
  80. data/src/org/apache/batik/svggen/font/table/HmtxTable.java +50 -49
  81. data/src/org/apache/batik/svggen/font/table/KernSubtable.java +29 -27
  82. data/src/org/apache/batik/svggen/font/table/KernSubtableFormat0.java +35 -32
  83. data/src/org/apache/batik/svggen/font/table/KernSubtableFormat2.java +28 -26
  84. data/src/org/apache/batik/svggen/font/table/KernTable.java +36 -31
  85. data/src/org/apache/batik/svggen/font/table/KerningPair.java +27 -23
  86. data/src/org/apache/batik/svggen/font/table/LangSys.java +28 -26
  87. data/src/org/apache/batik/svggen/font/table/LangSysRecord.java +22 -22
  88. data/src/org/apache/batik/svggen/font/table/Ligature.java +24 -24
  89. data/src/org/apache/batik/svggen/font/table/LigatureSet.java +24 -24
  90. data/src/org/apache/batik/svggen/font/table/LigatureSubst.java +9 -9
  91. data/src/org/apache/batik/svggen/font/table/LigatureSubstFormat1.java +30 -30
  92. data/src/org/apache/batik/svggen/font/table/LocaTable.java +37 -37
  93. data/src/org/apache/batik/svggen/font/table/Lookup.java +41 -40
  94. data/src/org/apache/batik/svggen/font/table/LookupList.java +34 -34
  95. data/src/org/apache/batik/svggen/font/table/LookupSubtableFactory.java +7 -5
  96. data/src/org/apache/batik/svggen/font/table/MaxpTable.java +96 -96
  97. data/src/org/apache/batik/svggen/font/table/NameRecord.java +64 -65
  98. data/src/org/apache/batik/svggen/font/table/NameTable.java +33 -33
  99. data/src/org/apache/batik/svggen/font/table/Os2Table.java +196 -196
  100. data/src/org/apache/batik/svggen/font/table/Panose.java +14 -12
  101. data/src/org/apache/batik/svggen/font/table/PostTable.java +338 -338
  102. data/src/org/apache/batik/svggen/font/table/PrepTable.java +9 -9
  103. data/src/org/apache/batik/svggen/font/table/Program.java +15 -15
  104. data/src/org/apache/batik/svggen/font/table/RangeRecord.java +26 -25
  105. data/src/org/apache/batik/svggen/font/table/Script.java +38 -38
  106. data/src/org/apache/batik/svggen/font/table/ScriptList.java +42 -42
  107. data/src/org/apache/batik/svggen/font/table/ScriptRecord.java +22 -22
  108. data/src/org/apache/batik/svggen/font/table/ScriptTags.java +2 -1
  109. data/src/org/apache/batik/svggen/font/table/SingleSubst.java +15 -16
  110. data/src/org/apache/batik/svggen/font/table/SingleSubstFormat1.java +33 -33
  111. data/src/org/apache/batik/svggen/font/table/SingleSubstFormat2.java +32 -32
  112. data/src/org/apache/batik/svggen/font/table/Table.java +171 -170
  113. data/src/org/apache/batik/svggen/font/table/TableDirectory.java +55 -55
  114. data/src/org/apache/batik/svggen/font/table/TableFactory.java +92 -93
  115. metadata +10 -11
  116. data/.travis.yml +0 -9
@@ -1,30 +1,29 @@
1
1
  /**
2
- Copyright 2004-2008 Ricard Marxer <email@ricardmarxer.com>
3
-
4
- This file is part of Geomerative.
5
-
6
- Geomerative is free software: you can redistribute it and/or modify
7
- it under the terms of the GNU General Public License as published by
8
- the Free Software Foundation, either version 3 of the License, or
9
- (at your option) any later version.
10
-
11
- Geomerative is distributed in the hope that it will be useful,
12
- but WITHOUT ANY WARRANTY; without even the implied warranty of
13
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
- GNU General Public License for more details.
15
-
16
- You should have received a copy of the GNU General Public License
17
- along with Geomerative. If not, see <http://www.gnu.org/licenses/>.
18
- */
19
-
20
- package geomerative ;
21
-
2
+ * Copyright 2004-2008 Ricard Marxer <email@ricardmarxer.com>
3
+ *
4
+ * This file is part of Geomerative.
5
+ *
6
+ * Geomerative is free software: you can redistribute it and/or modify it under
7
+ * the terms of the GNU General Public License as published by the Free Software
8
+ * Foundation, either version 3 of the License, or (at your option) any later
9
+ * version.
10
+ *
11
+ * Geomerative is distributed in the hope that it will be useful, but WITHOUT
12
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14
+ * details.
15
+ *
16
+ * You should have received a copy of the GNU General Public License along with
17
+ * Geomerative. If not, see <http://www.gnu.org/licenses/>.
18
+ */
19
+ package geomerative;
22
20
 
23
21
  /**
24
- * This class allows contains information about an evaluation of the closest points or intersections between shapes/paths/commands.
22
+ * This class allows contains information about an evaluation of the closest
23
+ * points or intersections between shapes/paths/commands.
25
24
  */
26
- public class RClosest
27
- {
25
+ public class RClosest {
26
+
28
27
  public RPoint[] intersects;
29
28
  public RPoint[] closest;
30
29
 
@@ -32,28 +31,31 @@ public class RClosest
32
31
  public float distance = 10000;
33
32
  public float[] advancements;
34
33
 
35
- public RClosest() {}
36
-
34
+ public RClosest() {
35
+ }
36
+
37
37
  public void update(RClosest other) {
38
38
  if (other.intersects == null) {
39
39
 
40
- if (other.distance > this.distance) return;
40
+ if (other.distance > this.distance) {
41
+ return;
42
+ }
41
43
 
42
44
  this.distance = other.distance;
43
45
  this.closest = other.closest;
44
46
  this.advancements = other.advancements;
45
-
47
+
46
48
  } else {
47
49
 
48
50
  this.closest = null;
49
51
  this.advancements = null;
50
52
  this.distance = 0;
51
53
  RPoint[] newIntersects;
52
-
53
- if(this.intersects==null){
54
+
55
+ if (this.intersects == null) {
54
56
  this.intersects = new RPoint[other.intersects.length];
55
57
  System.arraycopy(other.intersects, 0, this.intersects, 0, other.intersects.length);
56
- }else{
58
+ } else {
57
59
  newIntersects = new RPoint[this.intersects.length + other.intersects.length];
58
60
  System.arraycopy(this.intersects, 0, newIntersects, 0, this.intersects.length);
59
61
  System.arraycopy(other.intersects, 0, newIntersects, this.intersects.length, other.intersects.length);
@@ -61,4 +63,4 @@ public class RClosest
61
63
  }
62
64
  }
63
65
  }
64
- }
66
+ }
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Copyright 2004-2008 Ricard Marxer <email@ricardmarxer.com>
3
3
  *
4
- This file is part of Geomerative.
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
- * @extended
25
+
26
26
  */
27
27
  public class RCommand extends RGeomElem {
28
28
 
29
- /**
30
- * @invisible
31
- */
32
- public int type = RGeomElem.COMMAND;
29
+ /**
30
+ *
31
+ */
32
+ public int type = RGeomElem.COMMAND;
33
33
 
34
- public RPoint[] controlPoints;
35
- public RPoint startPoint;
36
- public RPoint endPoint;
37
- int commandType;
34
+ public RPoint[] controlPoints;
35
+ public RPoint startPoint;
36
+ public RPoint endPoint;
37
+ int commandType;
38
38
 
39
- RPoint[] curvePoints;
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
- public static final int QUADBEZIERTO = 1;
51
- /**
52
- * @invisible
44
+ */
45
+ public static final int LINETO = 0;
46
+ /**
53
47
  *
54
- */
55
- public static final int CUBICBEZIERTO = 2;
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
- public static final int UNIFORMLENGTH = 1;
67
- /**
68
- * @invisible
60
+ */
61
+ public static final int ADAPTATIVE = 0;
62
+ /**
69
63
  *
70
- */
71
- public static final int UNIFORMSTEP = 2;
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
- public static int segmentType = UNIFORMLENGTH;
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
- 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;
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
- static float segmentLength = 4.0F;
91
- static float segmentOffset = 0.0F;
92
- static float segmentAccOffset = 0.0F;
444
+ oldSegmentLength = RCommand.segmentLength;
445
+ oldSegmentOffset = RCommand.segmentOffset;
446
+ oldSegmentAccOffset = RCommand.segmentAccOffset;
93
447
 
94
448
  /* Parameters for UNIFORMSTEP */
95
- static int segmentSteps = 0;
96
- static boolean segmentLines = false;
449
+ oldSegmentSteps = RCommand.segmentSteps;
450
+ oldSegmentLines = RCommand.segmentLines;
451
+ }
97
452
 
98
- int oldSegmentType = UNIFORMLENGTH;
453
+ protected void restoreSegmentatorContext() {
454
+ RCommand.segmentType = oldSegmentType;
99
455
 
100
456
  /* 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;
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
- float oldSegmentLength = 4.0F;
114
- float oldSegmentOffset = 0.0F;
115
- float oldSegmentAccOffset = 0.0F;
466
+ RCommand.segmentLength = oldSegmentLength;
467
+ RCommand.segmentOffset = oldSegmentOffset;
468
+ RCommand.segmentAccOffset = oldSegmentAccOffset;
116
469
 
117
470
  /* 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
- }
471
+ RCommand.segmentSteps = oldSegmentSteps;
472
+ RCommand.segmentLines = oldSegmentLines;
473
+ }
128
474
 
129
- static RCommand createLine(float startx, float starty, float endx, float endy) {
130
- return createLine(new RPoint(startx, starty), new RPoint(endx, endy));
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
- 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
- }
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
- 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
- }
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
- 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
- }
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
- 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
- }
551
+ protected RPoint[] getPoints(boolean resetSegmentator) {
159
552
 
160
- /**
161
- * Create an empty command
162
- *
163
- * @invisible
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
- * Make a copy of another RCommand object. This can be useful when wanting
171
- * to transform one but at the same time keep the original.
172
- *
173
- * @param c the object of which to make the copy
174
- * @invisible
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]));
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
- this.endPoint = new RPoint(c.endPoint);
182
- this.commandType = c.commandType;
183
- }
581
+ break;
184
582
 
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]));
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
- 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
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
- * Create a QUADBEZIERTO command object with specific start, control and end
229
- * point coordinates.
230
- *
231
- * @param sp the start point of the command to be created
232
- * @param cp1 the first control point of the command to be created
233
- * @param ep the end point of the command to be created
234
- */
235
- public RCommand(RPoint sp, RPoint cp1, RPoint ep) {
236
- this.startPoint = sp;
237
- this.append(cp1);
238
- this.endPoint = ep;
239
- this.commandType = QUADBEZIERTO;
240
- }
241
-
242
- /**
243
- * Create a QUADBEZIERTO command object with specific start, control and end
244
- * point coordinates.
245
- *
246
- * @param spx the x coordinate of the start point of the command to be
247
- * created
248
- * @param spy the y coordinate of the start point of the command to be
249
- * created
250
- * @param cp1x the x coordinate of the first control point of the command to
251
- * be created
252
- * @param cp1y the y coordinate of the first control point of the command to
253
- * be created
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
- * @return @invisible
303
- */
304
- @Override
305
- public RShape toShape() {
306
- return new RShape(new RPath(this));
634
+ if (resetSegmentator) {
635
+ restoreSegmentatorContext();
307
636
  }
308
637
 
309
- @Override
310
- public int getType() {
311
- return this.type;
312
- }
638
+ return result;
639
+ }
313
640
 
314
- /**
315
- * Use this to set the segmentator type. ADAPTATIVE segmentator minimizes
316
- * the number of segments avoiding perceptual artifacts like angles or
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
- public static void setSegmentator(int segmentatorType) {
334
- segmentType = segmentatorType;
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
- public static void setSegmentGraphic(PGraphics g) {
346
- // Set the segmentApproxScale from the graphic context g
347
- segmentApproxScale = 1.0F;
348
-
349
- // Set all the gfx-context dependent parameters for all segmentators
350
- segmentDistTolSqr = 0.5F / segmentApproxScale;
351
- segmentDistTolSqr *= segmentDistTolSqr;
352
- segmentDistTolMnhttn = 4.0F / segmentApproxScale;
353
- segmentAngleTol = 0.0F;
354
-
355
- if (g.stroke && (g.strokeWeight * segmentApproxScale > 1.0F)) {
356
- segmentAngleTol = 0.1F;
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
- * Use this to set the segmentator angle tolerance for the ADAPTATIVE
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
- segmentAngleTol = segmentAngleTolerance;
373
- }
732
+ return getTangents(100);
733
+ }
374
734
 
375
- /**
376
- * Use this to set the segmentator length for the UNIFORMLENGTH segmentator
377
- * and set the segmentator to UNIFORMLENGTH.
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
- public static void setSegmentLength(float segmentLngth) {
384
- //segmentType = UNIFORMLENGTH;
385
- if (segmentLngth >= 1) {
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
- public static void setSegmentOffset(float segmentOffst) {
401
- //segmentType = UNIFORMLENGTH;
402
- if (segmentOffst >= 0) {
403
- segmentOffset = segmentOffst;
404
- } else {
405
- segmentOffset = 0;
406
- }
407
- }
408
-
409
- /**
410
- * Use this to set the segmentator step for the UNIFORMSTEP segmentator and
411
- * set the segmentator to UNIFORMSTEP.
412
- *
413
- * @eexample setSegmentStep
414
- * @param segmentStps if a float from +0.0 to 1.0 is passed it's considered
415
- * as the step, else it's considered as the number of steps. When a value of
416
- * 0.0 is used the steps will be calculated automatically depending on an
417
- * estimation of the length of the curve. The special value -1 is the same
418
- * as 0.0 but also turning of the segmentation of lines (faster
419
- * segmentation).
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
- public static void setSegmentStep(float segmentStps) {
423
- //segmentType = UNIFORMSTEP;
424
- if (segmentStps == -1F) {
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
- public int getCommandType() {
506
- return commandType;
507
- }
508
-
509
- /**
510
- * Use this to return the start point of the curve.
511
- *
512
- * @eexample getStartPoint
513
- * @return RPoint, the start point of the curve.
514
- * @invisible
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
- RPoint getStartPoint() {
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
- RPoint[] getControlPoints() {
543
- return controlPoints;
544
- }
545
-
546
- /**
547
- * Use this to return the points on the curve. It returns the points in the
548
- * way of an array of RPoint.
549
- *
550
- * @eexample getPoints
551
- * @return RPoint[], the vertices returned in an array.
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
- @Override
555
- public RPoint[] getPoints() {
556
- return getPoints(true);
557
- }
558
-
559
- protected RPoint[] getPoints(boolean resetSegmentator) {
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
- if (resetSegmentator) {
562
- saveSegmentatorContext();
563
- RCommand.segmentOffset = 0F;
564
- RCommand.segmentAccOffset = 0F;
565
- }
936
+ switch (commandType) {
937
+ case LINETO:
938
+ return splitLine(t);
566
939
 
567
- RPoint[] result = null;
568
- switch (segmentType) {
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
- if (resetSegmentator) {
643
- restoreSegmentatorContext();
644
- }
943
+ case CUBICBEZIERTO:
944
+ return splitCubicBezier(t);
645
945
 
646
- return result;
647
946
  }
947
+ return null;
948
+ }
648
949
 
649
- /**
650
- * Use this to return a specific point on the curve. It returns the RPoint
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
- public RPoint[] getTangents(int segments) {
715
- RPoint[] result;
716
- float dt, t;
717
- switch (commandType) {
718
- case LINETO:
719
- result = new RPoint[2];
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
- @Override
738
- public RPoint[] getTangents() {
964
+ RPoint[] ctrlPoints = this.getHandles();
739
965
 
740
- return getTangents(100);
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
- * Use this to return a specific tangent on the curve. It returns the RPoint
745
- * representing the tangent vector for a given value of the advancement
746
- * parameter t on the curve.
747
- *
748
- * @eexample getTangent
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
- * Use this to return arc length of a curve. It returns the float
790
- * representing the length given the value of the advancement parameter t on
791
- * the curve. The current implementation of this function is very slow, not
792
- * recommended for using during frame draw.
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
- return -1F;
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
- @Override
848
- public RPoint[][] getPointsInPaths() {
849
- PApplet.println("Feature not yet implemented for this class.");
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
- @Override
854
- public RPoint[][] getHandlesInPaths() {
855
- PApplet.println("Feature not yet implemented for this class.");
856
- return null;
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
- @Override
860
- public RPoint[][] getTangentsInPaths() {
861
- PApplet.println("Feature not yet implemented for this class.");
862
- return null;
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
- @Override
866
- public boolean contains(RPoint p) {
867
- PApplet.println("Feature not yet implemented for this class.");
868
- return false;
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
- * Use this method to draw the command.
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
- * Use this to return the start, control and end points of the curve. It
912
- * returns the points in the way of an array of RPoint.
913
- *
914
- * @eexample getHandles
915
- * @return RPoint[], the vertices returned in an array.
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
- * Returns two commands resulting of splitting the command.
936
- *
937
- * @eexample split
938
- * @param t the advancement on the curve where command should be split.
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
- case QUADBEZIERTO:
949
- return splitQuadBezier(t);
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
- case CUBICBEZIERTO:
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
- return null;
1052
+ if (level > SEGMENT_RECURSION_LIMIT) {
1053
+ return;
956
1054
  }
957
1055
 
958
- /**
959
- * Taken from: http://steve.hollasch.net/cgindex/curves/cbezarclen.html
960
- *
961
- * who took it from: Schneider's Bezier curve-fitter
962
- *
963
- */
964
- private RCommand[] splitCubicBezier(float t) {
965
- RPoint[][] triangleMatrix = new RPoint[4][4];
966
- for (int i = 0; i <= 3; i++) {
967
- for (int j = 0; j <= 3; j++) {
968
- triangleMatrix[i][j] = new RPoint();
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
- RPoint[] ctrlPoints = this.getHandles();
973
-
974
- // Copy control points to triangle matrix
975
- for (int i = 0; i <= 3; i++) {
976
- triangleMatrix[0][i].x = ctrlPoints[i].x;
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
- // Triangle computation
981
- for (int i = 1; i <= 3; i++) {
982
- for (int j = 0; j <= 3 - i; j++) {
983
- triangleMatrix[i][j].x = (1 - t) * triangleMatrix[i - 1][j].x + t * triangleMatrix[i - 1][j + 1].x;
984
- triangleMatrix[i][j].y = (1 - t) * triangleMatrix[i - 1][j].y + t * triangleMatrix[i - 1][j + 1].y;
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
- RCommand[] result = new RCommand[2];
989
- result[0] = createBezier4(startPoint, triangleMatrix[1][0], triangleMatrix[2][0], triangleMatrix[3][0]);
990
- result[1] = createBezier4(triangleMatrix[3][0], triangleMatrix[2][1], triangleMatrix[1][2], endPoint);
991
- return result;
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
- private RCommand[] splitQuadBezier(float t) {
995
- RPoint[][] triangleMatrix = new RPoint[3][3];
996
- for (int i = 0; i <= 2; i++) {
997
- for (int j = 0; j <= 2; j++) {
998
- triangleMatrix[i][j] = new RPoint();
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
- RPoint[] ctrlPoints = this.getHandles();
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
- // Copy control points to triangle matrix
1005
- for (int i = 0; i <= 2; i++) {
1006
- triangleMatrix[0][i] = ctrlPoints[i];
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
- // Triangle computation
1010
- for (int i = 1; i <= 2; i++) {
1011
- for (int j = 0; j <= 2 - i; j++) {
1012
- triangleMatrix[i][j].x = (1 - t) * triangleMatrix[i - 1][j].x + t * triangleMatrix[i - 1][j + 1].x;
1013
- triangleMatrix[i][j].y = (1 - t) * triangleMatrix[i - 1][j].y + t * triangleMatrix[i - 1][j + 1].y;
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
- RCommand[] result = new RCommand[2];
1018
- result[0] = createBezier3(startPoint, triangleMatrix[1][0], triangleMatrix[2][0]);
1019
- result[1] = createBezier3(triangleMatrix[2][0], triangleMatrix[1][1], endPoint);
1020
- return result;
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
- private RCommand[] splitLine(float t) {
1024
- RPoint[][] triangleMatrix = new RPoint[2][2];
1025
- for (int i = 0; i <= 1; i++) {
1026
- for (int j = 0; j <= 1; j++) {
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
- RPoint[] ctrlPoints = this.getHandles();
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
- // Copy control points to triangle matrix
1034
- for (int i = 0; i <= 1; i++) {
1035
- triangleMatrix[0][i] = ctrlPoints[i];
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
- // Triangle computation
1039
- for (int i = 1; i <= 1; i++) {
1040
- for (int j = 0; j <= 1 - i; j++) {
1041
- triangleMatrix[i][j].x = (1 - t) * triangleMatrix[i - 1][j].x + t * triangleMatrix[i - 1][j + 1].x;
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
- RCommand[] result = new RCommand[2];
1047
- result[0] = createLine(startPoint, triangleMatrix[1][0]);
1048
- result[1] = createLine(triangleMatrix[1][0], endPoint);
1049
- return result;
1050
- }
1051
-
1052
- private void quadBezierAdaptative() {
1053
- addCurvePoint(new RPoint(startPoint));
1054
- quadBezierAdaptativeRecursive(startPoint.x, startPoint.y, controlPoints[0].x, controlPoints[0].y, endPoint.x, endPoint.y, 0);
1055
- addCurvePoint(new RPoint(endPoint));
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
- if (level > SEGMENT_RECURSION_LIMIT) {
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
- // Calculate all the mid-points of the line segments
1065
- //----------------------
1066
- float x12 = (x1 + x2) / 2;
1067
- float y12 = (y1 + y2) / 2;
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
- } else {
1104
- if (Math.abs(x1 + x3 - x2 - x2) + Math.abs(y1 + y3 - y2 - y2) <= segmentDistTolMnhttn) {
1105
- addCurvePoint(new RPoint(x123, y123));
1106
- return;
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
- private void cubicBezierAdaptative() {
1117
- addCurvePoint(new RPoint(startPoint));
1118
- cubicBezierAdaptativeRecursive(startPoint.x, startPoint.y, controlPoints[0].x, controlPoints[0].y, controlPoints[1].x, controlPoints[1].y, endPoint.x, endPoint.y, 0);
1119
- addCurvePoint(new RPoint(endPoint));
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
- // Try to approximate the full cubic curve by a single straight line
1143
- //------------------
1144
- float dx = x4 - x1;
1145
- float dy = y4 - y1;
1146
-
1147
- float d2 = Math.abs(((x2 - x4) * dy - (y2 - y4) * dx));
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
- // Angle Condition
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
- // Angle Condition
1207
- //----------------------
1208
- da1 = Math.abs((float) Math.atan2(y3 - y2, x3 - x2) - (float) Math.atan2(y2 - y1, x2 - x1));
1209
- if (da1 >= (float) Math.PI) {
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
- // Angle & Cusp Condition
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
- // Continue subdivision
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
- private void lineUniformStep() {
1281
- // If the number of steps is equal to 0 then choose a number of steps adapted to the curve
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
- float len = (float) Math.sqrt(dx * dx + dy * dy);
1288
- steps = (int) (len * 0.25);
1294
+ fy = startPoint.y;
1295
+ fdy = (endPoint.y - startPoint.y) * dt;
1289
1296
 
1290
- if (steps < 4) {
1291
- steps = 4;
1292
- }
1293
- }
1297
+ for (int loop = 0; loop < steps; loop++) {
1298
+ addCurvePoint(new RPoint(fx, fy));
1294
1299
 
1295
- float dt = 1F / steps;
1300
+ fx = fx + fdx;
1296
1301
 
1297
- float fx, fy, fdx, fdy;
1302
+ fy = fy + fdy;
1303
+ }
1304
+ addCurvePoint(new RPoint(endPoint));
1305
+ }
1298
1306
 
1299
- fx = startPoint.x;
1300
- fdx = (endPoint.x - startPoint.x) * dt;
1307
+ private void cubicBezierUniformStep() {
1301
1308
 
1302
- fy = startPoint.y;
1303
- fdy = (endPoint.y - startPoint.y) * dt;
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
- for (int loop = 0; loop < steps; loop++) {
1306
- addCurvePoint(new RPoint(fx, fy));
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
- fx = fx + fdx;
1323
+ steps = (int) (len * 0.25);
1309
1324
 
1310
- fy = fy + fdy;
1311
- }
1312
- addCurvePoint(new RPoint(endPoint));
1325
+ if (steps < 4) {
1326
+ steps = 4;
1327
+ }
1313
1328
  }
1314
1329
 
1315
- private void cubicBezierUniformStep() {
1330
+ float dt = 1F / steps;
1316
1331
 
1317
- // If the number of steps is equal to 0 then choose a number of steps adapted to the curve
1318
- int steps = segmentSteps;
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
- float len = (float) Math.sqrt(dx1 * dx1 + dy1 * dy1)
1328
- + (float) Math.sqrt(dx2 * dx2 + dy2 * dy2)
1329
- + (float) Math.sqrt(dx3 * dx3 + dy3 * dy3);
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
- steps = (int) (len * 0.25);
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
- if (steps < 4) {
1334
- steps = 4;
1335
- }
1336
- }
1351
+ for (int loop = 0; loop < steps; loop++) {
1352
+ addCurvePoint(new RPoint(fx, fy));
1337
1353
 
1338
- float dt = 1F / steps;
1339
-
1340
- 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;
1341
- float temp = dt * dt;
1342
-
1343
- fx = startPoint.x;
1344
- fdx = 3F * (controlPoints[0].x - startPoint.x) * dt;
1345
- fdd_per_2x = 3F * (startPoint.x - 2F * controlPoints[0].x + controlPoints[1].x) * temp;
1346
- fddd_per_2x = 3F * (3F * (controlPoints[0].x - controlPoints[1].x) + endPoint.x - startPoint.x) * temp * dt;
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
- private void quadBezierUniformStep() {
1376
- // If the number of steps is equal to 0 then choose a number of steps adapted to the curve
1377
- int steps = segmentSteps;
1378
- if (segmentSteps == 0.0F) {
1379
- float dx1 = controlPoints[0].x - startPoint.x;
1380
- float dy1 = controlPoints[0].y - startPoint.y;
1381
- float dx2 = endPoint.x - controlPoints[0].x;
1382
- float dy2 = endPoint.y - controlPoints[0].y;
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
- float len = (float) Math.sqrt(dx1 * dx1 + dy1 * dy1) + (float) Math.sqrt(dx2 * dx2 + dy2 * dy2);
1385
- steps = (int) (len * 0.25);
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
- if (steps < 4) {
1388
- steps = 4;
1389
- }
1390
- }
1379
+ if (steps < 4) {
1380
+ steps = 4;
1381
+ }
1382
+ }
1391
1383
 
1392
- float dt = 1F / steps;
1384
+ float dt = 1F / steps;
1393
1385
 
1394
- float fx, fy, fdx, fdy, fddx, fddy, fdd_per_2x, fdd_per_2y;
1395
- float temp = dt * dt;
1386
+ float fx, fy, fdx, fdy, fddx, fddy, fdd_per_2x, fdd_per_2y;
1387
+ float temp = dt * dt;
1396
1388
 
1397
- fx = startPoint.x;
1398
- fdx = 2F * (controlPoints[0].x - startPoint.x) * dt;
1399
- fdd_per_2x = (startPoint.x - 2F * controlPoints[0].x + endPoint.x) * temp;
1400
- fddx = fdd_per_2x + fdd_per_2x;
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
- fy = startPoint.y;
1403
- fdy = 2F * (controlPoints[0].y - startPoint.y) * dt;
1404
- fdd_per_2y = (startPoint.y - 2F * controlPoints[0].y + endPoint.y) * temp;
1405
- fddy = fdd_per_2y + fdd_per_2y;
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
- for (int loop = 0; loop < steps; loop++) {
1408
- addCurvePoint(new RPoint(fx, fy));
1399
+ for (int loop = 0; loop < steps; loop++) {
1400
+ addCurvePoint(new RPoint(fx, fy));
1409
1401
 
1410
- fx = fx + fdx + fdd_per_2x;
1411
- fdx = fdx + fddx;
1402
+ fx = fx + fdx + fdd_per_2x;
1403
+ fdx = fdx + fddx;
1412
1404
 
1413
- fy = fy + fdy + fdd_per_2y;
1414
- fdy = fdy + fddy;
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
- private void lineUniformLength() {
1412
+ //----------------------
1413
+ private void lineUniformLength() {
1422
1414
 
1423
- // If the number of steps is equal to 0 then choose a number of steps adapted to the curve
1424
- float dx1 = endPoint.x - startPoint.x;
1425
- float dy1 = endPoint.y - startPoint.y;
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
- float len = (float) Math.sqrt(dx1 * dx1 + dy1 * dy1);
1428
- float steps = (int) (len * 2);
1419
+ float len = (float) Math.sqrt(dx1 * dx1 + dy1 * dy1);
1420
+ float steps = (int) (len * 2);
1429
1421
 
1430
- if (steps < 4) {
1431
- steps = 4;
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
- // This holds how much length has to bee advanced until adding a point
1438
- float untilPoint = RCommand.segmentAccOffset;
1426
+ // This holds the amount of steps used to calculate segment lengths
1427
+ float dt = 1F / steps;
1439
1428
 
1440
- float fx, fy, fdx, fdy;
1429
+ // This holds how much length has to bee advanced until adding a point
1430
+ float untilPoint = RCommand.segmentAccOffset;
1441
1431
 
1442
- fx = startPoint.x;
1443
- fdx = (endPoint.x - startPoint.x) * dt;
1432
+ float fx, fy, fdx, fdy;
1444
1433
 
1445
- fy = startPoint.y;
1446
- fdy = (endPoint.y - startPoint.y) * dt;
1434
+ fx = startPoint.x;
1435
+ fdx = (endPoint.x - startPoint.x) * dt;
1447
1436
 
1448
- for (int loop = 0; loop <= steps; loop++) {
1449
- /* Add point to curve if segment length is reached */
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
- /* Add segment differential to segment length */
1456
- untilPoint -= (float) Math.sqrt(fdx * fdx + fdy * fdy); // Eventually try other distance measures
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
- fx = fx + fdx;
1459
- fy = fy + fdy;
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
- //addCurvePoint(new RPoint(endPoint));
1463
- RCommand.segmentAccOffset = untilPoint;
1450
+ fx = fx + fdx;
1451
+ fy = fy + fdy;
1464
1452
  }
1465
1453
 
1466
- // Use Horner's method to advance
1467
- //----------------------
1468
- private void quadBezierUniformLength() {
1454
+ //addCurvePoint(new RPoint(endPoint));
1455
+ RCommand.segmentAccOffset = untilPoint;
1456
+ }
1469
1457
 
1470
- float dx1 = controlPoints[0].x - startPoint.x;
1471
- float dy1 = controlPoints[0].y - startPoint.y;
1472
- float dx2 = endPoint.x - controlPoints[0].x;
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
- if (steps < 4) {
1478
- steps = 4;
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
- float dt = 1F / steps;
1482
- float untilPoint = RCommand.segmentAccOffset;
1469
+ if (steps < 4) {
1470
+ steps = 4;
1471
+ }
1483
1472
 
1484
- float fx, fy, fdx, fdy, fddx, fddy, fdd_per_2x, fdd_per_2y, fix, fiy;
1485
- float temp = dt * dt;
1473
+ float dt = 1F / steps;
1474
+ float untilPoint = RCommand.segmentAccOffset;
1486
1475
 
1487
- fx = startPoint.x;
1488
- fdx = 2F * (controlPoints[0].x - startPoint.x) * dt;
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
- fy = startPoint.y;
1493
- fdy = 2F * (controlPoints[0].y - startPoint.y) * dt;
1494
- fdd_per_2y = (startPoint.y - 2F * controlPoints[0].y + endPoint.y) * temp;
1495
- fddy = fdd_per_2y + fdd_per_2y;
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
- for (int loop = 0; loop <= steps; loop++) {
1498
- /* Add point to curve if segment length is reached */
1499
- if (untilPoint <= 0) {
1500
- addCurvePoint(new RPoint(fx, fy));
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
- /* Add segment differential to segment length */
1505
- fix = fdx + fdd_per_2x;
1506
- fiy = fdy + fdd_per_2y;
1507
- untilPoint -= (float) Math.sqrt(fix * fix + fiy * fiy); // Eventually try other distance measures
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
- fx = fx + fix;
1510
- fdx = fdx + fddx;
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
- fy = fy + fiy;
1513
- fdy = fdy + fddy;
1514
- }
1501
+ fx = fx + fix;
1502
+ fdx = fdx + fddx;
1515
1503
 
1516
- //addCurvePoint(new RPoint(endPoint));
1517
- RCommand.segmentAccOffset = untilPoint;
1504
+ fy = fy + fiy;
1505
+ fdy = fdy + fddy;
1518
1506
  }
1519
1507
 
1520
- // Use Horner's method to advance
1521
- //----------------------
1522
- private void cubicBezierUniformLength() {
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
- fx = fx + fix;
1575
- fdx = fdx + fddx + fddd_per_2x;
1576
- fddx = fddx + fdddx;
1577
- fdd_per_2x = fdd_per_2x + fddd_per_2x;
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
- fy = fy + fiy;
1580
- fdy = fdy + fddy + fddd_per_2y;
1581
- fddy = fddy + fdddy;
1582
- fdd_per_2y = fdd_per_2y + fddd_per_2y;
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
- //addCurvePoint(new RPoint(endPoint));
1586
- RCommand.segmentAccOffset = untilPoint;
1528
+ if (steps < 4) {
1529
+ steps = 4;
1587
1530
  }
1588
1531
 
1589
- private float quadBezierLength() {
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
- if (steps < 4) {
1599
- steps = 4;
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
- float dt = 1F / steps;
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
- float fx, fy, fdx, fdy, fddx, fddy, fdd_per_2x, fdd_per_2y, fix, fiy;
1605
- float temp = dt * dt;
1606
- float totallen = 0F;
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
- fx = startPoint.x;
1609
- fdx = 2F * (controlPoints[0].x - startPoint.x) * dt;
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
- fy = startPoint.y;
1614
- fdy = 2F * (controlPoints[0].y - startPoint.y) * dt;
1615
- fdd_per_2y = (startPoint.y - 2F * controlPoints[0].y + endPoint.y) * temp;
1616
- fddy = fdd_per_2y + fdd_per_2y;
1619
+ fy = fy + fiy;
1620
+ fdy = fdy + fddy;
1621
+ }
1617
1622
 
1618
- for (int loop = 0; loop <= steps; loop++) {
1619
- /* Add segment differential to segment length */
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
- fx = fx + fix;
1625
- fdx = fdx + fddx;
1626
+ private float cubicBezierLength() {
1626
1627
 
1627
- fy = fy + fiy;
1628
- fdy = fdy + fddy;
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
- return totallen;
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
- private float cubicBezierLength() {
1644
+ float dt = 1F / steps;
1635
1645
 
1636
- float dx1 = controlPoints[0].x - startPoint.x;
1637
- float dy1 = controlPoints[0].y - startPoint.y;
1638
- float dx2 = controlPoints[1].x - controlPoints[0].x;
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
- float len = (float) Math.sqrt(dx1 * dx1 + dy1 * dy1)
1644
- + (float) Math.sqrt(dx2 * dx2 + dy2 * dy2)
1645
- + (float) Math.sqrt(dx3 * dx3 + dy3 * dy3);
1646
- float steps = (int) (len * 2);
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
- if (steps < 4) {
1649
- steps = 4;
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
- float dt = 1F / steps;
1653
-
1654
- 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;
1655
- float temp = dt * dt;
1656
- float totallen = 0F;
1657
-
1658
- fx = startPoint.x;
1659
- fdx = 3F * (controlPoints[0].x - startPoint.x) * dt;
1660
- fdd_per_2x = 3F * (startPoint.x - 2F * controlPoints[0].x + controlPoints[1].x) * temp;
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
- return totallen;
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
- * Use this method to transform the command.
1697
- *
1698
- * @eexample transformCommand
1699
- * @param g PGraphics, the graphics object on which to apply an affine
1700
- * transformation to the command
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
- private void append(RPoint nextcontrolpoint) {
1715
- RPoint[] newcontrolPoints;
1716
- if (controlPoints == null) {
1717
- newcontrolPoints = new RPoint[1];
1718
- newcontrolPoints[0] = nextcontrolpoint;
1719
- } else {
1720
- newcontrolPoints = new RPoint[controlPoints.length + 1];
1721
- System.arraycopy(controlPoints, 0, newcontrolPoints, 0, controlPoints.length);
1722
- newcontrolPoints[controlPoints.length] = nextcontrolpoint;
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
- this.controlPoints = newcontrolPoints;
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
- private void addCurvePoint(RPoint nextcurvepoint) {
1728
- RPoint[] newcurvePoints;
1729
- if (curvePoints == null) {
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
- this.curvePoints = newcurvePoints;
1738
- }
1766
+ break;
1739
1767
 
1740
- public RPoint[] intersectionPoints(RCommand other) {
1741
- RPoint[] result = null;
1768
+ case CUBICBEZIERTO:
1769
+ switch (other.getCommandType()) {
1770
+ case LINETO:
1771
+ result = lineCubicIntersection(other, this);
1772
+ break;
1742
1773
 
1743
- switch (commandType) {
1744
- case LINETO:
1745
- switch (other.getCommandType()) {
1746
- case LINETO:
1747
- result = lineLineIntersection(this, other);
1748
- break;
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
- return result;
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
- public static RPoint[] lineLineIntersection(RCommand c1, RCommand c2) {
1797
- RPoint a = new RPoint(c1.startPoint);
1798
- RPoint b = new RPoint(c1.endPoint);
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
- RPoint c = new RPoint(c2.startPoint);
1801
- RPoint d = new RPoint(c2.endPoint);
1836
+ public static RPoint[] quadCubicIntersection(RCommand c1, RCommand c2) {
1837
+ return null;
1838
+ }
1802
1839
 
1803
- float epsilon = 1e-9f;
1840
+ public static RPoint[] cubicCubicIntersection(RCommand c1, RCommand c2) {
1841
+ return null;
1842
+ }
1804
1843
 
1805
- //test for parallel case
1806
- float denom = (d.y - c.y) * (b.x - a.x) - (d.x - c.x) * (b.y - a.y);
1807
- if (Math.abs(denom) < epsilon) {
1808
- return null;
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
- //calculate segment parameter and ensure its within bounds
1812
- float t1 = ((d.x - c.x) * (a.y - c.y) - (d.y - c.y) * (a.x - c.x)) / denom;
1813
- float t2 = ((b.x - a.x) * (a.y - c.y) - (b.y - a.y) * (a.x - c.x)) / denom;
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
- if (t1 < 0.0f || t1 > 1.0f || t2 < 0.0f || t2 > 1.0f) {
1816
- return null;
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
- //store actual intersection
1820
- RPoint[] result = new RPoint[1];
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
- RPoint temp = new RPoint(b);
1823
- temp.sub(a);
1824
- temp.scale(t1);
1935
+ return result;
1936
+ }
1825
1937
 
1826
- result[0] = new RPoint(a);
1827
- result[0].add(temp);
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
- return result;
1830
- }
1942
+ RPoint ap = new RPoint(p);
1943
+ ap.sub(a);
1831
1944
 
1832
- public static RPoint[] lineQuadIntersection(RCommand c1, RCommand c2) {
1833
- return null;
1834
- }
1945
+ RPoint ab = new RPoint(b);
1946
+ ab.sub(a);
1835
1947
 
1836
- public static RPoint[] lineCubicIntersection(RCommand c1, RCommand c2) {
1837
- return null;
1838
- }
1948
+ float denom = ab.sqrnorm();
1949
+ float epsilon = 1e-19f;
1839
1950
 
1840
- public static RPoint[] quadQuadIntersection(RCommand c1, RCommand c2) {
1841
- return null;
1951
+ if (denom < epsilon) {
1952
+ return 0.5f;
1842
1953
  }
1843
1954
 
1844
- public static RPoint[] quadCubicIntersection(RCommand c1, RCommand c2) {
1845
- return null;
1846
- }
1955
+ float t = (ab.x * ap.x + ab.y * ap.y) / denom;
1847
1956
 
1848
- public static RPoint[] cubicCubicIntersection(RCommand c1, RCommand c2) {
1849
- return null;
1850
- }
1957
+ t = t > 0.0f ? t : 0.0f;
1958
+ t = t < 1.0f ? t : 1.0f;
1851
1959
 
1852
- public RClosest closestPoints(RCommand other) {
1853
- RClosest result = new RClosest();
1854
- result.distance = 0;
1855
- RPoint temp;
1960
+ return t;
1856
1961
 
1857
- switch (commandType) {
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
- return result;
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
- public static float closestAdvFrom(RCommand c, RPoint p) {
1947
- RPoint a = new RPoint(c.startPoint);
1948
- RPoint b = new RPoint(c.endPoint);
1968
+ float c2t1 = closestAdvFrom(c2, c1b);
1969
+ float c2t2 = closestAdvFrom(c2, c1e);
1949
1970
 
1950
- RPoint ap = new RPoint(p);
1951
- ap.sub(a);
1971
+ RPoint c2p1 = c2.getPoint(c2t1);
1972
+ RPoint c2p2 = c2.getPoint(c2t2);
1952
1973
 
1953
- RPoint ab = new RPoint(b);
1954
- ab.sub(a);
1974
+ float dist1c2 = c2p1.dist(c1b);
1975
+ float dist2c2 = c2p2.dist(c1e);
1955
1976
 
1956
- float denom = ab.sqrnorm();
1957
- float epsilon = 1e-19f;
1977
+ RPoint c2b = new RPoint(c2.startPoint);
1978
+ RPoint c2e = new RPoint(c2.endPoint);
1958
1979
 
1959
- if (denom < epsilon) {
1960
- return 0.5f;
1961
- }
1980
+ float c1t1 = closestAdvFrom(c1, c2b);
1981
+ float c1t2 = closestAdvFrom(c1, c2e);
1962
1982
 
1963
- float t = (ab.x * ap.x + ab.y * ap.y) / denom;
1983
+ RPoint c1p1 = c1.getPoint(c1t1);
1984
+ RPoint c1p2 = c1.getPoint(c1t2);
1964
1985
 
1965
- t = t > 0.0f ? t : 0.0f;
1966
- t = t < 1.0f ? t : 1.0f;
1986
+ float dist1c1 = c1p1.dist(c2b);
1987
+ float dist2c1 = c1p2.dist(c2e);
1967
1988
 
1968
- return t;
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
- return result;
2056
- }
2046
+ */
2047
+ return result;
2048
+ }
2057
2049
 
2058
- public static RClosest lineQuadClosest(RCommand c1, RCommand c2) {
2059
- return null;
2060
- }
2050
+ public static RClosest lineQuadClosest(RCommand c1, RCommand c2) {
2051
+ return null;
2052
+ }
2061
2053
 
2062
- public static RClosest lineCubicClosest(RCommand c1, RCommand c2) {
2063
- return null;
2064
- }
2054
+ public static RClosest lineCubicClosest(RCommand c1, RCommand c2) {
2055
+ return null;
2056
+ }
2065
2057
 
2066
- public static RClosest quadQuadClosest(RCommand c1, RCommand c2) {
2067
- return null;
2068
- }
2058
+ public static RClosest quadQuadClosest(RCommand c1, RCommand c2) {
2059
+ return null;
2060
+ }
2069
2061
 
2070
- public static RClosest quadCubicClosest(RCommand c1, RCommand c2) {
2071
- return null;
2072
- }
2062
+ public static RClosest quadCubicClosest(RCommand c1, RCommand c2) {
2063
+ return null;
2064
+ }
2073
2065
 
2074
- public static RClosest cubicCubicClosest(RCommand c1, RCommand c2) {
2075
- return null;
2076
- }
2066
+ public static RClosest cubicCubicClosest(RCommand c1, RCommand c2) {
2067
+ return null;
2068
+ }
2077
2069
  }