]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.g2d/src/org/simantics/g2d/utils/PathUtils.java
Fixed all line endings of the repository
[simantics/platform.git] / bundles / org.simantics.g2d / src / org / simantics / g2d / utils / PathUtils.java
index 13d2dd9b2b2671aa8810c8af1515f400f9fa50e9..7ff95ed013d2236c5f63a1fe7c7a9cf0f9d83baa 100644 (file)
-/*******************************************************************************\r
- * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
- * in Industry THTH ry.\r
- * All rights reserved. This program and the accompanying materials\r
- * are made available under the terms of the Eclipse Public License v1.0\r
- * which accompanies this distribution, and is available at\r
- * http://www.eclipse.org/legal/epl-v10.html\r
- *\r
- * Contributors:\r
- *     VTT Technical Research Centre of Finland - initial API and implementation\r
- *******************************************************************************/\r
-package org.simantics.g2d.utils;\r
-\r
-import java.awt.geom.Path2D;\r
-import java.awt.geom.PathIterator;\r
-import java.awt.geom.Point2D;\r
-import java.util.ArrayList;\r
-import java.util.Arrays;\r
-import java.util.Collection;\r
-import java.util.Iterator;\r
-\r
-/**\r
- * Path Utils.\r
- * <p>\r
- * A line segment (linear, quadratic or cubic bezier) is described\r
- * with a double array. The length of the array describes its degree (4,6,8).\r
- * The first 2 elements define start point and last 2 the end point.\r
- * Points in the middle are bezier control points.\r
- * \r
- * @author Toni Kalajainen\r
- */\r
-public class PathUtils {\r
-\r
-       /**\r
-        * Get tangent of an bezier\r
-        * @param lineSegment bezier of n degrees\r
-        * @param degree 1..3 \r
-        * @param t 0..1\r
-        * @return unit vector\r
-        */\r
-       public static Point2D getLineTangent(double lineSegment[], double t)\r
-       {\r
-               int degree = getLineDegree(lineSegment);\r
-               double x=0, y=0;\r
-               if (degree==1)\r
-               {\r
-                       x = lineSegment[2*1+0] - lineSegment[2*0+0];\r
-                       y = lineSegment[2*1+1] - lineSegment[2*0+1];\r
-               } else {                \r
-                       if (degree==2) {\r
-                               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]);\r
-                               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]);\r
-                       } else if (degree==3) {\r
-                               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;\r
-                               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;\r
-                       }\r
-               }               \r
-               return new Point2D.Double(x, y);\r
-       }\r
-       \r
-       /**\r
-        * \r
-        * @param lineSegment\r
-        * @param t 0..1\r
-        * @return\r
-        */\r
-       public static Point2D getLinePos(double lineSegment[], double t)\r
-       {               \r
-               assert(lineSegment!=null);\r
-               int degree = getLineDegree(lineSegment);\r
-               double x=0, y=0;\r
-               \r
-               if (degree==1) {\r
-                       double p0x = lineSegment[0];\r
-                       double p0y = lineSegment[1];\r
-                       double p1x = lineSegment[2];\r
-                       double p1y = lineSegment[3];\r
-                       \r
-                       x = p0x*(1-t) + t*p1x;\r
-                       y = p0y*(1-t) + t*p1y;\r
-               } else if (degree==2) {\r
-                       double p0x = lineSegment[0];\r
-                       double p0y = lineSegment[1];\r
-                       double p1x = lineSegment[2];\r
-                       double p1y = lineSegment[3];\r
-                       double p2x = lineSegment[4];\r
-                       double p2y = lineSegment[5];                    \r
-                       \r
-                       double c2x = p0x-2*p1x+p2x;\r
-                       double c2y = p0y-2*p1y+p2y;\r
-                       \r
-                       double c1x = -2*p0x+2*p1x;\r
-                       double c1y = -2*p0y+2*p1y;\r
-                       \r
-                       double c0x = p0x;\r
-                       double c0y = p0y;\r
-                       \r
-                       x = t*t*c2x+t*c1x+c0x;\r
-                       y = t*t*c2y+t*c1y+c0y;\r
-               } else if (degree==3) {\r
-                       double p0x = lineSegment[0];\r
-                       double p0y = lineSegment[1];\r
-                       double p1x = lineSegment[2];\r
-                       double p1y = lineSegment[3];\r
-                       double p2x = lineSegment[4];\r
-                       double p2y = lineSegment[5];                    \r
-                       double p3x = lineSegment[6];\r
-                       double p3y = lineSegment[7];                    \r
-\r
-                       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
-                       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
-               }\r
-               \r
-               return new Point2D.Double(x, y);\r
-       }\r
-       \r
-       public static double getLineLength(double lineSegment[])\r
-       {\r
-               int degree = getLineDegree(lineSegment);                \r
-               if (degree==1) {\r
-                       double dx = lineSegment[2]-lineSegment[0];\r
-                       double dy = lineSegment[3]-lineSegment[1];\r
-                       return Math.sqrt(dx*dx+dy*dy);\r
-               }\r
-               \r
-               // Quick'n'dirty approximation \r
-               // TODO Replace with accurate value\r
-               double result = 0;\r
-               Point2D prevPos = getLinePos(lineSegment, 0.0); \r
-               for (int i=0; i<10; i++)\r
-               {\r
-                       double t = (double)(i+1)/10;\r
-                       Point2D pos = getLinePos(lineSegment, t);\r
-                       result += pos.distance(prevPos);\r
-                       prevPos.setLocation(pos);\r
-               }\r
-               return result;\r
-               /*\r
-               if (degree==2) {\r
-                       double c2x = bezier[2*0+0]-2*bezier[2*1+0]+bezier[2*2+0];\r
-                       double c2y = bezier[2*0+1]-2*bezier[2*1+1]+bezier[2*2+1];\r
-                       \r
-                       double c1x = -2*bezier[2*0+0]+2*bezier[2*1+0];\r
-                       double c1y = -2*bezier[2*0+1]+2*bezier[2*1+1];\r
-                       \r
-                       double c0x = bezier[2*0+0];\r
-                       double c0y = bezier[2*0+1];\r
-                       \r
-                       double intg_x = c2x/3 + c1x/2 + c0x;\r
-                       double intg_y = c2y/3 + c1y/2 + c0y;\r
-                       System.out.println(intg_x +"\t" + intg_y);\r
-                       \r
-                       return intg_x + intg_y;\r
-               }\r
-               return 0;\r
-               */\r
-       }\r
-       \r
-       public static int getLineDegree(double lineSegment[])\r
-       {\r
-               assert(lineSegment.length==4 || lineSegment.length==6 || lineSegment.length==8);\r
-               return (lineSegment.length-2)/2;\r
-       }\r
-       \r
-       /**\r
-        * Get first and last point & tangent of a path\r
-        * @param path\r
-        * @param begin\r
-        * @param beginDirection\r
-        * @param end\r
-        * @param endDirection\r
-        * @return true if pi contained atleast one line segment\r
-        */\r
-       public static boolean getPathArrows(PathIterator pi, Point2D begin, Point2D beginDirection, Point2D end, Point2D endDirection)\r
-       {\r
-               Iterator<double[]> i = toLineIterator(pi);\r
-               double first[]=null, last[]=null;\r
-               while (i.hasNext()) {\r
-                       double[] current = i.next();\r
-                       if (first==null) first = current;\r
-                       if (!i.hasNext()) last = current;\r
-               }\r
-               if (first==null || last==null) return false;\r
-               begin.setLocation( getLinePos(first, 0) );\r
-               beginDirection.setLocation( getLineTangent(first, 0) );\r
-               end.setLocation( getLinePos(last, 1) );\r
-               Point2D endTangent = getLineTangent(last, 1);\r
-               endDirection.setLocation( -endTangent.getX(), -endTangent.getY() );\r
-               return true;\r
-       }\r
-\r
-       \r
-       \r
-       /**\r
-        * Interpolate two paths\r
-        * @param path1\r
-        * @param path2\r
-        * @param t phase 0..1, 0==path1, 1==path2\r
-        * @return\r
-        */\r
-       public static Path2D interpolatePaths(PathIterator path1, PathIterator path2, double t)\r
-       {\r
-               Path2D result = new Path2D.Double();\r
-                               \r
-               ArrayList<double[]> l1 = new ArrayList<double[]>(); \r
-               toLineSegments(path1, l1);\r
-               ArrayList<double[]> l2 = new ArrayList<double[]>(); \r
-               toLineSegments(path2, l2);\r
-               \r
-               if (l1.size()==l2.size())\r
-               {\r
-                       \r
-               }\r
-               \r
-               result.append(path1, false);\r
-               return result;\r
-       }\r
-       \r
-       public static double[] interpolateLineSegment(double l1[], double l2[], double t)\r
-       {\r
-               assert(t>=0 && t<=1);\r
-               if (t==0) return Arrays.copyOf(l1, l1.length);\r
-               if (t==1) return Arrays.copyOf(l1, l1.length);\r
-               \r
-               int d1 = getLineDegree(l1);\r
-               int d2 = getLineDegree(l2);\r
-               \r
-               if (d1==d2) {\r
-                       double result [] = new double[l1.length];               \r
-                       for (int i=0; i<l1.length; i++)                 \r
-                               result[i] = l2[i]*t + l1[i]*(1-t); \r
-                       return result;\r
-               }\r
-               \r
-               if (d2<d1) {\r
-                       int d_ = d1;\r
-                       d1 = d2;\r
-                       d2 = d_;\r
-                       double[] l_ = l1;\r
-                       l1 = l2;\r
-                       l2 = l_;\r
-                       t = 1-t;\r
-               }\r
-               \r
-               // d1 < d2\r
-               double res[] = new double[l2.length];\r
-               \r
-               if (d1==1 && d2==2) {\r
-                       res[0] = l1[0]*(1-t) + l2[0]*t;\r
-                       res[1] = l1[1]*(1-t) + l2[1]*t;\r
-                       res[4] = l1[2]*(1-t) + l2[4]*t;\r
-                       res[5] = l1[3]*(1-t) + l2[5]*t;\r
-                       double cx  = (l1[0]+l1[2])/2;\r
-                       double cy  = (l1[0]+l1[2])/2;\r
-                       res[2] = cx*(1-t) + l2[2]*t;\r
-                       res[3] = cy*(1-t) + l2[3]*t;                    \r
-               }\r
-\r
-               if (d1==1 && d2==3) {\r
-                       res[0] = l1[0]*(1-t) + l2[0]*t;\r
-                       res[1] = l1[1]*(1-t) + l2[1]*t;\r
-                       res[4] = l1[2]*(1-t) + l2[4]*t;\r
-                       res[5] = l1[3]*(1-t) + l2[5]*t;\r
-                       double cx  = (l1[0]+l1[2])/2;\r
-                       double cy  = (l1[0]+l1[2])/2;\r
-                       res[2] = cx*(1-t) + l2[2]*t;\r
-                       res[3] = cy*(1-t) + l2[3]*t;                    \r
-                       res[4] = cx*(1-t) + l2[4]*t;\r
-                       res[5] = cy*(1-t) + l2[5]*t;                    \r
-               }\r
-               \r
-               if (d1==2 && d2==3) {\r
-                       res[0] = l1[0]*(1-t) + l2[0]*t;\r
-                       res[1] = l1[1]*(1-t) + l2[1]*t;\r
-                       res[2] = l1[2]*(1-t) + l2[2]*t;\r
-                       res[3] = l1[3]*(1-t) + l2[3]*t;                 \r
-                       res[4] = l1[2]*(1-t) + l2[4]*t;\r
-                       res[5] = l1[3]*(1-t) + l2[5]*t;                 \r
-                       res[6] = l1[4]*(1-t) + l2[6]*t;\r
-                       res[7] = l1[5]*(1-t) + l2[7]*t;\r
-               }                                       \r
-               \r
-               return res;\r
-       }\r
-       \r
-       /**\r
-        * Returns an iterator that constructs line segments by traversing a path iterator\r
-        * @param pi path iterator\r
-        * @return line segment iterator\r
-        */\r
-       public static Iterator<double[]> toLineIterator(final PathIterator pi)\r
-       {\r
-               return new PathIteratorToSegmentIterator(pi);\r
-       }\r
-       \r
-       public static void toLineSegments(PathIterator pi, Collection<double[]> result)\r
-       {\r
-               Iterator<double[]> i = toLineIterator(pi);\r
-               while (i.hasNext()) {\r
-                       double[] segment = i.next();\r
-                       result.add(segment);\r
-               }\r
-       }\r
-       \r
-       private static class PathIteratorToSegmentIterator implements Iterator<double[]>\r
-       {\r
-               final PathIterator pi;\r
-               double  lineTo[] = new double[6];\r
-               double  startPos[] = new double[2];\r
-               double  from[] = new double[2];\r
-               int             degree = 0;\r
-               PathIteratorToSegmentIterator(PathIterator pi) {\r
-                       this.pi = pi;\r
-                       while(!pi.isDone()) {\r
-                               int type = pi.currentSegment(lineTo);\r
-                               pi.next();\r
-                               if (type == PathIterator.SEG_MOVETO) {\r
-                                       startPos[0] = from[0] = lineTo[0];\r
-                                       startPos[1] = from[1] = lineTo[1];\r
-                               }\r
-                               if (type == PathIterator.SEG_CLOSE) {\r
-                                       type = PathIterator.SEG_LINETO;\r
-                                       lineTo[0] = startPos[0];\r
-                                       lineTo[1] = startPos[1];\r
-                               }\r
-                               if (type>=PathIterator.SEG_LINETO && type<=PathIterator.SEG_CUBICTO)\r
-                               {\r
-                                       degree = type;\r
-                                       // from == xx\r
-                                       break;\r
-                               }\r
-                       }\r
-               }               \r
-               @Override\r
-               public boolean hasNext() {\r
-                       return degree>0;\r
-               }\r
-               @Override\r
-               public double[] next() {\r
-                       if (degree==0) return null;\r
-                       double result[] = new double[degree*2+2]; \r
-                       result[0] = from[0];\r
-                       result[1] = from[1];\r
-                       result[2] = lineTo[0];\r
-                       result[3] = lineTo[1];\r
-                       if (degree==2) {\r
-                               result[4] = lineTo[2];\r
-                               result[5] = lineTo[3];\r
-                       } else if (degree==3) {\r
-                               result[6] = lineTo[4];\r
-                               result[7] = lineTo[5];\r
-                       }\r
-                       // traverse path iterator until end or until next segment is known\r
-                       degree = 0;\r
-                       from[0] = lineTo[0];\r
-                       from[1] = lineTo[1];\r
-                       while(!pi.isDone()) {\r
-                               int type = pi.currentSegment(lineTo);\r
-                               pi.next();\r
-                               if (type == PathIterator.SEG_MOVETO) {\r
-                                       startPos[0] = from[0] = lineTo[0];\r
-                                       startPos[1] = from[1] = lineTo[1];\r
-                               }\r
-                               if (type == PathIterator.SEG_CLOSE) {\r
-                                       type = PathIterator.SEG_LINETO;\r
-                                       lineTo[0] = startPos[0];\r
-                                       lineTo[1] = startPos[1];\r
-                               }\r
-                               if (type>=PathIterator.SEG_LINETO && type<=PathIterator.SEG_CUBICTO)\r
-                               {\r
-                                       degree = type;\r
-                                       break;\r
-                               }\r
-                       }\r
-                       return result;\r
-               }\r
-               @Override\r
-               public void remove() {\r
-                       throw new UnsupportedOperationException();\r
-               }\r
-       }\r
-\r
-       \r
-       \r
-       \r
-       \r
-       \r
-       /**\r
-        * Finds intersection of two half-straight lines\r
-        * @param p0x\r
-        * @param p0y\r
-        * @param dir0\r
-        * @param p1x\r
-        * @param p1y\r
-        * @param dir1\r
-        * @return\r
-        */\r
-       public static Point2D findIntersection(double p0x, double p0y, double dir0, double p1x, double p1y, double dir1)\r
-       {\r
-               Point2D uv = new Point2D.Double();\r
-               GeometryUtils.toUnitVector(dir0, uv);\r
-               double v0x = uv.getX();\r
-               double v0y = uv.getY();\r
-               GeometryUtils.toUnitVector(dir1, uv);\r
-               double v1x = uv.getX();\r
-               double v1y = uv.getY();\r
-               return findIntersection(p0x, p0y, v0x, v0y, p1x, p1y, v1x, v1y);\r
-       }\r
-       \r
-       /**\r
-        * Finds intersection of two half-straight lines\r
-        * @param p0\r
-        * @param v0\r
-        * @param p1\r
-        * @param v1\r
-        * @return\r
-        */\r
-       public static Point2D findIntersection(Point2D p0, Point2D v0, Point2D p1, Point2D v1)\r
-       {\r
-               double v0x = v0.getX();\r
-               double v0y = v0.getY();\r
-               double v1x = v1.getX();\r
-               double v1y = v1.getY();\r
-               double p0x = p0.getX();\r
-               double p0y = p0.getY();\r
-               double p1x = p1.getX();\r
-               double p1y = p1.getY();         \r
-               return findIntersection(p0x, p0y, v0x, v0y, p1x, p1y, v1x, v1y);\r
-       }\r
-       \r
-       /**\r
-        * Finds intersection of two half-straight lines\r
-        * @param p1\r
-        * @param v1 direction vector (unit vector)\r
-        * @param p2\r
-        * @param v2 direction vector (unit vector)\r
-        * @return\r
-        */\r
-       public static Point2D findIntersection(double p0x, double p0y, double v0x, double v0y, double p1x, double p1y, double v1x, double v1y)\r
-       {\r
-               if (p0x==p1x && p0y==p1y) return new Point2D.Double(p0x, p0y);\r
-               /*\r
-                  i = Intersection point                 \r
-                  i = p0 + t*v0 = p1 + r*v1;\r
-                */                             \r
-               double denominator      = v0y*v1x - v0x*v1y;\r
-               // Straights are in same or opposite directions\r
-               if (denominator == 0) {\r
-                       return null;\r
-                       /*\r
-                       // Do they overlap?\r
-                       boolean overlap         = v0x*(p1y-p0y) - v0y*(p1x-p1x) == 0;\r
-                       if (!overlap) return null;\r
-                       double t = v1x==0?(p1y-p0y)/v0y:(p1x-p0x)/v0x;\r
-                       double r = v0x==0?(p0y-p1y)/v1y:(p0x-p1x)/v1x;\r
-                       boolean parallel        = (v0x==v1x)&&(v0y==v1y);\r
-                       if (parallel) {\r
-                               if (t<0) return new Point2D.Double(p1x, p1y);\r
-                               if (r<0) return new Point2D.Double(p0x, p0y);\r
-                               return null;\r
-                       }\r
-                       return null;\r
-                       */\r
-               }\r
-               \r
-               double nominator        = -v0x*p0y + v0x*p1y + v0y*p0x - v0y*p1x;\r
-               double r                        = nominator / denominator;\r
-               if (r<0) return null;\r
-               // XXX t on väärin\r
-               //double t                      = -p0x + p1x + v1x*r;\r
-               //if (t<0) return null;\r
-               \r
-               double x                        = p1x + r*v1x;\r
-               double y                        = p1y + r*v1y;\r
-               return new Point2D.Double(x, y);\r
-       }\r
-\r
-       public static int findNearestPoints(Point2D p0, Point2D v0, Point2D p1, Point2D v1, Point2D cp1, Point2D cp2)\r
-       {\r
-               return findNearestPoints(p0.getX(), p0.getY(), v0.getX(), v0.getY(), p1.getX(), p1.getY(), v1.getX(), v1.getY(), cp1, cp2);\r
-       }\r
-       \r
-       public static int findNearestPoints(double p0x, double p0y, double v0x, double v0y, double p1x, double p1y, double v1x, double v1y, Point2D cp1, Point2D cp2)\r
-       {\r
-               int result = 0;\r
-               double r = -( v1x*(p1x-p0x) + v1y*(p1y-p0y) ) / (v1x*v1x+v1y*v1y);\r
-               double t = -( v0x*(p0x-p1x) + v0y*(p0y-p1y) ) / (v0x*v0x+v0y*v0y);\r
-               if (t>0) {\r
-                       cp1.setLocation( p0x + v0x*t, p0y + v0y*t );\r
-                       result |= 1;\r
-               }\r
-               if (r>0) {\r
-                       cp2.setLocation( p1x + v1x*r, p1y + v1y*r );\r
-                       result |= 2;\r
-               }\r
-               return result;\r
-       }\r
-       \r
-       public static double[] subdiv_takeLeft(double line[], double t)\r
-       {\r
-               int     degree  = getLineDegree(line); \r
-               \r
-               double p0x = line[0];\r
-               double p0y = line[1];\r
-               double p1x = line[2];\r
-               double p1y = line[3];\r
-               double p1x_  = p0x*(1-t) + p1x*t;\r
-               double p1y_  = p0y*(1-t) + p1y*t;\r
-               if (degree==1)                  \r
-                       return new double[] {p0x, p0y, p1x_, p1y_};\r
-\r
-               double p2x = line[4];\r
-               double p2y = line[5];                   \r
-\r
-               double q0x = p0x*(1-t) + p1x*t;\r
-               double q0y = p0y*(1-t) + p1y*t;\r
-\r
-               double q1x = p1x*(1-t) + p2x*t;\r
-               double q1y = p1y*(1-t) + p2y*t;\r
-               \r
-               double p2x_ = q0x*(1-t) + q1x*t;\r
-               double p2y_ = q0y*(1-t) + q1y*t;\r
-               if (degree==2)          \r
-                       return new double[] {p0x, p0y, p1x_, p1y_, p2x_, p2y_};                 \r
-               \r
-               \r
-               double p3x = line[6];\r
-               double p3y = line[7];\r
-               \r
-               double q2x = p2x*(1-t) + p3x*t;\r
-               double q2y = p2y*(1-t) + p3y*t;\r
-\r
-               double r0x = q0x*(1-t) + q1x*t;\r
-               double r0y = q0y*(1-t) + q1y*t;\r
-                       \r
-               double r1x = q1x*(1-t) + q2x*t;\r
-               double r1y = q1y*(1-t) + q2y*t;\r
-                       \r
-               double p3x_  = r0x*(1-t) + r1x*t;\r
-               double p3y_  = r0y*(1-t) + r1y*t;\r
-\r
-               if (degree==3) \r
-                       return new double[] {p0x, p0y, p1x_, p1y_, p2x_, p2y_, p3x_, p3y_};\r
-               \r
-               return null;\r
-       }\r
-       \r
-       public static double[] subdiv_takeRight(double line[], double t)\r
-       {\r
-               int     degree  = getLineDegree(line); \r
-               \r
-               double p0x = line[0];\r
-               double p0y = line[1];\r
-               double p1x = line[2];\r
-               double p1y = line[3];\r
-\r
-               double p0x_  = p0x*(1-t) + p1x*t;\r
-               double p0y_  = p0y*(1-t) + p1y*t;\r
-               if (degree==1)                  \r
-                       return new double[] {p0x_, p0y_, p1x, p1y};\r
-               \r
-               double p2x = line[4];\r
-               double p2y = line[5];                   \r
-\r
-               double q0x = p0x*(1-t) + p1x*t;\r
-               double q0y = p0y*(1-t) + p1y*t;\r
-\r
-               double q1x = p1x*(1-t) + p2x*t;\r
-               double q1y = p1y*(1-t) + p2y*t;\r
-               \r
-               double p2x_ = q0x*(1-t) + q1x*t;\r
-               double p2y_ = q0y*(1-t) + q1y*t;        \r
-\r
-               if (degree==2)          \r
-                       return new double[] {p2x_, p2y_, q1x, q1y, p2x, p2y};                   \r
-                               \r
-               double p3x = line[6];\r
-               double p3y = line[7];\r
-               \r
-               double q2x = p2x*(1-t) + p3x*t;\r
-               double q2y = p2y*(1-t) + p3y*t;\r
-\r
-               double r0x = q0x*(1-t) + q1x*t;\r
-               double r0y = q0y*(1-t) + q1y*t;\r
-                       \r
-               double r1x = q1x*(1-t) + q2x*t;\r
-               double r1y = q1y*(1-t) + q2y*t;\r
-                       \r
-               double p3x_  = r0x*(1-t) + r1x*t;\r
-               double p3y_  = r0y*(1-t) + r1y*t;\r
-\r
-               if (degree==3) \r
-                       return new double[] {p3x_, p3y_, r1x, r1y, q2x, q2y, p3x, p3y};\r
-               \r
-               return null;\r
-       }\r
-       \r
-\r
-\r
-       /**\r
-        * Crops line segment into a smaller line segment\r
-        * @param line line segment\r
-        * @param t0 begin t\r
-        * @param t1 end t\r
-        * @return cropped line segment\r
-        */\r
-       public static double[] cropLine(double line[], double t0, double t1)\r
-       {\r
-               double temp[] = subdiv_takeLeft(line, t1);\r
-               return subdiv_takeRight(temp, t0/t1);\r
-       }\r
-       \r
-       @SuppressWarnings("unused")\r
-       private static Point2D interpolateLine(double x0, double y0, double x1, double y1, double t)\r
-       {\r
-               double x = (x1-x0)*t + x0;\r
-               double y = (y1-y0)*t + y0;\r
-               return new Point2D.Double(x, y);\r
-       }\r
-       \r
-       public static Path2D toPath(double lineSegment[])\r
-       {\r
-               int     degree  = getLineDegree(lineSegment); \r
-               Path2D  p = new Path2D.Double();\r
-               p.moveTo(lineSegment[0], lineSegment[1]);\r
-               if (degree==1)\r
-                       p.lineTo(lineSegment[2], lineSegment[3]);\r
-               if (degree==2)\r
-                       p.quadTo(lineSegment[2], lineSegment[3], lineSegment[4], lineSegment[5]);\r
-               if (degree==3)\r
-                       p.curveTo(lineSegment[2], lineSegment[3], lineSegment[4], lineSegment[5], lineSegment[6], lineSegment[7]);              \r
-               return p;\r
-       }\r
-\r
-       public static Path2D path(double ... pos)\r
-       {\r
-               assert(pos.length%2==0 && pos.length>=4);\r
-               Path2D p = new Path2D.Double();\r
-               p.moveTo(pos[0], pos[1]);\r
-               for (int i=1; i<pos.length/2; i++)\r
-               {\r
-                       p.lineTo(pos[i*2], pos[i*2+1]);\r
-               }\r
-               return p;\r
-       }\r
-\r
-       /**\r
-        * Create 3rd degree path. Every second point is a control point.\r
-        * @param positions\r
-        * @return\r
-        */\r
-//     public static Path2D closePath3rdDeg(double ... pos)\r
-//     {\r
-//             assert(pos.length%2==0 && pos.length>=4);\r
-//             Path2D p = new Path2D.Double();\r
-//             p.moveTo(pos[0], pos[1]);\r
-//             for (int i=1; i<pos.length/2; i++)\r
-//             {\r
-//                     p.lineTo(pos[i*2], pos[i*2+1]);\r
-//             }\r
-//             return p;\r
-//     }\r
-//     \r
-       \r
-       public static Path2D closedPath(double ... pos)\r
-       {\r
-               Path2D p = path(pos);\r
-               p.closePath();\r
-               return p;\r
-       }       \r
-       \r
-       public static void main(String[] args) {\r
-               // test crop line\r
-               double[] cubic = new double[] {0,0, 0, -1, 3, -1, 3,0};\r
-               double[] cropped = cropLine(cubic, 0.2, 1);\r
-               System.out.println(Arrays.toString(cropped));\r
-               System.out.println(getLinePos(cubic, 0.5));\r
-               System.out.println(getLinePos(cropped, 0.375));\r
-               /*              \r
-                               Path2D p = new Path2D.Double();\r
-                               p.moveTo(4, 1);\r
-                               p.quadTo(6,1,6,3);\r
-                               p.quadTo(6,5,4,5);\r
-                               p.quadTo(2,5,2,3);\r
-                               p.quadTo(2,1,4,1);\r
-                               PathIterator pi = p.getPathIterator(null);\r
-                               double dada[] = new double[6];\r
-                               while (!pi.isDone()) {\r
-                                       Arrays.fill(dada, 0);\r
-                                       int type = pi.currentSegment(dada);\r
-                                       System.out.println(type+":\t"+Arrays.toString(dada));\r
-                                       pi.next();\r
-                               }*/\r
-                               \r
-                               assert(findIntersection(0,0,90,  10,1,270+45)!=null);\r
-                               assert(findIntersection(0,0,90,  1,1,89)!=null);\r
-                               assert(findIntersection(0,0,90,  1,1,270+45)==null);\r
-                               //System.out.println(findIntersection(0,0,270,  10,0,270));\r
-                               //System.out.println(findIntersection(0,0,90,  10,-10,180));            \r
-                               /*\r
-                               Point2D cp1 = new Point2D.Double();\r
-                               Point2D cp2 = new Point2D.Double();\r
-                               int i = findNearestPoints(0, 0, 0, 1, 2, 10, 0, -1, cp1, cp2);\r
-                               if (i>0)\r
-                                       System.out.println(cp1+"\t"+cp2);\r
-                               else\r
-                                       System.out.println("non posible");\r
-*/\r
-                               /*\r
-                               double bezier[] = new double[] {100,1,102,1,105,1};  \r
-                               System.out.println(getLineLength(bezier, 2));\r
-                               for (int i=0; i<=10; i++)\r
-                               {\r
-                                       double t = ((double)i)/10;\r
-                                       System.out.println(GeometryUtils.getCompassDirection( getLineTangent(bezier, t) ));                     \r
-                               }*/\r
-                       }\r
-                       \r
-       \r
-}\r
+/*******************************************************************************
+ * 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.
+ * <p>
+ * 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<double[]> 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<double[]> l1 = new ArrayList<double[]>(); 
+               toLineSegments(path1, l1);
+               ArrayList<double[]> l2 = new ArrayList<double[]>(); 
+               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<l1.length; i++)                 
+                               result[i] = l2[i]*t + l1[i]*(1-t); 
+                       return result;
+               }
+               
+               if (d2<d1) {
+                       int d_ = d1;
+                       d1 = d2;
+                       d2 = d_;
+                       double[] l_ = l1;
+                       l1 = l2;
+                       l2 = l_;
+                       t = 1-t;
+               }
+               
+               // d1 < d2
+               double res[] = new double[l2.length];
+               
+               if (d1==1 && d2==2) {
+                       res[0] = l1[0]*(1-t) + l2[0]*t;
+                       res[1] = l1[1]*(1-t) + l2[1]*t;
+                       res[4] = l1[2]*(1-t) + l2[4]*t;
+                       res[5] = l1[3]*(1-t) + l2[5]*t;
+                       double cx  = (l1[0]+l1[2])/2;
+                       double cy  = (l1[0]+l1[2])/2;
+                       res[2] = cx*(1-t) + l2[2]*t;
+                       res[3] = cy*(1-t) + l2[3]*t;                    
+               }
+
+               if (d1==1 && d2==3) {
+                       res[0] = l1[0]*(1-t) + l2[0]*t;
+                       res[1] = l1[1]*(1-t) + l2[1]*t;
+                       res[4] = l1[2]*(1-t) + l2[4]*t;
+                       res[5] = l1[3]*(1-t) + l2[5]*t;
+                       double cx  = (l1[0]+l1[2])/2;
+                       double cy  = (l1[0]+l1[2])/2;
+                       res[2] = cx*(1-t) + l2[2]*t;
+                       res[3] = cy*(1-t) + l2[3]*t;                    
+                       res[4] = cx*(1-t) + l2[4]*t;
+                       res[5] = cy*(1-t) + l2[5]*t;                    
+               }
+               
+               if (d1==2 && d2==3) {
+                       res[0] = l1[0]*(1-t) + l2[0]*t;
+                       res[1] = l1[1]*(1-t) + l2[1]*t;
+                       res[2] = l1[2]*(1-t) + l2[2]*t;
+                       res[3] = l1[3]*(1-t) + l2[3]*t;                 
+                       res[4] = l1[2]*(1-t) + l2[4]*t;
+                       res[5] = l1[3]*(1-t) + l2[5]*t;                 
+                       res[6] = l1[4]*(1-t) + l2[6]*t;
+                       res[7] = l1[5]*(1-t) + l2[7]*t;
+               }                                       
+               
+               return res;
+       }
+       
+       /**
+        * Returns an iterator that constructs line segments by traversing a path iterator
+        * @param pi path iterator
+        * @return line segment iterator
+        */
+       public static Iterator<double[]> toLineIterator(final PathIterator pi)
+       {
+               return new PathIteratorToSegmentIterator(pi);
+       }
+       
+       public static void toLineSegments(PathIterator pi, Collection<double[]> result)
+       {
+               Iterator<double[]> i = toLineIterator(pi);
+               while (i.hasNext()) {
+                       double[] segment = i.next();
+                       result.add(segment);
+               }
+       }
+       
+       private static class PathIteratorToSegmentIterator implements Iterator<double[]>
+       {
+               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<pos.length/2; i++)
+               {
+                       p.lineTo(pos[i*2], pos[i*2+1]);
+               }
+               return p;
+       }
+
+       /**
+        * Create 3rd degree path. Every second point is a control point.
+        * @param positions
+        * @return
+        */
+//     public static Path2D closePath3rdDeg(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<pos.length/2; i++)
+//             {
+//                     p.lineTo(pos[i*2], pos[i*2+1]);
+//             }
+//             return p;
+//     }
+//     
+       
+       public static Path2D closedPath(double ... pos)
+       {
+               Path2D p = path(pos);
+               p.closePath();
+               return p;
+       }       
+       
+       public static void main(String[] args) {
+               // test crop line
+               double[] cubic = new double[] {0,0, 0, -1, 3, -1, 3,0};
+               double[] cropped = cropLine(cubic, 0.2, 1);
+               System.out.println(Arrays.toString(cropped));
+               System.out.println(getLinePos(cubic, 0.5));
+               System.out.println(getLinePos(cropped, 0.375));
+               /*              
+                               Path2D p = new Path2D.Double();
+                               p.moveTo(4, 1);
+                               p.quadTo(6,1,6,3);
+                               p.quadTo(6,5,4,5);
+                               p.quadTo(2,5,2,3);
+                               p.quadTo(2,1,4,1);
+                               PathIterator pi = p.getPathIterator(null);
+                               double dada[] = new double[6];
+                               while (!pi.isDone()) {
+                                       Arrays.fill(dada, 0);
+                                       int type = pi.currentSegment(dada);
+                                       System.out.println(type+":\t"+Arrays.toString(dada));
+                                       pi.next();
+                               }*/
+                               
+                               assert(findIntersection(0,0,90,  10,1,270+45)!=null);
+                               assert(findIntersection(0,0,90,  1,1,89)!=null);
+                               assert(findIntersection(0,0,90,  1,1,270+45)==null);
+                               //System.out.println(findIntersection(0,0,270,  10,0,270));
+                               //System.out.println(findIntersection(0,0,90,  10,-10,180));            
+                               /*
+                               Point2D cp1 = new Point2D.Double();
+                               Point2D cp2 = new Point2D.Double();
+                               int i = findNearestPoints(0, 0, 0, 1, 2, 10, 0, -1, cp1, cp2);
+                               if (i>0)
+                                       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) ));                     
+                               }*/
+                       }
+                       
+       
+}