X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.g2d%2Fsrc%2Forg%2Fsimantics%2Fg2d%2Futils%2FPathUtils.java;h=7ff95ed013d2236c5f63a1fe7c7a9cf0f9d83baa;hp=13d2dd9b2b2671aa8810c8af1515f400f9fa50e9;hb=refs%2Fchanges%2F38%2F238%2F2;hpb=24e2b34260f219f0d1644ca7a138894980e25b14 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) )); + }*/ + } + + +}