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.
*
*
* Modified Transverse Mercator parameters
@@ -220,8 +220,8 @@ public final class TransverseMercator ex
* 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);
}
}