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

1213 lines
34 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 TestGeoJsonPolygonIntersectsQuery(t *testing.T) {
tests := []struct {
polygon [][][]float64
field string
want []string
}{
// test intersecting query polygon for polygon1.
{[][][]float64{{
{77.57926940917969, 12.945257483731918},
{77.57875442504883, 12.942036966318216},
{77.58278846740721, 12.9424970427816},
{77.57926940917969, 12.945257483731918},
}}, "geometry", []string{"polygon1"}},
// test intersecting query polygon for polygon1, polygon2, circle1.
{
[][][]float64{{
{77.59562015533446, 12.94099133483504},
{77.59665012359619, 12.949356263896634},
{77.59313106536865, 12.951321981484776},
{77.59085655212402, 12.948477959536318},
{77.59562015533446, 12.94099133483504},
}},
"geometry",
[]string{"polygon1", "polygon2", "circle1"},
},
// test intersecting query polygon for polygon1, polygon2 and polygon3.
{[][][]float64{{
{77.5929594039917, 12.939151012774925},
{77.58321762084961, 12.94546660680072},
{77.59737968444824, 12.931998723107322},
{77.60111331939697, 12.955169724209911},
{77.59592056274414, 12.936265025833965},
{77.5929594039917, 12.939151012774925},
}}, "geometry", []string{"polygon1", "polygon2", "polygon3"}},
// test intersecting query polygon for polygon2 and the circle1.
{
[][][]float64{{
{77.59012699127197, 12.959853852513307},
{77.59836673736572, 12.959853852513307},
{77.59836673736572, 12.965541604118611},
{77.59012699127197, 12.965541604118611},
{77.59012699127197, 12.959853852513307},
}},
"geometry",
[]string{"polygon2", "circle1"},
},
// test intersecting query polygon for linestring2 and multilinestring2.
{
[][][]float64{{
{77.59669303894043, 12.989504011681609},
{77.60699272155762, 12.983231353311314},
{77.60115623474121, 12.993183897537897},
{77.59669303894043, 12.989504011681609},
}},
"geometry",
[]string{"linestring2", "multilinestring2"},
},
// test intersecting query polygon for multilinestring2.
{
[][][]float64{{
{77.60124206542969, 12.987162237749484},
{77.60330200195312, 12.992849364713313},
{77.59514808654785, 12.989671280403403},
{77.60124206542969, 12.987162237749484},
}},
"geometry",
[]string{"multilinestring2"},
},
// test intersecting query polygon for multipoint1.
{
[][][]float64{{
{77.56648063659668, 12.956382587313202},
{77.56819725036621, 12.949523559614263},
{77.5718879699707, 12.958222782120954},
{77.56648063659668, 12.956382587313202},
}},
"geometry",
[]string{"multipoint1"},
},
// test intersecting query polygon for envelope1.
{[][][]float64{{
{36.19986534118652, 50.00034673534484},
{36.19351387023926, 50.00464984215712},
{36.178321838378906, 49.991573824716205},
{36.19986534118652, 50.00034673534484},
}}, "geometry", []string{"envelope1"}},
// test intersecting query polygon for envelope1.
{[][][]float64{{
{36.170082092285156, 49.99229116680205},
{36.14982604980469, 49.99002874388075},
{36.227073669433594, 49.98754547425633},
{36.170082092285156, 49.99229116680205},
}}, "geometry", []string{"envelope1"}},
}
i := setupGeoJsonShapesIndexForPolygonQuery(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 := runGeoShapePolygonQueryWithRelation("intersects",
indexReader, test.polygon, 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.polygon)
}
}
}
func TestGeoJsonPolygonContainsQuery(t *testing.T) {
tests := []struct {
polygon [][][]float64
field string
want []string
}{
// test containment query polygon for polygon1.
{
[][][]float64{{
{77.5843334197998, 12.952702156906767},
{77.58510589599608, 12.952702156906767},
{77.58510589599608, 12.953622269606669},
{77.5843334197998, 12.953622269606669},
{77.5843334197998, 12.952702156906767},
}},
"geometry",
[]string{"polygon1"},
},
// test containment query polygon for circle1.
{
[][][]float64{{
{77.59025573730469, 12.953810474058429},
{77.59145736694336, 12.953810474058429},
{77.59145736694336, 12.954918786278716},
{77.59025573730469, 12.954918786278716},
{77.59025573730469, 12.953810474058429},
}},
"geometry",
[]string{"circle1"},
},
// test containment query polygon for polygon2, polygon3.
{
[][][]float64{{
{77.60235786437988, 12.956884459972992},
{77.60124206542969, 12.956800814599926},
{77.6008129119873, 12.955713422193524},
{77.60244369506836, 12.955211547173878},
{77.60313034057617, 12.955880713641998},
{77.60235786437988, 12.956884459972992},
}},
"geometry",
[]string{"polygon2", "polygon3"},
},
// test containment query polygon which resides within a hole in polygonWithHole1.
{
[][][]float64{{
{77.60012626647949, 12.97963495776207},
{77.5978946685791, 12.978213112610835},
{77.60089874267577, 12.977962197916442},
{77.60012626647949, 12.97963495776207},
}},
"geometry", nil,
},
// test containment query polygon which resides within polygonWithHole1.
{
[][][]float64{{
{77.59978294372559, 12.984067716910454},
{77.59780883789062, 12.982227713276774},
{77.60089874267577, 12.982227713276774},
{77.59978294372559, 12.984067716910454},
}},
"geometry",
[]string{"polygonWithHole1"},
},
// test with query polygon for polygon4 with a single vertex lying outside.
{
[][][]float64{{
{-121.48138761520384, 38.50964107572585},
{-121.48226737976073, 38.509238097766875},
{-121.48115158081055, 38.50781086602439},
{-121.48014307022095, 38.50806273250507},
{-121.48138761520384, 38.50964107572585},
}},
"geometry", nil,
},
// test with query polygon for polygon4.
{
[][][]float64{{
{-121.48381233215332, 38.507974579337045},
{-121.48361384868622, 38.507869634948676},
{-121.48361921310425, 38.50765135013098},
{-121.48343682289122, 38.50797038156446},
{-121.48381233215332, 38.507974579337045},
}},
"geometry",
[]string{"polygon4"},
},
// test with query polygon for multipolygon1.
{[][][]float64{{
{-121.47578716278075, 38.51617236229197},
{-121.47578716278075, 38.51566868518406},
{-121.47546529769896, 38.516105205547866},
{-121.47578716278075, 38.51617236229197},
}}, "geometry", []string{"multipolygon1"}},
// test with query polygon for envelope1.
{
[][][]float64{{
{36.197547912597656, 49.99642946989866},
{36.18939399719238, 49.988649165474},
{36.20201110839844, 49.98853879749191},
{36.1970329284668, 49.980150089789376},
{
36.205787658691406,
49.9885939815146,
},
{36.197547912597656, 49.99642946989866},
}},
"geometry",
[]string{"envelope1"},
},
// test with query polygon for no hits. (envelope1 has one vertex outside the polygon)
{[][][]float64{{
{36.19832038879394, 49.99626394461266},
{36.19016647338867, 49.98439981533724},
{36.20698928833008, 49.98158510403259},
{36.19832038879394, 49.99626394461266},
}}, "geometry", nil},
}
i := setupGeoJsonShapesIndexForPolygonQuery(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 := runGeoShapePolygonQueryWithRelation("contains",
indexReader, test.polygon, 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.polygon)
}
}
}
func TestGeoJsonPolygonWithInQuery(t *testing.T) {
tests := []struct {
polygon [][][]float64
field string
want []string
}{
// test with query polygon for polygon1.
{
[][][]float64{{
{77.58407592773438, 12.956382587313202},
{77.57746696472168, 12.943249893344905},
{77.5920581817627, 12.944086391304364},
{77.59454727172852, 12.95353862313803},
{77.58407592773438, 12.956382587313202},
}},
"geometry",
[]string{"polygon1"},
},
// test with query polygon for circle1 and polygon3.
{
[][][]float64{{
{77.59248733520508, 12.967841760870071},
{77.58261680603027, 12.968594534825176},
{77.57789611816406, 12.957302686416881},
{77.58896827697754, 12.945341132980488},
{77.60450363159178, 12.947599652080394},
{77.60673522949219, 12.96483064227584},
{77.59248733520508, 12.967841760870071},
}},
"geometry",
[]string{"polygon3", "circle1"},
},
// test with query polygon for linestring2, multilinestring2.
{
[][][]float64{{
{77.59909629821777, 12.998118204343788},
{77.58931159973145, 12.978882217224443},
{77.61128425598145, 12.983565899088745},
{77.59909629821777, 12.998118204343788},
}},
"geometry",
[]string{"linestring2", "multilinestring2"},
},
// test with query polygon for multipoint1.
{[][][]float64{{
{77.55703926086426, 12.964245142762644},
{77.5631332397461, 12.944253690559432},
{77.57429122924805, 12.957720912158363},
{77.55703926086426, 12.964245142762644},
}}, "geometry", []string{"multipoint1"}},
// test with query polygon with no results.
// (polygon4 has one vertex lying outside the query polygon).
{
[][][]float64{{
{-121.48812532424927, 38.51058134885975},
{-121.48258924484252, 38.500153704565065},
{-121.47492885589598, 38.50799556819636},
{-121.48630142211913, 38.51147123890908},
{-121.48812532424927, 38.51058134885975},
}},
"geometry", nil,
},
// test with query polygon for polygon4.
{[][][]float64{{
{-121.48366212844849, 38.510161585585045},
{-121.48533582687377, 38.50841534409804},
{-121.48376941680908, 38.507777283760426},
{-121.48370504379272, 38.50250467407243},
{-121.48010015487672, 38.50253825879518},
{-121.48018598556519, 38.504502937819765},
{-121.47756814956665, 38.50755899866278},
{-121.48113012313843, 38.50866720846446},
{-121.48115158081055, 38.51017837616302},
{-121.48366212844849, 38.510161585585045},
}}, "geometry", []string{"polygon4"}},
// test with query polygon for envelope1.
{
[][][]float64{{
{36.20587348937988, 50.00470500769241},
{36.17969512939453, 49.993946530777606},
{36.19368553161621, 49.971870325635074},
{36.21119499206543, 49.983075265826656},
{36.20587348937988, 50.00470500769241},
}},
"geometry",
[]string{"envelope1"},
},
// test with query polygon for linestring2 which lies outside except the endpoints.
{
[][][]float64{{
{8.515305519104004, 47.392597129887},
{8.514232635498047, 47.38896544894171},
{8.507537841796875, 47.38815191810328},
{8.514318466186523, 47.38725120859953},
{8.516035079956053, 47.383357642070706},
{8.516979217529295, 47.38733837470806},
{8.522472381591797, 47.38794853343167},
{8.516507148742676, 47.388994503382285},
{8.515305519104004, 47.392597129887},
}},
"geometry", nil,
},
// test with query polygon for all the shapes.
{
[][][]float64{{
{-135.0, -38.0},
{149.0, -38.0},
{149.0, 77.0},
{-135.0, 77.0},
}},
"geometry",
[]string{
"polygon1", "polygon2", "polygon3", "envelope1", "circle1", "linestring1",
"linestring2", "linestring3", "multilinestring1", "multilinestring2", "multipoint1",
"polygonWithHole1", "polygon4", "multipolygon1",
},
},
}
i := setupGeoJsonShapesIndexForPolygonQuery(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 := runGeoShapePolygonQueryWithRelation("within",
indexReader, test.polygon, 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.polygon)
}
}
}
func runGeoShapePolygonQueryWithRelation(relation string, i index.IndexReader,
points [][][]float64, field string,
) ([]string, error) {
var rv []string
s := geo.NewGeoJsonPolygon(points)
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 setupGeoJsonShapesIndexForPolygonQuery(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)
}
polygon2 := [][][][]float64{{{
{77.59527683258057, 12.951112863329588},
{77.59420394897461, 12.947976069940545},
{77.59579181671143, 12.946010325958518},
{77.60347366333008, 12.950401860289055},
{77.60673522949219, 12.95600618215462},
{77.60107040405273, 12.96345053407734},
{77.5984525680542, 12.961861309096507},
{77.59527683258057, 12.951112863329588},
}}}
doc = document.NewDocument("polygon2")
doc.AddField(document.NewGeoShapeFieldWithIndexingOptions("geometry", []uint64{},
polygon2, "polygon", document.DefaultGeoShapeIndexingOptions))
err = i.Update(doc)
if err != nil {
t.Fatal(err)
}
polygon3 := [][][][]float64{{{
{77.59974002838135, 12.953789562459688},
{77.60347366333008, 12.953789562459688},
{77.60347366333008, 12.957720912158363},
{77.59974002838135, 12.957720912158363},
{77.59974002838135, 12.953789562459688},
}}}
doc = document.NewDocument("polygon3")
doc.AddField(document.NewGeoShapeFieldWithIndexingOptions("geometry", []uint64{},
polygon3, "polygon", document.DefaultGeoShapeIndexingOptions))
err = i.Update(doc)
if err != nil {
t.Fatal(err)
}
/*polygon4 := [][][][]float64{{{{8.515305519104004, 47.392597129887},
{8.514232635498047, 47.38896544894171}, {8.507537841796875, 47.38815191810328},
{8.514318466186523, 47.38725120859953}, {8.516035079956053, 47.383357642070706},
{8.516979217529295, 47.38733837470806}, {8.522472381591797, 47.38794853343167},
{8.516507148742676, 47.388994503382285}, {8.515305519104004, 47.392597129887}}}}
doc = document.NewDocument("polygon4")
doc.AddField(document.NewGeoShapeFieldWithIndexingOptions("geometry", []uint64{},
polygon4, "polygon", document.DefaultGeoShapeIndexingOptions))
err = i.Update(doc)
if err != nil {
t.Fatal(err)
}*/
// not working envelope
envelope1 := [][][][]float64{{{
{36.18896484375, 49.9799293145682},
{36.20613098144531, 49.99714673955337},
}}}
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.59253025054932, 12.955587953533424}, "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)
}
linestring1 := [][][][]float64{{{
{77.60188579559325, 12.982604078764705},
{77.60557651519775, 12.987329508048184},
}}}
doc = document.NewDocument("linestring2")
doc.AddField(document.NewGeoShapeFieldWithIndexingOptions("geometry", []uint64{},
linestring1, "linestring", document.DefaultGeoShapeIndexingOptions))
err = i.Update(doc)
if err != nil {
t.Fatal(err)
}
linestring3 := [][][][]float64{{{
{8.51539134979248, 47.390592472948434},
{8.520884513854979, 47.388006643417924},
}}}
doc = document.NewDocument("linestring3")
doc.AddField(document.NewGeoShapeFieldWithIndexingOptions("geometry", []uint64{},
linestring3, "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)
}
multilinestring1 := [][][][]float64{{
{
{77.6015853881836, 12.990089451715061},
{77.60476112365723, 12.987747683302153},
},
{{77.59875297546387, 12.988751301039581}, {77.59446144104004, 12.98197680263484}},
{{77.60188579559325, 12.982604078764705}, {77.60557651519775, 12.987329508048184}},
}}
doc = document.NewDocument("multilinestring2")
doc.AddField(document.NewGeoShapeFieldWithIndexingOptions("geometry", []uint64{},
multilinestring1, "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)
}
polygon4 := [][][][]float64{{{
{-121.48125886917113, 38.51009442323401},
{-121.48361921310425, 38.51012800441735},
{-121.48497104644774, 38.50858325377352},
{-121.48366212844849, 38.507861239391026},
{-121.48353338241577, 38.50277335141579},
{-121.4803147315979, 38.50267259752949},
{-121.48033618927, 38.5046204810195},
{-121.47771835327147, 38.50754220747402},
{-121.48123741149902, 38.508616835661655},
{-121.48125886917113, 38.51009442323401},
}}}
doc = document.NewDocument("polygon4")
doc.AddField(document.NewGeoShapeFieldWithIndexingOptions("geometry", []uint64{},
polygon4, "polygon", document.DefaultGeoShapeIndexingOptions))
err = i.Update(doc)
if err != nil {
t.Fatal(err)
}
multipolygon1 := [][][][]float64{
{{
{-121.49104356765746, 38.52149433504263},
{-121.47857666015625, 38.51592052417851},
{-121.47688150405884, 38.515970891871696},
{-121.4770746231079, 38.51714612804143},
{-121.49033546447754, 38.52221621271097},
{-121.49104356765746, 38.52149433504263},
}},
{{
{-121.47647380828859, 38.51714612804143},
{-121.47658109664916, 38.51477884701455},
{-121.4741563796997, 38.5159876810949},
{-121.47647380828859, 38.51714612804143},
}},
}
doc = document.NewDocument("multipolygon1")
doc.AddField(document.NewGeoShapeFieldWithIndexingOptions("geometry", []uint64{},
multipolygon1, "multipolygon", document.DefaultGeoShapeIndexingOptions))
err = i.Update(doc)
if err != nil {
t.Fatal(err)
}
return i
}
func TestGeoJsonMultiPolygonWithInQuery(t *testing.T) {
tests := []struct {
polygon [][][][]float64
field string
want []string
}{
// test within multipolygon query for multipolygon1.
// (where each query polygon contains each of the indexed polygons)
{
[][][][]float64{
{
{
{-121.49458408355713, 38.53270780324851},
{-121.48823261260985, 38.52533866992879},
{-121.48048639297485, 38.53253994984147},
{-121.49458408355713, 38.53270780324851},
},
},
{{
{-121.48700952529907, 38.53306029412857},
{-121.48160219192505, 38.53306029412857},
{-121.48160219192505, 38.53829709805414},
{-121.48700952529907, 38.53829709805414},
{-121.48700952529907, 38.53306029412857},
}},
{{
{-121.47344827651976, 38.54475865436684},
{-121.46396398544312, 38.54475865436684},
{-121.46396398544312, 38.55366961462033},
{-121.47344827651976, 38.55366961462033},
{-121.47344827651976, 38.54475865436684},
}},
},
"geometry",
[]string{"multipolygon1"},
},
// test within multipolygon query. (only partial containment of the three
// indexed polygons by the two query polygons)
{
[][][][]float64{
{
{
{-121.49458408355713, 38.53270780324851},
{-121.48823261260985, 38.52533866992879},
{-121.48048639297485, 38.53253994984147},
{-121.49458408355713, 38.53270780324851},
},
},
{{
{-121.48700952529907, 38.53306029412857},
{-121.48160219192505, 38.53306029412857},
{-121.48160219192505, 38.53829709805414},
{-121.48700952529907, 38.53829709805414},
{-121.48700952529907, 38.53306029412857},
}},
{{
{-121.4734697341919, 38.544825784372485},
{-121.4644145965576, 38.544825784372485},
{-121.4644145965576, 38.5537199558913},
{-121.4734697341919, 38.5537199558913},
{-121.4734697341919, 38.544825784372485},
}},
},
"geometry", nil,
},
// test within multipolygon query for multilinestring1.
{[][][][]float64{
{{
{-121.49876832962036, 38.551739839324334},
{-121.49814605712889, 38.54553064564853},
{-121.49158000946044, 38.54908841140355},
{-121.49876832962036, 38.551739839324334},
}},
{
{
{-121.49258852005006, 38.54294612052762},
{-121.49117231369017, 38.54294612052762},
{-121.49117231369017, 38.54526212788182},
{-121.49258852005006, 38.54526212788182},
{-121.49258852005006, 38.54294612052762},
},
},
}, "geometry", []string{"multilinestring1"}},
// test within multipolygon query for multipoint1.
{[][][][]float64{
{{
{-121.50286674499512, 38.564810956372185},
{-121.49694442749023, 38.56226068115802},
{-121.48406982421875, 38.5675624676039},
{-121.4875030517578, 38.57514535565976},
{-121.50286674499512, 38.564810956372185},
}},
{{
{-121.48685932159422, 38.565163289911425},
{-121.48623704910278, 38.56283114531348},
{-121.48357629776001, 38.565129734410704},
{-121.48685932159422, 38.565163289911425},
}},
{
{
{-121.49430513381958, 38.56195866888961},
{-121.4899492263794, 38.5584518779682},
{-121.48842573165892, 38.56194189039304},
{-121.49430513381958, 38.56195866888961},
},
},
}, "geometry", []string{"multipoint1"}},
}
i := setupGeoJsonShapesIndexForMultiPolygonQuery(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 := runGeoShapeMultiPolygonQueryWithRelation("within",
indexReader, test.polygon, 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.polygon)
}
}
}
func runGeoShapeMultiPolygonQueryWithRelation(relation string,
i index.IndexReader,
points [][][][]float64, field string,
) ([]string, error) {
var rv []string
s := geo.NewGeoJsonMultiPolygon(points)
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 setupGeoJsonShapesIndexForMultiPolygonQuery(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)
}
multipolygon1 := [][][][]float64{{{
{-121.49140834808348, 38.5320028163074},
{-121.49112939834593, 38.52916601331889},
{-121.48889780044556, 38.52913244101627},
{-121.4887261390686, 38.527655244193205},
{-121.48559331893921, 38.52794061412457},
{-121.48638725280762, 38.53213710006686},
{-121.49140834808348, 38.5320028163074},
}}, // polygon1
{{
{-121.48677349090575, 38.533194575914315},
{-121.48179531097412, 38.533194575914315},
{-121.48179531097412, 38.53814604174215},
{-121.48677349090575, 38.53814604174215},
{-121.48677349090575, 38.533194575914315},
}}, // polygon2
{{
{-121.47334098815918, 38.553485029658475},
{-121.47329807281494, 38.54485934935182},
{-121.46415710449219, 38.54526212788182},
{-121.47334098815918, 38.553485029658475},
}}}
doc := document.NewDocument("multipolygon1")
doc.AddField(document.NewGeoShapeFieldWithIndexingOptions("geometry", []uint64{},
multipolygon1, "multipolygon", document.DefaultGeoShapeIndexingOptions))
err = i.Update(doc)
if err != nil {
t.Fatal(err)
}
multilinestring1 := [][][][]float64{{
{
{-121.4983820915222, 38.55081688500274},
{-121.49649381637572, 38.550447699956685},
},
{{-121.49655818939209, 38.548635309508775}, {-121.49370431900023, 38.54811507788636}},
{{-121.49134397506714, 38.54490969679143}, {-121.4919662475586, 38.54304681805045}},
}}
doc = document.NewDocument("multilinestring1")
doc.AddField(document.NewGeoShapeFieldWithIndexingOptions("geometry", []uint64{},
multilinestring1, "multilinestring", document.DefaultGeoShapeIndexingOptions))
err = i.Update(doc)
if err != nil {
t.Fatal(err)
}
multipoint1 := [][][][]float64{{{
{-121.48960590362547, 38.56066671319285},
{-121.4933180809021, 38.56157276247755},
{-121.4973521232605, 38.56318348855919},
{-121.48582935333252, 38.56736114108619},
{-121.50104284286498, 38.56449217691959},
{-121.4881682395935, 38.57158887950165},
}}}
doc = document.NewDocument("multipoint1")
doc.AddField(document.NewGeoShapeFieldWithIndexingOptions("geometry", []uint64{},
multipoint1, "multipoint", document.DefaultGeoShapeIndexingOptions))
err = i.Update(doc)
if err != nil {
t.Fatal(err)
}
return i
}
func setupGeoJsonPolygonS2LoopPortingIssue(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{{{
{-135.0, -38.0},
{149.0, -38.0},
{149.0, 77.0},
{-135.0, 77.0},
}}}
doc := document.NewDocument("polygon1")
doc.AddField(document.NewGeoShapeFieldWithIndexingOptions("geometry", []uint64{},
polygon1, "polygon", document.DefaultGeoShapeIndexingOptions))
err = i.Update(doc)
if err != nil {
t.Fatal(err)
}
return i
}
func TestGeoJsonPolygonContainsQueryS2LoopPortingIssue(t *testing.T) {
tests := []struct {
polygon [][][]float64
field string
want []string
}{
// test containment query polygon for polygon1.
{
[][][]float64{{
{13.007812500000002, 37.99616267972809},
{13.559375000000002, 37.99616267972809},
{13.559375000000002, 38.472819658516866},
{13.007812500000002, 38.472819658516866},
}},
"geometry",
[]string{"polygon1"},
},
// test containment query polygon for polygon1.
{
[][][]float64{{
{13.007812500000002, 37.99616267972809},
{13.359375000000002, 37.99616267972809},
{13.359375000000002, 38.272819658516866},
{13.007812500000002, 38.272819658516866},
}},
"geometry",
[]string{"polygon1"},
},
}
i := setupGeoJsonPolygonS2LoopPortingIssue(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 := runGeoShapePolygonQueryWithRelation("contains",
indexReader, test.polygon, 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.polygon)
}
}
}
func TestGeoJsonPolygonIntersectsQuery1(t *testing.T) {
tests := []struct {
polygon [][][]float64
field string
want []string
}{
// test non-intersecting query polygon.
{[][][]float64{{
{
97.745361328125,
68.21644657802169,
},
{
97.701416015625,
67.97051353559428,
},
{
97.80029296875,
67.97875365614591,
},
{
97.745361328125,
68.21644657802169,
},
}}, "geometry", nil},
// test intersecting query polygon.
{[][][]float64{{
{
77.59214401245117,
12.966043458314124,
},
{
77.58853912353516,
12.95232574618635,
},
{
77.60943889617919,
12.956466232826733,
},
{
77.59214401245117,
12.966043458314124,
},
}}, "geometry", nil},
// test intersecting query polygon for polygon1.
{[][][]float64{{
{97.0806884765625, 61.61423180712503},
{96.7510986328125, 61.54625879879804},
{97.305908203125, 61.367777577924},
{97.0806884765625, 61.61423180712503},
}}, "geometry", []string{"polygon1"}},
}
i := setupGeoJsonShapesIndexForPolygonQuery1(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 := runGeoShapePolygonQueryWithRelation("intersects",
indexReader, test.polygon, 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.polygon)
}
}
}
func setupGeoJsonShapesIndexForPolygonQuery1(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{{{
{96.69202458735312, 61.59480859768306},
{96.79202458735311, 61.39480859768306},
{96.79202458735311, 61.59480859768306},
{96.69202458735312, 61.59480859768306},
}}}
doc := document.NewDocument("polygon1")
doc.AddField(document.NewGeoShapeFieldWithIndexingOptions("geometry", []uint64{},
polygon1, "polygon", document.DefaultGeoShapeIndexingOptions))
err = i.Update(doc)
if err != nil {
t.Fatal(err)
}
polygon2 := [][][][]float64{{{
{91.35604953911839, 65.11164029408492},
{91.45604953911838, 64.91164029408492},
{91.45604953911838, 65.11164029408492},
{91.35604953911839, 65.11164029408492},
}}}
doc = document.NewDocument("polygon2")
doc.AddField(document.NewGeoShapeFieldWithIndexingOptions("geometry", []uint64{},
polygon2, "polygon", document.DefaultGeoShapeIndexingOptions))
err = i.Update(doc)
if err != nil {
t.Fatal(err)
}
return i
}