improve memory handling of geos geometries

master
Oliver Tonnhofer 2013-05-28 09:33:59 +02:00
parent 4739fcc484
commit 5eed0502ea
4 changed files with 54 additions and 9 deletions

View File

@ -86,7 +86,6 @@ func PolygonWkb(g *geos.Geos, nodes []element.Node) (*element.Geometry, error) {
if wkb == nil {
return nil, errors.New("could not create wkb")
}
g.DestroyLater(geom)
return &element.Geometry{
Wkb: wkb,
Geom: geom,
@ -105,15 +104,18 @@ func Polygon(g *geos.Geos, nodes []element.Node) (*geos.Geom, error) {
return nil, err
}
}
geom, err := coordSeq.AsLinearRing(g)
ring, err := coordSeq.AsLinearRing(g)
if err != nil {
g.DestroyCoordSeq(coordSeq)
return nil, err
}
// geom inherited by Polygon, no destroy
// ring inherited by Polygon, no destroy
geom = g.CreatePolygon(geom, nil)
if err != nil {
return nil, err
geom := g.CreatePolygon(ring, nil)
if geom == nil {
g.Destroy(ring)
return nil, errors.New("unable to create polygon")
}
g.DestroyLater(geom)
return geom, nil
}

View File

@ -55,6 +55,28 @@ func TestPolygonNotClosed(t *testing.T) {
}
}
func TestPolygonIntersection(t *testing.T) {
nodes := []element.Node{
element.Node{Lat: 0, Long: 0},
element.Node{Lat: 0, Long: 10},
element.Node{Lat: 10, Long: 10},
element.Node{Lat: 10, Long: 0},
element.Node{Lat: 0, Long: 0},
}
g := geos.NewGeos()
defer g.Finish()
geom, err := Polygon(g, nodes)
if err != nil {
t.Fatal(err)
}
result := g.Intersection(geom, g.FromWkt("LINESTRING(-10 5, 20 5)"))
if !g.Equals(result, g.FromWkt("LINESTRING(0 5, 10 5)")) {
t.Fatal(g.AsWkt(result))
}
}
func BenchmarkLineString(b *testing.B) {
size := 16
nodes := make([]element.Node, size)

View File

@ -367,13 +367,25 @@ func (this *Geos) AsWkb(geom *Geom) []byte {
}
func (this *Geos) FromWkb(wkb []byte) *Geom {
geom := C.GEOSGeomFromWKB_buf((*C.uchar)(&wkb[0]), C.size_t(len(wkb)))
geom := C.GEOSGeomFromWKB_buf_r(this.v, (*C.uchar)(&wkb[0]), C.size_t(len(wkb)))
if geom == nil {
return nil
}
return &Geom{geom}
}
func (this *Geos) Clone(geom *Geom) *Geom {
if geom == nil || geom.v == nil {
return nil
}
result := C.GEOSGeom_clone_r(this.v, geom.v)
if result == nil {
return nil
}
return &Geom{result}
}
func (this *Geos) IsValid(geom *Geom) bool {
if C.GEOSisValid_r(this.v, geom.v) == 1 {
return true
@ -415,6 +427,14 @@ func (this *Geom) Length() float64 {
}
}
func (this *Geos) Equals(a, b *Geom) bool {
result := C.GEOSEquals_r(this.v, a.v, b.v)
if result == 1 {
return true
}
return false
}
var NilBounds = Bounds{1e20, 1e20, -1e20, -1e20}
func (this *Geom) Bounds() Bounds {

View File

@ -119,14 +119,14 @@ func BuildRelGeometry(rel *element.Relation, rings []*Ring) (*geos.Geom, error)
var interiors []*geos.Geom
for hole, _ := range shell.holes {
hole.MarkInserted(relTags)
ring := g.ExteriorRing(hole.geom)
ring := g.Clone(g.ExteriorRing(hole.geom))
if ring == nil {
return nil, errors.New("Error while getting exterior ring.")
}
interiors = append(interiors, ring)
}
shell.MarkInserted(relTags)
exterior := g.ExteriorRing(shell.geom)
exterior := g.Clone(g.ExteriorRing(shell.geom))
if exterior == nil {
return nil, errors.New("Error while getting exterior ring.")
}
@ -146,6 +146,7 @@ func BuildRelGeometry(rel *element.Relation, rings []*Ring) (*geos.Geom, error)
return nil, errors.New("Error while building multi-polygon.")
}
}
g.DestroyLater(result)
insertedWays := make(map[int64]bool)
for _, r := range rings {