final boolean isUTM = φ >= TransverseMercator.Zoner.SOUTH_BOUNDS && φ < TransverseMercator.Zoner.NORTH_BOUNDS; final int zone = isUTM ? ZONER.zone(φ, λ) : POLE; final int signedZone = MathFunctions.isNegative(φ) ? -zone : zone; if (signedZone == 0) {
final boolean isUTM = latitude >= TransverseMercator.Zoner.SOUTH_BOUNDS && latitude < TransverseMercator.Zoner.NORTH_BOUNDS; final int zone = isUTM ? TransverseMercator.Zoner.UTM.zone(latitude, longitude) : POLAR; final Integer key = isSouth ? -zone : zone; ProjectedCRS crs;
final boolean isUTM = latitude >= TransverseMercator.Zoner.SOUTH_BOUNDS && latitude < TransverseMercator.Zoner.NORTH_BOUNDS; final int zone = isUTM ? TransverseMercator.Zoner.UTM.zone(latitude, longitude) : POLAR; final Integer key = isSouth ? -zone : zone; ProjectedCRS crs;
int zoneError = ZONER.zone(φ, λ) - zone; if (zoneError != 0) { final int zc = ZONER.zoneCount();
case 42002: isUTM = (latitude == 0) && (Zoner.UTM.centralMeridian(Zoner.UTM.zone(0, longitude)) == longitude); break; case 42003: method = "Orthographic"; param = Constants.LATITUDE_OF_ORIGIN; break; case 42004: method = "Equirectangular"; param = Constants.STANDARD_PARALLEL_1; break;
case 42002: isUTM = (latitude == 0) && (Zoner.UTM.centralMeridian(Zoner.UTM.zone(0, longitude)) == longitude); break; case 42003: method = "Orthographic"; param = Constants.LATITUDE_OF_ORIGIN; break; case 42004: method = "Equirectangular"; param = Constants.STANDARD_PARALLEL_1; break;
final OperationMethod method = projection.getMethod(); if (IdentifiedObjects.isHeuristicMatchForName(method, TransverseMercator.NAME)) { crsZone = ZONER.zone(projection.getParameterValues()); } else if (IdentifiedObjects.isHeuristicMatchForName(method, PolarStereographicA.NAME)) { crsZone = POLE * PolarStereographicA.isUPS(projection.getParameterValues());
int zone = zone(latitude, longitude); String name; if (this == ANY) {
int zone = zone(latitude, longitude); String name; if (this == ANY) {
/** * If the given parameter values are those of a zoned projection, returns the zone number (negative if South). * Otherwise returns 0. It is caller's responsibility to verify that the operation method is {@value #NAME}. * * @param group the Transverse Mercator projection parameters. * @return zone number (positive if North, negative if South), * or 0 if the given parameters are not for a zoned projection. */ public final int zone(final ParameterValueGroup group) { if (Numerics.epsilonEqual(group.parameter(Constants.SCALE_FACTOR) .doubleValue(Units.UNITY), scale, Numerics.COMPARISON_THRESHOLD) && Numerics.epsilonEqual(group.parameter(Constants.FALSE_EASTING) .doubleValue(Units.METRE), easting, Formulas.LINEAR_TOLERANCE) && Numerics.epsilonEqual(group.parameter(Constants.LATITUDE_OF_ORIGIN).doubleValue(Units.DEGREE), 0, Formulas.ANGULAR_TOLERANCE)) { double v = group.parameter(Constants.FALSE_NORTHING).doubleValue(Units.METRE); final boolean isNorth = Numerics.epsilonEqual(v, 0, Formulas.LINEAR_TOLERANCE); if (isNorth || Numerics.epsilonEqual(v, northing, Formulas.LINEAR_TOLERANCE)) { v = group.parameter(Constants.CENTRAL_MERIDIAN).doubleValue(Units.DEGREE); int zone = zone(0, v); if (Numerics.epsilonEqual(centralMeridian(zone), v, Formulas.ANGULAR_TOLERANCE)) { if (!isNorth) zone = -zone; return zone; } } } return 0; }
/** * If the given parameter values are those of a zoned projection, returns the zone number (negative if South). * Otherwise returns 0. It is caller's responsibility to verify that the operation method is {@value #NAME}. * * @param group the Transverse Mercator projection parameters. * @return zone number (positive if North, negative if South), * or 0 if the given parameters are not for a zoned projection. */ public final int zone(final ParameterValueGroup group) { if (Numerics.epsilonEqual(group.parameter(Constants.SCALE_FACTOR) .doubleValue(Units.UNITY), scale, Numerics.COMPARISON_THRESHOLD) && Numerics.epsilonEqual(group.parameter(Constants.FALSE_EASTING) .doubleValue(Units.METRE), easting, Formulas.LINEAR_TOLERANCE) && Numerics.epsilonEqual(group.parameter(Constants.LATITUDE_OF_ORIGIN).doubleValue(Units.DEGREE), 0, Formulas.ANGULAR_TOLERANCE)) { double v = group.parameter(Constants.FALSE_NORTHING).doubleValue(Units.METRE); final boolean isNorth = Numerics.epsilonEqual(v, 0, Formulas.LINEAR_TOLERANCE); if (isNorth || Numerics.epsilonEqual(v, northing, Formulas.LINEAR_TOLERANCE)) { v = group.parameter(Constants.CENTRAL_MERIDIAN).doubleValue(Units.DEGREE); int zone = zone(0, v); if (Numerics.epsilonEqual(centralMeridian(zone), v, Formulas.ANGULAR_TOLERANCE)) { if (!isNorth) zone = -zone; return zone; } } } return 0; }
/** * Tests {@link TransverseMercator.Zoner#setParameters(ParameterValueGroup, double, double)} * followed by {@link TransverseMercator.Zoner#zone(ParameterValueGroup)}. */ @Test @DependsOnMethod({ "testZone", "testCentralMeridian" }) public void testSetParameters() { final ParameterValueGroup p = TransverseMercator.PARAMETERS.createValue(); assertEquals("UTM zone 10N", TransverseMercator.Zoner.UTM.setParameters(p, 0, -122)); assertEquals(Constants.CENTRAL_MERIDIAN, -123, p.parameter(Constants.CENTRAL_MERIDIAN).doubleValue(), STRICT); assertEquals(Constants.FALSE_NORTHING, 0, p.parameter(Constants.FALSE_NORTHING).doubleValue(), STRICT); assertEquals("UTM.zone(parameters)", 10, TransverseMercator.Zoner.UTM.zone(p)); assertEquals("Transverse Mercator", TransverseMercator.Zoner.ANY.setParameters(p, 0, -122)); assertEquals(Constants.CENTRAL_MERIDIAN, -122, p.parameter(Constants.CENTRAL_MERIDIAN).doubleValue(), STRICT); assertEquals(Constants.FALSE_NORTHING, 0, p.parameter(Constants.FALSE_NORTHING).doubleValue(), STRICT); assertEquals("UTM.zone(parameters)", 0, TransverseMercator.Zoner.UTM.zone(p)); assertEquals("UTM zone 10S", TransverseMercator.Zoner.ANY.setParameters(p, -0.0, -123)); assertEquals(Constants.CENTRAL_MERIDIAN, -123, p.parameter(Constants.CENTRAL_MERIDIAN).doubleValue(), STRICT); assertEquals(Constants.FALSE_NORTHING, 10000000, p.parameter(Constants.FALSE_NORTHING).doubleValue(), STRICT); assertEquals("UTM.zone(parameters)", -10, TransverseMercator.Zoner.UTM.zone(p)); } }
/** Computes the zone from a meridian in the zone. */ @Override public int zone(final double φ, final double λ) { int zone = super.zone(φ, λ); switch (zone) { /* * Between 56° and 64°, zone 32 is widened to 9° at the expense of zone 31 to accommodate Norway. * Between 72° and 84°, zones 33 and 35 are widened to 12° to accommodate Svalbard. To compensate, * zones 31 and 37 are widened to 9° and zones 32, 34, and 36 are eliminated. * In this switch statement, only the zones that are reduced or eliminated needs to appear. */ case 31: if (isNorway (φ)) {if (λ >= 3) zone++; } break; // 3° is zone 31 central meridian. case 32: if (isSvalbard(φ)) {if (λ >= 9) zone++; else zone--;} break; // 9° is zone 32 central meridian. case 34: if (isSvalbard(φ)) {if (λ >= 21) zone++; else zone--;} break; // 21° is zone 34 central meridian. case 36: if (isSvalbard(φ)) {if (λ >= 33) zone++; else zone--;} break; // 33° is zone 36 central meridian. } return zone; }
/** Computes the zone from a meridian in the zone. */ @Override public int zone(final double φ, final double λ) { int zone = super.zone(φ, λ); switch (zone) { /* * Between 56° and 64°, zone 32 is widened to 9° at the expense of zone 31 to accommodate Norway. * Between 72° and 84°, zones 33 and 35 are widened to 12° to accommodate Svalbard. To compensate, * zones 31 and 37 are widened to 9° and zones 32, 34, and 36 are eliminated. * In this switch statement, only the zones that are reduced or eliminated needs to appear. */ case 31: if (isNorway (φ)) {if (λ >= 3) zone++; } break; // 3° is zone 31 central meridian. case 32: if (isSvalbard(φ)) {if (λ >= 9) zone++; else zone--;} break; // 9° is zone 32 central meridian. case 34: if (isSvalbard(φ)) {if (λ >= 21) zone++; else zone--;} break; // 21° is zone 34 central meridian. case 36: if (isSvalbard(φ)) {if (λ >= 33) zone++; else zone--;} break; // 33° is zone 36 central meridian. } return zone; }
/** * Tests {@link TransverseMercator.Zoner#zone(double, double)}, * including the special cases for Norway and Svalbard. */ @Test public void testZone() { assertEquals("180°E", 1, TransverseMercator.Zoner.UTM.zone( 0, -180 )); assertEquals("123°E", 10, TransverseMercator.Zoner.UTM.zone( 0, -123 )); assertEquals("179.9°W", 60, TransverseMercator.Zoner.UTM.zone( 0, 179.9)); assertEquals( "4°E band T", 31, TransverseMercator.Zoner.UTM.zone(45, 4 )); assertEquals( "4°E band V", 32, TransverseMercator.Zoner.UTM.zone(56, 4 )); assertEquals("20°E band W", 34, TransverseMercator.Zoner.UTM.zone(71, 20 )); assertEquals("20°E band X", 33, TransverseMercator.Zoner.UTM.zone(72, 20 )); }
/** Indicates whether the given geographic area intersects the regions that need to be handled in a special way. */ @Override public boolean isSpecialCase(final double φmin, final double φmax, final double λmin, final double λmax) { if (φmax >= NORWAY_BOUNDS && φmin < NORTH_BOUNDS) { return super.zone(0, λmax) >= 31 && super.zone(0, λmin) <= 37; } return false; } },
/** Indicates whether the given geographic area intersects the regions that need to be handled in a special way. */ @Override public boolean isSpecialCase(final double φmin, final double φmax, final double λmin, final double λmax) { if (φmax >= NORWAY_BOUNDS && φmin < NORTH_BOUNDS) { return super.zone(0, λmax) >= 31 && super.zone(0, λmin) <= 37; } return false; } },