use of org.opengis.referencing.cs.EllipsoidalCS in project sis by apache.
the class EllipsoidalHeightCombiner method createCompoundCRS.
/**
* Creates a compound CRS, but we special processing for (two-dimensional Geographic + ellipsoidal heights) tupples.
* If any such tupple is found, a three-dimensional geographic CRS is created instead than the compound CRS.
*
* @param properties name and other properties to give to the new object.
* @param components ordered array of {@code CoordinateReferenceSystem} objects.
* @return the coordinate reference system for the given properties.
* @throws FactoryException if the object creation failed.
*/
public final CoordinateReferenceSystem createCompoundCRS(final Map<String, ?> properties, CoordinateReferenceSystem... components) throws FactoryException {
for (int i = 0; i < components.length; i++) {
final CoordinateReferenceSystem vertical = components[i];
if (vertical instanceof VerticalCRS) {
final VerticalDatum datum = ((VerticalCRS) vertical).getDatum();
if (datum != null && datum.getVerticalDatumType() == VerticalDatumTypes.ELLIPSOIDAL) {
int axisPosition = 0;
CoordinateSystem cs = null;
CoordinateReferenceSystem crs = null;
if (i == 0 || (cs = getCsIfHorizontal2D(crs = components[i - 1])) == null) {
/*
* GeographicCRS are normally before VerticalCRS. But Apache SIS is tolerant to the
* opposite order (note however that such ordering is illegal according ISO 19162).
*/
if (i + 1 >= components.length || (cs = getCsIfHorizontal2D(crs = components[i + 1])) == null) {
continue;
}
axisPosition = 1;
}
/*
* At this point we have the horizontal and vertical components. The horizontal component
* begins at 'axisPosition', which is almost always zero. Create the three-dimensional CRS.
* If the result is the CRS to be returned directly by this method (components.length == 2),
* use the properties given in argument. Otherwise we need to use other properties; current
* implementation recycles the properties of the existing two-dimensional CRS.
*/
final CoordinateSystemAxis[] axes = new CoordinateSystemAxis[3];
axes[axisPosition++] = cs.getAxis(0);
axes[axisPosition++] = cs.getAxis(1);
axes[axisPosition %= 3] = vertical.getCoordinateSystem().getAxis(0);
final ReferencingServices referencing = ReferencingServices.getInstance();
final Map<String, ?> csProps = referencing.getProperties(cs, false);
final Map<String, ?> crsProps = (components.length == 2) ? properties : referencing.getProperties(crs, false);
if (crs instanceof GeodeticCRS) {
initialize(CS | CRS);
cs = csFactory.createEllipsoidalCS(csProps, axes[0], axes[1], axes[2]);
crs = crsFactory.createGeographicCRS(crsProps, ((GeodeticCRS) crs).getDatum(), (EllipsoidalCS) cs);
} else {
initialize(CS | CRS | OPERATION);
final ProjectedCRS proj = (ProjectedCRS) crs;
GeographicCRS base = proj.getBaseCRS();
if (base.getCoordinateSystem().getDimension() == 2) {
base = (GeographicCRS) createCompoundCRS(referencing.getProperties(base, false), base, vertical);
}
/*
* In Apache SIS implementation, the Conversion contains the source and target CRS together with
* a MathTransform2D. We need to recreate the same conversion, but without CRS and MathTransform
* for letting SIS create or associate new ones, which will be three-dimensional now.
*/
Conversion fromBase = proj.getConversionFromBase();
fromBase = opFactory.createDefiningConversion(referencing.getProperties(fromBase, true), fromBase.getMethod(), fromBase.getParameterValues());
cs = csFactory.createCartesianCS(csProps, axes[0], axes[1], axes[2]);
crs = crsFactory.createProjectedCRS(crsProps, base, fromBase, (CartesianCS) cs);
}
/*
* Remove the VerticalCRS and store the three-dimensional GeographicCRS in place of the previous
* two-dimensional GeographicCRS. Then let the loop continues in case there is other CRS to merge
* (should never happen, but we are paranoiac).
*/
components = ArraysExt.remove(components, i, 1);
// GeographicCRS before VerticalCRS (usual case).
if (axisPosition != 0)
i--;
components[i] = crs;
}
}
}
switch(components.length) {
case 0:
return null;
case 1:
return components[0];
default:
initialize(CRS);
return crsFactory.createCompoundCRS(properties, components);
}
}
use of org.opengis.referencing.cs.EllipsoidalCS in project sis by apache.
the class StandardDefinitionsTest method testCreateGeographicCRS.
/**
* Compares the values created by {@code StandardDefinitions} against hard-coded constants.
* This method tests the following methods:
*
* <ul>
* <li>{@link StandardDefinitions#createEllipsoid(short)}</li>
* <li>{@link StandardDefinitions#createGeodeticDatum(short, Ellipsoid, PrimeMeridian)}</li>
* <li>{@link StandardDefinitions#createGeographicCRS(short, GeodeticDatum, EllipsoidalCS)}</li>
* </ul>
*
* The geodetic objects are compared against the {@link HardCodedCRS}, {@link HardCodedDatum} and
* {@link GeodeticDatumMock} constants. Actually this is more a test of the above-cited constants
* than a {@code StandardDefinitions} one - in case of test failure, any of those classes could be
* at fault.
*/
@Test
@DependsOnMethod("testCreateAxis")
public void testCreateGeographicCRS() {
final PrimeMeridian pm = StandardDefinitions.primeMeridian();
final EllipsoidalCS cs = (EllipsoidalCS) StandardDefinitions.createCoordinateSystem((short) 6422);
for (final CommonCRS e : CommonCRS.values()) {
final Ellipsoid ellipsoid = StandardDefinitions.createEllipsoid(e.ellipsoid);
switch(e) {
case WGS84:
compare(GeodeticDatumMock.WGS84.getEllipsoid(), ellipsoid);
break;
case WGS72:
compare(GeodeticDatumMock.WGS72.getEllipsoid(), ellipsoid);
break;
case NAD83:
compare(GeodeticDatumMock.NAD83.getEllipsoid(), ellipsoid);
break;
case NAD27:
compare(GeodeticDatumMock.NAD27.getEllipsoid(), ellipsoid);
break;
case SPHERE:
compare(GeodeticDatumMock.SPHERE.getEllipsoid(), ellipsoid);
break;
}
final GeodeticDatum datum = StandardDefinitions.createGeodeticDatum(e.datum, ellipsoid, pm);
switch(e) {
case WGS84:
compare(HardCodedDatum.WGS84, datum);
break;
case WGS72:
compare(HardCodedDatum.WGS72, datum);
break;
case SPHERE:
compare(HardCodedDatum.SPHERE, datum);
break;
}
final GeographicCRS crs = StandardDefinitions.createGeographicCRS(e.geographic, datum, cs);
Validators.validate(crs);
switch(e) {
case WGS84:
compare(HardCodedCRS.WGS84, crs);
break;
}
Validators.validate(crs);
}
}
use of org.opengis.referencing.cs.EllipsoidalCS in project sis by apache.
the class CoordinateSystemsTest method testReplaceAxes.
/**
* Tests {@link CoordinateSystems#replaceAxes(CoordinateSystem, AxisFilter)}
* without change of coordinate system type.
*/
@Test
public void testReplaceAxes() {
final EllipsoidalCS sourceCS = HardCodedCS.GEODETIC_3D;
// What we want to get.
final EllipsoidalCS targetCS = HardCodedCS.ELLIPSOIDAL_gon;
final CoordinateSystem actualCS = CoordinateSystems.replaceAxes(sourceCS, new AxisFilter() {
@Override
public boolean accept(final CoordinateSystemAxis axis) {
return Units.isAngular(axis.getUnit());
}
@Override
public Unit<?> getUnitReplacement(CoordinateSystemAxis axis, Unit<?> unit) {
if (Units.isAngular(unit)) {
unit = Units.GRAD;
}
return unit;
}
});
assertEqualsIgnoreMetadata(targetCS, actualCS);
}
use of org.opengis.referencing.cs.EllipsoidalCS in project sis by apache.
the class CoordinateSystemsTest method testReplaceAxesWithTypeChange.
/**
* Tests {@link CoordinateSystems#replaceAxes(CoordinateSystem, AxisFilter)}
* with a change of coordinate system type.
*/
@Test
@DependsOnMethod("testReplaceAxes")
public void testReplaceAxesWithTypeChange() {
final EllipsoidalCS sourceCS = HardCodedCS.GEODETIC_3D;
// What we want to get.
final VerticalCS targetCS = HardCodedCS.ELLIPSOIDAL_HEIGHT;
final CoordinateSystem actualCS = CoordinateSystems.replaceAxes(sourceCS, new AxisFilter() {
@Override
public boolean accept(final CoordinateSystemAxis axis) {
return Units.isLinear(axis.getUnit());
}
});
assertEqualsIgnoreMetadata(targetCS, actualCS);
}
use of org.opengis.referencing.cs.EllipsoidalCS in project sis by apache.
the class DefaultMathTransformFactory method createCoordinateSystemChange.
/**
* Creates a math transform that represent a change of coordinate system. If exactly one argument is
* an {@linkplain org.apache.sis.referencing.cs.DefaultEllipsoidalCS ellipsoidal coordinate systems},
* then the {@code ellipsoid} argument is mandatory. In all other cases (including the case where both
* coordinate systems are ellipsoidal), the ellipsoid argument is ignored and can be {@code null}.
*
* <div class="note"><b>Design note:</b>
* this method does not accept separated ellipsoid arguments for {@code source} and {@code target} because
* this method should not be used for datum shifts. If the two given coordinate systems are ellipsoidal,
* then they are assumed to use the same ellipsoid. If different ellipsoids are desired, then a
* {@linkplain #createParameterizedTransform parameterized transform} like <cite>"Molodensky"</cite>,
* <cite>"Geocentric translations"</cite>, <cite>"Coordinate Frame Rotation"</cite> or
* <cite>"Position Vector transformation"</cite> should be used instead.</div>
*
* @param source the source coordinate system.
* @param target the target coordinate system.
* @param ellipsoid the ellipsoid of {@code EllipsoidalCS}, or {@code null} if none.
* @return a conversion from the given source to the given target coordinate system.
* @throws FactoryException if the conversion can not be created.
*
* @since 0.8
*/
public MathTransform createCoordinateSystemChange(final CoordinateSystem source, final CoordinateSystem target, final Ellipsoid ellipsoid) throws FactoryException {
ArgumentChecks.ensureNonNull("source", source);
ArgumentChecks.ensureNonNull("target", target);
if (ellipsoid != null) {
final boolean isEllipsoidalSource = (source instanceof EllipsoidalCS);
if (isEllipsoidalSource != (target instanceof EllipsoidalCS)) {
/*
* For now we support only conversion between EllipsoidalCS and CartesianCS.
* But future Apache SIS versions could add support for conversions between
* EllipsoidalCS and SphericalCS or other coordinate systems.
*/
if ((isEllipsoidalSource ? target : source) instanceof CartesianCS) {
final Context context = new Context();
final EllipsoidalCS cs;
final String operation;
if (isEllipsoidalSource) {
operation = GeographicToGeocentric.NAME;
context.setSource(cs = (EllipsoidalCS) source, ellipsoid);
context.setTarget(target);
} else {
operation = GeocentricToGeographic.NAME;
context.setSource(source);
context.setTarget(cs = (EllipsoidalCS) target, ellipsoid);
}
final ParameterValueGroup pg = getDefaultParameters(operation);
// Apache SIS specific parameter.
if (cs.getDimension() < 3)
pg.parameter("dim").setValue(2);
return createParameterizedTransform(pg, context);
}
}
}
return CoordinateSystemTransform.create(this, source, target);
// No need to use unique(…) here.
}
Aggregations