1
0
Fork 0
golang-github-blevesearch-b.../search/searcher/search_geoshape_points_test.go
Daniel Baumann 982828099e
Adding upstream version 2.5.1.
Signed-off-by: Daniel Baumann <daniel@debian.org>
2025-05-19 00:20:02 +02:00

600 lines
15 KiB
Go

// Copyright (c) 2022 Couchbase, Inc.
//
// 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 searcher
import (
"context"
"reflect"
"testing"
"github.com/blevesearch/bleve/v2/document"
"github.com/blevesearch/bleve/v2/geo"
"github.com/blevesearch/bleve/v2/index/scorch"
"github.com/blevesearch/bleve/v2/index/upsidedown/store/gtreap"
"github.com/blevesearch/bleve/v2/search"
index "github.com/blevesearch/bleve_index_api"
)
func TestGeoJsonPointContainsQuery(t *testing.T) {
tests := []struct {
point []float64
field string
want []string
}{
// test points inside the polygon1.
{
[]float64{77.58334636688232, 12.948268838994263},
"geometry",
[]string{"polygon1"},
},
// test points inside the circle1.
{
[]float64{77.58553504943848, 12.954040501528555},
"geometry",
[]string{"circle1"},
},
// test points inside the polygon1 and the circle.
{
[]float64{77.59293794631958, 12.948896200093982},
"geometry",
[]string{"polygon1", "circle1"},
},
// test points outside the polygon1 and the circle1.
{
[]float64{77.5614595413208, 12.953287683563568},
"geometry", nil,
},
// test point within the envelope1.
{
[]float64{81.28166198730469, 26.34203746601541},
"geometry",
[]string{"envelope1"},
},
// test point on the linestring vertex.
{
[]float64{77.57776737213135, 12.952074805390097},
"geometry",
[]string{"linestring1"},
},
// test point on the multilinestring vertex.
{
[]float64{77.5779390335083, 12.945006535817749},
"geometry",
[]string{"multilinestring1"},
},
// test point on the multipoint vertex.
{
[]float64{77.56407737731932, 12.951614746607163},
"geometry",
[]string{"multipoint1"},
},
// test point within the polygonWithHole1.
{
[]float64{77.60334491729736, 12.979844051951334},
"geometry",
[]string{"polygonWithHole1"},
},
// test point within the hole of the polygonWithHole1.
{
[]float64{77.60244369506836, 12.976247607394027},
"geometry", nil,
},
}
i := setupGeoJsonShapesIndex(t)
indexReader, err := i.Reader()
if err != nil {
t.Error(err)
}
defer func() {
err = indexReader.Close()
if err != nil {
t.Fatal(err)
}
}()
for n, test := range tests {
got, err := runGeoShapePointRelationQuery("contains",
false, indexReader, [][]float64{test.point}, test.field)
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(got, test.want) {
t.Errorf("test %d, expected %v, got %v for polygon: %+v",
n, test.want, got, test.point)
}
}
}
func TestGeoJsonMultiPointWithInQuery(t *testing.T) {
tests := []struct {
multipoint [][]float64
field string
want []string
}{
// test multipoint inside the polygon1.
{
[][]float64{
{77.58334636688232, 12.948268838994263},
{77.58467674255371, 12.944295515355652},
},
"geometry",
[]string{"polygon1"},
},
// test multipoint inside the circle1.
{
[][]float64{
{77.58553504943848, 12.954040501528555},
{77.58643627166747, 12.956089827794571},
},
"geometry",
[]string{"circle1"},
},
// test multipoint inside the envelope1.
{
[][]float64{
{81.28166198730469, 26.34203746601541},
{80.94314575195312, 26.346960121309415},
},
"geometry",
[]string{"envelope1"},
},
// test multipoint inside the polygon1 and the circle.
{
[][]float64{
{77.59293794631958, 12.948896200093982},
{77.58532047271729, 12.953789562459688},
},
"geometry",
[]string{"polygon1", "circle1"},
},
// test multipoint (only 1 point outside) outside.
{[][]float64{
{77.58334636688232, 12.948268838994263},
{77.58643627166747, 12.956089827794571},
{77.5615, 12.9533},
}, "geometry", nil},
// test multipoint on the linestring vertex.
{
[][]float64{
{77.5841188430786, 12.957093573282744},
{77.57776737213135, 12.952074805390097},
},
"geometry",
[]string{"linestring1"},
},
// test multipoint outside the linestring vertex.
{
[][]float64{
{77.5841188430786, 12.957093573282744},
{77.57776737213135, 12.952074805390097},
{77.58334636688232, 12.948268838994263},
},
"geometry", nil,
},
// test multipoint on the multilinestring vertex.
{
[][]float64{
{77.5779390335083, 12.94471376293191},
{77.57218837738037, 12.948268838994263},
},
"geometry",
[]string{"multilinestring1"},
},
// test multipoint outside the multilinestring vertex.
{
[][]float64{
{77.5779390335083, 12.94471376293191},
{77.57218837738037, 12.948268838994263},
{77.58532047271729, 12.953789562459688},
},
"geometry", nil,
},
// test multipoint with one inside the hole within the polygonWithHole1.
{
[][]float64{
{77.60334491729736, 12.979844051951334},
{77.60244369506836, 12.976247607394027},
},
"geometry", nil,
},
// test multipoint with all inside the hole witin the polygonWithHole1.
{
[][]float64{
{77.59656429290771, 12.981767710239714},
{77.59888172149658, 12.979969508380469},
},
"geometry", nil,
},
// test multipoint with all inside the polygonWithHole1.
{
[][]float64{
{77.60334491729736, 12.979844051951334},
{77.59656429290771, 12.981767710239714},
{77.59802341461182, 12.9751602999608},
},
"geometry",
[]string{"polygonWithHole1"},
},
}
i := setupGeoJsonShapesIndex(t)
indexReader, err := i.Reader()
if err != nil {
t.Error(err)
}
defer func() {
err = indexReader.Close()
if err != nil {
t.Fatal(err)
}
}()
for n, test := range tests {
got, err := runGeoShapePointRelationQuery("contains",
true, indexReader, test.multipoint, test.field)
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(got, test.want) {
t.Errorf("test %d, expected %v, got %v for polygon: %+v",
n, test.want, got, test.multipoint)
}
}
}
func TestGeoJsonMultiPointIntersectsQuery(t *testing.T) {
tests := []struct {
multipoint [][]float64
field string
want []string
}{
// test multipoint inside the polygon1.
{
[][]float64{
{77.58334636688232, 12.948268838994263},
{77.58467674255371, 12.944295515355652},
},
"geometry",
[]string{"polygon1"},
},
// test multipoint inside the circle1.
{
[][]float64{
{77.58553504943848, 12.954040501528555},
{77.58643627166747, 12.956089827794571},
},
"geometry",
[]string{"circle1"},
},
// test multipoint inside the envelope1. (1 point outside)
{
[][]float64{
{81.28166198730469, 26.34203746601541},
{80.94314575195312, 26.346960121309415},
{81.12716674804688, 26.353728430338332},
},
"geometry",
[]string{"envelope1"},
},
// test multipoint inside the polygon1 and the circle.
{
[][]float64{
{77.59293794631958, 12.948896200093982},
{77.58532047271729, 12.953789562459688},
},
"geometry",
[]string{"polygon1", "circle1"},
},
// test multipoint (only 1 point outside) intersects.
{
[][]float64{
{77.58334636688232, 12.948268838994263},
{77.58643627166747, 12.956089827794571},
{77.5615, 12.9533},
},
"geometry",
[]string{"polygon1", "circle1"},
},
// test multipoint on the linestring vertex.
{
[][]float64{
{77.5841188430786, 12.957093573282744},
{77.57776737213135, 12.952074805390097},
},
"geometry",
[]string{"linestring1"},
},
// test multipoint outside the linestring vertex.
{
[][]float64{
{77.5841188430786, 12.957093573282744},
{77.57776737213135, 12.952074805390097},
{77.58334636688232, 12.948268838994263},
},
"geometry",
[]string{"polygon1", "linestring1"},
},
// test multipoint on the multilinestring vertex.
{
[][]float64{
{77.5779390335083, 12.94471376293191},
{77.57218837738037, 12.948268838994263},
},
"geometry",
[]string{"multilinestring1"},
},
// test multipoint outside the multilinestring vertex.
{
[][]float64{
{77.5779390335083, 12.94471376293191},
{77.57218837738037, 12.948268838994263},
{77.58532047271729, 12.953789562459688},
},
"geometry",
[]string{"polygon1", "circle1", "multilinestring1"},
},
// test multipoint with one inside the hole within the polygonWithHole1.
{
[][]float64{
{77.60334491729736, 12.979844051951334},
{77.60244369506836, 12.976247607394027},
},
"geometry",
[]string{"polygonWithHole1"},
},
// test multipoint with all inside the hole witin the polygonWithHole1.
{
[][]float64{
{77.60244369506836, 12.976247607394027},
{77.59888172149658, 12.979969508380469},
},
"geometry", nil,
},
// test multipoint with all inside the polygonWithHole1.
{
[][]float64{
{77.60334491729736, 12.979844051951334},
{77.59656429290771, 12.981767710239714},
{77.59802341461182, 12.9751602999608},
},
"geometry",
[]string{"polygonWithHole1"},
},
}
i := setupGeoJsonShapesIndex(t)
indexReader, err := i.Reader()
if err != nil {
t.Error(err)
}
defer func() {
err = indexReader.Close()
if err != nil {
t.Fatal(err)
}
}()
for n, test := range tests {
got, err := runGeoShapePointRelationQuery("intersects",
true, indexReader, test.multipoint, test.field)
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(got, test.want) {
t.Errorf("test %d, expected %v, got %v for polygon: %+v",
n, test.want, got, test.multipoint)
}
}
}
func runGeoShapePointRelationQuery(relation string, multi bool,
i index.IndexReader, points [][]float64, field string,
) ([]string, error) {
var rv []string
var s index.GeoJSON
if multi {
s = geo.NewGeoJsonMultiPoint(points)
} else {
s = geo.NewGeoJsonPoint(points[0])
}
gbs, err := NewGeoShapeSearcher(context.TODO(), i, s, relation, field, 1.0, search.SearcherOptions{})
if err != nil {
return nil, err
}
ctx := &search.SearchContext{
DocumentMatchPool: search.NewDocumentMatchPool(gbs.DocumentMatchPoolSize(), 0),
}
docMatch, err := gbs.Next(ctx)
for docMatch != nil && err == nil {
docID, _ := i.ExternalID(docMatch.IndexInternalID)
rv = append(rv, docID)
docMatch, err = gbs.Next(ctx)
}
if err != nil {
return nil, err
}
return rv, nil
}
type Fatalfable interface {
Fatalf(format string, args ...interface{})
}
func setupGeoJsonShapesIndex(t *testing.T) index.Index {
analysisQueue := index.NewAnalysisQueue(1)
i, err := scorch.NewScorch(
gtreap.Name,
map[string]interface{}{
"path": "",
"spatialPlugin": "s2",
},
analysisQueue)
if err != nil {
t.Fatal(err)
}
err = i.Open()
if err != nil {
t.Fatal(err)
}
polygon1 := [][][][]float64{{{
{77.5853419303894, 12.953977766785052},
{77.58405447006226, 12.95393594361393},
{77.5819730758667, 12.9495026476557},
{77.58068561553955, 12.94883346405509},
{77.58019208908081, 12.948331575175299},
{77.57991313934326, 12.943814529775414},
{77.58497714996338, 12.94394000436408},
{77.58517026901245, 12.9446301134728},
{77.58572816848755, 12.945508431393435},
{77.58785247802734, 12.946365833997325},
{77.58967638015747, 12.946428570657417},
{77.59070634841918, 12.947474179333993},
{77.59317398071289, 12.948875288082773},
{77.59167194366454, 12.949962710338657},
{77.59077072143555, 12.950276388953625},
{77.59098529815674, 12.951196510612728},
{77.58729457855225, 12.952472128200755},
{77.5853419303894, 12.953977766785052},
}}}
doc := document.NewDocument("polygon1")
doc.AddField(document.NewGeoShapeFieldWithIndexingOptions("geometry", []uint64{},
polygon1, "polygon", document.DefaultGeoShapeIndexingOptions))
err = i.Update(doc)
if err != nil {
t.Fatal(err)
}
// not working envelope
envelope1 := [][][][]float64{{{
{80.93696594238281, 26.33957605983274},
{81.28440856933594, 26.351267272877074},
}}}
doc = document.NewDocument("envelope1")
doc.AddField(document.NewGeoShapeFieldWithIndexingOptions("geometry", []uint64{},
envelope1, "envelope", document.DefaultGeoShapeIndexingOptions))
err = i.Update(doc)
if err != nil {
t.Fatal(err)
}
doc = document.NewDocument("circle1")
doc.AddField(document.NewGeoCircleFieldWithIndexingOptions("geometry", []uint64{},
[]float64{77.59137153625487, 12.952660333521468}, "900m",
document.DefaultGeoShapeIndexingOptions))
err = i.Update(doc)
if err != nil {
t.Fatal(err)
}
linestring := [][][][]float64{{{
{77.5841188430786, 12.957093573282744},
{77.57776737213135, 12.952074805390097},
}}}
doc = document.NewDocument("linestring1")
doc.AddField(document.NewGeoShapeFieldWithIndexingOptions("geometry", []uint64{},
linestring, "linestring", document.DefaultGeoShapeIndexingOptions))
err = i.Update(doc)
if err != nil {
t.Fatal(err)
}
multilinestring := [][][][]float64{{{
{77.57227420806883, 12.948687079902895},
{77.57600784301758, 12.954165970968194},
{77.5779390335083, 12.94471376293191},
{77.57218837738037, 12.948268838994263},
{77.57781028747559, 12.951740217268595},
{77.5779390335083, 12.945006535817749},
}}}
doc = document.NewDocument("multilinestring1")
doc.AddField(document.NewGeoShapeFieldWithIndexingOptions("geometry", []uint64{},
multilinestring, "multilinestring", document.DefaultGeoShapeIndexingOptions))
err = i.Update(doc)
if err != nil {
t.Fatal(err)
}
multipoint1 := [][][][]float64{{{
{77.56618022918701, 12.958180959662695},
{77.56407737731932, 12.951614746607163},
{77.56922721862793, 12.956173473406446},
}}}
doc = document.NewDocument("multipoint1")
doc.AddField(document.NewGeoShapeFieldWithIndexingOptions("geometry", []uint64{},
multipoint1, "multipoint", document.DefaultGeoShapeIndexingOptions))
err = i.Update(doc)
if err != nil {
t.Fatal(err)
}
polygonWithHole1 := [][][][]float64{{
{
{77.59991168975829, 12.972232910164502},
{77.6039457321167, 12.97582941279006},
{77.60424613952637, 12.98168407323241},
{77.59974002838135, 12.985489528568463},
{77.59321689605713, 12.979300406693417},
{77.59991168975829, 12.972232910164502},
},
{
{77.59682178497314, 12.975787593290978},
{77.60295867919922, 12.975787593290978},
{77.60295867919922, 12.98143316204164},
{77.59682178497314, 12.98143316204164},
{77.59682178497314, 12.975787593290978},
},
}}
doc = document.NewDocument("polygonWithHole1")
doc.AddField(document.NewGeoShapeFieldWithIndexingOptions("geometry", []uint64{},
polygonWithHole1, "polygon", document.DefaultGeoShapeIndexingOptions))
err = i.Update(doc)
if err != nil {
t.Fatal(err)
}
return i
}