Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
JTS custom CoordinateSequence example
import com.vividsolutions.jts.geom._
import com.vividsolutions.jts.geom.impl.PackedCoordinateSequence
import com.vividsolutions.jts.geom.util.GeometryTransformer
* A custom CoordSequence based on byte arrays for compactness and speed
* Just 2 dimensions for now.
* It's an example of creating a custom CoordinateSequence.
* NOTE: This is much more memory efficient, but slower because of deserialization cost.
* To achieve both speed and memory efficiency, the JTS libraries need to be modified to stop
* relying on Coordinate[]'s and more of the other methods.
class ByteArrayCoordSequence(coords: Array[Coordinate]) extends XYReadOnlyCoordSequence {
val xArray: Array[Double] =
val yArray: Array[Double] =
def getCoordinate(i: Int): Coordinate =
new Coordinate(xArray(i), yArray(i))
// A mutable method to set the coordinate instance
def getCoordinate(i: Int, coord: Coordinate): Unit = {
coord.x = xArray(i)
coord.y = yArray(i)
def getX(i: Int): Double = xArray(i)
def getY(i: Int): Double = yArray(i)
def size(): Int = xArray.size
def expandEnvelope(env: Envelope): Envelope = {
env.expandToInclude(xArray.min, yArray.min)
env.expandToInclude(xArray.max, yArray.max)
trait XYReadOnlyCoordSequence extends CoordinateSequence {
def getCoordinate(i: Int): Coordinate
def getCoordinate(i: Int, coord: Coordinate): Unit
def getX(i: Int): Double
def getY(i: Int): Double
def size(): Int
def getDimension(): Int = 2
def getCoordinateCopy(i: Int): Coordinate = getCoordinate(i)
def getOrdinate(index: Int, ordinateIndex: Int): Double = {
require(ordinateIndex < 2, "only 2 dimensions!")
ordinateIndex match {
case 0 => getX(index)
case 1 => getY(index)
def setOrdinate(index: Int, ordinateIndex: Int, value: Double) = ???
def toCoordinateArray(): Array[Coordinate] =
(0 until size()).map(getCoordinate).toArray
object GeometryConverter {
// To easily transform another geometry to use our custom CoordinateSequence, do transformer.transform(geo)
val transformer = new GeometryTransformer {
override def transformCoordinates(coordSeq: CoordinateSequence, parent: Geometry): CoordinateSequence = {
new ByteArrayCoordSequence(coordSeq.toCoordinateArray)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.