1
0
Fork 0
golang-github-blevesearch-b.../search/searcher/search_geoshape_geometrycollection_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

692 lines
21 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 TestGeoJSONIntersectsQueryAgainstGeometryCollection(t *testing.T) {
tests := []struct {
points [][][][][]float64
types []string
field string
want []string
}{
// test intersects geometrycollection query for gc_polygon1_linestring1.
{
[][][][][]float64{
{{{
{-120.80017089843749, 36.54053616262899},
{-120.67932128906249, 36.33725319397006},
{-120.30578613281251, 36.90597988519294},
{-120.80017089843749, 36.54053616262899},
}}},
{{{{-118.24584960937499, 35.32184842037683}, {-117.8668212890625, 35.06597313798418}}}},
},
[]string{"polygon", "linestring"},
"geometry",
[]string{"gc_polygon1_linestring1"},
},
// test intersects geometrycollection query for gc_polygon1_linestring1.
{
[][][][][]float64{
{{
{{-118.3172607421875, 35.250105158539355}, {-117.50976562499999, 35.37561413174875}},
{{-118.69628906249999, 34.6241677899049}, {-118.3172607421875, 35.03899204678081}},
{{-117.94921874999999, 35.146862906756304}, {-117.674560546875, 34.41144164327245}},
}},
{{{
{-117.04284667968749, 35.263561862152095},
{-116.8505859375, 35.263561862152095},
{-116.8505859375, 35.33529320309328},
{-117.04284667968749, 35.33529320309328},
{-117.04284667968749, 35.263561862152095},
}}},
},
[]string{"multilinestring", "polygon"},
"geometry",
[]string{"gc_polygon1_linestring1"},
},
// test intersects geometrycollection query for gc_multipolygon1_multilinestring1.
{
[][][][][]float64{
{{
{{-115.8563232421875, 38.53957267203905}, {-115.58166503906251, 38.54816542304656}},
{{-115.8343505859375, 38.45789034424927}, {-115.81237792968749, 38.19502155795575}},
}},
{{{{-116.64905548095702, 37.94920616351679}}}},
},
[]string{"multilinestring", "point"},
"geometry",
[]string{"gc_multipolygon1_multilinestring1"},
},
// test intersects geometrycollection query for gc_polygon1_linestring1 and gc_multipolygon1_multilinestring1.
{
[][][][][]float64{
{{{{-116.64905548095702, 37.94920616351679}, {-118.29528808593751, 34.52466147177172}}}},
{{
{{-115.8563232421875, 38.53957267203905}, {-115.58166503906251, 38.54816542304656}},
{{-115.8343505859375, 38.45789034424927}, {-115.81237792968749, 38.19502155795575}},
}},
},
[]string{"multipoint", "multilinestring"},
"geometry",
[]string{
"gc_polygon1_linestring1",
"gc_multipolygon1_multilinestring1",
},
},
// test intersects geometrycollection query for gc_polygon1_linestring1 and gc_multipolygon1_multilinestring1.
{
[][][][][]float64{
{{{
{-117.46582031249999, 36.146746777814364},
{-116.70227050781249, 36.146746777814364},
{-116.70227050781249, 36.69485094156225},
{-117.46582031249999, 36.69485094156225},
{-117.46582031249999, 36.146746777814364},
}}, {{
{-115.5267333984375, 38.06106741381201},
{-115.4937744140625, 37.18220222107978},
{-114.93896484374999, 37.304644804751106},
{-115.5267333984375, 38.06106741381201},
}}},
{{
{{-115.8563232421875, 38.53957267203905}, {-115.58166503906251, 38.54816542304656}},
{{-115.8343505859375, 38.45789034424927}, {-115.81237792968749, 38.19502155795575}},
}},
},
[]string{"multipolygon", "multilinestring"},
"geometry",
[]string{"gc_point1_multipoint1"},
},
}
i := setupGeoJsonShapesIndexForGeometryCollectionQuery(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 := runGeoShapeGeometryCollectionRelationQuery("intersects",
indexReader, test.points, test.types, 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.points)
}
}
}
func TestGeoJSONWithInQueryAgainstGeometryCollection(t *testing.T) {
tests := []struct {
points [][][][][]float64
types []string
field string
want []string
}{
// test within geometrycollection query for gc_multipoint2_multipolygon2_multiline2.
{
[][][][][]float64{
{{{{-122.40434646606444, 37.73400071182758}, {-122.39730834960938, 37.73691949864062}}}},
{{{
{-122.42511749267578, 37.760808496517235},
{-122.42314338684082, 37.74248523826606},
{-122.40082740783691, 37.756669194195815},
{-122.42511749267578, 37.760808496517235},
}}},
{
{{
{-122.46339797973633, 37.76637243960179},
{-122.46176719665527, 37.7502901437285},
{-122.43644714355469, 37.75911208915015},
{-122.46339797973633, 37.76637243960179},
}},
{{
{-122.43653297424315, 37.714720253587004},
{-122.40563392639159, 37.714720253587004},
{-122.40563392639159, 37.72904529863455},
{-122.43653297424315, 37.72904529863455},
{-122.43653297424315, 37.714720253587004},
}},
},
},
[]string{"linestring", "polygon", "multipolygon"},
"geometry",
[]string{"gc_multipoint2_multipolygon2_multiline2"},
},
// test within geometrycollection query.
{
[][][][][]float64{
{{{{-122.40434646606444, 37.73400071182758}, {-122.39730834960938, 37.73691949864062}}}},
{
{{
{-122.46339797973633, 37.76637243960179},
{-122.46176719665527, 37.7502901437285},
{-122.43644714355469, 37.75911208915015},
{-122.46339797973633, 37.76637243960179},
}},
{{
{-122.43653297424315, 37.714720253587004},
{-122.40563392639159, 37.714720253587004},
{-122.40563392639159, 37.72904529863455},
{-122.43653297424315, 37.72904529863455},
{-122.43653297424315, 37.714720253587004},
}},
},
},
[]string{"linestring", "multipolygon"},
"geometry", nil,
},
// test within geometrycollection for gc_multipoint2_multipolygon2_multiline2.
{
[][][][][]float64{
{{{
{-122.4491500854492, 37.78170504295941},
{-122.4862289428711, 37.747371884118664},
{-122.43078231811525, 37.6949593672454},
{-122.3799705505371, 37.72945260537779},
{-122.3928451538086, 37.78007695280165},
{-122.4491500854492, 37.78170504295941},
}}},
},
[]string{"polygon"},
"geometry",
[]string{"gc_multipoint2_multipolygon2_multiline2"},
},
// test within geometrycollection for gc_multipolygon3
// gc_multipolygon3's multipolygons within the geometrycollection is covered by the
// query's geometric collection of a polygon and a multipolygon.
{
[][][][][]float64{
{{{
{86.6162109375, 57.26716357153586},
{85.1220703125, 8119},
{84.462890625, 56.27996083172844},
{86.98974609375, 55.70235509327093},
{87.802734375, 56.77680831656842},
{86.6162109375, 57.26716357153586},
}}},
{
{{
{75.1025390625, 54.3549556895541},
{73.1689453125, 54.29088164657006},
{72.7294921875, 53.08082737207479},
{74.091796875, 51.998410382390325},
{76.79443359375, 53.396432127095984},
{75.1025390625, 54.3549556895541},
}},
{{
{80.1123046875, 55.57834467218206},
{78.9697265625, 55.65279803318956},
{78.5302734375, 54.635697306063854},
{79.87060546875, 54.18815548107151},
{80.96923828125, 54.80068486732233},
{80.1123046875, 55.57834467218206},
}},
},
},
[]string{"polygon", "multipolygon"},
"geometry",
[]string{"gc_multipolygon3"},
},
}
i := setupGeoJsonShapesIndexForGeometryCollectionQuery(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 := runGeoShapeGeometryCollectionRelationQuery("within", indexReader, test.points, test.types, 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.points)
}
}
}
func TestGeoJSONContainsQueryAgainstGeometryCollection(t *testing.T) {
tests := []struct {
points [][][][][]float64
types []string
field string
want []string
}{
// test contains for a geometrycollection that comprises of a linestring,
// polygon, multipolygon, point and multipoint for polygon2.
{
[][][][][]float64{
// linestring
{{{{7.457013130187988, 46.966401589723894}, {7.482891082763671, 46.94554547022893}}}},
// polygon
{{{
{7.466454505920409, 46.965054389418476},
{7.46143341064453, 46.9641171865865},
{7.466325759887694, 46.96101258493027},
{7.466454505920409, 46.965054389418476},
}}},
// multipolygon
{
{{
{7.4811744689941415, 46.957966385567474},
{7.478899955749511, 46.95492001277476},
{7.484478950500488, 46.95509576976545},
{7.4811744689941415, 46.957966385567474},
}},
{{
{7.466540336608888, 46.94753769790697},
{7.464609146118165, 46.946219320241674},
{7.468342781066894, 46.94592634301753},
{7.466540336608888, 46.94753769790697},
}},
{{
{7.504348754882812, 47.00425575323296},
{7.501087188720703, 47.001680295206874},
{7.507266998291015, 47.00191443288521},
{7.504348754882812, 47.00425575323296},
}},
},
// point
{{{{7.449932098388673, 46.95817142366062}}}},
// multipoint
{{{{7.479157447814942, 46.96370715518446}, {7.4532365798950195, 46.96657730900153}}}},
},
[]string{"linestring", "polygon", "multipolygon", "point", "multipoint"},
"geometry",
[]string{"multipolygon4"},
},
// test contains for a geometrycollection query with one point inside the multipoint lying outside
// polygon2.
{
[][][][][]float64{
// linestring
{{{{7.457013130187988, 46.966401589723894}, {7.482891082763671, 46.94554547022893}}}},
// polygon
{{{
{7.466454505920409, 46.965054389418476},
{7.46143341064453, 46.9641171865865},
{7.466325759887694, 46.96101258493027},
{7.466454505920409, 46.965054389418476},
}}},
// multipolygon
{
{{
{7.4811744689941415, 46.957966385567474},
{7.478899955749511, 46.95492001277476},
{7.484478950500488, 46.95509576976545},
{7.4811744689941415, 46.957966385567474},
}},
{{
{7.466540336608888, 46.94753769790697},
{7.464609146118165, 46.946219320241674},
{7.468342781066894, 46.94592634301753},
{7.466540336608888, 46.94753769790697},
}},
},
// point
{{{{7.449932098388673, 46.95817142366062}}}},
// multipoint
{{{{7.479157447814942, 46.96370715518446}, {7.475638389587402, 46.965200825877794}}}},
},
[]string{"linestring", "polygon", "multipolygon", "point", "multipoint"},
"geometry",
nil,
},
// test contains for a geometrycollection query with one point inside the multipoint lying outside
// polygon2.
{
[][][][][]float64{
// linestring
{{{{7.457013130187988, 46.966401589723894}, {7.482891082763671, 46.94554547022893}}}},
// polygon
{{{
{7.466454505920409, 46.965054389418476},
{7.46143341064453, 46.9641171865865},
{7.466325759887694, 46.96101258493027},
{7.466454505920409, 46.965054389418476},
}}},
// multipolygon
{
{{
{7.4811744689941415, 46.957966385567474},
{7.478899955749511, 46.95492001277476},
{7.484478950500488, 46.95509576976545},
{7.4811744689941415, 46.957966385567474},
}},
{{
{7.466540336608888, 46.94753769790697},
{7.464609146118165, 46.946219320241674},
{7.468342781066894, 46.94592634301753},
{7.466540336608888, 46.94753769790697},
}},
},
// point
{{{{7.449932098388673, 46.95817142366062}}}},
// multipoint
{{{{7.479157447814942, 46.96370715518446}, {7.4532365798950195, 46.96657730900153}}}},
},
[]string{"linestring", "polygon", "multipolygon", "point", "multipoint"},
"geometry",
[]string{"polygon2", "multipolygon4"},
},
}
i := setupGeoJsonShapesIndexForGeometryCollectionQuery(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 := runGeoShapeGeometryCollectionRelationQuery("contains",
indexReader, test.points, test.types, 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.points)
}
}
}
func runGeoShapeGeometryCollectionRelationQuery(relation string, i index.IndexReader,
points [][][][][]float64, types []string, field string,
) ([]string, error) {
var rv []string
s, _, err := geo.NewGeometryCollection(points, types)
if err != nil {
return nil, err
}
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
}
func setupGeoJsonShapesIndexForGeometryCollectionQuery(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)
}
// document gc_polygon1_linestring1
polygon1 := [][][][]float64{{{
{-118.15246582031249, 34.876918445772084},
{-118.46557617187499, 34.773203753940734},
{-118.3172607421875, 34.50655662164561},
{-117.91625976562499, 34.4793919710481},
{-117.76245117187499, 34.76417891445512},
{-118.15246582031249, 34.876918445772084},
}}}
linestring1 := [][][][]float64{{{
{-120.78918457031251, 36.87522650673951},
{-118.9215087890625, 34.95349314197422},
}}}
coordinates := [][][][][]float64{polygon1, linestring1}
types := []string{"polygon", "linestring"}
doc := document.NewDocument("gc_polygon1_linestring1")
doc.AddField(document.NewGeometryCollectionFieldWithIndexingOptions("geometry",
[]uint64{}, coordinates, types, document.DefaultGeoShapeIndexingOptions))
err = i.Update(doc)
if err != nil {
t.Fatal(err)
}
// document gc_multipolygon1_multilinestring1
multipolygon1 := [][][][]float64{
{{
{-117.24609374999999, 37.67512527892127},
{-117.61962890624999, 37.26530995561875},
{-116.597900390625, 37.56199695314352},
{-117.24609374999999, 37.67512527892127},
}},
{{
{-117.60864257812501, 38.71123253895224},
{-117.41638183593749, 38.36750215395045},
{-117.66357421875, 37.93986540897977},
{-116.6473388671875, 37.94852933714952},
{-117.1307373046875, 38.363195134453846},
{-116.75170898437501, 38.7283759182398},
{-117.60864257812501, 38.71123253895224},
}},
}
multilinestring1 := [][][][]float64{{
{{-118.9215087890625, 38.74123075381228}, {-118.78967285156249, 38.43207668538207}},
{{-118.57543945312501, 38.8225909761771}, {-118.45458984375, 38.522384090200845}},
{{-118.94897460937499, 38.788345355085625}, {-118.61938476562499, 38.86965182408357}},
}}
coordinates = [][][][][]float64{multipolygon1, multilinestring1}
types = []string{"multipolygon", "multilinestring"}
doc = document.NewDocument("gc_multipolygon1_multilinestring1")
doc.AddField(document.NewGeometryCollectionFieldWithIndexingOptions("geometry",
[]uint64{}, coordinates, types, document.DefaultGeoShapeIndexingOptions))
err = i.Update(doc)
if err != nil {
t.Fatal(err)
}
// document gc_point1_multipoint1
point1 := [][][][]float64{{{{-115.10925292968749, 36.20882309283712}}}}
multipoint1 := [][][][]float64{{{
{-117.13623046874999, 36.474306755095235},
{-118.57543945312501, 36.518465989675875},
{-118.58642578124999, 36.90597988519294},
{-119.5477294921875, 37.85316995894978},
}}}
coordinates = [][][][][]float64{point1, multipoint1}
types = []string{"point", "multipoint"}
doc = document.NewDocument("gc_point1_multipoint1")
doc.AddField(document.NewGeometryCollectionFieldWithIndexingOptions("geometry",
[]uint64{}, coordinates, types, document.DefaultGeoShapeIndexingOptions))
err = i.Update(doc)
if err != nil {
t.Fatal(err)
}
// document gc_multipoint2_multipolygon2_multiline2
multipoint2 := [][][][]float64{{{
{-122.4052906036377, 37.75626203719391},
{-122.42091178894044, 37.74757548736071},
}}}
multipolygon2 := [][][][]float64{
{{
{-122.46168136596681, 37.765151122096945},
{-122.46168136596681, 37.754972691904946},
{-122.45103836059569, 37.754972691904946},
{-122.451810836792, 37.7624370109886},
{-122.46168136596681, 37.765151122096945},
}},
{{
{-122.41902351379395, 37.726194088705576},
{-122.43533134460448, 37.71668926284967},
{-122.40777969360353, 37.71634978222733},
{-122.41902351379395, 37.726194088705576},
}},
}
multilinestring2 := [][][][]float64{{
{{-122.41284370422362, 37.73155698786267}, {-122.40700721740721, 37.73338978839743}},
{{-122.40434646606444, 37.73400071182758}, {-122.39730834960938, 37.73691949864062}},
}}
coordinates = [][][][][]float64{multipoint2, multipolygon2, multilinestring2}
types = []string{"multipoint", "multipolygon", "multiline"}
doc = document.NewDocument("gc_multipoint2_multipolygon2_multiline2")
doc.AddField(document.NewGeometryCollectionFieldWithIndexingOptions("geometry",
[]uint64{}, coordinates, types, document.DefaultGeoShapeIndexingOptions))
err = i.Update(doc)
if err != nil {
t.Fatal(err)
}
// document gc_multipolygon3
multipolygon3 := [][][][]float64{
{{
{85.60546875, 57.20771009775018},
{86.396484375, 55.99838095535963},
{87.03369140625, 56.71656572651468},
{85.60546875, 57.20771009775018},
}},
{{
{79.56298828125, 55.3915921070334},
{79.60693359375, 54.43171285946844},
{80.39794921875, 54.85131525968606},
{79.56298828125, 55.3915921070334},
}},
{{
{74.35546875, 54.13669645687002},
{74.1796875, 52.802761415419674},
{75.87158203125, 53.44880683542759},
{74.35546875, 54.13669645687002},
}},
}
coordinates = [][][][][]float64{multipolygon3}
types = []string{"multipolygon"}
doc = document.NewDocument("gc_multipolygon3")
doc.AddField(document.NewGeometryCollectionFieldWithIndexingOptions("geometry",
[]uint64{}, coordinates, types, document.DefaultGeoShapeIndexingOptions))
err = i.Update(doc)
if err != nil {
t.Fatal(err)
}
polygon2 := [][][][]float64{{{
{7.452635765075683, 46.96692874582506},
{7.449803352355956, 46.95817142366062},
{7.4573564529418945, 46.95149263607834},
{7.462162971496582, 46.945955640812095},
{7.483148574829102, 46.945311085627445},
{7.487225532531738, 46.957029058564686},
{7.4793291091918945, 46.96388288331302},
{7.464480400085448, 46.96903731827891},
{7.452635765075683, 46.96692874582506},
}}}
doc = document.NewDocument("polygon2")
doc.AddField(document.NewGeoShapeFieldWithIndexingOptions("geometry", []uint64{},
polygon2, "polygon", document.DefaultGeoShapeIndexingOptions))
err = i.Update(doc)
if err != nil {
t.Fatal(err)
}
multipolygon4 := [][][][]float64{
{{
{7.452635765075683, 46.96692874582506},
{7.449803352355956, 46.95817142366062},
{7.4573564529418945, 46.95149263607834},
{7.462162971496582, 46.945955640812095},
{7.483148574829102, 46.945311085627445},
{7.487225532531738, 46.957029058564686},
{7.4793291091918945, 46.96388288331302},
{7.464480400085448, 46.96903731827891},
{7.452635765075683, 46.96692874582506},
}},
{{
{7.4478721618652335, 47.00015837528636},
{7.5110435485839835, 47.00015837528636},
{7.5110435485839835, 47.00683108710118},
{7.4478721618652335, 47.00683108710118},
{7.4478721618652335, 47.00015837528636},
}},
}
doc = document.NewDocument("multipolygon4")
doc.AddField(document.NewGeoShapeFieldWithIndexingOptions("geometry", []uint64{},
multipolygon4, "multipolygon", document.DefaultGeoShapeIndexingOptions))
err = i.Update(doc)
if err != nil {
t.Fatal(err)
}
return i
}