| /* |
| * 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.metadata.iso.spatial; |
| |
| import java.util.List; |
| import java.util.Collection; |
| import javax.xml.bind.annotation.XmlType; |
| import javax.xml.bind.annotation.XmlSeeAlso; |
| import javax.xml.bind.annotation.XmlElement; |
| import javax.xml.bind.annotation.XmlRootElement; |
| import org.opengis.metadata.spatial.GCP; |
| import org.opengis.metadata.spatial.Georectified; |
| import org.opengis.metadata.spatial.PixelOrientation; |
| import org.opengis.geometry.primitive.Point; |
| import org.opengis.util.InternationalString; |
| import org.apache.sis.internal.jaxb.Context; |
| import org.apache.sis.util.resources.Messages; |
| |
| |
| /** |
| * Grid whose cells are regularly spaced in a geographic or projected coordinate reference system. |
| * Any cell in the grid can be geolocated given its grid coordinate and the grid origin, cell spacing, |
| * and orientation indication of whether or not geographic. |
| * |
| * <p>The following properties are mandatory or conditional (i.e. mandatory under some circumstances) |
| * in a well-formed metadata according ISO 19115:</p> |
| * |
| * <div class="preformat">{@code MD_Georectified} |
| * {@code ├─numberOfDimensions…………………………………………………} Number of independent spatial-temporal axes. |
| * {@code ├─axisDimensionProperties……………………………………} Information about spatial-temporal axis properties. |
| * {@code │ ├─dimensionName……………………………………………………} Name of the axis. |
| * {@code │ └─dimensionSize……………………………………………………} Number of elements along the axis. |
| * {@code ├─cellGeometry…………………………………………………………………} Identification of grid data as point or cell. |
| * {@code ├─transformationParameterAvailability……} Whether parameters for transformation exists. |
| * {@code ├─checkPointAvailability………………………………………} Whether geographic position points are available to test the accuracy of the georeferenced grid data. |
| * {@code ├─checkPointDescription…………………………………………} Description of geographic position points used to test the accuracy of the georeferenced grid data. |
| * {@code ├─cornerPoints…………………………………………………………………} Earth location in the coordinate reference system and the grid coordinate of the cells at opposite ends. |
| * {@code └─pointInPixel…………………………………………………………………} Point in a pixel corresponding to the Earth location of the pixel.</div> |
| * |
| * Providing the {@linkplain #getCheckPointDescription() check point description} implies |
| * that {@linkplain #isCheckPointAvailable() check point availability} is {@code true}. |
| * The setter methods will ensure that this condition is not violated. |
| * |
| * <div class="section">Limitations</div> |
| * <ul> |
| * <li>Instances of this class are not synchronized for multi-threading. |
| * Synchronization, if needed, is caller's responsibility.</li> |
| * <li>Serialized objects of this class are not guaranteed to be compatible with future Apache SIS releases. |
| * Serialization support is appropriate for short term storage or RMI between applications running the |
| * same version of Apache SIS. For long term storage, use {@link org.apache.sis.xml.XML} instead.</li> |
| * </ul> |
| * |
| * @author Martin Desruisseaux (IRD, Geomatys) |
| * @author Touraïvane (IRD) |
| * @author Cédric Briançon (Geomatys) |
| * @version 1.0 |
| * @since 0.3 |
| * @module |
| */ |
| @XmlType(name = "MD_Georectified_Type", propOrder = { |
| "checkPointAvailable", |
| "checkPointDescription", |
| "cornerPoints", |
| "centerPoint", |
| "pointInPixel", |
| "transformationDimensionDescription", |
| "transformationDimensionMapping", |
| "checkPoints" |
| }) |
| @XmlRootElement(name = "MD_Georectified") |
| @XmlSeeAlso(org.apache.sis.internal.jaxb.gmi.MI_Georectified.class) |
| public class DefaultGeorectified extends DefaultGridSpatialRepresentation implements Georectified { |
| /** |
| * Serial number for inter-operability with different versions. |
| */ |
| private static final long serialVersionUID = -2924562334097446037L; |
| |
| /** |
| * Mask for the {@code checkPointAvailable} boolean value. |
| * |
| * @see #booleans |
| */ |
| private static final byte CHECK_POINT_MASK = TRANSFORMATION_MASK << 1; |
| |
| /** |
| * Description of geographic position points used to test the accuracy of the |
| * georeferenced grid data. |
| */ |
| private InternationalString checkPointDescription; |
| |
| /** |
| * Earth location in the coordinate system defined by the Spatial Reference System |
| * and the grid coordinate of the cells at opposite ends of grid coverage along two |
| * diagonals in the grid spatial dimensions. There are four corner points in a |
| * georectified grid; at least two corner points along one diagonal are required. |
| */ |
| private List<Point> cornerPoints; |
| |
| /** |
| * Earth location in the coordinate system defined by the Spatial Reference System |
| * and the grid coordinate of the cell halfway between opposite ends of the grid in the |
| * spatial dimensions. |
| */ |
| private Point centerPoint; |
| |
| /** |
| * Point in a pixel corresponding to the Earth location of the pixel. |
| */ |
| private PixelOrientation pointInPixel; |
| |
| /** |
| * Description of the information about which grid dimensions are the spatial dimensions. |
| */ |
| private InternationalString transformationDimensionDescription; |
| |
| /** |
| * Information about which grid dimensions are the spatial dimensions. |
| */ |
| private Collection<InternationalString> transformationDimensionMapping; |
| |
| /** |
| * Geographic references used to validate georectification of the data. |
| */ |
| private Collection<GCP> checkPoints; |
| |
| /** |
| * Constructs an initially empty georectified object. |
| */ |
| public DefaultGeorectified() { |
| } |
| |
| /** |
| * Constructs a new instance initialized with the values from the specified metadata object. |
| * This is a <cite>shallow</cite> copy constructor, since the other metadata contained in the |
| * given object are not recursively copied. |
| * |
| * @param object the metadata to copy values from, or {@code null} if none. |
| * |
| * @see #castOrCopy(Georectified) |
| */ |
| public DefaultGeorectified(final Georectified object) { |
| super(object); |
| if (object != null) { |
| checkPointDescription = object.getCheckPointDescription(); |
| cornerPoints = copyList(object.getCornerPoints(), Point.class); |
| centerPoint = object.getCenterPoint(); |
| pointInPixel = object.getPointInPixel(); |
| transformationDimensionDescription = object.getTransformationDimensionDescription(); |
| transformationDimensionMapping = copyCollection(object.getTransformationDimensionMapping(), InternationalString.class); |
| checkPoints = copyCollection(object.getCheckPoints(), GCP.class); |
| |
| // checkPointAvailability is required to be 'true' if there is a description. |
| if (checkPointDescription != null || object.isCheckPointAvailable()) { |
| booleans |= CHECK_POINT_MASK; |
| } |
| } |
| } |
| |
| /** |
| * Returns a SIS metadata implementation with the values of the given arbitrary implementation. |
| * This method performs the first applicable action in the following choices: |
| * |
| * <ul> |
| * <li>If the given object is {@code null}, then this method returns {@code null}.</li> |
| * <li>Otherwise if the given object is already an instance of |
| * {@code DefaultGeorectified}, then it is returned unchanged.</li> |
| * <li>Otherwise a new {@code DefaultGeorectified} instance is created using the |
| * {@linkplain #DefaultGeorectified(Georectified) copy constructor} |
| * and returned. Note that this is a <cite>shallow</cite> copy operation, since the other |
| * metadata contained in the given object are not recursively copied.</li> |
| * </ul> |
| * |
| * @param object the object to get as a SIS implementation, or {@code null} if none. |
| * @return a SIS implementation containing the values of the given object (may be the |
| * given object itself), or {@code null} if the argument was null. |
| */ |
| public static DefaultGeorectified castOrCopy(final Georectified object) { |
| if (object == null || object instanceof DefaultGeorectified) { |
| return (DefaultGeorectified) object; |
| } |
| return new DefaultGeorectified(object); |
| } |
| |
| /** |
| * Returns an indication of whether or not geographic position points are available to test the |
| * accuracy of the georeferenced grid data. |
| * |
| * @return whether or not geographic position points are available to test accuracy. |
| */ |
| @Override |
| @XmlElement(name = "checkPointAvailability", required = true) |
| public boolean isCheckPointAvailable() { |
| return (booleans & CHECK_POINT_MASK) != 0; |
| } |
| |
| /** |
| * Sets an indication of whether or not geographic position points are available to test the |
| * accuracy of the georeferenced grid data. |
| * |
| * <div class="section">Effect on other properties</div> |
| * If and only if the given {@code newValue} is {@code false}, then this method automatically hides |
| * the {@linkplain #setCheckPointDescription check point description} property. The description can |
| * be shown again by reverting {@code checkPointAvailability} to {@code true}. |
| * |
| * @param newValue {@code true} if check points are available. |
| */ |
| public void setCheckPointAvailable(final boolean newValue) { |
| checkWritePermission(isDefined(CHECK_POINT_MASK)); |
| if (newValue) { |
| booleans |= CHECK_POINT_MASK; |
| } else { |
| if (checkPointDescription != null && (booleans & CHECK_POINT_MASK) != 0) { |
| Context.warningOccured(Context.current(), DefaultGeorectified.class, "setCheckPointAvailable", |
| Messages.class, Messages.Keys.PropertyHiddenBy_2, "checkPointDescription", "checkPointAvailability"); |
| } |
| booleans &= ~CHECK_POINT_MASK; |
| } |
| } |
| |
| /** |
| * Returns a description of geographic position points used to test the accuracy of the |
| * georeferenced grid data. This value is non-null only if {@link #isCheckPointAvailable()} |
| * returns {@code true}. |
| * |
| * @return description of geographic position points used to test accuracy, or {@code null}. |
| */ |
| @Override |
| @XmlElement(name = "checkPointDescription") |
| public InternationalString getCheckPointDescription() { |
| return (booleans & CHECK_POINT_MASK) != 0 ? checkPointDescription : null; |
| } |
| |
| /** |
| * Sets the description of geographic position points used to test the accuracy of the |
| * georeferenced grid data. |
| * |
| * <div class="section">Effect on other properties</div> |
| * If and only if the given {@code newValue} is non-null, then this method automatically sets |
| * the {@linkplain #setCheckPointAvailable check point availability} property to {@code true}. |
| * |
| * @param newValue the new check point description. |
| */ |
| public void setCheckPointDescription(final InternationalString newValue) { |
| checkWritePermission(checkPointDescription); |
| checkPointDescription = newValue; |
| if (newValue != null) { |
| booleans |= CHECK_POINT_MASK; |
| } |
| } |
| |
| /** |
| * Returns the Earth location in the coordinate system defined by the Spatial Reference System |
| * and the grid coordinate of the cells at opposite ends of grid coverage along two diagonals. |
| * |
| * @return the corner points. |
| */ |
| @Override |
| @XmlElement(name = "cornerPoints", required = true) |
| public List<Point> getCornerPoints() { |
| return cornerPoints = nonNullList(cornerPoints, Point.class); |
| } |
| |
| /** |
| * Sets the corner points. |
| * |
| * The {@linkplain List#size() list size} should be 2 or 4. |
| * The list should contain at least two corner points along one diagonal. |
| * or may contains the 4 corner points of the georectified grid. |
| * |
| * <p>The first corner point shall correspond to the origin of the grid.</p> |
| * |
| * @param newValues the new corner points. |
| */ |
| public void setCornerPoints(final List<? extends Point> newValues) { |
| cornerPoints = writeList(newValues, cornerPoints, Point.class); |
| } |
| |
| /** |
| * Returns the Earth location in the coordinate system defined by the Spatial Reference System |
| * and the grid coordinate of the cell halfway between opposite ends of the grid in the |
| * spatial dimensions. |
| * |
| * <div class="warning"><b>Upcoming API change</b><br> |
| * This method may be renamed {@code getCentrePoint()} in GeoAPI 4.0 |
| * for compliance with ISO 19115:2014.</div> |
| * |
| * @return the center point, or {@code null}. |
| */ |
| @Override |
| @XmlElement(name = "centrePoint") |
| public Point getCenterPoint() { |
| return centerPoint; |
| } |
| |
| /** |
| * Sets the center point. |
| * |
| * <div class="warning"><b>Upcoming API change</b><br> |
| * This method may be renamed {@code setCentrePoint(…)} in GeoAPI 4.0 |
| * for compliance with ISO 19115:2014.</div> |
| * |
| * @param newValue the new center point. |
| */ |
| public void setCenterPoint(final Point newValue) { |
| checkWritePermission(centerPoint); |
| centerPoint = newValue; |
| } |
| |
| /** |
| * Returns the point in a pixel corresponding to the Earth location of the pixel. |
| * |
| * @return earth location of the pixel, or {@code null}. |
| */ |
| @Override |
| @XmlElement(name = "pointInPixel", required = true) |
| public PixelOrientation getPointInPixel() { |
| return pointInPixel; |
| } |
| |
| /** |
| * Sets the point in a pixel corresponding to the Earth location of the pixel. |
| * |
| * @param newValue the new point in a pixel. |
| */ |
| public void setPointInPixel(final PixelOrientation newValue) { |
| checkWritePermission(pointInPixel); |
| pointInPixel = newValue; |
| } |
| |
| /** |
| * Returns a general description of the transformation. |
| * |
| * @return general description of the transformation, or {@code null}. |
| */ |
| @Override |
| @XmlElement(name = "transformationDimensionDescription") |
| public InternationalString getTransformationDimensionDescription() { |
| return transformationDimensionDescription; |
| } |
| |
| /** |
| * Sets a general description of the transformation. |
| * |
| * @param newValue the new general description. |
| */ |
| public void setTransformationDimensionDescription(final InternationalString newValue) { |
| checkWritePermission(transformationDimensionDescription); |
| transformationDimensionDescription = newValue; |
| } |
| |
| /** |
| * Returns information about which grid dimensions are the spatial dimensions. |
| * |
| * @return information about which grid dimensions are the spatial dimensions, or {@code null}. |
| */ |
| @Override |
| @XmlElement(name = "transformationDimensionMapping") |
| public Collection<InternationalString> getTransformationDimensionMapping() { |
| return transformationDimensionMapping = nonNullCollection(transformationDimensionMapping, InternationalString.class); |
| } |
| |
| /** |
| * Sets information about which grid dimensions are the spatial dimensions. |
| * The given list should contain at most 2 elements. |
| * |
| * @param newValues the new transformation mapping. |
| */ |
| public void setTransformationDimensionMapping(final Collection<? extends InternationalString> newValues) { |
| transformationDimensionMapping = writeCollection(newValues, transformationDimensionMapping, InternationalString.class); |
| } |
| |
| /** |
| * Returns the geographic references used to validate georectification of the data. |
| * |
| * @return geographic references used to validate georectification. |
| */ |
| @Override |
| @XmlElement(name = "checkPoint") |
| public Collection<GCP> getCheckPoints() { |
| return checkPoints = nonNullCollection(checkPoints, GCP.class); |
| } |
| |
| /** |
| * Sets the geographic references used to validate georectification of the data. |
| * |
| * @param newValues the new check points values. |
| */ |
| public void setCheckPoints(final Collection<? extends GCP> newValues) { |
| checkPoints = writeCollection(newValues, checkPoints, GCP.class); |
| } |
| } |