Search in sources :

Example 1 with DefaultConversion

use of org.apache.sis.referencing.operation.DefaultConversion in project sis by apache.

the class DefaultMathTransformFactoryTest method testAllMapProjections.

/**
 * Tests the creation of all registered map projections.
 * Only the semi-axis lengths are specified. For the rest, we rely on default values.
 *
 * @throws FactoryException if the construction of a map projection failed.
 *
 * @since 0.7
 */
@Test
public void testAllMapProjections() throws FactoryException {
    /*
         * Gets all map projections and creates a projection using the WGS84 ellipsoid
         * and default parameter values.
         */
    final Map<String, ?> dummyName = Collections.singletonMap(DefaultProjectedCRS.NAME_KEY, "Test");
    final MathTransformFactory mtFactory = DefaultFactories.forBuildin(MathTransformFactory.class);
    final Collection<OperationMethod> methods = mtFactory.getAvailableMethods(Projection.class);
    for (final OperationMethod method : methods) {
        final String classification = method.getName().getCode();
        ParameterValueGroup param = mtFactory.getDefaultParameters(classification);
        param.parameter("semi_major").setValue(6377563.396);
        param.parameter("semi_minor").setValue(6356256.909237285);
        final MathTransform mt;
        try {
            mt = mtFactory.createParameterizedTransform(param);
        } catch (InvalidGeodeticParameterException e) {
            /*
                 * Some map projections have mandatory parameters which we ignore for now
                 * except for a few well-known projection that we know should not fail.
                 */
            if (classification.contains("Mercator")) {
                throw e;
            }
            out.print(classification);
            out.print(CharSequences.spaces(42 - classification.length()));
            out.print(": ");
            out.println(e.getLocalizedMessage());
            continue;
        }
        /*
             * Verifies that the map projection properties are the ones that we specified.
             * Note that the Equirectangular projection has been optimized as an affine transform, which we skip.
             */
        if (mt instanceof LinearTransform) {
            continue;
        }
        assertInstanceOf(classification, Parameterized.class, mt);
        param = ((Parameterized) mt).getParameterValues();
        assertEquals(classification, param.getDescriptor().getName().getCode());
        assertEquals(classification, 6377563.396, param.parameter("semi_major").doubleValue(), 1E-4);
        assertEquals(classification, 6356256.909237285, param.parameter("semi_minor").doubleValue(), 1E-4);
        /*
             * Creates a ProjectedCRS from the map projection. This part is more an integration test than
             * a DefaultMathTransformFactory test. Again, the intent is to verify that the properties are
             * the one that we specified.
             */
        final DefaultProjectedCRS crs = new DefaultProjectedCRS(dummyName, CommonCRS.WGS84.normalizedGeographic(), new DefaultConversion(dummyName, method, mt, null), HardCodedCS.PROJECTED);
        final Conversion projection = crs.getConversionFromBase();
        assertSame(classification, mt, projection.getMathTransform());
        assertEquals(classification, projection.getMethod().getName().getCode());
    }
}
Also used : InvalidGeodeticParameterException(org.apache.sis.referencing.factory.InvalidGeodeticParameterException) MathTransform(org.opengis.referencing.operation.MathTransform) MathTransformFactory(org.opengis.referencing.operation.MathTransformFactory) ParameterValueGroup(org.opengis.parameter.ParameterValueGroup) DefaultConversion(org.apache.sis.referencing.operation.DefaultConversion) DefaultProjectedCRS(org.apache.sis.referencing.crs.DefaultProjectedCRS) Conversion(org.opengis.referencing.operation.Conversion) DefaultConversion(org.apache.sis.referencing.operation.DefaultConversion) OperationMethod(org.opengis.referencing.operation.OperationMethod) Test(org.junit.Test)

Example 2 with DefaultConversion

use of org.apache.sis.referencing.operation.DefaultConversion in project sis by apache.

the class Proj4Factory method createCRS.

/**
 * Creates a coordinate reference system from the given {@literal Proj.4} wrapper.
 * The given {@code pj} will be stored as the CRS identifier.
 *
 * @param  pj          the Proj.4 object to wrap.
 * @param  withHeight  whether to include a height axis.
 * @throws IllegalArgumentException if a Proj.4 parameter value can not be parsed or assigned.
 * @throws ParserException if a unit symbol can not be parsed.
 */
private CoordinateReferenceSystem createCRS(final PJ pj, final boolean withHeight) throws FactoryException {
    final PJ.Type type = pj.getType();
    final boolean geographic = PJ.Type.GEOGRAPHIC.equals(type);
    final boolean geocentric = PJ.Type.GEOCENTRIC.equals(type);
    final Proj4Parser parser = new Proj4Parser(pj.getCode());
    final String dir = parser.value("axis", "enu");
    final CoordinateSystemAxis[] axes = new CoordinateSystemAxis[geocentric | withHeight ? dir.length() : 2];
    for (int i = 0; i < axes.length; i++) {
        final char d = Character.toLowerCase(dir.charAt(i));
        char abbreviation = Character.toUpperCase(d);
        boolean vertical = false;
        final AxisDirection c;
        final String name;
        if (geocentric)
            switch(d) {
                case 'e':
                    c = AxisDirection.GEOCENTRIC_X;
                    name = "Geocentric X";
                    break;
                case 'n':
                    c = AxisDirection.GEOCENTRIC_Y;
                    name = "Geocentric Y";
                    break;
                case 'u':
                    c = AxisDirection.GEOCENTRIC_Z;
                    name = "Geocentric Z";
                    break;
                default:
                    c = AxisDirection.OTHER;
                    name = "Unknown";
                    break;
            }
        else
            switch(d) {
                case 'e':
                    c = AxisDirection.EAST;
                    name = geographic ? "Geodetic longitude" : "Easting";
                    break;
                case 'w':
                    c = AxisDirection.WEST;
                    name = geographic ? "Geodetic longitude" : "Westing";
                    break;
                case 'n':
                    c = AxisDirection.NORTH;
                    name = geographic ? "Geodetic latitude" : "Northing";
                    break;
                case 's':
                    c = AxisDirection.SOUTH;
                    name = geographic ? "Geodetic latitude" : "Southing";
                    break;
                case 'u':
                    c = AxisDirection.UP;
                    name = "Height";
                    vertical = true;
                    abbreviation = 'h';
                    break;
                case 'd':
                    c = AxisDirection.DOWN;
                    name = "Depth";
                    vertical = true;
                    break;
                default:
                    c = AxisDirection.OTHER;
                    name = "Unknown";
                    break;
            }
        if (geographic && AxisDirections.isCardinal(c)) {
            abbreviation = (d == 'e' || d == 'w') ? 'λ' : 'φ';
        }
        final Unit<?> unit = (vertical || !geographic) ? parser.unit(vertical) : Units.DEGREE;
        axes[i] = csFactory.createCoordinateSystemAxis(identifier(name), String.valueOf(abbreviation).intern(), c, unit);
    }
    /*
         * At this point we got the coordinate system axes. Now create the CRS. The given Proj.4 object
         * will be stored as the CRS identifier for allowing OperationFactory to get it back before to
         * attempt to create a new one for a given CRS.
         */
    final Map<String, Object> csName = identifier(UNNAMED);
    final Map<String, Object> name = new HashMap<>(identifier(parser.name(type == PJ.Type.PROJECTED)));
    name.put(CoordinateReferenceSystem.IDENTIFIERS_KEY, pj);
    switch(type) {
        case GEOGRAPHIC:
            {
                return crsFactory.createGeographicCRS(name, createDatum(pj, parser), withHeight ? csFactory.createEllipsoidalCS(csName, axes[0], axes[1], axes[2]) : csFactory.createEllipsoidalCS(csName, axes[0], axes[1]));
            }
        case GEOCENTRIC:
            {
                return crsFactory.createGeocentricCRS(name, createDatum(pj, parser), csFactory.createCartesianCS(csName, axes[0], axes[1], axes[2]));
            }
        case PROJECTED:
            {
                final PJ base = unique(new PJ(pj));
                final CoordinateReferenceSystem baseCRS = createCRS(base, withHeight);
                final Transform tr = new Transform(pj, withHeight, base, withHeight);
                /*
                 * Try to convert the Proj.4 parameters into OGC parameters in order to have a less opaque structure.
                 * Failure to perform this conversion will not cause a failure to create the ProjectedCRS. After all,
                 * maybe the user invokes this method for using a map projection not yet supported by Apache SIS.
                 * Instead, fallback on the more opaque Transform.METHOD description. Apache SIS will not be able to
                 * perform analysis on those parameters, but it will not prevent the Proj.4 transformation to work.
                 */
                OperationMethod method;
                ParameterValueGroup parameters;
                try {
                    method = parser.method(opFactory());
                    parameters = parser.parameters();
                } catch (IllegalArgumentException | FactoryException e) {
                    Logging.recoverableException(Logging.getLogger(Modules.GDAL), Proj4Factory.class, "createProjectedCRS", e);
                    method = Transform.METHOD;
                    // Will let Apache SIS infers the parameters from the Transform instance.
                    parameters = null;
                }
                final Conversion fromBase = new DefaultConversion(name, method, tr, parameters);
                return crsFactory.createProjectedCRS(name, (GeographicCRS) baseCRS, fromBase, withHeight ? csFactory.createCartesianCS(csName, axes[0], axes[1], axes[2]) : csFactory.createCartesianCS(csName, axes[0], axes[1]));
            }
        default:
            {
                throw new FactoryException(Errors.getResources(defaultProperties).getString(Errors.Keys.UnknownEnumValue_2, type, PJ.Type.class));
            }
    }
}
Also used : WeakValueHashMap(org.apache.sis.util.collection.WeakValueHashMap) HashMap(java.util.HashMap) ParameterValueGroup(org.opengis.parameter.ParameterValueGroup) UnavailableFactoryException(org.apache.sis.referencing.factory.UnavailableFactoryException) FactoryException(org.opengis.util.FactoryException) DefaultConversion(org.apache.sis.referencing.operation.DefaultConversion) SimpleInternationalString(org.apache.sis.util.iso.SimpleInternationalString) DefaultConversion(org.apache.sis.referencing.operation.DefaultConversion) IdentifiedObject(org.opengis.referencing.IdentifiedObject)

Example 3 with DefaultConversion

use of org.apache.sis.referencing.operation.DefaultConversion in project sis by apache.

the class StandardDefinitions method createUniversal.

/**
 * Creates a Universal Transverse Mercator (UTM) or a Universal Polar Stereographic (UPS) projected CRS
 * using the Apache SIS factory implementation. This method restricts the factory to SIS implementation
 * instead than arbitrary factory in order to meet the contract saying that {@link CommonCRS} methods
 * should never fail.
 *
 * @param code       the EPSG code, or 0 if none.
 * @param baseCRS    the geographic CRS on which the projected CRS is based.
 * @param isUTM      {@code true} for UTM or {@code false} for UPS. Note: redundant with the given latitude.
 * @param latitude   a latitude in the zone of the desired projection, to be snapped to 0°, 90°S or 90°N.
 * @param longitude  a longitude in the zone of the desired projection, to be snapped to UTM central meridian.
 * @param derivedCS  the projected coordinate system.
 */
static ProjectedCRS createUniversal(final int code, final GeographicCRS baseCRS, final boolean isUTM, final double latitude, final double longitude, final CartesianCS derivedCS) {
    final OperationMethod method;
    try {
        method = DefaultFactories.forBuildin(MathTransformFactory.class, DefaultMathTransformFactory.class).getOperationMethod(isUTM ? TransverseMercator.NAME : PolarStereographicA.NAME);
    } catch (NoSuchIdentifierException e) {
        // Should not happen with SIS implementation.
        throw new IllegalStateException(e);
    }
    final ParameterValueGroup parameters = method.getParameters().createValue();
    String name = isUTM ? TransverseMercator.Zoner.UTM.setParameters(parameters, latitude, longitude) : PolarStereographicA.setParameters(parameters, latitude >= 0);
    final DefaultConversion conversion = new DefaultConversion(properties(0, name, null, false), method, null, parameters);
    name = baseCRS.getName().getCode() + " / " + name;
    return new DefaultProjectedCRS(properties(code, name, null, false), baseCRS, conversion, derivedCS);
}
Also used : ParameterValueGroup(org.opengis.parameter.ParameterValueGroup) DefaultConversion(org.apache.sis.referencing.operation.DefaultConversion) NoSuchIdentifierException(org.opengis.util.NoSuchIdentifierException) DefaultProjectedCRS(org.apache.sis.referencing.crs.DefaultProjectedCRS) OperationMethod(org.opengis.referencing.operation.OperationMethod)

Aggregations

DefaultConversion (org.apache.sis.referencing.operation.DefaultConversion)3 ParameterValueGroup (org.opengis.parameter.ParameterValueGroup)3 DefaultProjectedCRS (org.apache.sis.referencing.crs.DefaultProjectedCRS)2 OperationMethod (org.opengis.referencing.operation.OperationMethod)2 HashMap (java.util.HashMap)1 InvalidGeodeticParameterException (org.apache.sis.referencing.factory.InvalidGeodeticParameterException)1 UnavailableFactoryException (org.apache.sis.referencing.factory.UnavailableFactoryException)1 WeakValueHashMap (org.apache.sis.util.collection.WeakValueHashMap)1 SimpleInternationalString (org.apache.sis.util.iso.SimpleInternationalString)1 Test (org.junit.Test)1 IdentifiedObject (org.opengis.referencing.IdentifiedObject)1 Conversion (org.opengis.referencing.operation.Conversion)1 MathTransform (org.opengis.referencing.operation.MathTransform)1 MathTransformFactory (org.opengis.referencing.operation.MathTransformFactory)1 FactoryException (org.opengis.util.FactoryException)1 NoSuchIdentifierException (org.opengis.util.NoSuchIdentifierException)1