Improve geometry polygon searching functionality
This commit is contained in:
parent
e2635e8cf9
commit
27b80ceb8e
3 changed files with 184 additions and 0 deletions
114
db/fetch.go
114
db/fetch.go
|
@ -28,6 +28,7 @@ import (
|
||||||
|
|
||||||
"github.com/abcum/surreal/cnf"
|
"github.com/abcum/surreal/cnf"
|
||||||
"github.com/abcum/surreal/sql"
|
"github.com/abcum/surreal/sql"
|
||||||
|
"github.com/abcum/surreal/util/geof"
|
||||||
"github.com/abcum/surreal/util/data"
|
"github.com/abcum/surreal/util/data"
|
||||||
"github.com/abcum/surreal/util/deep"
|
"github.com/abcum/surreal/util/deep"
|
||||||
"github.com/abcum/surreal/util/fncs"
|
"github.com/abcum/surreal/util/fncs"
|
||||||
|
@ -708,6 +709,41 @@ func binaryCheck(op sql.Token, l, r, lo, ro interface{}, d *data.Doc) interface{
|
||||||
return chkArrayR(op, l, r)
|
return chkArrayR(op, l, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case *sql.Point:
|
||||||
|
switch r := r.(type) {
|
||||||
|
case *sql.Point:
|
||||||
|
return chkPoint(op, l, r)
|
||||||
|
case *sql.Polygon:
|
||||||
|
switch op {
|
||||||
|
case sql.INS:
|
||||||
|
return geof.Inside(l, r) == true
|
||||||
|
case sql.NIS:
|
||||||
|
return geof.Inside(l, r) == false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case *sql.Polygon:
|
||||||
|
switch r := r.(type) {
|
||||||
|
case *sql.Point:
|
||||||
|
switch op {
|
||||||
|
case sql.SIN:
|
||||||
|
return geof.Contains(l, r) == true
|
||||||
|
case sql.SNI:
|
||||||
|
return geof.Contains(l, r) == false
|
||||||
|
}
|
||||||
|
case []interface{}:
|
||||||
|
if p, ok := geof.Point(r); ok {
|
||||||
|
switch op {
|
||||||
|
case sql.SIN:
|
||||||
|
return geof.Contains(l, p) == true
|
||||||
|
case sql.SNI:
|
||||||
|
return geof.Contains(l, p) == false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return chkPolygonL(op, l, r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
case bool:
|
case bool:
|
||||||
switch r := r.(type) {
|
switch r := r.(type) {
|
||||||
case bool:
|
case bool:
|
||||||
|
@ -822,6 +858,8 @@ func binaryCheck(op sql.Token, l, r, lo, ro interface{}, d *data.Doc) interface{
|
||||||
return chkArray(op, l, r)
|
return chkArray(op, l, r)
|
||||||
case map[string]interface{}:
|
case map[string]interface{}:
|
||||||
return chkArrayL(op, l, r)
|
return chkArrayL(op, l, r)
|
||||||
|
case *sql.Polygon:
|
||||||
|
return chkPolygonR(op, l, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
case map[string]interface{}:
|
case map[string]interface{}:
|
||||||
|
@ -972,6 +1010,16 @@ func chkThing(op sql.Token, a, b *sql.Thing) (val bool) {
|
||||||
return negOp(op)
|
return negOp(op)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func chkPoint(op sql.Token, a, b *sql.Point) (val bool) {
|
||||||
|
switch op {
|
||||||
|
case sql.EQ:
|
||||||
|
return a.LA == b.LA && a.LO == b.LO
|
||||||
|
case sql.NEQ:
|
||||||
|
return a.LA != b.LA || a.LO != b.LO
|
||||||
|
}
|
||||||
|
return negOp(op)
|
||||||
|
}
|
||||||
|
|
||||||
func chkRegex(op sql.Token, a string, r *regexp.Regexp) (val bool) {
|
func chkRegex(op sql.Token, a string, r *regexp.Regexp) (val bool) {
|
||||||
switch op {
|
switch op {
|
||||||
case sql.EQ:
|
case sql.EQ:
|
||||||
|
@ -1004,6 +1052,72 @@ func chkObject(op sql.Token, m map[string]interface{}, i interface{}) (val bool)
|
||||||
return negOp(op)
|
return negOp(op)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func chkPolygonL(op sql.Token, a *sql.Polygon, b []interface{}) (val bool) {
|
||||||
|
switch op {
|
||||||
|
case sql.CONTAINSALL:
|
||||||
|
for _, v := range b {
|
||||||
|
if p, ok := geof.Point(v); ok {
|
||||||
|
if geof.Contains(a, p) == false {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
case sql.CONTAINSSOME:
|
||||||
|
for _, v := range b {
|
||||||
|
if p, ok := geof.Point(v); ok {
|
||||||
|
if geof.Contains(a, p) == true {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
case sql.CONTAINSNONE:
|
||||||
|
for _, v := range b {
|
||||||
|
if p, ok := geof.Point(v); ok {
|
||||||
|
if geof.Contains(a, p) == true {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func chkPolygonR(op sql.Token, a []interface{}, b *sql.Polygon) (val bool) {
|
||||||
|
switch op {
|
||||||
|
case sql.ALLCONTAINEDIN:
|
||||||
|
for _, v := range a {
|
||||||
|
if p, ok := geof.Point(v); ok {
|
||||||
|
if geof.Contains(b, p) == false {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
case sql.SOMECONTAINEDIN:
|
||||||
|
for _, v := range a {
|
||||||
|
if p, ok := geof.Point(v); ok {
|
||||||
|
if geof.Contains(b, p) == true {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
case sql.NONECONTAINEDIN:
|
||||||
|
for _, v := range a {
|
||||||
|
if p, ok := geof.Point(v); ok {
|
||||||
|
if geof.Contains(b, p) == true {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func chkArrayL(op sql.Token, a []interface{}, i interface{}) (val bool) {
|
func chkArrayL(op sql.Token, a []interface{}, i interface{}) (val bool) {
|
||||||
switch op {
|
switch op {
|
||||||
case sql.EQ:
|
case sql.EQ:
|
||||||
|
|
|
@ -144,6 +144,10 @@ func ensurePoint(val interface{}) (out *sql.Point, ok bool) {
|
||||||
switch val := val.(type) {
|
switch val := val.(type) {
|
||||||
case *sql.Point:
|
case *sql.Point:
|
||||||
return val, true
|
return val, true
|
||||||
|
case []interface{}:
|
||||||
|
if p := ensureFloats(val); len(p) == 2 {
|
||||||
|
return sql.NewPoint(p[0], p[1]), true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
|
|
66
util/geof/point.go
Normal file
66
util/geof/point.go
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
// Copyright © 2016 Abcum Ltd
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package geof
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/abcum/surreal/sql"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ensureSlice(args interface{}) (out []interface{}, ok bool) {
|
||||||
|
if i, ok := args.([]interface{}); ok {
|
||||||
|
return i, true
|
||||||
|
} else {
|
||||||
|
return []interface{}{args}, false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ensureFloats(args interface{}) (out []float64) {
|
||||||
|
arr, _ := ensureSlice(args)
|
||||||
|
for _, val := range arr {
|
||||||
|
switch val := val.(type) {
|
||||||
|
case int:
|
||||||
|
out = append(out, float64(val))
|
||||||
|
case int64:
|
||||||
|
out = append(out, float64(val))
|
||||||
|
case uint:
|
||||||
|
out = append(out, float64(val))
|
||||||
|
case uint64:
|
||||||
|
out = append(out, float64(val))
|
||||||
|
case float32:
|
||||||
|
out = append(out, float64(val))
|
||||||
|
case float64:
|
||||||
|
out = append(out, float64(val))
|
||||||
|
case string:
|
||||||
|
if val, err := strconv.ParseFloat(val, 64); err == nil {
|
||||||
|
out = append(out, float64(val))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func Point(val interface{}) (out *sql.Point, ok bool) {
|
||||||
|
switch val := val.(type) {
|
||||||
|
case *sql.Point:
|
||||||
|
return val, true
|
||||||
|
case []interface{}:
|
||||||
|
if p := ensureFloats(val); len(p) == 2 {
|
||||||
|
return sql.NewPoint(p[0], p[1]), true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, false
|
||||||
|
}
|
Loading…
Reference in a new issue