Search in sources :

Example 6 with EllipsoidalCS

use of org.opengis.referencing.cs.EllipsoidalCS in project sis by apache.

the class CRS method horizontalCode.

/**
 * If the given CRS would quality as horizontal except for its number of dimensions, returns that number.
 * Otherwise returns 0. The number of dimensions can only be 2 or 3.
 */
private static int horizontalCode(final CoordinateReferenceSystem crs) {
    /*
         * In order to determine if the CRS is geographic, checking the CoordinateSystem type is more reliable
         * then checking if the CRS implements the GeographicCRS interface.  This is because the GeographicCRS
         * type did not existed in ISO 19111:2007, so a CRS could be standard-compliant without implementing
         * the GeographicCRS interface.
         */
    boolean isEngineering = false;
    final boolean isGeodetic = (crs instanceof GeodeticCRS);
    if (isGeodetic || crs instanceof ProjectedCRS || (isEngineering = (crs instanceof EngineeringCRS))) {
        final CoordinateSystem cs = crs.getCoordinateSystem();
        final int dim = cs.getDimension();
        if ((dim & ~1) == 2 && (!isGeodetic || (cs instanceof EllipsoidalCS))) {
            if (isEngineering) {
                int n = 0;
                for (int i = 0; i < dim; i++) {
                    if (AxisDirections.isCompass(cs.getAxis(i).getDirection()))
                        n++;
                }
                // If we don't have exactly 2 east, north, etc. directions, consider as non-horizontal.
                if (n != 2)
                    return 0;
            }
            return dim;
        }
    }
    return 0;
}
Also used : EngineeringCRS(org.opengis.referencing.crs.EngineeringCRS) DefaultEngineeringCRS(org.apache.sis.referencing.crs.DefaultEngineeringCRS) ProjectedCRS(org.opengis.referencing.crs.ProjectedCRS) DefaultProjectedCRS(org.apache.sis.referencing.crs.DefaultProjectedCRS) CoordinateSystem(org.opengis.referencing.cs.CoordinateSystem) EllipsoidalCS(org.opengis.referencing.cs.EllipsoidalCS) GeodeticCRS(org.opengis.referencing.crs.GeodeticCRS)

Example 7 with EllipsoidalCS

use of org.opengis.referencing.cs.EllipsoidalCS in project sis by apache.

the class SubTypes method castOrCopy.

/**
 * Returns a SIS implementation for the given coordinate reference system.
 *
 * @see AbstractCRS#castOrCopy(CoordinateReferenceSystem)
 */
static AbstractCRS castOrCopy(final CoordinateReferenceSystem object) {
    if (object instanceof DerivedCRS) {
        return DefaultDerivedCRS.castOrCopy((DerivedCRS) object);
    }
    if (object instanceof ProjectedCRS) {
        return DefaultProjectedCRS.castOrCopy((ProjectedCRS) object);
    }
    if (object instanceof GeodeticCRS) {
        if (object instanceof GeographicCRS) {
            return DefaultGeographicCRS.castOrCopy((GeographicCRS) object);
        }
        if (object instanceof GeocentricCRS) {
            return DefaultGeocentricCRS.castOrCopy((GeocentricCRS) object);
        }
        /*
             * The GeographicCRS and GeocentricCRS types are not part of ISO 19111.
             * ISO uses a single type, GeodeticCRS, for both of them and infer the
             * geographic or geocentric type from the coordinate system. We do this
             * check here for instantiating the most appropriate SIS type, but only
             * if we need to create a new object anyway (see below for rational).
             */
        if (object instanceof DefaultGeodeticCRS) {
            /*
                 * Result of XML unmarshalling — keep as-is. We avoid creating a new object because it
                 * would break object identities specified in GML document by the xlink:href attribute.
                 * However we may revisit this policy in the future. See SC_CRS.setElement(AbstractCRS).
                 */
            return (DefaultGeodeticCRS) object;
        }
        final Map<String, ?> properties = IdentifiedObjects.getProperties(object);
        final GeodeticDatum datum = ((GeodeticCRS) object).getDatum();
        final CoordinateSystem cs = object.getCoordinateSystem();
        if (cs instanceof EllipsoidalCS) {
            return new DefaultGeographicCRS(properties, datum, (EllipsoidalCS) cs);
        }
        if (cs instanceof SphericalCS) {
            return new DefaultGeocentricCRS(properties, datum, (SphericalCS) cs);
        }
        if (cs instanceof CartesianCS) {
            return new DefaultGeocentricCRS(properties, datum, (CartesianCS) cs);
        }
    }
    if (object instanceof VerticalCRS) {
        return DefaultVerticalCRS.castOrCopy((VerticalCRS) object);
    }
    if (object instanceof TemporalCRS) {
        return DefaultTemporalCRS.castOrCopy((TemporalCRS) object);
    }
    if (object instanceof EngineeringCRS) {
        return DefaultEngineeringCRS.castOrCopy((EngineeringCRS) object);
    }
    if (object instanceof ImageCRS) {
        return DefaultImageCRS.castOrCopy((ImageCRS) object);
    }
    if (object instanceof CompoundCRS) {
        return DefaultCompoundCRS.castOrCopy((CompoundCRS) object);
    }
    /*
         * Intentionally check for AbstractCRS after the interfaces because user may have defined his own
         * subclass implementing the interface. If we were checking for AbstractCRS before the interfaces,
         * the returned instance could have been a user subclass without the JAXB annotations required
         * for XML marshalling.
         */
    if (object == null || object instanceof AbstractCRS) {
        return (AbstractCRS) object;
    }
    return new AbstractCRS(object);
}
Also used : CartesianCS(org.opengis.referencing.cs.CartesianCS) EngineeringCRS(org.opengis.referencing.crs.EngineeringCRS) CoordinateSystem(org.opengis.referencing.cs.CoordinateSystem) DerivedCRS(org.opengis.referencing.crs.DerivedCRS) CompoundCRS(org.opengis.referencing.crs.CompoundCRS) GeodeticDatum(org.opengis.referencing.datum.GeodeticDatum) GeodeticCRS(org.opengis.referencing.crs.GeodeticCRS) SphericalCS(org.opengis.referencing.cs.SphericalCS) TemporalCRS(org.opengis.referencing.crs.TemporalCRS) ProjectedCRS(org.opengis.referencing.crs.ProjectedCRS) ImageCRS(org.opengis.referencing.crs.ImageCRS) VerticalCRS(org.opengis.referencing.crs.VerticalCRS) EllipsoidalCS(org.opengis.referencing.cs.EllipsoidalCS) GeographicCRS(org.opengis.referencing.crs.GeographicCRS) GeocentricCRS(org.opengis.referencing.crs.GeocentricCRS)

Example 8 with EllipsoidalCS

use of org.opengis.referencing.cs.EllipsoidalCS in project sis by apache.

the class CRSPair method label.

/**
 * Returns the name of the GeoAPI interface implemented by the specified object. In the GeographicCRS
 * or EllipsoidalCS cases, the trailing CRS or CS suffix is replaced by the number of dimensions
 * (e.g. "Geographic3D").
 */
static String label(final IdentifiedObject object) {
    if (object == null) {
        return null;
    }
    Class<? extends IdentifiedObject> type;
    if (object instanceof AbstractIdentifiedObject) {
        type = ((AbstractIdentifiedObject) object).getInterface();
    } else {
        type = Classes.getLeafInterfaces(object.getClass(), IdentifiedObject.class)[0];
    }
    String suffix, label = Classes.getShortName(type);
    if (label.endsWith((suffix = "CRS")) || label.endsWith(suffix = "CS")) {
        Object cs = object;
        if (object instanceof CoordinateReferenceSystem) {
            cs = ((CoordinateReferenceSystem) object).getCoordinateSystem();
        }
        if (cs instanceof EllipsoidalCS) {
            final StringBuilder sb = new StringBuilder(label);
            sb.setLength(label.length() - suffix.length());
            label = sb.append(((CoordinateSystem) cs).getDimension()).append('D').toString();
        }
    }
    String name = IdentifiedObjects.getName(object, null);
    if (name != null) {
        // Arbitrary length threshold.
        int i = 30;
        if (name.length() >= i) {
            while (i > 15) {
                // Arbitrary minimal length.
                final int c = name.codePointBefore(i);
                if (Character.isSpaceChar(c))
                    break;
                i -= Character.charCount(c);
            }
            name = CharSequences.trimWhitespaces(name, 0, i).toString() + '…';
        }
        label = label + "[“" + name + "”]";
    }
    return label;
}
Also used : AbstractIdentifiedObject(org.apache.sis.referencing.AbstractIdentifiedObject) CoordinateSystem(org.opengis.referencing.cs.CoordinateSystem) IdentifiedObject(org.opengis.referencing.IdentifiedObject) AbstractIdentifiedObject(org.apache.sis.referencing.AbstractIdentifiedObject) EllipsoidalCS(org.opengis.referencing.cs.EllipsoidalCS) CoordinateReferenceSystem(org.opengis.referencing.crs.CoordinateReferenceSystem)

Example 9 with EllipsoidalCS

use of org.opengis.referencing.cs.EllipsoidalCS in project sis by apache.

the class CoordinateOperationRegistry method propagateVertical.

/**
 * Appends a vertical axis in the source CRS of the first step {@code forward = true} or in
 * the target CRS of the last step {@code forward = false} of the given operations chain.
 *
 * @param  source3D    the potentially three-dimensional source CRS
 * @param  target3D    the potentially three-dimensional target CRS
 * @param  operations  the chain of operations in which to add a vertical axis.
 * @param  forward     {@code true} for adding the vertical axis at the beginning, or
 *                     {@code false} for adding the vertical axis at the end.
 * @return {@code true} on success.
 * @throws IllegalArgumentException if the operation method can not have the desired number of dimensions.
 */
private boolean propagateVertical(final CoordinateReferenceSystem source3D, final CoordinateReferenceSystem target3D, final ListIterator<CoordinateOperation> operations, final boolean forward) throws IllegalArgumentException, FactoryException {
    while (forward ? operations.hasNext() : operations.hasPrevious()) {
        final CoordinateOperation op = forward ? operations.next() : operations.previous();
        /*
             * We will accept to increase the number of dimensions only for operations between geographic CRS.
             * We do not increase the number of dimensions for operations between other kind of CRS because we
             * would not know which value to give to the new dimension.
             */
        CoordinateReferenceSystem sourceCRS, targetCRS;
        if (!((sourceCRS = op.getSourceCRS()) instanceof GeodeticCRS && (targetCRS = op.getTargetCRS()) instanceof GeodeticCRS && sourceCRS.getCoordinateSystem() instanceof EllipsoidalCS && targetCRS.getCoordinateSystem() instanceof EllipsoidalCS)) {
            break;
        }
        /*
             * We can process mostly linear operations, otherwise it is hard to know how to add a dimension.
             * Examples of linear operations are:
             *
             *   - Longitude rotation (EPSG:9601). Note that this is a transformation rather than a conversion.
             *   - Geographic3D to 2D conversion (EPSG:9659).
             *
             * However there is a few special cases where we may be able to add a dimension in a non-linear operation.
             * We can attempt those special cases by just giving the same parameters to the math transform factory
             * together with the desired CRS. Examples of such special cases are:
             *
             *   - Geocentric translations (geog2D domain)
             *   - Coordinate Frame Rotation (geog2D domain)
             *   - Position Vector transformation (geog2D domain)
             */
        Matrix matrix = MathTransforms.getMatrix(op.getMathTransform());
        if (matrix == null) {
            if (SubTypes.isSingleOperation(op)) {
                final MathTransformFactory mtFactory = factorySIS.getMathTransformFactory();
                if (mtFactory instanceof DefaultMathTransformFactory) {
                    if (forward)
                        sourceCRS = toGeodetic3D(sourceCRS, source3D);
                    else
                        targetCRS = toGeodetic3D(targetCRS, target3D);
                    final MathTransform mt;
                    try {
                        mt = ((DefaultMathTransformFactory) mtFactory).createParameterizedTransform(((SingleOperation) op).getParameterValues(), ReferencingUtilities.createTransformContext(sourceCRS, targetCRS, null));
                    } catch (InvalidGeodeticParameterException e) {
                        log(null, e);
                        break;
                    }
                    operations.set(recreate(op, sourceCRS, targetCRS, mt, mtFactory.getLastMethodUsed()));
                    return true;
                }
            }
            break;
        }
        /*
             * We can process only one of the following cases:
             *
             *   - Replace a 2D → 2D operation by a 3D → 3D one (i.e. add a passthrough operation).
             *   - Usually remove (or otherwise edit) the operation that change the number of dimensions
             *     between the 2D and 3D cases.
             */
        final int numRow = matrix.getNumRow();
        final int numCol = matrix.getNumCol();
        // 2D → 2D operation.
        final boolean is2D = (numCol == 3 && numRow == 3);
        if (!(is2D || (// 2D → 3D operation.
        forward ? // 2D → 3D operation.
        (numCol == 3 && numRow == 4) : // 3D → 2D operation.
        (numCol == 4 && numRow == 3)))) {
            break;
        }
        matrix = Matrices.resizeAffine(matrix, 4, 4);
        if (matrix.isIdentity()) {
            operations.remove();
        } else {
            /*
                 * If we can not just remove the operation, build a new one with the expected number of dimensions.
                 * The new operation will inherit the same properties except the identifiers, since it is no longer
                 * conform to the definition provided by the authority.
                 */
            final MathTransform mt = factorySIS.getMathTransformFactory().createAffineTransform(matrix);
            operations.set(recreate(op, toGeodetic3D(sourceCRS, source3D), toGeodetic3D(targetCRS, target3D), mt, null));
        }
        /*
             * If we processed the operation that change the number of dimensions, we are done.
             */
        if (!is2D) {
            return true;
        }
    }
    return false;
}
Also used : InvalidGeodeticParameterException(org.apache.sis.referencing.factory.InvalidGeodeticParameterException) DefaultMathTransformFactory(org.apache.sis.referencing.operation.transform.DefaultMathTransformFactory) DefaultMathTransformFactory(org.apache.sis.referencing.operation.transform.DefaultMathTransformFactory) DeferredCoordinateOperation(org.apache.sis.internal.referencing.DeferredCoordinateOperation) EllipsoidalCS(org.opengis.referencing.cs.EllipsoidalCS) CoordinateReferenceSystem(org.opengis.referencing.crs.CoordinateReferenceSystem) GeodeticCRS(org.opengis.referencing.crs.GeodeticCRS)

Example 10 with EllipsoidalCS

use of org.opengis.referencing.cs.EllipsoidalCS in project sis by apache.

the class Normalizer method normalize.

/**
 * Optionally normalizes and reorders the axes in an attempt to get a right-handed system.
 * If no axis change is needed, then this method returns {@code null}.
 *
 * @param  cs       the coordinate system to normalize.
 * @param  changes  the change to apply on axis direction and units.
 * @param  reorder  {@code true} for reordering the axis for a right-handed coordinate system.
 * @return the normalized coordinate system, or {@code null} if no normalization is needed.
 */
static AbstractCS normalize(final CoordinateSystem cs, final AxisFilter changes, final boolean reorder) {
    boolean changed = false;
    final int dimension = cs.getDimension();
    CoordinateSystemAxis[] axes = new CoordinateSystemAxis[dimension];
    int n = 0;
    for (int i = 0; i < dimension; i++) {
        CoordinateSystemAxis axis = cs.getAxis(i);
        if (changes != null) {
            if (!changes.accept(axis)) {
                continue;
            }
            changed |= (axis != (axis = normalize(axis, changes)));
        }
        axes[n++] = axis;
    }
    axes = ArraysExt.resize(axes, n);
    /*
         * Sort the axes in an attempt to create a right-handed system.
         * If nothing changed, return the given Coordinate System as-is.
         */
    if (reorder) {
        int angularUnitOrder = 0;
        if (// (λ,φ,h) order
        cs instanceof EllipsoidalCS || cs instanceof SphericalCS)
            // (λ,φ,h) order
            angularUnitOrder = -1;
        else // (r,θ) order
        if (cs instanceof CylindricalCS || cs instanceof PolarCS)
            angularUnitOrder = +1;
        changed |= sort(axes, angularUnitOrder);
        if (angularUnitOrder == 1) {
            /*
                 * Change (r,z,θ) to (r,θ,z) order in CylindricalCS. The check on unit of
                 * measurements should be always true, but we verify as a paranoiac check.
                 */
            if (axes.length == 3 && isLengthAndAngle(axes, 1)) {
                ArraysExt.swap(axes, 1, 2);
            }
            /*
                 * If we were not allowed to normalize the axis direction, we may have a
                 * left-handed coordinate system here. If so, make it right-handed.
                 */
            if (AxisDirections.CLOCKWISE.equals(axes[1].getDirection()) && isLengthAndAngle(axes, 0)) {
                ArraysExt.swap(axes, 0, 1);
            }
        }
    }
    if (!changed && n == dimension) {
        return null;
    }
    /*
         * Create a new coordinate system of the same type than the given one, but with the given axes.
         * We need to change the Coordinate System name, since it is likely to not be valid anymore.
         */
    final AbstractCS impl = castOrCopy(cs);
    final StringBuilder buffer = (StringBuilder) CharSequences.camelCaseToSentence(impl.getInterface().getSimpleName());
    return impl.createForAxes(singletonMap(AbstractCS.NAME_KEY, AxisDirections.appendTo(buffer, axes)), axes);
}
Also used : SphericalCS(org.opengis.referencing.cs.SphericalCS) PolarCS(org.opengis.referencing.cs.PolarCS) CylindricalCS(org.opengis.referencing.cs.CylindricalCS) CoordinateSystemAxis(org.opengis.referencing.cs.CoordinateSystemAxis) EllipsoidalCS(org.opengis.referencing.cs.EllipsoidalCS)

Aggregations

EllipsoidalCS (org.opengis.referencing.cs.EllipsoidalCS)16 CoordinateSystem (org.opengis.referencing.cs.CoordinateSystem)9 CartesianCS (org.opengis.referencing.cs.CartesianCS)7 Test (org.junit.Test)5 GeodeticCRS (org.opengis.referencing.crs.GeodeticCRS)5 CoordinateSystemAxis (org.opengis.referencing.cs.CoordinateSystemAxis)5 GeographicCRS (org.opengis.referencing.crs.GeographicCRS)4 ProjectedCRS (org.opengis.referencing.crs.ProjectedCRS)4 GeodeticDatum (org.opengis.referencing.datum.GeodeticDatum)4 DependsOnMethod (org.apache.sis.test.DependsOnMethod)3 CoordinateReferenceSystem (org.opengis.referencing.crs.CoordinateReferenceSystem)3 SphericalCS (org.opengis.referencing.cs.SphericalCS)3 PrimeMeridian (org.opengis.referencing.datum.PrimeMeridian)3 Unit (javax.measure.Unit)2 Angle (javax.measure.quantity.Angle)2 BursaWolfParameters (org.apache.sis.referencing.datum.BursaWolfParameters)2 ParameterValueGroup (org.opengis.parameter.ParameterValueGroup)2 IdentifiedObject (org.opengis.referencing.IdentifiedObject)2 EngineeringCRS (org.opengis.referencing.crs.EngineeringCRS)2 VerticalCRS (org.opengis.referencing.crs.VerticalCRS)2