-
Notifications
You must be signed in to change notification settings - Fork 15
/
TransformPoints.java
170 lines (162 loc) · 8.47 KB
/
TransformPoints.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
/*
* Copyright © 2019-2021 Agency for Data Supply and Efficiency
* Copyright © 2021 Open Source Geospatial Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
import org.opengis.metadata.extent.Extent;
import org.opengis.metadata.extent.GeographicExtent;
import org.opengis.metadata.extent.GeographicBoundingBox;
import org.opengis.metadata.quality.PositionalAccuracy;
import org.opengis.metadata.quality.Result;
import org.opengis.referencing.crs.CRSAuthorityFactory;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.CoordinateOperation;
import org.opengis.referencing.operation.CoordinateOperationFactory;
import org.opengis.referencing.operation.TransformException;
import org.opengis.util.FactoryException;
import org.osgeo.proj.Proj;
/**
* An example of code transforming a few points from one
* Coordinate Reference System (CRS) to another one.
*/
public class TransformPoints {
/**
* The factory to use for creating Coordinate Reference Systems (CRS) from EPSG codes.
* For performance reasons, this instance should be fetched only at initialization time
* and reused as long as necessary.
*
* Note: this interface will become {@code RegisterOperations} in a future version.
*/
private final CRSAuthorityFactory factory;
/**
* The factory to use for inferring an operation between two Coordinate Reference Systems.
* For performance reasons, this instance should be fetched only at initialization time
* and reused as long as necessary.
*
* Note: this interface will become {@code RegisterOperations} in a future version.
*/
private final CoordinateOperationFactory regops;
/**
* Creates a new instance which will use PROJ factories for Coordinate Reference Systems and operations.
*/
private TransformPoints() {
factory = Proj.getAuthorityFactory("EPSG");
regops = Proj.getOperationFactory(null);
}
/**
* Projects the geographic coordinates of a few cities and prints the results.
* The target Coordinate Reference System (CRS) is given in argument.
*
* @param target the EPSG code of target CRS. Example: "3395" for "WGS 84 / World Mercator".
* @throws FactoryException if an error occurred while creating a CRS or inferring the coordinate operation.
* @throws TransformException if an error occurred while applying the operation on coordinate values.
*/
private void printCoordinates(String target) throws FactoryException, TransformException {
CoordinateReferenceSystem sourceCRS = factory.createCoordinateReferenceSystem("4326"); // WGS 84
CoordinateReferenceSystem targetCRS = factory.createCoordinateReferenceSystem(target);
CoordinateOperation operation = regops.createOperation(sourceCRS, targetCRS);
describe(operation);
double[] coordinates = {
45.500, -73.567, // Montreal
49.250, -123.100, // Vancouver
35.653, 139.839, // Tokyo
48.865, 2.349 // Paris
};
operation.getMathTransform().transform(
coordinates, 0, // Source coordinates.
coordinates, 0, // Target coordinates (in this case, overwrite sources).
4); // Number of points to transform.
System.out.printf("Montreal: %11.1f %11.1f%n", coordinates[0], coordinates[1]);
System.out.printf("Vancouver: %11.1f %11.1f%n", coordinates[2], coordinates[3]);
System.out.printf("Tokyo: %11.1f %11.1f%n", coordinates[4], coordinates[5]);
System.out.printf("Paris: %11.1f %11.1f%n", coordinates[6], coordinates[7]);
}
/**
* Prints a description of the given coordinate operation, in particular its domain of validity
* and accuracy. It is user's responsibility to ensure that the coordinates to transform are in
* the domain of validity.
*
* @param operation the coordinate operation to describe.
*/
private static void describe(CoordinateOperation operation) {
String name = operation.getName().getCode();
System.out.printf("The coordinate operation is: %s%n", name);
Extent extent = operation.getDomainOfValidity();
if (extent != null) {
/*
* The extent may have horizontal, vertical and temporal components. In this example we take only
* the horizontal components, and only the ones that are bounding boxes (other types are bounding
* polygons and plain text descriptions). Those bounds are easy to use for checking coordinate
* validity before transformation.
*/
for (GeographicExtent ge : extent.getGeographicElements()) {
if (ge instanceof GeographicBoundingBox) {
final GeographicBoundingBox bbox = (GeographicBoundingBox) ge;
System.out.printf("Its domain of validity is:%n"
+ " West bound longitude: %6.1f%n"
+ " East bound longitude: %6.1f%n"
+ " South bound latitude: %6.1f%n"
+ " North bound latitude: %6.1f%n",
bbox.getWestBoundLongitude(),
bbox.getEastBoundLongitude(),
bbox.getSouthBoundLatitude(),
bbox.getNorthBoundLatitude());
}
}
}
/*
* The way to get accuracy is a bit inconvenient and depends on whether the accuracy is only a
* description or is a quantitative measurement. The reason for this inconvenience is that the
* quality API is designed for describing the quality of a wide range of phenomenons, not only
* coordinate operations. Developers are encouraged to write their own convenience methods for
* their needs.
*/
for (PositionalAccuracy accuracy : operation.getCoordinateOperationAccuracy()) {
for (Result result : accuracy.getResults()) {
/*
* Result can be QuantitativeResult or ConformanceResult among others.
* For now we just print it.
*/
System.out.printf("Accuracy is: %s%n", result);
}
}
System.out.println();
}
/**
* Projects the geographic coordinates of a few cities and prints the results.
* The target Coordinate Reference Systems (CRS) are given in argument.
* More than once CRS may be specified.
*
* @param args the EPSG code of target CRS. Example: "3395" for "WGS 84 / World Mercator".
* @throws FactoryException if an error occurred while creating a CRS or inferring the coordinate operation.
* @throws TransformException if an error occurred while applying the operation on coordinate values.
*/
public static void main(String[] args) throws FactoryException, TransformException {
if (args.length == 0) {
args = new String[] {"3395"};
System.out.println("No EPSG code given. Default to 3395 (WGS 84 / World Mercator).");
}
TransformPoints transformer = new TransformPoints();
for (String target : args) {
transformer.printCoordinates(target);
System.out.println();
}
}
}