Author: aaime Date: 2012-05-06 03:24:21 -0700 (Sun, 06 May 2012) New Revision: 38703 Added: trunk/modules/library/referencing/src/main/java/org/geotools/referencing/factory/PropertyCoordinateOperationAuthorityFactory.java trunk/modules/library/referencing/src/main/java/org/geotools/referencing/factory/epsg/CoordinateOperationFactoryUsingWKT.java trunk/modules/library/referencing/src/test/java/org/geotools/referencing/factory/epsg/CoordinateOperationFactoryUsingWKTTest.java trunk/modules/library/referencing/src/test/resources/org/geotools/referencing/factory/epsg/epsg_operations.properties trunk/modules/plugin/epsg-hsql/src/test/java/org/geotools/referencing/factory/epsg/LongitudeFirstFactoryOverrideTest.java trunk/modules/plugin/epsg-hsql/src/test/resources/org/geotools/referencing/factory/epsg/ trunk/modules/plugin/epsg-hsql/src/test/resources/org/geotools/referencing/factory/epsg/epsg.properties trunk/modules/plugin/epsg-hsql/src/test/resources/org/geotools/referencing/factory/epsg/epsg_operations.properties Modified: trunk/modules/library/referencing/src/main/java/org/geotools/referencing/factory/DeferredAuthorityFactory.java trunk/modules/library/referencing/src/main/java/org/geotools/referencing/wkt/MathTransformParser.java trunk/modules/library/referencing/src/main/resources/META-INF/services/org.opengis.referencing.operation.CoordinateOperationAuthorityFactory trunk/modules/library/referencing/src/test/resources/org/geotools/referencing/factory/epsg/epsg.properties trunk/modules/plugin/epsg-hsql/src/test/java/org/geotools/referencing/factory/URN_EPSG_Test.java Log: [GEOT-4108] File based CoordinateOperation factory Modified: trunk/modules/library/referencing/src/main/java/org/geotools/referencing/factory/DeferredAuthorityFactory.java =================================================================== --- trunk/modules/library/referencing/src/main/java/org/geotools/referencing/factory/DeferredAuthorityFactory.java 2012-05-04 15:22:05 UTC (rev 38702) +++ trunk/modules/library/referencing/src/main/java/org/geotools/referencing/factory/DeferredAuthorityFactory.java 2012-05-06 10:24:21 UTC (rev 38703) @@ -126,7 +126,7 @@ * @throws FactoryException if the creation of backing store failed. */ @Override - final AbstractAuthorityFactory getBackingStore() throws FactoryException { + protected final AbstractAuthorityFactory getBackingStore() throws FactoryException { if (backingStore == null) { synchronized (this) { if(backingStore == null) { Added: trunk/modules/library/referencing/src/main/java/org/geotools/referencing/factory/PropertyCoordinateOperationAuthorityFactory.java =================================================================== --- trunk/modules/library/referencing/src/main/java/org/geotools/referencing/factory/PropertyCoordinateOperationAuthorityFactory.java (rev 0) +++ trunk/modules/library/referencing/src/main/java/org/geotools/referencing/factory/PropertyCoordinateOperationAuthorityFactory.java 2012-05-06 10:24:21 UTC (rev 38703) @@ -0,0 +1,342 @@ +/* + * GeoTools - The Open Source Java GIS Toolkit + * http://geotools.org + * + * (C) 2002-2012, Open Source Geospatial Foundation (OSGeo) + * + * 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. + */ +package org.geotools.referencing.factory; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Properties; +import java.util.Set; + +import org.geotools.referencing.CRS; +import org.geotools.referencing.operation.DefaultMathTransformFactory; +import org.geotools.referencing.operation.DefaultOperation; +import org.geotools.referencing.operation.DefaultOperationMethod; +import org.geotools.referencing.operation.transform.AbstractMathTransform; +import org.geotools.referencing.operation.transform.AffineTransform2D; +import org.geotools.util.SimpleInternationalString; +import org.opengis.metadata.citation.Citation; +import org.opengis.referencing.FactoryException; +import org.opengis.referencing.IdentifiedObject; +import org.opengis.referencing.NoSuchAuthorityCodeException; +import org.opengis.referencing.crs.CoordinateReferenceSystem; +import org.opengis.referencing.operation.CoordinateOperation; +import org.opengis.referencing.operation.CoordinateOperationAuthorityFactory; +import org.opengis.referencing.operation.MathTransform; +import org.opengis.referencing.operation.NoninvertibleTransformException; +import org.opengis.referencing.operation.OperationMethod; +import org.opengis.util.InternationalString; + +/** + * A {@link CoordinateOperationAuthorityFactory} backed by a properties file. + * Allows custom transform definitions across two CRSs, expressed as WKT math transforms. + * Entries in the properties file take this format: + * <pre> + * [source crs code],[target crs code]=[WKT math transform] + * </pre> + * Examples: + * <pre> + * 4230,4258=PARAM_MT["NTv2", PARAMETER["Latitude and longitude difference file", "100800401.gsb"]] + * 23031,25831=PARAM_MT["Similarity transformation", \ + * PARAMETER["Ordinate 1 of evaluation point in target CRS", -129.549], \ + * PARAMETER["Ordinate 2 of evaluation point in target CRS", -208.185], \ + * PARAMETER["Scale difference", 1.0000015504], \ + * PARAMETER["Rotation angle of source coordinate reference system axes", 1.56504]] + * </pre> + * For more compact definitions, parameter names can be replaced by their corresponding EPSG codes. + * Following examples are the same as former ones: + * <pre> + * 4230,4258=PARAM_MT["9615", PARAMETER["8656", "100800401.gsb"]] + * 23031,25831=PARAM_MT["9621", \ + * PARAMETER["8621", -129.549], \ + * PARAMETER["8622", -208.185], \ + * PARAMETER["8611", 1.0000015504], \ + * PARAMETER["8614", 1.56504]] + * </pre> + * References: + * <p> + * See <a href="http://www.geoapi.org/3.0/javadoc/org/opengis/referencing/doc-files/WKT.html"> + * <cite>Well-Known Text format</cite></a> for math transform syntax. + * Visit the <a href="http://www.epsg-registry.org/"> <cite>EPSG Geodetic Parameter Registry</cite> + * </a> for EPSG parameter codes and values. + * <p> + * Note that invertible transforms will be used in both directions. + * <p> + * This factory doesn't cache any result. Any call to a {@code createFoo} method will trig a new + * WKT parsing. For caching, this factory should be wrapped in some buffered factory like + * {@link BufferedAuthorityFactory}. + * + * @source $URL$ + * @version $Id$ + * @author Oscar Fonts + */ +public class PropertyCoordinateOperationAuthorityFactory extends + DirectAuthorityFactory implements CoordinateOperationAuthorityFactory { + + /** + * The authority for this factory. + */ + private final Citation authority; + + /** + * The properties object for our properties file. Keys are CRS code pairs + * separated by a comma. The associated value is a WKT string for the Math + * Transform. See {@link PropertyCoordinateOperationAuthorityFactory}. + */ + private final Properties definitions = new Properties(); + + /** + * An unmodifiable view of the authority keys. This view is always up to date + * even if entries are added or removed in the {@linkplain #definitions} map. + */ + @SuppressWarnings({ "rawtypes", "unchecked" }) + private final Set<String> codes = Collections.unmodifiableSet((Set) definitions.keySet()); + + /** + * Creates a factory for the specified authority from the specified file. + * + * @param factories The underlying factories used for objects creation. + * @param authority The organization or party responsible for definition and maintenance of + * the database. + * @param definitions URL to the definition file. + * @throws IOException if the definitions can't be read. + */ + public PropertyCoordinateOperationAuthorityFactory( + final ReferencingFactoryContainer factories, + final Citation authority, + final URL definitions) + throws IOException + { + // Set priority low + super(factories, MINIMUM_PRIORITY + 10); + + // Set authority + this.authority = authority; + ensureNonNull("authority", authority); + + // Load properties + final InputStream in = definitions.openStream(); + this.definitions.load(in); + in.close(); + } + + /** + * Creates an operation from a single operation code. + * + * @param code Coded value for operation. + * @return The operation for the given code. + * @throws NoSuchAuthorityCodeException if the specified {@code code} was not found. + * @throws FactoryException if the object creation failed for some other reason. + */ + @Override + public CoordinateOperation createCoordinateOperation(String code) + throws NoSuchAuthorityCodeException, FactoryException { + String[] crsPair = trimAuthority(code).split(","); + if (crsPair.length == 2) { + Set<CoordinateOperation> coordopset = createFromCoordinateReferenceSystemCodes( + trimAuthority(crsPair[0]), trimAuthority(crsPair[1])); + if (!coordopset.isEmpty()) { + return coordopset.iterator().next(); + } + } + return null; + } + + /** + * Creates a {@link CoordinateOperation} from + * {@linkplain CoordinateReferenceSystem coordinate reference system} codes. + * This method returns a single operation from the properties file. + * If operation is invertible, will check also for the inverse one. + * If operation not found, it will return an empty set. + * + * @param sourceCRS Coded value of source coordinate reference system. + * @param targetCRS Coded value of target coordinate reference system. + * @return The operation from {@code sourceCRS} to {@code targetCRS} (one single element). + * @throws NoSuchAuthorityCodeException if a specified code was not found. + * @throws FactoryException if the object creation failed for some other reason. + */ + @Override + public Set<CoordinateOperation> createFromCoordinateReferenceSystemCodes( + String sourceCRS, String targetCRS) + throws NoSuchAuthorityCodeException, FactoryException { + + Set<CoordinateOperation> coordops = new HashSet<CoordinateOperation>(1); + + CoordinateOperation coordop = createFromCoordinateReferenceSystemCodes(sourceCRS, + targetCRS, false); + if (coordop == null) { + // Not found. Try to create from the inverse. + coordop = createFromCoordinateReferenceSystemCodes(targetCRS, sourceCRS, true); + } + if (coordop != null) { + // Add to set if found. + coordops.add(coordop); + } + return coordops; + } + + + /** + * Seeks for a WKT definition in the properties file from a CRS pair, parses it, + * and creates the corresponding CoordinateOperation. Returns {@code null} + * if something went wrong. + * <p> + * Will log a WARNING message if a parsing error occurred. + * + * @param sourceCRS Coded value of source coordinate reference system. + * @param targetCRS Coded value of target coordinate reference system. + * @param inverse {@code true} to create operation from the inverse definition. + * @return The operation from {@code sourceCRS} to {@code targetCRS}, + * or {@code null} if not found. + * @throws NoSuchAuthorityCodeException if a specified code was not found. + * @throws FactoryException if the object creation failed for some other reason. + */ + CoordinateOperation createFromCoordinateReferenceSystemCodes( + String sourceCRS, String targetCRS, boolean inverse) + throws NoSuchAuthorityCodeException, FactoryException { + + // Get WKT definition from properties + sourceCRS = trimAuthority(sourceCRS); + targetCRS = trimAuthority(targetCRS); + String id = sourceCRS+","+targetCRS; + String WKT = definitions.getProperty(id); + if(WKT == null) { + // No definition found. + return null; + } + + // Create MathTransform from WKT + MathTransform mt = null; + try { + mt = factories.getMathTransformFactory().createFromWKT(WKT); + } catch (FactoryException e) { + // Probably malformed WKT. + LOGGER.warning("Error creating transformation: " + WKT); + return null; + } + + // Create the CRS definitions + String s = this.authority.getIdentifiers().iterator().next().getCode(); + CoordinateReferenceSystem source = CRS.decode(s+":"+sourceCRS); + CoordinateReferenceSystem target = CRS.decode(s+":"+targetCRS); + + // Need to create a derived MathTransform that will handle axis order and units + // as defined in CRS. Had to cast to DefaultMathTransformFactory because + // createBaseToDerived is not defined in MathTransformFactory interface (GeoAPI). + DefaultMathTransformFactory mtf = (DefaultMathTransformFactory)factories. + getMathTransformFactory(); + MathTransform mt2 = mtf.createBaseToDerived(source, mt, target.getCoordinateSystem()); + + // Extract name from the transform, if possible, or use class name. + String methodName; + try { + if (mt instanceof AbstractMathTransform) { + methodName = ((AbstractMathTransform)mt).getParameterValues().getDescriptor().getName().getCode(); + } else if (mt instanceof AffineTransform2D) { + methodName = ((AffineTransform2D)mt).getParameterValues().getDescriptor().getName().getCode(); + } else { + methodName = mt.getClass().getSimpleName(); + } + } catch (NullPointerException e) { + methodName = mt.getClass().getSimpleName(); + } + Map<String, String> props = new HashMap<String, String>(); + props.put("name", methodName); + + // Create the OperationMethod + OperationMethod method = new DefaultOperationMethod(props, + mt2.getSourceDimensions(), mt2.getTargetDimensions(), null); + + // Finally create CoordinateOperation + CoordinateOperation coordop = null; + if (!inverse) { // Direct operation + props.put("name", sourceCRS + " \u21E8 " + targetCRS); + coordop = DefaultOperation.create(props, source, target, + mt2, method, CoordinateOperation.class); + } else { // Inverse operation + try { + props.put("name", targetCRS + " \u21E8 " + sourceCRS); + coordop = DefaultOperation.create(props, target, source, + mt2.inverse(), method, CoordinateOperation.class); + } catch (NoninvertibleTransformException e) { + return null; + } + } + return coordop; + } + + /** + * Returns the set of authority codes of the given type. + * Only CoordinateOperation.class is accepted as type. + * + * This factory will not filter codes for its subclasses. + * + * @param type The CoordinateOperation type (or null, same effect). + * @return All of available authority codes, or an empty set. + */ + @Override + public Set<String> getAuthorityCodes(Class<? extends IdentifiedObject> type) { + if (type==null || type.isAssignableFrom(CoordinateOperation.class)) { + return codes; + } else { + return Collections.emptySet(); + } + } + + /** + * Gets a description of the object corresponding to a code. + * + * @param code Value allocated by authority. + * @return A description of the object, or {@code null} if the object + * corresponding to the specified {@code code} has no description. + * @throws NoSuchAuthorityCodeException if the specified {@code code} was not found. + * @throws FactoryException if the query failed for some other reason. + */ + @Override + public InternationalString getDescriptionText(String code) + throws NoSuchAuthorityCodeException, FactoryException { + + final String wkt = definitions.getProperty(trimAuthority(code)); + + if (wkt == null) { + throw noSuchAuthorityCode(IdentifiedObject.class, code); + } + + // The first string literal in WKT will be considered the description text. + int start = wkt.indexOf('"'); + if (start >= 0) { + final int end = wkt.indexOf('"', ++start); + if (end >= 0) { + return new SimpleInternationalString(wkt.substring(start, end).trim()); + } + } + return null; + } + + /** + * Returns the organization or party responsible for definition and maintenance of the + * database. + */ + @Override + public Citation getAuthority() { + return authority; + } +} Added: trunk/modules/library/referencing/src/main/java/org/geotools/referencing/factory/epsg/CoordinateOperationFactoryUsingWKT.java =================================================================== --- trunk/modules/library/referencing/src/main/java/org/geotools/referencing/factory/epsg/CoordinateOperationFactoryUsingWKT.java (rev 0) +++ trunk/modules/library/referencing/src/main/java/org/geotools/referencing/factory/epsg/CoordinateOperationFactoryUsingWKT.java 2012-05-06 10:24:21 UTC (rev 38703) @@ -0,0 +1,329 @@ +/* + * GeoTools - The Open Source Java GIS Toolkit + * http://geotools.org + * + * (C) 2002-2012, Open Source Geospatial Foundation (OSGeo) + * + * 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. + */ +package org.geotools.referencing.factory.epsg; + +import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Iterator; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.LogRecord; + +import org.geotools.factory.GeoTools; +import org.geotools.factory.Hints; +import org.geotools.metadata.iso.citation.Citations; +import org.geotools.referencing.ReferencingFactoryFinder; +import org.geotools.referencing.factory.AbstractAuthorityFactory; +import org.geotools.referencing.factory.DeferredAuthorityFactory; +import org.geotools.referencing.factory.FactoryNotFoundException; +import org.geotools.referencing.factory.PropertyCoordinateOperationAuthorityFactory; +import org.geotools.referencing.factory.ReferencingFactoryContainer; +import org.geotools.resources.i18n.ErrorKeys; +import org.geotools.resources.i18n.Errors; +import org.geotools.resources.i18n.LoggingKeys; +import org.geotools.resources.i18n.Loggings; +import org.geotools.util.logging.Logging; +import org.opengis.metadata.Identifier; +import org.opengis.metadata.citation.Citation; +import org.opengis.referencing.FactoryException; +import org.opengis.referencing.NoSuchAuthorityCodeException; +import org.opengis.referencing.crs.CoordinateReferenceSystem; +import org.opengis.referencing.operation.CoordinateOperation; +import org.opengis.referencing.operation.CoordinateOperationAuthorityFactory; + +/** + * Authority factory that holds user-defined + * {@linkplain CoordinateOperation Coordinate Operations}. + * <p> + * This factory can be used as a replacement for Coordinate Operations when there is no access + * to a complete EPSG database. Or can be used to override the coordinate operations defined in + * EPSG if assigned a higher priority. + * <p> + * The Coordinate Operations are defined as <cite>Well Known Text</cite> math transforms (see + * {@link PropertyCoordinateOperationAuthorityFactory} for format specification and examples). + * <p> + * Property file name is {@value #FILENAME}, and its possible locations are described + * {@linkplain #FILENAME here}. If no property file is found, the factory won't be activated. + * <p> + * If an operation is not found in the properties file, this factory will delegate + * creation on a fallback factory. The fallback factory is the next registered + * {@link CoordinateOperationAuthorityFactory} after this one in the + * {@linkplain org.geotools.factory.AbstractFactory#priority priority} chain. + * + * @source $URL$ + * @version $Id$ + * @author Oscar Fonts + */ +public class CoordinateOperationFactoryUsingWKT extends DeferredAuthorityFactory + implements CoordinateOperationAuthorityFactory { + /** + * The authority. Will be created only when first needed. + * + * @see #getAuthority + */ + protected Citation authority; + + /** + * The default filename to read. The default {@code FactoryUsingWKT} implementation will + * search for the first occurence of this file in the following places: + * <p> + * <ul> + * <li>In the directory specified by the + * {@value org.geotools.factory.GeoTools#CRS_AUTHORITY_EXTRA_DIRECTORY} + * system property.</li> + * <li>In every {@code org/geotools/referencing/factory/espg} directories found on the + * classpath.</li> + * </ul> + * <p> + * + * @see #getDefinitionsURL + */ + public static final String FILENAME = "epsg_operations.properties"; + + /** + * Priority for this factory + */ + public static final int PRIORITY = NORMAL_PRIORITY - 20; + + /** + * The factories to be given to the backing store. + */ + protected final ReferencingFactoryContainer factories; + + /** + * Directory scanned for extra definitions. + */ + protected final String directory; + + /** + * An alternate factory to be used when the primary one doesn't find an operation + */ + protected CoordinateOperationAuthorityFactory fallbackAuthorityFactory = null; + + /** + * Just a flag not to search more than once + */ + protected boolean fallbackAuthorityFactorySearched = false; + + /** + * Constructs an authority factory using the default set of factories. + */ + public CoordinateOperationFactoryUsingWKT() { + this(null, PRIORITY); + } + + /** + * Constructs an authority factory using a set of factories created from the specified hints. + */ + public CoordinateOperationFactoryUsingWKT(Hints userHints) { + this(userHints, PRIORITY); + } + + /** + * Constructs an authority factory using the specified hints and priority. + */ + protected CoordinateOperationFactoryUsingWKT(final Hints userHints, final int priority) { + super(userHints, priority); + factories = ReferencingFactoryContainer.instance(userHints); + + // Search for user CRS_AUTHORITY_EXTRA_DIRECTORY hint, or use system default value. + Object directoryHint = null; + if (userHints != null && userHints.get(Hints.CRS_AUTHORITY_EXTRA_DIRECTORY) != null) { + directoryHint = userHints.get(Hints.CRS_AUTHORITY_EXTRA_DIRECTORY); + } else if (Hints.getSystemDefault(Hints.CRS_AUTHORITY_EXTRA_DIRECTORY) != null) { + directoryHint = Hints.getSystemDefault(Hints.CRS_AUTHORITY_EXTRA_DIRECTORY); + } + if (directoryHint != null) { + directory = directoryHint.toString(); + hints.put(Hints.CRS_AUTHORITY_EXTRA_DIRECTORY, directory); + } else { + directory = null; + } + + } + + public synchronized Citation getAuthority() { + if (authority == null) { + authority = Citations.EPSG; + } + return authority; + } + + /** + * Creates the backing store authority factory. + * + * @return The backing store to uses in {@code createXXX(...)} methods. + * @throws FactoryNotFoundException if the {@code properties} file has not been found. + * @throws FactoryException if the constructor failed to find or read the file. + * This exception usually has an {@link IOException} as its cause. + */ + protected AbstractAuthorityFactory createBackingStore() throws FactoryException { + try { + URL url = getDefinitionsURL(); + if (url == null) { + throw new FactoryNotFoundException(Errors.format( + ErrorKeys.FILE_DOES_NOT_EXIST_$1, FILENAME)); + } + final Iterator<? extends Identifier> ids = getAuthority().getIdentifiers().iterator(); + final String authority = ids.hasNext() ? ids.next().getCode() : "EPSG"; + final LogRecord record = Loggings.format(Level.CONFIG, + LoggingKeys.USING_FILE_AS_FACTORY_$2, url.getPath(), authority); + record.setLoggerName(LOGGER.getName()); + LOGGER.log(record); + return new PropertyCoordinateOperationAuthorityFactory(factories, this.getAuthority(), url); + } catch (IOException exception) { + throw new FactoryException(Errors.format(ErrorKeys.CANT_READ_$1, FILENAME), exception); + } + } + + /** + * Returns the URL to the property file that contains Operation definitions. + * The default implementation performs the following search path: + * <ul> + * <li>If a value is set for the {@value GeoTools#CRS_AUTHORITY_EXTRA_DIRECTORY} system property key, + * then the {@value #FILENAME} file will be searched in this directory.</li> + * <li>If no value is set for the above-cited system property, or if no {@value #FILENAME} + * file was found in that directory, then the first {@value #FILENAME} file found in + * any {@code org/geotools/referencing/factory/epsg} directory on the classpath will + * be used.</li> + * <li>If no file was found on the classpath neither, then this factory will be disabled.</li> + * </ul> + * + * @return The URL, or {@code null} if none. + */ + protected URL getDefinitionsURL() { + try { + if (directory != null) { + final File file = new File(directory, FILENAME); + if (file.isFile()) { + return file.toURI().toURL(); // TODO + } + } + } catch (SecurityException exception) { + Logging.unexpectedException(LOGGER, exception); + } catch (MalformedURLException exception) { + Logging.unexpectedException(LOGGER, exception); + } + return this.getClass().getResource(FILENAME); + } + + /** + * Creates operations from {@linkplain CoordinateReferenceSystem coordinate reference system} + * codes. + * + * This method searches in the {@linkplain #FILENAME properties file} for operations. + * + * If not found there, it will create operations from a fallback factory (see + * {@link #getFallbackAuthorityFactory}). + * + * @param sourceCRS Coded value of source coordinate reference system. + * @param targetCRS Coded value of target coordinate reference system. + * @return The operations from {@code sourceCRS} to {@code targetCRS}. + * @throws NoSuchAuthorityCodeException if a specified code was not found. + * @throws FactoryException if the object creation failed for some other reason. + */ + @Override + public Set<CoordinateOperation> createFromCoordinateReferenceSystemCodes( + String sourceCRS, String targetCRS) throws NoSuchAuthorityCodeException, FactoryException { + Set<CoordinateOperation> coordops = super.createFromCoordinateReferenceSystemCodes(sourceCRS, targetCRS); + if (coordops.isEmpty()) { + // If not found, delegate to the fallback factory. + CoordinateOperationAuthorityFactory fallback = getFallbackAuthorityFactory(); + if (fallback != null) { + coordops = fallback.createFromCoordinateReferenceSystemCodes(sourceCRS, targetCRS); + } + } + return coordops; + } + + /** + * Creates an operation from a single operation code. + * + * This method searches in the {@linkplain #FILENAME properties file} for operations. + * + * If not found there, it will create operations from a fallback factory (see + * {@link #getFallbackAuthorityFactory}). + * + * @param code Coded value for operation. + * @return The operation from {@code sourceCRS} to {@code targetCRS}. + * @throws NoSuchAuthorityCodeException if a specified code was not found. + * @throws FactoryException if the object creation failed for some other reason. + */ + public CoordinateOperation createCoordinateOperation(String code) + throws NoSuchAuthorityCodeException, FactoryException { + CoordinateOperation coordop = super.createCoordinateOperation(code); + if (coordop == null) { + CoordinateOperationAuthorityFactory fallback = getFallbackAuthorityFactory(); + if (fallback != null) { + coordop = fallback.createCoordinateOperation(code); + } + } + return coordop; + } + + /** + * Gets the next available {@link CoordinateOperationAuthorityFactory} + * in the priority list. + * + * @return the alternative CoordinateOperationAuthorityFactory. + * @throws NoSuchAuthorityCodeException if a specified code was not found. + * @throws FactoryException if the object creation failed for some other reason. + */ + protected CoordinateOperationAuthorityFactory getFallbackAuthorityFactory() + throws NoSuchAuthorityCodeException, FactoryException { + + if(!fallbackAuthorityFactorySearched) { // Search once + CoordinateOperationAuthorityFactory candidate = null; + + // These hints are to prevent infinite recursion when called + // from OrderedAxisAuthorityFactory. See "noForce(Hints)" + // from AuthorityBackedFactory. + // See also: http://jira.codehaus.org/browse/GEOT-1161 + Hints h = new Hints(); + h.put(Hints.FORCE_LONGITUDE_FIRST_AXIS_ORDER, Boolean.FALSE); + h.put(Hints.FORCE_STANDARD_AXIS_DIRECTIONS, Boolean.FALSE); + h.put(Hints.FORCE_STANDARD_AXIS_UNITS, Boolean.FALSE); + + Set<CoordinateOperationAuthorityFactory> factories = ReferencingFactoryFinder. + getCoordinateOperationAuthorityFactories(h); + Iterator<CoordinateOperationAuthorityFactory> it = factories.iterator(); + + // Skip factories with higher priority than me. + while (it.hasNext()) { + candidate = it.next(); + if (candidate == this) { + break; + } + } + + // Get the next one for this same authority + while (it.hasNext()) { + candidate = it.next(); + if (!(candidate instanceof CoordinateOperationFactoryUsingWKT) + && candidate.getAuthority().getTitle().equals(this.getAuthority().getTitle())) { + fallbackAuthorityFactory = candidate; + break; + } + } + fallbackAuthorityFactorySearched = true; + } + + return fallbackAuthorityFactory; + } +} \ No newline at end of file Modified: trunk/modules/library/referencing/src/main/java/org/geotools/referencing/wkt/MathTransformParser.java =================================================================== --- trunk/modules/library/referencing/src/main/java/org/geotools/referencing/wkt/MathTransformParser.java 2012-05-04 15:22:05 UTC (rev 38702) +++ trunk/modules/library/referencing/src/main/java/org/geotools/referencing/wkt/MathTransformParser.java 2012-05-06 10:24:21 UTC (rev 38703) @@ -16,6 +16,7 @@ */ package org.geotools.referencing.wkt; +import java.net.URI; import java.text.ParseException; import java.text.ParsePosition; @@ -184,6 +185,8 @@ parameter.setValue(param.pullInteger("value")); } else if (Double.class.equals(type)) { parameter.setValue(param.pullDouble("value")); + } else if (URI.class.equals(type)){ + parameter.setValue(URI.create(param.pullString("value"))); } else { parameter.setValue(param.pullString("value")); } Modified: trunk/modules/library/referencing/src/main/resources/META-INF/services/org.opengis.referencing.operation.CoordinateOperationAuthorityFactory =================================================================== --- trunk/modules/library/referencing/src/main/resources/META-INF/services/org.opengis.referencing.operation.CoordinateOperationAuthorityFactory 2012-05-04 15:22:05 UTC (rev 38702) +++ trunk/modules/library/referencing/src/main/resources/META-INF/services/org.opengis.referencing.operation.CoordinateOperationAuthorityFactory 2012-05-06 10:24:21 UTC (rev 38703) @@ -1,3 +1,4 @@ +org.geotools.referencing.factory.epsg.CoordinateOperationFactoryUsingWKT org.geotools.referencing.factory.epsg.DefaultFactory org.geotools.referencing.factory.epsg.LongitudeFirstFactory org.geotools.referencing.factory.URN_AuthorityFactory Added: trunk/modules/library/referencing/src/test/java/org/geotools/referencing/factory/epsg/CoordinateOperationFactoryUsingWKTTest.java =================================================================== --- trunk/modules/library/referencing/src/test/java/org/geotools/referencing/factory/epsg/CoordinateOperationFactoryUsingWKTTest.java (rev 0) +++ trunk/modules/library/referencing/src/test/java/org/geotools/referencing/factory/epsg/CoordinateOperationFactoryUsingWKTTest.java 2012-05-06 10:24:21 UTC (rev 38703) @@ -0,0 +1,201 @@ +/* + * GeoTools - The Open Source Java GIS Toolkit + * http://geotools.org + * + * (C) 2002-2012, Open Source Geospatial Foundation (OSGeo) + * + * 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. + */ +package org.geotools.referencing.factory.epsg; + +import static org.junit.Assert.*; + +import java.io.File; +import java.util.Properties; +import java.util.Set; + +import org.geotools.factory.AbstractFactory; +import org.geotools.factory.Hints; +import org.geotools.metadata.iso.citation.Citations; +import org.geotools.referencing.CRS; +import org.geotools.referencing.ReferencingFactoryFinder; +import org.junit.Before; +import org.junit.Test; +import org.opengis.referencing.FactoryException; +import org.opengis.referencing.NoSuchAuthorityCodeException; +import org.opengis.referencing.crs.CoordinateReferenceSystem; +import org.opengis.referencing.operation.CoordinateOperation; +import org.opengis.referencing.operation.MathTransform; +import org.opengis.referencing.operation.TransformException; + +/** + * Tests the {@link testCoordinateOperationFactoryUsingWKT} public methods. + * + * @author Oscar Fonts + */ +public class CoordinateOperationFactoryUsingWKTTest { + + CoordinateOperationFactoryUsingWKT factory; + + private static final String DEFINITIONS_FILE_NAME = "epsg_operations.properties"; + private static Properties properties; + + private static final String SOURCE_CRS = "EPSG:TEST1"; + private static final String TARGET_CRS = "EPSG:TEST2"; + private static final String CRS_PAIR = SOURCE_CRS + "," + TARGET_CRS; + private static final String INVERSE_CRS_PAIR = TARGET_CRS + "," + SOURCE_CRS; + private static final String INVALID_CRS = "nonexistent"; + + private static final double[] SRC_TEST_POINT = {3.084896111, 39.592654167}; + private static final double[] DST_TEST_POINT = {3.0844689951999427, 39.594235744481225}; + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() throws Exception { + ReferencingFactoryFinder.addAuthorityFactory( + new FactoryUsingWKT(null, AbstractFactory.MAXIMUM_PRIORITY)); + + factory = (CoordinateOperationFactoryUsingWKT) ReferencingFactoryFinder. + getCoordinateOperationAuthorityFactory("EPSG", + new Hints(Hints.COORDINATE_OPERATION_AUTHORITY_FACTORY, + CoordinateOperationFactoryUsingWKT.class)); + + // Read definitions + properties = new Properties(); + properties.load(this.getClass().getResourceAsStream(DEFINITIONS_FILE_NAME)); + } + + /** + * @throws Exception + */ + @Test + public void testExtraDirectoryHint() throws Exception { + Hints hints = new Hints(Hints.COORDINATE_OPERATION_AUTHORITY_FACTORY, + CoordinateOperationFactoryUsingWKT.class); + try { + hints.put(Hints.CRS_AUTHORITY_EXTRA_DIRECTORY, "invalid"); + fail("Should of been tossed out as an invalid hint"); + } + catch (IllegalArgumentException expected) { + // This is the expected exception. + } + String directory = new File(".").getAbsolutePath(); + hints = new Hints(Hints.COORDINATE_OPERATION_AUTHORITY_FACTORY, + CoordinateOperationFactoryUsingWKT.class); + hints.put(Hints.CRS_AUTHORITY_EXTRA_DIRECTORY, directory); + + CoordinateOperationFactoryUsingWKT fact = (CoordinateOperationFactoryUsingWKT) + ReferencingFactoryFinder.getCoordinateOperationAuthorityFactory("EPSG", + new Hints(Hints.COORDINATE_OPERATION_AUTHORITY_FACTORY, + CoordinateOperationFactoryUsingWKT.class)); + + // BTW testing the inverse construction + CoordinateOperation co = fact.createCoordinateOperation(INVERSE_CRS_PAIR); + CoordinateReferenceSystem crs = CRS.decode(TARGET_CRS); + assertSame(crs, co.getSourceCRS()); + crs = CRS.decode(SOURCE_CRS); + assertSame(crs, co.getTargetCRS()); + + assertTrue(co.getMathTransform() instanceof MathTransform); + double[] p = new double[2]; + co.getMathTransform().transform(DST_TEST_POINT, 0, p, 0, 1); + assertEquals(p[0], SRC_TEST_POINT[0], 1e-8); + assertEquals(p[1], SRC_TEST_POINT[1], 1e-8); + } + + /** + * Test method for {@link CoordinateOperationFactoryUsingWKT#getAuthority}. + */ + @Test + public void testGetAuthority() { + assertTrue(factory.getAuthority().equals(Citations.EPSG)); + } + + /** + * Test method for {@link CoordinateOperationFactoryUsingWKT#createCoordinateOperation}. + * @throws TransformException + */ + @Test + public void testCreateCoordinateOperation() throws TransformException { + + try { + assertNull(factory.createCoordinateOperation(INVALID_CRS)); + } catch (FactoryException e) { + fail(factory.getClass().getSimpleName() + " threw a FactoryException when requesting" + + "a nonexistent operation. Instead, a NoSuchAuthorityCodeException was expected."); + } + + try { + // Test CoordinateOperation + CoordinateOperation co = factory.createCoordinateOperation(CRS_PAIR); + assertNotNull(co); + + // Test CRSs + CoordinateReferenceSystem crs = CRS.decode(SOURCE_CRS); + assertSame(crs, co.getSourceCRS()); + crs = CRS.decode(TARGET_CRS); + assertSame(crs, co.getTargetCRS()); + + // Test MathTransform + assertTrue(co.getMathTransform() instanceof MathTransform); + double[] p = new double[2]; + co.getMathTransform().transform(SRC_TEST_POINT, 0, p, 0, 1); + assertEquals(p[0], DST_TEST_POINT[0], 1e-8); + assertEquals(p[1], DST_TEST_POINT[1], 1e-8); + } catch (FactoryException e) { + fail(factory.getClass().getSimpleName() + " threw a FactoryException when creating" + + " coordinate operation from an existing code."); + } + } + + /** + * Test method for + * {@link CoordinateOperationFactoryUsingWKT#createFromCoordinateReferenceSystemCodes}. + * @throws TransformException + */ + @Test + public void testCreateFromCoordinateReferenceSystemCodes() throws TransformException { + try { + Set<CoordinateOperation> cos = factory.createFromCoordinateReferenceSystemCodes( + INVALID_CRS, INVALID_CRS); + assertTrue(cos.isEmpty()); + } catch (FactoryException e) { + fail(factory.getClass().getSimpleName() + " threw a FactoryException when requesting" + + "a nonexistent operation. Instead, a NoSuchAuthorityCodeException was expected."); + } + + try { + // Test CoordinateOperation + Set<CoordinateOperation> cos = factory.createFromCoordinateReferenceSystemCodes(SOURCE_CRS, TARGET_CRS); + assertTrue(cos.size() == 1); + CoordinateOperation co = cos.iterator().next(); + assertNotNull(co); + + // Test CRSs + CoordinateReferenceSystem crs = CRS.decode(SOURCE_CRS); + assertSame(crs, co.getSourceCRS()); + crs = CRS.decode(TARGET_CRS); + assertSame(crs, co.getTargetCRS()); + + // Test MathTransform + assertTrue(co.getMathTransform() instanceof MathTransform); + double[] p = new double[2]; + co.getMathTransform().transform(SRC_TEST_POINT, 0, p, 0, 1); + assertEquals(p[0], DST_TEST_POINT[0], 1e-8); + assertEquals(p[1], DST_TEST_POINT[1], 1e-8); + } catch (FactoryException e) { + fail(factory.getClass().getSimpleName() + " threw a FactoryException when creating" + + " coordinate operation from an existing code."); + } + } +} Modified: trunk/modules/library/referencing/src/test/resources/org/geotools/referencing/factory/epsg/epsg.properties =================================================================== --- trunk/modules/library/referencing/src/test/resources/org/geotools/referencing/factory/epsg/epsg.properties 2012-05-04 15:22:05 UTC (rev 38702) +++ trunk/modules/library/referencing/src/test/resources/org/geotools/referencing/factory/epsg/epsg.properties 2012-05-06 10:24:21 UTC (rev 38703) @@ -5,3 +5,24 @@ # 42101=PROJCS["WGS 84 / LCC Canada",GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Decimal_Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic_2SP"],PARAMETER["central_meridian",-95.0],PARAMETER["latitude_of_origin",0],PARAMETER["standard_parallel_1",49.0],PARAMETER["standard_parallel_2",77.0],PARAMETER["false_northing",-8000000.0],UNIT["Meter",1]] + +# These are used in CoordinateOperationFactoryUsingWKTTest +TEST1=GEOGCS["ED50", \ + DATUM["European Datum 1950", \ + SPHEROID["International 1924", 6378388.0, 297.0, AUTHORITY["EPSG","7022"]], \ + TOWGS84[-116.641, -56.931, -110.559, 0.893, 0.921, -0.917, -3.52], \ + AUTHORITY["EPSG","6230"]], \ + PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], \ + UNIT["degree", 0.017453292519943295], \ + AXIS["Geodetic latitude", NORTH], \ + AXIS["Geodetic longitude", EAST], \ + AUTHORITY["EPSG","4230"]] +TEST2=GEOGCS["WGS 84", \ + DATUM["World Geodetic System 1984", \ + SPHEROID["WGS 84", 6378137.0, 298.257223563, AUTHORITY["EPSG","7030"]], \ + AUTHORITY["EPSG","6326"]], \ + PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], \ + UNIT["degree", 0.017453292519943295], \ + AXIS["Geodetic latitude", NORTH], \ + AXIS["Geodetic longitude", EAST], \ + AUTHORITY["EPSG","4326"]] Added: trunk/modules/library/referencing/src/test/resources/org/geotools/referencing/factory/epsg/epsg_operations.properties =================================================================== --- trunk/modules/library/referencing/src/test/resources/org/geotools/referencing/factory/epsg/epsg_operations.properties (rev 0) +++ trunk/modules/library/referencing/src/test/resources/org/geotools/referencing/factory/epsg/epsg_operations.properties 2012-05-06 10:24:21 UTC (rev 38703) @@ -0,0 +1,13 @@ +# Data used in CoordinateOperationFactoryUsingWKTTest +TEST1,TEST2=CONCAT_MT[ \ + PARAM_MT["Ellipsoid_To_Geocentric", \ + PARAMETER["dim", 2], \ + PARAMETER["semi_major", 6378388.0], \ + PARAMETER["semi_minor", 6356911.9461279465]], \ + PARAM_MT["Position Vector transformation (geog2D domain)", PARAMETER["dx", 1], PARAMETER["dy", 2], PARAMETER["dz", 3], PARAMETER["ex", 4], PARAMETER["ey", 5], PARAMETER["ez", 6], PARAMETER["ppm", 7]], \ + PARAM_MT["Geocentric_To_Ellipsoid", \ + PARAMETER["dim", 2], \ + PARAMETER["semi_major", 6378137.0], \ + PARAMETER["semi_minor", 6356752.314245179]] \ + ] +#4230,4258=PARAM_MT["NTv2", PARAMETER["Latitude and longitude difference file", "100800401.gsb"]] Modified: trunk/modules/plugin/epsg-hsql/src/test/java/org/geotools/referencing/factory/URN_EPSG_Test.java =================================================================== --- trunk/modules/plugin/epsg-hsql/src/test/java/org/geotools/referencing/factory/URN_EPSG_Test.java 2012-05-04 15:22:05 UTC (rev 38702) +++ trunk/modules/plugin/epsg-hsql/src/test/java/org/geotools/referencing/factory/URN_EPSG_Test.java 2012-05-06 10:24:21 UTC (rev 38703) @@ -108,7 +108,7 @@ assertSame(expected, test.createCoordinateReferenceSystem("urn:ogc:def:crs:EPSG:6.11:4326")); assertEquals("6.11", test.lastVersion.toString()); assertEquals("Should use the fallback factory.", - failureCount + 1, FallbackAuthorityFactory.getFailureCount()); + failureCount + 2, FallbackAuthorityFactory.getFailureCount()); } /** Added: trunk/modules/plugin/epsg-hsql/src/test/java/org/geotools/referencing/factory/epsg/LongitudeFirstFactoryOverrideTest.java =================================================================== --- trunk/modules/plugin/epsg-hsql/src/test/java/org/geotools/referencing/factory/epsg/LongitudeFirstFactoryOverrideTest.java (rev 0) +++ trunk/modules/plugin/epsg-hsql/src/test/java/org/geotools/referencing/factory/epsg/LongitudeFirstFactoryOverrideTest.java 2012-05-06 10:24:21 UTC (rev 38703) @@ -0,0 +1,135 @@ +/* + * GeoTools - The Open Source Java GIS Toolkit + * http://geotools.org + * + * (C) 2002-2012, Open Source Geospatial Foundation (OSGeo) + * + * 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. + */ +package org.geotools.referencing.factory.epsg; + +import static org.junit.Assert.*; + +import java.util.Properties; + +import org.geotools.factory.AbstractFactory; +import org.geotools.referencing.CRS; +import org.geotools.referencing.ReferencingFactoryFinder; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.opengis.referencing.crs.CoordinateReferenceSystem; +import org.opengis.referencing.operation.ConcatenatedOperation; +import org.opengis.referencing.operation.CoordinateOperation; +import org.opengis.referencing.operation.MathTransform; +import org.opengis.referencing.operation.TransformException; + +/** + * Makes sure the {@link testCoordinateOperationFactoryUsingWKT} is not ignored when + * referencing is setup in "Longitude first" mode. + * + * @author Oscar Fonts + * @author Andrea Aime + */ +public class LongitudeFirstFactoryOverrideTest { + + private static final String DEFINITIONS_FILE_NAME = "epsg_operations.properties"; + private static Properties properties; + + private static final String SOURCE_CRS = "EPSG:TEST1"; + private static final String TARGET_CRS = "EPSG:TEST2"; + + private static final double[] SRC_TEST_POINT = {39.592654167, 3.084896111}; + private static final double[] DST_TEST_POINT = {39.594235744481225, 3.0844689951999427}; + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() throws Exception { + // force longitude first mode + System.setProperty("org.geotools.referencing.forceXY", "true"); + + CRS.reset("all"); + + ReferencingFactoryFinder.addAuthorityFactory( + new FactoryUsingWKT(null, AbstractFactory.MAXIMUM_PRIORITY)); + + ReferencingFactoryFinder.addAuthorityFactory(new CoordinateOperationFactoryUsingWKT(null, AbstractFactory.MAXIMUM_PRIORITY)); + + // Read definitions + properties = new Properties(); + properties.load(this.getClass().getResourceAsStream(DEFINITIONS_FILE_NAME)); + } + + @After + public void tearDown() { + // unset axis ordering hint + System.clearProperty("org.geotools.referencing.forceXY"); + + CRS.reset("all"); + } + + + /** + * Test method for {@link CoordinateOperationFactoryUsingWKT#createCoordinateOperation}. + * @throws TransformException + */ + @Test + public void testCreateOperationFromCustomCodes() throws Exception { + // Test CRSs + CoordinateReferenceSystem source = CRS.decode(SOURCE_CRS); + CoordinateReferenceSystem target = CRS.decode(TARGET_CRS); + MathTransform mt = CRS.findMathTransform(source, target, true); + + // Test MathTransform + double[] p = new double[2]; + mt.transform(SRC_TEST_POINT, 0, p, 0, 1); + assertEquals(p[0], DST_TEST_POINT[0], 1e-8); + assertEquals(p[1], DST_TEST_POINT[1], 1e-8); + } + + /** + * Test method for {@link CoordinateOperationFactoryUsingWKT#createCoordinateOperation}. + * @throws TransformException + */ + @Test + public void testOverrideEPSGOperation() throws Exception { + // Test CRSs + CoordinateReferenceSystem source = CRS.decode("EPSG:4269"); + CoordinateReferenceSystem target = CRS.decode("EPSG:4326"); + MathTransform mt = CRS.findMathTransform(source, target, true); + + // Test MathTransform + double[] p = new double[2]; + mt.transform(SRC_TEST_POINT, 0, p, 0, 1); + assertEquals(p[0], DST_TEST_POINT[0], 1e-8); + assertEquals(p[1], DST_TEST_POINT[1], 1e-8); + } + + /** + * Check we are actually using the EPSG database for anything not in override + * + * @throws TransformException + */ + @Test + public void testFallbackOnEPSGDatabase() throws Exception { + // Test CRSs + CoordinateReferenceSystem source = CRS.decode("EPSG:3003"); + CoordinateReferenceSystem target = CRS.decode("EPSG:4326"); + CoordinateOperation co = CRS.getCoordinateOperationFactory(true).createOperation(source, target); + ConcatenatedOperation cco = (ConcatenatedOperation) co; + // the EPSG one only has two steps, the non EPSG one 4 + assertEquals(2, cco.getOperations().size()); + } + + +} \ No newline at end of file Added: trunk/modules/plugin/epsg-hsql/src/test/resources/org/geotools/referencing/factory/epsg/epsg.properties =================================================================== --- trunk/modules/plugin/epsg-hsql/src/test/resources/org/geotools/referencing/factory/epsg/epsg.properties (rev 0) +++ trunk/modules/plugin/epsg-hsql/src/test/resources/org/geotools/referencing/factory/epsg/epsg.properties 2012-05-06 10:24:21 UTC (rev 38703) @@ -0,0 +1,20 @@ +# +# Additional CRS for unit testing FactoryUsingWkt. +# +# $Id$ +# + +42101=PROJCS["WGS 84 / LCC Canada",GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Decimal_Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic_2SP"],PARAMETER["central_meridian",-95.0],PARAMETER["latitude_of_origin",0],PARAMETER["standard_parallel_1",49.0],PARAMETER["standard_parallel_2",77.0],PARAMETER["false_northing",-8000000.0],UNIT["Meter",1]] + +# These are used in CoordinateOperationFactoryUsingWKTTest +TEST1=GEOGCS["ED50", \ + DATUM["European Datum 1950", \ + SPHEROID["International 1924", 6378388.0, 297.0, AUTHORITY["EPSG","7022"]], \ + TOWGS84[-116.641, -56.931, -110.559, 0.893, 0.921, -0.917, -3.52]], \ + PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], \ + UNIT["degree", 0.017453292519943295]] +TEST2=GEOGCS["WGS 84", \ + DATUM["World Geodetic System 1984", \ + SPHEROID["WGS 84", 6378137.0, 298.257223563, AUTHORITY["EPSG","7030"]]], \ + PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], \ + UNIT["degree", 0.017453292519943295]] Added: trunk/modules/plugin/epsg-hsql/src/test/resources/org/geotools/referencing/factory/epsg/epsg_operations.properties =================================================================== --- trunk/modules/plugin/epsg-hsql/src/test/resources/org/geotools/referencing/factory/epsg/epsg_operations.properties (rev 0) +++ trunk/modules/plugin/epsg-hsql/src/test/resources/org/geotools/referencing/factory/epsg/epsg_operations.properties 2012-05-06 10:24:21 UTC (rev 38703) @@ -0,0 +1,24 @@ +# Data used in CoordinateOperationFactoryUsingWKTTest +TEST1,TEST2=CONCAT_MT[ \ + PARAM_MT["Ellipsoid_To_Geocentric", \ + PARAMETER["dim", 2], \ + PARAMETER["semi_major", 6378388.0], \ + PARAMETER["semi_minor", 6356911.9461279465]], \ + PARAM_MT["Position Vector transformation (geog2D domain)", PARAMETER["dx", 1], PARAMETER["dy", 2], PARAMETER["dz", 3], PARAMETER["ex", 4], PARAMETER["ey", 5], PARAMETER["ez", 6], PARAMETER["ppm", 7]], \ + PARAM_MT["Geocentric_To_Ellipsoid", \ + PARAMETER["dim", 2], \ + PARAMETER["semi_major", 6378137.0], \ + PARAMETER["semi_minor", 6356752.314245179]] \ + ] +4269,4326=CONCAT_MT[ \ + PARAM_MT["Ellipsoid_To_Geocentric", \ + PARAMETER["dim", 2], \ + PARAMETER["semi_major", 6378388.0], \ + PARAMETER["semi_minor", 6356911.9461279465]], \ + PARAM_MT["Position Vector transformation (geog2D domain)", PARAMETER["dx", 1], PARAMETER["dy", 2], PARAMETER["dz", 3], PARAMETER["ex", 4], PARAMETER["ey", 5], PARAMETER["ez", 6], PARAMETER["ppm", 7]], \ + PARAM_MT["Geocentric_To_Ellipsoid", \ + PARAMETER["dim", 2], \ + PARAMETER["semi_major", 6378137.0], \ + PARAMETER["semi_minor", 6356752.314245179]] \ + ] +#4230,4258=PARAM_MT["NTv2", PARAMETER["Latitude and longitude difference file", "100800401.gsb"]] |