org.geotoolkit.referencing.factory.ReferencingObjectFactory Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of geotk-referencing Show documentation
Show all versions of geotk-referencing Show documentation
Implementations of Coordinate Reference Systems (CRS),
conversion and transformation services derived from ISO 19111.
/*
* Geotoolkit.org - An Open Source Java GIS Toolkit
* http://www.geotoolkit.org
*
* (C) 2004-2011, Open Source Geospatial Foundation (OSGeo)
* (C) 2009-2011, Geomatys
*
* This library 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;
* version 2.1 of the License.
*
* This library 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.
*
* This package contains documentation from OpenGIS specifications.
* OpenGIS consortium's work is fully acknowledged here.
*/
package org.geotoolkit.referencing.factory;
import java.util.Date;
import java.util.Map;
import java.util.HashMap;
import java.awt.RenderingHints;
import java.text.ParseException;
import javax.measure.unit.Unit;
import javax.measure.quantity.Angle;
import javax.measure.quantity.Length;
import net.jcip.annotations.ThreadSafe;
import org.opengis.referencing.*;
import org.opengis.referencing.cs.*;
import org.opengis.referencing.crs.*;
import org.opengis.referencing.datum.*;
import org.opengis.referencing.operation.*;
import org.opengis.parameter.ParameterValueGroup;
import org.opengis.util.FactoryException;
import org.geotoolkit.factory.Hints;
import org.geotoolkit.factory.FactoryFinder;
import org.geotoolkit.io.wkt.ReferencingParser;
import org.geotoolkit.io.wkt.Symbols;
import org.geotoolkit.lang.Buffered;
import org.geotoolkit.referencing.cs.*;
import org.geotoolkit.referencing.crs.*;
import org.geotoolkit.referencing.datum.*;
import org.geotoolkit.referencing.operation.DefiningConversion;
import org.geotoolkit.referencing.operation.MathTransformProvider;
import org.geotoolkit.referencing.operation.DefaultMathTransformFactory;
import org.geotoolkit.util.collection.WeakHashSet;
import org.geotoolkit.util.collection.XCollections;
/**
* Builds Geotk implementations of {@linkplain CoordinateReferenceSystem CRS},
* {@linkplain CoordinateSystem CS} and {@linkplain Datum datum} objects. Most factory methods
* expect properties given through a {@link Map} argument. The content of this map is described
* in the {@link ObjectFactory} interface.
*
* @author Martin Desruisseaux (IRD)
* @version 3.01
*
* @since 1.2
* @level advanced
* @module
*/
@Buffered
@ThreadSafe
public class ReferencingObjectFactory extends ReferencingFactory
implements CSFactory, DatumFactory, CRSFactory
{
/**
* The math transform factory. Will be created only when first needed.
*/
private volatile MathTransformFactory mtFactory;
/**
* The datum factory, which should be {@code this} or a {@link DatumAliases} backed
* by {@code this}. This information is stored in order to ensure that every WKT
* parser created by {@link #createFromWKT} use the same factories.
*/
private DatumFactory datumFactory;
/**
* The object to use for parsing Well-Known Text (WKT) strings.
* Values will be created only when first needed.
*/
private final ThreadLocal parser;
/**
* Set of weak references to existing objects (identifiers, CRS, Datum, whatever).
* This set is used in order to return a pre-existing object instead of creating a
* new one.
*/
private final WeakHashSet pool;
/**
* Constructs a default factory. This method is public in order to allows instantiations
* from a {@linkplain java.util.ServiceLoader service loaders}. Users should not instantiate
* this factory directly, but use one of the following lines instead:
*
* {@preformat java
* DatumFactory factory = FactoryFinder.getDatumFactory (null);
* CSFactory factory = FactoryFinder.getCSFactory (null);
* CRSFactory factory = FactoryFinder.getCRSFactory (null);
* }
*
* @see FactoryFinder
*/
public ReferencingObjectFactory() {
this(EMPTY_HINTS);
}
/**
* Constructs a factory with the specified hints. Users should not instantiate this
* factory directly, but use one of the following lines instead:
*
* {@preformat java
* DatumFactory factory = FactoryFinder.getDatumFactory (hints);
* CSFactory factory = FactoryFinder.getCSFactory (hints);
* CRSFactory factory = FactoryFinder.getCRSFactory (hints);
* }
*
* @param hints An optional set of hints, or {@code null} if none.
*
* @see FactoryFinder
*
* @since 2.5
*/
public ReferencingObjectFactory(final Hints hints) {
pool = WeakHashSet.newInstance(IdentifiedObject.class);
parser = new ThreadLocal();
if (!XCollections.isNullOrEmpty(hints)) {
/*
* Creates the dependencies (MathTransform factory, WKT parser...) now because
* we need to process user's hints. Then, we will keep only the relevant hints.
*/
mtFactory = FactoryFinder.getMathTransformFactory(hints);
}
}
/**
* Returns the datum factory, which should be {@code this} or a {@link DatumAliases}
* backed by {@code this}.
*/
private synchronized DatumFactory getDatumFactory() {
if (datumFactory == null) {
datumFactory = this; // The fallback value.
for (final DatumFactory factory : FactoryFinder.getDatumFactories(EMPTY_HINTS)) {
if (factory instanceof DatumAliases) {
if (((DatumAliases) factory).getDatumFactory() == this) {
datumFactory = factory;
break;
}
}
}
}
return datumFactory;
}
/**
* Returns the math transform factory for internal usage only. The hints given to
* {@link ReferencingFactoryFinder} must be null, since the non-null case should
* have been handled by the constructor.
*
* @see #createParser
*/
private MathTransformFactory getMathTransformFactory() {
MathTransformFactory factory = mtFactory;
if (factory == null) {
// Following line must be outside the synchronized block, as a safety against
// deadlocks. This is not a big deal if this information is fetched twice.
final MathTransformFactory candidate = FactoryFinder.getMathTransformFactory(EMPTY_HINTS);
synchronized (this) {
// Double-checked locking - was a deprecated practice before Java 5.
// Is okay since Java 5 provided that the variable is volatile.
factory = mtFactory;
if (factory == null) {
mtFactory = factory = candidate;
hints.put(Hints.MATH_TRANSFORM_FACTORY, factory);
}
}
}
return factory;
}
/**
* Returns the hints used by this factory to customize its use.
*/
@Override
public Map getImplementationHints() {
getMathTransformFactory(); // Forces the initialization of hints.
return super.getImplementationHints();
}
/////////////////////////////////////////////////////////////////////////////////////////
//////// ////////
//////// D A T U M F A C T O R Y ////////
//////// ////////
/////////////////////////////////////////////////////////////////////////////////////////
/**
* Creates an ellipsoid from radius values.
*
* @param properties Name and other properties to give to the new object.
* @param semiMajorAxis Equatorial radius in supplied linear units.
* @param semiMinorAxis Polar radius in supplied linear units.
* @param unit Linear units of ellipsoid axes.
* @throws FactoryException if the object creation failed.
*/
@Override
public Ellipsoid createEllipsoid(final Map properties,
final double semiMajorAxis, final double semiMinorAxis,
final Unit unit) throws FactoryException
{
Ellipsoid ellipsoid;
try {
ellipsoid = DefaultEllipsoid.createEllipsoid(properties,
semiMajorAxis, semiMinorAxis, unit);
} catch (IllegalArgumentException exception) {
throw new FactoryException(exception);
}
ellipsoid = pool.unique(ellipsoid);
return ellipsoid;
}
/**
* Creates an ellipsoid from an major radius, and inverse flattening.
*
* @param properties Name and other properties to give to the new object.
* @param semiMajorAxis Equatorial radius in supplied linear units.
* @param inverseFlattening Eccentricity of ellipsoid.
* @param unit Linear units of major axis.
* @throws FactoryException if the object creation failed.
*/
@Override
public Ellipsoid createFlattenedSphere(final Map properties,
final double semiMajorAxis, final double inverseFlattening,
final Unit unit) throws FactoryException
{
Ellipsoid ellipsoid;
try {
ellipsoid = DefaultEllipsoid.createFlattenedSphere(properties,
semiMajorAxis, inverseFlattening, unit);
} catch (IllegalArgumentException exception) {
throw new FactoryException(exception);
}
ellipsoid = pool.unique(ellipsoid);
return ellipsoid;
}
/**
* Creates a prime meridian, relative to Greenwich.
*
* @param properties Name and other properties to give to the new object.
* @param longitude Longitude of prime meridian in supplied angular units East of Greenwich.
* @param angularUnit Angular units of longitude.
* @throws FactoryException if the object creation failed.
*/
@Override
public PrimeMeridian createPrimeMeridian(final Map properties,
final double longitude, final Unit angularUnit) throws FactoryException
{
PrimeMeridian meridian;
try {
meridian = new DefaultPrimeMeridian(properties, longitude, angularUnit);
} catch (IllegalArgumentException exception) {
throw new FactoryException(exception);
}
meridian = pool.unique(meridian);
return meridian;
}
/**
* Creates geodetic datum from ellipsoid and (optionally) Bursa-Wolf parameters.
*
* @param properties Name and other properties to give to the new object.
* @param ellipsoid Ellipsoid to use in new geodetic datum.
* @param primeMeridian Prime meridian to use in new geodetic datum.
* @throws FactoryException if the object creation failed.
*/
@Override
public GeodeticDatum createGeodeticDatum(final Map properties,
final Ellipsoid ellipsoid, final PrimeMeridian primeMeridian) throws FactoryException
{
GeodeticDatum datum;
try {
datum = new DefaultGeodeticDatum(properties, ellipsoid, primeMeridian);
} catch (IllegalArgumentException exception) {
throw new FactoryException(exception);
}
datum = pool.unique(datum);
return datum;
}
/**
* Creates a vertical datum from an enumerated type value.
*
* @param properties Name and other properties to give to the new object.
* @param type The type of this vertical datum (often geoidal).
* @throws FactoryException if the object creation failed.
*/
@Override
public VerticalDatum createVerticalDatum(final Map properties,
final VerticalDatumType type) throws FactoryException
{
VerticalDatum datum;
try {
datum = new DefaultVerticalDatum(properties, type);
} catch (IllegalArgumentException exception) {
throw new FactoryException(exception);
}
datum = pool.unique(datum);
return datum;
}
/**
* Creates a temporal datum from an enumerated type value.
*
* @param properties Name and other properties to give to the new object.
* @param origin The date and time origin of this temporal datum.
* @throws FactoryException if the object creation failed.
*/
@Override
public TemporalDatum createTemporalDatum(final Map properties,
final Date origin) throws FactoryException
{
TemporalDatum datum;
try {
datum = new DefaultTemporalDatum(properties, origin);
} catch (IllegalArgumentException exception) {
throw new FactoryException(exception);
}
datum = pool.unique(datum);
return datum;
}
/**
* Creates an engineering datum.
*
* @param properties Name and other properties to give to the new object.
* @throws FactoryException if the object creation failed.
*/
@Override
public EngineeringDatum createEngineeringDatum(final Map properties)
throws FactoryException
{
EngineeringDatum datum;
try {
datum = new DefaultEngineeringDatum(properties);
} catch (IllegalArgumentException exception) {
throw new FactoryException(exception);
}
datum = pool.unique(datum);
return datum;
}
/**
* Creates an image datum.
*
* @param properties Name and other properties to give to the new object.
* @param pixelInCell Specification of the way the image grid is associated
* with the image data attributes.
* @throws FactoryException if the object creation failed.
*/
@Override
public ImageDatum createImageDatum(final Map properties,
final PixelInCell pixelInCell) throws FactoryException
{
ImageDatum datum;
try {
datum = new DefaultImageDatum(properties, pixelInCell);
} catch (IllegalArgumentException exception) {
throw new FactoryException(exception);
}
datum = pool.unique(datum);
return datum;
}
/////////////////////////////////////////////////////////////////////////////////////////
//////// ////////
//////// C O O R D I N A T E S Y S T E M F A C T O R Y ////////
//////// ////////
/////////////////////////////////////////////////////////////////////////////////////////
/**
* Creates a coordinate system axis from an abbreviation and a unit.
*
* @param properties Name and other properties to give to the new object.
* @param abbreviation The coordinate axis abbreviation.
* @param direction The axis direction.
* @param unit The coordinate axis unit.
* @throws FactoryException if the object creation failed.
*/
@Override
public CoordinateSystemAxis createCoordinateSystemAxis(final Map properties,
final String abbreviation, final AxisDirection direction,
final Unit unit) throws FactoryException
{
CoordinateSystemAxis axis;
try {
axis = new DefaultCoordinateSystemAxis(properties, abbreviation, direction, unit);
} catch (IllegalArgumentException exception) {
throw new FactoryException(exception);
}
axis = pool.unique(axis);
return axis;
}
/**
* Creates a two dimensional Cartesian coordinate system from the given pair of axis.
*
* @param properties Name and other properties to give to the new object.
* @param axis0 The first axis.
* @param axis1 The second axis.
* @throws FactoryException if the object creation failed.
*/
@Override
public CartesianCS createCartesianCS(final Map properties,
final CoordinateSystemAxis axis0,
final CoordinateSystemAxis axis1) throws FactoryException
{
CartesianCS cs;
try {
cs = new DefaultCartesianCS(properties, axis0, axis1);
} catch (IllegalArgumentException exception) {
throw new FactoryException(exception);
}
cs = pool.unique(cs);
return cs;
}
/**
* Creates a three dimensional Cartesian coordinate system from the given set of axis.
*
* @param properties Name and other properties to give to the new object.
* @param axis0 The first axis.
* @param axis1 The second axis.
* @param axis2 The third axis.
* @throws FactoryException if the object creation failed.
*/
@Override
public CartesianCS createCartesianCS(final Map properties,
final CoordinateSystemAxis axis0,
final CoordinateSystemAxis axis1,
final CoordinateSystemAxis axis2) throws FactoryException
{
CartesianCS cs;
try {
cs = new DefaultCartesianCS(properties, axis0, axis1, axis2);
} catch (IllegalArgumentException exception) {
throw new FactoryException(exception);
}
cs = pool.unique(cs);
return cs;
}
/**
* Creates a two dimensional coordinate system from the given pair of axis.
*
* @param properties Name and other properties to give to the new object.
* @param axis0 The first axis.
* @param axis1 The second axis.
* @throws FactoryException if the object creation failed.
*/
@Override
public AffineCS createAffineCS(final Map properties,
final CoordinateSystemAxis axis0,
final CoordinateSystemAxis axis1) throws FactoryException
{
AffineCS cs;
try {
cs = new DefaultAffineCS(properties, axis0, axis1);
} catch (IllegalArgumentException exception) {
throw new FactoryException(exception);
}
cs = pool.unique(cs);
return cs;
}
/**
* Creates a three dimensional coordinate system from the given set of axis.
*
* @param properties Name and other properties to give to the new object.
* @param axis0 The first axis.
* @param axis1 The second axis.
* @param axis2 The third axis.
* @throws FactoryException if the object creation failed.
*/
@Override
public AffineCS createAffineCS(final Map properties,
final CoordinateSystemAxis axis0,
final CoordinateSystemAxis axis1,
final CoordinateSystemAxis axis2) throws FactoryException
{
AffineCS cs;
try {
cs = new DefaultAffineCS(properties, axis0, axis1, axis2);
} catch (IllegalArgumentException exception) {
throw new FactoryException(exception);
}
cs = pool.unique(cs);
return cs;
}
/**
* Creates a polar coordinate system from the given pair of axis.
*
* @param properties Name and other properties to give to the new object.
* @param axis0 The first axis.
* @param axis1 The second axis.
* @throws FactoryException if the object creation failed.
*/
@Override
public PolarCS createPolarCS(final Map properties,
final CoordinateSystemAxis axis0,
final CoordinateSystemAxis axis1) throws FactoryException
{
PolarCS cs;
try {
cs = new DefaultPolarCS(properties, axis0, axis1);
} catch (IllegalArgumentException exception) {
throw new FactoryException(exception);
}
cs = pool.unique(cs);
return cs;
}
/**
* Creates a cylindrical coordinate system from the given set of axis.
*
* @param properties Name and other properties to give to the new object.
* @param axis0 The first axis.
* @param axis1 The second axis.
* @param axis2 The third axis.
* @throws FactoryException if the object creation failed.
*/
@Override
public CylindricalCS createCylindricalCS(final Map properties,
final CoordinateSystemAxis axis0,
final CoordinateSystemAxis axis1,
final CoordinateSystemAxis axis2) throws FactoryException
{
CylindricalCS cs;
try {
cs = new DefaultCylindricalCS(properties, axis0, axis1, axis2);
} catch (IllegalArgumentException exception) {
throw new FactoryException(exception);
}
cs = pool.unique(cs);
return cs;
}
/**
* Creates a spherical coordinate system from the given set of axis.
*
* @param properties Name and other properties to give to the new object.
* @param axis0 The first axis.
* @param axis1 The second axis.
* @param axis2 The third axis.
* @throws FactoryException if the object creation failed.
*/
@Override
public SphericalCS createSphericalCS(final Map properties,
final CoordinateSystemAxis axis0,
final CoordinateSystemAxis axis1,
final CoordinateSystemAxis axis2) throws FactoryException
{
SphericalCS cs;
try {
cs = new DefaultSphericalCS(properties, axis0, axis1, axis2);
} catch (IllegalArgumentException exception) {
throw new FactoryException(exception);
}
cs = pool.unique(cs);
return cs;
}
/**
* Creates an ellipsoidal coordinate system without ellipsoidal height.
*
* @param properties Name and other properties to give to the new object.
* @param axis0 The first axis.
* @param axis1 The second axis.
* @throws FactoryException if the object creation failed.
*/
@Override
public EllipsoidalCS createEllipsoidalCS(final Map properties,
final CoordinateSystemAxis axis0,
final CoordinateSystemAxis axis1) throws FactoryException
{
EllipsoidalCS cs;
try {
cs = new DefaultEllipsoidalCS(properties, axis0, axis1);
} catch (IllegalArgumentException exception) {
throw new FactoryException(exception);
}
cs = pool.unique(cs);
return cs;
}
/**
* Creates an ellipsoidal coordinate system with ellipsoidal height.
*
* @param properties Name and other properties to give to the new object.
* @param axis0 The first axis.
* @param axis1 The second axis.
* @param axis2 The third axis.
* @throws FactoryException if the object creation failed.
*/
@Override
public EllipsoidalCS createEllipsoidalCS(final Map properties,
final CoordinateSystemAxis axis0,
final CoordinateSystemAxis axis1,
final CoordinateSystemAxis axis2) throws FactoryException
{
EllipsoidalCS cs;
try {
cs = new DefaultEllipsoidalCS(properties, axis0, axis1, axis2);
} catch (IllegalArgumentException exception) {
throw new FactoryException(exception);
}
cs = pool.unique(cs);
return cs;
}
/**
* Creates a vertical coordinate system.
*
* @param properties Name and other properties to give to the new object.
* @param axis The axis.
* @throws FactoryException if the object creation failed.
*/
@Override
public VerticalCS createVerticalCS(final Map properties,
final CoordinateSystemAxis axis) throws FactoryException
{
VerticalCS cs;
try {
cs = new DefaultVerticalCS(properties, axis);
} catch (IllegalArgumentException exception) {
throw new FactoryException(exception);
}
cs = pool.unique(cs);
return cs;
}
/**
* Creates a temporal coordinate system.
*
* @param properties Name and other properties to give to the new object.
* @param axis The axis.
* @throws FactoryException if the object creation failed.
*/
@Override
public TimeCS createTimeCS(final Map properties,
final CoordinateSystemAxis axis) throws FactoryException
{
TimeCS cs;
try {
cs = new DefaultTimeCS(properties, axis);
} catch (IllegalArgumentException exception) {
throw new FactoryException(exception);
}
cs = pool.unique(cs);
return cs;
}
/**
* Creates a linear coordinate system.
*
* @param properties Name and other properties to give to the new object.
* @param axis The axis.
* @throws FactoryException if the object creation failed.
*/
@Override
public LinearCS createLinearCS(final Map properties,
final CoordinateSystemAxis axis) throws FactoryException
{
LinearCS cs;
try {
cs = new DefaultLinearCS(properties, axis);
} catch (IllegalArgumentException exception) {
throw new FactoryException(exception);
}
cs = pool.unique(cs);
return cs;
}
/**
* Creates a two dimensional user defined coordinate system from the given pair of axis.
*
* @param properties Name and other properties to give to the new object.
* @param axis0 The first axis.
* @param axis1 The second axis.
* @throws FactoryException if the object creation failed.
*/
@Override
public UserDefinedCS createUserDefinedCS(final Map properties,
final CoordinateSystemAxis axis0,
final CoordinateSystemAxis axis1) throws FactoryException
{
UserDefinedCS cs;
try {
cs = new DefaultUserDefinedCS(properties, axis0, axis1);
} catch (IllegalArgumentException exception) {
throw new FactoryException(exception);
}
cs = pool.unique(cs);
return cs;
}
/**
* Creates a three dimensional user defined coordinate system from the given set of axis.
*
* @param properties Name and other properties to give to the new object.
* @param axis0 The first axis.
* @param axis1 The second axis.
* @param axis2 The third axis.
* @throws FactoryException if the object creation failed.
*/
@Override
public UserDefinedCS createUserDefinedCS(final Map properties,
final CoordinateSystemAxis axis0,
final CoordinateSystemAxis axis1,
final CoordinateSystemAxis axis2) throws FactoryException
{
UserDefinedCS cs;
try {
cs = new DefaultUserDefinedCS(properties, axis0, axis1, axis2);
} catch (IllegalArgumentException exception) {
throw new FactoryException(exception);
}
cs = pool.unique(cs);
return cs;
}
/////////////////////////////////////////////////////////////////////////////////////////
//////// ////////
//////// C O O R D I N A T E R E F E R E N C E S Y S T E M F A C T O R Y ////////
//////// ////////
/////////////////////////////////////////////////////////////////////////////////////////
/**
* Creates a compound coordinate reference system from an ordered
* list of {@code CoordinateReferenceSystem} objects.
*
* @param properties Name and other properties to give to the new object.
* @param elements ordered array of {@code CoordinateReferenceSystem} objects.
* @throws FactoryException if the object creation failed.
*/
@Override
public CompoundCRS createCompoundCRS(final Map properties,
final CoordinateReferenceSystem... elements) throws FactoryException
{
CompoundCRS crs;
try {
crs = new DefaultCompoundCRS(properties, elements);
} catch (IllegalArgumentException exception) {
throw new FactoryException(exception);
}
crs = pool.unique(crs);
return crs;
}
/**
* Creates a engineering coordinate reference system.
*
* @param properties Name and other properties to give to the new object.
* @param datum Engineering datum to use in created CRS.
* @param cs The coordinate system for the created CRS.
* @throws FactoryException if the object creation failed.
*/
@Override
public EngineeringCRS createEngineeringCRS(final Map properties,
final EngineeringDatum datum, final CoordinateSystem cs) throws FactoryException
{
EngineeringCRS crs;
try {
crs = new DefaultEngineeringCRS(properties, datum, cs);
} catch (IllegalArgumentException exception) {
throw new FactoryException(exception);
}
crs = pool.unique(crs);
return crs;
}
/**
* Creates an image coordinate reference system.
*
* @param properties Name and other properties to give to the new object.
* @param datum Image datum to use in created CRS.
* @param cs The Cartesian or Oblique Cartesian coordinate system for the created CRS.
* @throws FactoryException if the object creation failed.
*/
@Override
public ImageCRS createImageCRS(final Map properties,
final ImageDatum datum, final AffineCS cs) throws FactoryException
{
ImageCRS crs;
try {
crs = new DefaultImageCRS(properties, datum, cs);
} catch (IllegalArgumentException exception) {
throw new FactoryException(exception);
}
crs = pool.unique(crs);
return crs;
}
/**
* Creates a temporal coordinate reference system.
*
* @param properties Name and other properties to give to the new object.
* @param datum Temporal datum to use in created CRS.
* @param cs The Temporal coordinate system for the created CRS.
* @throws FactoryException if the object creation failed.
*/
@Override
public TemporalCRS createTemporalCRS(final Map properties,
final TemporalDatum datum, final TimeCS cs) throws FactoryException
{
TemporalCRS crs;
try {
crs = new DefaultTemporalCRS(properties, datum, cs);
} catch (IllegalArgumentException exception) {
throw new FactoryException(exception);
}
crs = pool.unique(crs);
return crs;
}
/**
* Creates a vertical coordinate reference system.
*
* @param properties Name and other properties to give to the new object.
* @param datum Vertical datum to use in created CRS.
* @param cs The Vertical coordinate system for the created CRS.
* @throws FactoryException if the object creation failed.
*/
@Override
public VerticalCRS createVerticalCRS(final Map properties,
final VerticalDatum datum, final VerticalCS cs) throws FactoryException
{
VerticalCRS crs;
try {
crs = new DefaultVerticalCRS(properties, datum, cs);
} catch (IllegalArgumentException exception) {
throw new FactoryException(exception);
}
crs = pool.unique(crs);
return crs;
}
/**
* Creates a geocentric coordinate reference system from a {@linkplain CartesianCS
* Cartesian coordinate system}.
*
* @param properties Name and other properties to give to the new object.
* @param datum Geodetic datum to use in created CRS.
* @param cs The Cartesian coordinate system for the created CRS.
* @throws FactoryException if the object creation failed.
*/
@Override
public GeocentricCRS createGeocentricCRS(final Map properties,
final GeodeticDatum datum, final CartesianCS cs) throws FactoryException
{
GeocentricCRS crs;
try {
crs = new DefaultGeocentricCRS(properties, datum, cs);
} catch (IllegalArgumentException exception) {
throw new FactoryException(exception);
}
crs = pool.unique(crs);
return crs;
}
/**
* Creates a geocentric coordinate reference system from a {@linkplain SphericalCS
* spherical coordinate system}.
*
* @param properties Name and other properties to give to the new object.
* @param datum Geodetic datum to use in created CRS.
* @param cs The spherical coordinate system for the created CRS.
* @throws FactoryException if the object creation failed.
*/
@Override
public GeocentricCRS createGeocentricCRS(final Map properties,
final GeodeticDatum datum, final SphericalCS cs) throws FactoryException
{
GeocentricCRS crs;
try {
crs = new DefaultGeocentricCRS(properties, datum, cs);
} catch (IllegalArgumentException exception) {
throw new FactoryException(exception);
}
crs = pool.unique(crs);
return crs;
}
/**
* Creates a geographic coordinate reference system.
* It could be Latitude/Longitude or
* Longitude/Latitude.
*
* @param properties Name and other properties to give to the new object.
* @param datum Geodetic datum to use in created CRS.
* @param cs The ellipsoidal coordinate system for the created CRS.
* @throws FactoryException if the object creation failed.
*/
@Override
public GeographicCRS createGeographicCRS(final Map properties,
final GeodeticDatum datum, final EllipsoidalCS cs) throws FactoryException
{
GeographicCRS crs;
try {
crs = new DefaultGeographicCRS(properties, datum, cs);
} catch (IllegalArgumentException exception) {
throw new FactoryException(exception);
}
crs = pool.unique(crs);
return crs;
}
/**
* Creates a derived coordinate reference system from a conversion.
* It is the user's responsibility to ensure that the conversion performs all required steps,
* including {@linkplain AbstractCS#swapAndScaleAxis unit conversions and change of axis order},
* if needed.
*
* @param properties Name and other properties to give to the new object.
* @param baseCRS Coordinate reference system to base projection on.
* @param conversionFromBase The {@linkplain DefiningConversion defining conversion}.
* @param derivedCS The coordinate system for the derived CRS.
* @throws FactoryException if the object creation failed.
*
* @since 2.5
*/
@Override
public DerivedCRS createDerivedCRS(final Map properties,
final CoordinateReferenceSystem baseCRS, final Conversion conversionFromBase,
final CoordinateSystem derivedCS) throws FactoryException
{
MathTransform mt = conversionFromBase.getMathTransform();
if (mt == null) {
final ParameterValueGroup parameters = conversionFromBase.getParameterValues();
final MathTransformFactory mtFactory = getMathTransformFactory();
mt = mtFactory.createParameterizedTransform(parameters);
}
DerivedCRS crs;
try {
crs = new DefaultDerivedCRS(properties, conversionFromBase, baseCRS, mt, derivedCS);
} catch (IllegalArgumentException exception) {
throw new FactoryException(exception);
}
crs = pool.unique(crs);
return crs;
}
/**
* Creates a projected coordinate reference system from a conversion. The supplied
* conversion should not includes the operation steps for performing
* {@linkplain AbstractCS#swapAndScaleAxis unit conversions and change of axis order}
* since those operations will be inferred by this constructor
*
* @param properties Name and other properties to give to the new object.
* @param baseCRS Geographic coordinate reference system to base projection on.
* @param conversionFromBase The {@linkplain DefiningConversion defining conversion}.
* @param derivedCS The coordinate system for the projected CRS.
* @throws FactoryException if the object creation failed.
*
* @since 2.5
*/
@Override
public ProjectedCRS createProjectedCRS(Map properties,
final GeographicCRS baseCRS, final Conversion conversionFromBase,
final CartesianCS derivedCS) throws FactoryException
{
MathTransform mt;
final MathTransform existing = conversionFromBase.getMathTransform();
final MathTransformFactory mtFactory = getMathTransformFactory();
if (existing != null && mtFactory instanceof DefaultMathTransformFactory) {
/*
* In the particular case of Geotk implementation, we use a shortcut which avoid
* the cost of creating a new parameterized transform; we use directly the existing
* transform instance instead. It also avoid slight rounding errors as a side-effect.
* This is because transforms are free to convert angular parameters from degrees to
* radians, store the values internally in radians, and convert then back to degrees
* when 'conversionFromBase.getParameterValues()' is invoked. This sometime result in
* slightly different values than the original ones. Those differences are enough for
* getting a math transform which is different in the sense of equals(Object), with
* the usual consequences on cached instances.
*/
mt = ((DefaultMathTransformFactory) mtFactory).createBaseToDerived(baseCRS, existing, derivedCS);
} else {
/*
* Non-Geotk implementation, or no existing MathTransform instance.
* Creates the transform from the parameters.
*/
final ParameterValueGroup parameters = conversionFromBase.getParameterValues();
mt = mtFactory.createBaseToDerived(baseCRS, parameters, derivedCS);
OperationMethod method = conversionFromBase.getMethod();
if (!(method instanceof MathTransformProvider)) {
/*
* Our Geotk implementation of DefaultProjectedCRS may not be able to detect
* the conversion type (PlanarProjection, CylindricalProjection, etc.) because
* we rely on the Geotk-specific MathTransformProvider for that. We will try
* to help it with the optional "conversionType" hint, providing that the user
* does not already provide this hint.
*/
if (!properties.containsKey(DefaultProjectedCRS.CONVERSION_TYPE_KEY)) {
method = mtFactory.getLastMethodUsed();
if (method instanceof MathTransformProvider) {
final Map copy = new HashMap(properties);
copy.put(DefaultProjectedCRS.CONVERSION_TYPE_KEY,
((MathTransformProvider) method).getOperationType());
properties = copy;
}
}
}
/*
* If the user gave an explicit conversion, checks if it is suitable.
* It may not be suitable is unit conversion, axis switch, etc. have
* been inserted in the operation chain by 'createBaseToDerived'.
*/
if (existing != null && existing.equals(mt)) {
mt = existing;
}
}
ProjectedCRS crs;
try {
crs = new DefaultProjectedCRS(properties, conversionFromBase, baseCRS, mt, derivedCS);
} catch (IllegalArgumentException exception) {
throw new FactoryException(exception);
}
crs = pool.unique(crs);
return crs;
}
/**
* Creates a coordinate reference system object from a XML string.
*
* @param xml Coordinate reference system encoded in XML format.
* @throws FactoryException if the object creation failed.
*
* @todo Not yet implemented.
*/
@Override
public CoordinateReferenceSystem createFromXML(final String xml) throws FactoryException {
throw new FactoryException("Not yet implemented");
}
/**
* Creates a coordinate reference system object from a string.
*
* @param wkt Coordinate system encoded in Well-Known Text format.
* @throws FactoryException if the object creation failed.
*/
@Override
public CoordinateReferenceSystem createFromWKT(final String wkt) throws FactoryException {
/*
* Note: while this factory is thread safe, the WKT parser is not.
* We need either to synchronize, or use one instance per thread.
*/
ReferencingParser parser = this.parser.get();
if (parser == null) {
parser = new ReferencingParser(Symbols.DEFAULT,
getDatumFactory(), this, this, getMathTransformFactory());
parser.setISOConform(true);
this.parser.set(parser);
}
try {
return parser.parseCoordinateReferenceSystem(wkt);
} catch (ParseException exception) {
final Throwable cause = exception.getCause();
if (cause instanceof FactoryException) {
throw (FactoryException) cause;
}
throw new FactoryException(exception);
}
}
}