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

org.geolatte.geom.Geometry Maven / Gradle / Ivy

Go to download

This geoLatte-geom library offers a geometry model that conforms to the OGC Simple Features for SQL specification.

There is a newer version: 1.9.1
Show newest version
/*
 * This file is part of the GeoLatte project.
 *
 *     GeoLatte 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, either version 3 of the License, or
 *     (at your option) any later version.
 *
 *     GeoLatte 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.
 *
 *     You should have received a copy of the GNU Lesser General Public License
 *     along with GeoLatte.  If not, see .
 *
 * Copyright (C) 2010 - 2011 and Ownership of code is shared by:
 * Qmino bvba - Romeinsestraat 18 - 3001 Heverlee  (http://www.qmino.com)
 * Geovise bvba - Generaal Eisenhowerlei 9 - 2140 Antwerpen (http://www.geovise.com)
 */

package org.geolatte.geom;

import org.geolatte.geom.codec.Wkb;
import org.geolatte.geom.codec.Wkt;
import org.geolatte.geom.crs.CoordinateReferenceSystem;
import org.geolatte.geom.crs.CoordinateReferenceSystems;
import org.geolatte.geom.crs.CrsRegistry;

import java.io.*;
import java.lang.reflect.Array;

/**
 * The base class for Geometrys.
 *
 * @author Karel Maesen, Geovise BVBA, 2011
 */

public abstract class Geometry

implements Serializable { private static final long serialVersionUID = 6884205871950410215L; private static GeometryEquality geomEq = new GeometryPointEquality(); private final PositionSequence

positions; private final CoordinateReferenceSystem

crs; /** * Creates a new {@code Geometry} with the positions from the specified geometry and having the specified * {@code CoordinateReferenceSystem} * * @param geometry source {@code Geometry} that supplies the {@code Position}s for the returned {@code Geometry} * @param crs the {@code CoordinateReferenceSystem} for the returned {@code Geometry} * @param the {@code Position} type for the returned Geometry * @return a {@code Geometry} with the positions of the specified geometry and having * the specified {@code CoordinateReferenceSystem} */ @SuppressWarnings("unchecked") public static Geometry forceToCrs(Geometry geometry, CoordinateReferenceSystem crs) { if (crs == null || geometry == null) return (Geometry) geometry; if (crs.equals(geometry.getCoordinateReferenceSystem())) return (Geometry) geometry; if (geometry instanceof Simple) { Simple simple = (Simple) geometry; PositionSequence positions = Positions.copy(geometry.getPositions(), crs.getPositionClass()); return Geometries.mkGeometry(simple.getClass(), positions, crs); } else { Complex complex = (Complex) geometry; if (complex.getNumGeometries() == 0) { return Geometries.mkGeometry(complex.getClass(), crs); } Geometry[] targetParts = (Geometry[]) Array.newInstance(complex.getComponentType(), complex.getNumGeometries());//new Geometry[complex.getNumGeometries()]; int idx = 0; for (Geometry part : complex) { targetParts[idx++] = forceToCrs(part, crs); } return Geometries.mkGeometry(complex.getClass(), targetParts); } } /** * Creates an empty Geometry * * @param crs the CoordinateReferenceSystem to use */ protected Geometry(CoordinateReferenceSystem

crs) { if (crs == null) throw new IllegalArgumentException("Received null CRS argument"); this.crs = crs; this.positions = PositionSequenceBuilders.fixedSized(0, crs.getPositionClass()).toPositionSequence(); } protected Geometry(PositionSequence

positions, CoordinateReferenceSystem

crs) { if (crs == null) throw new IllegalArgumentException("Received null CRS argument"); if (positions == null) throw new IllegalArgumentException("Null Positions argument not allowd."); this.crs = crs; this.positions = positions; } @SuppressWarnings("unchecked") protected static PositionSequence nestPositionSequences(Geometry[] geometries) { if (geometries == null || geometries.length == 0) { return new NestedPositionSequence((PositionSequence[])new PositionSequence[0]); } PositionSequence[] sequences = (PositionSequence[]) (new PositionSequence[geometries.length]); int i = 0; for (Geometry g : geometries) { sequences[i++] = g.getPositions(); } return new NestedPositionSequence(sequences); } @SuppressWarnings("unchecked") protected static CoordinateReferenceSystem getCrs(Geometry[] geometries) { if (geometries == null || geometries.length == 0) { return (CoordinateReferenceSystem)CrsRegistry.getCoordinateReferenceSystemForEPSG(-1, CoordinateReferenceSystems.PROJECTED_2D_METER); } return geometries[0].getCoordinateReferenceSystem(); } /** * Returns the coordinate dimension of this Geometry *

*

The coordinate dimension is the number of components in the coordinates of the points in * this Geometry.

* * @return the coordinate dimension */ public int getCoordinateDimension() { return getPositions().getCoordinateDimension(); } /** * Returns the coordinate reference system of this Geometry * * @return the coordinate reference system of this Geometry */ public CoordinateReferenceSystem

getCoordinateReferenceSystem() { return this.crs; } /** * Returns the numeric identifier of the coordinate reference system of this Geometry. *

*

A SRID is usually interpreted as meaning the EPSG-code for the coordinate reference system. In this * implementation, this is not enforced.

* * @return the numeric identifier of the coordinate reference system of this Geometry. */ public int getSRID() { return getCoordinateReferenceSystem().getCrsId().getCode(); } /** * Tests whether this Geometry corresponds to the empty set. * * @return true if this Geometry corresponds to the empty set, false otherwise. */ public boolean isEmpty() { return this.getPositions().isEmpty(); } /** * Returns the number of positions in the PositionSequence of this Geometry. * * @return the number of positions in the PositionSequence of this Geometry. */ public int getNumPositions() { return getPositions().size(); } public Class

getPositionClass() { return !getPositions().isEmpty() ? getPositions().getPositionClass() : this.crs.getPositionClass(); } /** * Returns the position at the specified index in the PositionSequence of this Geometry. * * @param index the position in the PositionSequence (first point is at index 0). * @return the position at the specified index in the PositionSequence of this Geometry. */ public P getPositionN(int index) { if (index >= getPositions().size()) { throw new IndexOutOfBoundsException(); } double[] coords = new double[getCoordinateDimension()]; getPositions().getCoordinates(index, coords); return Positions.mkPosition(getCoordinateReferenceSystem(), coords); } /** * Returns the PositionSequence of this instance * * @return the PositionSequence of this instance */ public PositionSequence

getPositions() { return this.positions; } @Override @SuppressWarnings("unchecked") public boolean equals(Object o) { if (this == o) return true; if (o == null || !Geometry.class.isAssignableFrom(o.getClass())) return false; if (!this.getPositionClass().equals(((Geometry) o).getPositionClass())) return false; Geometry

otherGeometry = (Geometry

) o; //safe cast because we first check for position class equality return geomEq.equals(this, otherGeometry); } /** * Returns the {@code Envelope} of this instance. * @return the {@code Envelope} of this instance. */ public Envelope

getEnvelope() { if (isEmpty()) return new Envelope

(getCoordinateReferenceSystem()); PositionSequence

positions = getPositions(); EnvelopeVisitor

visitor = new EnvelopeVisitor

(getCoordinateReferenceSystem()); positions.accept(visitor); return visitor.result(); } @Override public int hashCode() { int result = getGeometryType().hashCode(); result = 31 * result + this.getPositions().hashCode(); return result; } /** * Returns the type of this Geometry. * * @return the GeometryType of this instance. */ public abstract GeometryType getGeometryType(); /** * Returns the Well-Known Text (WKT) representation of this Geometry. * * @return the Well-Known Text (WKT) representation of this Geometry. */ public String toString() { return Wkt.toWkt(this); } /** * Returns the topological dimension of this instance. In non-homogenous collections, this will return the largest * topological dimension of the contained Geometries. * * @return the topological dimension of this instance */ public abstract int getDimension(); /** * Accepts a GeometryVisitor. *

If this Geometry instance is a GeometryCollection then it will pass the * visitor to its contained Geometries.

* * @param visitor */ public abstract void accept(GeometryVisitor

visitor); private void readObject(ObjectInputStream in) throws IOException { throw new InvalidObjectException("Require WKB serialization"); } protected Object writeReplace() throws ObjectStreamException { ByteBuffer buffer = Wkb.toWkb(this); return new SerializationProxy(buffer); } //see Effective Java, 2ed, Item 78 private static class SerializationProxy implements Serializable { private final byte[] buffer; SerializationProxy(ByteBuffer buffer) { this.buffer = buffer.toByteArray(); } private Object readResolve() throws ObjectStreamException { return Wkb.fromWkb(ByteBuffer.from(this.buffer)); } } private static class EnvelopeVisitor

implements PositionVisitor

{ double[] coordinates; double xMin = Double.POSITIVE_INFINITY; double yMin = Double.POSITIVE_INFINITY; double xMax = Double.NEGATIVE_INFINITY; double yMax = Double.NEGATIVE_INFINITY; final CoordinateReferenceSystem

crs; EnvelopeVisitor(CoordinateReferenceSystem

crs) { this.crs = crs; coordinates = new double[crs.getCoordinateDimension()]; } @Override public void visit(P position) { position.toArray(coordinates); xMin = Math.min(xMin, coordinates[0]); xMax = Math.max(xMax, coordinates[0]); yMin = Math.min(yMin, coordinates[1]); yMax = Math.max(yMax, coordinates[1]); } public Envelope

result() { return new Envelope

(xMin, yMin, xMax, yMax, crs); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy