/******************************************************************************* * Copyright (c) 2011, 2015 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; import org.eclipse.gef.geometry.euclidean.Angle; import org.eclipse.gef.geometry.euclidean.Vector; import org.eclipse.gef.geometry.internal.utils.PrecisionUtils; /** * The {@link Pie} is a closed {@link AbstractArcBasedGeometry}. It is the * complement of the {@link Arc}, which is an open * {@link AbstractArcBasedGeometry}. * * The {@link Pie} covers an area, therefore it implements the {@link IShape} * interface. * * @author anyssen * @author mwienand */ public class Pie extends AbstractArcBasedGeometry<Pie, Path> implements IShape { private static final long serialVersionUID = 1L; /** * Constructs a new {@link Pie} from the given values. * * @param r * The {@link AbstractRectangleBasedGeometry} which provides the * size for this {@link Pie}. * @param startAngle * The counter-clockwise (CCW) {@link Angle} to the x-axis at * which this {@link Pie} begins. * @param angularExtent * The counter-clockwise (CCW) {@link Angle} that spans this * {@link Pie}. */ public Pie(AbstractRectangleBasedGeometry<?, ?> r, Angle startAngle, Angle angularExtent) { super(r.x, r.y, r.width, r.height, startAngle, angularExtent); } /** * Constructs a new {@link Pie} from the given {@link Arc}. * * @param arc * The {@link Arc} which provides size, start angle, and angular * extent for this {@link Pie}. */ public Pie(Arc arc) { super(arc.x, arc.y, arc.width, arc.height, arc.startAngle, arc.angularExtent); } /** * Constructs a new {@link Pie} from the given values. * * @see AbstractArcBasedGeometry#AbstractArcBasedGeometry(double, double, * double, double, Angle, Angle) * * @param x * The x-coordinate of the rectangular area which encloses thie * {@link Pie}. * @param y * The y-coordinate of the rectangular area which encloses thie * {@link Pie}. * @param width * The width of the rectangular area which encloses thie * {@link Pie}. * @param height * The height of the rectangular area which encloses thie * {@link Pie}. * @param startAngle * The counter-clockwise (CCW) {@link Angle} to the x-axis at * which this {@link Pie} begins. * @param angularExtent * The counter-clockwise (CCW) {@link Angle} that spans this * {@link Pie}. */ public Pie(double x, double y, double width, double height, Angle startAngle, Angle angularExtent) { super(x, y, width, height, startAngle, angularExtent); } @Override public boolean contains(IGeometry g) { return ShapeUtils.contains(this, g); } /* * TODO: Add additional methods to rotate a Pie so that it remains a Pie. */ @Override public boolean contains(Point p) { // check if the point is in the arc's angle Angle pAngle = new Vector(1, 0).getAngleCCW(new Vector(getCenter(), p)); if (!(PrecisionUtils.greater(pAngle.rad(), startAngle.rad()) && PrecisionUtils.smaller(pAngle.rad(), startAngle.getAdded(angularExtent).rad()))) { return false; } // angle is correct, check if the point is inside the bounding ellipse return new Ellipse(x, y, width, height).contains(p); } @Override public Rectangle getBounds() { return getOutline().getBounds(); } /** * @see org.eclipse.gef.geometry.planar.IGeometry#getCopy() */ @Override public Pie getCopy() { return new Pie(x, y, width, height, startAngle, angularExtent); } @Override public PolyBezier getOutline() { return new PolyBezier(getOutlineSegments()); } @Override public BezierCurve[] getOutlineSegments() { CubicCurve[] arcSegs = computeBezierApproximation(); BezierCurve[] outlineSegs = new BezierCurve[arcSegs.length + 2]; for (int i = 0; i < arcSegs.length; i++) { outlineSegs[i] = arcSegs[i]; } outlineSegs[outlineSegs.length - 2] = new Line( outlineSegs[outlineSegs.length - 3].getP2(), getCenter()); outlineSegs[outlineSegs.length - 1] = new Line(getCenter(), outlineSegs[0].getP1()); return outlineSegs; } @Override public Path getRotatedCCW(Angle angle) { return getRotatedCCW(angle, getCenter()); } @Override public Path getRotatedCCW(Angle angle, double cx, double cy) { return new PolyBezier(computeBezierApproximation()) .rotateCCW(angle, cx, cy).toPath(); } @Override public Path getRotatedCCW(Angle angle, Point center) { return new PolyBezier(computeBezierApproximation()) .rotateCCW(angle, center).toPath(); } @Override public Path getRotatedCW(Angle angle) { return getRotatedCW(angle, getCenter()); } @Override public Path getRotatedCW(Angle angle, double cx, double cy) { return new PolyBezier(computeBezierApproximation()) .rotateCW(angle, cx, cy).toPath(); } @Override public Path getRotatedCW(Angle angle, Point center) { return new PolyBezier(computeBezierApproximation()) .rotateCW(angle, center).toPath(); } /** * @see IGeometry#getTransformed(AffineTransform) */ @Override public CurvedPolygon getTransformed(AffineTransform t) { return new CurvedPolygon(getOutlineSegments()).getTransformed(t); } @Override public Path toPath() { CubicCurve[] arc = computeBezierApproximation(); Line endToMid = new Line(arc[arc.length - 1].getP2(), getCenter()); Line midToStart = new Line(getCenter(), arc[0].getP1()); ICurve[] curves = new ICurve[arc.length + 2]; for (int i = 0; i < arc.length; i++) { curves[i] = arc[i]; } curves[arc.length] = endToMid; curves[arc.length + 1] = midToStart; return CurveUtils.toPath(curves).close(); } }