Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 3EBB5200C1A for ; Mon, 13 Feb 2017 17:11:51 +0100 (CET) Received: by cust-asf.ponee.io (Postfix) id 3CF44160B4D; Mon, 13 Feb 2017 16:11:51 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id E06C1160B60 for ; Mon, 13 Feb 2017 17:11:49 +0100 (CET) Received: (qmail 48014 invoked by uid 500); 13 Feb 2017 16:11:49 -0000 Mailing-List: contact commits-help@sis.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: sis-dev@sis.apache.org Delivered-To: mailing list commits@sis.apache.org Received: (qmail 47994 invoked by uid 99); 13 Feb 2017 16:11:48 -0000 Received: from Unknown (HELO svn01-us-west.apache.org) (209.188.14.144) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 13 Feb 2017 16:11:48 +0000 Received: from svn01-us-west.apache.org (localhost [127.0.0.1]) by svn01-us-west.apache.org (ASF Mail Server at svn01-us-west.apache.org) with ESMTP id 323433A0316 for ; Mon, 13 Feb 2017 16:11:48 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Subject: svn commit: r1782798 - in /sis/branches/JDK8: core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/ core/sis-referencing/src/main/java/org/apache/sis/referencing/ core/sis-referencing/src/main/java/org/apache/sis/referencing/... Date: Mon, 13 Feb 2017 16:11:48 -0000 To: commits@sis.apache.org From: desruisseaux@apache.org X-Mailer: svnmailer-1.0.9 Message-Id: <20170213161148.323433A0316@svn01-us-west.apache.org> archived-at: Mon, 13 Feb 2017 16:11:51 -0000 Author: desruisseaux Date: Mon Feb 13 16:11:47 2017 New Revision: 1782798 URL: http://svn.apache.org/viewvc?rev=1782798&view=rev Log: Begin a skeleton of "referencing by geographic identifiers" package, using MGRS as a first system. Added: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/gazetteer/ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/gazetteer/MGRSEncoder.java (with props) sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/gazetteer/MilitaryGridReferenceSystem.java (with props) sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/gazetteer/package-info.java - copied, changed from r1782301, sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/index/package-info.java sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/gazetteer/ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/gazetteer/MGRSEncoderTest.java (with props) sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/gazetteer/MilitaryGridReferenceSystemTest.java (with props) Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/TransverseMercator.java sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/package-info.java sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java sis/branches/JDK8/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/GeoTiffStore.java sis/branches/JDK8/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/ImageFileDirectory.java sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/index/GeoHashCoder.java Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/TransverseMercator.java URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/TransverseMercator.java?rev=1782798&r1=1782797&r2=1782798&view=diff ============================================================================== --- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/TransverseMercator.java [UTF-8] (original) +++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/TransverseMercator.java [UTF-8] Mon Feb 13 16:11:47 2017 @@ -157,7 +157,7 @@ public final class TransverseMercator ex /** * Computes zones for the Modified Transverse Mercator (MTM) projections. - * This projection is in used in Canada only. + * This projection is used in Canada only. * *
* @@ -220,8 +220,8 @@ public final class TransverseMercator ex * * * - * - * + * + * * *
Modified Transverse Mercator parameters
Parameter name Value
Latitude of natural origin Given latitude, or 0° if zoned projection
Longitude of natural origin Given longitude, optionally snapped to a zone central meridian
Scale factor at natural origin 0.9996
False easting 500000 metres
Scale factor at natural origin 0.9996 for UTM or 0.9999 for MTM
False easting 500000 metres for UTM or 304800 metres for MTM
False northing 0 (North hemisphere) or 10000000 (South hemisphere) metres
* @@ -232,7 +232,7 @@ public final class TransverseMercator ex * @return a name like "Transverse Mercator" or "UTM zone 10N", * depending on the arguments given to this method. */ - public String setParameters(final ParameterValueGroup group, + public final String setParameters(final ParameterValueGroup group, final boolean zoned, double latitude, double longitude) { final boolean isSouth = MathFunctions.isNegative(latitude); @@ -256,14 +256,14 @@ public final class TransverseMercator ex } /** - * If the given parameter values are those of an UTM projection, returns the zone number (negative if South). + * 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 UTM zone number (positive if North, negative if South), - * or 0 if the given parameters are not for a UTM projection. + * @return zone number (positive if North, negative if South), + * or 0 if the given parameters are not for a zoned projection. */ - public int zone(final ParameterValueGroup group) { + 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)) @@ -283,13 +283,13 @@ public final class TransverseMercator ex } /** - * Computes the UTM zone from a meridian in the zone. + * Computes the zone from a meridian in the zone. * * @param longitude a meridian inside the desired zone, in degrees relative to Greenwich. * Positive longitudes are toward east, and negative longitudes toward west. - * @return the UTM zone number numbered from 1 to 60 inclusive, or 0 if the given central meridian was NaN. + * @return the zone number numbered from 1 inclusive, or 0 if the given central meridian was NaN. */ - public int zone(double longitude) { + public final int zone(double longitude) { /* * Casts to int are equivalent to Math.floor(double) for positive values, which is guaranteed * to be the case here since we normalize the central meridian to the [MIN_VALUE … MAX_VALUE] range. @@ -301,12 +301,12 @@ public final class TransverseMercator ex } /** - * Computes the central meridian of a given UTM zone. + * Computes the central meridian of a given zone. * - * @param zone the UTM zone as a number in the [1 … 60] range. - * @return the central meridian of the given UTM zone. + * @param zone the zone as a number starting with 1. + * @return the central meridian of the given zone. */ - public double centralMeridian(final int zone) { + public final double centralMeridian(final int zone) { return (zone - 0.5) * width + origin; } } Added: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/gazetteer/MGRSEncoder.java URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/gazetteer/MGRSEncoder.java?rev=1782798&view=auto ============================================================================== --- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/gazetteer/MGRSEncoder.java (added) +++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/gazetteer/MGRSEncoder.java [UTF-8] Mon Feb 13 16:11:47 2017 @@ -0,0 +1,258 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.sis.referencing.gazetteer; + +import org.opengis.util.FactoryException; +import org.opengis.geometry.DirectPosition; +import org.opengis.referencing.crs.CoordinateReferenceSystem; +import org.opengis.referencing.crs.ProjectedCRS; +import org.opengis.referencing.operation.Projection; +import org.opengis.referencing.operation.OperationMethod; +import org.opengis.referencing.operation.MathTransform; +import org.opengis.referencing.operation.TransformException; +import org.apache.sis.internal.referencing.provider.TransverseMercator; +import org.apache.sis.referencing.crs.DefaultGeographicCRS; +import org.apache.sis.referencing.crs.DefaultProjectedCRS; +import org.apache.sis.referencing.cs.AxesConvention; +import org.apache.sis.referencing.IdentifiedObjects; +import org.apache.sis.referencing.CRS; +import org.apache.sis.util.resources.Errors; + + +/** + * Conversions from direct positions to Military Grid Reference System (MGRS) labels. + * Each {@code MGRSEncoder} instance is configured for one {@code DirectPosition} CRS. + * If a position is given in another CRS, another {@code MGRSEncoder} instance must be created. + * + *
Immutability and thread safety
+ * This class is not thread-safe. A new instance must be created for each thread, + * or synchronization must be applied by the caller. + * + * @author Martin Desruisseaux (Geomatys) + * @since 0.8 + * @version 0.8 + * @module + * + * @see Military Grid Reference System on Wikipedia + */ +final class MGRSEncoder { + /** + * Height of latitude bands, in degrees. + * Those bands are labeled from {@code 'C'} to {@code 'X'} inclusive, excluding {@code 'I'} and {@code 'O'}. + */ + private static final double LATITUDE_BAND_HEIGHT = 8; + + /** + * Southernmost bound of the first latitude band ({@code 'C'}). + */ + private static final double UTM_SOUTH_BOUNDS = -80; + + /** + * Northernmost bound of the last latitude band ({@code 'X'}). + */ + private static final double UTM_NORTH_BOUNDS = 84; + + /** + * Size of the 100,000-meter squares. + */ + private static final double GRID_SQUARE_SIZE = 100_000; + + /** + * UTM zone of position CRS (negative for South hemisphere), or 0 if that CRS is not an UTM projection. + * Note that this is not necessarily the same zone than the one to use for formatting any given coordinate + * in that projected CRS, since the {@link #zone(double, char)} method has special rules for some latitudes. + */ + private int crsZone; + + /** + * Coordinate conversion from the position CRS to a CRS of the same type but with normalized axes. + * Axis directions are (East, North) and axis units are metres or degrees, depending on the CRS type. + */ + private MathTransform toNormalized; + + /** + * Coordinate conversion from the normalized position CRS to a normalized geographic CRS. + * Axis directions are (East, North) and axis units are degrees. + */ + private MathTransform toGeographic; + + /** + * Creates a new converter from direct positions to MGRS labels. + */ + MGRSEncoder(final CoordinateReferenceSystem crs) throws FactoryException, TransformException { + if (crs == null) { + throw new IllegalArgumentException(Errors.format(Errors.Keys.UnspecifiedCRS)); + } + if (crs instanceof ProjectedCRS) { + Projection projection = ((ProjectedCRS) crs).getConversionFromBase(); + final OperationMethod method = projection.getMethod(); + if (IdentifiedObjects.isHeuristicMatchForName(method, TransverseMercator.NAME)) { + crsZone = TransverseMercator.Zoner.UTM.zone(projection.getParameterValues()); + if (crsZone != 0) { + /* + * Usually, the projected CRS already has (E,N) axis orientations with metres units, + * so we let 'toNormalized' to null. In the rarer cases where the CRS axes do not + * have the expected orientations and units, then we build a normalized version of + * that CRS and compute the transformation to that CRS. + */ + DefaultProjectedCRS normalized = DefaultProjectedCRS.castOrCopy((ProjectedCRS) crs); + if (normalized != (normalized = normalized.forConvention(AxesConvention.NORMALIZED))) { + toNormalized = CRS.findOperation(crs, normalized, null).getMathTransform(); + projection = normalized.getConversionFromBase(); + } + /* + * We will also need the transformation from the normalized projected CRS to longitude + * and latitude (in that order) in degrees. We can get this transform directly from the + * projected CRS if its base CRS already has the expected axis orientations and units. + */ + DefaultGeographicCRS geographic = DefaultGeographicCRS.castOrCopy(normalized.getBaseCRS()); + if (geographic != (geographic = geographic.forConvention(AxesConvention.NORMALIZED))) { + toGeographic = CRS.findOperation(normalized, geographic, null).getMathTransform(); + } else { + toGeographic = projection.getMathTransform().inverse(); + } + } + } + } + } + + /** + * Returns the band letter for the given latitude. It is caller responsibility to ensure that the + * given latitude is between {@value #UTM_SOUTH_BOUNDS} and {@value #UTM_NORTH_BOUNDS} inclusive. + * The returned letter will be one of {@code "CDEFGHJKLMNPQRSTUVWX"} (note that I and O letters + * are excluded). All bands are 8° height except the X band which is 12° height. + * + * @param φ the latitude in degrees for which to get the band letter. + * @return the band letter for the given latitude. + */ + static char latitudeBand(final double φ) { + int band = 'C' + (int) ((φ - UTM_SOUTH_BOUNDS) / LATITUDE_BAND_HEIGHT); + if (band >= 'N') { + if (band == 'W') { + band++; // Because the last latitude band ('X') is 12° height instead of 8°. + } else { + band += 2; + } + } else if (band >= 'I') { + band++; + } + return (char) band; + } + + /** + * Computes the UTM zone for the given longitude and latitude band. + * Those zones are normally the same than UTM, except for Norway and + * Svalbard which have special rules. + * + * @param zone the value of {@code TransverseMercator.Zoner.UTM.zone(λ)}. + * @param band the latitude band computed by {@link #latitudeBand(double)}. + * @param λ the longitude for which to compute the UTM zone. + * @return the UTM zone for the given longitude. + */ + static int zone(int zone, final double λ, final char band) { + switch (band) { + /* + * Zone 32 has been widened to 9° (at the expense of zone 31) + * between latitudes 56° and 64° to accommodate southwest Norway. + */ + case 'V': { + if (zone == 31 && λ >= 3) zone++; // 3° is the central meridian of zone 31. + break; + } + /* + * Between 72° and 84°, zones 33 and 35 have been widened to 12° to accommodate Svalbard. + * To compensate for these 12° wide zones, zones 31 and 37 are widened to 9° and zones 32, + * 34, and 36 are eliminated. + */ + case 'X': { + switch (zone) { + case 32: if (λ >= 9) zone++; else zone--; break; // 9° is zone 32 central meridian. + case 34: if (λ >= 21) zone++; else zone--; break; // 21° is zone 34 central meridian. + case 36: if (λ >= 33) zone++; else zone--; break; // 33° is zone 36 central meridian. + } + break; + } + } + return zone; + } + + /** + * Encodes the given position into a MGRS label. It is caller responsibility to ensure that the + * position CRS is the same than the CRS specified at this {@code MGRSEncoder} creation time. + * + * @param position the direct position to format as a MGRS label. + * @param precision the precision as a power of 10. + * @param buffer where to format the direct position. + */ + void encode(DirectPosition position, final double precision, final StringBuilder buffer) throws TransformException { + if (toNormalized != null) { + position = toNormalized.transform(position, null); + } + final DirectPosition geographic; + if (crsZone != 0) { + geographic = toGeographic.transform(position, null); + final double φ = geographic.getOrdinate(1); + if (φ >= UTM_SOUTH_BOUNDS && φ <= UTM_NORTH_BOUNDS) { + final char band = latitudeBand(φ); + final double λ = geographic.getOrdinate(0); + final int utmZone = TransverseMercator.Zoner.UTM.zone(λ); + final int zone = zone(utmZone, λ, band); + if (zone != crsZone) { + // TODO: reproject + throw new IllegalArgumentException(); + } + buffer.append(zone).append(band); + /* + * Columns in zone 1 are A-H, zone 2 are J-R (skipping O), zone 3 are S-Z, + * then repeating every 3 zones. The zone number shall not take in account + * the special cases done by the zone(…) method. + */ + final double x = position.getOrdinate(0); + final double y = position.getOrdinate(1); + final double cx = Math.floor(x / GRID_SQUARE_SIZE); + final double cy = Math.floor(y / GRID_SQUARE_SIZE); + int col = (int) cx; + if (col < 0 || col >= 8) { + throw new IllegalArgumentException("UTM coordinates out of range"); // TODO: localize + } + switch (utmZone % 3) { + case 0: col += 'A'; break; + case 1: col += 'J'; if (col >= 'O') col++; break; + case 2: col += 'S'; break; + } + /* + * Rows in even zones are ABCDEFGHJKLMNPQRSTUV + * Rows in odd zones are FGHJKLMNPQRSTUVABCDE + * Those 20 letters are repeated in a cycle. + */ + int row = (int) cy; + if ((zone & 1) != 0) { + row += ('F' - 'A'); + } + row = 'A' + (row % 20); + if (row >= 'N') row += 2; + else if (row >= 'I') row++; + buffer.append((char) col).append((char) row); + /* + * Numerical location at the given precision. + */ + final int rx = (int) Math.floor((x - cx * GRID_SQUARE_SIZE) / precision); + final int ry = (int) Math.floor((y - cy * GRID_SQUARE_SIZE) / precision); + } + } + } +} Propchange: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/gazetteer/MGRSEncoder.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/gazetteer/MGRSEncoder.java ------------------------------------------------------------------------------ svn:mime-type = text/plain;charset=UTF-8 Added: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/gazetteer/MilitaryGridReferenceSystem.java URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/gazetteer/MilitaryGridReferenceSystem.java?rev=1782798&view=auto ============================================================================== --- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/gazetteer/MilitaryGridReferenceSystem.java (added) +++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/gazetteer/MilitaryGridReferenceSystem.java [UTF-8] Mon Feb 13 16:11:47 2017 @@ -0,0 +1,128 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.sis.referencing.gazetteer; + +import java.util.Map; +import java.text.ParseException; +import java.util.IdentityHashMap; +import java.util.ConcurrentModificationException; +import org.opengis.util.FactoryException; +import org.opengis.geometry.DirectPosition; +import org.opengis.referencing.crs.CoordinateReferenceSystem; +import org.opengis.referencing.operation.TransformException; +import org.apache.sis.util.ArgumentChecks; + + +/** + * The Military Grid Reference System (MGRS). + * The MGRS is the geocoordinate standard used by NATO militaries for locating points on the earth. + * It is based on the Universal Transverse Mercator (UTM) and the polar stereographic projections. + * + *
Immutability and thread safety
+ * This class is immutable and thus thread-safe. However the {@code Coder} performing conversions + * between labels and coordinates are not thread-safe; a new instance must be created for each thread. + * + * @author Martin Desruisseaux (Geomatys) + * @since 0.8 + * @version 0.8 + * @module + * + * @see Military Grid Reference System on Wikipedia + */ +public class MilitaryGridReferenceSystem { + /** + * Creates a new Military Grid Reference System (MGRS). + */ + public MilitaryGridReferenceSystem() { + } + + /** + * Conversions between direct positions and labels in the Military Grid Reference System (MGRS). + * Each {@code Coder} instance can read labels at arbitrary precision, but formats at the + * {@linkplain #setPrecision specified precision}. + * + *
Immutability and thread safety
+ * This class is not thread-safe. A new instance must be created for each thread, + * or synchronization must be applied by the caller. + * + * @author Martin Desruisseaux (Geomatys) + * @since 0.8 + * @version 0.8 + * @module + */ + public static class Coder { + /** + * The precision as a power of 10. + */ + private double precision; + + /** + * Cached information needed for building a MGRS label from a direct position in the given CRS. + */ + private final Map encoders; + + /** + * A buffer where to create label, to be reused for each new label. + */ + private final StringBuilder buffer; + + /** + * Creates a new coder initialized to the default precision. + */ + public Coder() { + precision = 1; // 1 meter precision. + buffer = new StringBuilder(12); // Length of "4QFJ12345678" sample value. + encoders = new IdentityHashMap<>(); + } + + /** + * Encodes the given position into a MGRS label. + * The given position must have a CRS associated to it. + * + * @param position the coordinate to encode. + * @return MGRS encoding of the given position. + * @throws TransformException if an error occurred while transforming the given coordinate to a MGRS label. + */ + public String encode(final DirectPosition position) throws TransformException { + ArgumentChecks.ensureNonNull("position", position); + final CoordinateReferenceSystem crs = position.getCoordinateReferenceSystem(); + MGRSEncoder encoder = encoders.get(crs); + if (encoder == null) try { + encoder = new MGRSEncoder(crs); + if (encoders.put(crs, encoder) != null) { + throw new ConcurrentModificationException(); // Opportunistic check. + } + } catch (FactoryException e) { + throw new TransformException(e.toString(), e); + } + buffer.setLength(0); + encoder.encode(position, precision, buffer); + return buffer.toString(); + } + + /** + * Decodes the given MGRS label into a position. + * + * @param label MGRS string to decode. + * @return a new position with the longitude at ordinate 0 and latitude at ordinate 1. + * @throws ParseException if an error occurred while parsing the given string. + */ + public DirectPosition decode(final String label) throws ParseException { + return null; + } + } +} Propchange: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/gazetteer/MilitaryGridReferenceSystem.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/gazetteer/MilitaryGridReferenceSystem.java ------------------------------------------------------------------------------ svn:mime-type = text/plain;charset=UTF-8 Copied: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/gazetteer/package-info.java (from r1782301, sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/index/package-info.java) URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/gazetteer/package-info.java?p2=sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/gazetteer/package-info.java&p1=sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/index/package-info.java&r1=1782301&r2=1782798&rev=1782798&view=diff ============================================================================== --- sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/index/package-info.java [UTF-8] (original) +++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/gazetteer/package-info.java [UTF-8] Mon Feb 13 16:11:47 2017 @@ -17,6 +17,16 @@ /** - * Computes geohash strings from geographic coordinates, and conversely. + * Directory mapping geographic identifiers to locations, either as descriptions or coordinates. + * Geographic identifiers are location descriptors such as addresses and grid indexes. + * Their reference systems are defined by Spatial referencing by geographic identifiers (ISO 19112). + * Gazetteers provide linking mechanism between referencing using geographic identifiers (this package) + * and referencing using coordinates ({@link org.apache.sis.referencing.crs} package). + * + * @author Chris Mattmann (JPL) + * @author Martin Desruisseaux (Geomatys) + * @since 0.8 + * @version 0.8 + * @module */ -package org.apache.sis.index; +package org.apache.sis.referencing.gazetteer; Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/package-info.java URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/package-info.java?rev=1782798&r1=1782797&r2=1782798&view=diff ============================================================================== --- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/package-info.java [UTF-8] (original) +++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/package-info.java [UTF-8] Mon Feb 13 16:11:47 2017 @@ -23,7 +23,13 @@ *

The most commonly used kinds of Reference Systems in Apache SIS are the Coordinate Reference Systems * (CRS), which handle coordinates of arbitrary dimensions. The SIS implementations can handle 2D and 3D coordinates, * as well as 4D, 5D, etc. An other less-frequently used kind of Reference System uses labels instead, as in - * postal address. This package is the root for both kinds, with an emphasis on the one for coordinates.

+ * postal address. This package is the root for both kinds, with an emphasis on the one for coordinates. + * The two kinds of referencing system are implemented in the following packages:

+ *
    + *
  • {@link org.apache.sis.referencing.crs} for referencing by coordinates (ISO 19111)
  • + *
  • {@link org.apache.sis.referencing.gazetteer} for referencing by geographic identifiers + * (ISO 19112), together with the linking from geographic identifiers to coordinates.
  • + *
* *
Fetching geodetic object instances
* Geodetic objects can be instantiated either Added: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/gazetteer/MGRSEncoderTest.java URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/gazetteer/MGRSEncoderTest.java?rev=1782798&view=auto ============================================================================== --- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/gazetteer/MGRSEncoderTest.java (added) +++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/gazetteer/MGRSEncoderTest.java [UTF-8] Mon Feb 13 16:11:47 2017 @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.sis.referencing.gazetteer; + +import org.apache.sis.test.TestCase; +import org.junit.Test; + +import static org.junit.Assert.*; +import static org.apache.sis.internal.referencing.provider.TransverseMercator.Zoner.UTM; + + +/** + * Tests {@link MGRSEncoder}. + * + * @author Martin Desruisseaux (Geomatys) + * @since 0.8 + * @version 0.8 + * @module + */ +public final strictfp class MGRSEncoderTest extends TestCase { + /** + * Tests {@link MGRSEncoder#latitudeBand(double)}. + */ + @Test + public void testLatitudeBand() { + assertEquals("80°S", 'C', MGRSEncoder.latitudeBand(-80)); + assertEquals("55°N", 'U', MGRSEncoder.latitudeBand( 55)); + assertEquals("56°N", 'V', MGRSEncoder.latitudeBand( 56)); + assertEquals("63°N", 'V', MGRSEncoder.latitudeBand( 63)); + assertEquals("64°N", 'W', MGRSEncoder.latitudeBand( 64)); + assertEquals("71°N", 'W', MGRSEncoder.latitudeBand( 71)); + assertEquals("72°N", 'X', MGRSEncoder.latitudeBand( 72)); + assertEquals("84°N", 'X', MGRSEncoder.latitudeBand( 84)); + } + + /** + * Tests {@link MGRSEncoder#zone(double, char)}. + */ + @Test + public void testZone() { + assertEquals( "4°E band T", 31, MGRSEncoder.zone(UTM.zone( 4), 4, 'T')); + assertEquals( "4°E band V", 32, MGRSEncoder.zone(UTM.zone( 4), 4, 'V')); + assertEquals("20°E band W", 34, MGRSEncoder.zone(UTM.zone(20), 20, 'W')); + assertEquals("20°E band X", 33, MGRSEncoder.zone(UTM.zone(20), 20, 'X')); + } +} Propchange: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/gazetteer/MGRSEncoderTest.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/gazetteer/MGRSEncoderTest.java ------------------------------------------------------------------------------ svn:mime-type = text/plain;charset=UTF-8 Added: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/gazetteer/MilitaryGridReferenceSystemTest.java URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/gazetteer/MilitaryGridReferenceSystemTest.java?rev=1782798&view=auto ============================================================================== --- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/gazetteer/MilitaryGridReferenceSystemTest.java (added) +++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/gazetteer/MilitaryGridReferenceSystemTest.java [UTF-8] Mon Feb 13 16:11:47 2017 @@ -0,0 +1,53 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.sis.referencing.gazetteer; + +import org.apache.sis.geometry.DirectPosition2D; +import org.apache.sis.referencing.CommonCRS; +import org.apache.sis.test.DependsOn; +import org.apache.sis.test.TestCase; +import org.junit.Test; + +import static org.junit.Assert.*; +import org.opengis.referencing.operation.TransformException; + + +/** + * Tests {@link MilitaryGridReferenceSystem}. + * + * @author Martin Desruisseaux (Geomatys) + * @since 0.8 + * @version 0.8 + * @module + */ +@DependsOn(MGRSEncoderTest.class) +public final strictfp class MilitaryGridReferenceSystemTest extends TestCase { + /** + * Tests encoding of coordinates. + * + * @throws TransformException if an error occurred while computing the MGRS label. + */ + @Test + @org.junit.Ignore + public void testEncoding() throws TransformException { + final MilitaryGridReferenceSystem.Coder coder = new MilitaryGridReferenceSystem.Coder(); + final DirectPosition2D position = new DirectPosition2D(CommonCRS.WGS84.UTM(13, 103)); + position.x = 377299; + position.y = 1483035; + assertEquals("48PUV7729883034", coder.encode(position)); + } +} Propchange: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/gazetteer/MilitaryGridReferenceSystemTest.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/gazetteer/MilitaryGridReferenceSystemTest.java ------------------------------------------------------------------------------ svn:mime-type = text/plain;charset=UTF-8 Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java?rev=1782798&r1=1782797&r2=1782798&view=diff ============================================================================== --- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java [UTF-8] (original) +++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java [UTF-8] Mon Feb 13 16:11:47 2017 @@ -244,6 +244,10 @@ import org.junit.BeforeClass; org.apache.sis.distance.LatLonPointRadiusTest.class, // Pending refactoring in a geometry package. + // Referencing by identifiers + org.apache.sis.referencing.gazetteer.MGRSEncoderTest.class, + org.apache.sis.referencing.gazetteer.MilitaryGridReferenceSystemTest.class, + org.apache.sis.test.integration.DatumShiftTest.class, org.apache.sis.test.integration.MetadataTest.class, org.apache.sis.test.integration.ConsistencyTest.class Modified: sis/branches/JDK8/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/GeoTiffStore.java URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/GeoTiffStore.java?rev=1782798&r1=1782797&r2=1782798&view=diff ============================================================================== --- sis/branches/JDK8/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/GeoTiffStore.java [UTF-8] (original) +++ sis/branches/JDK8/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/GeoTiffStore.java [UTF-8] Mon Feb 13 16:11:47 2017 @@ -43,6 +43,7 @@ import org.apache.sis.util.resources.Err * * @author Rémi Maréchal (Geomatys) * @author Martin Desruisseaux (Geomatys) + * @author Thi Phuong Hao Nguyen (VNSC) * @since 0.8 * @version 0.8 * @module Modified: sis/branches/JDK8/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/ImageFileDirectory.java URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/ImageFileDirectory.java?rev=1782798&r1=1782797&r2=1782798&view=diff ============================================================================== --- sis/branches/JDK8/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/ImageFileDirectory.java [UTF-8] (original) +++ sis/branches/JDK8/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/ImageFileDirectory.java [UTF-8] Mon Feb 13 16:11:47 2017 @@ -43,6 +43,7 @@ import org.apache.sis.measure.Units; * @author Rémi Marechal (Geomatys) * @author Alexis Manin (Geomatys) * @author Johann Sorel (Geomatys) + * @author Thi Phuong Hao Nguyen (VNSC) * @author Martin Desruisseaux (Geomatys) * @since 0.8 * @version 0.8 Modified: sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/index/GeoHashCoder.java URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/index/GeoHashCoder.java?rev=1782798&r1=1782797&r2=1782798&view=diff ============================================================================== --- sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/index/GeoHashCoder.java [UTF-8] (original) +++ sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/index/GeoHashCoder.java [UTF-8] Mon Feb 13 16:11:47 2017 @@ -19,7 +19,9 @@ package org.apache.sis.index; import java.io.Serializable; import java.text.ParseException; import org.opengis.geometry.DirectPosition; +import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.apache.sis.geometry.DirectPosition2D; +import org.apache.sis.referencing.CommonCRS; import org.apache.sis.util.ArgumentChecks; import org.apache.sis.util.resources.Errors; @@ -32,7 +34,7 @@ import org.apache.sis.util.resources.Err * * @author Chris Mattmann (JPL) * @since 0.1 - * @version 0.3 + * @version 0.8 * @module * * @see Wikipedia: Geohash @@ -124,11 +126,18 @@ public class GeoHashCoder implements Ser private transient char[] buffer; /** + * The coordinate reference system to assign to the decoded direct positions, + * or {@code null} if none. + */ + private final CoordinateReferenceSystem crs; + + /** * Creates a new geohash coder/decoder initialized to the default precision for {@link Format#BASE32}. */ public GeoHashCoder() { format = Format.BASE32; precision = 12; + crs = CommonCRS.defaultGeographic(); } /** @@ -164,7 +173,7 @@ public class GeoHashCoder implements Ser /** * Sets the length of geohashes strings to be encoded by the {@link #encode(DirectPosition)} method. * - * @param precision he new length of geohashes strings. + * @param precision the new length of geohashes strings. */ public void setPrecision(final int precision) { ArgumentChecks.ensureBetween("precision", 1, 255, precision); @@ -250,7 +259,7 @@ public class GeoHashCoder implements Ser /** * Decodes the given geohash into a longitude and a latitude. * - * @param geohash Geohash string to decode. + * @param geohash geohash string to decode. * @return a new position with the longitude at ordinate 0 and latitude at ordinate 1. * @throws ParseException if an error occurred while parsing the given string. */ @@ -307,7 +316,7 @@ public class GeoHashCoder implements Ser isEven = !isEven; } while ((mask >>>= 1) != 0); } - return new DirectPosition2D((xmin + xmax) / 2, - (ymin + ymax) / 2); + return new DirectPosition2D(crs, (xmin + xmax) / 2, + (ymin + ymax) / 2); } }