/* * 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; import java.math.BigDecimal; import java.util.List; import com.vividsolutions.jts.geom.Coordinate; import eu.esdihumboldt.util.geometry.interpolation.model.Arc; import eu.esdihumboldt.util.geometry.interpolation.model.ArcByCenterPoint; import eu.esdihumboldt.util.geometry.interpolation.model.ArcByPoints; /** * Utility functions related to interpolation. * * @author Arun Verma * @author Simon Templer */ public class InterpolationUtil { /** * Scale used when comparing slopes. */ public static final int SLOPE_SCALE = 4; /** * Determines if the Arc is very close to a straight line. * * @param arc the arc to check * @return if the arc closely represents a straight line */ public static boolean isStraightLine(Arc arc) { if (arc.isCircle()) { return false; } if (arc instanceof ArcByCenterPoint && Double.isInfinite(((ArcByCenterPoint) arc).getRadius())) { // treat as straight line if the radius is infinite return true; } ArcByPoints a = arc.toArcByPoints(); double yDelta_a = a.getMiddlePoint().y - a.getStartPoint().y; double xDelta_a = a.getMiddlePoint().x - a.getStartPoint().x; double yDelta_b = a.getEndPoint().y - a.getMiddlePoint().y; double xDelta_b = a.getEndPoint().x - a.getMiddlePoint().x; double aSlope = yDelta_a / xDelta_a; double bSlope = yDelta_b / xDelta_b; if (round(aSlope, SLOPE_SCALE) == round(bSlope, SLOPE_SCALE)) { return true; } return false; } /** * Rounding the given double value in a standardized manner. * * @param x a double value to be round off * @param scale location of decimal points in * @return rounded double value */ public static double round(double x, int scale) { return round(x, scale, BigDecimal.ROUND_HALF_UP); } private static double round(double x, int scale, int roundingMethod) { try { return (new BigDecimal(Double.toString(x)).setScale(scale, roundingMethod)) .doubleValue(); } catch (NumberFormatException ex) { if (Double.isInfinite(x)) { return x; } else { return Double.NaN; } } } /** * Add a coordinate to a coordinate list only if it is not equal to the last * coordinate in the list. * * @param coords the coordinates list * @param c the coordinate to add */ public static void addIfDifferent(List<Coordinate> coords, Coordinate c) { if (coords.isEmpty()) { coords.add(c); } else { Coordinate last = coords.get(coords.size() - 1); if (!c.equals(last)) { coords.add(c); } } } }