001/*
002 * Copyright 2006 - 2013
003 *     Stefan Balev     <stefan.balev@graphstream-project.org>
004 *     Julien Baudry    <julien.baudry@graphstream-project.org>
005 *     Antoine Dutot    <antoine.dutot@graphstream-project.org>
006 *     Yoann Pigné      <yoann.pigne@graphstream-project.org>
007 *     Guilhelm Savin   <guilhelm.savin@graphstream-project.org>
008 * 
009 * This file is part of GraphStream <http://graphstream-project.org>.
010 * 
011 * GraphStream is a library whose purpose is to handle static or dynamic
012 * graph, create them from scratch, file or any source and display them.
013 * 
014 * This program is free software distributed under the terms of two licenses, the
015 * CeCILL-C license that fits European law, and the GNU Lesser General Public
016 * License. You can  use, modify and/ or redistribute the software under the terms
017 * of the CeCILL-C license as circulated by CEA, CNRS and INRIA at the following
018 * URL <http://www.cecill.info> or under the terms of the GNU LGPL as published by
019 * the Free Software Foundation, either version 3 of the License, or (at your
020 * option) any later version.
021 * 
022 * This program is distributed in the hope that it will be useful, but WITHOUT ANY
023 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
024 * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
025 * 
026 * You should have received a copy of the GNU Lesser General Public License
027 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
028 * 
029 * The fact that you are presently reading this means that you have had
030 * knowledge of the CeCILL-C and LGPL licenses and that you accept their terms.
031 */
032package org.graphstream.ui.swingViewer.util;
033
034import org.graphstream.ui.geom.*;
035import java.awt.geom.*;
036
037/** Utility methods to deal with cubic Bézier curves. */
038public class CubicCurve {
039        /**
040         * Evaluate a cubic Bézier curve according to control points `x0`, `x1`,
041         * `x2` and `x3` and return the position at parametric position `t` of the
042         * curve.
043         * 
044         * @return The coordinate at parametric position `t` on the curve.
045         */
046        public static double eval(double x0, double x1, double x2, double x3, double t) {
047                double tt = (1f - t);
048
049                return x0 * (tt * tt * tt) + 3f * x1 * t * (tt * tt) + 3f * x2
050                                * (t * t) * tt + x3 * (t * t * t);
051        }
052
053        /**
054         * Evaluate a cubic Bézier curve according to control points `p0`, `p1`,
055         * `p2` and `p3` and return the position at parametric position `t` of the
056         * curve.
057         * 
058         * @return The point at parametric position `t` on the curve.
059         */
060        public static Point2 eval(Point2 p0, Point2 p1, Point2 p2, Point2 p3,
061                        double t) {
062                return new Point2(eval(p0.x, p1.x, p2.x, p3.x, t), eval(p0.y, p1.y,
063                                p2.y, p3.y, t));
064        }
065
066        /**
067         * Evaluate a cubic Bézier curve according to control points `p0`, `p1`,
068         * `p2` and `p3` and return the position at parametric position `t` of the
069         * curve.
070         * 
071         * @return The point at parametric position `t` on the curve.
072         */
073        public static Point2D.Double eval(Point2D.Double p0, Point2D.Double p1,
074                        Point2D.Double p2, Point2D.Double p3, double t) {
075                return new Point2D.Double(eval(p0.x, p1.x, p2.x, p3.x, t), eval(p0.y,
076                                p1.y, p2.y, p3.y, t));
077        }
078
079        /**
080         * Evaluate a cubic Bézier curve according to control points `p0`, `p1`,
081         * `p2` and `p3` and store the position at parametric position `t` of the
082         * curve in `result`.
083         * 
084         * @return the given reference to `result`.
085         */
086        public static Point2 eval(Point2 p0, Point2 p1, Point2 p2, Point2 p3,
087                        double t, Point2 result) {
088                result.set(eval(p0.x, p1.x, p2.x, p3.x, t),
089                                eval(p0.y, p1.y, p2.y, p3.y, t));
090                return result;
091        }
092
093        /**
094         * Derivative of a cubic Bézier curve according to control points `x0`,
095         * `x1`, `x2` and `x3` at parametric position `t` of the curve.
096         * 
097         * @return The derivative at parametric position `t` on the curve.
098         */
099        public static double derivative(double x0, double x1, double x2, double x3,
100                        double t) {
101                return 3 * (x3 - 3 * x2 + 3 * x1 - x0) * t * t + 2
102                                * (3 * x2 - 6 * x1 + 3 * x0) * t + (3 * x1 - 3 * x0);
103        }
104
105        /**
106         * Derivative point of a cubic Bézier curve according to control points
107         * `x0`, `x1`, `x2` and `x3` at parametric position `t` of the curve.
108         * 
109         * @return The derivative point at parametric position `t` on the curve.
110         */
111        public static Point2 derivative(Point2 p0, Point2 p1, Point2 p2, Point3 p3,
112                        double t) {
113                return new Point2(derivative(p0.x, p1.x, p2.x, p3.x, t), derivative(
114                                p0.y, p1.y, p2.y, p3.y, t));
115        }
116
117        /**
118         * Store in `result` the derivative point of a cubic Bézier curve according
119         * to control points `x0`, `x1`, `x2` and `x3` at parametric position `t` of
120         * the curve.
121         * 
122         * @return the given reference to `result`.
123         */
124        public static Point2 derivative(Point2 p0, Point2 p1, Point2 p2, Point3 p3,
125                        double t, Point2 result) {
126                result.set(derivative(p0.x, p1.x, p2.x, p3.x, t),
127                                derivative(p0.y, p1.y, p2.y, p3.y, t));
128                return result;
129        }
130
131        /**
132         * The perpendicular vector to the curve defined by control points `p0`,
133         * `p1`, `p2` and `p3` at parametric position `t`.
134         * 
135         * @return A vector perpendicular to the curve at position `t`.
136         */
137        public static Vector2 perpendicular(Point2 p0, Point2 p1, Point2 p2,
138                        Point2 p3, double t) {
139                return new Vector2(derivative(p0.y, p1.y, p2.y, p3.y, t), -derivative(
140                                p0.x, p1.x, p2.x, p3.x, t));
141        }
142
143        /**
144         * Store in `result` the perpendicular vector to the curve defined by
145         * control points `p0`, `p1`, `p2` and `p3` at parametric position `t`.
146         * 
147         * @return the given reference to `result`.
148         */
149        public static Vector2 perpendicular(Point2 p0, Point2 p1, Point2 p2,
150                        Point2 p3, double t, Vector2 result) {
151                result.set(derivative(p0.y, p1.y, p2.y, p3.y, t),
152                                -derivative(p0.x, p1.x, p2.x, p3.x, t));
153                return result;
154        }
155
156        /**
157         * The perpendicular vector to the curve defined by control points `p0`,
158         * `p1`, `p2` and `p3` at parametric position `t`.
159         * 
160         * @return A vector perpendicular to the curve at position `t`.
161         */
162        public static Point2D.Double perpendicular(Point2D.Double p0,
163                        Point2D.Double p1, Point2D.Double p2, Point2D.Double p3, double t) {
164                return new Point2D.Double(derivative(p0.y, p1.y, p2.y, p3.y, t),
165                                -derivative(p0.x, p1.x, p2.x, p3.x, t));
166        }
167}