mirror of https://github.com/tidwall/tile38.git
Merge branch 'master' of https://github.com/tidwall/tile38
This commit is contained in:
commit
5e4c1601b1
|
@ -243,7 +243,7 @@
|
|||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:36ee77434dbfa0fafc20f0788cfc0a30f7dda8aea228b2574028be818cfabc31"
|
||||
digest = "1:24cb019229d3a4d0febd3934800b3759df35c722e93d63d9cfe32015d7abfec3"
|
||||
name = "github.com/tidwall/geojson"
|
||||
packages = [
|
||||
".",
|
||||
|
@ -251,7 +251,7 @@
|
|||
"geometry",
|
||||
]
|
||||
pruneopts = ""
|
||||
revision = "0d533c870e85d0cb1909818503e0127f9e543d92"
|
||||
revision = "ade1bcf7b6db0e5ffb0605fea152254d2c002d6a"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:3ddca2bd5496c6922a2a9e636530e178a43c2a534ea6634211acdc7d10222794"
|
||||
|
|
|
@ -27,6 +27,11 @@ func (s String) Empty() bool {
|
|||
return true
|
||||
}
|
||||
|
||||
// Valid ...
|
||||
func (s String) Valid() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// Rect ...
|
||||
func (s String) Rect() geometry.Rect {
|
||||
return geometry.Rect{}
|
||||
|
|
|
@ -166,7 +166,7 @@ func (server *Server) cmdSearchArgs(
|
|||
err = errInvalidNumberOfArguments
|
||||
return
|
||||
}
|
||||
s.obj, err = geojson.Parse(obj, nil)
|
||||
s.obj, err = geojson.Parse(obj, &server.geomParseOpts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -183,6 +183,10 @@ func Serve(host string, port int, dir string, http bool) error {
|
|||
if err == nil {
|
||||
server.geomParseOpts.IndexChildren = int(n)
|
||||
}
|
||||
requireValid := os.Getenv("REQUIREVALID")
|
||||
if requireValid != "" {
|
||||
server.geomParseOpts.RequireValid = true
|
||||
}
|
||||
indexKind := os.Getenv("T38IDXGEOMKIND")
|
||||
switch indexKind {
|
||||
default:
|
||||
|
|
|
@ -178,6 +178,11 @@ func (g *Circle) Empty() bool {
|
|||
return false
|
||||
}
|
||||
|
||||
// Valid ...
|
||||
func (g *Circle) Valid() bool {
|
||||
return g.getObject().Valid()
|
||||
}
|
||||
|
||||
// ForEach ...
|
||||
func (g *Circle) ForEach(iter func(geom Object) bool) bool {
|
||||
return iter(g)
|
||||
|
|
|
@ -64,6 +64,11 @@ func (g *collection) Empty() bool {
|
|||
return g.pempty
|
||||
}
|
||||
|
||||
// Valid ...
|
||||
func (g *collection) Valid() bool {
|
||||
return g.Rect().Valid()
|
||||
}
|
||||
|
||||
// Rect ...
|
||||
func (g *collection) Rect() geometry.Rect {
|
||||
return g.prect
|
||||
|
|
|
@ -45,6 +45,11 @@ func (g *Feature) Empty() bool {
|
|||
return g.base.Empty()
|
||||
}
|
||||
|
||||
// Valid ...
|
||||
func (g *Feature) Valid() bool {
|
||||
return g.base.Valid()
|
||||
}
|
||||
|
||||
// Rect ...
|
||||
func (g *Feature) Rect() geometry.Rect {
|
||||
return g.base.Rect()
|
||||
|
|
|
@ -18,3 +18,9 @@ func TestFeatureCollectionPoly(t *testing.T) {
|
|||
expect(t, p.Intersects(PO(1, 2)))
|
||||
expect(t, p.Contains(PO(1, 2)))
|
||||
}
|
||||
|
||||
func TestFeatureCollectionValid(t *testing.T) {
|
||||
json := `{"type":"FeatureCollection","features":[{"type":"Point","coordinates":[1,200]}]}`
|
||||
expectJSON(t, json, nil)
|
||||
expectJSONOpts(t, json, errCoordinatesInvalid, &ParseOptions{RequireValid: true})
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ package geometry
|
|||
type Geometry interface {
|
||||
Rect() Rect
|
||||
Empty() bool
|
||||
Valid() bool
|
||||
ContainsPoint(point Point) bool
|
||||
IntersectsPoint(point Point) bool
|
||||
ContainsRect(rect Rect) bool
|
||||
|
@ -20,3 +21,8 @@ type Geometry interface {
|
|||
|
||||
// require conformance
|
||||
var _ = []Geometry{Point{}, Rect{}, &Line{}, &Poly{}}
|
||||
|
||||
// WorldPolygon is the maximum bounds for any GeoPoint
|
||||
var WorldPolygon = NewPoly([]Point{
|
||||
{-180, -90}, {-180, 90}, {180, 90}, {180, -90}, {-180, -90},
|
||||
}, nil, &IndexOptions{})
|
||||
|
|
|
@ -9,6 +9,14 @@ type Line struct {
|
|||
baseSeries
|
||||
}
|
||||
|
||||
// Valid ...
|
||||
func (line *Line) Valid() bool {
|
||||
if !WorldPolygon.ContainsLine(line) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// NewLine creates a new Line
|
||||
func NewLine(points []Point, opts *IndexOptions) *Line {
|
||||
line := new(Line)
|
||||
|
|
|
@ -19,6 +19,14 @@ func (point Point) Empty() bool {
|
|||
return false
|
||||
}
|
||||
|
||||
// Valid ...
|
||||
func (point Point) Valid() bool {
|
||||
if !WorldPolygon.ContainsPoint(point) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Rect ...
|
||||
func (point Point) Rect() Rect {
|
||||
return Rect{point, point}
|
||||
|
|
|
@ -39,6 +39,14 @@ func (poly *Poly) Empty() bool {
|
|||
return poly.Exterior.Empty()
|
||||
}
|
||||
|
||||
// Valid ...
|
||||
func (poly *Poly) Valid() bool {
|
||||
if !WorldPolygon.ContainsPoly(poly) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Rect ...
|
||||
func (poly *Poly) Rect() Rect {
|
||||
if poly == nil || poly.Exterior == nil {
|
||||
|
|
|
@ -234,10 +234,21 @@ func Test369(t *testing.T) {
|
|||
{-122.44, 37.7341129},
|
||||
{-122.4408378, 37.7341129},
|
||||
}, nil, DefaultIndexOptions)
|
||||
d := NewPoly([]Point{
|
||||
{-182.4408378, 37.7341129},
|
||||
{-122.4408378, 37.733},
|
||||
{-122.44, 37.733},
|
||||
{-122.44, 37.7341129},
|
||||
{-122.4408378, 137.7341129},
|
||||
}, nil, DefaultIndexOptions)
|
||||
expect(t, polyHoles.IntersectsPoly(a))
|
||||
expect(t, !polyHoles.IntersectsPoly(b))
|
||||
expect(t, !polyHoles.IntersectsPoly(c))
|
||||
expect(t, a.IntersectsPoly(polyHoles))
|
||||
expect(t, !b.IntersectsPoly(polyHoles))
|
||||
expect(t, !c.IntersectsPoly(polyHoles))
|
||||
expect(t, a.Valid())
|
||||
expect(t, b.Valid())
|
||||
expect(t, c.Valid())
|
||||
expect(t, !d.Valid())
|
||||
}
|
||||
|
|
|
@ -113,6 +113,14 @@ func (rect Rect) Empty() bool {
|
|||
return false
|
||||
}
|
||||
|
||||
// Valid ...
|
||||
func (rect Rect) Valid() bool {
|
||||
if !WorldPolygon.ContainsRect(rect) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Rect ...
|
||||
func (rect Rect) Rect() Rect {
|
||||
return rect
|
||||
|
|
|
@ -81,6 +81,10 @@ func TestRectEmpty(t *testing.T) {
|
|||
expect(t, !R(0, 0, 10, 10).Empty())
|
||||
}
|
||||
|
||||
func TestRectValid(t *testing.T) {
|
||||
expect(t, R(0, 0, 10, 10).Valid())
|
||||
}
|
||||
|
||||
func TestRectRect(t *testing.T) {
|
||||
expect(t, R(0, 0, 10, 10).Rect() == R(0, 0, 10, 10))
|
||||
}
|
||||
|
|
|
@ -136,6 +136,17 @@ func (series *baseSeries) Empty() bool {
|
|||
return (series.closed && len(series.points) < 3) || len(series.points) < 2
|
||||
}
|
||||
|
||||
// Valid ...
|
||||
func (series *baseSeries) Valid() bool {
|
||||
valid := true
|
||||
for _, point := range series.points {
|
||||
if !point.Valid() {
|
||||
valid = false
|
||||
}
|
||||
}
|
||||
return valid
|
||||
}
|
||||
|
||||
// Rect returns the series rectangle
|
||||
func (series *baseSeries) Rect() Rect {
|
||||
return series.rect
|
||||
|
|
|
@ -16,3 +16,9 @@ func TestGeometryCollectionPoly(t *testing.T) {
|
|||
expect(t, p.Intersects(PO(1, 2)))
|
||||
expect(t, p.Contains(PO(1, 2)))
|
||||
}
|
||||
|
||||
func TestGeometryCollectionValid(t *testing.T) {
|
||||
json := `{"type":"GeometryCollection","geometries":[{"type":"Point","coordinates":[1,200]}]}`
|
||||
expectJSON(t, json, nil)
|
||||
expectJSONOpts(t, json, errCoordinatesInvalid, &ParseOptions{RequireValid: true})
|
||||
}
|
||||
|
|
|
@ -21,6 +21,11 @@ func (g *LineString) Empty() bool {
|
|||
return g.base.Empty()
|
||||
}
|
||||
|
||||
// Valid ...
|
||||
func (g *LineString) Valid() bool {
|
||||
return g.base.Valid()
|
||||
}
|
||||
|
||||
// Rect ...
|
||||
func (g *LineString) Rect() geometry.Rect {
|
||||
return g.base.Rect()
|
||||
|
@ -145,6 +150,11 @@ func parseJSONLineString(keys *parseKeys, opts *ParseOptions) (Object, error) {
|
|||
if err := parseBBoxAndExtras(&g.extra, keys, opts); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if opts.RequireValid {
|
||||
if !g.Valid() {
|
||||
return nil, errDataInvalid
|
||||
}
|
||||
}
|
||||
return &g, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,12 @@ func TestLineStringParse(t *testing.T) {
|
|||
expectJSON(t, `{"type":"LineString","coordinates":[[3,4],[1,2]],"bbox":[1,2,3,4]}`, nil)
|
||||
}
|
||||
|
||||
func TestLineStringParseValid(t *testing.T) {
|
||||
json := `{"type":"LineString","coordinates":[[1,2],[-12,-190]]}`
|
||||
expectJSON(t, json, nil)
|
||||
expectJSONOpts(t, json, errDataInvalid, &ParseOptions{RequireValid: true})
|
||||
}
|
||||
|
||||
func TestLineStringVarious(t *testing.T) {
|
||||
var g = expectJSON(t, `{"type":"LineString","coordinates":[[3,4],[1,2]]}`, nil)
|
||||
expect(t, string(g.AppendJSON(nil)) == `{"type":"LineString","coordinates":[[3,4],[1,2]]}`)
|
||||
|
@ -30,6 +36,16 @@ func TestLineStringVarious(t *testing.T) {
|
|||
expect(t, g.Center() == R(1, 2, 3, 4).Center())
|
||||
}
|
||||
|
||||
func TestLineStringValid(t *testing.T) {
|
||||
var g = expectJSON(t, `{"type":"LineString","coordinates":[[3,4],[1,2]]}`, nil)
|
||||
expect(t, g.Valid())
|
||||
}
|
||||
|
||||
func TestLineStringInvalid(t *testing.T) {
|
||||
var g = expectJSON(t, `{"type":"LineString","coordinates":[[3,4],[1,2],[0, 190]]}`, nil)
|
||||
expect(t, !g.Valid())
|
||||
}
|
||||
|
||||
// func TestLineStringPoly(t *testing.T) {
|
||||
// ls := expectJSON(t, `{"type":"LineString","coordinates":[
|
||||
// [10,10],[20,20],[20,10]
|
||||
|
|
|
@ -42,6 +42,17 @@ func (g *MultiLineString) String() string {
|
|||
return string(g.AppendJSON(nil))
|
||||
}
|
||||
|
||||
// Valid ...
|
||||
func (g *MultiLineString) Valid() bool {
|
||||
valid := true
|
||||
for _, p := range g.children {
|
||||
if !p.Valid() {
|
||||
valid = false
|
||||
}
|
||||
}
|
||||
return valid
|
||||
}
|
||||
|
||||
// JSON ...
|
||||
func (g *MultiLineString) JSON() string {
|
||||
return string(g.AppendJSON(nil))
|
||||
|
@ -80,6 +91,11 @@ func parseJSONMultiLineString(
|
|||
if err := parseBBoxAndExtras(&g.extra, keys, opts); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if opts.RequireValid {
|
||||
if !g.Valid() {
|
||||
return nil, errCoordinatesInvalid
|
||||
}
|
||||
}
|
||||
g.parseInitRectIndex(opts)
|
||||
return &g, nil
|
||||
}
|
||||
|
|
|
@ -10,6 +10,15 @@ func TestMultiLineString(t *testing.T) {
|
|||
expectJSON(t, `{"type":"MultiLineString","coordinates":[1,null]}`, errCoordinatesInvalid)
|
||||
}
|
||||
|
||||
func TestMultiLineStringValid(t *testing.T) {
|
||||
json := `{"type":"MultiLineString","coordinates":[
|
||||
[[10,10],[120,190]],
|
||||
[[50,50],[100,100]]
|
||||
]}`
|
||||
expectJSON(t, json, nil)
|
||||
expectJSONOpts(t, json, errCoordinatesInvalid, &ParseOptions{RequireValid: true})
|
||||
}
|
||||
|
||||
func TestMultiLineStringPoly(t *testing.T) {
|
||||
p := expectJSON(t, `{"type":"MultiLineString","coordinates":[
|
||||
[[10,10],[20,20]],
|
||||
|
|
|
@ -41,6 +41,17 @@ func (g *MultiPolygon) String() string {
|
|||
return string(g.AppendJSON(nil))
|
||||
}
|
||||
|
||||
// Valid ...
|
||||
func (g *MultiPolygon) Valid() bool {
|
||||
valid := true
|
||||
for _, p := range g.children {
|
||||
if !p.Valid() {
|
||||
valid = false
|
||||
}
|
||||
}
|
||||
return valid
|
||||
}
|
||||
|
||||
// JSON ...
|
||||
func (g *MultiPolygon) JSON() string {
|
||||
return string(g.AppendJSON(nil))
|
||||
|
@ -90,6 +101,11 @@ func parseJSONMultiPolygon(
|
|||
if err := parseBBoxAndExtras(&g.extra, keys, opts); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if opts.RequireValid {
|
||||
if !g.Valid() {
|
||||
return nil, errCoordinatesInvalid
|
||||
}
|
||||
}
|
||||
g.parseInitRectIndex(opts)
|
||||
return &g, nil
|
||||
}
|
||||
|
|
|
@ -25,6 +25,19 @@ func TestMultiPolygon(t *testing.T) {
|
|||
expectJSON(t, `{"type":"MultiPolygon","coordinates":[1,null]}`, errCoordinatesInvalid)
|
||||
}
|
||||
|
||||
func TestMultiPolygonParseValid(t *testing.T) {
|
||||
json := `{"type":"MultiPolygon","coordinates":[
|
||||
[
|
||||
[[0,0],[10,0],[10,10],[0,10],[0,0]],
|
||||
[[2,2],[8,2],[8,8],[2,8],[2,2]]
|
||||
],[
|
||||
[[0,0],[10,0],[10,10],[0,10],[0,0]],
|
||||
[[2,2],[8,2],[8,8],[2,8],[2,2]]
|
||||
]
|
||||
]}`
|
||||
expectJSONOpts(t, json, nil, &ParseOptions{RequireValid: true})
|
||||
}
|
||||
|
||||
func TestMultiPolygonPoly(t *testing.T) {
|
||||
p := expectJSON(t, `{"type":"MultiPolygon","coordinates":[
|
||||
[
|
||||
|
|
|
@ -30,6 +30,7 @@ var (
|
|||
// Object is a GeoJSON type
|
||||
type Object interface {
|
||||
Empty() bool
|
||||
Valid() bool
|
||||
Rect() geometry.Rect
|
||||
Center() geometry.Point
|
||||
Contains(other Object) bool
|
||||
|
@ -87,6 +88,7 @@ type ParseOptions struct {
|
|||
// IndexGeometryKind is the kind of index implementation.
|
||||
// Default is QuadTreeCompressed
|
||||
IndexGeometryKind geometry.IndexKind
|
||||
RequireValid bool
|
||||
}
|
||||
|
||||
// DefaultParseOptions ...
|
||||
|
@ -94,6 +96,7 @@ var DefaultParseOptions = &ParseOptions{
|
|||
IndexChildren: 64,
|
||||
IndexGeometry: 64,
|
||||
IndexGeometryKind: geometry.QuadTree,
|
||||
RequireValid: false,
|
||||
}
|
||||
|
||||
// Parse a GeoJSON object
|
||||
|
|
|
@ -34,6 +34,11 @@ func (g *Point) Empty() bool {
|
|||
return g.base.Empty()
|
||||
}
|
||||
|
||||
// Valid ...
|
||||
func (g *Point) Valid() bool {
|
||||
return g.base.Valid()
|
||||
}
|
||||
|
||||
// Rect ...
|
||||
func (g *Point) Rect() geometry.Rect {
|
||||
return g.base.Rect()
|
||||
|
@ -151,6 +156,11 @@ func parseJSONPoint(keys *parseKeys, opts *ParseOptions) (Object, error) {
|
|||
if err := parseBBoxAndExtras(&g.extra, keys, opts); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if opts.RequireValid {
|
||||
if !g.Valid() {
|
||||
return nil, errCoordinatesInvalid
|
||||
}
|
||||
}
|
||||
return &g, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,11 @@ func TestPointParse(t *testing.T) {
|
|||
expectJSON(t, `{"type":"Point","coordinates":[1]}`, errCoordinatesInvalid)
|
||||
expectJSON(t, `{"type":"Point","coordinates":[1,2,3],"bbox":[1,2,3,4]}`, `{"type":"Point","coordinates":[1,2,3],"bbox":[1,2,3,4]}`)
|
||||
}
|
||||
func TestPointParseValid(t *testing.T) {
|
||||
json := `{"type":"Point","coordinates":[190,90]}`
|
||||
expectJSON(t, json, nil)
|
||||
expectJSONOpts(t, json, errCoordinatesInvalid, &ParseOptions{RequireValid: true})
|
||||
}
|
||||
|
||||
func TestPointVarious(t *testing.T) {
|
||||
var g Object = PO(10, 20)
|
||||
|
@ -22,6 +27,34 @@ func TestPointVarious(t *testing.T) {
|
|||
expect(t, !g.Empty())
|
||||
}
|
||||
|
||||
func TestPointValid(t *testing.T) {
|
||||
var g Object = PO(0, 20)
|
||||
expect(t, g.Valid())
|
||||
|
||||
var g1 Object = PO(10, 20)
|
||||
expect(t, g1.Valid())
|
||||
}
|
||||
|
||||
func TestPointInvalidLargeX(t *testing.T) {
|
||||
var g Object = PO(10, 91)
|
||||
expect(t, !g.Valid())
|
||||
}
|
||||
|
||||
func TestPointInvalidLargeY(t *testing.T) {
|
||||
var g Object = PO(181, 20)
|
||||
expect(t, !g.Valid())
|
||||
}
|
||||
|
||||
func TestPointValidLargeX(t *testing.T) {
|
||||
var g Object = PO(180, 20)
|
||||
expect(t, g.Valid())
|
||||
}
|
||||
|
||||
func TestPointValidLargeY(t *testing.T) {
|
||||
var g Object = PO(180, 90)
|
||||
expect(t, g.Valid())
|
||||
}
|
||||
|
||||
// func TestPointPoly(t *testing.T) {
|
||||
// p := expectJSON(t, `{"type":"Point","coordinates":[15,15,0]}`, nil)
|
||||
// expect(t, p.Within(PO(15, 15)))
|
||||
|
|
|
@ -21,6 +21,11 @@ func (g *Polygon) Empty() bool {
|
|||
return g.base.Empty()
|
||||
}
|
||||
|
||||
// Valid ...
|
||||
func (g *Polygon) Valid() bool {
|
||||
return g.base.Valid()
|
||||
}
|
||||
|
||||
// Rect ...
|
||||
func (g *Polygon) Rect() geometry.Rect {
|
||||
return g.base.Rect()
|
||||
|
@ -163,6 +168,11 @@ func parseJSONPolygon(keys *parseKeys, opts *ParseOptions) (Object, error) {
|
|||
if err := parseBBoxAndExtras(&g.extra, keys, opts); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if opts.RequireValid {
|
||||
if !g.Valid() {
|
||||
return nil, errCoordinatesInvalid
|
||||
}
|
||||
}
|
||||
return &g, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,14 @@ func TestPolygonParse(t *testing.T) {
|
|||
`{"type":"Polygon","coordinates":[[[0,0,0],[10,0,4,5],[5,10],[0,0]]]}`,
|
||||
`{"type":"Polygon","coordinates":[[[0,0,0],[10,0,4],[5,10,0],[0,0,0]]]}`)
|
||||
}
|
||||
func TestPolygonParseValid(t *testing.T) {
|
||||
json := `{"type":"Polygon","coordinates":[
|
||||
[[0,0],[190,0],[10,10],[0,10],[0,0]],
|
||||
[[2,2],[8,2],[8,8],[2,8],[2,2]]
|
||||
]}`
|
||||
expectJSON(t, json, nil)
|
||||
expectJSONOpts(t, json, errCoordinatesInvalid, &ParseOptions{RequireValid: true})
|
||||
}
|
||||
|
||||
func TestPolygonVarious(t *testing.T) {
|
||||
var g = expectJSON(t, `{"type":"Polygon","coordinates":[[[0,0],[10,0],[10,10],[0,10],[0,0]]]}`, nil)
|
||||
|
|
|
@ -24,6 +24,11 @@ func (g *Rect) Empty() bool {
|
|||
return g.base.Empty()
|
||||
}
|
||||
|
||||
// Valid ...
|
||||
func (g *Rect) Valid() bool {
|
||||
return g.base.Valid()
|
||||
}
|
||||
|
||||
// Rect ...
|
||||
func (g *Rect) Rect() geometry.Rect {
|
||||
return g.base
|
||||
|
|
|
@ -41,3 +41,9 @@ func TestRect(t *testing.T) {
|
|||
expect(t, (&Polygon{}).Distance(rect) != 0)
|
||||
|
||||
}
|
||||
|
||||
func TestRectValid(t *testing.T) {
|
||||
json := `{"type":"Polygon","coordinates":[[[10,200],[30,200],[30,40],[10,40],[10,200]]]}`
|
||||
expectJSON(t, json, nil)
|
||||
expectJSONOpts(t, json, errCoordinatesInvalid, &ParseOptions{RequireValid: true})
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue