Skip to content

Commit e7ca4bf

Browse files
committed
add function to convert neo4j native point(s) to WKT format
1 parent 68a0859 commit e7ca4bf

File tree

5 files changed

+67
-3
lines changed

5 files changed

+67
-3
lines changed

src/main/java/org/neo4j/gis/spatial/Constants.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,4 +69,8 @@ public interface Constants {
6969
int GTYPE_MULTILINESTRING = 5;
7070
int GTYPE_MULTIPOLYGON = 6;
7171

72+
73+
int SRID_COORDINATES_2D = 4326;
74+
int SRID_COORDINATES_3D = 4979;
75+
7276
}

src/main/java/org/neo4j/gis/spatial/encoders/neo4j/Neo4jCRS.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
*/
2020
package org.neo4j.gis.spatial.encoders.neo4j;
2121

22+
import org.neo4j.gis.spatial.Constants;
2223
import org.neo4j.values.storable.CoordinateReferenceSystem;
2324

2425
public class Neo4jCRS implements org.neo4j.graphdb.spatial.CRS {
@@ -51,7 +52,7 @@ public int dimensions() {
5152
public static Neo4jCRS findCRS(String crs) {
5253
return switch (crs) { // name in Neo4j CRS table
5354
case "WGS-84", "WGS84(DD)" -> // name in geotools crs library
54-
makeCRS(4326);
55+
makeCRS(Constants.SRID_COORDINATES_2D);
5556
case "Cartesian" -> makeCRS(7203);
5657
default -> throw new IllegalArgumentException("Cypher type system does not support CRS: " + crs);
5758
};

src/main/java/org/neo4j/gis/spatial/functions/SpatialFunctions.java

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,18 @@
2020

2121
package org.neo4j.gis.spatial.functions;
2222

23+
import static org.neo4j.gis.spatial.Constants.SRID_COORDINATES_2D;
24+
import static org.neo4j.gis.spatial.Constants.SRID_COORDINATES_3D;
25+
26+
import java.util.Arrays;
27+
import java.util.Collection;
28+
import org.locationtech.jts.geom.Coordinate;
29+
import org.locationtech.jts.io.WKTWriter;
2330
import org.neo4j.gis.spatial.Layer;
2431
import org.neo4j.gis.spatial.procedures.SpatialProcedures.GeometryResult;
2532
import org.neo4j.gis.spatial.utilities.SpatialApiBase;
2633
import org.neo4j.graphdb.Node;
34+
import org.neo4j.graphdb.spatial.Point;
2735
import org.neo4j.procedure.Description;
2836
import org.neo4j.procedure.Name;
2937
import org.neo4j.procedure.UserFunction;
@@ -54,5 +62,38 @@ public Object asGeometry(@Name("geometry") Object geometry) {
5462
return toNeo4jGeometry(null, geometry);
5563
}
5664

65+
@UserFunction("spatial.convert.nativeToWkt")
66+
@Description("Converts a point or point array to WKT")
67+
public String nativeToWkt(@Name("data") Object object) {
68+
if (object instanceof Point point) {
69+
var coordinate = convertToCoordinate(point);
70+
return WKTWriter.toPoint(coordinate);
71+
}
72+
if (object instanceof Point[] points) {
73+
var coordinates = Arrays.stream(points).map(SpatialFunctions::convertToCoordinate)
74+
.toArray(Coordinate[]::new);
75+
return WKTWriter.toLineString(coordinates);
76+
}
77+
if (object instanceof Collection<?> points) {
78+
var coordinates = points.stream()
79+
.filter(Point.class::isInstance)
80+
.map(Point.class::cast)
81+
.map(SpatialFunctions::convertToCoordinate)
82+
.toArray(Coordinate[]::new);
83+
return WKTWriter.toLineString(coordinates);
84+
85+
}
86+
throw new IllegalArgumentException("Unsupported type: " + object.getClass());
87+
}
5788

89+
private static Coordinate convertToCoordinate(Point point) {
90+
double[] coordinate = point.getCoordinate().getCoordinate();
91+
if (point.getCRS().getCode() == SRID_COORDINATES_3D) {
92+
return new Coordinate(coordinate[0], coordinate[1], coordinate[2]);
93+
} else if (point.getCRS().getCode() == SRID_COORDINATES_2D) {
94+
return new Coordinate(coordinate[0], coordinate[1]);
95+
} else {
96+
throw new IllegalArgumentException("Unsupported CRS: " + point.getCRS().getCode());
97+
}
98+
}
5899
}

src/main/java/org/neo4j/gis/spatial/utilities/GeotoolsAdapter.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import org.geotools.api.referencing.crs.CoordinateReferenceSystem;
2828
import org.geotools.referencing.CRS;
2929
import org.geotools.referencing.ReferencingFactoryFinder;
30+
import org.neo4j.gis.spatial.Constants;
3031
import org.neo4j.gis.spatial.SpatialDatabaseException;
3132

3233
/**
@@ -54,8 +55,8 @@ public static CoordinateReferenceSystem getCRS(String crsText) {
5455

5556
public static Integer getEPSGCode(CoordinateReferenceSystem crs) {
5657
try {
57-
// TODO: upgrade geotools to avoid Java11 failures on CRS.lookupEpsgCode
58-
return (crs == WGS84) ? Integer.valueOf(4326) : (crs == GENERIC_2D) ? null : CRS.lookupEpsgCode(crs, true);
58+
return (crs == WGS84) ? Integer.valueOf(Constants.SRID_COORDINATES_2D)
59+
: (crs == GENERIC_2D) ? null : CRS.lookupEpsgCode(crs, true);
5960
} catch (FactoryException e) {
6061
System.err.println("Failed to lookup CRS: " + e.getMessage());
6162
return null;

src/test/java/org/neo4j/gis/spatial/functions/SpatialFunctionsTest.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@
2020

2121
package org.neo4j.gis.spatial.functions;
2222

23+
import static org.hamcrest.MatcherAssert.assertThat;
2324
import static org.hamcrest.Matchers.closeTo;
25+
import static org.hamcrest.Matchers.equalTo;
2426
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
2527

2628
import java.util.Map;
@@ -69,4 +71,19 @@ public void literal_geometry_return() {
6971
"WITH spatial.asGeometry({latitude: 5.0, longitude: 4.0}) AS geometry RETURN geometry", "geometry");
7072
assertInstanceOf(Geometry.class, geometry, "Should be Geometry type");
7173
}
74+
75+
@Test
76+
public void testPointToWkt() {
77+
Object wkt = executeObject("return spatial.convert.nativeToWkt(point({longitude: 1, latitude: 2})) as wkt",
78+
"wkt");
79+
assertThat(wkt, equalTo("POINT ( 1 2 )"));
80+
}
81+
82+
@Test
83+
public void testPointArrayToWkt() {
84+
Object wkt = executeObject(
85+
"return spatial.convert.nativeToWkt([point({longitude: 1, latitude: 2}), point({longitude: 3, latitude: 4}) ]) as wkt",
86+
"wkt");
87+
assertThat(wkt, equalTo("LINESTRING (1 2, 3 4)"));
88+
}
7289
}

0 commit comments

Comments
 (0)