Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions encoding/wkt/wkt_decode.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ func (d *Decoder) readByte() (byte, error) {
d.row++
d.col = 0
} else {
d.lastCol = d.col
d.col++
}

Expand Down Expand Up @@ -446,14 +445,29 @@ func (d *Decoder) readGeometry() (geom.Geometry, error) {
for b, err = d.readByte(); b != ')' && err == nil; b, err = d.readByte() {
d.unreadByte()


geo, err := d.readGeometry()
if err != nil {
return nil, err
}
geoms = append(geoms, geo)

d.readWhitespace()

b, err := d.readByte()
if err != nil {
return nil, err
}

switch b {
case ')':
d.unreadByte()
case ',':
//noop
d.readWhitespace()
default:
return nil, d.expected(",)")
}

}

if err != nil {
Expand Down
4 changes: 4 additions & 0 deletions encoding/wkt/wkt_decode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,10 @@ func TestDecode(t *testing.T) {
in: "geometrycollection(MULTIPOLYGON())",
err: errors.New("syntax error (1:34): not enough polys in MULTIPOLYGON, 0"),
},
"collection 4": {
in: "geometrycollection(multipolygon(((0 0, 1 1, 1 0, 0 0))), point(1 1))",
out: geom.Collection{geom.MultiPolygon{{{{0, 0}, {1, 1}, {1, 0}}}}, geom.Point{1, 1}},
},
}

for k, v := range tcases {
Expand Down
47 changes: 10 additions & 37 deletions encoding/wkt/wkt_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package wkt

import (
"bytes"
"errors"
"math"
"testing"
Expand Down Expand Up @@ -29,7 +28,6 @@ func TestEncode(t *testing.T) {
return
}


if tc.Err == nil && gerr != nil {
t.Errorf("error, expected nil got %v", gerr)
return
Expand Down Expand Up @@ -129,11 +127,11 @@ func TestEncode(t *testing.T) {
},
{
Geom: geom.MultiLineString{{{0, 0}, {1, 1}, {math.NaN(), math.NaN()}}, {}},
Err: errors.New("cannot have empty points in MULTILINESTRING"),
Err: errors.New("cannot have empty points in MULTILINESTRING"),
},
{
Geom: geom.MultiLineString{{{10, 10}}},
Err: errors.New("not enough points for LINESTRING [[10 10]]"),
Err: errors.New("not enough points for LINESTRING [[10 10]]"),
},
{
Geom: geom.MultiLineString{{{10, 10}, {11, 11}}},
Expand All @@ -145,31 +143,31 @@ func TestEncode(t *testing.T) {
},
{
Geom: geom.MultiLineString{{}, {{10, 10}}},
Err: errors.New("not enough points for LINESTRING [[10 10]]"),
Err: errors.New("not enough points for LINESTRING [[10 10]]"),
},
{
Geom: geom.MultiLineString{{}, {{10, 10}, {20, 20}}},
Rep: "MULTILINESTRING ((10 10,20 20))",
},
{
Geom: geom.MultiLineString{{{10, 10}}, {}},
Err: errors.New("not enough points for LINESTRING [[10 10]]"),
Err: errors.New("not enough points for LINESTRING [[10 10]]"),
},
{
Geom: geom.MultiLineString{{{10, 10}}, {{10, 10}}},
Err: errors.New("not enough points for LINESTRING [[10 10]]"),
Err: errors.New("not enough points for LINESTRING [[10 10]]"),
},
{
Geom: geom.MultiLineString{{{10, 10}}, {{10, 10}, {20, 20}}},
Err: errors.New("not enough points for LINESTRING [[10 10]]"),
Err: errors.New("not enough points for LINESTRING [[10 10]]"),
},
{
Geom: geom.MultiLineString{{{10, 10}, {20, 20}}, {}},
Rep: "MULTILINESTRING ((10 10,20 20))",
},
{
Geom: geom.MultiLineString{{{10, 10}, {20, 20}}, {{10, 10}}},
Err: errors.New("not enough points for LINESTRING [[10 10]]"),
Err: errors.New("not enough points for LINESTRING [[10 10]]"),
},
{
Geom: geom.MultiLineString{{{10, 10}, {20, 20}}, {{10, 10}, {20, 20}}},
Expand Down Expand Up @@ -211,15 +209,15 @@ func TestEncode(t *testing.T) {
},
{
Geom: geom.Polygon{{{10, 10}, {11, 11}, {12, 12}, {math.NaN(), math.NaN()}}, {}},
Err: errors.New("cannot have empty points in POLYGON"),
Err: errors.New("cannot have empty points in POLYGON"),
},
{
Geom: geom.Polygon{{{10, 10}, {11, 11}, {12, 12}}, {{20, 20}, {21, 21}, {22, 22}}},
Rep: "POLYGON ((10 10,11 11,12 12,10 10),(20 20,21 21,22 22,20 20))",
},
{
Geom: geom.Polygon{{{10, 10}, {11, 11}, {12, 12}}, {{20, 20}, {21, 21}, {math.NaN(), math.NaN()}, {22, 22}}},
Err: errors.New("cannot have empty points in POLYGON"),
Err: errors.New("cannot have empty points in POLYGON"),
},
{
Geom: geom.Polygon{{}, {{10, 10}, {11, 11}, {12, 12}}},
Expand Down Expand Up @@ -277,7 +275,7 @@ func TestEncode(t *testing.T) {
},
{
Geom: &geom.MultiPolygon{{{{10, 10}, {11, 11}, {math.NaN(), math.NaN()}, {12, 12}}}},
Err: errors.New("cannot have empty points in MULTIPOLYGON"),
Err: errors.New("cannot have empty points in MULTIPOLYGON"),
},
},
"Collectioner": {
Expand Down Expand Up @@ -390,28 +388,3 @@ func BenchmarkEncodeSin1000(b *testing.B) {
EncodeBytes(gtesting.SinLineString(1.0, 0.0, 100.0, 1000))
}
}

func BenchmarkEncodeTile(b *testing.B) {
for n := 0; n < b.N; n++ {
EncodeBytes(gtesting.Tiles[0])
}
}


func BenchmarkEncodeTilePrealloc(b *testing.B) {
for n := 0; n < b.N; n++ {
// the encoded wkt is ~32MB
buf := bytes.NewBuffer(make([]byte, 0, (1 << 20) * 32))
enc := NewEncoder(buf)
enc.Encode(gtesting.Tiles[0], true)
}
}


func BenchmarkEncodeTileNoprealloc(b *testing.B) {
for n := 0; n < b.N; n++ {
buf := bytes.NewBuffer(make([]byte, 0, 0))
enc := NewEncoder(buf)
enc.Encode(gtesting.Tiles[0], true)
}
}
35 changes: 35 additions & 0 deletions encoding/wkt/wkt_tile_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package wkt

import (
"bytes"
"testing"

gtesting "github.com/go-spatial/geom/testing"
)

func init() {
gtesting.CompileTiles(DecodeString)
}

func BenchmarkEncodeTile(b *testing.B) {
for n := 0; n < b.N; n++ {
EncodeBytes(gtesting.Tiles()[0])
}
}

func BenchmarkEncodeTilePrealloc(b *testing.B) {
for n := 0; n < b.N; n++ {
// the encoded wkt is ~32MB
buf := bytes.NewBuffer(make([]byte, 0, (1<<20)*32))
enc := NewEncoder(buf)
enc.Encode(gtesting.Tiles()[0], true)
}
}

func BenchmarkEncodeTileNoprealloc(b *testing.B) {
for n := 0; n < b.N; n++ {
buf := bytes.NewBuffer(make([]byte, 0, 0))
enc := NewEncoder(buf)
enc.Encode(gtesting.Tiles()[0], true)
}
}
26 changes: 24 additions & 2 deletions testing/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,27 @@
# testing

This package contains functions and variables for using pre made geometries.
Be carefule, some of the geometries are very large, in particular the tile
geometries.

The tile variables are very large and are initially stored as strings. In order
to access them, you must first compile compile them by calling `CompileTiles`.
Once compiled, access the tiles via the `Tiles` function (this does no processing
besides endusring that compilation has already occured).

```go
package my_test

import (
"github.com/go-spatial/geom/encoding/wkt"
gtesting "github.com/go-spatial/testing"
)

func init {
// put this in init so benchmarks aren't skewed
gtesting.CompileTiles(wkt.DecodeString)
}

func TestMy(t *testing) {
tiles := gtesting.Tiles()
...
}
```
5 changes: 1 addition & 4 deletions testing/ne_6_43_21.go

Large diffs are not rendered by default.

5 changes: 1 addition & 4 deletions testing/ne_8_42_98.go

Large diffs are not rendered by default.

80 changes: 78 additions & 2 deletions testing/ne_tiles.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,81 @@
package testing

import "github.com/go-spatial/geom"
import (
"fmt"
"github.com/go-spatial/geom"
)

var Tiles = []geom.Collection{_ne_6_43_21, _ne_8_42_98}
var tilesWkt = []string{_ne_6_43_21, _ne_8_42_98}
var tilesCompiled []geom.Collection

// Tiles returns geom.Collections that represent Natural Earth tiles
// generated with the utility https://github.com/ear7h/tile-dump. The
// tiles must be compiled at runtime by calling the CompileTiles
// function (see documentation for it) or this funciton will panic.
// package my_test
//
// import (
// gtesting "github.com/go-spatial/testing"
// "github.com/go-spatial/geom/encoding/wkt"
// )
//
// func init {
// // put this in init so benchmarks aren't skewed
// gtesting.CompileTiles(wkt.DecodeString)
// }
//
// func TestMy(t *testing) {
// tiles := gtesting.Tiles()
// ...
// }
//
func Tiles() []geom.Collection {
if tilesCompiled == nil {
panic("no compiled tiles, make sure to call CompileTiles")
}

return tilesCompiled
}

// CompileTiles will compile some Natural Earth tiles so they are accessible
// through the Tiles function. It takes a WKT decoding function which can be
// accessible in the package github.com/go-spatial/geom/encoding/wkt as the
// function DecodeString.
// package my_test
//
// import (
// gtesting "github.com/go-spatial/testing"
// "github.com/go-spatial/geom/encoding/wkt"
// )
//
// func init {
// // put this in init so benchmarks aren't skewed
// gtesting.CompileTiles(wkt.DecodeString)
// }
//
// func TestMy(t *testing) {
// tiles := gtesting.Tiles()
// ...
// }
//
func CompileTiles(wktDecoder func(string) (geom.Geometry, error)) {
if tilesCompiled != nil {
return
}

ret := make([]geom.Collection, len(tilesWkt))

for i, v := range tilesWkt {

col, err := wktDecoder(v)
if err != nil {
fmt.Println("i: ", i, "str: ", v[57-10:57+10])
panic(err)
}

ret[i] = col.(geom.Collection)

}

tilesCompiled = ret
}