Skip to content

Commit e4402dc

Browse files
committed
Add wrappers for Projected CRS and Coordinate Operation.
Test the transform of a point from geographic to projected CRS.
1 parent 644c104 commit e4402dc

16 files changed

+2142
-30
lines changed

geoapi/src/main/java/org/locationtech/proj4j/geoapi/AbstractCRS.java

+17-12
Original file line numberDiff line numberDiff line change
@@ -28,21 +28,20 @@
2828

2929
/**
3030
* Wraps a PROJ4J implementation behind the equivalent GeoAPI interface.
31-
* The CRS is assumed two-dimensional.
3231
*
3332
* @author Martin Desruisseaux (Geomatys)
3433
*/
3534
@SuppressWarnings("serial")
3635
abstract class AbstractCRS extends Wrapper implements SingleCRS, CoordinateSystem, Serializable {
3736
/**
38-
* The number of dimensions of the CRS.
37+
* The wrapped PROJ4 implementation.
3938
*/
40-
private static final int BIDIMENSIONAL = 2;
39+
final org.locationtech.proj4j.CoordinateReferenceSystem impl;
4140

4241
/**
43-
* The wrapped PROJ4 implementation.
42+
* Whether this CRS is three-dimensional instead of two-dimensional.
4443
*/
45-
private final org.locationtech.proj4j.CoordinateReferenceSystem impl;
44+
final boolean is3D;
4645

4746
/**
4847
* The coordinate system axes, computed and cached when first requested.
@@ -55,23 +54,29 @@ abstract class AbstractCRS extends Wrapper implements SingleCRS, CoordinateSyste
5554
/**
5655
* Creates a new wrapper for the given PROJ4J implementation.
5756
*/
58-
AbstractCRS(final org.locationtech.proj4j.CoordinateReferenceSystem impl) {
57+
AbstractCRS(final org.locationtech.proj4j.CoordinateReferenceSystem impl, final boolean is3D) {
5958
this.impl = impl;
59+
this.is3D = is3D;
6060
}
6161

6262
/**
6363
* Wraps the given implementation.
6464
*
6565
* @param impl the implementation to wrap, or {@code null}
66+
* @param is3D whether to return a three-dimensional CRS instead of a two-dimensional one
6667
* @return the wrapper, or {@code null} if the given implementation was null
6768
*/
68-
static AbstractCRS wrap(final org.locationtech.proj4j.CoordinateReferenceSystem impl) {
69+
static AbstractCRS wrap(final org.locationtech.proj4j.CoordinateReferenceSystem impl, final boolean is3D) {
6970
if (impl != null) {
7071
final Projection proj = impl.getProjection();
7172
if (proj == null || proj.isGeographic()) {
72-
return new GeographicCRSWrapper(impl);
73+
return new GeographicCRSWrapper(impl, is3D);
7374
} else {
74-
// TODO
75+
/*
76+
* TODO: there is a possibility that the PROJ4J `projection` is actually for something
77+
* else than a map projection. But there is apparently no easy way to determine that.
78+
*/
79+
return new ProjectedCRSWrapper(impl, is3D);
7580
}
7681
}
7782
return null;
@@ -111,11 +116,11 @@ public CoordinateSystem getCoordinateSystem() {
111116
}
112117

113118
/**
114-
* {@return the number of dimensions, which is fixed to 2}.
119+
* {@return the number of dimensions, which is 2 or 3}.
115120
*/
116121
@Override
117122
public final int getDimension() {
118-
return BIDIMENSIONAL;
123+
return is3D ? TRIDIMENSIONAL : BIDIMENSIONAL;
119124
}
120125

121126
/**
@@ -147,7 +152,7 @@ public final CoordinateSystemAxis getAxis(int dimension) {
147152
Axis[] axes = this.axes;
148153
if (axes == null) {
149154
final Axis[] axesForAllDirections = axesForAllDirections();
150-
axes = Arrays.copyOfRange(axesForAllDirections, Axis.INDEX_OF_EAST, axesForAllDirections.length);
155+
axes = Arrays.copyOfRange(axesForAllDirections, Axis.INDEX_OF_EAST, Axis.INDEX_OF_EAST + getDimension());
151156
final Projection proj = impl.getProjection();
152157
if (proj != null) {
153158
final AxisOrder order = proj.getAxisOrder();

geoapi/src/main/java/org/locationtech/proj4j/geoapi/GeographicCRSWrapper.java

+2-3
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121

2222
/**
2323
* Wraps a PROJ4J implementation behind the equivalent GeoAPI interface.
24-
* The CRS is assumed two-dimensional.
2524
*
2625
* @author Martin Desruisseaux (Geomatys)
2726
*/
@@ -30,8 +29,8 @@ final class GeographicCRSWrapper extends AbstractCRS implements EllipsoidalCS, G
3029
/**
3130
* Creates a new wrapper for the given PROJ4J implementation.
3231
*/
33-
GeographicCRSWrapper(final org.locationtech.proj4j.CoordinateReferenceSystem impl) {
34-
super(impl);
32+
GeographicCRSWrapper(org.locationtech.proj4j.CoordinateReferenceSystem impl, boolean is3D) {
33+
super(impl, is3D);
3534
}
3635

3736
/**
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
/*
2+
* Copyright 2025, PROJ4J contributors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.locationtech.proj4j.geoapi;
17+
18+
import java.util.Collections;
19+
import java.util.Set;
20+
import org.opengis.referencing.ReferenceIdentifier;
21+
22+
23+
/**
24+
* A simple EPSG identifier made of only a code and a code space.
25+
*
26+
* @author Martin Desruisseaux (Geomatys)
27+
*/
28+
final class IdentifierEPSG extends Wrapper {
29+
/**
30+
* The EPSG code.
31+
*/
32+
private final int code;
33+
34+
/**
35+
* Creates a new identifier for the given EPSG code.
36+
*/
37+
private IdentifierEPSG(final int code) {
38+
this.code = code;
39+
}
40+
41+
/**
42+
* Wraps the given EPSG code.
43+
*
44+
* @param code the EPSG code, or 0 if none
45+
* @return the wrapper, or an empty set if the given EPSG code was 0
46+
*/
47+
static Set<ReferenceIdentifier> wrap(final int code) {
48+
return (code != 0) ? Collections.singleton(new IdentifierEPSG(code)) : Collections.emptySet();
49+
}
50+
51+
/**
52+
* {@return the EPSG code}.
53+
*/
54+
@Override
55+
Object implementation() {
56+
return code;
57+
}
58+
59+
/**
60+
* {@return the code space, which is fixed to "EPSG"}.
61+
*/
62+
@Override
63+
public String getCodeSpace() {
64+
return "EPSG";
65+
}
66+
67+
/**
68+
* {@return the string representation of the EPSG code}.
69+
*/
70+
@Override
71+
public String getCode() {
72+
return Integer.toString(code);
73+
}
74+
75+
/**
76+
* {@return the string representation of this identifier}.
77+
*/
78+
@Override
79+
public String toString() {
80+
return getCodeSpace() + ':' + code;
81+
}
82+
}

0 commit comments

Comments
 (0)