Search in sources :

Example 61 with FactoryException

use of org.opengis.util.FactoryException in project sis by apache.

the class GeodeticObjectFactory method createFromWKT.

/**
 * Creates a Coordinate Reference System object from a <cite>Well Known Text</cite> (WKT).
 * This method understands both version 1 (a.k.a. OGC 01-009) and version 2 (a.k.a. ISO 19162)
 * of the WKT format.
 *
 * <div class="note"><b>Example:</b> below is a slightly simplified WKT 2 string for a Mercator projection.
 * For making this example smaller, some optional {@code UNIT[…]} and {@code ORDER[…]} elements have been omitted.
 *
 * {@preformat wkt
 *   ProjectedCRS["SIRGAS 2000 / Brazil Mercator",
 *     BaseGeodCRS["SIRGAS 2000",
 *       Datum["Sistema de Referencia Geocentrico para las Americas 2000",
 *         Ellipsoid["GRS 1980", 6378137, 298.257222101]]],
 *     Conversion["Petrobras Mercator",
 *       Method["Mercator (variant B)", Id["EPSG",9805]],
 *       Parameter["Latitude of 1st standard parallel", -2],
 *       Parameter["Longitude of natural origin", -43],
 *       Parameter["False easting", 5000000],
 *       Parameter["False northing", 10000000]],
 *     CS[cartesian,2],
 *       Axis["easting (E)", east],
 *       Axis["northing (N)", north],
 *       LengthUnit["metre", 1],
 *     Id["EPSG",5641]]
 * }
 * </div>
 *
 * If the given text contains non-fatal anomalies
 * (unknown or unsupported WKT elements, inconsistent unit definitions, unparsable axis abbreviations, <i>etc.</i>),
 * warnings may be reported in a {@linkplain java.util.logging.Logger logger} named {@code "org.apache.sis.io.wkt"}.
 * However this parser does not verify if the overall parsed object matches the EPSG (or other authority) definition,
 * since this geodetic object factory is not an {@linkplain GeodeticAuthorityFactory authority factory}.
 * For such verification, see the {@link org.apache.sis.referencing.CRS#fromWKT(String)} convenience method.
 *
 * <div class="section">Usage and performance considerations</div>
 * The default implementation uses a shared instance of {@link org.apache.sis.io.wkt.WKTFormat}
 * with the addition of thread-safety. This is okay for occasional use,
 * but is sub-optimal if this method is extensively used in a multi-thread environment.
 * Furthermore this method offers no control on the WKT {@linkplain org.apache.sis.io.wkt.Convention conventions}
 * in use and on the handling of {@linkplain org.apache.sis.io.wkt.Warnings warnings}.
 * Applications which need to parse a large amount of WKT strings should consider to use
 * the {@link org.apache.sis.io.wkt.WKTFormat} class instead than this method.
 *
 * @param  text  coordinate system encoded in Well-Known Text format (version 1 or 2).
 * @throws FactoryException if the object creation failed.
 *
 * @see org.apache.sis.io.wkt
 * @see org.apache.sis.referencing.CRS#fromWKT(String)
 * @see <a href="http://docs.opengeospatial.org/is/12-063r5/12-063r5.html">WKT 2 specification</a>
 * @see <a href="http://www.geoapi.org/3.0/javadoc/org/opengis/referencing/doc-files/WKT.html">Legacy WKT 1</a>
 */
@Override
public CoordinateReferenceSystem createFromWKT(final String text) throws FactoryException {
    Parser p = parser.getAndSet(null);
    if (p == null)
        try {
            Constructor<? extends Parser> c = parserConstructor;
            if (c == null) {
                c = Class.forName("org.apache.sis.io.wkt.GeodeticObjectParser").asSubclass(Parser.class).getConstructor(Map.class, ObjectFactory.class, MathTransformFactory.class);
                // For allowing use in inner class or lambda expression.
                final Constructor<?> cp = c;
                AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
                    cp.setAccessible(true);
                    return null;
                });
                parserConstructor = c;
            }
            p = c.newInstance(defaultProperties, this, getMathTransformFactory());
        } catch (ReflectiveOperationException e) {
            throw new FactoryException(e);
        }
    final Object object;
    try {
        object = p.createFromWKT(text);
    } catch (FactoryException e) {
        /*
             * In the case of map projection, the parsing may fail because a projection parameter is not known to SIS.
             * If this happen, replace the generic exception thrown be the parser (which is FactoryException) by a
             * more specific one. Note that InvalidGeodeticParameterException is defined only in this sis-referencing
             * module, so we could not throw it from the sis-metadata module that contain the parser.
             */
        Throwable cause = e.getCause();
        while (cause != null) {
            if (cause instanceof ParameterNotFoundException) {
                throw new InvalidGeodeticParameterException(e.getLocalizedMessage(), cause);
            }
            cause = cause.getCause();
        }
        throw e;
    }
    parser.set(p);
    if (object instanceof CoordinateReferenceSystem) {
        return (CoordinateReferenceSystem) object;
    } else {
        throw new FactoryException(Errors.getResources(defaultProperties).getString(Errors.Keys.IllegalClass_2, CoordinateReferenceSystem.class, object.getClass()));
    }
}
Also used : PrivilegedAction(java.security.PrivilegedAction) FactoryException(org.opengis.util.FactoryException) Constructor(java.lang.reflect.Constructor) AbstractIdentifiedObject(org.apache.sis.referencing.AbstractIdentifiedObject) ParameterNotFoundException(org.opengis.parameter.ParameterNotFoundException) Parser(org.apache.sis.io.wkt.Parser)

Example 62 with FactoryException

use of org.opengis.util.FactoryException in project sis by apache.

the class LinearTransformBuilder method create.

/**
 * Creates a linear transform approximation from the source positions to the target positions.
 * This method assumes that source positions are precise and that all uncertainty is in the target positions.
 *
 * @param  factory  the factory to use for creating the transform, or {@code null} for the default factory.
 *                  The {@link MathTransformFactory#createAffineTransform(Matrix)} method of that factory
 *                  shall return {@link LinearTransform} instances.
 * @return the fitted linear transform.
 * @throws FactoryException if the transform can not be created,
 *         for example because the source or target points have not be specified.
 *
 * @since 0.8
 */
@Override
@SuppressWarnings("serial")
public LinearTransform create(final MathTransformFactory factory) throws FactoryException {
    if (transform == null) {
        // Protect from changes.
        final double[][] sources = this.sources;
        final double[][] targets = this.targets;
        if (targets == null) {
            throw new InvalidGeodeticParameterException(noData());
        }
        final int sourceDim = (sources != null) ? sources.length : gridSize.length;
        final int targetDim = targets.length;
        correlation = new double[targetDim];
        final MatrixSIS matrix = Matrices.create(targetDim + 1, sourceDim + 1, ExtendedPrecisionMatrix.ZERO);
        matrix.setElement(targetDim, sourceDim, 1);
        for (int j = 0; j < targetDim; j++) {
            final double c;
            switch(sourceDim) {
                case 1:
                    {
                        final int row = j;
                        final Line line = new Line() {

                            @Override
                            public void setEquation(final Number slope, final Number y0) {
                                super.setEquation(slope, y0);
                                // Preserve the extended precision (double-double).
                                matrix.setNumber(row, 0, slope);
                                matrix.setNumber(row, 1, y0);
                            }
                        };
                        if (sources != null) {
                            c = line.fit(vector(sources[0]), vector(targets[j]));
                        } else {
                            c = line.fit(Vector.createSequence(0, 1, gridSize[0]), Vector.create(targets[j], false));
                        }
                        break;
                    }
                case 2:
                    {
                        final int row = j;
                        final Plane plan = new Plane() {

                            @Override
                            public void setEquation(final Number sx, final Number sy, final Number z0) {
                                super.setEquation(sx, sy, z0);
                                // Preserve the extended precision (double-double).
                                matrix.setNumber(row, 0, sx);
                                matrix.setNumber(row, 1, sy);
                                matrix.setNumber(row, 2, z0);
                            }
                        };
                        if (sources != null) {
                            c = plan.fit(vector(sources[0]), vector(sources[1]), vector(targets[j]));
                        } else
                            try {
                                c = plan.fit(gridSize[0], gridSize[1], Vector.create(targets[j], false));
                            } catch (IllegalArgumentException e) {
                                // This may happen if the z vector still contain some "NaN" values.
                                throw new InvalidGeodeticParameterException(noData(), e);
                            }
                        break;
                    }
                default:
                    {
                        throw new FactoryException(Errors.format(Errors.Keys.ExcessiveNumberOfDimensions_1, sourceDim));
                    }
            }
            correlation[j] = c;
        }
        transform = (LinearTransform) nonNull(factory).createAffineTransform(matrix);
    }
    return transform;
}
Also used : Line(org.apache.sis.math.Line) InvalidGeodeticParameterException(org.apache.sis.referencing.factory.InvalidGeodeticParameterException) Plane(org.apache.sis.math.Plane) FactoryException(org.opengis.util.FactoryException) MatrixSIS(org.apache.sis.referencing.operation.matrix.MatrixSIS)

Example 63 with FactoryException

use of org.opengis.util.FactoryException in project sis by apache.

the class ServicesForMetadata method setGeographicExtent.

/**
 * Implementation of the public {@code setBounds(…, DefaultGeographicBoundingBox, …)} methods for
 * the horizontal extent. If the {@code crs} argument is null, then it is caller's responsibility
 * to ensure that the given envelope is two-dimensional.
 *
 * @param  envelope       the source envelope.
 * @param  target         the target bounding box.
 * @param  crs            the envelope CRS, or {@code null} if unknown.
 * @param  normalizedCRS  the horizontal component of the given CRS, or null if the {@code crs} argument is null.
 * @throws TransformException if the given envelope can not be transformed.
 */
private void setGeographicExtent(Envelope envelope, final DefaultGeographicBoundingBox target, final CoordinateReferenceSystem crs, final GeographicCRS normalizedCRS) throws TransformException {
    if (normalizedCRS != null) {
        // No need to check for dimension, since GeodeticCRS can not have less than 2.
        final CoordinateSystem cs1 = crs.getCoordinateSystem();
        final CoordinateSystem cs2 = normalizedCRS.getCoordinateSystem();
        if (!Utilities.equalsIgnoreMetadata(cs2.getAxis(0), cs1.getAxis(0)) || !Utilities.equalsIgnoreMetadata(cs2.getAxis(1), cs1.getAxis(1))) {
            final CoordinateOperation operation;
            final CoordinateOperationFactory factory = CoordinateOperations.factory();
            try {
                operation = factory.createOperation(crs, normalizedCRS);
            } catch (FactoryException e) {
                throw new TransformException(Resources.format(Resources.Keys.CanNotTransformEnvelopeToGeodetic), e);
            }
            envelope = Envelopes.transform(operation, envelope);
        }
    }
    /*
         * At this point, the envelope should use (longitude, latitude) coordinates in degrees.
         * However the prime meridian is not necessarily Greenwich.
         */
    double westBoundLongitude = envelope.getMinimum(0);
    double eastBoundLongitude = envelope.getMaximum(0);
    double southBoundLatitude = envelope.getMinimum(1);
    double northBoundLatitude = envelope.getMaximum(1);
    if (normalizedCRS != null) {
        final double rotation = CRS.getGreenwichLongitude(normalizedCRS);
        westBoundLongitude += rotation;
        eastBoundLongitude += rotation;
    }
    target.setBounds(westBoundLongitude, eastBoundLongitude, southBoundLatitude, northBoundLatitude);
    target.setInclusion(Boolean.TRUE);
}
Also used : FactoryException(org.opengis.util.FactoryException) CoordinateSystem(org.opengis.referencing.cs.CoordinateSystem) DefaultCoordinateOperationFactory(org.apache.sis.referencing.operation.DefaultCoordinateOperationFactory) CoordinateOperationFactory(org.opengis.referencing.operation.CoordinateOperationFactory) TransformException(org.opengis.referencing.operation.TransformException) CoordinateOperation(org.opengis.referencing.operation.CoordinateOperation)

Example 64 with FactoryException

use of org.opengis.util.FactoryException in project sis by apache.

the class FranceGeocentricInterpolation method load.

/**
 * Unconditionally loads the grid for the given file without in-memory compression.
 *
 * @param  in    reader of the RGF93 datum shift file.
 * @param  file  path to the file being read, used only for error reporting.
 * @throws IOException if an I/O error occurred.
 * @throws NumberFormatException if a number can not be parsed.
 * @throws NoSuchElementException if a data line is missing a value.
 * @throws FactoryException if an problem is found with the file content.
 * @throws ArithmeticException if the width or the height exceed the integer capacity.
 */
static DatumShiftGridFile.Float<Angle, Length> load(final BufferedReader in, final Path file) throws IOException, FactoryException, NoninvertibleTransformException {
    DatumShiftGridFile.Float<Angle, Length> grid = null;
    double x0 = 0;
    double xf = 0;
    double y0 = 0;
    double yf = 0;
    double Δx = 0;
    double Δy = 0;
    int nx = 0;
    int ny = 0;
    /*
         * The header should be like below, but the only essential line for this class is the one
         * starting with "GR3D1". We also check that "GR3D2" declares the expected interpolation.
         *
         *     GR3D  002024 024 20370201
         *     GR3D1   -5.5000  10.0000  41.0000  52.0000    .1000    .1000
         *     GR3D2 INTERPOLATION BILINEAIRE
         *     GR3D3 PREC CM 01:5 02:10 03:20 04:50 99>100
         */
    String line;
    while (true) {
        line = in.readLine();
        if (line == null) {
            throw new EOFException(Errors.format(Errors.Keys.UnexpectedEndOfFile_1, file));
        }
        final int length = CharSequences.skipTrailingWhitespaces(line, 0, line.length());
        if (length <= 0) {
            // Skip empty lines.
            continue;
        }
        int p = CharSequences.skipLeadingWhitespaces(line, 0, length);
        if (line.charAt(p) == '#') {
            // Skip comment lines (not officially part of the format).
            continue;
        }
        if (!line.regionMatches(true, p, HEADER, 0, HEADER.length())) {
            // End of header.
            break;
        }
        if ((p += HEADER.length()) < length) {
            final char c = line.charAt(p);
            p = CharSequences.skipLeadingWhitespaces(line, p + 1, length);
            switch(c) {
                case '1':
                    {
                        if (grid != null) {
                            throw new FactoryException(Errors.format(Errors.Keys.DuplicatedElement_1, HEADER));
                        }
                        final double[] gridGeometry = CharSequences.parseDoubles(line.substring(p, length), ' ');
                        if (gridGeometry.length == 6) {
                            x0 = gridGeometry[0];
                            xf = gridGeometry[1];
                            y0 = gridGeometry[2];
                            yf = gridGeometry[3];
                            Δx = gridGeometry[4];
                            Δy = gridGeometry[5];
                            nx = Math.toIntExact(Math.round((xf - x0) / Δx + 1));
                            ny = Math.toIntExact(Math.round((yf - y0) / Δy + 1));
                            grid = new DatumShiftGridFile.Float<>(3, Units.DEGREE, Units.METRE, false, x0, y0, Δx, Δy, nx, ny, PARAMETERS, file);
                        }
                        break;
                    }
                case '2':
                    {
                        final String interp = line.substring(p, length);
                        if (!interp.matches("(?i)INTERPOLATION[^A-Z]+BILINEAIRE")) {
                            final LogRecord record = Errors.getResources((Locale) null).getLogRecord(Level.WARNING, Errors.Keys.UnsupportedInterpolation_1, interp);
                            record.setLoggerName(Loggers.COORDINATE_OPERATION);
                            Logging.log(FranceGeocentricInterpolation.class, "createMathTransform", record);
                        // We declare 'createMathTransform' method because it is closer to public API.
                        }
                        break;
                    }
            }
        }
    }
    if (grid == null) {
        throw new FactoryException(Errors.format(Errors.Keys.CanNotParseFile_2, HEADER, file));
    }
    /*
         * Loads the data with the sign of all offsets reversed. Data columns are
         *
         *     (unknown), longitude, latitude, tX, tY, tZ, accuracy code, data sheet (ignored)
         *
         * where the longitude and latitude values are in RGF93 system.
         * Example:
         *
         *     00002   -5.500000000   41.000000000  -165.027   -67.100   315.813  99  -0158
         *     00002   -5.500000000   41.100000000  -165.169   -66.948   316.007  99  -0157
         *     00002   -5.500000000   41.200000000  -165.312   -66.796   316.200  99  -0157
         *
         * Translation values in the IGN file are from NTF to RGF93, but Apache SIS implementation needs
         * the opposite direction (from RGF93 to NTF). The reason is that SIS expect the source datum to
         * be the datum in which longitude and latitude values are expressed.
         */
    final float[] tX = grid.offsets[0];
    final float[] tY = grid.offsets[1];
    final float[] tZ = grid.offsets[2];
    do {
        final StringTokenizer t = new StringTokenizer(line.trim());
        // Ignored
        t.nextToken();
        // Longitude in degrees
        final double x = Double.parseDouble(t.nextToken());
        // Latitude in degrees
        final double y = Double.parseDouble(t.nextToken());
        // Column index
        final int i = Math.toIntExact(Math.round((x - x0) / Δx));
        // Row index
        final int j = Math.toIntExact(Math.round((y - y0) / Δy));
        if (i < 0 || i >= nx) {
            throw new FactoryException(Errors.format(Errors.Keys.ValueOutOfRange_4, "x", x, x0, xf));
        }
        if (j < 0 || j >= ny) {
            throw new FactoryException(Errors.format(Errors.Keys.ValueOutOfRange_4, "y", y, y0, yf));
        }
        final int p = j * nx + i;
        if (!Double.isNaN(tX[p]) || !Double.isNaN(tY[p]) || !Double.isNaN(tZ[p])) {
            throw new FactoryException(Errors.format(Errors.Keys.ValueAlreadyDefined_1, x + ", " + y));
        }
        // See javadoc for the reason why we reverse the sign.
        tX[p] = -parseFloat(t.nextToken());
        tY[p] = -parseFloat(t.nextToken());
        tZ[p] = -parseFloat(t.nextToken());
        final double accuracy = ACCURACY[Math.min(ACCURACY.length - 1, Math.max(0, Integer.parseInt(t.nextToken()) - 1))];
        if (!(accuracy >= grid.accuracy)) {
            // Use '!' for replacing the initial NaN.
            grid.accuracy = accuracy;
        }
    } while ((line = in.readLine()) != null);
    return grid;
}
Also used : FactoryException(org.opengis.util.FactoryException) Float.parseFloat(java.lang.Float.parseFloat) StringTokenizer(java.util.StringTokenizer) Angle(javax.measure.quantity.Angle) Length(javax.measure.quantity.Length) LogRecord(java.util.logging.LogRecord) EOFException(java.io.EOFException)

Example 65 with FactoryException

use of org.opengis.util.FactoryException in project sis by apache.

the class CC_OperationMethod method group.

/**
 * Wraps the given descriptors in a descriptor group of the given name. If the given name can be matched
 * to the name of one of the predefined operation method, then the predefined parameters will be used.
 *
 * <p>We try to use predefined parameters if possible because they contain information, especially the
 * {@link org.opengis.parameter.ParameterDescriptor#getValueClass()} property, which are not available
 * in the GML document.</p>
 *
 * <div class="note"><b>Note:</b>
 * this code is defined in this {@code CC_OperationMethod} class instead than in the
 * {@link DefaultOperationMethod} class in the hope to reduce the amount of code processed
 * by the JVM in the common case where JAXB (un)marshalling is not needed.</div>
 *
 * @param  name         the operation method name, to be also given to the descriptor group.
 * @param  descriptors  the parameter descriptors to wrap in a group. This array will be modified in-place.
 * @return a parameter group containing at least the given descriptors, or equivalent descriptors.
 */
public static ParameterDescriptorGroup group(final Identifier name, final GeneralParameterDescriptor[] descriptors) {
    OperationMethod method;
    try {
        method = CoordinateOperations.factory().getOperationMethod(name.getCode());
    } catch (FactoryException e) {
        // Use DefaultOperationMethod as the source class because it is the first public class in callers.
        Context.warningOccured(Context.current(), DefaultOperationMethod.class, "setDescriptors", e, true);
        method = null;
    }
    final Map<String, ?> properties = Collections.singletonMap(ParameterDescriptorGroup.NAME_KEY, name);
    if (method != null) {
        /*
             * Verify that the pre-defined operation method contains at least all the parameters specified by
             * the 'descriptors' array. If this is the case, then the pre-defined parameters will be used in
             * replacement of the given ones.
             */
        final ParameterDescriptorGroup parameters = method.getParameters();
        return CC_GeneralOperationParameter.merge(DefaultOperationMethod.class, properties, IdentifiedObjects.getProperties(parameters), 1, 1, descriptors, parameters, true);
    }
    return new DefaultParameterDescriptorGroup(properties, 1, 1, descriptors);
}
Also used : DefaultParameterDescriptorGroup(org.apache.sis.parameter.DefaultParameterDescriptorGroup) FactoryException(org.opengis.util.FactoryException) ParameterDescriptorGroup(org.opengis.parameter.ParameterDescriptorGroup) DefaultParameterDescriptorGroup(org.apache.sis.parameter.DefaultParameterDescriptorGroup) DefaultOperationMethod(org.apache.sis.referencing.operation.DefaultOperationMethod) DefaultOperationMethod(org.apache.sis.referencing.operation.DefaultOperationMethod) OperationMethod(org.opengis.referencing.operation.OperationMethod)

Aggregations

FactoryException (org.opengis.util.FactoryException)84 TransformException (org.opengis.referencing.operation.TransformException)27 GeometryWrapper (org.apache.jena.geosparql.implementation.GeometryWrapper)21 MismatchedDimensionException (org.opengis.geometry.MismatchedDimensionException)19 ExprEvalException (org.apache.jena.sparql.expr.ExprEvalException)17 MathTransform (org.opengis.referencing.operation.MathTransform)15 DatatypeFormatException (org.apache.jena.datatypes.DatatypeFormatException)12 CoordinateReferenceSystem (org.opengis.referencing.crs.CoordinateReferenceSystem)10 IdentifiedObject (org.opengis.referencing.IdentifiedObject)8 Envelope (org.locationtech.jts.geom.Envelope)7 ArrayList (java.util.ArrayList)6 ParameterValueGroup (org.opengis.parameter.ParameterValueGroup)6 NoninvertibleTransformException (org.opengis.referencing.operation.NoninvertibleTransformException)6 Literal (org.apache.jena.rdf.model.Literal)5 UnavailableFactoryException (org.apache.sis.referencing.factory.UnavailableFactoryException)5 CoordinateSystem (org.opengis.referencing.cs.CoordinateSystem)5 ParseException (java.text.ParseException)4 AbstractIdentifiedObject (org.apache.sis.referencing.AbstractIdentifiedObject)4 BackingStoreException (org.apache.sis.util.collection.BackingStoreException)4 Test (org.junit.Test)4