use of org.apache.sis.parameter.Parameters in project sis by apache.
the class ZonedGridSystemTest method createProjection.
/**
* Creates a new instance of {@link ZonedGridSystem}.
*
* @param ellipse {@code false} for a sphere, or {@code true} for WGS84 ellipsoid.
*/
private void createProjection(final boolean ellipse) throws FactoryException {
final ZonedTransverseMercator method = new ZonedTransverseMercator();
final Parameters values = parameters(method, ellipse);
values.parameter(Constants.SCALE_FACTOR).setValue(0.9996, Units.UNITY);
values.parameter(Constants.FALSE_EASTING).setValue(500000, Units.METRE);
values.parameter("Initial longitude").setValue(-180, Units.DEGREE);
values.parameter("Zone width").setValue(6, Units.DEGREE);
transform = new MathTransformFactoryMock(method).createParameterizedTransform(values);
tolerance = Formulas.LINEAR_TOLERANCE;
validate();
}
use of org.apache.sis.parameter.Parameters in project sis by apache.
the class FolderStoreProvider method open.
/**
* Returns a data store implementation associated with this provider for the given parameters.
*
* @return a folder data store implementation for the given parameters.
* @throws DataStoreException if an error occurred while creating the data store instance.
*/
@Override
public DataStore open(final ParameterValueGroup parameters) throws DataStoreException {
ArgumentChecks.ensureNonNull("parameter", parameters);
final StorageConnector connector = URIDataStore.Provider.connector(this, parameters);
final Parameters pg = Parameters.castOrWrap(parameters);
connector.setOption(OptionKey.LOCALE, pg.getValue(LOCALE));
connector.setOption(OptionKey.TIMEZONE, pg.getValue(TIMEZONE));
connector.setOption(OptionKey.ENCODING, pg.getValue(ENCODING));
final EnumSet<StandardOpenOption> options = EnumSet.of(StandardOpenOption.WRITE);
if (Boolean.TRUE.equals(pg.getValue(URIDataStore.Provider.CREATE_PARAM))) {
options.add(StandardOpenOption.CREATE);
}
return open(connector, pg.getValue(FORMAT), options);
}
use of org.apache.sis.parameter.Parameters in project sis by apache.
the class Equirectangular method createMathTransform.
/**
* Creates an Equirectangular projection from the specified group of parameter values. This method is an
* adaptation of {@link org.apache.sis.referencing.operation.projection.NormalizedProjection} constructor,
* reproduced in this method because we will create an affine transform instead than the usual projection
* classes.
*
* @param factory the factory to use if this constructor needs to create other math transforms.
* @param parameters the parameter values that define the transform to create.
* @return the map projection created from the given parameter values.
* @throws FactoryException if an error occurred while creating the math transform.
*/
@Override
public MathTransform createMathTransform(final MathTransformFactory factory, final ParameterValueGroup parameters) throws FactoryException {
final Parameters p = Parameters.castOrWrap(parameters);
final ContextualParameters context = new ContextualParameters(this);
double a = getAndStore(p, context, MapProjection.SEMI_MAJOR);
double b = getAndStore(p, context, MapProjection.SEMI_MINOR);
double λ0 = getAndStore(p, context, LONGITUDE_OF_ORIGIN);
double φ0 = getAndStore(p, context, LATITUDE_OF_ORIGIN);
double φ1 = getAndStore(p, context, STANDARD_PARALLEL);
double fe = getAndStore(p, context, FALSE_EASTING);
double fn = getAndStore(p, context, FALSE_NORTHING);
/*
* Perform following transformation, in that order. Note that following
* AffineTransform convention, the Java code appears in reverse order:
*
* 1) Subtract φ0 to the latitude.
* 2) Subtract λ0 to the longitude.
* 3) Convert degrees to radians.
* 4) Scale longitude by cos(φ1).
*/
φ1 = toRadians(φ1);
final MatrixSIS normalize = context.getMatrix(ContextualParameters.MatrixRole.NORMALIZATION);
normalize.convertBefore(0, cos(φ1), null);
context.normalizeGeographicInputs(λ0).convertBefore(1, null, -φ0);
/*
* At this point, we usually invoke 'denormalize.convertAfter(…, a, …)' where 'a' (the semi-major axis length)
* is taken as the Earth radius (R). However quoting EPSG: "If the figure of the earth used is an ellipsoid
* rather than a sphere then R should be calculated as the radius of the conformal sphere at the projection
* origin at latitude φ1 using the formula for RC given in section 1.2, table 3".
*/
if (a != b) {
final double rs = b / a;
final double sinφ1 = sin(φ1);
a = b / (1 - (1 - rs * rs) * (sinφ1 * sinφ1));
}
final DoubleDouble k = new DoubleDouble(a);
final MatrixSIS denormalize = context.getMatrix(ContextualParameters.MatrixRole.DENORMALIZATION);
denormalize.convertAfter(0, k, new DoubleDouble(fe));
denormalize.convertAfter(1, k, new DoubleDouble(fn));
/*
* Creates the ConcatenatedTransform, letting the factory returns the cached instance
* if the caller already invoked this method previously (which usually do not happen).
*/
MathTransform mt = context.completeTransform(factory, MathTransforms.identity(2));
if (mt instanceof AffineTransform) {
// Always true in Apache SIS implementation.
mt = new ParameterizedAffine((AffineTransform) mt, context, true);
}
return mt;
}
use of org.apache.sis.parameter.Parameters in project sis by apache.
the class FranceGeocentricInterpolation method createMathTransform.
/**
* Creates a transform from the specified group of parameter values.
* This method creates the transform from <em>target</em> to <em>source</em>
* (which is the direction that use the interpolation grid directly without iteration),
* then inverts the transform.
*
* @param factory the factory to use if this constructor needs to create other math transforms.
* @param values the group of parameter values.
* @return the created math transform.
* @throws ParameterNotFoundException if a required parameter was not found.
* @throws FactoryException if an error occurred while loading the grid.
*/
@Override
public MathTransform createMathTransform(final MathTransformFactory factory, final ParameterValueGroup values) throws ParameterNotFoundException, FactoryException {
boolean withHeights = false;
final Parameters pg = Parameters.castOrWrap(values);
final Integer dim = pg.getValue(Molodensky.DIMENSION);
if (dim != null)
switch(dim) {
case 2:
break;
case 3:
withHeights = true;
break;
default:
throw new InvalidParameterValueException(Errors.format(Errors.Keys.IllegalArgumentValue_2, "dim", dim), "dim", dim);
}
final Path file = pg.getMandatoryValue(FILE);
final DatumShiftGridFile<Angle, Length> grid = getOrLoad(file, isRecognized(file) ? new double[] { TX, TY, TZ } : null, PRECISION);
MathTransform tr = createGeodeticTransformation(factory, createEllipsoid(pg, Molodensky.TGT_SEMI_MAJOR, Molodensky.TGT_SEMI_MINOR, // GRS 1980 ellipsoid
CommonCRS.ETRS89.ellipsoid()), createEllipsoid(pg, Molodensky.SRC_SEMI_MAJOR, Molodensky.SRC_SEMI_MINOR, // Clarke 1880 (IGN) ellipsoid
null), withHeights, grid);
try {
tr = tr.inverse();
} catch (NoninvertibleTransformException e) {
// Should never happen.
throw new FactoryException(e);
}
return tr;
}
use of org.apache.sis.parameter.Parameters in project sis by apache.
the class GeocentricAffine method createParameters.
/**
* Returns the parameters for creating a datum shift operation.
* The operation method will be one of the {@code GeocentricAffine} subclasses,
* unless the specified {@code method} argument is {@link DatumShiftMethod#NONE}.
* If no single operation method can be used, then this method returns {@code null}.
*
* <p>This method does <strong>not</strong> change the coordinate system type.
* The source and target coordinate systems can be both {@code EllipsoidalCS} or both {@code CartesianCS}.
* Any other type or mix of types (e.g. a {@code EllipsoidalCS} source and {@code CartesianCS} target)
* will cause this method to return {@code null}. In such case, it is caller's responsibility to apply
* the datum shift itself in Cartesian geocentric coordinates.</p>
*
* @param sourceCS the source coordinate system. Only the type and number of dimensions is checked.
* @param targetCS the target coordinate system. Only the type and number of dimensions is checked.
* @param datumShift the datum shift as a matrix, or {@code null} if there is no datum shift information.
* @param method the preferred datum shift method. Note that {@code createParameters(…)} may overwrite.
* @return the parameter values, or {@code null} if no single operation method can be found.
*/
public static ParameterValueGroup createParameters(final CoordinateSystem sourceCS, final CoordinateSystem targetCS, final Matrix datumShift, DatumShiftMethod method) {
final boolean isEllipsoidal = (sourceCS instanceof EllipsoidalCS);
if (!(isEllipsoidal ? (targetCS instanceof EllipsoidalCS) : (targetCS instanceof CartesianCS && sourceCS instanceof CartesianCS))) {
// Coordinate systems are not two EllipsoidalCS or two CartesianCS.
return null;
}
@SuppressWarnings("null") int dimension = sourceCS.getDimension();
if (dimension != targetCS.getDimension()) {
// Any value greater than 3 means "mismatched dimensions" for this method.
dimension = 4;
}
if (method == DatumShiftMethod.NONE) {
if (dimension <= 3) {
return Affine.identity(dimension);
} else if (isEllipsoidal) {
final ParameterDescriptorGroup descriptor;
switch(sourceCS.getDimension()) {
case 2:
descriptor = Geographic2Dto3D.PARAMETERS;
break;
case 3:
descriptor = Geographic3Dto2D.PARAMETERS;
break;
default:
return null;
}
return descriptor.createValue();
} else {
return null;
}
}
/*
* Try to convert the matrix into (tX, tY, tZ, rX, rY, rZ, dS) parameters.
* The matrix may not be convertible, in which case we will let the caller
* uses the matrix directly in Cartesian geocentric coordinates.
*/
final BursaWolfParameters parameters = new BursaWolfParameters(null, null);
if (datumShift != null)
try {
parameters.setPositionVectorTransformation(datumShift, BURSAWOLF_TOLERANCE);
} catch (IllegalArgumentException e) {
log(Loggers.COORDINATE_OPERATION, "createParameters", e);
return null;
}
else {
/*
* If there is no datum shift parameters (not to be confused with identity), then those parameters
* are assumed unknown. Using the most accurate methods would give a false impression of accuracy,
* so we use the fastest method instead. Since all parameter values are zero, Apache SIS should use
* the AbridgedMolodenskyTransform2D optimization.
*/
method = DatumShiftMethod.ABRIDGED_MOLODENSKY;
}
final boolean isTranslation = parameters.isTranslation();
final ParameterDescriptorGroup descriptor;
/*
* Following "if" blocks are ordered from most accurate to less accurate datum shift method
* supported by GeocentricAffine subclasses (except NONE which has already been handled).
* Special cases:
*
* - If the datum shift is applied between geocentric CRS, then the Molodensky approximations do not apply
* as they are designed for transformations between geographic CRS only. User preference is then ignored.
*
* - Molodensky methods are approximations for datum shifts having only translation terms in their Bursa-Wolf
* parameters. If there is also a scale or rotation terms, then we can not use Molodensky methods. The user
* preference is then ignored.
*/
if (!isEllipsoidal) {
method = DatumShiftMethod.GEOCENTRIC_DOMAIN;
descriptor = isTranslation ? GeocentricTranslation.PARAMETERS : PositionVector7Param.PARAMETERS;
} else if (!isTranslation) {
method = DatumShiftMethod.GEOCENTRIC_DOMAIN;
descriptor = (dimension >= 3) ? PositionVector7Param3D.PARAMETERS : PositionVector7Param2D.PARAMETERS;
} else
switch(method) {
case GEOCENTRIC_DOMAIN:
{
descriptor = (dimension >= 3) ? GeocentricTranslation3D.PARAMETERS : GeocentricTranslation2D.PARAMETERS;
break;
}
case MOLODENSKY:
{
descriptor = Molodensky.PARAMETERS;
break;
}
case ABRIDGED_MOLODENSKY:
{
descriptor = AbridgedMolodensky.PARAMETERS;
break;
}
default:
throw new AssertionError(method);
}
/*
* Following lines will set all Bursa-Wolf parameter values (scale, translation
* and rotation terms). In the particular case of Molodensky method, we have an
* additional parameter for the number of source and target dimensions (2 or 3).
*/
final Parameters values = createParameters(descriptor, parameters, isTranslation);
switch(method) {
case MOLODENSKY:
case ABRIDGED_MOLODENSKY:
{
if (dimension <= 3) {
values.getOrCreate(Molodensky.DIMENSION).setValue(dimension);
}
break;
}
}
return values;
}
Aggregations