use of org.opengis.referencing.cs.CoordinateSystemAxis in project hale by halestudio.
the class AreaCalc method checkEPSG.
/**
* Checks if GeoPosition are in a metric system and if not convert them if
* necessary.
*
* @param pos List of {@link GeoPosition}
*
* @return List of {@link GeoPosition}
*/
public List<GeoPosition> checkEPSG(List<GeoPosition> pos) {
// list is empty
if (pos.size() == 0) {
return pos;
}
//
int epsg = pos.get(0).getEpsgCode();
// Worldmercator
int FALLBACK_EPSG = 3395;
// WGS84
FALLBACK_EPSG = 4326;
try {
CoordinateSystem cs = CRS.decode("EPSG:" + epsg).getCoordinateSystem();
for (int i = 0; epsg != FALLBACK_EPSG && i < cs.getDimension(); i++) {
CoordinateSystemAxis axis = cs.getAxis(i);
try {
Unit<Length> unit = axis.getUnit().asType(Length.class);
if (!unit.toString().equals("m")) {
// $NON-NLS-1$
// not metric
epsg = FALLBACK_EPSG;
}
} catch (ClassCastException e) {
// no length unit
epsg = FALLBACK_EPSG;
}
}
} catch (Exception e) {
e.printStackTrace();
}
// convert all coordinates
try {
GeotoolsConverter g = (GeotoolsConverter) GeotoolsConverter.getInstance();
pos = g.convertAll(pos, epsg);
} catch (IllegalGeoPositionException e1) {
e1.printStackTrace();
}
return pos;
}
use of org.opengis.referencing.cs.CoordinateSystemAxis in project sis by apache.
the class Extents method getVerticalRange.
/**
* Returns the union of chosen vertical ranges found in the given extent, or {@code null} if none.
* This method gives preference to heights above the Mean Sea Level when possible.
* Depths have negative height values: if the
* {@linkplain org.apache.sis.referencing.cs.DefaultCoordinateSystemAxis#getDirection() axis direction}
* is toward down, then this method reverses the sign of minimum and maximum values.
*
* <div class="section">Multi-occurrences</div>
* If the given {@code Extent} object contains more than one vertical extent, then this method
* performs a choice based on the vertical datum and the unit of measurement:
*
* <ul class="verbose">
* <li><p><b>Choice based on vertical datum</b><br>
* Only the extents associated (indirectly, through their CRS) to the same non-null {@link VerticalDatumType}
* will be taken in account. If all datum types are null, then this method conservatively uses only the first
* vertical extent. Otherwise the datum type used for filtering the vertical extents is:</p>
*
* <ul>
* <li>{@link VerticalDatumType#GEOIDAL} or {@link VerticalDatumType#DEPTH DEPTH} if at least one extent
* uses those datum types. For this method, {@code DEPTH} is considered as equivalent to {@code GEOIDAL}
* except for the axis direction.</li>
* <li>Otherwise, the first non-null datum type found in iteration order.</li>
* </ul>
*
* <div class="note"><b>Rational:</b> like {@linkplain #getGeographicBoundingBox(Extent) geographic bounding box},
* the vertical range is an approximative information; the range returned by this method does not carry any
* information about the vertical CRS and this method does not attempt to perform coordinate transformation.
* But this method is more useful if the returned ranges are close to a frequently used surface, like the
* Mean Sea Level. The same simplification is applied in the
* <a href="http://docs.opengeospatial.org/is/12-063r5/12-063r5.html#31">{@code VerticalExtent} element of
* Well Known Text (WKT) format</a>, which specifies that <cite>“Vertical extent is an approximate description
* of location; heights are relative to an unspecified mean sea level.”</cite></div></li>
*
* <li><p><b>Choice based on units of measurement</b><br>
* If, after the choice based on the vertical datum described above, there is still more than one vertical
* extent to consider, then the next criterion checks for the units of measurement.</p>
* <ul>
* <li>If no range specify a unit of measurement, return the first range and ignore all others.</li>
* <li>Otherwise take the first range having a unit of measurement. Then:<ul>
* <li>All other ranges having an incompatible unit of measurement will be ignored.</li>
* <li>All other ranges having a compatible unit of measurement will be converted to
* the unit of the first retained range, and their union will be computed.</li>
* </ul></li>
* </ul>
*
* <div class="note"><b>Example:</b>
* Heights or depths are often measured using some pressure units, for example hectopascals (hPa).
* An {@code Extent} could contain two vertical elements: one with the height measurements in hPa,
* and the other element with heights transformed to metres using an empirical formula.
* In such case this method will select the first vertical element on the assumption that it is
* the "main" one that the metadata producer intended to show. Next, this method will search for
* other vertical elements using pressure unit. In our example there is none, but if such elements
* were found, this method would compute their union.</div></li>
* </ul>
*
* @param extent the extent to convert to a vertical measurement range, or {@code null}.
* @return a vertical measurement range created from the given extent, or {@code null} if none.
*
* @since 0.4
*/
public static MeasurementRange<Double> getVerticalRange(final Extent extent) {
MeasurementRange<Double> range = null;
VerticalDatumType selectedType = null;
if (extent != null) {
for (final VerticalExtent element : extent.getVerticalElements()) {
double min = element.getMinimumValue();
double max = element.getMaximumValue();
final VerticalCRS crs = element.getVerticalCRS();
VerticalDatumType type = null;
Unit<?> unit = null;
if (crs != null) {
final VerticalDatum datum = crs.getDatum();
if (datum != null) {
type = datum.getVerticalDatumType();
if (VerticalDatumType.DEPTH.equals(type)) {
type = VerticalDatumType.GEOIDAL;
}
}
final CoordinateSystemAxis axis = crs.getCoordinateSystem().getAxis(0);
unit = axis.getUnit();
if (AxisDirection.DOWN.equals(axis.getDirection())) {
final double tmp = min;
min = -max;
max = -tmp;
}
}
if (range != null) {
/*
* If the new range does not specify any datum type or unit, then we do not know how to
* convert the values before to perform the union operation. Conservatively do nothing.
*/
if (type == null || unit == null) {
continue;
}
/*
* If the new range is not measured relative to the same kind of surface than the previous range,
* then we do not know how to combine those ranges. Do nothing, unless the new range is a Mean Sea
* Level Height in which case we forget all previous ranges and use the new one instead.
*/
if (!type.equals(selectedType)) {
if (!type.equals(VerticalDatumType.GEOIDAL)) {
continue;
}
} else if (selectedType != null) {
/*
* If previous range did not specify any unit, then unconditionally replace it by
* the new range since it provides more information. If both ranges specify units,
* then we will compute the union if we can, or ignore the new range otherwise.
*/
final Unit<?> previous = range.unit();
if (previous != null) {
if (previous.isCompatible(unit)) {
range = (MeasurementRange<Double>) range.union(MeasurementRange.create(min, true, max, true, unit));
}
continue;
}
}
}
range = MeasurementRange.create(min, true, max, true, unit);
selectedType = type;
}
}
return range;
}
use of org.opengis.referencing.cs.CoordinateSystemAxis in project sis by apache.
the class AxisDirectionsTest method verifyAbbreviationConsistency.
/**
* Verifies that the abbreviations used in {@link HardCodedAxes} constants are consistent with the abbreviations
* suggested by {@link AxisDirections#suggestAbbreviation(String, AxisDirection, Unit)}. Note that a failure in
* this verification does not necessarily means that the {@code suggestAbbreviation(…)}. It could also be the
* hard-coded constant which need a revision, or we may decide that the different abbreviations are intended and
* should not be compared.
*
* @throws IllegalAccessException should never happen since we inspect only for public fields.
*
* @since 0.6
*/
@Test
public void verifyAbbreviationConsistency() throws IllegalAccessException {
for (final Field field : HardCodedAxes.class.getFields()) {
if (CoordinateSystemAxis.class.isAssignableFrom(field.getType())) {
final CoordinateSystemAxis axis = (CoordinateSystemAxis) field.get(null);
assertEquals(field.getName(), axis.getAbbreviation(), AxisDirections.suggestAbbreviation(axis.getName().getCode(), axis.getDirection(), axis.getUnit()));
}
}
}
use of org.opengis.referencing.cs.CoordinateSystemAxis in project sis by apache.
the class GeodeticObjectVerifier method assertIsProjected2D.
/**
* Asserts that the given coordinate system contains the (easting, northing) axes in metres.
* This method verifies the following properties:
*
* <table class="sis">
* <caption>Verified properties</caption>
* <tr><th>Property</th> <th colspan="2">Expected value</th></tr>
* <tr><td>{@linkplain CartesianCS#getDimension() Dimension}</td>
* <td colspan="2">2</td></tr>
* <tr><td>Axes {@linkplain Identifier#getCode() Code} of the {@linkplain GeodeticDatum#getName() name}</td>
* <td>{@code "Easting"}</td>
* <td>{@code "Northing"}</td></tr>
* <tr><td>Axes {@linkplain CoordinateSystemAxis#getAbbreviation() abbreviation}</td>
* <td>{@code "E"}</td>
* <td>{@code "N"}</td></tr>
* <tr><td>Axes {@linkplain CoordinateSystemAxis#getDirection() direction}</td>
* <td>{@link AxisDirection#EAST EAST}</td>
* <td>{@link AxisDirection#NORTH NORTH}</td></tr>
* <tr><td>Axes {@linkplain CoordinateSystemAxis#getUnit() units}</td>
* <td>{@link Units#METRE}</td>
* <td>{@link Units#METRE}</td></tr>
* <tr><td>Axes range</td>
* <td>[−∞ … ∞]</td>
* <td>[−∞ … ∞]</td></tr>
* <tr><td>Axes range meaning</td>
* <td>{@code null}</td>
* <td>{@code null}</td>
* </table>
*
* @param cs the coordinate system to verify.
*/
public static void assertIsProjected2D(final CartesianCS cs) {
assertEquals("dimension", 2, cs.getDimension());
final CoordinateSystemAxis E = cs.getAxis(0);
final CoordinateSystemAxis N = cs.getAxis(1);
assertNotNull("axis", E);
assertNotNull("axis", N);
assertEquals("axis[0].name", AxisNames.EASTING, E.getName().getCode());
assertEquals("axis[1].name", AxisNames.NORTHING, N.getName().getCode());
assertEquals("axis[0].abbreviation", "E", E.getAbbreviation());
assertEquals("axis[1].abbreviation", "N", N.getAbbreviation());
assertEquals("axis[0].direction", AxisDirection.EAST, E.getDirection());
assertEquals("axis[1].direction", AxisDirection.NORTH, N.getDirection());
assertEquals("axis[0].unit", Units.METRE, E.getUnit());
assertEquals("axis[1].unit", Units.METRE, N.getUnit());
verifyRange(E, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, null, true);
verifyRange(N, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, null, true);
}
use of org.opengis.referencing.cs.CoordinateSystemAxis in project sis by apache.
the class StandardDefinitionsTest method testCreateAxis.
/**
* Compares the values created by {@link StandardDefinitions#createAxis(short)} against the {@link HardCodedAxes}
* constants. Actually this is more a {@code HardCodedAxes} test than a {@code StandardDefinitions} one - in case
* of test failure, both classes could be at fault.
*/
@Test
public void testCreateAxis() {
for (final short code : new short[] { 1, 2, 60, 61, 62, 106, 107, 110, 114, 113 }) {
final CoordinateSystemAxis actual = StandardDefinitions.createAxis(code);
Validators.validate(actual);
switch(code) {
case 1:
compare(HardCodedAxes.EASTING, actual);
break;
case 2:
compare(HardCodedAxes.NORTHING, actual);
break;
case 60:
compare(HardCodedAxes.SPHERICAL_LATITUDE, actual);
break;
case 61:
compare(HardCodedAxes.SPHERICAL_LONGITUDE, actual);
break;
case 62:
compare(HardCodedAxes.GEOCENTRIC_RADIUS, actual);
break;
case 106:
compare(HardCodedAxes.GEODETIC_LATITUDE, actual);
break;
case 107:
compare(HardCodedAxes.GEODETIC_LONGITUDE, actual);
break;
case 110:
compare(HardCodedAxes.ELLIPSOIDAL_HEIGHT, actual);
break;
case 114:
compare(HardCodedAxes.GRAVITY_RELATED_HEIGHT, actual);
break;
case 113:
compare(HardCodedAxes.DEPTH, actual);
break;
default:
throw new AssertionError(code);
}
}
}
Aggregations