blob: 65a7624e86daf1cf0ef800e9d90817751d7ca57a [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.sis.referencing.crs;
import org.opengis.parameter.ParameterValue;
import org.opengis.parameter.GeneralParameterValue;
import org.opengis.parameter.GeneralParameterDescriptor;
import org.opengis.referencing.datum.Datum;
import org.opengis.referencing.datum.GeodeticDatum;
import org.opengis.referencing.datum.Ellipsoid;
import org.opengis.referencing.operation.Conversion;
import org.apache.sis.referencing.IdentifiedObjects;
import org.apache.sis.referencing.operation.DefaultOperationMethod;
import org.apache.sis.referencing.privy.WKTKeywords;
import org.apache.sis.referencing.privy.WKTUtilities;
import org.apache.sis.util.privy.Constants;
import org.apache.sis.io.wkt.FormattableObject;
import org.apache.sis.io.wkt.Formatter;
import org.apache.sis.util.logging.Logging;
/**
* Temporary object for formatting the projection method and parameters inside a {@code Conversion} element.
* This object formats only the explicit parameters. Implicit parameters derived from source ellipsoid are omitted.
*
* @author Martin Desruisseaux (IRD, Geomatys)
*/
final class ExplicitParameters extends FormattableObject {
/**
* The conversion which specify the operation method and parameters.
*/
private final Conversion conversion;
/**
* Semi-major and semi-minor axis lengths, or {@code null} if the datum is not geodetic.
*/
private final Ellipsoid ellipsoid;
/**
* The keyword to be returned by {@link #formatTo(Formatter)}.
* Should be {@link WKTKeywords#Conversion} or {@link WKTKeywords#DerivingConversion}.
*/
private final String keyword;
/**
* Creates a new temporary {@code Conversion} elements for the parameters of the given CRS.
*/
ExplicitParameters(final AbstractDerivedCRS crs, final String keyword) {
conversion = crs.getConversionFromBase();
final Datum datum = crs.getDatum();
ellipsoid = (datum instanceof GeodeticDatum) ? ((GeodeticDatum) datum).getEllipsoid() : null;
this.keyword = keyword;
}
/**
* Formats this {@code Conversion} element.
*/
@Override
protected String formatTo(final Formatter formatter) {
WKTUtilities.appendName(conversion, formatter, null);
formatter.newLine();
append(formatter);
return keyword;
}
/**
* Formats this {@code Conversion} element without the conversion name.
*/
void append(final Formatter formatter) {
formatter.append(DefaultOperationMethod.castOrCopy(conversion.getMethod()));
formatter.newLine();
for (final GeneralParameterValue param : conversion.getParameterValues().values()) {
final GeneralParameterDescriptor desc = param.getDescriptor();
if (ellipsoid != null) {
String name;
if (IdentifiedObjects.isHeuristicMatchForName(desc, name = Constants.SEMI_MAJOR) ||
IdentifiedObjects.isHeuristicMatchForName(desc, name = Constants.SEMI_MINOR))
{
/*
* Do not format semi-major and semi-minor axis length in most cases, since those
* information are provided in the ellipsoid. An exception to this rule occurs if
* the lengths are different from the ones declared in the datum.
*/
if (param instanceof ParameterValue<?>) {
final double value;
try {
value = ((ParameterValue<?>) param).doubleValue(ellipsoid.getAxisUnit());
} catch (IllegalStateException e) {
/*
* May happen if the `conversionFromBase` parameter group does not provide values
* for "semi_major" or "semi_minor" axis length. This should not happen with SIS
* implementation, but may happen with user-defined map projection implementations.
* Since the intent of this check was to skip those parameters anyway, it is okay
* for the purpose of WKT formatting if there are no parameters for axis lengths.
*/
Logging.recoverableException(WKTUtilities.LOGGER, DefaultProjectedCRS.class, "formatTo", e);
continue;
}
if (Double.isNaN(value)) {
continue;
}
final double expected = (name == Constants.SEMI_MINOR) // using `==` is okay here.
? ellipsoid.getSemiMinorAxis() : ellipsoid.getSemiMajorAxis();
if (value == expected) {
continue;
}
}
}
}
WKTUtilities.append(param, formatter);
}
}
}