Match geometry indexing to server config

This commit is contained in:
tidwall 2020-03-25 15:35:31 -07:00
parent b3dc025545
commit 951fc58e02
11 changed files with 47 additions and 22 deletions

View File

@ -6,20 +6,22 @@ import (
)
// Clip clips the contents of a geojson object and return
func Clip(obj geojson.Object, clipper geojson.Object) (clipped geojson.Object) {
func Clip(
obj geojson.Object, clipper geojson.Object, opts *geometry.IndexOptions,
) (clipped geojson.Object) {
switch obj := obj.(type) {
case *geojson.Point:
return clipPoint(obj, clipper)
return clipPoint(obj, clipper, opts)
case *geojson.Rect:
return clipRect(obj, clipper)
return clipRect(obj, clipper, opts)
case *geojson.LineString:
return clipLineString(obj, clipper)
return clipLineString(obj, clipper, opts)
case *geojson.Polygon:
return clipPolygon(obj, clipper)
return clipPolygon(obj, clipper, opts)
case *geojson.Feature:
return clipFeature(obj, clipper)
return clipFeature(obj, clipper, opts)
case geojson.Collection:
return clipCollection(obj, clipper)
return clipCollection(obj, clipper, opts)
}
return obj
}

View File

@ -27,7 +27,7 @@ func TestClipLineStringSimple(t *testing.T) {
{X: 1, Y: 1},
{X: 2, Y: 2},
{X: 3, Y: 1}})
clipped := Clip(ls, RO(1.5, 0.5, 2.5, 1.8))
clipped := Clip(ls, RO(1.5, 0.5, 2.5, 1.8), nil)
cl, ok := clipped.(*geojson.MultiLineString)
if !ok {
t.Fatal("wrong type")
@ -56,7 +56,7 @@ func TestClipPolygonSimple(t *testing.T) {
},
}
polygon := PPO(exterior, holes)
clipped := Clip(polygon, RO(1.3, 1.3, 1.4, 2.15))
clipped := Clip(polygon, RO(1.3, 1.3, 1.4, 2.15), nil)
cp, ok := clipped.(*geojson.Polygon)
if !ok {
t.Fatal("wrong type")

View File

@ -1,13 +1,17 @@
package clip
import "github.com/tidwall/geojson"
import (
"github.com/tidwall/geojson"
"github.com/tidwall/geojson/geometry"
)
func clipCollection(
collection geojson.Collection, clipper geojson.Object,
opts *geometry.IndexOptions,
) geojson.Object {
var features []geojson.Object
for _, feature := range collection.Children() {
feature = Clip(feature, clipper)
feature = Clip(feature, clipper, opts)
if feature.Empty() {
continue
}

View File

@ -1,11 +1,15 @@
package clip
import "github.com/tidwall/geojson"
import (
"github.com/tidwall/geojson"
"github.com/tidwall/geojson/geometry"
)
func clipFeature(
feature *geojson.Feature, clipper geojson.Object,
opts *geometry.IndexOptions,
) geojson.Object {
newFeature := Clip(feature.Base(), clipper)
newFeature := Clip(feature.Base(), clipper, opts)
if _, ok := newFeature.(*geojson.Feature); !ok {
newFeature = geojson.NewFeature(newFeature, feature.Members())
}

View File

@ -7,6 +7,7 @@ import (
func clipLineString(
lineString *geojson.LineString, clipper geojson.Object,
opts *geometry.IndexOptions,
) geojson.Object {
bbox := clipper.Rect()
var newPoints [][]geometry.Point
@ -34,7 +35,7 @@ func clipLineString(
var children []*geometry.Line
for _, points := range newPoints {
children = append(children,
geometry.NewLine(points, nil))
geometry.NewLine(points, opts))
}
if len(children) == 1 {
return geojson.NewLineString(children[0])

View File

@ -1,8 +1,13 @@
package clip
import "github.com/tidwall/geojson"
import (
"github.com/tidwall/geojson"
"github.com/tidwall/geojson/geometry"
)
func clipPoint(point *geojson.Point, clipper geojson.Object) geojson.Object {
func clipPoint(
point *geojson.Point, clipper geojson.Object, opts *geometry.IndexOptions,
) geojson.Object {
if point.IntersectsRect(clipper.Rect()) {
return point
}

View File

@ -7,6 +7,7 @@ import (
func clipPolygon(
polygon *geojson.Polygon, clipper geojson.Object,
opts *geometry.IndexOptions,
) geojson.Object {
rect := clipper.Rect()
var newPoints [][]geometry.Point
@ -30,7 +31,7 @@ func clipPolygon(
holes = newPoints[1:]
}
newPoly := geojson.NewPolygon(
geometry.NewPoly(exterior, holes, nil),
geometry.NewPoly(exterior, holes, opts),
)
if newPoly.Empty() {
return geojson.NewMultiPolygon(nil)

View File

@ -5,13 +5,15 @@ import (
"github.com/tidwall/geojson/geometry"
)
func clipRect(rect *geojson.Rect, clipper geojson.Object) geojson.Object {
func clipRect(
rect *geojson.Rect, clipper geojson.Object, opts *geometry.IndexOptions,
) geojson.Object {
base := rect.Base()
points := make([]geometry.Point, base.NumPoints())
for i := 0; i < len(points); i++ {
points[i] = base.PointAt(i)
}
poly := geometry.NewPoly(points, nil, nil)
poly := geometry.NewPoly(points, nil, opts)
gPoly := geojson.NewPolygon(poly)
return Clip(gPoly, clipper)
return Clip(gPoly, clipper, opts)
}

View File

@ -368,7 +368,7 @@ func (sw *scanWriter) writeObject(opts ScanWriterParams) bool {
return sw.count < sw.limit
}
if opts.clip != nil {
opts.o = clip.Clip(opts.o, opts.clip)
opts.o = clip.Clip(opts.o, opts.clip, &sw.s.geomIndexOpts)
}
switch sw.msg.OutputType {
case JSON:

View File

@ -80,6 +80,7 @@ type Server struct {
// env opts
geomParseOpts geojson.ParseOptions
geomIndexOpts geometry.IndexOptions
// atomics
followc aint // counter increases when follow property changes
@ -178,9 +179,11 @@ func Serve(host string, port int, dir string, http bool) error {
// T38IDXGEOM -- Min number of points in a geometry for indexing.
// T38IDXMULTI -- Min number of object in a Multi/Collection for indexing.
server.geomParseOpts = *geojson.DefaultParseOptions
server.geomIndexOpts = *geometry.DefaultIndexOptions
n, err := strconv.ParseUint(os.Getenv("T38IDXGEOM"), 10, 32)
if err == nil {
server.geomParseOpts.IndexGeometry = int(n)
server.geomIndexOpts.MinPoints = int(n)
}
n, err = strconv.ParseUint(os.Getenv("T38IDXMULTI"), 10, 32)
if err == nil {
@ -197,10 +200,13 @@ func Serve(host string, port int, dir string, http bool) error {
case "":
case "None":
server.geomParseOpts.IndexGeometryKind = geometry.None
server.geomIndexOpts.Kind = geometry.None
case "RTree":
server.geomParseOpts.IndexGeometryKind = geometry.RTree
server.geomIndexOpts.Kind = geometry.RTree
case "QuadTree":
server.geomParseOpts.IndexGeometryKind = geometry.QuadTree
server.geomIndexOpts.Kind = geometry.QuadTree
}
if server.geomParseOpts.IndexGeometryKind == geometry.None {
log.Debugf("Geom indexing: %s",

View File

@ -280,7 +280,7 @@ func (s *Server) cmdTest(msg *Message) (res resp.Value, err error) {
if area1.IntersectsExpr(area2) {
result = 1
if doClip {
clipped = clip.Clip(area1.obj, area2.obj)
clipped = clip.Clip(area1.obj, area2.obj, nil)
}
}
}