* the 'projectedScale' transform. The matrix dimensions are selected accordingly using
* a robust code when possible, but the result should be a 3x3 matrix most of the time.
*/
final int sourceDim = (transform != null) ? transform.getTargetDimensions() : 2;
final int targetDim = (projectedScale != null) ? projectedScale.getNumCol()-1 : sourceDim;
final XMatrix matrix = MatrixFactory.create(targetDim + 1, sourceDim + 1);
/*
* Search for "scale factor", "false easting" and "false northing" parameters.
* All parameters found are removed from the list. Note: we assume that linear
* units in the "normalized projection" are metres, as specified in the legacy
* OGC 01-009 specification, and that unit conversions (if needed) are applied
* by 'projectedScale'. However there is no way I can see to ensure that since
* it is really a matter of how the map projection is implemented (for example
* the unit conversion factor could be merged with the "scale_factor" -- not a
* clean approach and I do not recommand, but some could do in order to save a
* few multiplications).
*
* We need "false easting" and "false northing" offsets in either user's unit or
* in metres, depending if the unit conversions are applied in 'transform' or in
* 'projectedScale' respectively. We assume the later, which stands for Geotools
* implementation and is closer to OGC 01-009 spirit. But we will log a warning
* in case of doubt.
*/
Unit<?> unit = null;
String warning = null;
for (final Iterator<GeneralParameterValue> it=parameters.iterator(); it.hasNext();) {
final GeneralParameterValue parameter = it.next();
if (parameter instanceof ParameterValue) {
final ParameterValue<?> value = (ParameterValue) parameter;
final ParameterDescriptor<?> descriptor = value.getDescriptor();
if (Number.class.isAssignableFrom(descriptor.getValueClass())) {
if (nameMatches(descriptor, "scale_factor")) {
final double scale = value.doubleValue();
for (int i=Math.min(sourceDim, targetDim); --i>=0;) {
matrix.setElement(i,i, matrix.getElement(i,i) * scale);
}
} else {
final int d;
if (nameMatches(descriptor, "false_easting")) {
d = 0;
} else if (nameMatches(descriptor, "false_northing")) {
d = 1;
} else {
continue;
}
final double offset = value.doubleValue(SI.METER);
if (!Double.isNaN(offset) && offset != value.doubleValue()) {
// See the above comment about units. The above check could have been
// replaced by "if (!SI.METER.equals(unit))", but the above avoid the
// warning in the very common case where 'offset == 0'.
unit = value.getUnit();
warning = descriptor.getName().getCode();
}
matrix.setElement(d, sourceDim, matrix.getElement(d, sourceDim) + offset);
}
it.remove();
}
}
}