]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.g2d/src/org/simantics/g2d/utils/PathUtils2.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.g2d / src / org / simantics / g2d / utils / PathUtils2.java
1 /*******************************************************************************\r
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
3  * in Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.g2d.utils;\r
13 \r
14 import java.awt.Shape;\r
15 import java.awt.geom.CubicCurve2D;\r
16 import java.awt.geom.Line2D;\r
17 import java.awt.geom.Path2D;\r
18 import java.awt.geom.PathIterator;\r
19 import java.awt.geom.Point2D;\r
20 import java.awt.geom.QuadCurve2D;\r
21 import java.util.ArrayList;\r
22 import java.util.Collection;\r
23 import java.util.Iterator;\r
24 import java.util.List;\r
25 \r
26 /**\r
27  * Path Utils.\r
28  * <p>\r
29  * A line segment (linear, quadratic or cubic bezier) is described\r
30  * with a double array. The length of the array describes its degree (4,6,8).\r
31  * The first 2 elements define start point and last 2 the end point.\r
32  * Points in the middle are bezier control points.\r
33  * \r
34  * @See {@link GeometryUtils} for more geometry related utilities\r
35  * @author Toni Kalajainen\r
36  */\r
37 public class PathUtils2 {\r
38 \r
39         /**\r
40          * Get tangent of an bezier\r
41          * @param lineSegment bezier of n degrees\r
42          * @param degree 1..3 \r
43          * @param t 0..1\r
44          * @return unit vector\r
45          */\r
46         public static Point2D getLineTangent(Shape line, double t, Point2D pt)\r
47         {\r
48                 double x=0, y=0;\r
49                 if (line instanceof Line2D)\r
50                 {\r
51                         Line2D l = (Line2D) line;\r
52                         x = l.getX1() - l.getX2();\r
53                         y = l.getY1() - l.getY2();\r
54                 } else if (line instanceof QuadCurve2D) {\r
55                         QuadCurve2D l = (QuadCurve2D) line;\r
56                         double p0x = l.getX1();\r
57                         double p0y = l.getY1();\r
58                         double p1x = l.getCtrlX();\r
59                         double p1y = l.getCtrlY();\r
60                         double p2x = l.getX2();\r
61                         double p2y = l.getY2();                 \r
62                         x = 2*t*(p0x - 2*p1x + p2x) + 2*(-p0x + p1x);\r
63                         y = 2*t*(p0y - 2*p1y + p2y) + 2*(-p0y + p1y);\r
64                         \r
65                 } else if (line instanceof CubicCurve2D) {\r
66                         CubicCurve2D l = (CubicCurve2D) line;\r
67                         double p0x = l.getX1();\r
68                         double p0y = l.getY1();\r
69                         double p1x = l.getCtrlX1();\r
70                         double p1y = l.getCtrlY1();\r
71                         double p2x = l.getCtrlX2();\r
72                         double p2y = l.getCtrlY2();\r
73                         double p3x = l.getX2();\r
74                         double p3y = l.getY2();                 \r
75                         x = 3*(1-t)*(1-t)*(p1x-p2x) + 3*(p2x-p1x)*2*t*(1-t) + 3*(p3x-p0x)*t*t;\r
76                         y = 3*(1-t)*(1-t)*(p1y-p0y) + 3*(p2y-p1y)*2*t*(1-t) + 3*(p3y-p2y)*t*t;\r
77                 } else throw new IllegalArgumentException();\r
78                 \r
79                 return new Point2D.Double(x, y);\r
80         }\r
81         \r
82         /**\r
83          * \r
84          * @param lineSegment\r
85          * @param t 0..1\r
86          * @return\r
87          */\r
88         public static Point2D getLinePos(Shape line, double t, Point2D pt)\r
89         {               \r
90                 assert(line!=null);\r
91                 double x=0, y=0;\r
92                 if (pt==null) pt = new Point2D.Double();\r
93                 \r
94                 if (line instanceof Line2D) {\r
95                         Line2D l = (Line2D) line;\r
96                         double p0x = l.getX1();\r
97                         double p0y = l.getY1();\r
98                         double p1x = l.getX2();\r
99                         double p1y = l.getY2();\r
100                         \r
101                         x = p0x*(1-t) + t*p1x;\r
102                         y = p0y*(1-t) + t*p1y;\r
103                 } else \r
104                 if (line instanceof QuadCurve2D) {\r
105                         QuadCurve2D l = (QuadCurve2D) line;\r
106                         double p0x = l.getX1();\r
107                         double p0y = l.getY1();\r
108                         double p1x = l.getCtrlX();\r
109                         double p1y = l.getCtrlY();\r
110                         double p2x = l.getX2();\r
111                         double p2y = l.getY2();                 \r
112                         \r
113                         double c2x = p0x-2*p1x+p2x;\r
114                         double c2y = p0y-2*p1y+p2y;\r
115                         \r
116                         double c1x = -2*p0x+2*p1x;\r
117                         double c1y = -2*p0y+2*p1y;\r
118                         \r
119                         double c0x = p0x;\r
120                         double c0y = p0y;\r
121                         \r
122                         x = t*t*c2x+t*c1x+c0x;\r
123                         y = t*t*c2y+t*c1y+c0y;\r
124                 } else if (line instanceof CubicCurve2D) {\r
125                         CubicCurve2D l = (CubicCurve2D) line;\r
126                         double p0x = l.getX1();\r
127                         double p0y = l.getY1();\r
128                         double p1x = l.getCtrlX1();\r
129                         double p1y = l.getCtrlY1();\r
130                         double p2x = l.getCtrlX2();\r
131                         double p2y = l.getCtrlY2();\r
132                         double p3x = l.getX2();\r
133                         double p3y = l.getY2();                 \r
134 \r
135                         x = (1-t)*(1-t)*(1-t)*p0x + 3*t*(1-t)*(1-t)*p1x + 3*t*t*(1-t)*p2x + t*t*t*p3x;\r
136                         y = (1-t)*(1-t)*(1-t)*p0y + 3*t*(1-t)*(1-t)*p1y + 3*t*t*(1-t)*p2y + t*t*t*p3y;\r
137                 } else throw new IllegalArgumentException();\r
138                 pt.setLocation(x, y);\r
139                 \r
140                 return pt;\r
141         }\r
142         \r
143         public static double getLineLength(Shape line)\r
144         {\r
145                 if (line instanceof Line2D) {\r
146                         Line2D l = (Line2D) line;\r
147                         double dx = l.getX2() - l.getX1();\r
148                         double dy = l.getY2() - l.getY1();\r
149                         return Math.sqrt(dx*dx+dy*dy);\r
150                 }\r
151                 \r
152                 // Quick'n'dirty approximation \r
153                 // TODO Replace with accurate value\r
154                 double result = 0;\r
155                 Point2D prevPos = getLinePos(line, 0.0, null); \r
156                 for (int i=0; i<10; i++)\r
157                 {\r
158                         double t = (double)(i+1)/10;\r
159                         Point2D pos = getLinePos(line, t, null);\r
160                         result += pos.distance(prevPos);\r
161                         prevPos.setLocation(pos);\r
162                 }\r
163                 return result;\r
164         }\r
165         \r
166         public static int getLineDegree(Shape line)\r
167         {\r
168                 if (line instanceof Line2D) return 1;\r
169                 if (line instanceof QuadCurve2D) return 2;\r
170                 if (line instanceof CubicCurve2D) return 3;\r
171                 throw new IllegalArgumentException(line+" is not a shape");\r
172         }\r
173         \r
174         \r
175         public static double[] toArray(Shape line)\r
176         {\r
177                 if (line instanceof Line2D) {\r
178                         Line2D l = (Line2D) line;\r
179                         return new double[] {l.getX1(), l.getY1(), l.getX2(), l.getY2()};\r
180                 }\r
181                 if (line instanceof QuadCurve2D) {\r
182                         QuadCurve2D l = (QuadCurve2D) line;\r
183                         return new double[] {l.getX1(), l.getY1(), l.getCtrlX(), l.getCtrlY(), l.getX2(), l.getY2()};\r
184                 }\r
185                 if (line instanceof CubicCurve2D) {\r
186                         CubicCurve2D l = (CubicCurve2D) line;\r
187                         return new double[] {l.getX1(), l.getY1(), l.getCtrlX1(), l.getCtrlY1(), l.getCtrlX2(), l.getCtrlY2(), l.getX2(), l.getY2()};                   \r
188                 }\r
189                 throw new IllegalArgumentException(line+" is not a shape");             \r
190         }\r
191         \r
192         public static Shape toShape(double dada[])\r
193         {\r
194                 if (dada.length==4) \r
195                         return new Line2D.Double(dada[0], dada[1], dada[2], dada[3]);\r
196                 if (dada.length==6) \r
197                         return new QuadCurve2D.Double(dada[0], dada[1], dada[2], dada[3], dada[4], dada[5]);\r
198                 if (dada.length==8) \r
199                         return new CubicCurve2D.Double(dada[0], dada[1], dada[2], dada[3], dada[4], dada[5], dada[6], dada[7]);\r
200                 throw new IllegalArgumentException();\r
201         }\r
202 \r
203         public static void interpolatePaths(List<Shape> l1, List<Shape> l2, double t, Collection<Shape> result)\r
204         {\r
205                 if (l1.size()>l2.size()) {\r
206                         List<Shape> l_ = l1;\r
207                         l1 = l2;\r
208                         l2 = l_;\r
209                         t = 1-t;\r
210                 }\r
211                 \r
212                 int div = l2.size() / l1.size();\r
213                 int mod = l2.size() % l1.size();\r
214                 \r
215                 int rightIndex = 0;\r
216                 for (int i=0; i<l1.size(); i++) {\r
217                         int rightCounterParts = i<l1.size()-1 ? (i<mod?div+1:div) : div; \r
218                         int leftIndex = i;\r
219                         Shape leftShape = l1.get(leftIndex); \r
220                         for (int j=0; j<rightCounterParts; j++)\r
221                         {\r
222                                 Shape rightShape = l2.get(rightIndex++);\r
223                                 double inv = 1/(double)rightCounterParts;\r
224                                 double t0  = j*inv;\r
225                                 double t1  = (j+1)*inv;\r
226                                 Shape leftShapePart  = subdiv(leftShape, t0, t1);                               \r
227                                 Shape intpShape = interpolateLine(leftShapePart, rightShape, t);\r
228                                 result.add( intpShape );\r
229                         }\r
230                 }\r
231         }\r
232         \r
233         /**\r
234          * Interpolate two paths\r
235          * @param path1\r
236          * @param path2\r
237          * @param t phase 0..1, 0==path1, 1==path2\r
238          * @return\r
239          */\r
240         public static Path2D interpolatePaths(PathIterator path1, PathIterator path2, double t)\r
241         {\r
242                 ArrayList<Shape> l1 = new ArrayList<Shape>();\r
243                 ArrayList<Shape> l2 = new ArrayList<Shape>(); \r
244                 toShapes(path1, l1);\r
245                 toShapes(path2, l2);\r
246                 ArrayList<Shape> result = new ArrayList<Shape>();\r
247                 interpolatePaths(l1, l2, t, result);\r
248                 Path2D p = new Path2D.Double();\r
249                 appedToPath(p, result);\r
250                 return p;\r
251         }\r
252 \r
253         public static Path2D interpolatePaths(Path2D path1, Path2D path2, double t)\r
254         {\r
255                 return interpolatePaths(path1.getPathIterator(null), path2.getPathIterator(null), t);\r
256         }\r
257         \r
258         public static Shape interpolateLine(Shape l1, Shape l2, double t)\r
259         {\r
260                 assert(t>=0 && t<=1);\r
261                 if (t==0) return l1;\r
262                 if (t==1) return l2;\r
263                 \r
264                 double[] a1 = toArray(l1);\r
265                 double[] a2 = toArray(l2);\r
266                 double[] res = PathUtils.interpolateLineSegment(a1, a2, t);\r
267                 return toShape(res);\r
268         }\r
269         \r
270         public static void toShapes(PathIterator pi, Collection<Shape> result)\r
271         {\r
272                 Iterator<Shape> i = toShapeIterator(pi);\r
273                 while (i.hasNext()) {\r
274                         Shape segment = i.next();\r
275                         result.add(segment);\r
276                 }\r
277         }\r
278         \r
279         /**\r
280          * Returns an iterator that splits path into line shapes\r
281          * @param pi path iterator\r
282          * @return line segment iterator\r
283          */\r
284         public static Iterator<Shape> toShapeIterator(final PathIterator pi)\r
285         {\r
286                 return new PathIteratorToShapeIterator(pi);\r
287         }\r
288         \r
289         private static class PathIteratorToShapeIterator implements Iterator<Shape>\r
290         {\r
291                 final PathIterator pi;\r
292                 double  lineTo[] = new double[6];\r
293                 double  startPos[] = new double[2];\r
294                 double  from[] = new double[2];\r
295                 int             degree = 0;\r
296                 PathIteratorToShapeIterator(PathIterator pi) {\r
297                         this.pi = pi;\r
298                         while(!pi.isDone()) {\r
299                                 int type = pi.currentSegment(lineTo);\r
300                                 pi.next();\r
301                                 if (type == PathIterator.SEG_MOVETO) {\r
302                                         startPos[0] = from[0] = lineTo[0];\r
303                                         startPos[1] = from[1] = lineTo[1];\r
304                                 }\r
305                                 if (type == PathIterator.SEG_CLOSE) {\r
306                                         type = PathIterator.SEG_LINETO;\r
307                                         lineTo[0] = startPos[0];\r
308                                         lineTo[1] = startPos[1];\r
309                                 }\r
310                                 if (type>=PathIterator.SEG_LINETO && type<=PathIterator.SEG_CUBICTO)\r
311                                 {\r
312                                         degree = type;\r
313                                         // from == xx\r
314                                         break;\r
315                                 }\r
316                         }\r
317                 }               \r
318                 @Override\r
319                 public boolean hasNext() {\r
320                         return degree>0;\r
321                 }\r
322                 @Override\r
323                 public Shape next() {\r
324                         if (degree==0) return null;\r
325                         Shape res = null;\r
326                         if (degree==1) \r
327                                 res = new Line2D.Double(from[0], from[1], lineTo[0], lineTo[1]);\r
328                         else if (degree==2) \r
329                                 res = new QuadCurve2D.Double(from[0], from[1], lineTo[0], lineTo[1], lineTo[2], lineTo[3]);\r
330                         else if (degree==3) \r
331                                 res = new CubicCurve2D.Double(from[0], from[1], lineTo[0], lineTo[1], lineTo[2], lineTo[3], lineTo[4], lineTo[5]);\r
332                         else throw new IllegalArgumentException();\r
333                         // traverse path iterator until end or until next segment is known\r
334                         degree = 0;\r
335                         from[0] = lineTo[0];\r
336                         from[1] = lineTo[1];\r
337                         while(!pi.isDone()) {\r
338                                 int type = pi.currentSegment(lineTo);\r
339                                 pi.next();\r
340                                 if (type == PathIterator.SEG_MOVETO) {\r
341                                         startPos[0] = from[0] = lineTo[0];\r
342                                         startPos[1] = from[1] = lineTo[1];\r
343                                 }\r
344                                 if (type == PathIterator.SEG_CLOSE) {\r
345                                         type = PathIterator.SEG_LINETO;\r
346                                         lineTo[0] = startPos[0];\r
347                                         lineTo[1] = startPos[1];\r
348                                 }\r
349                                 if (type>=PathIterator.SEG_LINETO && type<=PathIterator.SEG_CUBICTO)\r
350                                 {\r
351                                         degree = type;                                  \r
352                                         break;\r
353                                 }\r
354                         }\r
355                         return res;\r
356                 }\r
357                 @Override\r
358                 public void remove() {\r
359                         throw new UnsupportedOperationException();\r
360                 }\r
361         }\r
362 \r
363         \r
364         \r
365         \r
366         public static Shape subdiv_takeLeft(Shape line, double t)\r
367         {\r
368                 if (t==1) return line;\r
369                 if (line instanceof Line2D) {\r
370                         Line2D l = (Line2D) line;\r
371                         double p0x = l.getX1();\r
372                         double p0y = l.getY1();\r
373                         double p1x = l.getX2();\r
374                         double p1y = l.getY2();                 \r
375                         double p1x_  = p0x*(1-t) + p1x*t;\r
376                         double p1y_  = p0y*(1-t) + p1y*t;\r
377                         \r
378                         return new Line2D.Double( p0x, p0y, p1x_, p1y_ );\r
379                 }\r
380                 \r
381                 if (line instanceof QuadCurve2D) {\r
382                         QuadCurve2D l = (QuadCurve2D) line;\r
383                         double p0x = l.getX1();\r
384                         double p0y = l.getY1();\r
385                         double p1x = l.getCtrlX();\r
386                         double p1y = l.getCtrlY();                      \r
387                         double p2x = l.getX2();\r
388                         double p2y = l.getY2();                 \r
389                         double p1x_  = p0x*(1-t) + p1x*t;\r
390                         double p1y_  = p0y*(1-t) + p1y*t;\r
391                 \r
392                         double q0x = p0x*(1-t) + p1x*t;\r
393                         double q0y = p0y*(1-t) + p1y*t;\r
394 \r
395                         double q1x = p1x*(1-t) + p2x*t;\r
396                         double q1y = p1y*(1-t) + p2y*t;\r
397                         \r
398                         double p2x_ = q0x*(1-t) + q1x*t;\r
399                         double p2y_ = q0y*(1-t) + q1y*t;\r
400                                                                 \r
401                         return new QuadCurve2D.Double( p0x, p0y, p1x_, p1y_, p2x_, p2y_ );                      \r
402                 }\r
403 \r
404                 if (line instanceof CubicCurve2D) {\r
405                         CubicCurve2D l = (CubicCurve2D) line;\r
406                         double p0x = l.getX1();\r
407                         double p0y = l.getY1();\r
408                         double p1x = l.getCtrlX1();\r
409                         double p1y = l.getCtrlY1();                     \r
410                         double p2x = l.getCtrlX2();\r
411                         double p2y = l.getCtrlY2();                     \r
412                         double p3x = l.getX2();\r
413                         double p3y = l.getY2();                 \r
414                         double p1x_  = p0x*(1-t) + p1x*t;\r
415                         double p1y_  = p0y*(1-t) + p1y*t;\r
416                 \r
417                         double q0x = p0x*(1-t) + p1x*t;\r
418                         double q0y = p0y*(1-t) + p1y*t;\r
419 \r
420                         double q1x = p1x*(1-t) + p2x*t;\r
421                         double q1y = p1y*(1-t) + p2y*t;\r
422                         \r
423                         double p2x_ = q0x*(1-t) + q1x*t;\r
424                         double p2y_ = q0y*(1-t) + q1y*t;\r
425                         \r
426                         double q2x = p2x*(1-t) + p3x*t;\r
427                         double q2y = p2y*(1-t) + p3y*t;\r
428 \r
429                         double r0x = q0x*(1-t) + q1x*t;\r
430                         double r0y = q0y*(1-t) + q1y*t;\r
431                                 \r
432                         double r1x = q1x*(1-t) + q2x*t;\r
433                         double r1y = q1y*(1-t) + q2y*t;\r
434                                 \r
435                         double p3x_  = r0x*(1-t) + r1x*t;\r
436                         double p3y_  = r0y*(1-t) + r1y*t;                       \r
437                         \r
438                         return new CubicCurve2D.Double(p0x, p0y, p1x_, p1y_, p2x_, p2y_, p3x_, p3y_);                   \r
439                 }\r
440 \r
441                 throw new IllegalArgumentException();\r
442         }\r
443         \r
444         public static Shape subdiv_takeRight(Shape line, double t)\r
445         {\r
446                 if (t==0) return line;\r
447                 if (line instanceof Line2D) {\r
448                         Line2D l = (Line2D) line;\r
449                         double p0x = l.getX1();\r
450                         double p0y = l.getY1();\r
451                         double p1x = l.getX2();\r
452                         double p1y = l.getY2();                 \r
453                         double p0x_  = p0x*(1-t) + p1x*t;\r
454                         double p0y_  = p0y*(1-t) + p1y*t;\r
455                         \r
456                         return new Line2D.Double( p0x_, p0y_, p1x, p1y );\r
457                 }\r
458                 \r
459                 if (line instanceof QuadCurve2D) {\r
460                         QuadCurve2D l = (QuadCurve2D) line;             \r
461                         double p0x = l.getX1();\r
462                         double p0y = l.getY1();\r
463                         double p1x = l.getCtrlX();\r
464                         double p1y = l.getCtrlY();                      \r
465                         double p2x = l.getX2();\r
466                         double p2y = l.getY2();                 \r
467 \r
468                         double q0x = p0x*(1-t) + p1x*t;\r
469                         double q0y = p0y*(1-t) + p1y*t;\r
470 \r
471                         double q1x = p1x*(1-t) + p2x*t;\r
472                         double q1y = p1y*(1-t) + p2y*t;\r
473                         \r
474                         double p2x_ = q0x*(1-t) + q1x*t;\r
475                         double p2y_ = q0y*(1-t) + q1y*t;\r
476                         \r
477                         return new QuadCurve2D.Double( p2x_, p2y_, q1x, q1y, p2x, p2y );                        \r
478                 }               \r
479 \r
480                 \r
481                 if (line instanceof CubicCurve2D) {\r
482                         CubicCurve2D l = (CubicCurve2D) line;\r
483                         \r
484                         double p0x = l.getX1();\r
485                         double p0y = l.getY1();\r
486                         double p1x = l.getCtrlX1();\r
487                         double p1y = l.getCtrlY1();                     \r
488                         double p2x = l.getCtrlX2();\r
489                         double p2y = l.getCtrlY2();                     \r
490                         double p3x = l.getX2();\r
491                         double p3y = l.getY2();\r
492                         \r
493                         double q0x = p0x*(1-t) + p1x*t;\r
494                         double q0y = p0y*(1-t) + p1y*t;\r
495 \r
496                         double q1x = p1x*(1-t) + p2x*t;\r
497                         double q1y = p1y*(1-t) + p2y*t;\r
498                         \r
499                         double q2x = p2x*(1-t) + p3x*t;\r
500                         double q2y = p2y*(1-t) + p3y*t;\r
501 \r
502                         double r0x = q0x*(1-t) + q1x*t;\r
503                         double r0y = q0y*(1-t) + q1y*t;\r
504                                 \r
505                         double r1x = q1x*(1-t) + q2x*t;\r
506                         double r1y = q1y*(1-t) + q2y*t;\r
507                                 \r
508                         double p3x_  = r0x*(1-t) + r1x*t;\r
509                         double p3y_  = r0y*(1-t) + r1y*t;                       \r
510                         \r
511                         return new CubicCurve2D.Double( p3x_, p3y_, r1x, r1y, q2x, q2y, p3x, p3y );                     \r
512                 }                               \r
513                 \r
514                 return null;\r
515         }\r
516         \r
517 \r
518 \r
519         /**\r
520          * Crops line segment into a smaller line segment\r
521          * @param line line segment\r
522          * @param t0 begin t\r
523          * @param t1 end t\r
524          * @return cropped line segment\r
525          */\r
526         public static Shape subdiv(Shape line, double t0, double t1)\r
527         {\r
528                 if (t0==0 && t1==1) return line;\r
529                 Shape temp = subdiv_takeLeft(line, t1);\r
530                 return subdiv_takeRight(temp, t0/t1);\r
531         }\r
532         \r
533         public static void appedToPath(Path2D p, Shape ... shapes)\r
534         {\r
535                 for (Shape s : shapes)\r
536                 {\r
537                         Point2D cur = p.getCurrentPoint();\r
538                         if (s instanceof Line2D) {\r
539                                 Line2D l = (Line2D) s;\r
540                                 if (cur.getX()!=l.getX1() || cur.getY()!=l.getY1())\r
541                                         p.moveTo(l.getX1(), l.getY1());\r
542                                 p.lineTo(l.getX2(), l.getY2());\r
543                         } else if (s instanceof QuadCurve2D) {\r
544                                 QuadCurve2D l = (QuadCurve2D) s;\r
545                                 if (cur.getX()!=l.getX1() || cur.getY()!=l.getY1())\r
546                                         p.moveTo(l.getX1(), l.getY1());\r
547                                 p.quadTo(l.getCtrlX(), l.getCtrlY(), l.getX2(), l.getY2());\r
548                         } else if (s instanceof CubicCurve2D) {\r
549                                 CubicCurve2D l = (CubicCurve2D) s;\r
550                                 if (cur.getX()!=l.getX1() || cur.getY()!=l.getY1())\r
551                                         p.moveTo(l.getX1(), l.getY1());\r
552                                 p.curveTo(l.getCtrlX1(), l.getCtrlY1(), l.getCtrlX2(), l.getCtrlY2(), l.getX2(), l.getY2());\r
553                         } throw new IllegalArgumentException();\r
554                 }\r
555         }\r
556         public static void appedToPath(Path2D p, Collection<Shape> shapes)\r
557         {\r
558                 for (Shape s : shapes)\r
559                 {\r
560                         Point2D cur = p.getCurrentPoint();\r
561                         if (s instanceof Line2D) {\r
562                                 Line2D l = (Line2D) s;\r
563                                 if (cur==null || cur.getX()!=l.getX1() || cur.getY()!=l.getY1())\r
564                                         p.moveTo(l.getX1(), l.getY1());\r
565                                 p.lineTo(l.getX2(), l.getY2());\r
566                         } else if (s instanceof QuadCurve2D) {\r
567                                 QuadCurve2D l = (QuadCurve2D) s;\r
568                                 if (cur==null || cur.getX()!=l.getX1() || cur.getY()!=l.getY1())\r
569                                         p.moveTo(l.getX1(), l.getY1());\r
570                                 p.quadTo(l.getCtrlX(), l.getCtrlY(), l.getX2(), l.getY2());\r
571                         } else if (s instanceof CubicCurve2D) {\r
572                                 CubicCurve2D l = (CubicCurve2D) s;\r
573                                 if (cur==null || cur.getX()!=l.getX1() || cur.getY()!=l.getY1())\r
574                                         p.moveTo(l.getX1(), l.getY1());\r
575                                 p.curveTo(l.getCtrlX1(), l.getCtrlY1(), l.getCtrlX2(), l.getCtrlY2(), l.getX2(), l.getY2());\r
576                         } else throw new IllegalArgumentException();\r
577                 }\r
578         }\r
579         \r
580 \r
581         public static void main(String[] args) {\r
582                 \r
583         }\r
584                         \r
585         \r
586 }\r