X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.g2d%2Fsrc%2Forg%2Fsimantics%2Fg2d%2Futils%2FPathUtils2.java;h=6a418a39c403cf191618632287a5ca0707ceeb9b;hb=197f65594b46aaa087ac4d9bb6cb5514376377ca;hp=2dfd0707c0666330d7cc5f00a1c3c951948991ef;hpb=969bd23cab98a79ca9101af33334000879fb60c5;p=simantics%2Fplatform.git
diff --git a/bundles/org.simantics.g2d/src/org/simantics/g2d/utils/PathUtils2.java b/bundles/org.simantics.g2d/src/org/simantics/g2d/utils/PathUtils2.java
index 2dfd0707c..6a418a39c 100644
--- a/bundles/org.simantics.g2d/src/org/simantics/g2d/utils/PathUtils2.java
+++ b/bundles/org.simantics.g2d/src/org/simantics/g2d/utils/PathUtils2.java
@@ -1,586 +1,586 @@
-/*******************************************************************************
- * Copyright (c) 2007, 2010 Association for Decentralized Information Management
- * in Industry THTH ry.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * VTT Technical Research Centre of Finland - initial API and implementation
- *******************************************************************************/
-package org.simantics.g2d.utils;
-
-import java.awt.Shape;
-import java.awt.geom.CubicCurve2D;
-import java.awt.geom.Line2D;
-import java.awt.geom.Path2D;
-import java.awt.geom.PathIterator;
-import java.awt.geom.Point2D;
-import java.awt.geom.QuadCurve2D;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-
-/**
- * Path Utils.
- *
- * A line segment (linear, quadratic or cubic bezier) is described
- * with a double array. The length of the array describes its degree (4,6,8).
- * The first 2 elements define start point and last 2 the end point.
- * Points in the middle are bezier control points.
- *
- * @See {@link GeometryUtils} for more geometry related utilities
- * @author Toni Kalajainen
- */
-public class PathUtils2 {
-
- /**
- * Get tangent of an bezier
- * @param lineSegment bezier of n degrees
- * @param degree 1..3
- * @param t 0..1
- * @return unit vector
- */
- public static Point2D getLineTangent(Shape line, double t, Point2D pt)
- {
- double x=0, y=0;
- if (line instanceof Line2D)
- {
- Line2D l = (Line2D) line;
- x = l.getX1() - l.getX2();
- y = l.getY1() - l.getY2();
- } else if (line instanceof QuadCurve2D) {
- QuadCurve2D l = (QuadCurve2D) line;
- double p0x = l.getX1();
- double p0y = l.getY1();
- double p1x = l.getCtrlX();
- double p1y = l.getCtrlY();
- double p2x = l.getX2();
- double p2y = l.getY2();
- x = 2*t*(p0x - 2*p1x + p2x) + 2*(-p0x + p1x);
- y = 2*t*(p0y - 2*p1y + p2y) + 2*(-p0y + p1y);
-
- } else if (line instanceof CubicCurve2D) {
- CubicCurve2D l = (CubicCurve2D) line;
- double p0x = l.getX1();
- double p0y = l.getY1();
- double p1x = l.getCtrlX1();
- double p1y = l.getCtrlY1();
- double p2x = l.getCtrlX2();
- double p2y = l.getCtrlY2();
- double p3x = l.getX2();
- double p3y = l.getY2();
- x = 3*(1-t)*(1-t)*(p1x-p2x) + 3*(p2x-p1x)*2*t*(1-t) + 3*(p3x-p0x)*t*t;
- y = 3*(1-t)*(1-t)*(p1y-p0y) + 3*(p2y-p1y)*2*t*(1-t) + 3*(p3y-p2y)*t*t;
- } else throw new IllegalArgumentException();
-
- return new Point2D.Double(x, y);
- }
-
- /**
- *
- * @param lineSegment
- * @param t 0..1
- * @return
- */
- public static Point2D getLinePos(Shape line, double t, Point2D pt)
- {
- assert(line!=null);
- double x=0, y=0;
- if (pt==null) pt = new Point2D.Double();
-
- if (line instanceof Line2D) {
- Line2D l = (Line2D) line;
- double p0x = l.getX1();
- double p0y = l.getY1();
- double p1x = l.getX2();
- double p1y = l.getY2();
-
- x = p0x*(1-t) + t*p1x;
- y = p0y*(1-t) + t*p1y;
- } else
- if (line instanceof QuadCurve2D) {
- QuadCurve2D l = (QuadCurve2D) line;
- double p0x = l.getX1();
- double p0y = l.getY1();
- double p1x = l.getCtrlX();
- double p1y = l.getCtrlY();
- double p2x = l.getX2();
- double p2y = l.getY2();
-
- double c2x = p0x-2*p1x+p2x;
- double c2y = p0y-2*p1y+p2y;
-
- double c1x = -2*p0x+2*p1x;
- double c1y = -2*p0y+2*p1y;
-
- double c0x = p0x;
- double c0y = p0y;
-
- x = t*t*c2x+t*c1x+c0x;
- y = t*t*c2y+t*c1y+c0y;
- } else if (line instanceof CubicCurve2D) {
- CubicCurve2D l = (CubicCurve2D) line;
- double p0x = l.getX1();
- double p0y = l.getY1();
- double p1x = l.getCtrlX1();
- double p1y = l.getCtrlY1();
- double p2x = l.getCtrlX2();
- double p2y = l.getCtrlY2();
- double p3x = l.getX2();
- double p3y = l.getY2();
-
- 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;
- 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;
- } else throw new IllegalArgumentException();
- pt.setLocation(x, y);
-
- return pt;
- }
-
- public static double getLineLength(Shape line)
- {
- if (line instanceof Line2D) {
- Line2D l = (Line2D) line;
- double dx = l.getX2() - l.getX1();
- double dy = l.getY2() - l.getY1();
- return Math.sqrt(dx*dx+dy*dy);
- }
-
- // Quick'n'dirty approximation
- // TODO Replace with accurate value
- double result = 0;
- Point2D prevPos = getLinePos(line, 0.0, null);
- for (int i=0; i<10; i++)
- {
- double t = (double)(i+1)/10;
- Point2D pos = getLinePos(line, t, null);
- result += pos.distance(prevPos);
- prevPos.setLocation(pos);
- }
- return result;
- }
-
- public static int getLineDegree(Shape line)
- {
- if (line instanceof Line2D) return 1;
- if (line instanceof QuadCurve2D) return 2;
- if (line instanceof CubicCurve2D) return 3;
- throw new IllegalArgumentException(line+" is not a shape");
- }
-
-
- public static double[] toArray(Shape line)
- {
- if (line instanceof Line2D) {
- Line2D l = (Line2D) line;
- return new double[] {l.getX1(), l.getY1(), l.getX2(), l.getY2()};
- }
- if (line instanceof QuadCurve2D) {
- QuadCurve2D l = (QuadCurve2D) line;
- return new double[] {l.getX1(), l.getY1(), l.getCtrlX(), l.getCtrlY(), l.getX2(), l.getY2()};
- }
- if (line instanceof CubicCurve2D) {
- CubicCurve2D l = (CubicCurve2D) line;
- return new double[] {l.getX1(), l.getY1(), l.getCtrlX1(), l.getCtrlY1(), l.getCtrlX2(), l.getCtrlY2(), l.getX2(), l.getY2()};
- }
- throw new IllegalArgumentException(line+" is not a shape");
- }
-
- public static Shape toShape(double dada[])
- {
- if (dada.length==4)
- return new Line2D.Double(dada[0], dada[1], dada[2], dada[3]);
- if (dada.length==6)
- return new QuadCurve2D.Double(dada[0], dada[1], dada[2], dada[3], dada[4], dada[5]);
- if (dada.length==8)
- return new CubicCurve2D.Double(dada[0], dada[1], dada[2], dada[3], dada[4], dada[5], dada[6], dada[7]);
- throw new IllegalArgumentException();
- }
-
- public static void interpolatePaths(List l1, List l2, double t, Collection result)
- {
- if (l1.size()>l2.size()) {
- List l_ = l1;
- l1 = l2;
- l2 = l_;
- t = 1-t;
- }
-
- int div = l2.size() / l1.size();
- int mod = l2.size() % l1.size();
-
- int rightIndex = 0;
- for (int i=0; i l1 = new ArrayList();
- ArrayList l2 = new ArrayList();
- toShapes(path1, l1);
- toShapes(path2, l2);
- ArrayList result = new ArrayList();
- interpolatePaths(l1, l2, t, result);
- Path2D p = new Path2D.Double();
- appedToPath(p, result);
- return p;
- }
-
- public static Path2D interpolatePaths(Path2D path1, Path2D path2, double t)
- {
- return interpolatePaths(path1.getPathIterator(null), path2.getPathIterator(null), t);
- }
-
- public static Shape interpolateLine(Shape l1, Shape l2, double t)
- {
- assert(t>=0 && t<=1);
- if (t==0) return l1;
- if (t==1) return l2;
-
- double[] a1 = toArray(l1);
- double[] a2 = toArray(l2);
- double[] res = PathUtils.interpolateLineSegment(a1, a2, t);
- return toShape(res);
- }
-
- public static void toShapes(PathIterator pi, Collection result)
- {
- Iterator i = toShapeIterator(pi);
- while (i.hasNext()) {
- Shape segment = i.next();
- result.add(segment);
- }
- }
-
- /**
- * Returns an iterator that splits path into line shapes
- * @param pi path iterator
- * @return line segment iterator
- */
- public static Iterator toShapeIterator(final PathIterator pi)
- {
- return new PathIteratorToShapeIterator(pi);
- }
-
- private static class PathIteratorToShapeIterator implements Iterator
- {
- final PathIterator pi;
- double lineTo[] = new double[6];
- double startPos[] = new double[2];
- double from[] = new double[2];
- int degree = 0;
- PathIteratorToShapeIterator(PathIterator pi) {
- this.pi = pi;
- while(!pi.isDone()) {
- int type = pi.currentSegment(lineTo);
- pi.next();
- if (type == PathIterator.SEG_MOVETO) {
- startPos[0] = from[0] = lineTo[0];
- startPos[1] = from[1] = lineTo[1];
- }
- if (type == PathIterator.SEG_CLOSE) {
- type = PathIterator.SEG_LINETO;
- lineTo[0] = startPos[0];
- lineTo[1] = startPos[1];
- }
- if (type>=PathIterator.SEG_LINETO && type<=PathIterator.SEG_CUBICTO)
- {
- degree = type;
- // from == xx
- break;
- }
- }
- }
- @Override
- public boolean hasNext() {
- return degree>0;
- }
- @Override
- public Shape next() {
- if (degree==0) return null;
- Shape res = null;
- if (degree==1)
- res = new Line2D.Double(from[0], from[1], lineTo[0], lineTo[1]);
- else if (degree==2)
- res = new QuadCurve2D.Double(from[0], from[1], lineTo[0], lineTo[1], lineTo[2], lineTo[3]);
- else if (degree==3)
- res = new CubicCurve2D.Double(from[0], from[1], lineTo[0], lineTo[1], lineTo[2], lineTo[3], lineTo[4], lineTo[5]);
- else throw new IllegalArgumentException();
- // traverse path iterator until end or until next segment is known
- degree = 0;
- from[0] = lineTo[0];
- from[1] = lineTo[1];
- while(!pi.isDone()) {
- int type = pi.currentSegment(lineTo);
- pi.next();
- if (type == PathIterator.SEG_MOVETO) {
- startPos[0] = from[0] = lineTo[0];
- startPos[1] = from[1] = lineTo[1];
- }
- if (type == PathIterator.SEG_CLOSE) {
- type = PathIterator.SEG_LINETO;
- lineTo[0] = startPos[0];
- lineTo[1] = startPos[1];
- }
- if (type>=PathIterator.SEG_LINETO && type<=PathIterator.SEG_CUBICTO)
- {
- degree = type;
- break;
- }
- }
- return res;
- }
- @Override
- public void remove() {
- throw new UnsupportedOperationException();
- }
- }
-
-
-
-
- public static Shape subdiv_takeLeft(Shape line, double t)
- {
- if (t==1) return line;
- if (line instanceof Line2D) {
- Line2D l = (Line2D) line;
- double p0x = l.getX1();
- double p0y = l.getY1();
- double p1x = l.getX2();
- double p1y = l.getY2();
- double p1x_ = p0x*(1-t) + p1x*t;
- double p1y_ = p0y*(1-t) + p1y*t;
-
- return new Line2D.Double( p0x, p0y, p1x_, p1y_ );
- }
-
- if (line instanceof QuadCurve2D) {
- QuadCurve2D l = (QuadCurve2D) line;
- double p0x = l.getX1();
- double p0y = l.getY1();
- double p1x = l.getCtrlX();
- double p1y = l.getCtrlY();
- double p2x = l.getX2();
- double p2y = l.getY2();
- double p1x_ = p0x*(1-t) + p1x*t;
- double p1y_ = p0y*(1-t) + p1y*t;
-
- double q0x = p0x*(1-t) + p1x*t;
- double q0y = p0y*(1-t) + p1y*t;
-
- double q1x = p1x*(1-t) + p2x*t;
- double q1y = p1y*(1-t) + p2y*t;
-
- double p2x_ = q0x*(1-t) + q1x*t;
- double p2y_ = q0y*(1-t) + q1y*t;
-
- return new QuadCurve2D.Double( p0x, p0y, p1x_, p1y_, p2x_, p2y_ );
- }
-
- if (line instanceof CubicCurve2D) {
- CubicCurve2D l = (CubicCurve2D) line;
- double p0x = l.getX1();
- double p0y = l.getY1();
- double p1x = l.getCtrlX1();
- double p1y = l.getCtrlY1();
- double p2x = l.getCtrlX2();
- double p2y = l.getCtrlY2();
- double p3x = l.getX2();
- double p3y = l.getY2();
- double p1x_ = p0x*(1-t) + p1x*t;
- double p1y_ = p0y*(1-t) + p1y*t;
-
- double q0x = p0x*(1-t) + p1x*t;
- double q0y = p0y*(1-t) + p1y*t;
-
- double q1x = p1x*(1-t) + p2x*t;
- double q1y = p1y*(1-t) + p2y*t;
-
- double p2x_ = q0x*(1-t) + q1x*t;
- double p2y_ = q0y*(1-t) + q1y*t;
-
- double q2x = p2x*(1-t) + p3x*t;
- double q2y = p2y*(1-t) + p3y*t;
-
- double r0x = q0x*(1-t) + q1x*t;
- double r0y = q0y*(1-t) + q1y*t;
-
- double r1x = q1x*(1-t) + q2x*t;
- double r1y = q1y*(1-t) + q2y*t;
-
- double p3x_ = r0x*(1-t) + r1x*t;
- double p3y_ = r0y*(1-t) + r1y*t;
-
- return new CubicCurve2D.Double(p0x, p0y, p1x_, p1y_, p2x_, p2y_, p3x_, p3y_);
- }
-
- throw new IllegalArgumentException();
- }
-
- public static Shape subdiv_takeRight(Shape line, double t)
- {
- if (t==0) return line;
- if (line instanceof Line2D) {
- Line2D l = (Line2D) line;
- double p0x = l.getX1();
- double p0y = l.getY1();
- double p1x = l.getX2();
- double p1y = l.getY2();
- double p0x_ = p0x*(1-t) + p1x*t;
- double p0y_ = p0y*(1-t) + p1y*t;
-
- return new Line2D.Double( p0x_, p0y_, p1x, p1y );
- }
-
- if (line instanceof QuadCurve2D) {
- QuadCurve2D l = (QuadCurve2D) line;
- double p0x = l.getX1();
- double p0y = l.getY1();
- double p1x = l.getCtrlX();
- double p1y = l.getCtrlY();
- double p2x = l.getX2();
- double p2y = l.getY2();
-
- double q0x = p0x*(1-t) + p1x*t;
- double q0y = p0y*(1-t) + p1y*t;
-
- double q1x = p1x*(1-t) + p2x*t;
- double q1y = p1y*(1-t) + p2y*t;
-
- double p2x_ = q0x*(1-t) + q1x*t;
- double p2y_ = q0y*(1-t) + q1y*t;
-
- return new QuadCurve2D.Double( p2x_, p2y_, q1x, q1y, p2x, p2y );
- }
-
-
- if (line instanceof CubicCurve2D) {
- CubicCurve2D l = (CubicCurve2D) line;
-
- double p0x = l.getX1();
- double p0y = l.getY1();
- double p1x = l.getCtrlX1();
- double p1y = l.getCtrlY1();
- double p2x = l.getCtrlX2();
- double p2y = l.getCtrlY2();
- double p3x = l.getX2();
- double p3y = l.getY2();
-
- double q0x = p0x*(1-t) + p1x*t;
- double q0y = p0y*(1-t) + p1y*t;
-
- double q1x = p1x*(1-t) + p2x*t;
- double q1y = p1y*(1-t) + p2y*t;
-
- double q2x = p2x*(1-t) + p3x*t;
- double q2y = p2y*(1-t) + p3y*t;
-
- double r0x = q0x*(1-t) + q1x*t;
- double r0y = q0y*(1-t) + q1y*t;
-
- double r1x = q1x*(1-t) + q2x*t;
- double r1y = q1y*(1-t) + q2y*t;
-
- double p3x_ = r0x*(1-t) + r1x*t;
- double p3y_ = r0y*(1-t) + r1y*t;
-
- return new CubicCurve2D.Double( p3x_, p3y_, r1x, r1y, q2x, q2y, p3x, p3y );
- }
-
- return null;
- }
-
-
-
- /**
- * Crops line segment into a smaller line segment
- * @param line line segment
- * @param t0 begin t
- * @param t1 end t
- * @return cropped line segment
- */
- public static Shape subdiv(Shape line, double t0, double t1)
- {
- if (t0==0 && t1==1) return line;
- Shape temp = subdiv_takeLeft(line, t1);
- return subdiv_takeRight(temp, t0/t1);
- }
-
- public static void appedToPath(Path2D p, Shape ... shapes)
- {
- for (Shape s : shapes)
- {
- Point2D cur = p.getCurrentPoint();
- if (s instanceof Line2D) {
- Line2D l = (Line2D) s;
- if (cur.getX()!=l.getX1() || cur.getY()!=l.getY1())
- p.moveTo(l.getX1(), l.getY1());
- p.lineTo(l.getX2(), l.getY2());
- } else if (s instanceof QuadCurve2D) {
- QuadCurve2D l = (QuadCurve2D) s;
- if (cur.getX()!=l.getX1() || cur.getY()!=l.getY1())
- p.moveTo(l.getX1(), l.getY1());
- p.quadTo(l.getCtrlX(), l.getCtrlY(), l.getX2(), l.getY2());
- } else if (s instanceof CubicCurve2D) {
- CubicCurve2D l = (CubicCurve2D) s;
- if (cur.getX()!=l.getX1() || cur.getY()!=l.getY1())
- p.moveTo(l.getX1(), l.getY1());
- p.curveTo(l.getCtrlX1(), l.getCtrlY1(), l.getCtrlX2(), l.getCtrlY2(), l.getX2(), l.getY2());
- } throw new IllegalArgumentException();
- }
- }
- public static void appedToPath(Path2D p, Collection shapes)
- {
- for (Shape s : shapes)
- {
- Point2D cur = p.getCurrentPoint();
- if (s instanceof Line2D) {
- Line2D l = (Line2D) s;
- if (cur==null || cur.getX()!=l.getX1() || cur.getY()!=l.getY1())
- p.moveTo(l.getX1(), l.getY1());
- p.lineTo(l.getX2(), l.getY2());
- } else if (s instanceof QuadCurve2D) {
- QuadCurve2D l = (QuadCurve2D) s;
- if (cur==null || cur.getX()!=l.getX1() || cur.getY()!=l.getY1())
- p.moveTo(l.getX1(), l.getY1());
- p.quadTo(l.getCtrlX(), l.getCtrlY(), l.getX2(), l.getY2());
- } else if (s instanceof CubicCurve2D) {
- CubicCurve2D l = (CubicCurve2D) s;
- if (cur==null || cur.getX()!=l.getX1() || cur.getY()!=l.getY1())
- p.moveTo(l.getX1(), l.getY1());
- p.curveTo(l.getCtrlX1(), l.getCtrlY1(), l.getCtrlX2(), l.getCtrlY2(), l.getX2(), l.getY2());
- } else throw new IllegalArgumentException();
- }
- }
-
-
- public static void main(String[] args) {
-
- }
-
-
-}
+/*******************************************************************************
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management
+ * in Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * VTT Technical Research Centre of Finland - initial API and implementation
+ *******************************************************************************/
+package org.simantics.g2d.utils;
+
+import java.awt.Shape;
+import java.awt.geom.CubicCurve2D;
+import java.awt.geom.Line2D;
+import java.awt.geom.Path2D;
+import java.awt.geom.PathIterator;
+import java.awt.geom.Point2D;
+import java.awt.geom.QuadCurve2D;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Path Utils.
+ *
+ * A line segment (linear, quadratic or cubic bezier) is described
+ * with a double array. The length of the array describes its degree (4,6,8).
+ * The first 2 elements define start point and last 2 the end point.
+ * Points in the middle are bezier control points.
+ *
+ * @See {@link GeometryUtils} for more geometry related utilities
+ * @author Toni Kalajainen
+ */
+public class PathUtils2 {
+
+ /**
+ * Get tangent of an bezier
+ * @param lineSegment bezier of n degrees
+ * @param degree 1..3
+ * @param t 0..1
+ * @return unit vector
+ */
+ public static Point2D getLineTangent(Shape line, double t, Point2D pt)
+ {
+ double x=0, y=0;
+ if (line instanceof Line2D)
+ {
+ Line2D l = (Line2D) line;
+ x = l.getX1() - l.getX2();
+ y = l.getY1() - l.getY2();
+ } else if (line instanceof QuadCurve2D) {
+ QuadCurve2D l = (QuadCurve2D) line;
+ double p0x = l.getX1();
+ double p0y = l.getY1();
+ double p1x = l.getCtrlX();
+ double p1y = l.getCtrlY();
+ double p2x = l.getX2();
+ double p2y = l.getY2();
+ x = 2*t*(p0x - 2*p1x + p2x) + 2*(-p0x + p1x);
+ y = 2*t*(p0y - 2*p1y + p2y) + 2*(-p0y + p1y);
+
+ } else if (line instanceof CubicCurve2D) {
+ CubicCurve2D l = (CubicCurve2D) line;
+ double p0x = l.getX1();
+ double p0y = l.getY1();
+ double p1x = l.getCtrlX1();
+ double p1y = l.getCtrlY1();
+ double p2x = l.getCtrlX2();
+ double p2y = l.getCtrlY2();
+ double p3x = l.getX2();
+ double p3y = l.getY2();
+ x = 3*(1-t)*(1-t)*(p1x-p2x) + 3*(p2x-p1x)*2*t*(1-t) + 3*(p3x-p0x)*t*t;
+ y = 3*(1-t)*(1-t)*(p1y-p0y) + 3*(p2y-p1y)*2*t*(1-t) + 3*(p3y-p2y)*t*t;
+ } else throw new IllegalArgumentException();
+
+ return new Point2D.Double(x, y);
+ }
+
+ /**
+ *
+ * @param lineSegment
+ * @param t 0..1
+ * @return
+ */
+ public static Point2D getLinePos(Shape line, double t, Point2D pt)
+ {
+ assert(line!=null);
+ double x=0, y=0;
+ if (pt==null) pt = new Point2D.Double();
+
+ if (line instanceof Line2D) {
+ Line2D l = (Line2D) line;
+ double p0x = l.getX1();
+ double p0y = l.getY1();
+ double p1x = l.getX2();
+ double p1y = l.getY2();
+
+ x = p0x*(1-t) + t*p1x;
+ y = p0y*(1-t) + t*p1y;
+ } else
+ if (line instanceof QuadCurve2D) {
+ QuadCurve2D l = (QuadCurve2D) line;
+ double p0x = l.getX1();
+ double p0y = l.getY1();
+ double p1x = l.getCtrlX();
+ double p1y = l.getCtrlY();
+ double p2x = l.getX2();
+ double p2y = l.getY2();
+
+ double c2x = p0x-2*p1x+p2x;
+ double c2y = p0y-2*p1y+p2y;
+
+ double c1x = -2*p0x+2*p1x;
+ double c1y = -2*p0y+2*p1y;
+
+ double c0x = p0x;
+ double c0y = p0y;
+
+ x = t*t*c2x+t*c1x+c0x;
+ y = t*t*c2y+t*c1y+c0y;
+ } else if (line instanceof CubicCurve2D) {
+ CubicCurve2D l = (CubicCurve2D) line;
+ double p0x = l.getX1();
+ double p0y = l.getY1();
+ double p1x = l.getCtrlX1();
+ double p1y = l.getCtrlY1();
+ double p2x = l.getCtrlX2();
+ double p2y = l.getCtrlY2();
+ double p3x = l.getX2();
+ double p3y = l.getY2();
+
+ 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;
+ 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;
+ } else throw new IllegalArgumentException();
+ pt.setLocation(x, y);
+
+ return pt;
+ }
+
+ public static double getLineLength(Shape line)
+ {
+ if (line instanceof Line2D) {
+ Line2D l = (Line2D) line;
+ double dx = l.getX2() - l.getX1();
+ double dy = l.getY2() - l.getY1();
+ return Math.sqrt(dx*dx+dy*dy);
+ }
+
+ // Quick'n'dirty approximation
+ // TODO Replace with accurate value
+ double result = 0;
+ Point2D prevPos = getLinePos(line, 0.0, null);
+ for (int i=0; i<10; i++)
+ {
+ double t = (double)(i+1)/10;
+ Point2D pos = getLinePos(line, t, null);
+ result += pos.distance(prevPos);
+ prevPos.setLocation(pos);
+ }
+ return result;
+ }
+
+ public static int getLineDegree(Shape line)
+ {
+ if (line instanceof Line2D) return 1;
+ if (line instanceof QuadCurve2D) return 2;
+ if (line instanceof CubicCurve2D) return 3;
+ throw new IllegalArgumentException(line+" is not a shape");
+ }
+
+
+ public static double[] toArray(Shape line)
+ {
+ if (line instanceof Line2D) {
+ Line2D l = (Line2D) line;
+ return new double[] {l.getX1(), l.getY1(), l.getX2(), l.getY2()};
+ }
+ if (line instanceof QuadCurve2D) {
+ QuadCurve2D l = (QuadCurve2D) line;
+ return new double[] {l.getX1(), l.getY1(), l.getCtrlX(), l.getCtrlY(), l.getX2(), l.getY2()};
+ }
+ if (line instanceof CubicCurve2D) {
+ CubicCurve2D l = (CubicCurve2D) line;
+ return new double[] {l.getX1(), l.getY1(), l.getCtrlX1(), l.getCtrlY1(), l.getCtrlX2(), l.getCtrlY2(), l.getX2(), l.getY2()};
+ }
+ throw new IllegalArgumentException(line+" is not a shape");
+ }
+
+ public static Shape toShape(double dada[])
+ {
+ if (dada.length==4)
+ return new Line2D.Double(dada[0], dada[1], dada[2], dada[3]);
+ if (dada.length==6)
+ return new QuadCurve2D.Double(dada[0], dada[1], dada[2], dada[3], dada[4], dada[5]);
+ if (dada.length==8)
+ return new CubicCurve2D.Double(dada[0], dada[1], dada[2], dada[3], dada[4], dada[5], dada[6], dada[7]);
+ throw new IllegalArgumentException();
+ }
+
+ public static void interpolatePaths(List l1, List l2, double t, Collection result)
+ {
+ if (l1.size()>l2.size()) {
+ List l_ = l1;
+ l1 = l2;
+ l2 = l_;
+ t = 1-t;
+ }
+
+ int div = l2.size() / l1.size();
+ int mod = l2.size() % l1.size();
+
+ int rightIndex = 0;
+ for (int i=0; i l1 = new ArrayList();
+ ArrayList l2 = new ArrayList();
+ toShapes(path1, l1);
+ toShapes(path2, l2);
+ ArrayList result = new ArrayList();
+ interpolatePaths(l1, l2, t, result);
+ Path2D p = new Path2D.Double();
+ appedToPath(p, result);
+ return p;
+ }
+
+ public static Path2D interpolatePaths(Path2D path1, Path2D path2, double t)
+ {
+ return interpolatePaths(path1.getPathIterator(null), path2.getPathIterator(null), t);
+ }
+
+ public static Shape interpolateLine(Shape l1, Shape l2, double t)
+ {
+ assert(t>=0 && t<=1);
+ if (t==0) return l1;
+ if (t==1) return l2;
+
+ double[] a1 = toArray(l1);
+ double[] a2 = toArray(l2);
+ double[] res = PathUtils.interpolateLineSegment(a1, a2, t);
+ return toShape(res);
+ }
+
+ public static void toShapes(PathIterator pi, Collection result)
+ {
+ Iterator i = toShapeIterator(pi);
+ while (i.hasNext()) {
+ Shape segment = i.next();
+ result.add(segment);
+ }
+ }
+
+ /**
+ * Returns an iterator that splits path into line shapes
+ * @param pi path iterator
+ * @return line segment iterator
+ */
+ public static Iterator toShapeIterator(final PathIterator pi)
+ {
+ return new PathIteratorToShapeIterator(pi);
+ }
+
+ private static class PathIteratorToShapeIterator implements Iterator
+ {
+ final PathIterator pi;
+ double lineTo[] = new double[6];
+ double startPos[] = new double[2];
+ double from[] = new double[2];
+ int degree = 0;
+ PathIteratorToShapeIterator(PathIterator pi) {
+ this.pi = pi;
+ while(!pi.isDone()) {
+ int type = pi.currentSegment(lineTo);
+ pi.next();
+ if (type == PathIterator.SEG_MOVETO) {
+ startPos[0] = from[0] = lineTo[0];
+ startPos[1] = from[1] = lineTo[1];
+ }
+ if (type == PathIterator.SEG_CLOSE) {
+ type = PathIterator.SEG_LINETO;
+ lineTo[0] = startPos[0];
+ lineTo[1] = startPos[1];
+ }
+ if (type>=PathIterator.SEG_LINETO && type<=PathIterator.SEG_CUBICTO)
+ {
+ degree = type;
+ // from == xx
+ break;
+ }
+ }
+ }
+ @Override
+ public boolean hasNext() {
+ return degree>0;
+ }
+ @Override
+ public Shape next() {
+ if (degree==0) return null;
+ Shape res = null;
+ if (degree==1)
+ res = new Line2D.Double(from[0], from[1], lineTo[0], lineTo[1]);
+ else if (degree==2)
+ res = new QuadCurve2D.Double(from[0], from[1], lineTo[0], lineTo[1], lineTo[2], lineTo[3]);
+ else if (degree==3)
+ res = new CubicCurve2D.Double(from[0], from[1], lineTo[0], lineTo[1], lineTo[2], lineTo[3], lineTo[4], lineTo[5]);
+ else throw new IllegalArgumentException();
+ // traverse path iterator until end or until next segment is known
+ degree = 0;
+ from[0] = lineTo[0];
+ from[1] = lineTo[1];
+ while(!pi.isDone()) {
+ int type = pi.currentSegment(lineTo);
+ pi.next();
+ if (type == PathIterator.SEG_MOVETO) {
+ startPos[0] = from[0] = lineTo[0];
+ startPos[1] = from[1] = lineTo[1];
+ }
+ if (type == PathIterator.SEG_CLOSE) {
+ type = PathIterator.SEG_LINETO;
+ lineTo[0] = startPos[0];
+ lineTo[1] = startPos[1];
+ }
+ if (type>=PathIterator.SEG_LINETO && type<=PathIterator.SEG_CUBICTO)
+ {
+ degree = type;
+ break;
+ }
+ }
+ return res;
+ }
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+
+
+
+ public static Shape subdiv_takeLeft(Shape line, double t)
+ {
+ if (t==1) return line;
+ if (line instanceof Line2D) {
+ Line2D l = (Line2D) line;
+ double p0x = l.getX1();
+ double p0y = l.getY1();
+ double p1x = l.getX2();
+ double p1y = l.getY2();
+ double p1x_ = p0x*(1-t) + p1x*t;
+ double p1y_ = p0y*(1-t) + p1y*t;
+
+ return new Line2D.Double( p0x, p0y, p1x_, p1y_ );
+ }
+
+ if (line instanceof QuadCurve2D) {
+ QuadCurve2D l = (QuadCurve2D) line;
+ double p0x = l.getX1();
+ double p0y = l.getY1();
+ double p1x = l.getCtrlX();
+ double p1y = l.getCtrlY();
+ double p2x = l.getX2();
+ double p2y = l.getY2();
+ double p1x_ = p0x*(1-t) + p1x*t;
+ double p1y_ = p0y*(1-t) + p1y*t;
+
+ double q0x = p0x*(1-t) + p1x*t;
+ double q0y = p0y*(1-t) + p1y*t;
+
+ double q1x = p1x*(1-t) + p2x*t;
+ double q1y = p1y*(1-t) + p2y*t;
+
+ double p2x_ = q0x*(1-t) + q1x*t;
+ double p2y_ = q0y*(1-t) + q1y*t;
+
+ return new QuadCurve2D.Double( p0x, p0y, p1x_, p1y_, p2x_, p2y_ );
+ }
+
+ if (line instanceof CubicCurve2D) {
+ CubicCurve2D l = (CubicCurve2D) line;
+ double p0x = l.getX1();
+ double p0y = l.getY1();
+ double p1x = l.getCtrlX1();
+ double p1y = l.getCtrlY1();
+ double p2x = l.getCtrlX2();
+ double p2y = l.getCtrlY2();
+ double p3x = l.getX2();
+ double p3y = l.getY2();
+ double p1x_ = p0x*(1-t) + p1x*t;
+ double p1y_ = p0y*(1-t) + p1y*t;
+
+ double q0x = p0x*(1-t) + p1x*t;
+ double q0y = p0y*(1-t) + p1y*t;
+
+ double q1x = p1x*(1-t) + p2x*t;
+ double q1y = p1y*(1-t) + p2y*t;
+
+ double p2x_ = q0x*(1-t) + q1x*t;
+ double p2y_ = q0y*(1-t) + q1y*t;
+
+ double q2x = p2x*(1-t) + p3x*t;
+ double q2y = p2y*(1-t) + p3y*t;
+
+ double r0x = q0x*(1-t) + q1x*t;
+ double r0y = q0y*(1-t) + q1y*t;
+
+ double r1x = q1x*(1-t) + q2x*t;
+ double r1y = q1y*(1-t) + q2y*t;
+
+ double p3x_ = r0x*(1-t) + r1x*t;
+ double p3y_ = r0y*(1-t) + r1y*t;
+
+ return new CubicCurve2D.Double(p0x, p0y, p1x_, p1y_, p2x_, p2y_, p3x_, p3y_);
+ }
+
+ throw new IllegalArgumentException();
+ }
+
+ public static Shape subdiv_takeRight(Shape line, double t)
+ {
+ if (t==0) return line;
+ if (line instanceof Line2D) {
+ Line2D l = (Line2D) line;
+ double p0x = l.getX1();
+ double p0y = l.getY1();
+ double p1x = l.getX2();
+ double p1y = l.getY2();
+ double p0x_ = p0x*(1-t) + p1x*t;
+ double p0y_ = p0y*(1-t) + p1y*t;
+
+ return new Line2D.Double( p0x_, p0y_, p1x, p1y );
+ }
+
+ if (line instanceof QuadCurve2D) {
+ QuadCurve2D l = (QuadCurve2D) line;
+ double p0x = l.getX1();
+ double p0y = l.getY1();
+ double p1x = l.getCtrlX();
+ double p1y = l.getCtrlY();
+ double p2x = l.getX2();
+ double p2y = l.getY2();
+
+ double q0x = p0x*(1-t) + p1x*t;
+ double q0y = p0y*(1-t) + p1y*t;
+
+ double q1x = p1x*(1-t) + p2x*t;
+ double q1y = p1y*(1-t) + p2y*t;
+
+ double p2x_ = q0x*(1-t) + q1x*t;
+ double p2y_ = q0y*(1-t) + q1y*t;
+
+ return new QuadCurve2D.Double( p2x_, p2y_, q1x, q1y, p2x, p2y );
+ }
+
+
+ if (line instanceof CubicCurve2D) {
+ CubicCurve2D l = (CubicCurve2D) line;
+
+ double p0x = l.getX1();
+ double p0y = l.getY1();
+ double p1x = l.getCtrlX1();
+ double p1y = l.getCtrlY1();
+ double p2x = l.getCtrlX2();
+ double p2y = l.getCtrlY2();
+ double p3x = l.getX2();
+ double p3y = l.getY2();
+
+ double q0x = p0x*(1-t) + p1x*t;
+ double q0y = p0y*(1-t) + p1y*t;
+
+ double q1x = p1x*(1-t) + p2x*t;
+ double q1y = p1y*(1-t) + p2y*t;
+
+ double q2x = p2x*(1-t) + p3x*t;
+ double q2y = p2y*(1-t) + p3y*t;
+
+ double r0x = q0x*(1-t) + q1x*t;
+ double r0y = q0y*(1-t) + q1y*t;
+
+ double r1x = q1x*(1-t) + q2x*t;
+ double r1y = q1y*(1-t) + q2y*t;
+
+ double p3x_ = r0x*(1-t) + r1x*t;
+ double p3y_ = r0y*(1-t) + r1y*t;
+
+ return new CubicCurve2D.Double( p3x_, p3y_, r1x, r1y, q2x, q2y, p3x, p3y );
+ }
+
+ return null;
+ }
+
+
+
+ /**
+ * Crops line segment into a smaller line segment
+ * @param line line segment
+ * @param t0 begin t
+ * @param t1 end t
+ * @return cropped line segment
+ */
+ public static Shape subdiv(Shape line, double t0, double t1)
+ {
+ if (t0==0 && t1==1) return line;
+ Shape temp = subdiv_takeLeft(line, t1);
+ return subdiv_takeRight(temp, t0/t1);
+ }
+
+ public static void appedToPath(Path2D p, Shape ... shapes)
+ {
+ for (Shape s : shapes)
+ {
+ Point2D cur = p.getCurrentPoint();
+ if (s instanceof Line2D) {
+ Line2D l = (Line2D) s;
+ if (cur.getX()!=l.getX1() || cur.getY()!=l.getY1())
+ p.moveTo(l.getX1(), l.getY1());
+ p.lineTo(l.getX2(), l.getY2());
+ } else if (s instanceof QuadCurve2D) {
+ QuadCurve2D l = (QuadCurve2D) s;
+ if (cur.getX()!=l.getX1() || cur.getY()!=l.getY1())
+ p.moveTo(l.getX1(), l.getY1());
+ p.quadTo(l.getCtrlX(), l.getCtrlY(), l.getX2(), l.getY2());
+ } else if (s instanceof CubicCurve2D) {
+ CubicCurve2D l = (CubicCurve2D) s;
+ if (cur.getX()!=l.getX1() || cur.getY()!=l.getY1())
+ p.moveTo(l.getX1(), l.getY1());
+ p.curveTo(l.getCtrlX1(), l.getCtrlY1(), l.getCtrlX2(), l.getCtrlY2(), l.getX2(), l.getY2());
+ } throw new IllegalArgumentException();
+ }
+ }
+ public static void appedToPath(Path2D p, Collection shapes)
+ {
+ for (Shape s : shapes)
+ {
+ Point2D cur = p.getCurrentPoint();
+ if (s instanceof Line2D) {
+ Line2D l = (Line2D) s;
+ if (cur==null || cur.getX()!=l.getX1() || cur.getY()!=l.getY1())
+ p.moveTo(l.getX1(), l.getY1());
+ p.lineTo(l.getX2(), l.getY2());
+ } else if (s instanceof QuadCurve2D) {
+ QuadCurve2D l = (QuadCurve2D) s;
+ if (cur==null || cur.getX()!=l.getX1() || cur.getY()!=l.getY1())
+ p.moveTo(l.getX1(), l.getY1());
+ p.quadTo(l.getCtrlX(), l.getCtrlY(), l.getX2(), l.getY2());
+ } else if (s instanceof CubicCurve2D) {
+ CubicCurve2D l = (CubicCurve2D) s;
+ if (cur==null || cur.getX()!=l.getX1() || cur.getY()!=l.getY1())
+ p.moveTo(l.getX1(), l.getY1());
+ p.curveTo(l.getCtrlX1(), l.getCtrlY1(), l.getCtrlX2(), l.getCtrlY2(), l.getX2(), l.getY2());
+ } else throw new IllegalArgumentException();
+ }
+ }
+
+
+ public static void main(String[] args) {
+
+ }
+
+
+}