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

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

Go to download

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

The newest version!
package org.geolatte.geom;

import org.geolatte.geom.crs.CoordinateReferenceSystem;

import static java.lang.String.format;

/**
 * An 2D envelope or bounding box implementation.
 *
 * 

An Envelope determines a 2D area characterised by a lower-left and an upper-right coordinate.

*

An Envelope is empty if the set of enclosed points are empty, and has Double.NaN for its lowerleft/upperright coordinates.

* * @author Karel Maesen, Geovise BVBA, 2011 */ public class Envelope

{ private final CoordinateReferenceSystem

crs; private final P lowerLeft; private final P upperRight; /** * Creates an empty Envelop */ public Envelope(CoordinateReferenceSystem

crs) { this.crs = crs; lowerLeft = Positions.mkPosition(crs); upperRight = lowerLeft; } /** * Creates an instance from specified lower-left and upper-right Points. * * If the positions have coordinate dimension higher than 2, the Z/M coordinate values will be * set to 0 in the constructed Envelope * * @param lowerLeft the Point designating the lower-left coordinates * @param upperRight the Point designating the upper-right coordinates * of the envelope. */ public Envelope(P lowerLeft, P upperRight, CoordinateReferenceSystem

crs) { this(lowerLeft.getCoordinate(0), lowerLeft.getCoordinate(1), upperRight.getCoordinate(0), upperRight.getCoordinate(1), crs); } /** * Create an instance using the specified coordinates and CoordinateReferenceSystem. * * If the {@code CoordinateReferenceSystem} has coordinate dimension higher than 2, the Z/M coordinate values will be set to 0 * in the envelope * * @param minC1 minimum first coordinate * @param minC2 minimum second coordinate * @param maxC1 maximum first coordinate * @param maxC2 maximum second coordinate * @param crs the CoordinateReferenceSystem for the coordinates * of the envelope. */ public Envelope(double minC1, double minC2, double maxC1, double maxC2, CoordinateReferenceSystem

crs) { if (crs == null) { throw new IllegalArgumentException("Null CRS argument not allowed"); } double[] lowerLeft = new double[crs.getCoordinateDimension()]; double[] upperRight = new double[crs.getCoordinateDimension()]; lowerLeft[0] = Math.min(minC1, maxC1); lowerLeft[1] = Math.min(minC2, maxC2); upperRight[0] = Math.max(minC1, maxC1); upperRight[1] = Math.max(minC2, maxC2); this.crs = crs; this.lowerLeft = Positions.mkPosition(crs, lowerLeft); this.upperRight = Positions.mkPosition(crs, upperRight); } /** * Returns the CoordinateReferenceSystem for this Envelope * * @return */ public CoordinateReferenceSystem

getCoordinateReferenceSystem() { return this.crs; } /** * Returns the lower-left point of this Envelope. * * @return the lower-left point */ public P lowerLeft() { return this.lowerLeft; } /** * Returns the upper-right point of this Envelope. * * @return the upper-right point */ public P upperRight() { return this.upperRight; } /** * Returns the upper-left point of this Envelope. * * @return the upper-left point */ public P upperLeft() { return Positions.mkPosition(getCoordinateReferenceSystem(), lowerLeft.getCoordinate(0), upperRight.getCoordinate(1)); } /** * Returns the lower-right point of this Envelope. * * @return the lower-right point */ public P lowerRight() { return Positions.mkPosition(getCoordinateReferenceSystem(), upperRight.getCoordinate(0), lowerLeft.getCoordinate(1)); } /** * Returns the lowerleft and upperright coordinates in 2D for this envelope. * * @return [ll.x, ll.y, ur.x, ur.y] for Cartesian envelopes; [ll.lon, ll.lat, ur.lon, ur.lat] for Geographic envelopes */ public double[] toArray(){ return new double[]{lowerLeft.getCoordinate(0), lowerLeft.getCoordinate(1), upperRight.getCoordinate(0), upperRight.getCoordinate(1)}; } public String toString() { StringBuilder builder = new StringBuilder(getCoordinateReferenceSystem().getCrsId().toString()); builder.append("LL: ") .append(this.lowerLeft.toString()) .append(" - UR: ") .append(this.upperRight.toString()); return builder.toString(); } protected double getMinC0() { return lowerLeft.getCoordinate(0); } protected double getMinC1() { return lowerLeft.getCoordinate(1); } protected double getMaxC0() { return upperRight.getCoordinate(0); } protected double getMaxC1() { return upperRight.getCoordinate(1); } /** * Creates an Envelope that is the set-theoretic union of this {@code Envelope} with the specified {@code Envelope} * * @param other other Envelope * @return an Envelope that encompasses both operands. * @throws IllegalArgumentException when the operand Envelopes don't have the same coordinate reference system. */ public Envelope

union(Envelope

other) { if (other == null || other.isEmpty()) return this; if (!this.getCoordinateReferenceSystem().equals(other.getCoordinateReferenceSystem())) throw new IllegalArgumentException("Envelopes have different CRS."); double minC0 = Math.min(getMinC0(), other.getMinC0()); double minC1 = Math.min(getMinC1(), other.getMinC1()); double maxC0 = Math.max(getMaxC0(), other.getMaxC0()); double maxC1 = Math.max(getMaxC1(), other.getMaxC1()); return new Envelope

(minC0, minC1, maxC0, maxC1, this.getCoordinateReferenceSystem()); } /** * Intersects the specified Envelope with this Envelope and returns the result. * * @param other the Envelope to intersect with this instance * @return the set-theoretic intersection of this Envelope and the specified Envelope. * @throws IllegalArgumentException when the specified Envelope doesn't have the same coordinate reference system as this instance. */ public Envelope

intersect(Envelope

other) { if (this.isEmpty() || other.isEmpty()) return mkEmpty(); if (!this.getCoordinateReferenceSystem().equals(other.getCoordinateReferenceSystem())) throw new IllegalArgumentException("Envelopes have different CRS."); double minC0 = Math.max(getMinC0(), other.getMinC0()); double minC1 = Math.max(getMinC1(), other.getMinC1()); double maxC0 = Math.min(getMaxC0(), other.getMaxC0()); double maxC1 = Math.min(getMaxC1(), other.getMaxC1()); if (minC0 > maxC0 || minC1 > maxC1) return mkEmpty(); return new Envelope

(minC0, minC1, maxC0, maxC1, this.getCoordinateReferenceSystem()); } private Envelope

mkEmpty() { return new Envelope

(Double.NaN, Double.NaN, Double.NaN, Double.NaN, getCoordinateReferenceSystem()); } /** * Checks whether this Envelope is empty. * * @return true iff this instance is empty (the empty set). */ public boolean isEmpty() { return Double.isNaN(getMinC0()) || Double.isNaN(getMinC1()) || Double.isNaN(getMaxC0()) || Double.isNaN(getMaxC1()); } /** * Checks whether this Envelope is contained within the specified Envelope * * @param other the other Envelope * @return true iff this instance is contained within the specified Envelope * @throws IllegalArgumentException when the specified Envelope doesn't have the same coordinate reference system as this instance. */ public boolean within(Envelope

other) { if (isEmpty()) return true; if (other.isEmpty()) return false; if (!this.getCoordinateReferenceSystem().equals(other.getCoordinateReferenceSystem())) throw new IllegalArgumentException("Envelopes have different CRS."); return other.getMinC0() <= this.getMinC0() && other.getMaxC0() >= this.getMaxC0() && other.getMinC1() <= this.getMinC1() && other.getMaxC1() >= this.getMaxC1(); } public double extentAlongDimension(int i) { if (i < 0 || i > 2) { throw new IndexOutOfBoundsException("Index negative or larger than defined extent dimension"); } return upperRight.getCoordinate(i) - lowerLeft.getCoordinate(i); } /** * Checks whether this Envelope contains the specifies Envelope. * * @param other the other Envelope * @return true iff this instance contains the specified Envelope * @throws IllegalArgumentException when the specified Envelope doesn't have the same coordinate reference system as this instance. */ public boolean contains(Envelope other) { return other.within(this); } /** * Checks whether this Envelope contains the specifies Envelope. * * @param p the Point * @return true iff this instance contains the specified Point * @throws IllegalArgumentException when the specified Point doesn't have the same coordinate reference system as this instance. */ public boolean contains(P p) { if (!p.getClass().equals(this.getCoordinateReferenceSystem().getPositionClass())) throw new IllegalArgumentException("Position and envelope of different types"); if (isEmpty()) return false; return getMinC0() <= p.getCoordinate(0) && getMaxC0() >= p.getCoordinate(0) && getMinC1() <= p.getCoordinate(1) && getMaxC1() >= p.getCoordinate(1); } /** * Checks whether this Envelope intersects the specifies Envelope. * *

Two instances intersect when their set-theoretic intersection is non-empty.

* * @param other the other Envelope * @return true iff this instance intersects with the other Envelope * @throws IllegalArgumentException when the specified Envelope doesn't have the same coordinate reference system as this instance. */ public boolean intersects(Envelope

other) { return !(isEmpty() || other.isEmpty()) && !(this.getMaxC0() < other.getMinC0() || this.getMinC0() > other.getMaxC0() || this.getMaxC1() < other.getMinC1() || this.getMinC1() > other.getMaxC1()); } @SuppressWarnings("unchecked") public Envelope as(Class castToType){ if (! castToType.isAssignableFrom(this.crs.getPositionClass()) ) { throw new ClassCastException(format("Can't cast a %s to a %s", this.crs.getPositionClass().getName(), castToType.getName())); } return (Envelope)this; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Envelope envelope = (Envelope) o; if (crs != null ? !crs.equals(envelope.crs) : envelope.crs != null) return false; if (this.isEmpty() && envelope.isEmpty()) return true; if (lowerLeft != null ? !lowerLeft.equals(envelope.lowerLeft) : envelope.lowerLeft != null) return false; if (upperRight != null ? !upperRight.equals(envelope.upperRight) : envelope.upperRight != null) return false; return true; } @Override public int hashCode() { int result = crs != null ? crs.hashCode() : 0; result = 31 * result + (lowerLeft != null ? lowerLeft.hashCode() : 0); result = 31 * result + (upperRight != null ? upperRight.hashCode() : 0); return result; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy