use of org.opengis.referencing.cs.AxisDirection in project sis by apache.
the class Matrices method createTransform.
/**
* Implementation of {@code createTransform(…)} public methods expecting envelopes and/or axis directions.
* Argument validity shall be verified by the caller.
*
* @param useEnvelopes {@code true} if source and destination envelopes shall be taken in account.
* If {@code false}, then source and destination envelopes will be ignored and can be null.
*/
@SuppressWarnings("null")
private static MatrixSIS createTransform(final Envelope srcEnvelope, final AxisDirection[] srcAxes, final Envelope dstEnvelope, final AxisDirection[] dstAxes, final boolean useEnvelopes) {
final DirectPosition dstCorner, srcCorner, srcOppositeCorner;
if (useEnvelopes) {
dstCorner = dstEnvelope.getLowerCorner();
srcCorner = srcEnvelope.getLowerCorner();
srcOppositeCorner = srcEnvelope.getUpperCorner();
} else {
dstCorner = srcCorner = srcOppositeCorner = null;
}
/*
* Unconditionally create extended precision matrix even if standard precision would be
* enough because callers in other package may perform additional arithmetic operations
* on it (for example org.apache.sis.referencing.cs.CoordinateSystems.swapAndScaleAxes).
*/
final MatrixSIS matrix = new GeneralMatrix(dstAxes.length + 1, srcAxes.length + 1, false, 2);
/*
* Maps source axes to destination axes. If no axis is moved (for example if the user
* want to transform (NORTH,EAST) to (SOUTH,EAST)), then source and destination index
* will be equal. If some axes are moved (for example if the user want to transform
* (NORTH,EAST) to (EAST,NORTH)), then ordinates at index {@code srcIndex} will have
* to be moved at index {@code dstIndex}.
*/
for (int dstIndex = 0; dstIndex < dstAxes.length; dstIndex++) {
boolean hasFound = false;
final AxisDirection dstDir = dstAxes[dstIndex];
final AxisDirection search = AxisDirections.absolute(dstDir);
for (int srcIndex = 0; srcIndex < srcAxes.length; srcIndex++) {
final AxisDirection srcDir = srcAxes[srcIndex];
if (search.equals(AxisDirections.absolute(srcDir))) {
if (hasFound) {
throw new IllegalArgumentException(Resources.format(Resources.Keys.ColinearAxisDirections_2, srcDir, dstDir));
}
hasFound = true;
/*
* Set the matrix elements. Some matrix elements will never be set.
* They will be left to zero, which is their desired value.
*/
final boolean same = srcDir.equals(dstDir);
if (useEnvelopes) {
/*
* See the comment in transform(Envelope, Envelope) for an explanation about why
* we use the lower/upper corners instead than getMinimum()/getMaximum() methods.
*/
final DoubleDouble scale = new DoubleDouble(same ? +1 : -1, 0);
scale.multiply(dstEnvelope.getSpan(dstIndex));
scale.divide(srcEnvelope.getSpan(srcIndex));
final DoubleDouble translate = new DoubleDouble(scale);
translate.multiply((same ? srcCorner : srcOppositeCorner).getOrdinate(srcIndex));
translate.negate();
translate.add(dstCorner.getOrdinate(dstIndex));
matrix.setNumber(dstIndex, srcIndex, scale);
matrix.setNumber(dstIndex, srcAxes.length, translate);
} else {
matrix.setElement(dstIndex, srcIndex, same ? +1 : -1);
}
}
}
if (!hasFound) {
throw new IllegalArgumentException(Resources.format(Resources.Keys.CanNotMapAxisToDirection_1, dstAxes[dstIndex]));
}
}
matrix.setElement(dstAxes.length, srcAxes.length, 1);
return matrix;
}
use of org.opengis.referencing.cs.AxisDirection in project hale by halestudio.
the class WindingOrder method isCRSFlip.
/**
* To determine axis of given CRS is flip or not
*
* @param crs the CRS
* @return true, if CRS is flip, else false
*/
public static boolean isCRSFlip(CoordinateReferenceSystem crs) {
// get number of dimensions and it should be two
if (crs.getCoordinateSystem().getDimension() == 2) {
AxisDirection axis1 = crs.getCoordinateSystem().getAxis(0).getDirection();
AxisDirection axis2 = crs.getCoordinateSystem().getAxis(1).getDirection();
// check if direction is flip?
if (axis1.equals(AxisDirection.EAST) || axis1.equals(AxisDirection.WEST)) {
if (axis1.equals(AxisDirection.EAST) && (axis2.equals(AxisDirection.SOUTH) || axis2.equals(AxisDirection.DOWN))) {
return true;
} else if (axis1.equals(AxisDirection.WEST) && (axis2.equals(AxisDirection.NORTH) || axis2.equals(AxisDirection.UP))) {
return true;
}
} else {
// Check if order of axis flip?
if ((axis1.equals(AxisDirection.SOUTH) || axis1.equals(AxisDirection.DOWN)) && axis2.equals(AxisDirection.WEST)) {
return true;
} else if ((axis1.equals(AxisDirection.NORTH) || axis1.equals(AxisDirection.UP)) && axis2.equals(AxisDirection.EAST)) {
return true;
}
}
}
// if not any case return false above.
return false;
}
use of org.opengis.referencing.cs.AxisDirection in project sis by apache.
the class CoordinateFormat method initialize.
/**
* Computes the value of transient fields from the given CRS.
*/
private void initialize(final CoordinateReferenceSystem crs) {
types = null;
formats = null;
units = null;
toFormatUnit = null;
unitSymbols = null;
epochs = null;
negate = 0;
lastCRS = crs;
if (crs == null) {
return;
}
/*
* If no CRS were specified, we will format everything as numbers. Working with null CRS
* is sometime useful because null CRS are allowed in DirectPosition according ISO 19107.
* Otherwise (if a CRS is given), infer the format subclasses from the axes.
*/
final CoordinateSystem cs = crs.getCoordinateSystem();
final int dimension = cs.getDimension();
final byte[] types = new byte[dimension];
final Format[] formats = new Format[dimension];
for (int i = 0; i < dimension; i++) {
final CoordinateSystemAxis axis = cs.getAxis(i);
final Unit<?> unit = axis.getUnit();
/*
* Formatter for angular units. Target unit is DEGREE_ANGLE.
* Type is LONGITUDE, LATITUDE or ANGLE depending on axis direction.
*/
if (Units.isAngular(unit)) {
byte type = ANGLE;
final AxisDirection dir = axis.getDirection();
if (AxisDirection.NORTH.equals(dir)) {
type = LATITUDE;
} else if (AxisDirection.EAST.equals(dir)) {
type = LONGITUDE;
} else if (AxisDirection.SOUTH.equals(dir)) {
type = LATITUDE;
negate(i);
} else if (AxisDirection.WEST.equals(dir)) {
type = LONGITUDE;
negate(i);
}
types[i] = type;
formats[i] = getFormat(Angle.class);
setConverter(dimension, i, unit.asType(javax.measure.quantity.Angle.class).getConverterTo(Units.DEGREE));
continue;
}
/*
* Formatter for temporal units. Target unit is MILLISECONDS.
* Type is DATE.
*/
if (Units.isTemporal(unit)) {
final CoordinateReferenceSystem t = CRS.getComponentAt(crs, i, i + 1);
if (t instanceof TemporalCRS) {
if (epochs == null) {
epochs = new long[dimension];
}
types[i] = DATE;
formats[i] = getFormat(Date.class);
epochs[i] = ((TemporalCRS) t).getDatum().getOrigin().getTime();
setConverter(dimension, i, unit.asType(Time.class).getConverterTo(Units.MILLISECOND));
if (AxisDirection.PAST.equals(axis.getDirection())) {
negate(i);
}
continue;
}
types[i] = TIME;
// Fallthrough: formatted as number.
}
/*
* Formatter for all other units. Do NOT set types[i] since it may have been set
* to a non-zero value by previous case. If not, the default value (zero) is the
* one we want.
*/
formats[i] = getFormat(Number.class);
if (unit != null) {
if (units == null) {
units = new Unit<?>[dimension];
}
units[i] = unit;
final String symbol = getFormat(Unit.class).format(unit);
if (!symbol.isEmpty()) {
if (unitSymbols == null) {
unitSymbols = new String[dimension];
}
unitSymbols[i] = symbol;
}
}
}
// Assign only on success.
this.types = types;
this.formats = formats;
}
use of org.opengis.referencing.cs.AxisDirection in project sis by apache.
the class StandardDefinitions method createAxis.
/**
* Creates an axis from hard-coded values for the given code.
*
* @param code the EPSG code.
* @return the coordinate system axis for the given code.
*/
static CoordinateSystemAxis createAxis(final short code) {
final String name, abrv;
Unit<?> unit = Units.METRE;
double min = Double.NEGATIVE_INFINITY;
double max = Double.POSITIVE_INFINITY;
RangeMeaning rm = null;
final AxisDirection dir;
switch(code) {
case 1:
name = "Easting";
abrv = "E";
dir = AxisDirection.EAST;
break;
case 2:
name = "Northing";
abrv = "N";
dir = AxisDirection.NORTH;
break;
case 60:
name = "Spherical latitude";
// See HardCodedAxes.SPHERICAL_LATITUDE in tests.
abrv = "φ′";
unit = Units.DEGREE;
dir = AxisDirection.NORTH;
min = Latitude.MIN_VALUE;
max = Latitude.MAX_VALUE;
rm = RangeMeaning.EXACT;
break;
case 61:
name = "Spherical longitude";
// See HardCodedAxes.SPHERICAL_LONGITUDE in tests.
abrv = "θ";
unit = Units.DEGREE;
dir = AxisDirection.EAST;
min = Longitude.MIN_VALUE;
max = Longitude.MAX_VALUE;
rm = RangeMeaning.WRAPAROUND;
break;
case 62:
name = "Geocentric radius";
// See HardCodedAxes.GEOCENTRIC_RADIUS in tests.
abrv = "R";
dir = AxisDirection.UP;
rm = RangeMeaning.EXACT;
min = 0;
break;
// Used in Ellipsoidal 3D.
case 108:
case 106:
name = AxisNames.GEODETIC_LATITUDE;
abrv = "φ";
unit = Units.DEGREE;
dir = AxisDirection.NORTH;
min = Latitude.MIN_VALUE;
max = Latitude.MAX_VALUE;
rm = RangeMeaning.EXACT;
break;
// Used in Ellipsoidal 3D.
case 109:
case 107:
name = AxisNames.GEODETIC_LONGITUDE;
abrv = "λ";
unit = Units.DEGREE;
dir = AxisDirection.EAST;
min = Longitude.MIN_VALUE;
max = Longitude.MAX_VALUE;
rm = RangeMeaning.WRAPAROUND;
break;
case 110:
name = AxisNames.ELLIPSOIDAL_HEIGHT;
abrv = "h";
dir = AxisDirection.UP;
break;
case 114:
name = AxisNames.GRAVITY_RELATED_HEIGHT;
abrv = "H";
dir = AxisDirection.UP;
break;
case 113:
name = AxisNames.DEPTH;
abrv = "D";
dir = AxisDirection.DOWN;
break;
case 115:
name = AxisNames.GEOCENTRIC_X;
abrv = "X";
dir = AxisDirection.GEOCENTRIC_X;
break;
case 116:
name = AxisNames.GEOCENTRIC_Y;
abrv = "Y";
dir = AxisDirection.GEOCENTRIC_Y;
break;
case 117:
name = AxisNames.GEOCENTRIC_Z;
abrv = "Z";
dir = AxisDirection.GEOCENTRIC_Z;
break;
// Actually no axis allocated by EPSG here, but createCoordinateSystem(1027) needs this number.
case 1057:
case 1056:
name = "Easting";
abrv = "E";
dir = CoordinateSystems.directionAlongMeridian(AxisDirection.NORTH, 90);
break;
case 1058:
name = "Northing";
abrv = "N";
dir = CoordinateSystems.directionAlongMeridian(AxisDirection.NORTH, 0);
break;
case 1065:
name = "Easting";
abrv = "E";
dir = CoordinateSystems.directionAlongMeridian(AxisDirection.SOUTH, 90);
break;
case 1066:
name = "Northing";
abrv = "N";
dir = CoordinateSystems.directionAlongMeridian(AxisDirection.SOUTH, 180);
break;
default:
throw new AssertionError(code);
}
final Map<String, Object> properties = properties(code, name, null, false);
properties.put(DefaultCoordinateSystemAxis.MINIMUM_VALUE_KEY, min);
properties.put(DefaultCoordinateSystemAxis.MAXIMUM_VALUE_KEY, max);
properties.put(DefaultCoordinateSystemAxis.RANGE_MEANING_KEY, rm);
return new DefaultCoordinateSystemAxis(properties, abrv, dir, unit);
}
use of org.opengis.referencing.cs.AxisDirection in project sis by apache.
the class CoordinateSystems method parseAxisDirection.
/**
* Returns an axis direction code from the given direction name.
* Names are case-insensitive. They may be:
*
* <ul>
* <li>Cardinal directions like <cite>"north"</cite> and <cite>"east"</cite>.</li>
* <li>Inter-cardinal directions <cite>"north-east"</cite> and <cite>"south-south-east"</cite>,
* using either {@code '-'}, {@code '_'} or spaces as separator between the cardinal points.</li>
* <li>Directions from a pole like <cite>"South along 180 deg"</cite> and <cite>"South along 90° East"</cite>,
* using either the {@code "deg"} or {@code "°"} symbol. Note that the meridian is not necessarily relative
* to Greenwich (see {@link #directionAlongMeridian directionAlongMeridian(…)} for more information).</li>
* </ul>
*
* @param name the direction name (e.g. "north", "north-east", <i>etc.</i>).
* @return the axis direction for the given name.
* @throws IllegalArgumentException if the given name is not a known axis direction.
*/
public static AxisDirection parseAxisDirection(String name) throws IllegalArgumentException {
ensureNonNull("name", name);
name = CharSequences.trimWhitespaces(name);
AxisDirection candidate = AxisDirections.valueOf(name);
if (candidate != null) {
return candidate;
}
/*
* Some EPSG direction names are of the form "South along 180 deg". We check that the
* direction before "along" is valid and create a new axis direction if it is. We can
* not just replace "South along 180 deg" by "South" because the same CRS may use two
* of those directions. For example EPSG:32661 has the following axis direction:
*
* South along 180 deg
* South along 90 deg East
*/
final DirectionAlongMeridian meridian = DirectionAlongMeridian.parse(name);
if (meridian != null) {
candidate = meridian.getDirection();
assert candidate == AxisDirections.valueOf(meridian.toString());
return candidate;
}
throw new IllegalArgumentException(Resources.format(Resources.Keys.UnknownAxisDirection_1, name));
}
Aggregations