1 /*
2  * Copyright (c) 2005 David Benson
3  *
4  * See LICENSE file in distribution for licensing details of this source file
5  */
6 package org.jgraph.util;
7 
8 import java.awt.Point;
9 import java.awt.geom.Point2D;
10 
11 /**
12  * Interpolates given points by a bezier curve. The first
13  * and the last two points are interpolated by a quadratic
14  * bezier curve; the other points by a cubic bezier curve.
15  *
16  * Let p a list of given points and b the calculated bezier points,
17  * then one get the whole curve by:
18  *
19  * sharedPath.moveTo(p[0])
20  * sharedPath.quadTo(b[0].x, b[0].getY(), p[1].x, p[1].getY());
21  *
22  * for(int i = 2; i < p.length - 1; i++ ) {
23  *    Point b0 = b[2*i-3];
24  *	  Point b1 = b[2*i-2];
25  *	  sharedPath.curveTo(b0.x, b0.getY(), b1.x, b1.getY(), p[i].x, p[i].getY());
26  * }
27  *
28  * sharedPath.quadTo(b[b.length-1].x, b[b.length-1].getY(), p[n - 1].x, p[n - 1].getY());
29  *
30  * @author krueger
31  */
32 public class Bezier {
33 
34 	private static final float AP = 0.5f;
35 	private Point2D[] bPoints;
36 
37 	/**
38 	 * Creates a new Bezier curve.
39 	 * @param points
40 	 */
Bezier(Point2D[] points)41 	public Bezier(Point2D[] points) {
42 		int n = points.length;
43 		if (n < 3) {
44 			// Cannot create bezier with less than 3 points
45 			return;
46 		}
47 		bPoints = new Point[2 * (n - 2)];
48 		double paX, paY;
49 		double pbX = points[0].getX();
50 		double pbY = points[0].getY();
51 		double pcX = points[1].getX();
52 		double pcY = points[1].getY();
53 		for (int i = 0; i < n - 2; i++) {
54 			paX = pbX;
55 			paY = pbY;
56 			pbX = pcX;
57 			pbY = pcY;
58 			pcX = points[i + 2].getX();
59 			pcY = points[i + 2].getY();
60 			double abX = pbX - paX;
61 			double abY = pbY - paY;
62 			double acX = pcX - paX;
63 			double acY = pcY - paY;
64 			double lac = Math.sqrt(acX * acX + acY * acY);
65 			acX = acX /lac;
66 			acY = acY /lac;
67 
68 			double proj = abX * acX + abY * acY;
69 			proj = proj < 0 ? -proj : proj;
70 			double apX = proj * acX;
71 			double apY = proj * acY;
72 
73 			double p1X = pbX - AP * apX;
74 			double p1Y = pbY - AP * apY;
75 			bPoints[2 * i] = new Point((int) p1X, (int) p1Y);
76 
77 			acX = -acX;
78 			acY = -acY;
79 			double cbX = pbX - pcX;
80 			double cbY = pbY - pcY;
81 			proj = cbX * acX + cbY * acY;
82 			proj = proj < 0 ? -proj : proj;
83 			apX = proj * acX;
84 			apY = proj * acY;
85 
86 			double p2X = pbX - AP * apX;
87 			double p2Y = pbY - AP * apY;
88 			bPoints[2 * i + 1] = new Point((int) p2X, (int) p2Y);
89 		}
90 	}
91 
92 	/**
93 	 * Returns the calculated bezier points.
94 	 * @return the calculated bezier points
95 	 */
96 	public Point2D[] getPoints() {
97 		return bPoints;
98 	}
99 
100 	/**
101 	 * Returns the number of bezier points.
102 	 * @return number of bezier points
103 	 */
104 	public int getPointCount() {
105 		return bPoints.length;
106 	}
107 
108 	/**
109 	 * Returns the bezier points at position i.
110 	 * @param i
111 	 * @return the bezier point at position i
112 	 */
113 	public Point2D getPoint(int i) {
114 		return bPoints[i];
115 	}
116 
117 }
118