diff --git a/data.json.gz b/data.json.gz index aec3e2a..2ae06dc 100644 Binary files a/data.json.gz and b/data.json.gz differ diff --git a/go.mod b/go.mod index 5b6bc5a..9532f84 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,9 @@ require ( ) require ( + github.com/gogo/protobuf v1.3.2 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect go.mongodb.org/mongo-driver v1.17.4 // indirect + github.com/paulmach/protoscan v0.2.1 // indirect ) diff --git a/go.sum b/go.sum index 48c2d64..19a14dc 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,7 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= @@ -25,6 +26,7 @@ github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjY github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= github.com/paulmach/orb v0.12.0 h1:z+zOwjmG3MyEEqzv92UN49Lg1JFYx0L9GpGKNVDKk1s= github.com/paulmach/orb v0.12.0/go.mod h1:5mULz1xQfs3bmQm63QEJA6lNGujuRafwA5S/EnuLaLU= +github.com/paulmach/protoscan v0.2.1 h1:rM0FpcTjUMvPUNk2BhPJrreDKetq43ChnL+x1sRg8O8= github.com/paulmach/protoscan v0.2.1/go.mod h1:SpcSwydNLrxUGSDvXvO0P7g7AuhJ7lcKfDlhJCDw2gY= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -81,6 +83,7 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/localtimezone.go b/localtimezone.go index a29b5ce..e9b1886 100644 --- a/localtimezone.go +++ b/localtimezone.go @@ -30,6 +30,7 @@ import ( json "github.com/json-iterator/go" "github.com/paulmach/orb" + "github.com/paulmach/orb/encoding/mvt" "github.com/paulmach/orb/geojson" "github.com/paulmach/orb/planar" ) @@ -274,13 +275,21 @@ func (z *localTimeZone) LoadGeoJSON(r io.Reader) error { if err != nil { return err } - orbData, err := geojson.UnmarshalFeatureCollection(buf.Bytes()) + layers, err := mvt.Unmarshal(buf.Bytes()) if err != nil { z.tzData = make(map[string]tzData) z.tzids = []string{} z.mu.Unlock() return err } + fcs := layers.ToFeatureCollections() + orbData, ok := fcs["data"] + if !ok { + z.tzData = make(map[string]tzData) + z.tzids = []string{} + z.mu.Unlock() + return errors.New("asdf") + } z.tzData = make(map[string]tzData, TZCount) // Possibly the incorrect length in case of Mock or custom data z.tzids = []string{} // Cannot set a length or else array will be full of empty strings go func(features []*geojson.Feature) { diff --git a/localtimezone_test.go b/localtimezone_test.go index 453beb4..e7802a7 100644 --- a/localtimezone_test.go +++ b/localtimezone_test.go @@ -8,6 +8,8 @@ import ( "testing" "github.com/paulmach/orb" + "github.com/paulmach/orb/encoding/mvt" + "github.com/paulmach/orb/geojson" "go.uber.org/goleak" ) @@ -15,6 +17,47 @@ func TestMain(m *testing.M) { goleak.VerifyTestMain(m) } +func TestMVT(t *testing.T) { + g, err := gzip.NewReader(bytes.NewBuffer(MockTZShapeFile)) + if err != nil { + t.Errorf("cannot create gzip reader, got error %v", err) + } + defer g.Close() + + var buf bytes.Buffer + _, err = buf.ReadFrom(g) + if err != nil { + t.Errorf("cannot read from gzip, got error %v", err) + } + + geojsonFeatureCollection, err := geojson.UnmarshalFeatureCollection(buf.Bytes()) + if err != nil { + t.Errorf("cannot unmarshal geojson, got error %v", err) + } + + collections := map[string]*geojson.FeatureCollection{ + "data": geojsonFeatureCollection, + } + layers := mvt.NewLayers(collections) + mvtMarshalled, err := mvt.Marshal(layers) + if err != nil { + t.Errorf("cannot marshal mvt, got error %v", err) + } + + unmarshalledLayers, err := mvt.Unmarshal(mvtMarshalled) + if err != nil { + t.Errorf("cannot unmarshal mvt, got error %v", err) + } + unmarshalledCollections := unmarshalledLayers.ToFeatureCollections() + unmarshalledFeatureCollection, ok := unmarshalledCollections["data"] + if !ok { + t.Errorf("cannot find data layer") + } + if len(unmarshalledFeatureCollection.Features) != len(geojsonFeatureCollection.Features) { + t.Errorf("expected %d features; got %d", len(geojsonFeatureCollection.Features), len(unmarshalledFeatureCollection.Features)) + } +} + func TestPointFromOrb(t *testing.T) { p1 := orb.Point{1, 2} p2 := pointFromOrb(p1) @@ -235,40 +278,6 @@ func TestGetOneZone(t *testing.T) { } } -func TestMockLocalTimeZone(t *testing.T) { - z := NewMockLocalTimeZone() - for _, tc := range tt { - t.Run(tc.name, func(t *testing.T) { - t.Parallel() - tzids, err := z.GetZone(tc.point) - if tc.err != nil { - if err != tc.err { - t.Errorf("expected err %v; got %v", tc.err, err) - } - return - } - if len(tzids) != 1 { - t.Errorf("expected 1 zone; got %d", len(tzids)) - } - if tzids[0] != MockTimeZone { - t.Errorf("expected zone America/Los_Angeles; got %s", tzids[0]) - } - }) - } -} - -func TestMockLocalTimeZonePanic(t *testing.T) { - tempMockTZShapeFile := MockTZShapeFile - MockTZShapeFile = []byte("asdf") - defer func() { - MockTZShapeFile = tempMockTZShapeFile - if r := recover(); r == nil { - t.Errorf("expected a panic; got no panic") - } - }() - NewMockLocalTimeZone() -} - func BenchmarkZones(b *testing.B) { zInterface, err := NewLocalTimeZone() if err != nil { @@ -335,18 +344,8 @@ func BenchmarkClientInit(b *testing.B) { defer cStruct.mu.RUnlock() } }) - b.Run("mock client", func(b *testing.B) { - for b.Loop() { - c := NewMockLocalTimeZone() - cStruct, ok := c.(*localTimeZone) - if !ok { - b.Errorf("cannot initialize timezone client") - } - cStruct.mu.RLock() - defer cStruct.mu.RUnlock() - } - }) } + func TestNautical(t *testing.T) { t.Parallel() tt := []struct { @@ -431,27 +430,3 @@ func TestLoadGeoJSONMalformed(t *testing.T) { t.Errorf("tzData not reset") } } - -func TestLoadOverwrite(t *testing.T) { - client, err := NewLocalTimeZone() - if err != nil { - t.Errorf("cannot initialize client, got %v", err) - } - c, ok := client.(*localTimeZone) - if !ok { - t.Errorf("cannot initialize client") - } - c.mu.RLock() - lenTzData := len(c.tzData) - c.mu.RUnlock() - - err = c.load(MockTZShapeFile) - c.mu.RLock() - defer c.mu.RUnlock() - if err != nil { - t.Errorf("cannot switch client to mock data, got %v", err) - } - if len(c.tzData) >= lenTzData { - t.Errorf("boundCache not overwritten by loading new data") - } -} diff --git a/tzshapefilegen/main.go b/tzshapefilegen/main.go index 7d96afd..ff7cf35 100644 --- a/tzshapefilegen/main.go +++ b/tzshapefilegen/main.go @@ -15,6 +15,7 @@ import ( "sort" json "github.com/json-iterator/go" + "github.com/paulmach/orb/encoding/mvt" "github.com/paulmach/orb/geojson" "github.com/paulmach/orb/simplify" ) @@ -146,7 +147,12 @@ func orbExec(combinedJSON []byte) ([]byte, []string, error) { return features[i].Properties.MustString("tzid") < features[j].Properties.MustString("tzid") }) fc.Features = features - reducedJSON, err := fc.MarshalJSON() + data := map[string]*geojson.FeatureCollection{ + "data": fc, + } + layers := mvt.NewLayers(data) + // layers.Simplify(simplify.VisvalingamThreshold(0.0001)) + reducedJSON, err := mvt.Marshal(layers) if err != nil { log.Printf("Error: could not marshal reduced.json: %v\n", err) return nil, nil, err