Geospatial types

The driver comes with client-side representations of the DSE geospatial data types: Point, LineString and Polygon.

Usage in requests

Geospatial types can be retrieved from query results like any other value; use the “typed” getter that takes the class as a second argument:

// Schema: CREATE TABLE poi(id int PRIMARY KEY, location 'PointType', description text);

DseSession session = DseSession.builder().build()

Row row = session.execute("SELECT location FROM poi WHERE id = 1").one();
Point location = row.get(0, Point.class);

The corresponding setter can be used for insertions:

PreparedStatement pst =
    session.prepare("INSERT INTO poi (id, location, description) VALUES (?, ?, ?)");
session.execute(
    pst.boundStatementBuilder()
        .setInt("id", 2)
        .set("location", Point.fromCoordinates(2.2945, 48.8584), Point.class)
        .setString("description", "Eiffel Tower")
        .build());

This also works with the vararg syntax where target CQL types are inferred:

session.execute(pst.bind(2, Point.fromCoordinates(2.2945, 48.8584), "Eiffel Tower"));

Client-side API

The driver provides methods to create instances or inspect existing ones.

Point is a trivial pair of coordinates:

Point point = Point.fromCoordinates(2.2945, 48.8584);
System.out.println(point.X());
System.out.println(point.Y());

LineString is a series of 2 or more points:

LineString lineString =
    LineString.fromPoints(
        Point.fromCoordinates(30, 10),
        Point.fromCoordinates(10, 30),
        Point.fromCoordinates(40, 40));

for (Point point : lineString.getPoints()) {
  System.out.println(point);
}

Polygon is a planar surface in a two-dimensional XY-plane. You can build a simple polygon from a list of points:

Polygon polygon =
    Polygon.fromPoints(
        Point.fromCoordinates(30, 10),
        Point.fromCoordinates(10, 20),
        Point.fromCoordinates(20, 40),
        Point.fromCoordinates(40, 40));

In addition to its exterior boundary, a polygon can have an arbitrary number of interior rings, possibly nested (the first level defines “lakes” in the shape, the next level “islands” in those lakes, etc). To create such complex polygons, use the builder:

Polygon polygon =
    Polygon.builder()
        .addRing(
            Point.fromCoordinates(0, 0),
            Point.fromCoordinates(0, 3),
            Point.fromCoordinates(5, 3),
            Point.fromCoordinates(5, 0))
        .addRing(
            Point.fromCoordinates(1, 1),
            Point.fromCoordinates(1, 2),
            Point.fromCoordinates(2, 2),
            Point.fromCoordinates(2, 1))
        .addRing(
            Point.fromCoordinates(3, 1),
            Point.fromCoordinates(3, 2),
            Point.fromCoordinates(4, 2),
            Point.fromCoordinates(4, 1))
        .build();

You can then retrieve all the points with the following methods:

List<Point> exteriorRing = polygon.getExteriorRing();

for (List<Point> interiorRing : polygon.getInteriorRings()) {
  ...
}

Note that all rings (exterior or interior) are defined with the same builder method: you can provide them in any order, the implementation will figure out which is the exterior one. In addition, points are always ordered counterclockwise for the exterior ring, clockwise for the first interior level, counterclockwise for the second level, etc. Again, this is done automatically, so you don’t need to sort them beforehand; however, be prepared to get a different order when you read them back:

Polygon polygon =
    Polygon.fromPoints(
            // Clockwise:
            Point.fromCoordinates(0, 0),
            Point.fromCoordinates(0, 3),
            Point.fromCoordinates(5, 3),
            Point.fromCoordinates(5, 0));

System.out.println(polygon);
// Counterclockwise:
// POLYGON ((0 0, 5 0, 5 3, 0 3, 0 0))

All geospatial types interoperate with three standard formats:

  • Well-known text:

    Point point = Point.fromWellKnownText("POINT (0 1)");
    System.out.println(point.asWellKnownText());
    
  • Well-known binary:

    import com.datastax.oss.protocol.internal.util.Bytes;
    
    Point point =
        Point.fromWellKnownBinary(
            Bytes.fromHexString("0x01010000000000000000000000000000000000f03f"));
    System.out.println(Bytes.toHexString(point.asWellKnownBinary()));
    
  • GeoJSON:

    Point point = Point.fromGeoJson("{\"type\":\"Point\",\"coordinates\":[0.0,1.0]}");
    System.out.println(point.asGeoJson());