use of org.opengis.referencing.cs.CoordinateSystem in project sis by apache.
the class Angle method valueOf.
/**
* Returns the angular value of the axis having the given direction.
* This helper method is used for subclass constructors expecting a {@link DirectPosition} argument.
*
* @param position the position from which to get an angular value.
* @param positive axis direction of positive values.
* @param negative axis direction of negative values.
* @return angular value in degrees.
* @throws IllegalArgumentException if the given coordinate it not associated to a CRS,
* or if no axis oriented toward the given directions is found, or if that axis
* does not use {@linkplain Units#isAngular angular units}.
*/
static double valueOf(final DirectPosition position, final AxisDirection positive, final AxisDirection negative) {
final CoordinateReferenceSystem crs = position.getCoordinateReferenceSystem();
if (crs == null) {
throw new IllegalArgumentException(Errors.format(Errors.Keys.UnspecifiedCRS));
}
final CoordinateSystem cs = crs.getCoordinateSystem();
final int dimension = cs.getDimension();
IncommensurableException cause = null;
for (int i = 0; i < dimension; i++) {
final CoordinateSystemAxis axis = cs.getAxis(i);
final AxisDirection dir = axis.getDirection();
final boolean isPositive = dir.equals(positive);
if (isPositive || dir.equals(negative)) {
double value = position.getOrdinate(i);
if (!isPositive)
value = -value;
final Unit<?> unit = axis.getUnit();
if (unit != Units.DEGREE)
try {
value = unit.getConverterToAny(Units.DEGREE).convert(value);
} catch (IncommensurableException e) {
cause = e;
break;
}
return value;
}
}
throw new IllegalArgumentException(Errors.format(Errors.Keys.IllegalCRSType_1, Classes.getLeafInterfaces(crs.getClass(), CoordinateReferenceSystem.class)[0]), cause);
}
use of org.opengis.referencing.cs.CoordinateSystem in project sis by apache.
the class WKTUtilities method suggestFractionDigits.
/**
* Suggests an amount of fraction digits to use for formatting numbers in each column of the given sequence
* of points. The number of fraction digits may be negative if we could round the numbers to 10, <i>etc</i>.
*
* @param crs the coordinate reference system for each points, or {@code null} if unknown.
* @param points the sequence of points. It is not required that each point has the same dimension.
* @return suggested amount of fraction digits as an array as long as the longest row.
*/
public static int[] suggestFractionDigits(final CoordinateReferenceSystem crs, final double[]... points) {
final int[] fractionDigits = Numerics.suggestFractionDigits(points);
final Ellipsoid ellipsoid = ReferencingUtilities.getEllipsoid(crs);
if (ellipsoid != null) {
/*
* Use heuristic precisions for geodetic or projected CRS. We do not apply those heuristics
* for other kind of CRS (e.g. engineering) because we do not know what could be the size
* of the object attached to the CRS.
*/
final CoordinateSystem cs = crs.getCoordinateSystem();
final int dimension = Math.min(cs.getDimension(), fractionDigits.length);
final double scale = Formulas.scaleComparedToEarth(ellipsoid);
for (int i = 0; i < dimension; i++) {
final Unit<?> unit = cs.getAxis(i).getUnit();
double precision;
if (Units.isLinear(unit)) {
// In metres
precision = Formulas.LINEAR_TOLERANCE * scale;
} else if (Units.isAngular(unit)) {
// In radians
precision = Formulas.ANGULAR_TOLERANCE * (Math.PI / 180) * scale;
} else if (Units.isTemporal(unit)) {
// In seconds
precision = Formulas.TEMPORAL_TOLERANCE;
} else {
continue;
}
// In units used by the coordinates.
precision /= Units.toStandardUnit(unit);
final int f = DecimalFunctions.fractionDigitsForDelta(precision, false);
if (f > fractionDigits[i]) {
// Use at least the heuristic precision.
fractionDigits[i] = f;
}
}
}
return fractionDigits;
}
use of org.opengis.referencing.cs.CoordinateSystem in project sis by apache.
the class MathTransformContext method getMatrix.
/**
* Returns the normalization or denormalization matrix.
*/
@Override
@SuppressWarnings("fallthrough")
public Matrix getMatrix(final MatrixRole role) throws FactoryException {
final CoordinateSystem cs;
boolean inverse = false;
double rotation;
switch(role) {
default:
throw new IllegalArgumentException(Errors.format(Errors.Keys.IllegalArgumentValue_2, "role", role));
// Fall through
case INVERSE_NORMALIZATION:
inverse = true;
case NORMALIZATION:
rotation = sourceMeridian;
cs = getSourceCS();
break;
// Fall through
case INVERSE_DENORMALIZATION:
inverse = true;
case DENORMALIZATION:
inverse = !inverse;
rotation = targetMeridian;
cs = getTargetCS();
break;
}
Matrix matrix = super.getMatrix(role);
if (rotation != 0) {
if (inverse)
rotation = -rotation;
MatrixSIS cm = MatrixSIS.castOrCopy(matrix);
if (cs instanceof CartesianCS) {
rotation = Math.toRadians(rotation);
final Matrix4 rot = new Matrix4();
rot.m00 = rot.m11 = Math.cos(rotation);
rot.m01 = -(rot.m10 = Math.sin(rotation));
if (inverse) {
// Apply the rotation after denormalization.
matrix = Matrices.multiply(rot, cm);
} else {
// Apply the rotation before normalization.
matrix = cm.multiply(rot);
}
} else if (cs == null || cs instanceof EllipsoidalCS || cs instanceof SphericalCS) {
final Double value = rotation;
if (inverse) {
// Longitude is the first axis in normalized CS.
cm.convertBefore(0, null, value);
} else {
cm.convertAfter(0, null, value);
}
matrix = cm;
} else {
throw new FactoryException(Errors.format(Errors.Keys.UnsupportedCoordinateSystem_1, cs.getName()));
}
}
return matrix;
}
use of org.opengis.referencing.cs.CoordinateSystem in project sis by apache.
the class AbstractDirectPosition method normalize.
/**
* Ensures that the position is contained in the coordinate system domain.
* For each dimension, this method compares the ordinate values against the
* limits of the coordinate system axis for that dimension.
* If some ordinates are out of range, then there is a choice depending on the
* {@linkplain CoordinateSystemAxis#getRangeMeaning() axis range meaning}:
*
* <ul>
* <li>If {@link RangeMeaning#EXACT} (typically <em>latitudes</em> ordinates), then values
* greater than the {@linkplain CoordinateSystemAxis#getMaximumValue() axis maximal value}
* are replaced by the axis maximum, and values smaller than the
* {@linkplain CoordinateSystemAxis#getMinimumValue() axis minimal value}
* are replaced by the axis minimum.</li>
*
* <li>If {@link RangeMeaning#WRAPAROUND} (typically <em>longitudes</em> ordinates), then
* a multiple of the axis range (e.g. 360° for longitudes) is added or subtracted.</li>
* </ul>
*
* @return {@code true} if this position has been modified as a result of this method call,
* or {@code false} if no change has been done.
*
* @see GeneralEnvelope#normalize()
*/
public boolean normalize() {
boolean changed = false;
final CoordinateReferenceSystem crs = getCoordinateReferenceSystem();
if (crs != null) {
final int dimension = getDimension();
final CoordinateSystem cs = crs.getCoordinateSystem();
for (int i = 0; i < dimension; i++) {
double ordinate = getOrdinate(i);
final CoordinateSystemAxis axis = cs.getAxis(i);
final double minimum = axis.getMinimumValue();
final double maximum = axis.getMaximumValue();
final RangeMeaning rm = axis.getRangeMeaning();
if (RangeMeaning.EXACT.equals(rm)) {
if (ordinate < minimum)
ordinate = minimum;
else if (ordinate > maximum)
ordinate = maximum;
else
continue;
} else if (RangeMeaning.WRAPAROUND.equals(rm)) {
final double csSpan = maximum - minimum;
final double shift = Math.floor((ordinate - minimum) / csSpan) * csSpan;
if (shift == 0) {
continue;
}
ordinate -= shift;
}
setOrdinate(i, ordinate);
changed = true;
}
}
return changed;
}
use of org.opengis.referencing.cs.CoordinateSystem 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;
}
Aggregations