Skip to content

Commit

Permalink
Work-around for bad spatial data
Browse files Browse the repository at this point in the history
  • Loading branch information
darkfrog26 committed Nov 16, 2024
1 parent decbe6c commit 8691f8f
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 8 deletions.
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,8 @@ libraryDependencies += "com.outr" %% "lightdb-all" % "0.15.0"
For a specific implementation like Lucene:
```scala
libraryDependencies += "com.outr" %% "lightdb-lucene" % "0.15.0"
```
```

## Videos
OKC JUG Presentation
https://www.youtube.com/watch?v=E_5fwgbF4rc
16 changes: 11 additions & 5 deletions core/src/main/scala/lightdb/spatial/Geo.scala
Original file line number Diff line number Diff line change
Expand Up @@ -49,24 +49,24 @@ object Geo {

def parse(json: Json): Geo = json("type").asString match {
case "Point" =>
val v = json("coordinates").asVector
Geo.Point(latitude = v(1).asDouble, longitude = v(0).asDouble)
val v = json("coordinates").asVector.map(_.asDouble)
Geo.Point(latitude = v(1).asDouble, longitude = v(0).asDouble).fixed
case "LineString" => Line(
json("coordinates").asVector.toList.map { p =>
val v = p.asVector
Geo.Point(latitude = v(1).asDouble, longitude = v(0).asDouble)
Geo.Point(latitude = v(1).asDouble, longitude = v(0).asDouble).fixed
}
)
case "Polygon" => Polygon(
json("coordinates").asVector.head.asVector.toList.map { p =>
val v = p.asVector
Geo.Point(latitude = v(1).asDouble, longitude = v(0).asDouble)
Geo.Point(latitude = v(1).asDouble, longitude = v(0).asDouble).fixed
}
)
case "MultiPolygon" => MultiPolygon(
json("coordinates").asVector.toList.map { p =>
p.asVector.head.asVector.toList.map(_.asVector.toList).map { v =>
Geo.Point(latitude = v(1).asDouble, longitude = v(0).asDouble)
Geo.Point(latitude = v(1).asDouble, longitude = v(0).asDouble).fixed
}
}.map(list => Polygon(list))
)
Expand Down Expand Up @@ -98,6 +98,12 @@ object Geo {

case class Point(latitude: Double, longitude: Double) extends Geo {
override def center: Point = this

def fixed: Point = if (latitude < -90.0 || latitude > 90.0) {
Point(longitude, latitude)
} else {
this
}
}
case class MultiPoint(points: List[Point]) extends Geo {
lazy val center: Point = Geo.center(points)
Expand Down
13 changes: 13 additions & 0 deletions core/src/test/scala/spec/AbstractSpatialSpec.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package spec

import fabric.io.JsonParser
import fabric.rw._
import lightdb.collection.Collection
import lightdb.distance._
Expand Down Expand Up @@ -111,6 +112,18 @@ abstract class AbstractSpatialSpec extends AnyWordSpec with Matchers { spec =>
))
}
}
"parse and insert from a GeometryCollection" in {
DB.people.transaction { implicit transaction =>
val json = JsonParser("""{"crs": {"type": "name", "properties": {"name": "urn:ogc:def:crs:EPSG::4269"}}, "type": "GeometryCollection", "geometries": [{"type": "LineString", "coordinates": [[-103.79558, 32.30492], [-103.793467263, 32.331700182]]}]}""")
val geo = Geo.parseMulti(json)
DB.people.insert(Person(
name = "Baby Dole",
age = 2,
point = yonkers,
geo = geo
))
}
}
"truncate the database" in {
DB.truncate()
}
Expand Down
12 changes: 10 additions & 2 deletions lucene/src/main/scala/lightdb/lucene/LuceneStore.scala
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,17 @@ class LuceneStore[Doc <: Document[Doc], Model <: DocumentModel[Doc]](directory:
field.className match {
case Some("lightdb.spatial.Geo.Point") =>
val p = json.as[Geo.Point]
add(new LatLonPoint(field.name, p.latitude, p.longitude))
try {
add(new LatLonPoint(field.name, p.latitude, p.longitude))
} catch {
case t: Throwable => throw new RuntimeException(s"Failed to add LatLonPoint(${field.name}, ${p.latitude}, ${p.longitude}): ${JsonFormatter.Default(json)}", t)
}
case _ =>
def indexPoint(p: Geo.Point): Unit = LatLonShape.createIndexableFields(field.name, p.latitude, p.longitude)
def indexPoint(p: Geo.Point): Unit = try {
LatLonShape.createIndexableFields(field.name, p.latitude, p.longitude)
} catch {
case t: Throwable => throw new RuntimeException(s"Failed to add LatLonPoint.createIndexableFields(${field.name}, ${p.latitude}, ${p.longitude}): ${JsonFormatter.Default(json)}", t)
}
def indexLine(l: Geo.Line): Unit = {
val line = new Line(l.points.map(_.latitude).toArray, l.points.map(_.longitude).toArray)
LatLonShape.createIndexableFields(field.name, line)
Expand Down

0 comments on commit 8691f8f

Please sign in to comment.