use of org.opengis.referencing.operation.Conversion in project sis by apache.
the class TransformTestCase method testTransformNotOverPole.
/**
* Tests conversions of an envelope or rectangle which is <strong>not</strong> over a pole,
* but was wrongly considered as over a pole before SIS-329 fix.
*
* @throws FactoryException if an error occurred while creating the operation.
* @throws TransformException if an error occurred while transforming the envelope.
*
* @see <a href="https://issues.apache.org/jira/browse/SIS-329">SIS-329</a>
*/
@Test
@DependsOnMethod("testTransform")
public final void testTransformNotOverPole() throws FactoryException, TransformException {
final ProjectedCRS sourceCRS = CommonCRS.WGS84.universal(10, -3.5);
final GeographicCRS targetCRS = sourceCRS.getBaseCRS();
final Conversion conversion = inverse(sourceCRS.getConversionFromBase());
final G rectangle = createFromExtremums(sourceCRS, 199980, 4490220, 309780, 4600020);
final G expected = createFromExtremums(targetCRS, // Computed by SIS (not validated by external authority).
40.50846282536367, // Computed by SIS (not validated by external authority).
-6.594124551832373, 41.52923550023067, -5.246186118392847);
final G actual = transform(conversion, rectangle);
assertGeometryEquals(expected, actual, ANGULAR_TOLERANCE, ANGULAR_TOLERANCE);
}
use of org.opengis.referencing.operation.Conversion in project sis by apache.
the class DefaultOperationMethod method formatTo.
/**
* Formats this operation as a <cite>Well Known Text</cite> {@code Method[…]} element.
*
* @return {@code "Method"} (WKT 2) or {@code "Projection"} (WKT 1).
*
* @see <a href="http://docs.opengeospatial.org/is/12-063r5/12-063r5.html#118">WKT 2 specification §17.2.3</a>
*/
@Override
protected String formatTo(final Formatter formatter) {
final boolean isWKT1 = formatter.getConvention().majorVersion() == 1;
/*
* The next few lines below are basically a copy of the work done by super.formatTo(formatter),
* which search for the name to write inside METHOD["name"]. The difference is in the fallback
* executed if we do not find a name for the given authority.
*/
final Citation authority = formatter.getNameAuthority();
String name = IdentifiedObjects.getName(this, authority);
ElementKind kind = ElementKind.METHOD;
if (name == null) {
/*
* No name found for the given authority. We may use the primary name as a fallback.
* But before doing that, maybe we can find the name that we are looking for in the
* hard-coded values in the 'org.apache.sis.internal.referencing.provider' package.
* The typical use case is when this DefaultOperationMethod has been instantiated
* by the EPSG factory using only the information found in the EPSG database.
*
* We can find the hard-coded names by looking at the ParameterDescriptorGroup of the
* enclosing ProjectedCRS or DerivedCRS. This is because that parameter descriptor was
* typically provided by the 'org.apache.sis.internal.referencing.provider' package in
* order to create the MathTransform associated with the enclosing CRS. The enclosing
* CRS is either the immediate parent in WKT 1, or the parent of the parent in WKT 2.
*/
final FormattableObject parent = formatter.getEnclosingElement(isWKT1 ? 1 : 2);
if (parent instanceof GeneralDerivedCRS) {
final Conversion conversion = ((GeneralDerivedCRS) parent).getConversionFromBase();
if (conversion != null) {
// Should never be null, but let be safe.
final ParameterDescriptorGroup descriptor;
if (conversion instanceof Parameterized) {
// Usual case in SIS implementation.
descriptor = ((Parameterized) conversion).getParameterDescriptors();
} else {
descriptor = conversion.getParameterValues().getDescriptor();
}
name = IdentifiedObjects.getName(descriptor, authority);
}
}
if (name == null) {
name = IdentifiedObjects.getName(this, null);
if (name == null) {
name = Vocabulary.getResources(formatter.getLocale()).getString(Vocabulary.Keys.Unnamed);
// Because the "Unnamed" string is not a real OperationMethod name.
kind = ElementKind.NAME;
}
}
}
formatter.append(name, kind);
if (isWKT1) {
/*
* The WKT 1 keyword is "PROJECTION", which imply that the operation method should be of type
* org.opengis.referencing.operation.Projection. So strictly speaking only the first check in
* the following 'if' statement is relevant.
*
* Unfortunately in many cases we do not know the operation type, because the method that we
* invoked - getOperationType() - is not a standard OGC/ISO property, so this information is
* usually not provided in XML documents for example. The user could also have instantiated
* DirectOperationMethod directly without creating a subclass. Consequently we also accept to
* format the keyword as "PROJECTION" if the operation type *could* be a projection. This is
* the second check in the following 'if' statement.
*
* In other words, the combination of those two checks exclude the following operation types:
* Transformation, ConcatenatedOperation, PassThroughOperation, or any user-defined type that
* do not extend Projection. All other operation types are accepted.
*/
final Class<? extends SingleOperation> type = getOperationType();
if (Projection.class.isAssignableFrom(type) || type.isAssignableFrom(Projection.class)) {
return WKTKeywords.Projection;
}
formatter.setInvalidWKT(this, null);
}
return WKTKeywords.Method;
}
use of org.opengis.referencing.operation.Conversion in project sis by apache.
the class DefaultDerivedCRSTest method testConstruction.
/**
* Tests the construction of a {@link DefaultDerivedCRS}.
*/
@Test
public void testConstruction() {
final DefaultDerivedCRS crs = createLongitudeRotation();
// Validators.validate(crs);
assertEquals("name", "Back to Greenwich", crs.getName().getCode());
assertEquals("baseCRS", "NTF (Paris)", crs.getBaseCRS().getName().getCode());
assertEquals("datum", "Nouvelle Triangulation Française", crs.getDatum().getName().getCode());
assertSame("coordinateSystem", HardCodedCS.GEODETIC_φλ, crs.getCoordinateSystem());
final Conversion conversion = crs.getConversionFromBase();
assertSame("sourceCRS", crs.getBaseCRS(), conversion.getSourceCRS());
assertSame("targetCRS", crs, conversion.getTargetCRS());
assertMatrixEquals("Longitude rotation", new Matrix3(0, 1, 0, 1, 0, 2.33722917, 0, 0, 1), MathTransforms.getMatrix(conversion.getMathTransform()), STRICT);
}
use of org.opengis.referencing.operation.Conversion in project sis by apache.
the class DefaultDerivedCRS method formatTo.
/**
* Formats the inner part of the <cite>Well Known Text</cite> (WKT) representation of this CRS.
*
* @return {@code "Fitted_CS"} (WKT 1) or a type-dependent keyword (WKT 2).
*
* @see <a href="http://docs.opengeospatial.org/is/12-063r5/12-063r5.html#93">WKT 2 specification §15</a>
*/
@Override
protected String formatTo(final Formatter formatter) {
// Gives to users a chance to override.
final Conversion conversion = getConversionFromBase();
if (conversion == null) {
/*
* Should never happen except temporarily at construction time, or if the user invoked the copy
* constructor with an invalid Conversion, or if the user overrides the getConversionFromBase()
* method. Delegates to the super-class method for avoiding a NullPointerException. That method
* returns 'null', which will cause the WKT to be declared invalid.
*/
return super.formatTo(formatter);
}
WKTUtilities.appendName(this, formatter, null);
final Convention convention = formatter.getConvention();
final boolean isWKT1 = (convention.majorVersion() == 1);
/*
* Both WKT 1 and WKT 2 format the base CRS. But WKT 1 formats the MathTransform before the base CRS,
* while WKT 2 formats the conversion method and parameter values after the base CRS.
*/
if (isWKT1) {
MathTransform inverse = conversion.getMathTransform();
try {
inverse = inverse.inverse();
} catch (NoninvertibleTransformException exception) {
formatter.setInvalidWKT(this, exception);
inverse = null;
}
formatter.newLine();
formatter.append(inverse);
}
formatter.newLine();
formatter.append(WKTUtilities.toFormattable(getBaseCRS()));
if (isWKT1) {
return WKTKeywords.Fitted_CS;
} else {
formatter.newLine();
formatter.append(new // Format inside a "DefiningConversion" element.
FormattableObject() {
@Override
protected String formatTo(final Formatter formatter) {
WKTUtilities.appendName(conversion, formatter, null);
formatter.newLine();
formatter.append(DefaultOperationMethod.castOrCopy(conversion.getMethod()));
formatter.newLine();
for (final GeneralParameterValue param : conversion.getParameterValues().values()) {
WKTUtilities.append(param, formatter);
}
return WKTKeywords.DerivingConversion;
}
});
if (convention == Convention.INTERNAL || !isBaseCRS(formatter)) {
final CoordinateSystem cs = getCoordinateSystem();
formatCS(formatter, cs, ReferencingUtilities.getUnit(cs), isWKT1);
}
return keyword(formatter);
}
}
use of org.opengis.referencing.operation.Conversion 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);
}
}
Aggregations