X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.g2d%2Fsrc%2Forg%2Fsimantics%2Fg2d%2Futils%2FPathUtils.java;h=7ff95ed013d2236c5f63a1fe7c7a9cf0f9d83baa;hb=refs%2Fchanges%2F80%2F4480%2F1;hp=13d2dd9b2b2671aa8810c8af1515f400f9fa50e9;hpb=969bd23cab98a79ca9101af33334000879fb60c5;p=simantics%2Fplatform.git
diff --git a/bundles/org.simantics.g2d/src/org/simantics/g2d/utils/PathUtils.java b/bundles/org.simantics.g2d/src/org/simantics/g2d/utils/PathUtils.java
index 13d2dd9b2..7ff95ed01 100644
--- a/bundles/org.simantics.g2d/src/org/simantics/g2d/utils/PathUtils.java
+++ b/bundles/org.simantics.g2d/src/org/simantics/g2d/utils/PathUtils.java
@@ -1,720 +1,720 @@
-/*******************************************************************************
- * 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.geom.Path2D;
-import java.awt.geom.PathIterator;
-import java.awt.geom.Point2D;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Iterator;
-
-/**
- * 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.
- *
- * @author Toni Kalajainen
- */
-public class PathUtils {
-
- /**
- * 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(double lineSegment[], double t)
- {
- int degree = getLineDegree(lineSegment);
- double x=0, y=0;
- if (degree==1)
- {
- x = lineSegment[2*1+0] - lineSegment[2*0+0];
- y = lineSegment[2*1+1] - lineSegment[2*0+1];
- } else {
- if (degree==2) {
- x = 2*t*(lineSegment[2*0+0] - 2*lineSegment[2*1+0] + lineSegment[2*2+0]) + 2*(-lineSegment[2*0+0] + lineSegment[2*1+0]);
- y = 2*t*(lineSegment[2*0+1] - 2*lineSegment[2*1+1] + lineSegment[2*2+1]) + 2*(-lineSegment[2*0+1] + lineSegment[2*1+1]);
- } else if (degree==3) {
- x = 3*(1-t)*(1-t)*(lineSegment[2*1+0]-lineSegment[2*0+0]) + 3*(lineSegment[2*2+0]-lineSegment[2*1+0])*2*t*(1-t) + 3*(lineSegment[2*3+0]-lineSegment[2*2+0])*t*t;
- y = 3*(1-t)*(1-t)*(lineSegment[2*1+1]-lineSegment[2*0+1]) + 3*(lineSegment[2*2+1]-lineSegment[2*1+1])*2*t*(1-t) + 3*(lineSegment[2*3+1]-lineSegment[2*2+1])*t*t;
- }
- }
- return new Point2D.Double(x, y);
- }
-
- /**
- *
- * @param lineSegment
- * @param t 0..1
- * @return
- */
- public static Point2D getLinePos(double lineSegment[], double t)
- {
- assert(lineSegment!=null);
- int degree = getLineDegree(lineSegment);
- double x=0, y=0;
-
- if (degree==1) {
- double p0x = lineSegment[0];
- double p0y = lineSegment[1];
- double p1x = lineSegment[2];
- double p1y = lineSegment[3];
-
- x = p0x*(1-t) + t*p1x;
- y = p0y*(1-t) + t*p1y;
- } else if (degree==2) {
- double p0x = lineSegment[0];
- double p0y = lineSegment[1];
- double p1x = lineSegment[2];
- double p1y = lineSegment[3];
- double p2x = lineSegment[4];
- double p2y = lineSegment[5];
-
- 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 (degree==3) {
- double p0x = lineSegment[0];
- double p0y = lineSegment[1];
- double p1x = lineSegment[2];
- double p1y = lineSegment[3];
- double p2x = lineSegment[4];
- double p2y = lineSegment[5];
- double p3x = lineSegment[6];
- double p3y = lineSegment[7];
-
- 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;
- }
-
- return new Point2D.Double(x, y);
- }
-
- public static double getLineLength(double lineSegment[])
- {
- int degree = getLineDegree(lineSegment);
- if (degree==1) {
- double dx = lineSegment[2]-lineSegment[0];
- double dy = lineSegment[3]-lineSegment[1];
- return Math.sqrt(dx*dx+dy*dy);
- }
-
- // Quick'n'dirty approximation
- // TODO Replace with accurate value
- double result = 0;
- Point2D prevPos = getLinePos(lineSegment, 0.0);
- for (int i=0; i<10; i++)
- {
- double t = (double)(i+1)/10;
- Point2D pos = getLinePos(lineSegment, t);
- result += pos.distance(prevPos);
- prevPos.setLocation(pos);
- }
- return result;
- /*
- if (degree==2) {
- double c2x = bezier[2*0+0]-2*bezier[2*1+0]+bezier[2*2+0];
- double c2y = bezier[2*0+1]-2*bezier[2*1+1]+bezier[2*2+1];
-
- double c1x = -2*bezier[2*0+0]+2*bezier[2*1+0];
- double c1y = -2*bezier[2*0+1]+2*bezier[2*1+1];
-
- double c0x = bezier[2*0+0];
- double c0y = bezier[2*0+1];
-
- double intg_x = c2x/3 + c1x/2 + c0x;
- double intg_y = c2y/3 + c1y/2 + c0y;
- System.out.println(intg_x +"\t" + intg_y);
-
- return intg_x + intg_y;
- }
- return 0;
- */
- }
-
- public static int getLineDegree(double lineSegment[])
- {
- assert(lineSegment.length==4 || lineSegment.length==6 || lineSegment.length==8);
- return (lineSegment.length-2)/2;
- }
-
- /**
- * Get first and last point & tangent of a path
- * @param path
- * @param begin
- * @param beginDirection
- * @param end
- * @param endDirection
- * @return true if pi contained atleast one line segment
- */
- public static boolean getPathArrows(PathIterator pi, Point2D begin, Point2D beginDirection, Point2D end, Point2D endDirection)
- {
- Iterator i = toLineIterator(pi);
- double first[]=null, last[]=null;
- while (i.hasNext()) {
- double[] current = i.next();
- if (first==null) first = current;
- if (!i.hasNext()) last = current;
- }
- if (first==null || last==null) return false;
- begin.setLocation( getLinePos(first, 0) );
- beginDirection.setLocation( getLineTangent(first, 0) );
- end.setLocation( getLinePos(last, 1) );
- Point2D endTangent = getLineTangent(last, 1);
- endDirection.setLocation( -endTangent.getX(), -endTangent.getY() );
- return true;
- }
-
-
-
- /**
- * Interpolate two paths
- * @param path1
- * @param path2
- * @param t phase 0..1, 0==path1, 1==path2
- * @return
- */
- public static Path2D interpolatePaths(PathIterator path1, PathIterator path2, double t)
- {
- Path2D result = new Path2D.Double();
-
- ArrayList l1 = new ArrayList();
- toLineSegments(path1, l1);
- ArrayList l2 = new ArrayList();
- toLineSegments(path2, l2);
-
- if (l1.size()==l2.size())
- {
-
- }
-
- result.append(path1, false);
- return result;
- }
-
- public static double[] interpolateLineSegment(double l1[], double l2[], double t)
- {
- assert(t>=0 && t<=1);
- if (t==0) return Arrays.copyOf(l1, l1.length);
- if (t==1) return Arrays.copyOf(l1, l1.length);
-
- int d1 = getLineDegree(l1);
- int d2 = getLineDegree(l2);
-
- if (d1==d2) {
- double result [] = new double[l1.length];
- for (int i=0; i toLineIterator(final PathIterator pi)
- {
- return new PathIteratorToSegmentIterator(pi);
- }
-
- public static void toLineSegments(PathIterator pi, Collection result)
- {
- Iterator i = toLineIterator(pi);
- while (i.hasNext()) {
- double[] segment = i.next();
- result.add(segment);
- }
- }
-
- private static class PathIteratorToSegmentIterator implements Iterator
- {
- final PathIterator pi;
- double lineTo[] = new double[6];
- double startPos[] = new double[2];
- double from[] = new double[2];
- int degree = 0;
- PathIteratorToSegmentIterator(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 double[] next() {
- if (degree==0) return null;
- double result[] = new double[degree*2+2];
- result[0] = from[0];
- result[1] = from[1];
- result[2] = lineTo[0];
- result[3] = lineTo[1];
- if (degree==2) {
- result[4] = lineTo[2];
- result[5] = lineTo[3];
- } else if (degree==3) {
- result[6] = lineTo[4];
- result[7] = lineTo[5];
- }
- // 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 result;
- }
- @Override
- public void remove() {
- throw new UnsupportedOperationException();
- }
- }
-
-
-
-
-
-
- /**
- * Finds intersection of two half-straight lines
- * @param p0x
- * @param p0y
- * @param dir0
- * @param p1x
- * @param p1y
- * @param dir1
- * @return
- */
- public static Point2D findIntersection(double p0x, double p0y, double dir0, double p1x, double p1y, double dir1)
- {
- Point2D uv = new Point2D.Double();
- GeometryUtils.toUnitVector(dir0, uv);
- double v0x = uv.getX();
- double v0y = uv.getY();
- GeometryUtils.toUnitVector(dir1, uv);
- double v1x = uv.getX();
- double v1y = uv.getY();
- return findIntersection(p0x, p0y, v0x, v0y, p1x, p1y, v1x, v1y);
- }
-
- /**
- * Finds intersection of two half-straight lines
- * @param p0
- * @param v0
- * @param p1
- * @param v1
- * @return
- */
- public static Point2D findIntersection(Point2D p0, Point2D v0, Point2D p1, Point2D v1)
- {
- double v0x = v0.getX();
- double v0y = v0.getY();
- double v1x = v1.getX();
- double v1y = v1.getY();
- double p0x = p0.getX();
- double p0y = p0.getY();
- double p1x = p1.getX();
- double p1y = p1.getY();
- return findIntersection(p0x, p0y, v0x, v0y, p1x, p1y, v1x, v1y);
- }
-
- /**
- * Finds intersection of two half-straight lines
- * @param p1
- * @param v1 direction vector (unit vector)
- * @param p2
- * @param v2 direction vector (unit vector)
- * @return
- */
- public static Point2D findIntersection(double p0x, double p0y, double v0x, double v0y, double p1x, double p1y, double v1x, double v1y)
- {
- if (p0x==p1x && p0y==p1y) return new Point2D.Double(p0x, p0y);
- /*
- i = Intersection point
- i = p0 + t*v0 = p1 + r*v1;
- */
- double denominator = v0y*v1x - v0x*v1y;
- // Straights are in same or opposite directions
- if (denominator == 0) {
- return null;
- /*
- // Do they overlap?
- boolean overlap = v0x*(p1y-p0y) - v0y*(p1x-p1x) == 0;
- if (!overlap) return null;
- double t = v1x==0?(p1y-p0y)/v0y:(p1x-p0x)/v0x;
- double r = v0x==0?(p0y-p1y)/v1y:(p0x-p1x)/v1x;
- boolean parallel = (v0x==v1x)&&(v0y==v1y);
- if (parallel) {
- if (t<0) return new Point2D.Double(p1x, p1y);
- if (r<0) return new Point2D.Double(p0x, p0y);
- return null;
- }
- return null;
- */
- }
-
- double nominator = -v0x*p0y + v0x*p1y + v0y*p0x - v0y*p1x;
- double r = nominator / denominator;
- if (r<0) return null;
- // XXX t on väärin
- //double t = -p0x + p1x + v1x*r;
- //if (t<0) return null;
-
- double x = p1x + r*v1x;
- double y = p1y + r*v1y;
- return new Point2D.Double(x, y);
- }
-
- public static int findNearestPoints(Point2D p0, Point2D v0, Point2D p1, Point2D v1, Point2D cp1, Point2D cp2)
- {
- return findNearestPoints(p0.getX(), p0.getY(), v0.getX(), v0.getY(), p1.getX(), p1.getY(), v1.getX(), v1.getY(), cp1, cp2);
- }
-
- public static int findNearestPoints(double p0x, double p0y, double v0x, double v0y, double p1x, double p1y, double v1x, double v1y, Point2D cp1, Point2D cp2)
- {
- int result = 0;
- double r = -( v1x*(p1x-p0x) + v1y*(p1y-p0y) ) / (v1x*v1x+v1y*v1y);
- double t = -( v0x*(p0x-p1x) + v0y*(p0y-p1y) ) / (v0x*v0x+v0y*v0y);
- if (t>0) {
- cp1.setLocation( p0x + v0x*t, p0y + v0y*t );
- result |= 1;
- }
- if (r>0) {
- cp2.setLocation( p1x + v1x*r, p1y + v1y*r );
- result |= 2;
- }
- return result;
- }
-
- public static double[] subdiv_takeLeft(double line[], double t)
- {
- int degree = getLineDegree(line);
-
- double p0x = line[0];
- double p0y = line[1];
- double p1x = line[2];
- double p1y = line[3];
- double p1x_ = p0x*(1-t) + p1x*t;
- double p1y_ = p0y*(1-t) + p1y*t;
- if (degree==1)
- return new double[] {p0x, p0y, p1x_, p1y_};
-
- double p2x = line[4];
- double p2y = line[5];
-
- 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;
- if (degree==2)
- return new double[] {p0x, p0y, p1x_, p1y_, p2x_, p2y_};
-
-
- double p3x = line[6];
- double p3y = line[7];
-
- 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;
-
- if (degree==3)
- return new double[] {p0x, p0y, p1x_, p1y_, p2x_, p2y_, p3x_, p3y_};
-
- return null;
- }
-
- public static double[] subdiv_takeRight(double line[], double t)
- {
- int degree = getLineDegree(line);
-
- double p0x = line[0];
- double p0y = line[1];
- double p1x = line[2];
- double p1y = line[3];
-
- double p0x_ = p0x*(1-t) + p1x*t;
- double p0y_ = p0y*(1-t) + p1y*t;
- if (degree==1)
- return new double[] {p0x_, p0y_, p1x, p1y};
-
- double p2x = line[4];
- double p2y = line[5];
-
- 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;
-
- if (degree==2)
- return new double[] {p2x_, p2y_, q1x, q1y, p2x, p2y};
-
- double p3x = line[6];
- double p3y = line[7];
-
- 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;
-
- if (degree==3)
- return new 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 double[] cropLine(double line[], double t0, double t1)
- {
- double temp[] = subdiv_takeLeft(line, t1);
- return subdiv_takeRight(temp, t0/t1);
- }
-
- @SuppressWarnings("unused")
- private static Point2D interpolateLine(double x0, double y0, double x1, double y1, double t)
- {
- double x = (x1-x0)*t + x0;
- double y = (y1-y0)*t + y0;
- return new Point2D.Double(x, y);
- }
-
- public static Path2D toPath(double lineSegment[])
- {
- int degree = getLineDegree(lineSegment);
- Path2D p = new Path2D.Double();
- p.moveTo(lineSegment[0], lineSegment[1]);
- if (degree==1)
- p.lineTo(lineSegment[2], lineSegment[3]);
- if (degree==2)
- p.quadTo(lineSegment[2], lineSegment[3], lineSegment[4], lineSegment[5]);
- if (degree==3)
- p.curveTo(lineSegment[2], lineSegment[3], lineSegment[4], lineSegment[5], lineSegment[6], lineSegment[7]);
- return p;
- }
-
- public static Path2D path(double ... pos)
- {
- assert(pos.length%2==0 && pos.length>=4);
- Path2D p = new Path2D.Double();
- p.moveTo(pos[0], pos[1]);
- for (int i=1; i=4);
-// Path2D p = new Path2D.Double();
-// p.moveTo(pos[0], pos[1]);
-// for (int i=1; i0)
- System.out.println(cp1+"\t"+cp2);
- else
- System.out.println("non posible");
-*/
- /*
- double bezier[] = new double[] {100,1,102,1,105,1};
- System.out.println(getLineLength(bezier, 2));
- for (int i=0; i<=10; i++)
- {
- double t = ((double)i)/10;
- System.out.println(GeometryUtils.getCompassDirection( getLineTangent(bezier, t) ));
- }*/
- }
-
-
-}
+/*******************************************************************************
+ * 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.geom.Path2D;
+import java.awt.geom.PathIterator;
+import java.awt.geom.Point2D;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Iterator;
+
+/**
+ * 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.
+ *
+ * @author Toni Kalajainen
+ */
+public class PathUtils {
+
+ /**
+ * 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(double lineSegment[], double t)
+ {
+ int degree = getLineDegree(lineSegment);
+ double x=0, y=0;
+ if (degree==1)
+ {
+ x = lineSegment[2*1+0] - lineSegment[2*0+0];
+ y = lineSegment[2*1+1] - lineSegment[2*0+1];
+ } else {
+ if (degree==2) {
+ x = 2*t*(lineSegment[2*0+0] - 2*lineSegment[2*1+0] + lineSegment[2*2+0]) + 2*(-lineSegment[2*0+0] + lineSegment[2*1+0]);
+ y = 2*t*(lineSegment[2*0+1] - 2*lineSegment[2*1+1] + lineSegment[2*2+1]) + 2*(-lineSegment[2*0+1] + lineSegment[2*1+1]);
+ } else if (degree==3) {
+ x = 3*(1-t)*(1-t)*(lineSegment[2*1+0]-lineSegment[2*0+0]) + 3*(lineSegment[2*2+0]-lineSegment[2*1+0])*2*t*(1-t) + 3*(lineSegment[2*3+0]-lineSegment[2*2+0])*t*t;
+ y = 3*(1-t)*(1-t)*(lineSegment[2*1+1]-lineSegment[2*0+1]) + 3*(lineSegment[2*2+1]-lineSegment[2*1+1])*2*t*(1-t) + 3*(lineSegment[2*3+1]-lineSegment[2*2+1])*t*t;
+ }
+ }
+ return new Point2D.Double(x, y);
+ }
+
+ /**
+ *
+ * @param lineSegment
+ * @param t 0..1
+ * @return
+ */
+ public static Point2D getLinePos(double lineSegment[], double t)
+ {
+ assert(lineSegment!=null);
+ int degree = getLineDegree(lineSegment);
+ double x=0, y=0;
+
+ if (degree==1) {
+ double p0x = lineSegment[0];
+ double p0y = lineSegment[1];
+ double p1x = lineSegment[2];
+ double p1y = lineSegment[3];
+
+ x = p0x*(1-t) + t*p1x;
+ y = p0y*(1-t) + t*p1y;
+ } else if (degree==2) {
+ double p0x = lineSegment[0];
+ double p0y = lineSegment[1];
+ double p1x = lineSegment[2];
+ double p1y = lineSegment[3];
+ double p2x = lineSegment[4];
+ double p2y = lineSegment[5];
+
+ 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 (degree==3) {
+ double p0x = lineSegment[0];
+ double p0y = lineSegment[1];
+ double p1x = lineSegment[2];
+ double p1y = lineSegment[3];
+ double p2x = lineSegment[4];
+ double p2y = lineSegment[5];
+ double p3x = lineSegment[6];
+ double p3y = lineSegment[7];
+
+ 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;
+ }
+
+ return new Point2D.Double(x, y);
+ }
+
+ public static double getLineLength(double lineSegment[])
+ {
+ int degree = getLineDegree(lineSegment);
+ if (degree==1) {
+ double dx = lineSegment[2]-lineSegment[0];
+ double dy = lineSegment[3]-lineSegment[1];
+ return Math.sqrt(dx*dx+dy*dy);
+ }
+
+ // Quick'n'dirty approximation
+ // TODO Replace with accurate value
+ double result = 0;
+ Point2D prevPos = getLinePos(lineSegment, 0.0);
+ for (int i=0; i<10; i++)
+ {
+ double t = (double)(i+1)/10;
+ Point2D pos = getLinePos(lineSegment, t);
+ result += pos.distance(prevPos);
+ prevPos.setLocation(pos);
+ }
+ return result;
+ /*
+ if (degree==2) {
+ double c2x = bezier[2*0+0]-2*bezier[2*1+0]+bezier[2*2+0];
+ double c2y = bezier[2*0+1]-2*bezier[2*1+1]+bezier[2*2+1];
+
+ double c1x = -2*bezier[2*0+0]+2*bezier[2*1+0];
+ double c1y = -2*bezier[2*0+1]+2*bezier[2*1+1];
+
+ double c0x = bezier[2*0+0];
+ double c0y = bezier[2*0+1];
+
+ double intg_x = c2x/3 + c1x/2 + c0x;
+ double intg_y = c2y/3 + c1y/2 + c0y;
+ System.out.println(intg_x +"\t" + intg_y);
+
+ return intg_x + intg_y;
+ }
+ return 0;
+ */
+ }
+
+ public static int getLineDegree(double lineSegment[])
+ {
+ assert(lineSegment.length==4 || lineSegment.length==6 || lineSegment.length==8);
+ return (lineSegment.length-2)/2;
+ }
+
+ /**
+ * Get first and last point & tangent of a path
+ * @param path
+ * @param begin
+ * @param beginDirection
+ * @param end
+ * @param endDirection
+ * @return true if pi contained atleast one line segment
+ */
+ public static boolean getPathArrows(PathIterator pi, Point2D begin, Point2D beginDirection, Point2D end, Point2D endDirection)
+ {
+ Iterator i = toLineIterator(pi);
+ double first[]=null, last[]=null;
+ while (i.hasNext()) {
+ double[] current = i.next();
+ if (first==null) first = current;
+ if (!i.hasNext()) last = current;
+ }
+ if (first==null || last==null) return false;
+ begin.setLocation( getLinePos(first, 0) );
+ beginDirection.setLocation( getLineTangent(first, 0) );
+ end.setLocation( getLinePos(last, 1) );
+ Point2D endTangent = getLineTangent(last, 1);
+ endDirection.setLocation( -endTangent.getX(), -endTangent.getY() );
+ return true;
+ }
+
+
+
+ /**
+ * Interpolate two paths
+ * @param path1
+ * @param path2
+ * @param t phase 0..1, 0==path1, 1==path2
+ * @return
+ */
+ public static Path2D interpolatePaths(PathIterator path1, PathIterator path2, double t)
+ {
+ Path2D result = new Path2D.Double();
+
+ ArrayList l1 = new ArrayList();
+ toLineSegments(path1, l1);
+ ArrayList l2 = new ArrayList();
+ toLineSegments(path2, l2);
+
+ if (l1.size()==l2.size())
+ {
+
+ }
+
+ result.append(path1, false);
+ return result;
+ }
+
+ public static double[] interpolateLineSegment(double l1[], double l2[], double t)
+ {
+ assert(t>=0 && t<=1);
+ if (t==0) return Arrays.copyOf(l1, l1.length);
+ if (t==1) return Arrays.copyOf(l1, l1.length);
+
+ int d1 = getLineDegree(l1);
+ int d2 = getLineDegree(l2);
+
+ if (d1==d2) {
+ double result [] = new double[l1.length];
+ for (int i=0; i toLineIterator(final PathIterator pi)
+ {
+ return new PathIteratorToSegmentIterator(pi);
+ }
+
+ public static void toLineSegments(PathIterator pi, Collection result)
+ {
+ Iterator i = toLineIterator(pi);
+ while (i.hasNext()) {
+ double[] segment = i.next();
+ result.add(segment);
+ }
+ }
+
+ private static class PathIteratorToSegmentIterator implements Iterator
+ {
+ final PathIterator pi;
+ double lineTo[] = new double[6];
+ double startPos[] = new double[2];
+ double from[] = new double[2];
+ int degree = 0;
+ PathIteratorToSegmentIterator(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 double[] next() {
+ if (degree==0) return null;
+ double result[] = new double[degree*2+2];
+ result[0] = from[0];
+ result[1] = from[1];
+ result[2] = lineTo[0];
+ result[3] = lineTo[1];
+ if (degree==2) {
+ result[4] = lineTo[2];
+ result[5] = lineTo[3];
+ } else if (degree==3) {
+ result[6] = lineTo[4];
+ result[7] = lineTo[5];
+ }
+ // 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 result;
+ }
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+
+
+
+
+
+ /**
+ * Finds intersection of two half-straight lines
+ * @param p0x
+ * @param p0y
+ * @param dir0
+ * @param p1x
+ * @param p1y
+ * @param dir1
+ * @return
+ */
+ public static Point2D findIntersection(double p0x, double p0y, double dir0, double p1x, double p1y, double dir1)
+ {
+ Point2D uv = new Point2D.Double();
+ GeometryUtils.toUnitVector(dir0, uv);
+ double v0x = uv.getX();
+ double v0y = uv.getY();
+ GeometryUtils.toUnitVector(dir1, uv);
+ double v1x = uv.getX();
+ double v1y = uv.getY();
+ return findIntersection(p0x, p0y, v0x, v0y, p1x, p1y, v1x, v1y);
+ }
+
+ /**
+ * Finds intersection of two half-straight lines
+ * @param p0
+ * @param v0
+ * @param p1
+ * @param v1
+ * @return
+ */
+ public static Point2D findIntersection(Point2D p0, Point2D v0, Point2D p1, Point2D v1)
+ {
+ double v0x = v0.getX();
+ double v0y = v0.getY();
+ double v1x = v1.getX();
+ double v1y = v1.getY();
+ double p0x = p0.getX();
+ double p0y = p0.getY();
+ double p1x = p1.getX();
+ double p1y = p1.getY();
+ return findIntersection(p0x, p0y, v0x, v0y, p1x, p1y, v1x, v1y);
+ }
+
+ /**
+ * Finds intersection of two half-straight lines
+ * @param p1
+ * @param v1 direction vector (unit vector)
+ * @param p2
+ * @param v2 direction vector (unit vector)
+ * @return
+ */
+ public static Point2D findIntersection(double p0x, double p0y, double v0x, double v0y, double p1x, double p1y, double v1x, double v1y)
+ {
+ if (p0x==p1x && p0y==p1y) return new Point2D.Double(p0x, p0y);
+ /*
+ i = Intersection point
+ i = p0 + t*v0 = p1 + r*v1;
+ */
+ double denominator = v0y*v1x - v0x*v1y;
+ // Straights are in same or opposite directions
+ if (denominator == 0) {
+ return null;
+ /*
+ // Do they overlap?
+ boolean overlap = v0x*(p1y-p0y) - v0y*(p1x-p1x) == 0;
+ if (!overlap) return null;
+ double t = v1x==0?(p1y-p0y)/v0y:(p1x-p0x)/v0x;
+ double r = v0x==0?(p0y-p1y)/v1y:(p0x-p1x)/v1x;
+ boolean parallel = (v0x==v1x)&&(v0y==v1y);
+ if (parallel) {
+ if (t<0) return new Point2D.Double(p1x, p1y);
+ if (r<0) return new Point2D.Double(p0x, p0y);
+ return null;
+ }
+ return null;
+ */
+ }
+
+ double nominator = -v0x*p0y + v0x*p1y + v0y*p0x - v0y*p1x;
+ double r = nominator / denominator;
+ if (r<0) return null;
+ // XXX t on väärin
+ //double t = -p0x + p1x + v1x*r;
+ //if (t<0) return null;
+
+ double x = p1x + r*v1x;
+ double y = p1y + r*v1y;
+ return new Point2D.Double(x, y);
+ }
+
+ public static int findNearestPoints(Point2D p0, Point2D v0, Point2D p1, Point2D v1, Point2D cp1, Point2D cp2)
+ {
+ return findNearestPoints(p0.getX(), p0.getY(), v0.getX(), v0.getY(), p1.getX(), p1.getY(), v1.getX(), v1.getY(), cp1, cp2);
+ }
+
+ public static int findNearestPoints(double p0x, double p0y, double v0x, double v0y, double p1x, double p1y, double v1x, double v1y, Point2D cp1, Point2D cp2)
+ {
+ int result = 0;
+ double r = -( v1x*(p1x-p0x) + v1y*(p1y-p0y) ) / (v1x*v1x+v1y*v1y);
+ double t = -( v0x*(p0x-p1x) + v0y*(p0y-p1y) ) / (v0x*v0x+v0y*v0y);
+ if (t>0) {
+ cp1.setLocation( p0x + v0x*t, p0y + v0y*t );
+ result |= 1;
+ }
+ if (r>0) {
+ cp2.setLocation( p1x + v1x*r, p1y + v1y*r );
+ result |= 2;
+ }
+ return result;
+ }
+
+ public static double[] subdiv_takeLeft(double line[], double t)
+ {
+ int degree = getLineDegree(line);
+
+ double p0x = line[0];
+ double p0y = line[1];
+ double p1x = line[2];
+ double p1y = line[3];
+ double p1x_ = p0x*(1-t) + p1x*t;
+ double p1y_ = p0y*(1-t) + p1y*t;
+ if (degree==1)
+ return new double[] {p0x, p0y, p1x_, p1y_};
+
+ double p2x = line[4];
+ double p2y = line[5];
+
+ 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;
+ if (degree==2)
+ return new double[] {p0x, p0y, p1x_, p1y_, p2x_, p2y_};
+
+
+ double p3x = line[6];
+ double p3y = line[7];
+
+ 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;
+
+ if (degree==3)
+ return new double[] {p0x, p0y, p1x_, p1y_, p2x_, p2y_, p3x_, p3y_};
+
+ return null;
+ }
+
+ public static double[] subdiv_takeRight(double line[], double t)
+ {
+ int degree = getLineDegree(line);
+
+ double p0x = line[0];
+ double p0y = line[1];
+ double p1x = line[2];
+ double p1y = line[3];
+
+ double p0x_ = p0x*(1-t) + p1x*t;
+ double p0y_ = p0y*(1-t) + p1y*t;
+ if (degree==1)
+ return new double[] {p0x_, p0y_, p1x, p1y};
+
+ double p2x = line[4];
+ double p2y = line[5];
+
+ 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;
+
+ if (degree==2)
+ return new double[] {p2x_, p2y_, q1x, q1y, p2x, p2y};
+
+ double p3x = line[6];
+ double p3y = line[7];
+
+ 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;
+
+ if (degree==3)
+ return new 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 double[] cropLine(double line[], double t0, double t1)
+ {
+ double temp[] = subdiv_takeLeft(line, t1);
+ return subdiv_takeRight(temp, t0/t1);
+ }
+
+ @SuppressWarnings("unused")
+ private static Point2D interpolateLine(double x0, double y0, double x1, double y1, double t)
+ {
+ double x = (x1-x0)*t + x0;
+ double y = (y1-y0)*t + y0;
+ return new Point2D.Double(x, y);
+ }
+
+ public static Path2D toPath(double lineSegment[])
+ {
+ int degree = getLineDegree(lineSegment);
+ Path2D p = new Path2D.Double();
+ p.moveTo(lineSegment[0], lineSegment[1]);
+ if (degree==1)
+ p.lineTo(lineSegment[2], lineSegment[3]);
+ if (degree==2)
+ p.quadTo(lineSegment[2], lineSegment[3], lineSegment[4], lineSegment[5]);
+ if (degree==3)
+ p.curveTo(lineSegment[2], lineSegment[3], lineSegment[4], lineSegment[5], lineSegment[6], lineSegment[7]);
+ return p;
+ }
+
+ public static Path2D path(double ... pos)
+ {
+ assert(pos.length%2==0 && pos.length>=4);
+ Path2D p = new Path2D.Double();
+ p.moveTo(pos[0], pos[1]);
+ for (int i=1; i=4);
+// Path2D p = new Path2D.Double();
+// p.moveTo(pos[0], pos[1]);
+// for (int i=1; i0)
+ System.out.println(cp1+"\t"+cp2);
+ else
+ System.out.println("non posible");
+*/
+ /*
+ double bezier[] = new double[] {100,1,102,1,105,1};
+ System.out.println(getLineLength(bezier, 2));
+ for (int i=0; i<=10; i++)
+ {
+ double t = ((double)i)/10;
+ System.out.println(GeometryUtils.getCompassDirection( getLineTangent(bezier, t) ));
+ }*/
+ }
+
+
+}