Skip to content

Commit

Permalink
Spatial improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
darkfrog26 committed Nov 13, 2024
1 parent ee471a9 commit 796b56e
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 16 deletions.
3 changes: 3 additions & 0 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ val reactifyVersion: String = "4.1.2"

val spatial4JVersion: String = "0.8"

val jtsVersion: String = "1.20.0"

val haloDBVersion: String = "0.5.6"

val rocksDBVersion: String = "9.7.3"
Expand Down Expand Up @@ -108,6 +110,7 @@ lazy val core = crossProject(JVMPlatform) // TODO: Add JSPlatform and NativePlat
"org.typelevel" %%% "fabric-io" % fabricVersion,
"com.outr" %% "scribe-slf4j" % scribeVersion,
"org.locationtech.spatial4j" % "spatial4j" % spatial4JVersion,
"org.locationtech.jts" % "jts-core" % jtsVersion,
"org.scalatest" %%% "scalatest" % scalaTestVersion % Test
),
libraryDependencies ++= (
Expand Down
5 changes: 5 additions & 0 deletions core/src/main/scala/lightdb/spatial/Geo.scala
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ object Geo {
)
})

def parseMulti(json: Json): List[Geo] = parse(json) match {
case GeometryCollection(geometries) => geometries
case geo => List(geo)
}

def parse(json: Json): Geo = json("type").asString match {
case "Point" =>
val v = json("coordinates").asVector
Expand Down
42 changes: 26 additions & 16 deletions core/src/main/scala/lightdb/spatial/Spatial.scala
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
package lightdb.spatial

import lightdb.distance._
import org.locationtech.jts.geom.{Coordinate, Geometry, GeometryFactory, LineString, Polygon}
import org.locationtech.spatial4j.context.SpatialContext
import org.locationtech.spatial4j.context.jts.JtsSpatialContext
import org.locationtech.spatial4j.distance.DistanceUtils
import org.locationtech.spatial4j.shape
import org.locationtech.spatial4j.shape.Shape
import org.locationtech.spatial4j.shape.ShapeFactory.{LineStringBuilder, PolygonBuilder}
import org.locationtech.spatial4j.shape.jts.JtsGeometry

object Spatial {
private lazy val context = SpatialContext.GEO
private lazy val context = JtsSpatialContext.GEO
private lazy val factory = new GeometryFactory()

def distance(p1: Geo, p2: Geo): Distance = {
val point1 = context.getShapeFactory.pointLatLon(p1.center.latitude, p1.center.longitude)
Expand All @@ -28,24 +32,30 @@ object Spatial {
b.pointLatLon(p.latitude, p.longitude)
)

private def toShape(g: Geo): Shape = g match {
case Geo.Point(lat, lon) => context.getShapeFactory.pointLatLon(lat, lon)
case Geo.MultiPoint(points) => points.foldLeft(context.getShapeFactory.multiPoint())((b, p) =>
b.pointLatLon(p.latitude, p.longitude)
).build()
case line: Geo.Line => line2Builder(line).build()
case Geo.MultiLine(lines) => lines.foldLeft(context.getShapeFactory.multiLineString())((b, l) =>
b.add(line2Builder(l))
).build()
case polygon: Geo.Polygon => polygon2Builder(polygon).build()
case Geo.MultiPolygon(polygons) => polygons.foldLeft(context.getShapeFactory.multiPolygon())((b, p) =>
b.add(polygon2Builder(p))
).build()
private def toShape(g: Geo): Geometry = g match {
case Geo.Point(lat, lon) => factory.createPoint(new Coordinate(lon, lat))
case Geo.MultiPoint(points) =>
factory.createMultiPoint(points.map {
case Geo.Point(lat, lon) => factory.createPoint(new Coordinate(lon, lat))
case _ => throw new IllegalArgumentException("Invalid point in MultiPoint")
}.toArray)
case line: Geo.Line => factory.createLineString(line.points.map {
case Geo.Point(lat, lon) => new Coordinate(lon, lat)
}.toArray)
case Geo.MultiLine(lines) => factory.createMultiLineString(lines.map(toShape).map {
case l: LineString => l
}.toArray)
case polygon: Geo.Polygon => factory.createPolygon(polygon.points.map {
case Geo.Point(lat, lon) => new Coordinate(lon, lat)
}.toArray)
case Geo.MultiPolygon(polygons) => factory.createMultiPolygon(polygons.map(toShape).map {
case p: Polygon => p
}.toArray)
}

def relation(g1: Geo, g2: Geo): SpatialRelation = {
val s1 = toShape(g1)
val s2 = toShape(g2)
val s1 = new JtsGeometry(toShape(g1), context, false, false)
val s2 = new JtsGeometry(toShape(g2), context, false, false)
s1.relate(s2) match {
case shape.SpatialRelation.WITHIN => SpatialRelation.Within
case shape.SpatialRelation.CONTAINS => SpatialRelation.Contains
Expand Down

0 comments on commit 796b56e

Please sign in to comment.