/* * Copyright (c) 2017 wetransform GmbH * * All rights reserved. This program and the accompanying materials are made * available under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the License, * or (at your option) any later version. * * You should have received a copy of the GNU Lesser General Public License * along with this distribution. If not, see <http://www.gnu.org/licenses/>. * * Contributors: * wetransform GmbH <http://www.wetransform.to> */ package eu.esdihumboldt.util.geometry.interpolation.model.impl; import java.text.MessageFormat; import com.vividsolutions.jts.geom.Coordinate; import eu.esdihumboldt.util.geometry.interpolation.model.Angle; import eu.esdihumboldt.util.geometry.interpolation.model.ArcByCenterPoint; import eu.esdihumboldt.util.geometry.interpolation.model.ArcByPoints; /** * An arc represented by center point and radius. * * @author Simon Templer */ public class ArcByCenterPointImpl implements ArcByCenterPoint { private final Coordinate centerPoint; private final double radius; private final Angle startAngle; private final Angle endAngle; private final boolean clockwise; private ArcByPoints pointsRepresentation; /** * Create an Arc represented by center point and radius. * * @param centerPoint the center point * @param radius the radius * @param startAngle the start angle * @param endAngle the end angle * @param clockwise if the Arc is clockwise (rather than counter-clockwise) */ public ArcByCenterPointImpl(Coordinate centerPoint, double radius, Angle startAngle, Angle endAngle, boolean clockwise) { super(); this.centerPoint = centerPoint; this.radius = radius; this.startAngle = startAngle; this.endAngle = endAngle; this.clockwise = clockwise; } @Override public boolean isCircle() { // is a circle if the normalised angles are equal return com.vividsolutions.jts.algorithm.Angle .normalize(startAngle.getRadians()) == com.vividsolutions.jts.algorithm.Angle .normalize(endAngle.getRadians()); } /** * Determine the point at the given angle. * * @param angle the angle * @return the point at the given angle that lies on the arc's circle */ public Coordinate getPointAtAngle(Angle angle) { double x = centerPoint.x + (radius * Math.cos(angle.getRadians())); double y = centerPoint.y + (radius * Math.sin(angle.getRadians())); return new Coordinate(x, y); } /** * {@inheritDoc} * * @author Arun Verma */ @Override public ArcByPoints toArcByPoints() { if (pointsRepresentation == null) { Angle middleAngle = Angle .fromRadians(startAngle.getRadians() + 0.5 * getAngleBetween().getRadians()); // getting start coordinate Coordinate startPoint = getPointAtAngle(startAngle); // getting end coordinate Coordinate endPoint = getPointAtAngle(endAngle); // will generate middle coordinate to use already coded arc // interpolation Coordinate middlePoint = getPointAtAngle(middleAngle); pointsRepresentation = new ArcByPointsImpl(startPoint, middlePoint, endPoint); } return pointsRepresentation; } @Override public Coordinate getCenterPoint() { return centerPoint; } @Override public double getRadius() { return radius; } @Override public Angle getStartAngle() { return startAngle; } @Override public Angle getEndAngle() { return endAngle; } @Override public boolean isClockwise() { return clockwise; } @Override public Angle getAngleBetween() { double diff = endAngle.getRadians() - startAngle.getRadians(); if (!isClockwise()) { // normalise to positive value between 0 (exclusive) and 2Pi if (diff > 0) { while (diff > Angle.PI_TIMES_2) { diff = diff - Angle.PI_TIMES_2; } } else { while (diff <= 0) { diff = diff + Angle.PI_TIMES_2; } } } else { // normalise to negative value between 0 (exclusive) and -2Pi if (diff < 0) { while (diff < -Angle.PI_TIMES_2) { diff = diff + Angle.PI_TIMES_2; } } else { while (diff >= 0) { diff = diff - Angle.PI_TIMES_2; } } } return Angle.fromRadians(diff); } @Override public String toString() { return MessageFormat.format("Arc(c: {0}, r: {1}, {2} - {3} ", centerPoint, radius, startAngle.getDegrees(), endAngle.getDegrees()) + ((clockwise) ? ("CW)") : ("CCW)")); } }