/******************************************************************************* * Copyright (c) 2011, 2016 itemis AG and others. * * 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: * Alexander Nyßen (itemis AG) - initial API and implementation * Matthias Wienand (itemis AG) - contribution for Bugzilla #355997 * *******************************************************************************/ package org.eclipse.gef.geometry.planar; /** * Represents the geometric shape of a quadratic Bézier curve. * * @author anyssen * @author mwienand * */ public class QuadraticCurve extends BezierCurve { private static final long serialVersionUID = 1L; /** * Constructs a new {@link QuadraticCurve} from the given sequence of x- and * y-coordinates of the start-, the control-, and the end-point. * * @param coordinates * a sequence containing the x- and y-coordinates * * @see QuadraticCurve#QuadraticCurve(double, double, double, double, * double, double) */ public QuadraticCurve(double... coordinates) { this(coordinates[0], coordinates[1], coordinates[2], coordinates[3], coordinates[4], coordinates[5]); if (coordinates.length != 6) { throw new IllegalArgumentException( "A QuadraticCurve may only be defined by 6 coordinates (3 points), while " + coordinates.length + " were passed in."); } } /** * Constructs a new QuadraticCurve object from the given point coordinates. * * @param x1 * the start point's x-coordinate * @param y1 * the start point's y-coordinate * @param ctrlX * the control point's x-coordinate * @param ctrlY * the control point's y-coordinate * @param x2 * the end point's x-coordinate * @param y2 * the end point's y-coordinate */ public QuadraticCurve(double x1, double y1, double ctrlX, double ctrlY, double x2, double y2) { super(x1, y1, ctrlX, ctrlY, x2, y2); } /** * Constructs a new {@link QuadraticCurve} from the given sequence of * {@link Point}s formed by start-, control-, and end-point. * * @param points * the control {@link Point}s * * @see QuadraticCurve#QuadraticCurve(Point, Point, Point) */ public QuadraticCurve(Point... points) { this(points[0], points[1], points[2]); if (points.length != 3) { throw new IllegalArgumentException( "A QuadraticCurve may only be defined by three points, while " + points.length + " were passed in."); } } /** * Constructs a new QuadraticCurve object from the given points. * * @param p1 * the start point * @param pCtrl * the control point * @param p2 * the end point */ public QuadraticCurve(Point p1, Point pCtrl, Point p2) { this(p1.x, p1.y, pCtrl.x, pCtrl.y, p2.x, p2.y); } /** * Erroneous getBounds() implementation... use the generic one instead. * * TODO: find out why the mathematical solution is erroneous in some cases. * * Returns the bounds of this QuadraticCurve. The bounds are calculated by * examining the extreme points of the x(t) and y(t) function * representations of this QuadraticCurve. * * @return the bounds {@link Rectangle} */ /** * Returns a new {@link QuadraticCurve}, which has the same start, end, and * control point coordinates as this one. * * @return a new {@link QuadraticCurve} with the same start, end, and * control point coordinates */ @Override public QuadraticCurve getCopy() { return new QuadraticCurve(getP1(), getCtrl(), getP2()); } /** * Get the control point. * * @return a Point object representing the control point */ public Point getCtrl() { return new Point(getCtrlX(), getCtrlY()); } /** * Get the control point's x-coordinate. * * @return the control point's x-coordinate */ public double getCtrlX() { return getPoint(1).x; } /** * Get the control point's y-coordinate. * * @return the control point's y-coordinate */ public double getCtrlY() { return getPoint(1).y; } /** * Degree elevation: Returns a {@link CubicCurve} representation of this * {@link QuadraticCurve}. * * @return A {@link CubicCurve} that represents this {@link QuadraticCurve}. */ @Override public CubicCurve getElevated() { Point[] controlPoints = new Point[4]; // "Curves and Surfaces for Computer Aided Geometric Design" by Farin, // Gerald E., Academic Press 1988 controlPoints[0] = getP1(); controlPoints[1] = getP1().getScaled(1d / 3d) .getTranslated(getCtrl().getScaled(2d / 3d)); controlPoints[2] = getCtrl().getScaled(2d / 3d) .getTranslated(getP2().getScaled(1d / 3d)); controlPoints[3] = getP2(); return new CubicCurve(controlPoints); } @Override public QuadraticCurve getTransformed(AffineTransform t) { return new QuadraticCurve(t.getTransformed(getPoints())); } /** * Sets the curve's control point. * * @param ctrl * The new curve's control point. * @return <code>this</code> for convenience */ public QuadraticCurve setCtrl(Point ctrl) { setCtrlX(ctrl.x); setCtrlY(ctrl.y); return this; } /** * Sets the x-coordinate of the curve's control point. * * @param ctrlX * The new x-coordinate of the curve's control point. * @return <code>this</code> for convenience */ public QuadraticCurve setCtrlX(double ctrlX) { setPoint(1, new Point(ctrlX, getCtrlY())); return this; } /** * Sets the y-coordinate of the curve's control point. * * @param ctrlY * The y-coordinate of the curve's control point. * @return <code>this</code> for convenience */ public QuadraticCurve setCtrlY(double ctrlY) { setPoint(1, new Point(getCtrlX(), ctrlY)); return this; } /** * Splits this QuadraticCurve using the de Casteljau algorithm at parameter * t into two separate QuadraticCurve objects. The returned * {@link QuadraticCurve}s are the curves for [0, t] and [t, 1]. * * @param t * in range [0,1] * @return two QuadraticCurve objects constituting the original curve: 1. * [0, t] 2. [t, 1] */ @Override public QuadraticCurve[] split(double t) { BezierCurve[] split = super.split(t); return new QuadraticCurve[] { split[0].toQuadratic(), split[1].toQuadratic() }; } /** * Transform the QuadraticCurve object to a {@link Path} object with the * same shape. * * @return a {@link Path} object representing the curve */ @Override public Path toPath() { Path p = new Path(); p.moveTo(getX1(), getY1()); p.quadTo(getCtrlX(), getCtrlY(), getX2(), getY2()); return p; } @Override public String toString() { return "QuadraticCurve(x1 = " + getX1() + ", y1 = " + getY1() + ", ctrlX = " + getCtrlX() + ", ctrlY = " + getCtrlY() + ", x2 = " + getX2() + ", y2 = " + getY2() + ")"; } }