1 /**
2  * Copyright (c) 2010, David Benson
3  */
4 package com.mxgraph.util;
5 
6 import java.util.List;
7 
8 public class mxSpline
9 {
10 	/**
11 	 *	Array representing the relative proportion of the total distance
12 	 *	of each point in the line ( i.e. first point is 0.0, end point is
13 	 *	1.0, a point halfway on line is 0.5 ).
14 	 */
15 	private double[] t;
16 
17 	private mxSpline1D splineX;
18 
19 	private mxSpline1D splineY;
20 
21 	/**
22 	 * Total length tracing the points on the spline
23 	 */
24 	private double length;
25 
mxSpline(List<mxPoint> points)26 	public mxSpline(List<mxPoint> points)
27 	{
28 		if (points != null)
29 		{
30 			double[] x = new double[points.size()];
31 			double[] y = new double[points.size()];
32 			int i = 0;
33 
34 			for (mxPoint point : points)
35 			{
36 				x[i] = point.getX();
37 				y[i++] = point.getY();
38 			}
39 
40 			init(x, y);
41 		}
42 	}
43 
44 	/**
45 	 * Creates a new mxSpline.
46 	 * @param x
47 	 * @param y
48 	 */
Spline2D(double[] x, double[] y)49 	public void Spline2D(double[] x, double[] y)
50 	{
51 		init(x, y);
52 	}
53 
init(double[] x, double[] y)54 	protected void init(double[] x, double[] y)
55 	{
56 		if (x.length != y.length)
57 		{
58 			// Arrays must have the same length
59 			// TODO log something
60 			return;
61 		}
62 
63 		if (x.length < 2)
64 		{
65 			// Spline edges must have at least two points
66 			// TODO log something
67 			return;
68 		}
69 
70 		t = new double[x.length];
71 		t[0] = 0.0; // start point is always 0.0
72 		length = 0.0;
73 
74 		// Calculate the partial proportions of each section between each set
75 		// of points and the total length of sum of all sections
76 		for (int i = 1; i < t.length; i++)
77 		{
78 			double lx = x[i] - x[i - 1];
79 			double ly = y[i] - y[i - 1];
80 
81 			// If either diff is zero there is no point performing the square root
82 			if (0.0 == lx)
83 			{
84 				t[i] = Math.abs(ly);
85 			}
86 			else if (0.0 == ly)
87 			{
88 				t[i] = Math.abs(lx);
89 			}
90 			else
91 			{
92 				t[i] = Math.sqrt(lx * lx + ly * ly);
93 			}
94 
95 			length += t[i];
96 			t[i] += t[i - 1];
97 		}
98 
99 		for (int j = 1; j < (t.length) - 1; j++)
100 		{
101 			t[j] = t[j] / length;
102 		}
103 
104 		t[(t.length) - 1] = 1.0; // end point is always 1.0
105 
106 		splineX = new mxSpline1D(t, x);
107 		splineY = new mxSpline1D(t, y);
108 	}
109 
110 	/**
111 	 * @param t 0 <= t <= 1
112 	 */
getPoint(double t)113 	public mxPoint getPoint(double t)
114 	{
115 		mxPoint result = new mxPoint(splineX.getValue(t), splineY.getValue(t));
116 
117 		return result;
118 	}
119 
120 	/**
121 	 * Used to check the correctness of this spline
122 	 */
checkValues()123 	public boolean checkValues()
124 	{
125 		return (splineX.len.length > 1 && splineY.len.length > 1);
126 	}
127 
getDx(double t)128 	public double getDx(double t)
129 	{
130 		return splineX.getDx(t);
131 	}
132 
getDy(double t)133 	public double getDy(double t)
134 	{
135 		return splineY.getDx(t);
136 	}
137 
getSplineX()138 	public mxSpline1D getSplineX()
139 	{
140 		return splineX;
141 	}
142 
getSplineY()143 	public mxSpline1D getSplineY()
144 	{
145 		return splineY;
146 	}
147 
getLength()148 	public double getLength()
149 	{
150 		return length;
151 	}
152 }
153