use of org.opengis.referencing.IdentifiedObject in project sis by apache.
the class ReferencingFunctions method getIdentifiedObject.
/**
* Gets the CRS or other kind of object from the given code.
* If the code is a URN, then it can be any kind of object.
* Otherwise a Coordinate Reference System is assumed.
* This method caches the result.
*
* @param codeOrPath the code allocated by an authority, or the path to a file.
* @param type how to interpret {@code codeOrPath}, or {@code null} for guessing.
* @return the identified object for the given code.
* @throws FactoryException if an error occurred while creating the object.
* @throws DataStoreException if an error occurred while reading a data file.
*/
private IdentifiedObject getIdentifiedObject(final String codeOrPath, CodeType type) throws FactoryException, DataStoreException {
final CacheKey<IdentifiedObject> key = new CacheKey<>(IdentifiedObject.class, codeOrPath, null, null);
IdentifiedObject object = key.peek();
if (object == null) {
final Cache.Handler<IdentifiedObject> handler = key.lock();
try {
object = handler.peek();
if (object == null) {
if (type == null) {
type = CodeType.guess(codeOrPath);
}
if (type.equals(CodeType.URN)) {
object = CRS.getAuthorityFactory(null).createObject(codeOrPath);
} else if (type.isCRS) {
object = CRS.forCode(codeOrPath);
} else {
/*
* Apparently not an AUTHORITY:CODE string.
* Try to read a dataset from a file or URL, then get its CRS.
*/
final Metadata metadata;
try (DataStore store = DataStores.open(codeOrPath)) {
metadata = store.getMetadata();
}
if (metadata != null) {
for (final ReferenceSystem rs : metadata.getReferenceSystemInfo()) {
if (rs instanceof CoordinateReferenceSystem) {
return rs;
} else if (object == null) {
// Will be used as a fallback if we find no CRS.
object = rs;
}
}
}
if (object == null) {
throw new FactoryException(Errors.getResources(getJavaLocale()).getString(Errors.Keys.UnspecifiedCRS));
}
}
}
} finally {
handler.putAndUnlock(object);
}
}
return object;
}
use of org.opengis.referencing.IdentifiedObject in project sis by apache.
the class ReferencingFunctions method getAxis.
/**
* Returns the axis name and units for the specified dimension in a coordinate reference system or coordinate system.
* This method returns a short axis name as used in Well Known Text (WKT) format, for example <cite>"Latitude"</cite>
* instead of <cite>"Geodetic latitude"</cite>.
*
* @param codeOrPath the code allocated by an authority, or the path to a file.
* @param dimension the dimension (1, 2, …).
* @return the name of the requested axis.
*/
@Override
public String getAxis(final String codeOrPath, final int dimension) {
final CacheKey<String> key = new CacheKey<>(String.class, codeOrPath, dimension, null);
String name = key.peek();
if (name == null) {
final Cache.Handler<String> handler = key.lock();
try {
name = handler.peek();
if (name == null) {
final IdentifiedObject object;
try {
object = getIdentifiedObject(codeOrPath, null);
} catch (Exception exception) {
return getLocalizedMessage(exception);
}
CoordinateSystem cs = null;
final CoordinateSystemAxis axis;
if (object instanceof CoordinateSystemAxis) {
axis = (CoordinateSystemAxis) object;
} else {
if (object instanceof CoordinateReferenceSystem) {
cs = ((CoordinateReferenceSystem) object).getCoordinateSystem();
} else if (object instanceof CoordinateSystem) {
cs = (CoordinateSystem) object;
} else {
final Class<?> actual;
if (object instanceof AbstractIdentifiedObject) {
actual = ((AbstractIdentifiedObject) object).getInterface();
} else {
actual = Classes.getClass(object);
}
return Errors.getResources(getJavaLocale()).getString(Errors.Keys.UnexpectedTypeForReference_3, codeOrPath, CoordinateReferenceSystem.class, actual);
}
if (dimension >= 1 && dimension <= cs.getDimension()) {
axis = cs.getAxis(dimension - 1);
} else {
return Errors.getResources(getJavaLocale()).getString(Errors.Keys.IndexOutOfBounds_1, dimension);
}
}
final String unit = axis.getUnit().toString();
name = Transliterator.DEFAULT.toShortAxisName(cs, axis.getDirection(), axis.getName().getCode());
if (unit != null && !unit.isEmpty()) {
name = name + " (" + unit + ')';
}
}
} finally {
handler.putAndUnlock(name);
}
}
return name;
}
use of org.opengis.referencing.IdentifiedObject in project sis by apache.
the class AbstractCoordinateOperation method formatTo.
/**
* Formats this coordinate operation in Well Known Text (WKT) version 2 format.
*
* @param formatter the formatter to use.
* @return {@code "CoordinateOperation"}.
*
* @see <a href="http://docs.opengeospatial.org/is/12-063r5/12-063r5.html#113">WKT 2 specification §17</a>
*/
@Override
protected String formatTo(final Formatter formatter) {
super.formatTo(formatter);
formatter.newLine();
/*
* If the WKT is a component of a ConcatenatedOperation, do not format the source CRS since it is identical
* to the target CRS of the previous step, or to the source CRS of the enclosing "ConcatenatedOperation" if
* this step is the first step.
*
* This decision is SIS-specific since the WKT 2 specification does not define concatenated operations.
* This choice may change in any future SIS version.
*/
final FormattableObject enclosing = formatter.getEnclosingElement(1);
final boolean isSubOperation = (enclosing instanceof PassThroughOperation);
final boolean isComponent = (enclosing instanceof ConcatenatedOperation);
if (!isSubOperation && !isComponent) {
append(formatter, getSourceCRS(), WKTKeywords.SourceCRS);
append(formatter, getTargetCRS(), WKTKeywords.TargetCRS);
}
final OperationMethod method = getMethod();
if (method != null) {
formatter.append(DefaultOperationMethod.castOrCopy(method));
ParameterValueGroup parameters;
try {
parameters = getParameterValues();
} catch (UnsupportedOperationException e) {
final IdentifiedObject c = getParameterDescriptors();
formatter.setInvalidWKT(c != null ? c : this, e);
parameters = null;
}
if (parameters != null) {
/*
* Format the parameter values. Apache SIS uses the EPSG geodetic dataset as the main source of
* parameter definitions. When a parameter is defined by both OGC and EPSG with different names,
* the Formatter class is responsible for choosing an appropriate name. But when the difference
* is more fundamental, we may have duplication. For example in the "Molodensky" operation, OGC
* uses source and target axis lengths while EPSG uses only difference between those lengths.
* In this case, OGC and EPSG parameters are defined separately and are redundant. To simplify
* the CoordinateOperation WKT, we omit non-EPSG parameters when we have determined that we are
* about to describe an EPSG operation. We could generalize this filtering to any authority, but
* we don't because few authorities are as complete as EPSG, so other authorities are more likely
* to mix EPSG or someone else components with their own. Note also that we don't apply filtering
* on MathTransform WKT neither for more reliable debugging.
*/
final boolean filter = // NOT method.getName()
WKTUtilities.isEPSG(parameters.getDescriptor(), false) && Constants.EPSG.equalsIgnoreCase(Citations.getCodeSpace(formatter.getNameAuthority()));
formatter.newLine();
formatter.indent(+1);
for (final GeneralParameterValue param : parameters.values()) {
if (!filter || WKTUtilities.isEPSG(param.getDescriptor(), true)) {
WKTUtilities.append(param, formatter);
}
}
formatter.indent(-1);
}
}
if (!isSubOperation && !(this instanceof ConcatenatedOperation)) {
append(formatter, getInterpolationCRS(), WKTKeywords.InterpolationCRS);
final double accuracy = getLinearAccuracy();
if (accuracy > 0) {
formatter.append(new FormattableObject() {
@Override
protected String formatTo(final Formatter formatter) {
formatter.append(accuracy);
return WKTKeywords.OperationAccuracy;
}
});
}
}
if (formatter.getConvention().majorVersion() == 1) {
formatter.setInvalidWKT(this, null);
}
if (isComponent) {
formatter.setInvalidWKT(this, null);
return "CoordinateOperationStep";
}
return WKTKeywords.CoordinateOperation;
}
use of org.opengis.referencing.IdentifiedObject 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;
}
use of org.opengis.referencing.IdentifiedObject in project sis by apache.
the class CoordinateOperationFinder method derivedFrom.
/**
* Returns a name for an object derived from the specified one.
* This method builds a name of the form "{@literal <original identifier>} (step 1)"
* where "(step 1)" may be replaced by "(step 2)", "(step 3)", <i>etc.</i> if this
* method has already been invoked for the same identifier (directly or indirectly).
*/
private Map<String, ?> derivedFrom(final IdentifiedObject object) {
Identifier oldID = object.getName();
Object p = identifierOfStepCRS.get(oldID);
if (p instanceof Identifier) {
oldID = (Identifier) p;
p = identifierOfStepCRS.get(oldID);
}
final int count = (p != null) ? (Integer) p + 1 : 1;
final Identifier newID = new NamedIdentifier(Citations.SIS, oldID.getCode() + " (step " + count + ')');
identifierOfStepCRS.put(newID, oldID);
identifierOfStepCRS.put(oldID, count);
final Map<String, Object> properties = new HashMap<>(4);
properties.put(IdentifiedObject.NAME_KEY, newID);
properties.put(IdentifiedObject.REMARKS_KEY, Vocabulary.formatInternational(Vocabulary.Keys.DerivedFrom_1, CRSPair.label(object)));
return properties;
}
Aggregations