make geos.QueryIndex less hacky
parent
5aed40b843
commit
d6e46f78c9
|
@ -1,6 +1,10 @@
|
||||||
package geos
|
package geos
|
||||||
|
|
||||||
import "testing"
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
func TestFoo(t *testing.T) {
|
func TestFoo(t *testing.T) {
|
||||||
_ = NewGeos()
|
_ = NewGeos()
|
||||||
|
@ -23,3 +27,63 @@ func BenchmarkWKB(b *testing.B) {
|
||||||
g.Destroy(geom)
|
g.Destroy(geom)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestIndexQuery(t *testing.T) {
|
||||||
|
g := NewGeos()
|
||||||
|
defer g.Finish()
|
||||||
|
|
||||||
|
idx := g.CreateIndex()
|
||||||
|
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
p := g.FromWkt(fmt.Sprintf("POLYGON((%d 0, 10 0, 10 10, %d 10, %d 0))", i, i, i))
|
||||||
|
if p == nil {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
g.IndexAdd(idx, p)
|
||||||
|
}
|
||||||
|
|
||||||
|
if geoms := g.IndexQuery(idx, g.Point(0, 10.000001)); len(geoms) != 0 {
|
||||||
|
t.Fatal(geoms)
|
||||||
|
}
|
||||||
|
|
||||||
|
if geoms := g.IndexQuery(idx, g.Point(9.5, 5)); len(geoms) != 10 {
|
||||||
|
t.Fatal(geoms)
|
||||||
|
}
|
||||||
|
|
||||||
|
if geoms := g.IndexQuery(idx, g.Point(0.5, 5)); len(geoms) != 1 {
|
||||||
|
t.Fatal(geoms)
|
||||||
|
}
|
||||||
|
if geoms := g.IndexQuery(idx, g.Point(4.5, 5)); len(geoms) != 5 {
|
||||||
|
t.Fatal(geoms)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkIndexQuery(b *testing.B) {
|
||||||
|
g := NewGeos()
|
||||||
|
defer g.Finish()
|
||||||
|
|
||||||
|
idx := g.CreateIndex()
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
p := g.FromWkt(fmt.Sprintf("POLYGON((%d 0, 10 0, 10 10, %d 10, %d 0))", i, i, i))
|
||||||
|
if p == nil {
|
||||||
|
b.Fatal()
|
||||||
|
}
|
||||||
|
g.IndexAdd(idx, p)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if geoms := g.IndexQuery(idx, g.Point(8.5, 5)); len(geoms) != 9 {
|
||||||
|
b.Fatal(geoms)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if geoms := g.IndexQuery(idx, g.Point(0, 0)); len(geoms) != 10 {
|
||||||
|
// b.Fatal(geoms)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if geoms := g.IndexQuery(idx, g.Point(5, 5)); len(geoms) != 10 {
|
||||||
|
// b.Fatal(geoms)
|
||||||
|
// }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -3,12 +3,13 @@ package geos
|
||||||
/*
|
/*
|
||||||
#cgo LDFLAGS: -lgeos_c
|
#cgo LDFLAGS: -lgeos_c
|
||||||
#include "geos_c.h"
|
#include "geos_c.h"
|
||||||
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
extern void goLogString(char *msg);
|
extern void goLogString(char *msg);
|
||||||
extern void goSendQueryResult(size_t, void *);
|
|
||||||
|
|
||||||
void debug_wrap(const char *fmt, ...) {
|
void debug_wrap(const char *fmt, ...) {
|
||||||
va_list a_list;
|
va_list a_list;
|
||||||
|
@ -31,9 +32,33 @@ void initGEOS_debug() {
|
||||||
return initGEOS(devnull, debug_wrap);
|
return initGEOS(devnull, debug_wrap);
|
||||||
}
|
}
|
||||||
|
|
||||||
// wrap goIndexSendQueryResult
|
typedef struct {
|
||||||
void IndexQuerySendCallback(void *item, void *userdata) {
|
uint32_t num;
|
||||||
goIndexSendQueryResult((size_t)item, userdata);
|
uint32_t *arr;
|
||||||
|
uint32_t arrCap;
|
||||||
|
} queryResult;
|
||||||
|
|
||||||
|
void queryResultAppend(queryResult *r, int idx) {
|
||||||
|
r->num += 1;
|
||||||
|
if (r->num >= r->arrCap) {
|
||||||
|
uint32_t newCap = r->arrCap > 0 ? r->arrCap * 2 : 8;
|
||||||
|
uint32_t *newArr = malloc(sizeof(uint32_t) * newCap);
|
||||||
|
if (r->arrCap == 0) {
|
||||||
|
r->arr = newArr;
|
||||||
|
} else {
|
||||||
|
memcpy(newArr, r->arr, r->num-1);
|
||||||
|
free(r->arr);
|
||||||
|
r->arr = newArr;
|
||||||
|
}
|
||||||
|
r->arrCap = newCap;
|
||||||
|
}
|
||||||
|
r->arr[r->num] = idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IndexQueryCallback(void *item, void *userdata) {
|
||||||
|
int idx = (size_t)item;
|
||||||
|
queryResult *result = (queryResult *)userdata;
|
||||||
|
queryResultAppend(result, idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IndexAdd(
|
void IndexAdd(
|
||||||
|
@ -47,14 +72,18 @@ void IndexAdd(
|
||||||
GEOSSTRtree_insert_r(handle, tree, g, (void *)id);
|
GEOSSTRtree_insert_r(handle, tree, g, (void *)id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// query with our custom callback
|
// query with our custom callback
|
||||||
void IndexQuery(
|
uint32_t *IndexQuery(
|
||||||
GEOSContextHandle_t handle,
|
GEOSContextHandle_t handle,
|
||||||
GEOSSTRtree *tree,
|
GEOSSTRtree *tree,
|
||||||
const GEOSGeometry *g,
|
const GEOSGeometry *g,
|
||||||
void *userdata)
|
uint32_t *num)
|
||||||
{
|
{
|
||||||
GEOSSTRtree_query_r(handle, tree, g, IndexQuerySendCallback, userdata);
|
queryResult result = {0};
|
||||||
}
|
GEOSSTRtree_query_r(handle, tree, g, IndexQueryCallback, &result);
|
||||||
|
*num = result.num;
|
||||||
|
return result.arr;
|
||||||
|
}
|
||||||
*/
|
*/
|
||||||
import "C"
|
import "C"
|
||||||
|
|
|
@ -4,10 +4,11 @@ package geos
|
||||||
#cgo LDFLAGS: -lgeos_c
|
#cgo LDFLAGS: -lgeos_c
|
||||||
#include "geos_c.h"
|
#include "geos_c.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
extern void IndexQuerySendCallback(void *, void *);
|
extern void IndexQueryCallback(void *, void *);
|
||||||
extern void goIndexSendQueryResult(size_t, void *);
|
extern void goIndexSendQueryResult(size_t, void *);
|
||||||
extern void IndexQuery(GEOSContextHandle_t, GEOSSTRtree *, const GEOSGeometry *, void *);
|
extern uint32_t *IndexQuery(GEOSContextHandle_t, GEOSSTRtree *, const GEOSGeometry *, uint32_t *);
|
||||||
extern void IndexAdd(GEOSContextHandle_t, GEOSSTRtree *, const GEOSGeometry *, size_t);
|
extern void IndexAdd(GEOSContextHandle_t, GEOSSTRtree *, const GEOSGeometry *, size_t);
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
@ -47,23 +48,17 @@ func (this *Geos) IndexAdd(index *Index, geom *Geom) {
|
||||||
|
|
||||||
// IndexQuery queries the index for intersections with geom.
|
// IndexQuery queries the index for intersections with geom.
|
||||||
func (this *Geos) IndexQuery(index *Index, geom *Geom) []IndexGeom {
|
func (this *Geos) IndexQuery(index *Index, geom *Geom) []IndexGeom {
|
||||||
hits := make(chan int)
|
var num C.uint32_t
|
||||||
go func() {
|
r := C.IndexQuery(this.v, index.v, geom.v, &num)
|
||||||
// using a pointer to our hits chan to pass it through
|
if r == nil {
|
||||||
// C.IndexQuerySendCallback (in C.IndexQuery) back
|
return nil
|
||||||
// to goIndexSendQueryResult
|
}
|
||||||
C.IndexQuery(this.v, index.v, geom.v, unsafe.Pointer(&hits))
|
hits := (*[2 << 16]C.uint32_t)(unsafe.Pointer(r))[:num]
|
||||||
close(hits)
|
defer C.free(unsafe.Pointer(r))
|
||||||
}()
|
|
||||||
var geoms []IndexGeom
|
var geoms []IndexGeom
|
||||||
for idx := range hits {
|
for idx := range hits {
|
||||||
geoms = append(geoms, index.geoms[idx])
|
geoms = append(geoms, index.geoms[idx])
|
||||||
}
|
}
|
||||||
return geoms
|
return geoms
|
||||||
}
|
}
|
||||||
|
|
||||||
//export goIndexSendQueryResult
|
|
||||||
func goIndexSendQueryResult(id C.size_t, ptr unsafe.Pointer) {
|
|
||||||
results := *(*chan int)(ptr)
|
|
||||||
results <- int(id)
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue