All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.oscim.utils.geom.GeomBuilder Maven / Gradle / Ivy

Go to download

OpenGL vector map library - running on Android, iOS, Desktop and browser.

There is a newer version: 0.21.0
Show newest version
/* Copyright 2013 The jeo project. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.oscim.utils.geom;

import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.GeometryCollection;
import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geom.LineString;
import org.locationtech.jts.geom.LinearRing;
import org.locationtech.jts.geom.MultiLineString;
import org.locationtech.jts.geom.MultiPoint;
import org.locationtech.jts.geom.MultiPolygon;
import org.locationtech.jts.geom.Point;
import org.locationtech.jts.geom.Polygon;
import org.locationtech.jts.geom.PrecisionModel;

import java.lang.reflect.Array;
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Deque;
import java.util.Iterator;

/**
 * Builder for geometry objects.
 * 

* Example usage: *

*

 * 
 * GeometryBuilder gb = new GeometryBuilder();
 *
 * // create array two 2d points and turn into a line string
 * gb.points(1,2,3,4,5,6).toLineString();
 *
 * // build a polygon with holes
 * gb.points(0,0,10,0,10,10,0,10,0,0).ring()
 *   .points(4,4,6,4,6,6,4,6,4,4).ring()
 *   .toPolygon();
 *
 * 
 * 
*

*

* * @author Justin Deoliveira, OpenGeo */ public class GeomBuilder { GeometryFactory factory; Deque cstack = new ArrayDeque(); Deque gstack = new ArrayDeque(); /** * Constructs a builder with the default geometry factory. */ public GeomBuilder() { this(new GeometryFactory()); } /** * Constructs a builder with an explicit geometry factory. */ public GeomBuilder(GeometryFactory factory) { this.factory = factory; } /** * Constructs a builder with a specific srid for geometry objects. */ public GeomBuilder(int srid) { this.factory = new GeometryFactory(new PrecisionModel(), srid); } /** * Adds a 2d point to the coordinate stack. */ public GeomBuilder point(double x, double y) { cstack.push(new Coordinate(x, y)); return this; } /** * Adds a 3d point to the coordinate stack. */ public GeomBuilder pointz(double x, double y, double z) { cstack.push(new Coordinate(x, y, z)); return this; } /** * Adds an array of 2d points to the coordinate stack. */ public GeomBuilder points(double... ord) { if (ord.length % 2 != 0) { throw new IllegalArgumentException("Must specify even number of ordinates"); } for (int i = 0; i < ord.length; i += 2) { point(ord[i], ord[i + 1]); } return this; } /** * Adds an array of 3d points to the coordinate stack. */ public GeomBuilder pointsz(double... ord) { if (ord.length % 3 != 0) { throw new IllegalArgumentException("Must specify ordinates as triples"); } for (int i = 0; i < ord.length; i += 3) { pointz(ord[i], ord[i + 1], ord[i + 2]); } return this; } /** * Creates a Point from the last point on the coordinate stack, and places * the result * on the geometry stack. */ public GeomBuilder point() { gstack.push(factory.createPoint(cpop())); return this; } /** * Creates a LineString from all points on the coordinate stack, and places * the result * on the geometry stack. */ public GeomBuilder lineString() { gstack.push(factory.createLineString(cpopAll())); return this; } /** * Creates a LinearRing from all points on the coordinate stack, and places * the result * on the geometry stack. *

* If the first and last coordinate on the point stack are not equal an * additional point will be added. *

*/ public GeomBuilder ring() { Coordinate[] coords = cpopAll(); if (coords.length > 1 && !coords[0].equals(coords[coords.length - 1])) { Coordinate[] tmp = new Coordinate[coords.length + 1]; System.arraycopy(coords, 0, tmp, 0, coords.length); tmp[tmp.length - 1] = new Coordinate(tmp[0]); coords = tmp; } gstack.push(factory.createLinearRing(coords)); return this; } /** * Creates a Polygon from all LinearRings on the geometry stack and places * the result back * on the geometry stack. */ public GeomBuilder polygon() { if (gstack.isEmpty() || !(gstack.peek() instanceof LinearRing)) { ring(); } LinearRing[] rings = gpopAll(LinearRing.class); LinearRing outer = rings[0]; LinearRing[] inner = null; if (rings.length > 1) { inner = Arrays.copyOfRange(rings, 1, rings.length); } gstack.push(factory.createPolygon(outer, inner)); return this; } /** * Creates a MultiPoint from all coordinates on the coordinate stack, * plaching the result * back on the geometry stack. *

* If the coordinate stack is empty this method will consume all Point * geometries on the geometry stack. *

*/ public GeomBuilder multiPoint() { if (!cstack.isEmpty()) { gstack.push(factory.createMultiPoint(cpopAll())); } else { gstack.push(factory.createMultiPoint(gpopAll(Point.class))); } return this; } /** * Creates a MultiLineString from all LineStrings on the geometry stack and * places the result * back on the geometry stack. */ public GeomBuilder multiLineString() { gstack.push(factory.createMultiLineString(gpopAll(LineString.class))); return this; } /** * Creates a MultiPolygon from all Polygons on the geometry stack and places * the result * back on the geometry stack. */ public GeomBuilder multiPolygon() { gstack.push(factory.createMultiPolygon(gpopAll(Polygon.class))); return this; } /** * Creates a GeometryCollection from all Geometries on the geometry stack * and places the result * back on the geometry stack. */ public GeomBuilder collection() { gstack.push(factory.createGeometryCollection(gpopAll(Geometry.class))); return this; } /** * Buffers the geometry at the top of the geometry stack, and places the * result back on the * geometry stack. */ public GeomBuilder buffer(double amt) { gstack.push(gpop(Geometry.class).buffer(amt)); return this; } /** * Consumes the top of the geometry stack. */ public Geometry get() { return gpop(Geometry.class); } /** * Builds and returns a Point. *

* This method is equivalent to: *

*

     *   (Point) point().get();
     * 
*

*

*/ public Point toPoint() { return point().gpop(Point.class); } /** * Builds and returns a LineString. *

* This method is equivalent to: *

*

     *   (LineString) lineString().get();
     * 
*

*

*/ public LineString toLineString() { return lineString().gpop(LineString.class); } /** * Builds and returns a LineString. *

* This method is equivalent to: *

*

     *   (LinearRing) ring().get();
     * 
*

*

*/ public LinearRing toLinearRing() { return ring().gpop(LinearRing.class); } /** * Builds and returns a Polygon. *

* This method is equivalent to: *

*

     *   (Polygon) polygon().get();
     * 
*

*

*/ public Polygon toPolygon() { return polygon().gpop(Polygon.class); } /** * Builds and returns a MultiPoint. *

* This method is equivalent to: *

*

     *   (MultiPoint) multiPoint().get();
     * 
*

*

*/ public MultiPoint toMultiPoint() { return multiPoint().gpop(MultiPoint.class); } /** * Builds and returns a MultiLineString. *

* This method is equivalent to: *

*

     *   (MultiLineString) multiLineString().get();
     * 
*

*

*/ public MultiLineString toMultiLineString() { return multiLineString().gpop(MultiLineString.class); } /** * Builds and returns a MultiPolygon. *

* This method is equivalent to: *

*

     *   (MultiPolygon) multiPolygon().get();
     * 
*

*

*/ public MultiPolygon toMultiPolygon() { return multiPolygon().gpop(MultiPolygon.class); } /** * Builds and returns a GEometryCollection. *

* This method is equivalent to: *

*

     *   (GeometryCollection) collection().get();
     * 
*

*

*/ public GeometryCollection toCollection() { return collection().gpop(GeometryCollection.class); } Coordinate cpop() { return cpop(1)[0]; } Coordinate[] cpop(int n) { if (cstack.size() < n) { throw new IllegalStateException(String.format("Expected %d values on coordinate stack, " + "but found %d", n, cstack.size())); } Coordinate[] c = new Coordinate[n]; for (int i = 0; i < n; i++) { c[n - i - 1] = cstack.pop(); } return c; } Coordinate[] cpopAll() { if (cstack.isEmpty()) { throw new IllegalStateException("Coordinate stack is empty"); } return cpop(cstack.size()); } T gpop(Class clazz) { return gpop(1, clazz)[0]; } T[] gpop(int n, Class clazz) { if (gstack.size() < n) { throw new IllegalStateException(String.format("Expected %d values on geometry stack, " + "but found %d", n, gstack.size())); } @SuppressWarnings("unchecked") T[] l = (T[]) Array.newInstance(clazz, n); for (int i = 0; i < n; i++) { Object g = gstack.pop(); if (!clazz.isInstance(g)) { throw new IllegalStateException(String.format("Expected %s on geometry stack, but " + "found %s", clazz.getSimpleName(), g.getClass().getSimpleName())); } l[n - i - 1] = clazz.cast(g); } return l; } T[] gpopAll(Class clazz) { if (gstack.isEmpty()) { throw new IllegalArgumentException("Geometry stack is empty"); } int n = 0; Iterator it = gstack.iterator(); while (it.hasNext() && clazz.isInstance(it.next())) { n++; } if (n == 0) { throw new IllegalArgumentException( String.format("Expected %s on geometry stack", clazz.getSimpleName())); } return gpop(n, clazz); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy