Skip to content

Commit 8d935c4

Browse files
committed
Charting and some tweaks to rendering API
1 parent 7640a02 commit 8d935c4

File tree

10 files changed

+185
-48
lines changed

10 files changed

+185
-48
lines changed

geoscript/build.sbt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ libraryDependencies <++= gtVersion { v =>
88
"org.geotools" % "gt-render" % v,
99
"org.geotools" % "gt-xml" % v,
1010
"org.geotools" % "gt-geojson" % v,
11+
"org.geotools" % "gt-charts" % v,
1112
"org.geotools.jdbc" % "gt-jdbc-postgis" % v,
1213
"org.geotools.jdbc" % "gt-jdbc-spatialite" % v
1314
)

geoscript/src/main/scala/Converters.scala

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ package object geoscript {
55
import layer._
66
import workspace._
77
import render._
8-
import projection.{ Projection, RichProjection }
8+
import projection.{ Projection, RichProjection, Projectable, Referenced }
99

1010
implicit def enrichGeometry(g: Geometry): RichGeometry =
1111
new RichGeometry(g)
@@ -37,4 +37,11 @@ package object geoscript {
3737

3838
implicit def enrichProjection(p: Projection): RichProjection =
3939
new RichProjection(p)
40+
41+
class RichProjectable[P : Projectable](p: P) {
42+
def in(proj: Projection): Referenced[P] = Referenced(p, proj)
43+
def lift: Option[Referenced[P]] = implicitly[Projectable[P]].lift(p)
44+
}
45+
46+
implicit def enrichProjectable[P : Projectable](p: P) = new RichProjectable(p)
4047
}

geoscript/src/main/scala/geometry/Geometry.scala

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,50 @@ class RichGeometry(geometry: Geometry) {
99
*/
1010
def area: Double = geometry.getArea()
1111

12+
/**
13+
* A symbolic alias for the union operation
14+
*/
15+
def ||(that: Geometry): Geometry = geometry union that
16+
17+
/**
18+
* A symbolic alias for the intersection operation
19+
*/
20+
def &&(that: Geometry): Geometry = geometry intersection that
21+
1222
/**
1323
* A jts.Envelope that fully encloses this Geometry.
1424
*/
15-
def envelope: Envelope = geometry.getEnvelopeInternal() // in projection
25+
def envelope: Envelope = geometry.getEnvelopeInternal()
1626

1727
/**
1828
* A point that represents the "center of gravity" of this geometry's
1929
* enclosed area. Note that this point is not necessarily on the geometry!
2030
*/
21-
def centroid: Point = geometry.getCentroid() // in projection
31+
def centroid: Point = geometry.getCentroid()
2232

2333
/**
2434
* All the coordinates that compose this Geometry as a sequence.
2535
*/
2636
def coordinates: Seq[Coordinate] = geometry.getCoordinates().toSeq
2737

38+
/**
39+
* prepare creates a PreparedGeometry instance, which requires more time to
40+
* construct but has faster implementations of several operations including
41+
* `contains`, `coveredBy`, `covers`, `crosses`, `disjoint`,
42+
* `intersects`, `overlaps`, `touches`, and `within`
43+
*
44+
* Typically, this would be used when one geometry is being compared against
45+
* many others.
46+
*
47+
* {{{
48+
* (needle: Geometry, haystack: Geometry) => {
49+
* val p = needle.prepared
50+
* haystack.filter(p.contains(_))
51+
* }
52+
* }}}
53+
*/
54+
def prepare = preparingFactory.create(geometry)
55+
2856
/**
2957
* The length of the line segments that compose this geometry, in the same
3058
* units as used by its coordinates.

geoscript/src/main/scala/geometry/io/package.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package org.geoscript.geometry
22

33
import org.geoscript.serialize._
4+
import org.geotools.geojson.geom.GeometryJSON
45

56
object WKT extends Format[Geometry] {
67
private val reader = new com.vividsolutions.jts.io.WKTReader()
@@ -23,7 +24,6 @@ object WKB extends Codec[Geometry] {
2324
}
2425
}
2526

26-
import org.geotools.geojson.geom.GeometryJSON
2727
class GeoJSON(format: GeometryJSON) extends Format[Geometry] {
2828
def this(precision: Int) = this(new GeometryJSON(precision))
2929

geoscript/src/main/scala/geometry/package.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package object geometry {
1919
val EmptyEnvelope = new jts.Envelope
2020

2121
val factory = new jts.GeometryFactory
22+
protected[geometry] val preparingFactory = new jts.prep.PreparedGeometryFactory
2223

2324
def union(a: Envelope, b: Envelope): Envelope =
2425
if (a.isNull) b

geoscript/src/main/scala/projection/Projectable.scala

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,32 @@ package org.geoscript
22
package projection
33

44
import geometry._
5-
import org.geotools.geometry.jts.JTS
5+
import org.geotools.geometry.jts.{ JTS, ReferencedEnvelope }
66

77
trait Projectable[T] {
8+
def extractProjection(t: T): Option[Projection]
9+
def lift(t: T): Option[Referenced[T]] =
10+
extractProjection(t).map(Referenced(t, _)(this))
811
def project(from: Projection, to: Projection)(t: T): T
912
}
1013

1114
object Projectable {
1215
implicit def geometriesAreProjectable[T <: Geometry]:
1316
Projectable[T] = new Projectable[T] {
17+
def extractProjection(t: T): Option[Projection] =
18+
if (t.getSRID > 0)
19+
fromSrid("EPSG:" + t.getSRID)
20+
else
21+
None
22+
1423
def project(from: Projection, to: Projection)(t: T): T =
1524
JTS.transform(t, transform(from, to)).asInstanceOf[T]
1625
}
1726

1827
implicit def envelopesAreProjectable: Projectable[Envelope] =
1928
new Projectable[Envelope] {
29+
def extractProjection(e: Envelope): Option[Projection] = None
30+
2031
def project(from: Projection, to: Projection)(e: Envelope) =
2132
JTS.transform(e, transform(from, to))
2233
}

geoscript/src/main/scala/projection/Projection.scala

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,15 @@ package object projection {
1616
type Projection = CoordinateReferenceSystem
1717
type Transform = org.opengis.referencing.operation.MathTransform
1818

19+
lazy val LatLon = fromSrid("EPSG:4326").get
20+
lazy val WebMercator = fromSrid("EPSG:3857").get
21+
1922
private val catchLookup = catching(classOf[FactoryException])
2023

24+
def forceXYAxisOrder() {
25+
System.setProperty("org.geotools.referencing.forceXY", "true")
26+
}
27+
2128
def fromWKT(s: String): Option[Projection] =
2229
catching(classOf[FactoryException]).opt { CRS.parseWKT(s) }
2330

@@ -35,14 +42,6 @@ package object projection {
3542
CRS.findMathTransform(p, q)
3643

3744
def Projection(s: String): Projection = (fromSrid(s) orElse fromWKT(s)).orNull
38-
39-
lazy val LatLon = fromSrid("EPSG:4326").get
40-
lazy val WebMercator = fromSrid("EPSG:3857").get
41-
42-
def reference[T : Projectable](t: T, proj: Projection): Referenced[T] =
43-
Referenced(t, proj)
44-
45-
def aspatial[T](t: T): Referenced[T] = Referenced(t)
4645
}
4746

4847
package projection {

geoscript/src/main/scala/projection/Referenced.scala

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ trait Referenced[T] {
88
def map[U](f: T => U): Referenced[U]
99
def flatMap[U](f: T => Referenced[U]): Referenced[U]
1010
def native: Option[Projection]
11-
def force(p: Projection): T
12-
def forceNative: T = force(native.get)
11+
def project(p: Projection): T
12+
def forceNative: T = project(native.get)
1313
}
1414

1515
object Referenced {
@@ -21,7 +21,7 @@ object Referenced {
2121
private class Ideal[T](value: T) extends Referenced[T] {
2222
def map[U](f: T => U): Referenced[U] = new Ideal(f(value))
2323
def flatMap[U](f: T => Referenced[U]): Referenced[U] = f(value)
24-
def force(p: Projection): T = value
24+
def project(p: Projection): T = value
2525
def native = None
2626
}
2727

@@ -33,7 +33,7 @@ object Referenced {
3333
def flatMap[U](f: T => Referenced[U]): Referenced[U] =
3434
new FlatMapped(this, f)
3535

36-
def force(p: Projection): T =
36+
def project(p: Projection): T =
3737
implicitly[Projectable[T]].project(proj, p)(value)
3838

3939
def native = Some(proj)
@@ -46,7 +46,7 @@ object Referenced {
4646
def flatMap[V](g: U => Referenced[V]): Referenced[V] =
4747
new FlatMapped(base, f andThen g)
4848

49-
def force(p: Projection): U = f(base.force(p))
49+
def project(p: Projection): U = f(base.project(p))
5050

5151
def native = base.native
5252
}
@@ -58,8 +58,8 @@ object Referenced {
5858
def flatMap[V](g: U => Referenced[V]): Referenced[V] =
5959
new FlatMapped(this, g)
6060

61-
def force(p: Projection): U =
62-
f(base.force(p)).force(p)
61+
def project(p: Projection): U =
62+
f(base.project(p)).project(p)
6363

6464
def native = base.native
6565
}

0 commit comments

Comments
 (0)