blob: 991d3d9fde60f2d54155b6de3012d8103120634a [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.apache.sis.geometry;
/*
* Do not add dependency to java.awt.Rectangle2D in this class, because not every platforms
* support Java2D (e.g. Android), or applications that do not need it may want to avoid to
* force installation of the Java2D module (e.g. JavaFX/SWT).
*/
import java.io.Serializable;
import org.opengis.geometry.Envelope;
import org.opengis.geometry.DirectPosition;
import org.opengis.geometry.MismatchedDimensionException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.metadata.extent.GeographicBoundingBox;
import static org.apache.sis.util.ArgumentChecks.ensureDimensionMatches;
/**
* An immutable {@code Envelope} (a minimum bounding box or rectangle) of arbitrary dimension.
* This class is final in order to ensure that the immutability contract can not be broken
* (assuming not using <cite>Java Native Interface</cite> or reflections).
*
* <div class="section">Immutability and thread safety</div>
* This final class is immutable and thus inherently thread-safe if the {@link CoordinateReferenceSystem}
* instance given to the constructor is immutable. This is usually the case in Apache SIS.
*
* @author Cédric Briançon (Geomatys)
* @author Martin Desruisseaux (IRD, Geomatys)
* @version 0.3
* @since 0.3
* @module
*/
public final class ImmutableEnvelope extends ArrayEnvelope implements Serializable {
/**
* For cross-version compatibility.
*/
private static final long serialVersionUID = 8740224085449107870L;
/**
* Constructs an envelope defined by two corners given as direct positions.
* The envelope CRS will be the CRS of the given positions.
*
* @param lowerCorner the limits in the direction of decreasing coordinate values for each dimension.
* @param upperCorner the limits in the direction of increasing coordinate values for each dimension.
* @throws MismatchedDimensionException if the two positions do not have the same dimension.
* @throws MismatchedReferenceSystemException if the CRS of the two position are not equal.
*/
public ImmutableEnvelope(final DirectPosition lowerCorner, final DirectPosition upperCorner)
throws MismatchedDimensionException, MismatchedReferenceSystemException
{
super(lowerCorner, upperCorner);
}
/**
* Constructs an envelope defined by two corners given as sequences of coordinate values.
*
* @param lowerCorner the limits in the direction of decreasing coordinate values for each dimension.
* @param upperCorner the limits in the direction of increasing coordinate values for each dimension.
* @param crs the CRS to assign to this envelope, or {@code null}.
* @throws MismatchedDimensionException if the two sequences do not have the same length, or
* if the dimension of the given CRS is not equals to the dimension of the given corners.
*/
public ImmutableEnvelope(final double[] lowerCorner, final double[] upperCorner,
final CoordinateReferenceSystem crs) throws MismatchedDimensionException
{
super(lowerCorner, upperCorner);
this.crs = crs;
ensureDimensionMatches("crs", getDimension(), crs);
}
/**
* Constructs a new envelope with the same data than the specified geographic bounding box.
* The coordinate reference system is set to the
* {@linkplain org.apache.sis.referencing.CommonCRS#defaultGeographic() default geographic CRS}.
* Axis order is (<var>longitude</var>, <var>latitude</var>).
*
* @param box the bounding box to copy.
*/
public ImmutableEnvelope(final GeographicBoundingBox box) {
super(box);
}
/**
* Creates an immutable envelope with the values of the given envelope.
* This constructor can be used when the given envelope is known to not
* be an instance of {@code ImmutableEnvelope}. In case of doubt,
* consider using {@link #castOrCopy(Envelope)} instead.
*
* @param envelope the envelope to copy.
*
* @see #castOrCopy(Envelope)
*/
public ImmutableEnvelope(final Envelope envelope) {
super(envelope);
}
/**
* Creates an immutable envelope with the coordinate values of the given envelope but
* a different CRS. This method does <strong>not</strong> reproject the given envelope.
* It just assign the given CRS to this envelope without any check, except for the CRS
* dimension.
*
* <p>The main purpose of this method is to assign a non-null CRS when the envelope to
* copy has a null CRS.</p>
*
* @param crs the CRS to assign to this envelope, or {@code null}.
* @param envelope the envelope from which to copy coordinate values.
* @throws MismatchedDimensionException if the dimension of the given CRS is not equals
* to the dimension of the given envelope.
*/
public ImmutableEnvelope(final CoordinateReferenceSystem crs, final Envelope envelope)
throws MismatchedDimensionException
{
super(envelope);
this.crs = crs;
ensureDimensionMatches("crs", getDimension(), crs);
}
/**
* Constructs a new envelope initialized to the values parsed from the given string in
* {@code BOX} or <cite>Well Known Text</cite> (WKT) format. The given string is typically
* a {@code BOX} element like below:
*
* {@preformat wkt
* BOX(-180 -90, 180 90)
* }
*
* However this constructor is lenient to other geometry types like {@code POLYGON}.
* See the javadoc of the {@link GeneralEnvelope#GeneralEnvelope(CharSequence) GeneralEnvelope}
* constructor for more information.
*
* @param crs the coordinate reference system, or {@code null} if none.
* @param wkt the {@code BOX}, {@code POLYGON} or other kind of element to parse.
* @throws IllegalArgumentException if the given string can not be parsed.
* @throws MismatchedDimensionException if the dimension of the given CRS is not equals
* to the dimension of the parsed envelope.
*/
public ImmutableEnvelope(final CoordinateReferenceSystem crs, final CharSequence wkt)
throws IllegalArgumentException, MismatchedDimensionException
{
super(wkt);
this.crs = crs;
ensureDimensionMatches("crs", getDimension(), crs);
}
/**
* Returns the given envelope as an {@code ImmutableEnvelope} instance. If the given envelope
* is already an instance of {@code ImmutableEnvelope}, then it is returned unchanged.
* Otherwise the coordinate values and the CRS of the given envelope are copied in a
* new envelope.
*
* @param envelope the envelope to cast, or {@code null}.
* @return the values of the given envelope as an {@code ImmutableEnvelope} instance.
*
* @see AbstractEnvelope#castOrCopy(Envelope)
* @see GeneralEnvelope#castOrCopy(Envelope)
*/
public static ImmutableEnvelope castOrCopy(final Envelope envelope) {
if (envelope == null || envelope instanceof ImmutableEnvelope) {
return (ImmutableEnvelope) envelope;
}
return new ImmutableEnvelope(envelope);
}
}