Skip to content

Instantly share code, notes, and snippets.

@velvia
Created March 2, 2015 18:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save velvia/69ca1ab5e758d3b0ab13 to your computer and use it in GitHub Desktop.
Save velvia/69ca1ab5e758d3b0ab13 to your computer and use it in GitHub Desktop.
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] = coords.map(_.x)
val yArray: Array[Double] = coords.map(_.y)
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)
env
}
}
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