geomerative 0.1.0-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (111) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +14 -0
  3. data/LICENSE +662 -0
  4. data/LICENSE.md +9 -0
  5. data/README.md +2 -0
  6. data/Rakefile +37 -0
  7. data/examples/README.md +7 -0
  8. data/examples/data/FreeSans.ttf +0 -0
  9. data/examples/data/ReplicaBold.ttf +0 -0
  10. data/examples/data/bot1.svg +160 -0
  11. data/examples/hello_svg_to_pdf.rb +26 -0
  12. data/examples/hello_world.rb +23 -0
  13. data/examples/physics_type.rb +77 -0
  14. data/examples/rotate_first_letter.rb +28 -0
  15. data/geomerative.gemspec +32 -0
  16. data/lib/geomerative.rb +12 -0
  17. data/lib/geomerative/version.rb +3 -0
  18. data/pom.xml +110 -0
  19. data/src/geomerative/FastRClip.java +2715 -0
  20. data/src/geomerative/RClip.java +2892 -0
  21. data/src/geomerative/RClosest.java +64 -0
  22. data/src/geomerative/RCommand.java +1941 -0
  23. data/src/geomerative/RContour.java +348 -0
  24. data/src/geomerative/RFont.java +583 -0
  25. data/src/geomerative/RG.java +753 -0
  26. data/src/geomerative/RGeomElem.java +1075 -0
  27. data/src/geomerative/RGroup.java +888 -0
  28. data/src/geomerative/RMatrix.java +401 -0
  29. data/src/geomerative/RMesh.java +420 -0
  30. data/src/geomerative/RPath.java +1095 -0
  31. data/src/geomerative/RPoint.java +419 -0
  32. data/src/geomerative/RPolygon.java +1110 -0
  33. data/src/geomerative/RRectangle.java +91 -0
  34. data/src/geomerative/RSVG.java +976 -0
  35. data/src/geomerative/RShape.java +2045 -0
  36. data/src/geomerative/RStrip.java +221 -0
  37. data/src/geomerative/RStyle.java +469 -0
  38. data/src/org/apache/batik/svggen/font/.SVGFont.java.swp +0 -0
  39. data/src/org/apache/batik/svggen/font/Font.java +188 -0
  40. data/src/org/apache/batik/svggen/font/Glyph.java +113 -0
  41. data/src/org/apache/batik/svggen/font/Messages.java.bak +72 -0
  42. data/src/org/apache/batik/svggen/font/Point.java +38 -0
  43. data/src/org/apache/batik/svggen/font/RandomAccessFileEmulator.java +15 -0
  44. data/src/org/apache/batik/svggen/font/table/ClassDef.java +42 -0
  45. data/src/org/apache/batik/svggen/font/table/ClassDefFormat1.java +55 -0
  46. data/src/org/apache/batik/svggen/font/table/ClassDefFormat2.java +49 -0
  47. data/src/org/apache/batik/svggen/font/table/CmapFormat.java +81 -0
  48. data/src/org/apache/batik/svggen/font/table/CmapFormat0.java +60 -0
  49. data/src/org/apache/batik/svggen/font/table/CmapFormat2.java +48 -0
  50. data/src/org/apache/batik/svggen/font/table/CmapFormat4.java +147 -0
  51. data/src/org/apache/batik/svggen/font/table/CmapFormat6.java +60 -0
  52. data/src/org/apache/batik/svggen/font/table/CmapIndexEntry.java +84 -0
  53. data/src/org/apache/batik/svggen/font/table/CmapTable.java +87 -0
  54. data/src/org/apache/batik/svggen/font/table/Coverage.java +50 -0
  55. data/src/org/apache/batik/svggen/font/table/CoverageFormat1.java +59 -0
  56. data/src/org/apache/batik/svggen/font/table/CoverageFormat2.java +56 -0
  57. data/src/org/apache/batik/svggen/font/table/CvtTable.java +48 -0
  58. data/src/org/apache/batik/svggen/font/table/Device.java +63 -0
  59. data/src/org/apache/batik/svggen/font/table/DirectoryEntry.java +73 -0
  60. data/src/org/apache/batik/svggen/font/table/Feature.java +56 -0
  61. data/src/org/apache/batik/svggen/font/table/FeatureList.java +70 -0
  62. data/src/org/apache/batik/svggen/font/table/FeatureRecord.java +52 -0
  63. data/src/org/apache/batik/svggen/font/table/FeatureTags.java +30 -0
  64. data/src/org/apache/batik/svggen/font/table/FpgmTable.java +38 -0
  65. data/src/org/apache/batik/svggen/font/table/GlyfCompositeComp.java +165 -0
  66. data/src/org/apache/batik/svggen/font/table/GlyfCompositeDescript.java +160 -0
  67. data/src/org/apache/batik/svggen/font/table/GlyfDescript.java +79 -0
  68. data/src/org/apache/batik/svggen/font/table/GlyfSimpleDescript.java +155 -0
  69. data/src/org/apache/batik/svggen/font/table/GlyfTable.java +111 -0
  70. data/src/org/apache/batik/svggen/font/table/GlyphDescription.java +39 -0
  71. data/src/org/apache/batik/svggen/font/table/GposTable.java +80 -0
  72. data/src/org/apache/batik/svggen/font/table/GsubTable.java +118 -0
  73. data/src/org/apache/batik/svggen/font/table/HeadTable.java +159 -0
  74. data/src/org/apache/batik/svggen/font/table/HheaTable.java +109 -0
  75. data/src/org/apache/batik/svggen/font/table/HmtxTable.java +99 -0
  76. data/src/org/apache/batik/svggen/font/table/KernSubtable.java +58 -0
  77. data/src/org/apache/batik/svggen/font/table/KernSubtableFormat0.java +65 -0
  78. data/src/org/apache/batik/svggen/font/table/KernSubtableFormat2.java +56 -0
  79. data/src/org/apache/batik/svggen/font/table/KernTable.java +64 -0
  80. data/src/org/apache/batik/svggen/font/table/KerningPair.java +53 -0
  81. data/src/org/apache/batik/svggen/font/table/LangSys.java +58 -0
  82. data/src/org/apache/batik/svggen/font/table/LangSysRecord.java +52 -0
  83. data/src/org/apache/batik/svggen/font/table/Ligature.java +57 -0
  84. data/src/org/apache/batik/svggen/font/table/LigatureSet.java +55 -0
  85. data/src/org/apache/batik/svggen/font/table/LigatureSubst.java +40 -0
  86. data/src/org/apache/batik/svggen/font/table/LigatureSubstFormat1.java +63 -0
  87. data/src/org/apache/batik/svggen/font/table/LocaTable.java +72 -0
  88. data/src/org/apache/batik/svggen/font/table/Lookup.java +77 -0
  89. data/src/org/apache/batik/svggen/font/table/LookupList.java +68 -0
  90. data/src/org/apache/batik/svggen/font/table/LookupSubtable.java +27 -0
  91. data/src/org/apache/batik/svggen/font/table/LookupSubtableFactory.java +31 -0
  92. data/src/org/apache/batik/svggen/font/table/MaxpTable.java +124 -0
  93. data/src/org/apache/batik/svggen/font/table/NameRecord.java +98 -0
  94. data/src/org/apache/batik/svggen/font/table/NameTable.java +67 -0
  95. data/src/org/apache/batik/svggen/font/table/Os2Table.java +232 -0
  96. data/src/org/apache/batik/svggen/font/table/Panose.java +108 -0
  97. data/src/org/apache/batik/svggen/font/table/PostTable.java +379 -0
  98. data/src/org/apache/batik/svggen/font/table/PrepTable.java +38 -0
  99. data/src/org/apache/batik/svggen/font/table/Program.java +49 -0
  100. data/src/org/apache/batik/svggen/font/table/RangeRecord.java +57 -0
  101. data/src/org/apache/batik/svggen/font/table/Script.java +72 -0
  102. data/src/org/apache/batik/svggen/font/table/ScriptList.java +78 -0
  103. data/src/org/apache/batik/svggen/font/table/ScriptRecord.java +52 -0
  104. data/src/org/apache/batik/svggen/font/table/ScriptTags.java +28 -0
  105. data/src/org/apache/batik/svggen/font/table/SingleSubst.java +47 -0
  106. data/src/org/apache/batik/svggen/font/table/SingleSubstFormat1.java +67 -0
  107. data/src/org/apache/batik/svggen/font/table/SingleSubstFormat2.java +67 -0
  108. data/src/org/apache/batik/svggen/font/table/Table.java +204 -0
  109. data/src/org/apache/batik/svggen/font/table/TableDirectory.java +94 -0
  110. data/src/org/apache/batik/svggen/font/table/TableFactory.java +121 -0
  111. metadata +206 -0
@@ -0,0 +1,888 @@
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
+ import processing.core.*;
22
+
23
+
24
+ /**
25
+ * RGroup is a holder for a group of geometric elements that can be drawn and transformed, such as shapes, polygons or meshes.
26
+ * @usage geometry
27
+ * @extended
28
+ */
29
+ public class RGroup extends RGeomElem
30
+ {
31
+ /**
32
+ * @invisible
33
+ */
34
+ public int type = RGeomElem.GROUP;
35
+
36
+ /**
37
+ * Array of RGeomElem objects holding the elements of the group. When accessing theses elements we must cast them to their class in order to get all the functionalities of each representation. e.g. RShape s = group.elements[i].toShape() If the element cannot be converted to the target class it will throw a RuntimeException, to ignore these, use try-catch syntax.
38
+ * @eexample RGroup_elements
39
+ * @related RShape
40
+ * @related RPolygon
41
+ * @related RMesh
42
+ * @related countElements ( )
43
+ * @related addElement ( )
44
+ * @related removeElement ( )
45
+ */
46
+ public RGeomElem[] elements;
47
+
48
+ /**
49
+ * Use this method to create a new empty group.
50
+ * @eexample RGroup
51
+ */
52
+ public RGroup(){
53
+ elements = null;
54
+ }
55
+
56
+ /**
57
+ * Use this method to create a copy of a group.
58
+ * @eexample RGroup
59
+ */
60
+ public RGroup(RGroup grp){
61
+ for(int i=0;i<grp.countElements();i++){
62
+ //System.out.println(grp.elements[i].getType());
63
+ switch(grp.elements[i].getType()){
64
+ case RGeomElem.MESH:
65
+ this.addElement(new RMesh((RMesh)grp.elements[i]));
66
+ break;
67
+
68
+ case RGeomElem.GROUP:
69
+ this.addElement(new RGroup((RGroup)grp.elements[i]));
70
+ break;
71
+
72
+ case RGeomElem.POLYGON:
73
+ this.addElement(new RPolygon((RPolygon)grp.elements[i]));
74
+ break;
75
+
76
+ case RGeomElem.SHAPE:
77
+ this.addElement(new RShape((RShape)grp.elements[i]));
78
+ break;
79
+
80
+ }
81
+ }
82
+
83
+ setStyle(grp);
84
+ }
85
+
86
+
87
+ /**
88
+ * Use this method to get the centroid of the element.
89
+ * @eexample RGroup_getCentroid
90
+ * @return RPoint, the centroid point of the element
91
+ * @related getBounds ( )
92
+ * @related getCenter ( )
93
+ */
94
+ public RPoint getCentroid(){
95
+ RPoint bestCentroid = new RPoint();
96
+ float bestArea = Float.NEGATIVE_INFINITY;
97
+ if(elements != null){
98
+ for(int i=0;i<elements.length-1;i++)
99
+ {
100
+ float area = elements[i].getArea();
101
+ if(area > bestArea){
102
+ bestArea = area;
103
+ bestCentroid = elements[i].getCentroid();
104
+ }
105
+ }
106
+ return bestCentroid;
107
+ }
108
+ return null;
109
+ }
110
+
111
+ /**
112
+ * Use this method to count the number of elements in the group.
113
+ * @eexample RGroup_countElements
114
+ * @return int, the number elements in the group.
115
+ * @related addElement ( )
116
+ * @related removeElement ( )
117
+ */
118
+ public int countElements(){
119
+ if(elements==null) return 0;
120
+ return elements.length;
121
+ }
122
+
123
+ public void print(){
124
+ System.out.println("group: ");
125
+ for(int i=0;i<countElements();i++)
126
+ {
127
+ System.out.println("--- "+i+" ---");
128
+ elements[i].print();
129
+ System.out.println("---------------");
130
+ }
131
+ }
132
+
133
+ /**
134
+ * Use this method to draw the group. This will draw each element at a time, without worrying about intersections or holes. This is the main difference between having a shape with multiple paths and having a group with multiple shapes.
135
+ * @eexample RGroup_draw
136
+ * @param g PGraphics, the graphics object on which to draw the group
137
+ */
138
+ public void draw(PGraphics g){
139
+ if(!RG.ignoreStyles){
140
+ saveContext(g);
141
+ setContext(g);
142
+ }
143
+
144
+ for(int i=0; i<countElements(); i++){
145
+ elements[i].draw(g);
146
+ }
147
+
148
+ if(!RG.ignoreStyles){
149
+ restoreContext(g);
150
+ }
151
+ }
152
+
153
+ public void draw(PApplet a){
154
+ if(!RG.ignoreStyles){
155
+ saveContext(a);
156
+ setContext(a);
157
+ }
158
+
159
+ for(int i=0; i<countElements(); i++){
160
+ elements[i].draw(a);
161
+ }
162
+
163
+ if(!RG.ignoreStyles){
164
+ restoreContext(a);
165
+ }
166
+ }
167
+
168
+ /**
169
+ * Use this method to add a new element.
170
+ * @eexample RGroup_addElement
171
+ * @param elem RGeomElem, any kind of RGeomElem to add. It accepts the classes RShape, RPolygon and RMesh.
172
+ * @related removeElement ( )
173
+ */
174
+ public void addElement(RGeomElem elem){
175
+ this.append(elem);
176
+ }
177
+
178
+ /**
179
+ * Use this method to add a new element.
180
+ * @eexample RGroup_addGroup
181
+ * @param grupo RGroup, A group of elements to add to this group.
182
+ * @related removeElement ( )
183
+ */
184
+ public void addGroup(RGroup grupo){
185
+ for(int i=0;i<grupo.countElements();i++){
186
+ this.addElement(grupo.elements[i]);
187
+ }
188
+ }
189
+
190
+ /**
191
+ * Use this method to remove an element.
192
+ * @eexample RGroup_removeElement
193
+ * @param i int, the index of the element to remove from the group.
194
+ * @related addElement ( )
195
+ */
196
+ public void removeElement(int i) throws RuntimeException{
197
+ this.extract(i);
198
+ }
199
+
200
+ /**
201
+ * Use this method to get a new group whose elements are the corresponding meshes of the elements in the current group. This can be used for increasing performance in exchange of losing abstraction.
202
+ * @eexample RGroup_toMeshGroup
203
+ * @return RGroup, the new group made of RMeshes
204
+ * @related toPolygonGroup ( )
205
+ * @related toShapeGroup ( )
206
+ */
207
+ public RGroup toMeshGroup() throws RuntimeException{
208
+ RGroup result = new RGroup();
209
+ for(int i=0;i<countElements();i++){
210
+ result.addElement(elements[i].toMesh());
211
+ }
212
+ return result;
213
+ }
214
+
215
+ /**
216
+ * Use this method to get a new group whose elements are the corresponding polygons of the elements in the current group. At this moment there is no implementation for transforming a mesh to a polygon so applying this method to groups holding mesh elements will generate an exception.
217
+ * @eexample RGroup_toPolygonGroup
218
+ * @return RGroup, the new group made of RPolygons
219
+ * @related toMeshGroup ( )
220
+ * @related toShapeGroup ( )
221
+ */
222
+ public RGroup toPolygonGroup() throws RuntimeException{
223
+ RGroup result = new RGroup();
224
+ for(int i=0;i<countElements();i++){
225
+ RGeomElem element = elements[i];
226
+ if(element.getType() == RGeomElem.GROUP){
227
+ RGeomElem newElement = ((RGroup)(element)).toPolygonGroup();
228
+ result.addElement(newElement);
229
+ }else{
230
+ result.addElement(element.toPolygon());
231
+ }
232
+ }
233
+ result.setStyle(this);
234
+ return result;
235
+ }
236
+
237
+ /**
238
+ * Use this method to get a new group whose elements are all the corresponding shapes of the elements in the current group. At this moment there is no implementation for transforming a mesh or a polygon to a shape so applying this method to groups holding mesh or polygon elements will generate an exception.
239
+ * @eexample RGroup_toShapeGroup
240
+ * @return RGroup, the new group made of RShapes
241
+ * @related toMeshGroup ( )
242
+ * @related toPolygonGroup ( )
243
+ */
244
+ public RGroup toShapeGroup() throws RuntimeException{
245
+ RGroup result = new RGroup();
246
+ for(int i=0;i<countElements();i++){
247
+ RGeomElem element = elements[i];
248
+ if(element.getType() == RGeomElem.GROUP){
249
+ RGeomElem newElement = ((RGroup)(element)).toShapeGroup();
250
+ result.addElement(newElement);
251
+ }else{
252
+ result.addElement(element.toShape());
253
+ }
254
+ }
255
+ result.setStyle(this);
256
+ return result;
257
+ }
258
+
259
+ /**
260
+ * @invisible
261
+ */
262
+ public RMesh toMesh() throws RuntimeException{
263
+ //throw new RuntimeException("Transforming a Group to a Mesh is not yet implemented.");
264
+ RGroup meshGroup = toMeshGroup();
265
+ RMesh result = new RMesh();
266
+ for(int i=0;i<countElements();i++){
267
+ RMesh currentMesh = (RMesh)(meshGroup.elements[i]);
268
+ for(int j=0;j<currentMesh.countStrips();j++){
269
+ result.addStrip(currentMesh.strips[j]);
270
+ }
271
+ }
272
+ result.setStyle(this);
273
+ return result;
274
+ }
275
+
276
+ /**
277
+ * @invisible
278
+ */
279
+ public RPolygon toPolygon() throws RuntimeException{
280
+ //throw new RuntimeException("Transforming a Group to a Polygon is not yet implemented.");
281
+ //RGroup polygonGroup = toPolygonGroup();
282
+ RPolygon result = new RPolygon();
283
+ for(int i=0;i<countElements();i++){
284
+ RPolygon currentPolygon = elements[i].toPolygon();
285
+ for(int j=0;j<currentPolygon.countContours();j++){
286
+ result.addContour(currentPolygon.contours[j]);
287
+ }
288
+ }
289
+ result.setStyle(this);
290
+ return result;
291
+ }
292
+
293
+ /**
294
+ * @invisible
295
+ */
296
+ public RShape toShape() throws RuntimeException{
297
+ //throw new RuntimeException("Transforming a Group to a Shape is not yet implemented.");
298
+ RShape result = new RShape();
299
+ for(int i=0;i<countElements();i++){
300
+ RShape currentShape = elements[i].toShape();
301
+ for(int j=0;j<currentShape.countPaths();j++){
302
+ result.addPath(currentShape.paths[j]);
303
+ }
304
+ }
305
+ result.setStyle(this);
306
+ return result;
307
+ }
308
+
309
+ /**
310
+ * Use this to return the points of the group. It returns the points as an array of RPoint.
311
+ * @eexample RGroup_getHandles
312
+ * @return RPoint[], the points returned in an array.
313
+ * */
314
+ public RPoint[] getHandles(){
315
+ int numElements = countElements();
316
+ if(numElements == 0){
317
+ return null;
318
+ }
319
+
320
+ RPoint[] result=null;
321
+ RPoint[] newresult=null;
322
+ for(int i=0;i<numElements;i++){
323
+ RPoint[] newPoints = elements[i].getHandles();
324
+ if(newPoints!=null){
325
+ if(result==null){
326
+ result = new RPoint[newPoints.length];
327
+ System.arraycopy(newPoints,0,result,0,newPoints.length);
328
+ }else{
329
+ newresult = new RPoint[result.length + newPoints.length];
330
+ System.arraycopy(result,0,newresult,0,result.length);
331
+ System.arraycopy(newPoints,0,newresult,result.length,newPoints.length);
332
+ result = newresult;
333
+ }
334
+ }
335
+ }
336
+ return result;
337
+ }
338
+
339
+ public RPoint getPoint(float t){
340
+ float[] indAndAdv = indAndAdvAt(t);
341
+ int indOfElement = (int)(indAndAdv[0]);
342
+ float advOfElement = indAndAdv[1];
343
+
344
+ return elements[indOfElement].getPoint(advOfElement);
345
+ }
346
+
347
+ /**
348
+ * Use this to return the points of the group. It returns the points as an array of RPoint.
349
+ * @eexample RGroup_getPoints
350
+ * @return RPoint[], the points returned in an array.
351
+ * */
352
+ public RPoint[] getPoints(){
353
+ int numElements = countElements();
354
+ if(numElements == 0){
355
+ return null;
356
+ }
357
+
358
+ RCommand.segmentAccOffset = RCommand.segmentOffset;
359
+ RPoint[] result=null;
360
+ RPoint[] newresult=null;
361
+ for(int i=0;i<numElements;i++){
362
+ RPoint[] newPoints = elements[i].getPoints();
363
+ if(newPoints!=null){
364
+ if(result==null){
365
+ result = new RPoint[newPoints.length];
366
+ System.arraycopy(newPoints,0,result,0,newPoints.length);
367
+ }else{
368
+ newresult = new RPoint[result.length + newPoints.length];
369
+ System.arraycopy(result,0,newresult,0,result.length);
370
+ System.arraycopy(newPoints,0,newresult,result.length,newPoints.length);
371
+ result = newresult;
372
+ }
373
+ }
374
+ }
375
+
376
+ return result;
377
+ }
378
+
379
+ public RPoint getTangent(float t){
380
+ float[] indAndAdv = indAndAdvAt(t);
381
+ int indOfElement = (int)(indAndAdv[0]);
382
+ float advOfElement = indAndAdv[1];
383
+
384
+ return elements[indOfElement].getTangent(advOfElement);
385
+ }
386
+
387
+ /**
388
+ * Use this to return the points of the group. It returns the points as an array of RPoint.
389
+ * @eexample RGroup_getPoints
390
+ * @return RPoint[], the points returned in an array.
391
+ * */
392
+ public RPoint[] getTangents(){
393
+ int numElements = countElements();
394
+ if(numElements == 0){
395
+ return null;
396
+ }
397
+
398
+ RPoint[] result=null;
399
+ RPoint[] newresult=null;
400
+ for(int i=0;i<numElements;i++){
401
+ RPoint[] newPoints = elements[i].getTangents();
402
+ if(newPoints!=null){
403
+ if(result==null){
404
+ result = new RPoint[newPoints.length];
405
+ System.arraycopy(newPoints,0,result,0,newPoints.length);
406
+ }else{
407
+ newresult = new RPoint[result.length + newPoints.length];
408
+ System.arraycopy(result,0,newresult,0,result.length);
409
+ System.arraycopy(newPoints,0,newresult,result.length,newPoints.length);
410
+ result = newresult;
411
+ }
412
+ }
413
+ }
414
+ return result;
415
+ }
416
+
417
+ /**
418
+ * Use this to return the points of each path of the group. It returns the points as an array of arrays of RPoint.
419
+ * @eexample RGroup_getPoints
420
+ * @return RPoint[], the points returned in an array.
421
+ * */
422
+ public RPoint[][] getPointsInPaths(){
423
+ int numElements = countElements();
424
+ if(numElements == 0){
425
+ return null;
426
+ }
427
+
428
+ RPoint[][] result=null;
429
+ RPoint[][] newresult=null;
430
+ for(int i=0;i<numElements;i++){
431
+ RPoint[][] newPointPaths = elements[i].getPointsInPaths();
432
+ if(newPointPaths != null){
433
+ if(result == null){
434
+ result = new RPoint[newPointPaths.length][];
435
+ System.arraycopy(newPointPaths,0,result,0,newPointPaths.length);
436
+ }else{
437
+ newresult = new RPoint[result.length + newPointPaths.length][];
438
+ System.arraycopy(result,0,newresult,0,result.length);
439
+ System.arraycopy(newPointPaths,0,newresult,result.length,newPointPaths.length);
440
+ result = newresult;
441
+ }
442
+ }
443
+ }
444
+ return result;
445
+ }
446
+
447
+ public RPoint[][] getHandlesInPaths(){
448
+ int numElements = countElements();
449
+ if(numElements == 0){
450
+ return null;
451
+ }
452
+
453
+ RPoint[][] result=null;
454
+ RPoint[][] newresult=null;
455
+ for(int i=0;i<numElements;i++){
456
+ RPoint[][] newHandlePaths = elements[i].getHandlesInPaths();
457
+ if(newHandlePaths != null){
458
+ if(result == null){
459
+ result = new RPoint[newHandlePaths.length][];
460
+ System.arraycopy(newHandlePaths,0,result,0,newHandlePaths.length);
461
+ }else{
462
+ newresult = new RPoint[result.length + newHandlePaths.length][];
463
+ System.arraycopy(result,0,newresult,0,result.length);
464
+ System.arraycopy(newHandlePaths,0,newresult,result.length,newHandlePaths.length);
465
+ result = newresult;
466
+ }
467
+ }
468
+ }
469
+ return result;
470
+ }
471
+
472
+ public RPoint[][] getTangentsInPaths(){
473
+ int numElements = countElements();
474
+ if(numElements == 0){
475
+ return null;
476
+ }
477
+
478
+ RPoint[][] result=null;
479
+ RPoint[][] newresult=null;
480
+ for(int i=0;i<numElements;i++){
481
+ RPoint[][] newTangentPaths = elements[i].getTangentsInPaths();
482
+ if(newTangentPaths != null){
483
+ if(result == null){
484
+ result = new RPoint[newTangentPaths.length][];
485
+ System.arraycopy(newTangentPaths,0,result,0,newTangentPaths.length);
486
+ }else{
487
+ newresult = new RPoint[result.length + newTangentPaths.length][];
488
+ System.arraycopy(result,0,newresult,0,result.length);
489
+ System.arraycopy(newTangentPaths,0,newresult,result.length,newTangentPaths.length);
490
+ result = newresult;
491
+ }
492
+ }
493
+ }
494
+ return result;
495
+ }
496
+
497
+ /**
498
+ * Use this to return a specific tangent on the curve. It returns true if the point passed as a parameter is inside the group.
499
+ * @param p the point for which to test containment..
500
+ * @return boolean, true if the point is in the path.
501
+ * */
502
+ public boolean contains(RPoint p){
503
+ float testx = p.x;
504
+ float testy = p.y;
505
+
506
+ // Test for containment in bounding box
507
+ RRectangle bbox = getBounds();
508
+ float xmin = bbox.getMinX();
509
+ float xmax = bbox.getMaxX();
510
+
511
+ float ymin = bbox.getMinY();
512
+ float ymax = bbox.getMaxY();
513
+
514
+ if( (testx < xmin) || (testx > xmax) || (testy < ymin) || (testy > ymax)){
515
+ return false;
516
+ }
517
+
518
+ // Test for containment in elements
519
+ boolean result = false;
520
+ for(int i = 0;i<countElements();i++){
521
+ result |= elements[i].contains(p);
522
+ }
523
+ return result;
524
+ }
525
+
526
+
527
+ /**
528
+ * Use this method to get the type of element this is.
529
+ * @eexample RPolygon_getType
530
+ * @return int, will allways return RGeomElem.POLYGON
531
+ */
532
+ public int getType(){
533
+ return type;
534
+ }
535
+
536
+ private float[] indAndAdvAt(float t){
537
+ int indOfElement = 0;
538
+ float[] lengthsCurves = getCurveLengths();
539
+ float lengthCurve = getCurveLength();
540
+
541
+ /* Calculate the amount of advancement t mapped to each command */
542
+ /* We use a simple algorithm where we give to each command the same amount of advancement */
543
+ /* A more useful way would be to give to each command an advancement proportional to the length of the command */
544
+
545
+ float accumulatedAdvancement = lengthsCurves[indOfElement] / lengthCurve;
546
+ float prevAccumulatedAdvancement = 0F;
547
+
548
+ /* Find in what command the advancement point is */
549
+ while(t > accumulatedAdvancement){
550
+ indOfElement++;
551
+ prevAccumulatedAdvancement = accumulatedAdvancement;
552
+ accumulatedAdvancement += (lengthsCurves[indOfElement] / lengthCurve);
553
+ }
554
+
555
+ float advOfElement = (t-prevAccumulatedAdvancement) / (lengthsCurves[indOfElement] / lengthCurve);
556
+
557
+ float[] indAndAdv = new float[2];
558
+
559
+ indAndAdv[0] = indOfElement;
560
+ indAndAdv[1] = advOfElement;
561
+
562
+ return indAndAdv;
563
+ }
564
+
565
+ public RGroup[] split(float t){
566
+ RGroup[] result = new RGroup[2];
567
+
568
+ if(t == 0.0F){
569
+ result[0] = new RGroup();
570
+ result[1] = new RGroup(this);
571
+ result[0].setStyle(this);
572
+ result[1].setStyle(this);
573
+
574
+ return result;
575
+ }
576
+
577
+ if(t == 1.0F){
578
+ result[0] = new RGroup(this);
579
+ result[1] = new RGroup();
580
+ result[0].setStyle(this);
581
+ result[1].setStyle(this);
582
+
583
+ return result;
584
+ }
585
+
586
+ result[0] = new RGroup();
587
+ result[1] = new RGroup();
588
+
589
+ float[] indAndAdv = indAndAdvAt(t);
590
+ int indOfElement = (int)(indAndAdv[0]);
591
+ float advOfElement = indAndAdv[1];
592
+
593
+ // Add the elements before the cut point
594
+ for(int i=0; i<indOfElement; i++){
595
+ switch(elements[i].getType()){
596
+ case RGeomElem.MESH:
597
+ result[0].addElement(new RMesh((RMesh)elements[i]));
598
+ break;
599
+
600
+ case RGeomElem.GROUP:
601
+ result[0].addElement(new RGroup((RGroup)elements[i]));
602
+ break;
603
+
604
+ case RGeomElem.POLYGON:
605
+ result[0].addElement(new RPolygon((RPolygon)elements[i]));
606
+ break;
607
+
608
+ case RGeomElem.SHAPE:
609
+ result[0].addElement(new RShape((RShape)elements[i]));
610
+ break;
611
+ }
612
+ }
613
+
614
+ // Add the cut point element cutted
615
+ RGeomElem element = this.elements[indOfElement];
616
+ switch(element.getType())
617
+ {
618
+ case RGeomElem.GROUP:
619
+ RGroup[] splittedGroups = ((RGroup)element).split(advOfElement);
620
+ if( splittedGroups != null ){
621
+ result[0].addElement(new RGroup(splittedGroups[0]));
622
+ result[1].addElement(new RGroup(splittedGroups[1]));
623
+ }
624
+ break;
625
+
626
+ case RGeomElem.SHAPE:
627
+ RShape[] splittedShapes = ((RShape)element).split(advOfElement);
628
+ if( splittedShapes != null ){
629
+ result[0].addElement(new RShape(splittedShapes[0]));
630
+ result[1].addElement(new RShape(splittedShapes[1]));
631
+ }
632
+ break;
633
+ }
634
+
635
+ // Add the elements after the cut point
636
+ for(int i=indOfElement+1; i<countElements(); i++){
637
+ switch(elements[i].getType()){
638
+ case RGeomElem.MESH:
639
+ result[1].addElement(new RMesh((RMesh)elements[i]));
640
+ break;
641
+
642
+ case RGeomElem.GROUP:
643
+ result[1].addElement(new RGroup((RGroup)elements[i]));
644
+ break;
645
+
646
+ case RGeomElem.POLYGON:
647
+ result[1].addElement(new RPolygon((RPolygon)elements[i]));
648
+ break;
649
+
650
+ case RGeomElem.SHAPE:
651
+ result[1].addElement(new RShape((RShape)elements[i]));
652
+ break;
653
+ }
654
+ }
655
+
656
+ result[0].setStyle(this);
657
+ result[1].setStyle(this);
658
+
659
+ return result;
660
+ }
661
+
662
+ public RGroup[] splitPaths(float t){
663
+ RGroup[] result = new RGroup[2];
664
+ result[0] = new RGroup();
665
+ result[1] = new RGroup();
666
+ for(int i = 0; i<this.countElements(); i++){
667
+ RGeomElem element = this.elements[i];
668
+
669
+ switch(element.getType())
670
+ {
671
+ case RGeomElem.GROUP:
672
+ RGroup[] splittedGroups = ((RGroup)element).splitPaths(t);
673
+ if( splittedGroups != null ){
674
+ result[0].addElement(splittedGroups[0]);
675
+ result[1].addElement(splittedGroups[1]);
676
+ }
677
+ break;
678
+
679
+ case RGeomElem.SHAPE:
680
+ RShape[] splittedShapes = ((RShape)element).splitPaths(t);
681
+ if( splittedShapes != null ){
682
+ result[0].addElement(splittedShapes[0]);
683
+ result[1].addElement(splittedShapes[1]);
684
+ }
685
+ break;
686
+ }
687
+ }
688
+ result[0].setStyle(this);
689
+ result[1].setStyle(this);
690
+
691
+ return result;
692
+ }
693
+
694
+ /**
695
+ * Use this to insert a split point into each command of the group.
696
+ * @eexample insertHandleInPaths
697
+ * @param t float, the parameter of advancement on the curve. t must have values between 0 and 1.
698
+ * */
699
+ public void insertHandleInPaths(float t){
700
+ if((t == 0F) || (t == 1F)){
701
+ return;
702
+ }
703
+
704
+ for(int i = 0; i<this.countElements(); i++){
705
+ RGeomElem element = this.elements[i];
706
+
707
+ switch(element.getType())
708
+ {
709
+ case RGeomElem.GROUP:
710
+ ((RGroup)element).insertHandleInPaths(t);
711
+ break;
712
+
713
+ case RGeomElem.SHAPE:
714
+ ((RShape)element).insertHandleInPaths(t);
715
+ break;
716
+ }
717
+ }
718
+
719
+ return;
720
+ }
721
+
722
+
723
+ protected void calculateCurveLengths(){
724
+ lenCurves = new float[countElements()];
725
+ lenCurve = 0F;
726
+ for(int i=0;i<countElements();i++){
727
+ lenCurves[i] = elements[i].getCurveLength();
728
+ lenCurve += lenCurves[i];
729
+ }
730
+ }
731
+
732
+
733
+ /**
734
+ * Use this method to adapt a group of of figures to a group.
735
+ * @eexample RGroup_adapt
736
+ * @param grp the path to which to adapt
737
+ */
738
+ public void adapt(RGroup grp, float wght, float lngthOffset) throws RuntimeException{
739
+ RRectangle c = this.getBounds();
740
+ float xmin = c.getMinX();
741
+ float xmax = c.getMaxX();
742
+ float ymax = c.getMaxY();
743
+
744
+ int numElements = this.countElements();
745
+
746
+ switch(RG.adaptorType){
747
+ case RG.BYPOINT:
748
+ for(int i=0;i<numElements;i++){
749
+ RGeomElem elem = this.elements[i];
750
+ RPoint[] ps = elem.getHandles();
751
+ if(ps != null){
752
+ for(int k=0;k<ps.length;k++){
753
+ float px = ps[k].x;
754
+ float py = ps[k].y;
755
+
756
+ float t = ((px-xmin)/(xmax-xmin) + lngthOffset ) % 1.001F;
757
+ float amp = (ymax-py);
758
+
759
+ RPoint tg = grp.getTangent(t);
760
+ RPoint p = grp.getPoint(t);
761
+ float angle = (float)Math.atan2(tg.y, tg.x) - (float)Math.PI/2F;
762
+
763
+ ps[k].x = p.x + wght*amp*(float)Math.cos(angle);
764
+ ps[k].y = p.y + wght*amp*(float)Math.sin(angle);
765
+ }
766
+ }
767
+ }
768
+ break;
769
+ case RG.BYELEMENTPOSITION:
770
+
771
+ for(int i=0;i<numElements;i++){
772
+ RGeomElem elem = this.elements[i];
773
+ RRectangle elemc = elem.getBounds();
774
+
775
+ float px = (elemc.bottomRight.x + elemc.topLeft.x) / 2F;
776
+ float py = (elemc.bottomRight.y - elemc.topLeft.y) / 2F;
777
+ float t = ((px-xmin)/(xmax-xmin) + lngthOffset ) % 1F;
778
+
779
+ RPoint tg = grp.getTangent(t);
780
+ RPoint p = grp.getPoint(t);
781
+ float angle = (float)Math.atan2(tg.y, tg.x);
782
+
783
+ RPoint pletter = new RPoint(px,py);
784
+ p.sub(pletter);
785
+
786
+ RMatrix mtx = new RMatrix();
787
+ mtx.translate(p);
788
+ mtx.rotate(angle,pletter);
789
+ mtx.scale(wght,pletter);
790
+
791
+ elem.transform(mtx);
792
+ }
793
+ break;
794
+
795
+ case RG.BYELEMENTINDEX:
796
+
797
+ for(int i=0;i<numElements;i++){
798
+ RGeomElem elem = this.elements[i];
799
+ RRectangle elemc = elem.getBounds();
800
+
801
+ float px = (elemc.bottomRight.x + elemc.topLeft.x) / 2F;
802
+ float py = (elemc.bottomRight.y - elemc.topLeft.y) / 2F;
803
+ float t = ((float)i/(float)numElements + lngthOffset ) % 1F;
804
+
805
+ RPoint tg = grp.getTangent(t);
806
+ RPoint p = grp.getPoint(t);
807
+ float angle = (float)Math.atan2(tg.y, tg.x);
808
+
809
+ RPoint pletter = new RPoint(px,py);
810
+ p.sub(pletter);
811
+
812
+ RMatrix mtx = new RMatrix();
813
+ mtx.translate(p);
814
+ mtx.rotate(angle,pletter);
815
+ mtx.scale(wght,pletter);
816
+
817
+ elem.transform(mtx);
818
+ }
819
+ break;
820
+
821
+ default:
822
+ throw new RuntimeException("Unknown adaptor type : "+RG.adaptorType+". The method RG.setAdaptor() only accepts RG.BYPOINT or RG.BYELEMENT as parameter values.");
823
+ }
824
+ }
825
+
826
+ public void adapt(RGroup grp) throws RuntimeException{
827
+ adapt(grp, RG.adaptorScale, RG.adaptorLengthOffset);
828
+ }
829
+
830
+ public void adapt(RShape shp){
831
+ RGroup grp = new RGroup();
832
+ grp.addElement(shp);
833
+ adapt(grp);
834
+ }
835
+
836
+ public void adapt(RShape shp, float wght, float lngthOffset){
837
+ RGroup grp = new RGroup();
838
+ grp.addElement(shp);
839
+ adapt(grp, wght, lngthOffset);
840
+ }
841
+
842
+
843
+ public void polygonize(){
844
+ RGroup grp = toPolygonGroup().toShapeGroup();
845
+ this.elements = grp.elements;
846
+ }
847
+
848
+ private void append(RGeomElem elem){
849
+ RGeomElem[] newelements;
850
+ if(elements==null){
851
+ newelements = new RGeomElem[1];
852
+ newelements[0] = elem;
853
+ }else{
854
+ newelements = new RGeomElem[this.elements.length+1];
855
+ System.arraycopy(this.elements,0,newelements,0,this.elements.length);
856
+ newelements[this.elements.length]=elem;
857
+ }
858
+ this.elements=newelements;
859
+ }
860
+
861
+ private void extract(int i) throws RuntimeException{
862
+ RGeomElem[] newelements;
863
+ if(elements==null){
864
+ throw new RuntimeException("The group is empty. No elements to remove.");
865
+ }else{
866
+ if(i<0){
867
+ throw new RuntimeException("Negative values for indexes are not valid.");
868
+ }
869
+ if(i>elements.length-1){
870
+ throw new RuntimeException("Index out of the bounds of the group. You are trying to erase an element with an index higher than the number of elements in the group.");
871
+ }
872
+ if(elements.length==1){
873
+ newelements = null;
874
+ }else if(i==0){
875
+ newelements = new RGeomElem[this.elements.length-1];
876
+ System.arraycopy(this.elements,1,newelements,0,this.elements.length-1);
877
+ }else if(i==elements.length-1){
878
+ newelements = new RGeomElem[this.elements.length-1];
879
+ System.arraycopy(this.elements,0,newelements,0,this.elements.length-1);
880
+ }else{
881
+ newelements = new RGeomElem[this.elements.length-1];
882
+ System.arraycopy(this.elements,0,newelements,0,i);
883
+ System.arraycopy(this.elements,i+1,newelements,i,this.elements.length-i-1);
884
+ }
885
+ }
886
+ this.elements=newelements;
887
+ }
888
+ }