javax.measure.quantity.Angle Java Examples
The following examples show how to use
javax.measure.quantity.Angle.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: DefaultPrimeMeridian.java From sis with Apache License 2.0 | 6 votes |
/** * Invoked by JAXB for setting the Greenwich longitude and its unit of measurement. */ private void setGreenwichMeasure(final Measure measure) { if (greenwichLongitude == 0 && angularUnit == null) { greenwichLongitude = measure.value; angularUnit = measure.getUnit(Angle.class); if (angularUnit == null) { /* * Missing unit: if the Greenwich longitude is zero, any angular unit gives the same result * (assuming that the missing unit was not applying an offset), so we can select a default. * If the Greenwich longitude is not zero, presume egrees but log a warning. */ angularUnit = Units.DEGREE; if (greenwichLongitude != 0) { Measure.missingUOM(DefaultPrimeMeridian.class, "setGreenwichMeasure"); } } } else { MetadataUtilities.propertyAlreadySet(DefaultPrimeMeridian.class, "setGreenwichMeasure", "greenwichLongitude"); } }
Example #2
Source File: UnitsTest.java From sis with Apache License 2.0 | 6 votes |
/** * Tests getting a unit for a given quantity type. */ @Test public void testGetForQuantity() { assertSame("Length", Units.METRE, Units.get(Length.class)); assertSame("Mass", Units.KILOGRAM, Units.get(Mass.class)); assertSame("Time", Units.SECOND, Units.get(Time.class)); assertSame("Temperature", Units.KELVIN, Units.get(Temperature.class)); assertSame("Area", Units.SQUARE_METRE, Units.get(Area.class)); assertSame("Volume", Units.CUBIC_METRE, Units.get(Volume.class)); assertSame("Speed", Units.METRES_PER_SECOND, Units.get(Speed.class)); assertSame("LuminousIntensity", Units.CANDELA, Units.get(LuminousIntensity.class)); assertSame("LuminousFlux", Units.LUMEN, Units.get(LuminousFlux.class)); assertSame("SolidAngle", Units.STERADIAN, Units.get(SolidAngle.class)); assertSame("Angle", Units.RADIAN, Units.get(Angle.class)); assertSame("Dimensionless", Units.UNITY, Units.get(Dimensionless.class)); }
Example #3
Source File: FranceGeocentricInterpolationTest.java From sis with Apache License 2.0 | 6 votes |
/** * Tests the {@link FranceGeocentricInterpolation#getOrLoad(Path, double[], double)} method and its cache. * * @throws URISyntaxException if the URL to the test file can not be converted to a path. * @throws FactoryException if an error occurred while computing the grid. * @throws TransformException if an error occurred while computing the envelope. */ @Test @DependsOnMethod("testGrid") public void testGetOrLoad() throws URISyntaxException, FactoryException, TransformException { final DatumShiftGridFile<Angle,Length> grid = FranceGeocentricInterpolation.getOrLoad( getResource(TEST_FILE), new double[] { FranceGeocentricInterpolation.TX, FranceGeocentricInterpolation.TY, FranceGeocentricInterpolation.TZ}, FranceGeocentricInterpolation.PRECISION); verifyGrid(grid); assertSame("Expected a cached value.", grid, FranceGeocentricInterpolation.getOrLoad( getResource(TEST_FILE), new double[] { FranceGeocentricInterpolation.TX, FranceGeocentricInterpolation.TY, FranceGeocentricInterpolation.TZ}, FranceGeocentricInterpolation.PRECISION)); }
Example #4
Source File: FranceGeocentricInterpolationTest.java From sis with Apache License 2.0 | 6 votes |
/** * Tests a small grid file with interpolations in geocentric coordinates as {@code short} values. * * <p>This method is part of a chain. * The previous method is {@link #testGridAsFloats()}.</p> * * @param grid the grid created by {@link #testGridAsFloats()}. * @return the given grid, but compressed as {@code short} values. * @throws TransformException if an error occurred while computing the envelope. */ @TestStep private static DatumShiftGridFile<Angle,Length> testGridAsShorts(DatumShiftGridFile<Angle,Length> grid) throws TransformException { grid = DatumShiftGridCompressed.compress((DatumShiftGridFile.Float<Angle,Length>) grid, new double[] { FranceGeocentricInterpolation.TX, // 168 metres FranceGeocentricInterpolation.TY, // 60 metres FranceGeocentricInterpolation.TZ}, // -320 metres FranceGeocentricInterpolation.PRECISION); assertInstanceOf("Failed to compress 'float' values into 'short' values.", DatumShiftGridCompressed.class, grid); assertEquals("cellPrecision", 0.0005, grid.getCellPrecision(), STRICT); assertEquals("getCellMean", 168, grid.getCellMean(0), STRICT); assertEquals("getCellMean", 60, grid.getCellMean(1), STRICT); assertEquals("getCellMean", -320, grid.getCellMean(2), STRICT); verifyGrid(grid); return grid; }
Example #5
Source File: FranceGeocentricInterpolationTest.java From sis with Apache License 2.0 | 6 votes |
/** * Tests a small grid file with interpolations in geocentric coordinates as {@code float} values. * * <p>This method is part of a chain. * The next method is {@link #testGridAsShorts(DatumShiftGridFile)}.</p> * * @return the loaded grid with values as {@code float}. * @throws URISyntaxException if the URL to the test file can not be converted to a path. * @throws IOException if an error occurred while loading the grid. * @throws FactoryException if an error occurred while computing the grid. * @throws TransformException if an error occurred while computing the envelope. */ @TestStep private static DatumShiftGridFile<Angle,Length> testGridAsFloats() throws URISyntaxException, IOException, FactoryException, TransformException { final Path file = getResource(TEST_FILE); final DatumShiftGridFile.Float<Angle,Length> grid; try (BufferedReader in = Files.newBufferedReader(file)) { grid = FranceGeocentricInterpolation.load(in, file); } assertEquals("cellPrecision", 0.005, grid.getCellPrecision(), STRICT); assertEquals("getCellMean", 168.2587, grid.getCellMean(0), 0.0001); assertEquals("getCellMean", 58.7163, grid.getCellMean(1), 0.0001); assertEquals("getCellMean", -320.1801, grid.getCellMean(2), 0.0001); verifyGrid(grid); return grid; }
Example #6
Source File: GeodeticObjectParser.java From sis with Apache License 2.0 | 6 votes |
/** * Parses a {@code "PrimeMeridian"} element. The syntax is given by * <a href="http://docs.opengeospatial.org/is/12-063r5/12-063r5.html#53">WKT 2 specification §8.2.2</a>. * * The legacy WKT 1 pattern was: * * {@preformat wkt * PRIMEM["<name>", <longitude> {,<authority>}] * } * * @param mode {@link #FIRST}, {@link #OPTIONAL} or {@link #MANDATORY}. * @param parent the parent element. * @param isWKT1 {@code true} if this method is invoked while parsing a WKT 1 element. * @param angularUnit the contextual unit. * @return the {@code "PrimeMeridian"} element as a {@link PrimeMeridian} object. * @throws ParseException if the {@code "PrimeMeridian"} element can not be parsed. * * @see org.apache.sis.referencing.datum.DefaultPrimeMeridian#formatTo(Formatter) */ private PrimeMeridian parsePrimeMeridian(final int mode, final Element parent, final boolean isWKT1, Unit<Angle> angularUnit) throws ParseException { if (isWKT1 && usesCommonUnits) { angularUnit = Units.DEGREE; } final Element element = parent.pullElement(mode, WKTKeywords.PrimeMeridian, WKTKeywords.PrimeM); if (element == null) { return null; } final String name = element.pullString("name"); final double longitude = element.pullDouble("longitude"); final Unit<Angle> unit = parseScaledUnit(element, WKTKeywords.AngleUnit, Units.RADIAN); if (unit != null) { angularUnit = unit; } else if (angularUnit == null) { throw parent.missingComponent(WKTKeywords.AngleUnit); } final DatumFactory datumFactory = factories.getDatumFactory(); try { return datumFactory.createPrimeMeridian(parseMetadataAndClose(element, name, null), longitude, angularUnit); } catch (FactoryException exception) { throw element.parseFailed(exception); } }
Example #7
Source File: AxisDirections.java From sis with Apache License 2.0 | 6 votes |
/** * Returns the angular unit of the specified coordinate system. * The preference will be given to the longitude axis, if found. * * @param cs the coordinate system from which to get the angular unit, or {@code null}. * @param fallback the default unit to return if no angular unit is found. * @return the angular unit, of {@code unit} if no angular unit was found. * * @see org.apache.sis.internal.referencing.ReferencingUtilities#getUnit(CoordinateSystem) * * @since 0.6 */ public static Unit<Angle> getAngularUnit(final CoordinateSystem cs, Unit<Angle> fallback) { if (cs != null) { for (int i = cs.getDimension(); --i>=0;) { final CoordinateSystemAxis axis = cs.getAxis(i); if (axis != null) { // Paranoiac check. final Unit<?> candidate = axis.getUnit(); if (Units.isAngular(candidate)) { fallback = candidate.asType(Angle.class); if (AxisDirection.EAST.equals(absolute(axis.getDirection()))) { break; // Found the longitude axis. } } } } } return fallback; }
Example #8
Source File: DatumShiftGridFile.java From sis with Apache License 2.0 | 6 votes |
/** * Creates a transformation between two geodetic CRS, including the sub-grid transforms. * If the given grid has no sub-grid, then this method is equivalent to a direct call to * {@link InterpolatedTransform#createGeodeticTransformation(MathTransformFactory, DatumShiftGrid)}. * * @param provider the provider which is creating a transform. * @param factory the factory to use for creating the transform. * @param grid the grid of datum shifts from source to target datum. * @return the transformation between geodetic coordinates. * @throws FactoryException if an error occurred while creating a transform. * * @see InterpolatedTransform#createGeodeticTransformation(MathTransformFactory, DatumShiftGrid) */ public static MathTransform createGeodeticTransformation(final Class<? extends AbstractProvider> provider, final MathTransformFactory factory, final DatumShiftGridFile<Angle,Angle> grid) throws FactoryException { MathTransform global = InterpolatedTransform.createGeodeticTransformation(factory, grid); final DatumShiftGridFile<Angle,Angle>[] subgrids = grid.subgrids; if (subgrids == null) { return global; } final Map<Envelope,MathTransform> specializations = new LinkedHashMap<>(Containers.hashMapCapacity(subgrids.length)); for (final DatumShiftGridFile<Angle,Angle> sg : subgrids) try { final Envelope domain = sg.getDomainOfValidity(Units.DEGREE); final MathTransform st = createGeodeticTransformation(provider, factory, sg); if (specializations.putIfAbsent(domain, st) != null) { DatumShiftGridLoader.log(provider, Errors.getResources((Locale) null) .getLogRecord(Level.FINE, Errors.Keys.DuplicatedElement_1, domain)); } } catch (TransformException e) { throw new FactoryException(e); } return MathTransforms.specialize(global, specializations); }
Example #9
Source File: DefaultPrimeMeridian.java From sis with Apache License 2.0 | 6 votes |
/** * Formats this prime meridian as a <cite>Well Known Text</cite> {@code PrimeMeridian[…]} element. * * @return {@code "PrimeMeridian"} (WKT 2) or {@code "PrimeM"} (WKT 1). * * @see <a href="http://docs.opengeospatial.org/is/12-063r5/12-063r5.html#53">WKT 2 specification §8.2.2</a> */ @Override protected String formatTo(final Formatter formatter) { super.formatTo(formatter); final Convention convention = formatter.getConvention(); final boolean isWKT1 = (convention.majorVersion() == 1); final Unit<Angle> contextualUnit = formatter.toContextualUnit(Units.DEGREE); Unit<Angle> unit = contextualUnit; if (!isWKT1) { unit = getAngularUnit(); if (convention != Convention.INTERNAL) { unit = WKTUtilities.toFormattable(unit); } } formatter.append(getGreenwichLongitude(unit)); if (isWKT1) { return WKTKeywords.PrimeM; } if (!convention.isSimplified() || !contextualUnit.equals(unit) || beConservative(formatter, contextualUnit)) { formatter.append(unit); } return formatter.shortOrLong(WKTKeywords.PrimeM, WKTKeywords.PrimeMeridian); }
Example #10
Source File: I18nProviderImpl.java From smarthome with Eclipse Public License 2.0 | 5 votes |
private void initDimensionMap() { Map<SystemOfUnits, Unit<? extends Quantity<?>>> temperatureMap = new HashMap<>(); temperatureMap.put(SIUnits.getInstance(), SIUnits.CELSIUS); temperatureMap.put(ImperialUnits.getInstance(), ImperialUnits.FAHRENHEIT); dimensionMap.put(Temperature.class, temperatureMap); Map<SystemOfUnits, Unit<? extends Quantity<?>>> pressureMap = new HashMap<>(); pressureMap.put(SIUnits.getInstance(), HECTO(SIUnits.PASCAL)); pressureMap.put(ImperialUnits.getInstance(), ImperialUnits.INCH_OF_MERCURY); dimensionMap.put(Pressure.class, pressureMap); Map<SystemOfUnits, Unit<? extends Quantity<?>>> speedMap = new HashMap<>(); speedMap.put(SIUnits.getInstance(), SIUnits.KILOMETRE_PER_HOUR); speedMap.put(ImperialUnits.getInstance(), ImperialUnits.MILES_PER_HOUR); dimensionMap.put(Speed.class, speedMap); Map<SystemOfUnits, Unit<? extends Quantity<?>>> lengthMap = new HashMap<>(); lengthMap.put(SIUnits.getInstance(), SIUnits.METRE); lengthMap.put(ImperialUnits.getInstance(), ImperialUnits.INCH); dimensionMap.put(Length.class, lengthMap); Map<SystemOfUnits, Unit<? extends Quantity<?>>> intensityMap = new HashMap<>(); intensityMap.put(SIUnits.getInstance(), SmartHomeUnits.IRRADIANCE); intensityMap.put(ImperialUnits.getInstance(), SmartHomeUnits.IRRADIANCE); dimensionMap.put(Intensity.class, intensityMap); Map<SystemOfUnits, Unit<? extends Quantity<?>>> percentMap = new HashMap<>(); percentMap.put(SIUnits.getInstance(), SmartHomeUnits.ONE); percentMap.put(ImperialUnits.getInstance(), SmartHomeUnits.ONE); dimensionMap.put(Dimensionless.class, percentMap); Map<SystemOfUnits, Unit<? extends Quantity<?>>> angleMap = new HashMap<>(); angleMap.put(SIUnits.getInstance(), SmartHomeUnits.DEGREE_ANGLE); angleMap.put(ImperialUnits.getInstance(), SmartHomeUnits.DEGREE_ANGLE); dimensionMap.put(Angle.class, angleMap); }
Example #11
Source File: FranceGeocentricInterpolation.java From sis with Apache License 2.0 | 5 votes |
/** * Returns the grid of the given name. This method returns the cached instance if it still exists, * or load the grid otherwise. * * @param file name of the datum shift grid file to load. * @param averages an "average" value for the offset in each dimension, or {@code null} if unknown. * @param scale the factor by which to multiply each compressed value before to add to the average value. */ @SuppressWarnings("null") static DatumShiftGridFile<Angle,Length> getOrLoad(final Path file, final double[] averages, final double scale) throws FactoryException { final Path resolved = DataDirectory.DATUM_CHANGES.resolve(file).toAbsolutePath(); DatumShiftGridFile<?,?> grid = DatumShiftGridFile.CACHE.peek(resolved); if (grid == null) { final Cache.Handler<DatumShiftGridFile<?,?>> handler = DatumShiftGridFile.CACHE.lock(resolved); try { grid = handler.peek(); if (grid == null) { try (BufferedReader in = Files.newBufferedReader(resolved)) { DatumShiftGridLoader.startLoading(FranceGeocentricInterpolation.class, file); final DatumShiftGridFile.Float<Angle,Length> g = load(in, file); grid = DatumShiftGridCompressed.compress(g, averages, scale); } catch (IOException | NoninvertibleTransformException | RuntimeException e) { // NumberFormatException, ArithmeticException, NoSuchElementException, possibly other. throw DatumShiftGridLoader.canNotLoad(HEADER, file, e); } grid = grid.useSharedData(); } } finally { handler.putAndUnlock(grid); } } return grid.castTo(Angle.class, Length.class); }
Example #12
Source File: FranceGeocentricInterpolation.java From sis with Apache License 2.0 | 5 votes |
/** * Creates the actual math transform. The default implementation delegates to the static method defined in * {@link InterpolatedGeocentricTransform}, but the {@link MolodenskyInterpolation} subclass will rather * delegate to {@link org.apache.sis.referencing.operation.transform.InterpolatedMolodenskyTransform}. */ MathTransform createGeodeticTransformation(final MathTransformFactory factory, final Ellipsoid source, final Ellipsoid target, final boolean withHeights, final DatumShiftGridFile<Angle,Length> grid) throws FactoryException { return InterpolatedGeocentricTransform.createGeodeticTransformation( factory, source, withHeights, target, withHeights, grid); }
Example #13
Source File: FranceGeocentricInterpolation.java From sis with Apache License 2.0 | 5 votes |
/** * 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, CommonCRS.ETRS89.ellipsoid()), // GRS 1980 ellipsoid createEllipsoid(pg, Molodensky.SRC_SEMI_MAJOR, Molodensky.SRC_SEMI_MINOR, null), // Clarke 1880 (IGN) ellipsoid withHeights, grid); try { tr = tr.inverse(); } catch (NoninvertibleTransformException e) { throw new FactoryException(e); // Should never happen. } return tr; }
Example #14
Source File: CRSBuilder.java From sis with Apache License 2.0 | 5 votes |
/** * Creates a prime meridian from an EPSG code or from user-defined parameters. * The GeoTIFF values used by this method are: * * <ul> * <li>A code given by {@link GeoKeys#PrimeMeridian}.</li> * <li>If above code is {@link GeoCodes#userDefined}, then:<ul> * <li>a prime meridian value given by {@link GeoKeys#PrimeMeridianLong}.</li> * </ul></li> * </ul> * * If no prime-meridian is defined, then the default is Greenwich as per GeoTIFF specification. * * @param names the component names to use if the prime meridian is user-defined. * @param unit the angular unit of the longitude value relative to Greenwich. * @return a prime meridian created from the given {@link Unit} and the above-cited GeoTIFF keys. * @throws NumberFormatException if a numeric value was stored as a string and can not be parsed. * @throws FactoryException if an error occurred during objects creation with the factories. */ private PrimeMeridian createPrimeMeridian(final String[] names, final Unit<Angle> unit) throws FactoryException { final int epsg = getAsInteger(GeoKeys.PrimeMeridian); switch (epsg) { case GeoCodes.undefined: // If not specified, should default to Greenwich but we nevertheless verify. case GeoCodes.userDefined: { final double longitude = getAsDouble(GeoKeys.PrimeMeridianLong); if (Double.isNaN(longitude)) { if (epsg != GeoCodes.undefined) { missingValue(GeoKeys.PrimeMeridianLong); } } else if (longitude != 0) { /* * If the prime meridian is not Greenwich, create that meridian but do not use the * GeoKeys.GeogCitation value (unless it had a sub-element for the prime meridian). * This is because the citation value is for the CRS (e.g. "WGS84") while the prime * meridian names are very different (e.g. "Paris", "Madrid", etc). */ return getDatumFactory().createPrimeMeridian(properties(names[PRIMEM]), longitude, unit); } break; // Default to Greenwich. } default: { /* * Prime meridian defined by an EPSG code. In principle we should just use the EPSG code. * But if the file also provide the longitude value, verify that the value is consistent * with what we would expect for a prime meridian of the given EPSG code. */ final PrimeMeridian pm = getDatumAuthorityFactory().createPrimeMeridian(String.valueOf(epsg)); verify(pm, unit); return pm; } } return CommonCRS.WGS84.primeMeridian(); }
Example #15
Source File: NTv2.java From sis with Apache License 2.0 | 5 votes |
/** * Returns the grid of the given name. This method returns the cached instance if it still exists, * or load the grid otherwise. * * @param provider the provider which is creating a transform. * @param file name of the datum shift grid file to load. * @param version the expected version (1 or 2). */ @SuppressWarnings("null") static DatumShiftGridFile<Angle,Angle> getOrLoad(final Class<? extends AbstractProvider> provider, final Path file, final int version) throws FactoryException { final Path resolved = DataDirectory.DATUM_CHANGES.resolve(file).toAbsolutePath(); DatumShiftGridFile<?,?> grid = DatumShiftGridFile.CACHE.peek(resolved); if (grid == null) { final Cache.Handler<DatumShiftGridFile<?,?>> handler = DatumShiftGridFile.CACHE.lock(resolved); try { grid = handler.peek(); if (grid == null) { try (ReadableByteChannel in = Files.newByteChannel(resolved)) { DatumShiftGridLoader.startLoading(provider, file); final Loader loader = new Loader(in, file, version); grid = loader.readAllGrids(); loader.report(provider); } catch (IOException | NoninvertibleTransformException | RuntimeException e) { throw DatumShiftGridLoader.canNotLoad(provider.getSimpleName(), file, e); } grid = grid.useSharedData(); } } finally { handler.putAndUnlock(grid); } } return grid.castTo(Angle.class, Angle.class); }
Example #16
Source File: MolodenskyInterpolation.java From sis with Apache License 2.0 | 5 votes |
/** * Invoked by {@link #createMathTransform(MathTransformFactory, ParameterValueGroup)} * after all parameters have been processed. */ @Override MathTransform createGeodeticTransformation(final MathTransformFactory factory, final Ellipsoid source, final Ellipsoid target, final boolean withHeights, final DatumShiftGridFile<Angle,Length> grid) throws FactoryException { return InterpolatedMolodenskyTransform.createGeodeticTransformation( factory, source, withHeights, target, withHeights, grid); }
Example #17
Source File: CRSBuilder.java From sis with Apache License 2.0 | 5 votes |
/** * Returns a coordinate system (CS) with the same axis directions than the given CS but potentially different units. * If a coordinate system exists in the EPSG database with the requested characteristics, that CS will be returned * in order to have a richer set of metadata (name, minimal and maximal values, <i>etc</i>). Otherwise an CS with * an arbitrary name will be returned. * * @see CoordinateSystems#replaceAngularUnit(CoordinateSystem, Unit) */ private EllipsoidalCS replaceAngularUnit(final EllipsoidalCS cs, final Unit<Angle> unit) throws FactoryException { final Integer epsg = CoordinateSystems.getEpsgCode(unit, CoordinateSystems.getAxisDirections(cs)); if (epsg != null) try { return getCSAuthorityFactory().createEllipsoidalCS(epsg.toString()); } catch (NoSuchAuthorityCodeException e) { reader.owner.warning(null, e); } return (EllipsoidalCS) CoordinateSystems.replaceAngularUnit(cs, unit); }
Example #18
Source File: I18nProviderImpl.java From openhab-core with Eclipse Public License 2.0 | 5 votes |
private void initDimensionMap() { Map<SystemOfUnits, Unit<? extends Quantity<?>>> temperatureMap = new HashMap<>(); temperatureMap.put(SIUnits.getInstance(), SIUnits.CELSIUS); temperatureMap.put(ImperialUnits.getInstance(), ImperialUnits.FAHRENHEIT); dimensionMap.put(Temperature.class, temperatureMap); Map<SystemOfUnits, Unit<? extends Quantity<?>>> pressureMap = new HashMap<>(); pressureMap.put(SIUnits.getInstance(), HECTO(SIUnits.PASCAL)); pressureMap.put(ImperialUnits.getInstance(), ImperialUnits.INCH_OF_MERCURY); dimensionMap.put(Pressure.class, pressureMap); Map<SystemOfUnits, Unit<? extends Quantity<?>>> speedMap = new HashMap<>(); speedMap.put(SIUnits.getInstance(), SIUnits.KILOMETRE_PER_HOUR); speedMap.put(ImperialUnits.getInstance(), ImperialUnits.MILES_PER_HOUR); dimensionMap.put(Speed.class, speedMap); Map<SystemOfUnits, Unit<? extends Quantity<?>>> lengthMap = new HashMap<>(); lengthMap.put(SIUnits.getInstance(), SIUnits.METRE); lengthMap.put(ImperialUnits.getInstance(), ImperialUnits.INCH); dimensionMap.put(Length.class, lengthMap); Map<SystemOfUnits, Unit<? extends Quantity<?>>> intensityMap = new HashMap<>(); intensityMap.put(SIUnits.getInstance(), SmartHomeUnits.IRRADIANCE); intensityMap.put(ImperialUnits.getInstance(), SmartHomeUnits.IRRADIANCE); dimensionMap.put(Intensity.class, intensityMap); Map<SystemOfUnits, Unit<? extends Quantity<?>>> percentMap = new HashMap<>(); percentMap.put(SIUnits.getInstance(), SmartHomeUnits.ONE); percentMap.put(ImperialUnits.getInstance(), SmartHomeUnits.ONE); dimensionMap.put(Dimensionless.class, percentMap); Map<SystemOfUnits, Unit<? extends Quantity<?>>> angleMap = new HashMap<>(); angleMap.put(SIUnits.getInstance(), SmartHomeUnits.DEGREE_ANGLE); angleMap.put(ImperialUnits.getInstance(), SmartHomeUnits.DEGREE_ANGLE); dimensionMap.put(Angle.class, angleMap); }
Example #19
Source File: DefaultPrimeMeridianTest.java From sis with Apache License 2.0 | 5 votes |
/** * Tests WKT formatting of a prime meridian with sexagesimal units. * Since those units can not be formatted in a {@code UNIT["name", scale]} element, * the formatter should convert them to a formattable unit like degrees. * * @since 0.6 */ @Test @DependsOnMethod("testWKT_inGrads") public void testWKT_withUnformattableUnit() { final DefaultPrimeMeridian pm = new DefaultPrimeMeridian(singletonMap(DefaultPrimeMeridian.NAME_KEY, "Test"), 10.3, Units.valueOfEPSG(9111).asType(Angle.class)); /* * In WKT 1 format, if there is no contextual unit (which is the case of this test), * the formatter default to decimal degrees. In WKT 2 format it depends on the PM unit. */ assertWktEquals(Convention.WKT1, "PRIMEM[“Test”, 10.5]", pm); // 10.3 DM == 10.5° assertWktEquals(Convention.WKT2, "PRIMEM[“Test”, 10.5, ANGLEUNIT[“degree”, 0.017453292519943295]]", pm); assertWktEquals(Convention.WKT2_SIMPLIFIED, "PrimeMeridian[“Test”, 10.5]", pm); assertWktEquals(Convention.INTERNAL, "PrimeMeridian[“Test”, 10.3, Unit[“D.M”, 0.017453292519943295, Id[“EPSG”, 9111]]]", pm); }
Example #20
Source File: EPSGDataAccess.java From sis with Apache License 2.0 | 5 votes |
/** * Creates a prime meridian defining the origin from which longitude values are determined. * * <div class="note"><b>Example:</b> * some EPSG codes for prime meridians are: * * <table class="sis"> * <caption>EPSG codes examples</caption> * <tr><th>Code</th> <th>Description</th></tr> * <tr><td>8901</td> <td>Greenwich</td></tr> * <tr><td>8903</td> <td>Paris</td></tr> * <tr><td>8904</td> <td>Bogota</td></tr> * <tr><td>8905</td> <td>Madrid</td></tr> * <tr><td>8906</td> <td>Rome</td></tr> * </table></div> * * @param code value allocated by EPSG. * @return the prime meridian for the given code. * @throws NoSuchAuthorityCodeException if the specified {@code code} was not found. * @throws FactoryException if the object creation failed for some other reason. * * @see #createGeodeticDatum(String) * @see org.apache.sis.referencing.datum.DefaultPrimeMeridian */ @Override public synchronized PrimeMeridian createPrimeMeridian(final String code) throws NoSuchAuthorityCodeException, FactoryException { ArgumentChecks.ensureNonNull("code", code); PrimeMeridian returnValue = null; try (ResultSet result = executeQuery("Prime Meridian", "PRIME_MERIDIAN_CODE", "PRIME_MERIDIAN_NAME", "SELECT PRIME_MERIDIAN_CODE," + " PRIME_MERIDIAN_NAME," + " GREENWICH_LONGITUDE," + " UOM_CODE," + " REMARKS," + " DEPRECATED" + " FROM [Prime Meridian]" + " WHERE PRIME_MERIDIAN_CODE = ?", code)) { while (result.next()) { final Integer epsg = getInteger (code, result, 1); final String name = getString (code, result, 2); final double longitude = getDouble (code, result, 3); final String unitCode = getString (code, result, 4); final String remarks = getOptionalString (result, 5); final boolean deprecated = getOptionalBoolean(result, 6); final Unit<Angle> unit = owner.createUnit(unitCode).asType(Angle.class); final PrimeMeridian primeMeridian = owner.datumFactory.createPrimeMeridian( createProperties("Prime Meridian", name, epsg, remarks, deprecated), longitude, unit); returnValue = ensureSingleton(primeMeridian, returnValue, code); } } catch (SQLException exception) { throw databaseFailure(PrimeMeridian.class, code, exception); } if (returnValue == null) { throw noSuchAuthorityCode(PrimeMeridian.class, code); } return returnValue; }
Example #21
Source File: BlukiiHandler.java From smarthome with Eclipse Public License 2.0 | 5 votes |
@Override public void onScanRecordReceived(BluetoothScanNotification scanNotification) { final byte[] manufacturerData = scanNotification.getManufacturerData(); if (manufacturerData != null) { final BlukiiData blukiiData = decoder.decode(manufacturerData); if (blukiiData != null) { updateState(BlukiiBindingConstants.CHANNEL_ID_BATTERY, new DecimalType(blukiiData.battery)); blukiiData.environment.ifPresent(environment -> { updateState(BlukiiBindingConstants.CHANNEL_ID_TEMPERATURE, new QuantityType<Temperature>(environment.temperature, SIUnits.CELSIUS)); updateState(BlukiiBindingConstants.CHANNEL_ID_HUMIDITY, new QuantityType<Dimensionless>(environment.humidity, SmartHomeUnits.PERCENT)); updateState(BlukiiBindingConstants.CHANNEL_ID_PRESSURE, new QuantityType<Pressure>(environment.pressure, MetricPrefix.HECTO(SIUnits.PASCAL))); updateState(BlukiiBindingConstants.CHANNEL_ID_LUMINANCE, new QuantityType<Illuminance>(environment.luminance, SmartHomeUnits.LUX)); }); blukiiData.accelerometer.ifPresent(accelerometer -> { updateState(BlukiiBindingConstants.CHANNEL_ID_TILTX, new QuantityType<Angle>(accelerometer.tiltX, SmartHomeUnits.DEGREE_ANGLE)); updateState(BlukiiBindingConstants.CHANNEL_ID_TILTY, new QuantityType<Angle>(accelerometer.tiltY, SmartHomeUnits.DEGREE_ANGLE)); updateState(BlukiiBindingConstants.CHANNEL_ID_TILTZ, new QuantityType<Angle>(accelerometer.tiltZ, SmartHomeUnits.DEGREE_ANGLE)); }); blukiiData.magnetometer.ifPresent(magnetometer -> { // It isn't easy to get a heading from these values without any calibration, so we ignore those // right // now. }); } } super.onScanRecordReceived(scanNotification); }
Example #22
Source File: CRSBuilder.java From sis with Apache License 2.0 | 5 votes |
/** * Verifies if the user-defined CRS created from GeoTIFF values * matches the given CRS created from the EPSG geodetic dataset. * This method does not verify the EPSG code of the given CRS. * * @param crs the CRS created from the EPSG geodetic dataset. * @param angularUnit the angular unit of the latitude and longitude values. */ private void verify(final GeographicCRS crs, final Unit<Angle> angularUnit) throws FactoryException { /* * Note: current createUnit(…) implementation does not allow us to distinguish whether METRE ou DEGREE units * were specified in the GeoTIFF file or if we got the default values. We do not compare units of that reason. */ final Unit<Length> linearUnit = createUnit(GeoKeys.GeogLinearUnits, GeoKeys.GeogLinearUnitSize, Length.class, Units.METRE); final GeodeticDatum datum = crs.getDatum(); verifyIdentifier(crs, datum, GeoKeys.GeodeticDatum); verify(datum, angularUnit, linearUnit); }
Example #23
Source File: CRSBuilder.java From sis with Apache License 2.0 | 5 votes |
/** * Verifies if the user-defined CRS created from GeoTIFF values * matches the given CRS created from the EPSG geodetic dataset. * This method does not verify the EPSG code of the given CRS. * * @param crs the CRS created from the EPSG geodetic dataset. */ private void verify(final GeocentricCRS crs) throws FactoryException { /* * Note: current createUnit(…) implementation does not allow us to distinguish whether METRE ou DEGREE units * were specified in the GeoTIFF file or if we got the default values. We do not compare units of that reason. */ final Unit<Length> linearUnit = createUnit(GeoKeys.GeogLinearUnits, GeoKeys.GeogLinearUnitSize, Length.class, Units.METRE); final Unit<Angle> angularUnit = createUnit(GeoKeys.AngularUnits, GeoKeys.AngularUnitSize, Angle.class, Units.DEGREE); final GeodeticDatum datum = crs.getDatum(); verifyIdentifier(crs, datum, GeoKeys.GeodeticDatum); verify(datum, angularUnit, linearUnit); }
Example #24
Source File: CRSBuilder.java From sis with Apache License 2.0 | 5 votes |
/** * Verifies if the user-defined CRS created from GeoTIFF values * matches the given CRS created from the EPSG geodetic dataset. * This method does not verify the EPSG code of the given CRS. * * @param crs the CRS created from the EPSG geodetic dataset. */ private void verify(final ProjectedCRS crs) throws FactoryException { final Unit<Length> linearUnit = createUnit(GeoKeys.LinearUnits, GeoKeys.LinearUnitSize, Length.class, Units.METRE); final Unit<Angle> angularUnit = createUnit(GeoKeys.AngularUnits, GeoKeys.AngularUnitSize, Angle.class, Units.DEGREE); final GeographicCRS baseCRS = crs.getBaseCRS(); verifyIdentifier(crs, baseCRS, GeoKeys.GeographicType); verify(baseCRS, angularUnit); final Conversion projection = crs.getConversionFromBase(); verifyIdentifier(crs, projection, GeoKeys.Projection); verify(projection, angularUnit, linearUnit); }
Example #25
Source File: NTv2Test.java From sis with Apache License 2.0 | 5 votes |
/** * Writes a sub-grid of the given grid in pseudo-NTv2 format. This method is used only for creating the test file. * The file created by this method is not fully NTv2 compliant (in particular, we do not write complete header), * but we take this opportunity for testing {@code NTv2.Loader} capability to be lenient. * * <p>This method has been executed once for creating the {@code "NTF_R93-extract.gsb"} test file and should not * be needed anymore, but we keep it around in case we have new test files to generate. The parameter used for * creating the test file are:</p> * * <ul> * <li>{@code gridX} = 72</li> * <li>{@code gridY} = 74</li> * <li>{@code nx} = 6</li> * <li>{@code ny} = 7</li> * </ul> * * This ensure that the grid indices (75.7432814, 78.4451225) is included in the test file. * Those grid indices is the location of the (2°25′32.4187″N 48°50′40.2441″W) test point to interpolate. * * <h4>Limitations</h4> * This method assumes that bounding box and increments have integer values, and that any fractional part * is rounding errors. This is usually the case when using the {@code "SECONDS"} unit of measurement. * This assumption does not apply to the shift values. * * @param grid the full grid from which to extract a few values. * @param out where to write the test file. * @param gridX index along the longitude axis of the first cell to write. * @param gridY index along the latitude axis of the first cell to write. * @param nx number of cells to write along the longitude axis. * @param ny number of cells to write along the latitude axis. * @throws TransformException if an error occurred while computing the envelope. * @throws IOException if an error occurred while writing the test file. */ public static void writeSubGrid(final DatumShiftGridFile<Angle,Angle> grid, final Path out, final int gridX, final int gridY, final int nx, final int ny) throws IOException, TransformException { Envelope envelope = new Envelope2D(null, gridX, gridY, nx - 1, ny - 1); envelope = Envelopes.transform(grid.getCoordinateToGrid().inverse(), envelope); final ByteBuffer buffer = ByteBuffer.allocate(4096); buffer.order(ByteOrder.LITTLE_ENDIAN); writeString(buffer, "NUM_OREC"); buffer.putInt(5); nextRecord(buffer); writeString(buffer, "NUM_SREC"); buffer.putInt(7); nextRecord(buffer); writeString(buffer, "NUM_FILE"); buffer.putInt(1); nextRecord(buffer); writeString(buffer, "GS_TYPE"); writeString(buffer, "SECONDS"); writeString(buffer, "VERSION"); writeString(buffer, "SIS_TEST"); // Last overview record. writeString(buffer, "S_LAT"); buffer.putDouble(StrictMath.rint( envelope.getMinimum(1))); writeString(buffer, "N_LAT"); buffer.putDouble(StrictMath.rint( envelope.getMaximum(1))); writeString(buffer, "E_LONG"); buffer.putDouble(StrictMath.rint(-envelope.getMaximum(0))); // Sign reversed. writeString(buffer, "W_LONG"); buffer.putDouble(StrictMath.rint(-envelope.getMinimum(0))); writeString(buffer, "LAT_INC"); buffer.putDouble(StrictMath.rint( envelope.getSpan(1) / (ny - 1))); writeString(buffer, "LONG_INC"); buffer.putDouble(StrictMath.rint( envelope.getSpan(0) / (nx - 1))); writeString(buffer, "GS_COUNT"); buffer.putInt(nx * ny); nextRecord(buffer); for (int y=0; y<ny; y++) { for (int x=0; x<nx; x++) { buffer.putFloat((float) grid.getCellValue(1, gridX + x, gridY + y)); buffer.putFloat((float) grid.getCellValue(0, gridX + x, gridY + y)); buffer.putFloat(ACCURACY); buffer.putFloat(ACCURACY); } } writeString(buffer, "END"); nextRecord(buffer); try (WritableByteChannel c = Files.newByteChannel(out, StandardOpenOption.CREATE, StandardOpenOption.WRITE)) { buffer.flip(); c.write(buffer); } }
Example #26
Source File: FranceGeocentricInterpolationTest.java From sis with Apache License 2.0 | 5 votes |
/** * Verifies the envelope and the interpolation performed by the given grid. * * @throws TransformException if an error occurred while computing the envelope. */ private static void verifyGrid(final DatumShiftGridFile<Angle,Length> grid) throws TransformException { final Envelope envelope = grid.getDomainOfValidity(); assertEquals("xmin", 2.2, envelope.getMinimum(0), 1E-12); assertEquals("xmax", 2.5, envelope.getMaximum(0), 1E-12); assertEquals("ymin", 48.5, envelope.getMinimum(1), 1E-12); assertEquals("ymax", 49.0, envelope.getMaximum(1), 1E-12); /* * The values in the NTG_88 document are: * * (gridX=2, gridY=3) 00002 2.400000000 48.800000000 -168.252 -58.630 320.170 01 2314 * (gridX=2, gridY=4) 00002 2.400000000 48.900000000 -168.275 -58.606 320.189 01 2314 * (gridX=3, gridY=3) 00002 2.500000000 48.800000000 -168.204 -58.594 320.125 01 2314 * (gridX=3, gridY=4) 00002 2.500000000 48.900000000 -168.253 -58.554 320.165 01 2314 * * Directions (signs) are reversed compared to NTG_88 document. */ assertEquals("translationDimensions", 3, grid.getTranslationDimensions()); assertEquals("grid.accuracy", 0.05, grid.accuracy, STRICT); assertEquals("getCellValue", 168.196, grid.getCellValue(0, 2, 1), STRICT); assertEquals("getCellValue", 58.778, grid.getCellValue(1, 2, 1), STRICT); assertEquals("getCellValue", -320.127, grid.getCellValue(2, 2, 1), STRICT); /* * Interpolate the (ΔX, ΔY, ΔZ) at a point. * Directions (signs) are reversed compared to NTG_88 document. */ final double[] expected = { 168.253, // ΔX: Toward prime meridian 58.609, // ΔY: Toward 90° east -320.170 // ΔZ: Toward north pole }; final double[] point = samplePoint(3); final double[] vector = grid.interpolateAt(point[0], point[1]); assertArrayEquals("(ΔX, ΔY, ΔZ)", expected, vector, 0.0005); }
Example #27
Source File: NADCONTest.java From sis with Apache License 2.0 | 4 votes |
/** * Writes a sub-grid of the given grid in pseudo-NADCON ASCII format. * This method is used only for creating the test file, and the output is not fully NADCON compliant. * We take this opportunity for testing the parser capability to be lenient. * * <p>This method has been executed once for creating the {@code "conus-extract.laa"} and * {@code "conus-extract.loa"} test files and should not be needed anymore, but we keep it * around in case we have new test files to generate. The parameter used for creating the * test file are:</p> * * <ul> * <li>{@code gridX} = 125</li> * <li>{@code gridY} = 70</li> * <li>{@code nx} = 8</li> * <li>{@code ny} = 10</li> * </ul> * * This ensure that the grid indices (129.83277, 76.89632) is included in the test file. * Those grid indices is the location of the (39°13′26.71″N, 98°32′31.75″W) test point to interpolate. * * @param grid the full grid from which to extract a few values. * @param file where to write the test file. * @param dim 0 for writing longitudes, or 1 for writing latitudes. * @param gridX index along the longitude axis of the first cell to write. * @param gridY index along the latitude axis of the first cell to write. * @param nx number of cells to write along the longitude axis. * @param ny number of cells to write along the latitude axis. * @throws TransformException if an error occurred while computing the envelope. * @throws IOException if an error occurred while writing the test file. */ public static void writeSubGrid(final DatumShiftGridFile<Angle,Angle> grid, final Path file, final int dim, final int gridX, final int gridY, final int nx, final int ny) throws IOException, TransformException { Envelope envelope = new Envelope2D(null, gridX, gridY, nx - 1, ny - 1); envelope = Envelopes.transform(grid.getCoordinateToGrid().inverse(), envelope); try (BufferedWriter out = Files.newBufferedWriter(file)) { out.write("NADCON EXTRACTED REGION\n"); out.write(String.format(Locale.US, "%4d %3d %3d %11.5f %11.5f %11.5f %11.5f %11.5f\n", nx, ny, 1, envelope.getMinimum(0), envelope.getSpan(0) / (nx - 1), envelope.getMinimum(1), envelope.getSpan(1) / (ny - 1), 0.0)); for (int y=0; y<ny; y++) { for (int x=0; x<nx; x++) { out.write(String.format(Locale.US, " %11.6f", grid.getCellValue(dim, gridX + x, gridY + y))); } out.write('\n'); } } }
Example #28
Source File: NTv2.java From sis with Apache License 2.0 | 4 votes |
/** * Reads all grids and returns the root grid. After reading all grids, this method rearrange * them in a child-parent relationship. The result is a tree with a single root containing * sub-grids (if any) as children. */ final DatumShiftGridFile<Angle,Angle> readAllGrids() throws IOException, FactoryException, NoninvertibleTransformException { final Map<String, DatumShiftGridFile<Angle,Angle>> grids = new HashMap<>(Containers.hashMapCapacity(numGrids)); final Map<String, List<DatumShiftGridFile<Angle,Angle>>> children = new LinkedHashMap<>(); // Should have few entries. while (grids.size() < numGrids) { readGrid(grids, children); } /* * Assign the sub-grids to their parent only after we finished to read all grids. * Doing this work last is more robust to cases where grids are in random order. * * Notes: if the parent-child graph contains cycles (deeper than a child declaring itself as its parent), * the grids in cycles will be lost. This is because we need a grid without parent for getting the * graph added in the roots list. There is currently no mechanism for detecting those problems. */ final List<DatumShiftGridFile<Angle,Angle>> roots = new ArrayList<>(); for (final Map.Entry<String, List<DatumShiftGridFile<Angle,Angle>>> entry : children.entrySet()) { final DatumShiftGridFile<Angle,Angle> parent = grids.get(entry.getKey()); final List<DatumShiftGridFile<Angle,Angle>> subgrids = entry.getValue(); if (parent != null) { /* * Verify that the children does not declare themselves as their parent. * It may happen if SUB_GRID and PARENT have the same value, typically a * null or empty value if those records were actually unspecified. */ for (int i=subgrids.size(); --i >= 0;) { if (subgrids.get(i) == parent) { // Want identity check, no need for equals(Object). subgrids.remove(i); roots.add(parent); break; } } if (!subgrids.isEmpty()) { parent.setSubGrids(subgrids); } } else { roots.addAll(subgrids); } } switch (roots.size()) { case 0: throw new FactoryException(Errors.format(Errors.Keys.CanNotRead_1, file)); case 1: return roots.get(0); default: return DatumShiftGridGroup.create(file, roots); } }
Example #29
Source File: NADCON.java From sis with Apache License 2.0 | 4 votes |
/** * Returns the grid of the given name. This method returns the cached instance if it still exists, * or load the grid otherwise. * * @param latitudeShifts name of the grid file for latitude shifts. * @param longitudeShifts name of the grid file for longitude shifts. */ @SuppressWarnings("null") static DatumShiftGridFile<Angle,Angle> getOrLoad(final Path latitudeShifts, final Path longitudeShifts) throws FactoryException { final Path rlat = DataDirectory.DATUM_CHANGES.resolve(latitudeShifts).toAbsolutePath(); final Path rlon = DataDirectory.DATUM_CHANGES.resolve(longitudeShifts).toAbsolutePath(); final Object key = new AbstractMap.SimpleImmutableEntry<>(rlat, rlon); DatumShiftGridFile<?,?> grid = DatumShiftGridFile.CACHE.peek(key); if (grid == null) { final Cache.Handler<DatumShiftGridFile<?,?>> handler = DatumShiftGridFile.CACHE.lock(key); try { grid = handler.peek(); if (grid == null) { final Loader loader; Path file = latitudeShifts; try { // Note: buffer size must be divisible by the size of 'float' data type. final ByteBuffer buffer = ByteBuffer.allocate(4096).order(ByteOrder.LITTLE_ENDIAN); final FloatBuffer fb = buffer.asFloatBuffer(); try (ReadableByteChannel in = Files.newByteChannel(rlat)) { DatumShiftGridLoader.startLoading(NADCON.class, CharSequences.commonPrefix( latitudeShifts.toString(), longitudeShifts.toString()).toString() + '…'); loader = new Loader(in, buffer, file); loader.readGrid(fb, null, longitudeShifts); } buffer.clear(); file = longitudeShifts; try (ReadableByteChannel in = Files.newByteChannel(rlon)) { new Loader(in, buffer, file).readGrid(fb, loader, null); } } catch (IOException | NoninvertibleTransformException | RuntimeException e) { throw DatumShiftGridLoader.canNotLoad("NADCON", file, e); } grid = DatumShiftGridCompressed.compress(loader.grid, null, loader.grid.accuracy); grid = grid.useSharedData(); } } finally { handler.putAndUnlock(grid); } } return grid.castTo(Angle.class, Angle.class); }
Example #30
Source File: NTv2Test.java From sis with Apache License 2.0 | 4 votes |
/** * Tests using a file containing many grids. This tests depends on the {@value #MULTIGRID_TEST_FILE} * to be present in the {@code $SIS_DATA/DatumChanges} directory. This test is executed only if the * {@link #RUN_EXTENSIVE_TESTS} flag is set. * * @throws FactoryException if an error occurred while loading or computing the grid. * @throws TransformException if an error occurred while computing the envelope or testing the point. */ @Test public void testMultiGrids() throws FactoryException, TransformException { assumeTrue(RUN_EXTENSIVE_TESTS); final Path file = DataDirectory.DATUM_CHANGES.resolve(Paths.get(MULTIGRID_TEST_FILE)); assumeTrue(Files.exists(file)); final DatumShiftGridFile<Angle,Angle> grid = NTv2.getOrLoad(NTv2.class, file, 2); assertInstanceOf("Should contain many grids.", DatumShiftGridGroup.class, grid); assertEquals("coordinateUnit", Units.ARC_SECOND, grid.getCoordinateUnit()); assertEquals("translationUnit", Units.ARC_SECOND, grid.getTranslationUnit()); assertEquals("translationDimensions", 2, grid.getTranslationDimensions()); assertTrue ("isCellValueRatio", grid.isCellValueRatio()); /* * Area of use declared in EPSG database for coordinate operation EPSG::1693: * * 40.04°N to 83.17°N and 141.01°W to 47.74°W. * * In the assertions below, the `cellSize` value has been verified in the NTv2 * file header but the envelope bounds have been determined empirically. */ final double cellSize = 300; // Number of arc-seconds in a cell. final Envelope envelope = grid.getDomainOfValidity(); assertEquals("xmin", -142.25 * DEGREES_TO_SECONDS, envelope.getMinimum(0), 1E-10); assertEquals("xmax", -44.00 * DEGREES_TO_SECONDS, envelope.getMaximum(0), 1E-10); assertEquals("ymin", 40.00 * DEGREES_TO_SECONDS, envelope.getMinimum(1), 1E-10); assertEquals("ymax", 84.00 * DEGREES_TO_SECONDS, envelope.getMaximum(1), 1E-10); /* * Test a point. This point is located on the 3th grid in the NTv2 file. * Consequently if the NTv2 implementation just pickups the first grid, * then this test would fail with an error around 100 metres. */ final double[] position = {-134.998106062 * DEGREES_TO_SECONDS, 61.000285047 * DEGREES_TO_SECONDS}; final double[] expected = {-135.0 * DEGREES_TO_SECONDS, 61.0 * DEGREES_TO_SECONDS}; final double[] indices = new double[position.length]; grid.getCoordinateToGrid().transform(position, 0, indices, 0, 1); final int gridX = Math.toIntExact(Math.round(indices[0])); final int gridY = Math.toIntExact(Math.round(indices[1])); assertEquals("gridX", 1092, gridX); // Value determined empirically. assertEquals("gridY", 252, gridY); /* * First check the value computed by `getCellValue(…)`. This method is only a fallback and * should not be invoked in normal usage, so a direct invocation is the only way to test it. */ final double[] result = new double[] { position[0] - grid.getCellValue(0, gridX, gridY) * cellSize, // Positive translation is toward west. position[1] + grid.getCellValue(1, gridX, gridY) * cellSize }; assertArrayEquals("getCellValue", expected, result, 0.001); /* * Check `interpolateInCell(…)`, which is the method invoked by `InterpolatedTransform` * when `SpecializableTransform` has not been able to find the most appropriate grid. */ grid.interpolateInCell(indices[0], indices[1], result); result[0] = position[0] - result[0] * cellSize; // Positive translation is toward west. result[1] = position[1] + result[1] * cellSize; assertArrayEquals("interpolateInCell", expected, result, Formulas.ANGULAR_TOLERANCE * DEGREES_TO_SECONDS); /* * Verify that the caching mechanism works for DatumShiftGridGroup too. */ assertSame("Grid should be cached.", grid, NTv2.getOrLoad(NTv2.class, file, 2)); }