/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2014, Open Source Geospatial Foundation (OSGeo) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. */ package org.geotools.geometry.jts; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.CoordinateSequence; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.GeometryComponentFilter; import com.vividsolutions.jts.geom.GeometryFactory; import com.vividsolutions.jts.geom.LineString; /** * Utility methods for curved geometries * * @author Andrea Aime - GeoSolutions */ public class CurvedGeometries { /** * Returns true if the geometry is curved, or contains elements that are curved * * @param geometry * @return */ public static boolean isCurved(Geometry geometry) { if (geometry instanceof CurvedGeometry<?>) { return true; } final AtomicBoolean curveFound = new AtomicBoolean(false); geometry.apply(new GeometryComponentFilter() { @Override public void filter(Geometry geom) { if (geom instanceof CurvedGeometry<?>) { curveFound.set(true); } } }); return curveFound.get(); } /** * Checks if the specified geometry is a circle * * @param geom * @return */ public static boolean isCircle(Geometry geom) { if(geom.isEmpty()) { return false; } if (!(geom instanceof CircularRing) && !(geom instanceof CompoundRing)) { return false; } if (geom instanceof CircularRing) { // check that all arcs have the same center and radius CircularRing curved = (CircularRing) geom; CircularArc first = curved.getArcN(0); double radius = first.getRadius(); if (radius == Double.POSITIVE_INFINITY) { return false; } Coordinate center = first.getCenter(); final int numArcs = curved.getNumArcs(); for (int i = 1; i < numArcs; i++) { CircularArc curr = curved.getArcN(i); if (!CircularArc.equals(curr.getRadius(), radius)) { return false; } Coordinate cc = curr.getCenter(); if (!CircularArc.equals(cc.x, center.x) || !CircularArc.equals(cc.y, center.y)) { return false; } } return true; } else { // check that all arcs in the components have the same center and radius, and that // all components are curved CompoundRing curved = (CompoundRing) geom; List<LineString> components = curved.getComponents(); double radius = Double.NaN; Coordinate center = null; for (LineString component : components) { if (!(component instanceof SingleCurvedGeometry<?>)) { return false; } SingleCurvedGeometry<?> curvedComponent = (SingleCurvedGeometry<?>) component; final int numArcs = curvedComponent.getNumArcs(); for (int i = 0; i < numArcs; i++) { CircularArc curr = curvedComponent.getArcN(i); if (center == null) { radius = curr.getRadius(); if (radius == Double.POSITIVE_INFINITY) { return false; } center = curr.getCenter(); } else { if (!CircularArc.equals(curr.getRadius(), radius)) { return false; } Coordinate cc = curr.getCenter(); if (!CircularArc.equals(cc.x, center.x) || !CircularArc.equals(cc.y, center.y)) { return false; } } } } return true; } } /** * Builds a circular arc out of the specified coordinate sequence * * @param cs * @param startCoordinate * @return */ public static CircularArc getArc(CoordinateSequence cs, int startCoordinate) { if (cs.size() < (startCoordinate + 3)) { throw new IllegalArgumentException("The coordinate sequence has " + cs.size() + " points, cannot extract a circular arc starting from coordinate " + startCoordinate); } else if (startCoordinate < 0) { throw new IllegalArgumentException("Start coordinate must be 0 or positive, not: " + startCoordinate); } return new CircularArc(cs.getOrdinate(0, 0), cs.getOrdinate(0, 1), // cs.getOrdinate(1, 0), cs.getOrdinate(1, 1), // cs.getOrdinate(2, 0), cs.getOrdinate(2, 1)); } /** * Returns the circle containing this arc * * @return */ public static CircularRing toCircle(CircularArc arc, GeometryFactory geometryFactory, double tolerance) { double radius = arc.getRadius(); Coordinate center = arc.getCenter(); double[] rcp = new double[10]; rcp[0] = center.x + radius; rcp[1] = center.y; rcp[2] = center.x; rcp[3] = center.y + radius; rcp[4] = center.x - radius; rcp[5] = center.y; rcp[6] = center.x; rcp[7] = center.y - radius; rcp[8] = center.x + radius; rcp[9] = center.y; return new CircularRing(rcp, geometryFactory, tolerance); } /** * Extracts a {@link CurvedGeometryFactory} from the provided geometry, either by just returning * the one that is held by the geometry, if consistent with its tolerance, or by creating a new * one * * @param curved * @return */ public static CurvedGeometryFactory getFactory(CurvedGeometry<?> curved) { GeometryFactory factory = ((Geometry) curved).getFactory(); if (factory instanceof CurvedGeometryFactory) { CurvedGeometryFactory cf = (CurvedGeometryFactory) factory; if (cf.getTolerance() == curved.getTolerance()) { return cf; } } return new CurvedGeometryFactory(factory, curved.getTolerance()); } }