001/* 002 * GeoAPI - Java interfaces for OGC/ISO standards 003 * This file is hereby placed into the Public Domain. 004 * This means anyone is free to do whatever they wish with this file. 005 */ 006package org.opengis.example; 007 008import java.util.Map; 009import java.awt.geom.RectangularShape; 010import org.opengis.util.NameFactory; 011import org.opengis.util.GenericName; 012import org.opengis.metadata.Identifier; 013import org.opengis.metadata.citation.Citation; 014import org.opengis.metadata.extent.GeographicBoundingBox; 015import org.opengis.geometry.DirectPosition; 016import org.opengis.geometry.Envelope; 017import org.opengis.referencing.operation.MathTransform; 018import org.opengis.referencing.operation.MathTransformFactory; 019import org.opengis.referencing.crs.CoordinateReferenceSystem; 020import org.opengis.referencing.crs.CRSAuthorityFactory; 021import org.opengis.referencing.cs.CoordinateSystemAxis; 022import org.opengis.referencing.cs.AxisDirection; 023import org.opengis.referencing.cs.RangeMeaning; 024import org.opengis.coordinate.MismatchedDimensionException; 025import org.opengis.coordinate.MismatchedCoordinateMetadataException; 026import org.opengis.annotation.UML; 027import org.opengis.annotation.Specification; 028import org.opengis.example.util.SimpleNameFactory; 029import org.opengis.example.geometry.SimpleEnvelope; 030import org.opengis.example.geometry.SimpleDirectPosition; 031import org.opengis.example.metadata.MetadataProxyFactory; 032import org.opengis.example.metadata.SimpleCitation; 033import org.opengis.example.metadata.SimpleIdentifier; 034import org.opengis.example.metadata.SimpleGeographicBoundingBox; 035import org.opengis.example.referencing.SimpleAuthorityFactory; 036import org.opengis.example.referencing.SimpleTransformFactory; 037import org.opengis.example.referencing.SimpleAxis; 038 039 040/** 041 * Provides simple factories backed by the example implementations. 042 * This class is provided only for illustrative purposes with simple implementations. 043 * <strong>This class is not for use in production.</strong> 044 * For real applications, use a library implementing GeoAPI or providing GeoAPI wrappers. 045 * 046 * @see Specification#ISO_19115 047 * @see Specification#ISO_19103 048 */ 049public final class SimpleFactories { 050 /** 051 * Do not allow instantiation of this class. 052 */ 053 private SimpleFactories() { 054 } 055 056 /** 057 * Creates a new citation having the given title. 058 * This citation can be used for defining the authority of a set of identifiers. 059 * 060 * @param title the citation title. 061 * @return a citation with the given title. 062 */ 063 public static Citation createCitation(String title) { 064 return new SimpleCitation(title); 065 } 066 067 /** 068 * Creates a new identifier of the given authority and code. 069 * 070 * @param authority the authority, or {@code null} if none. 071 * @param code the identifier code. 072 * @return identifier of the given code and (optionally) authority. 073 */ 074 public static Identifier createIdentifier(Citation authority, String code) { 075 return new SimpleIdentifier(authority, code); 076 } 077 078 /** 079 * Creates a new direct position of the given dimension. 080 * The Coordinate Reference System is left unspecified. 081 * All coordinate values are initialized to zero. 082 * 083 * @param dimension the dimension. 084 * @return a new direct position of the given number of dimensions. 085 */ 086 public static DirectPosition createPosition(final int dimension) { 087 return new SimpleDirectPosition(dimension); 088 } 089 090 /** 091 * Creates a new direct position associated to the given coordinate reference system. 092 * The {@linkplain DirectPosition#getDimension() dimension} of the new direct position 093 * is the dimension of the given CRS. All coordinate values are initialized to zero. 094 * 095 * @param crs the coordinate reference system to associate to the new direct position. 096 * @return a new direct position associated to the given <abbr>CRS</abbr>. 097 */ 098 public static DirectPosition createPosition(CoordinateReferenceSystem crs) { 099 return new SimpleDirectPosition(crs); 100 } 101 102 /** 103 * Creates a new envelope defined by two direct positions. 104 * The CRS of the envelope will be the CRS of the given direct positions, which shall be the equal. 105 * The coordinates of the given direct positions are copied. 106 * 107 * <p>This simple implementation does not support envelopes crossing the anti-meridian. 108 * Therefore, lower coordinate values shall not be greater than corresponding upper coordinate values.</p> 109 * 110 * @param lowerCorner the limits in the direction of decreasing coordinate values for each dimension. 111 * @param upperCorner the limits in the direction of increasing coordinate values for each dimension. 112 * @return the envelope defined by the given corners. 113 * @throws MismatchedCoordinateMetadataException if the CRS of the two position are not equal. 114 * @throws MismatchedDimensionException if the two positions do not have the same dimension. 115 * @throws IllegalArgumentException if an coordinate value in the lower corner is greater than 116 * the corresponding coordinate value in the upper corner. 117 */ 118 public static Envelope createEnvelope(DirectPosition lowerCorner, DirectPosition upperCorner) { 119 return new SimpleEnvelope(lowerCorner, upperCorner); 120 } 121 122 /** 123 * Creates a geographic bounding box from the specified rectangular area. 124 * The coordinate values are assumed in WGS84 <abbr>CRS</abbr>. 125 * 126 * @param bounds the rectangle to use for the geographic bounding box. 127 * @return a geographic bounding box with the coordinates of the given rectangle. 128 * @throws IllegalArgumentException if (<var>west bound</var> > <var>east bound</var>) 129 * or (<var>south bound</var> > <var>north bound</var>). 130 * Note that {@linkplain Double#NaN NaN} values are allowed. 131 */ 132 public static GeographicBoundingBox createGeographicBoundingBox(RectangularShape bounds) { 133 return new SimpleGeographicBoundingBox(bounds); 134 } 135 136 /** 137 * Creates a new implementation of the given metadata interface which will contains the values in the given map. 138 * The metadata values are specified by a {@link Map} of attributes in which keys are {@linkplain UML#identifier() 139 * UML identifiers}, and values must be assignable to the return value of the corresponding GeoAPI methods. 140 * 141 * <p><b>Example:</b> create an {@code Individual} instance:</p> 142 * 143 * {@snippet lang="java" : 144 * var attributes = new HashMap<String,Object>(); 145 * attributes.put("name", getNameFactory().createInternationalString("Aristotle")); 146 * Individual party = createMetadataView(Individual.class, attributes); 147 * } 148 * 149 * The returned metadata is <i>live</i>, i.e. any change to the given map of attributes 150 * will be immediately reflected in the values returned by the metadata object. 151 * 152 * @param <T> the compile-time type of the {@code type} argument. 153 * @param type the metadata interface for which to get an instance. 154 * @param attributes the attribute values to give to the metadata instance. 155 * @return a metadata object which will fetch the values in the given map. 156 * @throws IllegalArgumentException if the given type is not an interface 157 * from the GeoAPI metadata package. 158 */ 159 public <T> T createMetadataView(Class<T> type, Map<String,?> attributes) { 160 return MetadataProxyFactory.INSTANCE.create(type, attributes); 161 } 162 163 /** 164 * Creates a new axis for the given authority, name and abbreviation. 165 * This is a simplified constructor which infers {@linkplain AxisDirection axis direction} 166 * and units from the abbreviation using the following table. 167 * 168 * <blockquote><table class="ogc"> 169 * <caption>Axis properties inferred from the abbreviation</caption> 170 * <tr><th>Symbol</th> <th>Common name</th> <th>Axis direction</th> <th>Unit</th> <th>Range</th></tr> 171 * <tr><td>λ</td> <td>geodetic longitude</td> <td>east</td> <td>degree</td><td>±90° ({@link RangeMeaning#EXACT})</td></tr> 172 * <tr><td>φ</td> <td>geodetic latitude</td> <td>north</td> <td>degree</td><td>±180° ({@link RangeMeaning#WRAPAROUND})</td></tr> 173 * <tr><td>h</td> <td>ellipsoidal height</td> <td>up</td> <td>metre</td> <td></td></tr> 174 * <tr><td>H</td> <td>gravity-related height</td><td>up</td> <td>metre</td> <td></td></tr> 175 * <tr><td>d</td> <td>depth</td> <td>down</td> <td>metre</td> <td></td></tr> 176 * <tr><td>r</td> <td>geocentric radius</td> <td>up</td> <td>metre</td> <td>[0…∞]</td></tr> 177 * <tr><td>Ω</td> <td>spherical longitude</td> <td>east</td> <td>degree</td><td>±90° ({@link RangeMeaning#EXACT})</td></tr> 178 * <tr><td>Θ</td> <td>spherical latitude</td> <td>north</td> <td>degree</td><td>±180° ({@link RangeMeaning#WRAPAROUND})</td></tr> 179 * <tr><td>X</td> <td>geocentric X</td> <td>geocentric X</td> <td>metre</td> <td></td></tr> 180 * <tr><td>Y</td> <td>geocentric Y</td> <td>geocentric Y</td> <td>metre</td> <td></td></tr> 181 * <tr><td>Z</td> <td>geocentric Z</td> <td>geocentric Z</td> <td>metre</td> <td></td></tr> 182 * <tr><td>E</td> <td>easting</td> <td>east</td> <td>metre</td> <td></td></tr> 183 * <tr><td>W</td> <td>westing</td> <td>west</td> <td>metre</td> <td></td></tr> 184 * <tr><td>N</td> <td>northing</td> <td>north</td> <td>metre</td> <td></td></tr> 185 * <tr><td>S</td> <td>southing</td> <td>south</td> <td>metre</td> <td></td></tr> 186 * <tr><td>t</td> <td>time</td> <td>future</td> <td>second</td><td></td></tr> 187 * <tr><td>i</td> <td>column</td> <td>column positive</td><td>unity</td> <td></td></tr> 188 * <tr><td>j</td> <td>row</td> <td>row positive</td> <td>unity</td> <td></td></tr> 189 * </table></blockquote> 190 * 191 * @param authority organization responsible for definition of the name, or {@code null}. 192 * @param name the name of the new axis. 193 * @param abbreviation the abbreviation used for this coordinate system axes. 194 * @return a coordinate system axis of the given name and abbreviation. 195 * @throws IllegalArgumentException if the abbreviation is not recognized. 196 */ 197 public static CoordinateSystemAxis createAxis(Citation authority, String name, char abbreviation) { 198 return new SimpleAxis(authority, name, abbreviation); 199 } 200 201 /** 202 * Returns a factory for creating {@code GenericName} instances. 203 * This factory provides methods for constructing 204 * {@link org.opengis.util.InternationalString}, 205 * {@link org.opengis.util.GenericName}, 206 * {@link org.opengis.util.LocalName}, 207 * {@link org.opengis.util.ScopedName}, 208 * {@link org.opengis.util.TypeName} and 209 * {@link org.opengis.util.MemberName}. 210 * 211 * @return a factory for creating instances of {@link GenericName}. 212 */ 213 public static NameFactory getNameFactory() { 214 return SimpleNameFactory.provider(); 215 } 216 217 /** 218 * Returns a factory for creating {@code CoordinateReferenceSystem} instances. 219 * The simple factory provided as an example defines only the following codes: 220 * 221 * <blockquote><table class="ogc"> 222 * <caption>CRS codes defined by "GeoAPI example" pseudo-authority</caption> 223 * <tr><th>Code</th> <th>Type</th> <th>Name</th></tr> 224 * <tr><td>4326</td> <td>Geographic</td> <td>WGS 84</td></tr> 225 * <tr><td>4047</td> <td>Geographic</td> <td>GRS 1980 Authalic Sphere</td></tr> 226 * <tr><td>5714</td> <td>Vertical</td> <td>Mean Sea Level (MSL) height</td></tr> 227 * <tr><td>JulianDate</td> <td>Temporal</td> <td>Julian Date</td></tr> 228 * </table></blockquote> 229 * 230 * @return a factory for creating a few {@code CoordinateReferenceSystem} instances. 231 */ 232 public static CRSAuthorityFactory getCRSAuthorityFactory() { 233 return SimpleAuthorityFactory.provider(); 234 } 235 236 /** 237 * Returns a factory for creating {@code MathTransformFactory} instances. 238 * The simple factory provided as an example can create only linear transforms. 239 * 240 * @return a factory for creating linear instances of {@link MathTransform}. 241 */ 242 public static MathTransformFactory getMathTransformFactory() { 243 return SimpleTransformFactory.provider(); 244 } 245}