From 7f1d93825f522bd7fb98d49cb5a2aea032ba8513 Mon Sep 17 00:00:00 2001 From: Alexander Rolek Date: Mon, 8 Apr 2019 23:34:55 -0700 Subject: [PATCH] Paumas implement dont clip flag (#593) * implement dont_clip configuration option. closes #562. --- README.md | 1 + atlas/layer.go | 3 +++ atlas/map.go | 1 + cmd/internal/register/maps.go | 1 + config/config.go | 3 +++ config/config_test.go | 4 +++- maths/validate/validate.go | 2 ++ mvt/feature.go | 15 ++++++++++----- mvt/feature_internal_test.go | 2 +- mvt/layer.go | 4 +++- 10 files changed, 28 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index c293b140c..0a8d1d721 100644 --- a/README.md +++ b/README.md @@ -178,6 +178,7 @@ name = "zoning" # used in the URL to reference this # It can also be used to group multiple ProviderLayers under the same namespace. provider_layer = "test_postgis.rivers" # must match a data provider layer dont_simplify = true # optionally, turn off simplification for this layer. Default is false. + dont_clip = true # optionally, turn off clipping for this layer. Default is false. min_zoom = 10 # minimum zoom level to include this layer max_zoom = 18 # maximum zoom level to include this layer ``` diff --git a/atlas/layer.go b/atlas/layer.go index 8d5c0f630..48249fe2f 100644 --- a/atlas/layer.go +++ b/atlas/layer.go @@ -19,6 +19,9 @@ type Layer struct { // DontSimplify indicates wheather feature simplification should be applied. // We use a negative in the name so the default is to simplify DontSimplify bool + // DontClip indicates wheather feature clipping should be applied. + // We use a negative in the name so the default is to clip + DontClip bool } // MVTName will return the value that will be encoded in the Name field when the layer is encoded as MVT diff --git a/atlas/map.go b/atlas/map.go index 66e1a6fc9..9675fa491 100644 --- a/atlas/map.go +++ b/atlas/map.go @@ -146,6 +146,7 @@ func (m Map) Encode(ctx context.Context, tile *slippy.Tile) ([]byte, error) { mvtLayer := mvt.Layer{ Name: l.MVTName(), DontSimplify: l.DontSimplify, + DontClip: l.DontClip, } // on completion let the wait group know diff --git a/cmd/internal/register/maps.go b/cmd/internal/register/maps.go index 8e605c11e..c940112bd 100644 --- a/cmd/internal/register/maps.go +++ b/cmd/internal/register/maps.go @@ -162,6 +162,7 @@ func Maps(a *atlas.Atlas, maps []config.Map, providers map[string]provider.Tiler DefaultTags: defaultTags, GeomType: layerGeomType, DontSimplify: bool(l.DontSimplify), + DontClip: bool(l.DontClip), }) } diff --git a/config/config.go b/config/config.go index 32d22b630..223a4c464 100644 --- a/config/config.go +++ b/config/config.go @@ -61,6 +61,9 @@ type MapLayer struct { // DontSimplify indicates wheather feature simplification should be applied. // We use a negative in the name so the default is to simplify DontSimplify env.Bool `toml:"dont_simplify"` + // DontClip indicates wheather feature clipping should be applied. + // We use a negative in the name so the default is to clipping + DontClip env.Bool `toml:"dont_clip"` } // GetName helper to get the name we care about. diff --git a/config/config_test.go b/config/config_test.go index 4a242197d..bb78d856d 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -132,7 +132,8 @@ func TestParse(t *testing.T) { provider_layer = "provider1.water" min_zoom = 10 max_zoom = 20 - dont_simplify = true`, + dont_simplify = true + dont_clip = true`, expected: config.Config{ TileBuffer: env.IntPtr(env.Int(12)), LocationName: "", @@ -180,6 +181,7 @@ func TestParse(t *testing.T) { MinZoom: env.UintPtr(10), MaxZoom: env.UintPtr(20), DontSimplify: true, + DontClip: true, }, }, }, diff --git a/maths/validate/validate.go b/maths/validate/validate.go index ab2be6413..bf3253ede 100644 --- a/maths/validate/validate.go +++ b/maths/validate/validate.go @@ -96,6 +96,8 @@ func scaleMultiPolygon(p tegola.MultiPolygon, factor float64) (bmp basic.MultiPo return bmp } +// CleanGeometry will apply various geoprocessing algorithems to the provided geometry. +// the extent will be used as a clipping region. if no clipping is desired, pass in a nil extent. func CleanGeometry(ctx context.Context, g tegola.Geometry, extent *geom.Extent) (geo tegola.Geometry, err error) { if g == nil { return nil, nil diff --git a/mvt/feature.go b/mvt/feature.go index fb44ce670..dbb292066 100644 --- a/mvt/feature.go +++ b/mvt/feature.go @@ -15,7 +15,7 @@ import ( "github.com/go-spatial/tegola/maths" "github.com/go-spatial/tegola/maths/points" "github.com/go-spatial/tegola/maths/validate" - "github.com/go-spatial/tegola/mvt/vector_tile" + vectorTile "github.com/go-spatial/tegola/mvt/vector_tile" ) // errors @@ -87,7 +87,7 @@ func NewFeatures(geo tegola.Geometry, tags map[string]interface{}) (f []Feature) } // VTileFeature will return a vectorTile.Feature that would represent the Feature -func (f *Feature) VTileFeature(ctx context.Context, keys []string, vals []interface{}, tile *tegola.Tile, simplify bool) (tf *vectorTile.Tile_Feature, err error) { +func (f *Feature) VTileFeature(ctx context.Context, keys []string, vals []interface{}, tile *tegola.Tile, simplify bool, clip bool) (tf *vectorTile.Tile_Feature, err error) { tf = new(vectorTile.Tile_Feature) tf.Id = f.ID @@ -95,7 +95,7 @@ func (f *Feature) VTileFeature(ctx context.Context, keys []string, vals []interf return tf, err } - geo, gtype, err := encodeGeometry(ctx, f.Geometry, tile, simplify) + geo, gtype, err := encodeGeometry(ctx, f.Geometry, tile, simplify, clip) if err != nil { return tf, err } @@ -570,7 +570,7 @@ func (c *cursor) ClosePath() uint32 { // encodeGeometry will take a tegola.Geometry type and encode it according to the // mapbox vector_tile spec. -func encodeGeometry(ctx context.Context, geometry tegola.Geometry, tile *tegola.Tile, simplify bool) (g []uint32, vtyp vectorTile.Tile_GeomType, err error) { +func encodeGeometry(ctx context.Context, geometry tegola.Geometry, tile *tegola.Tile, simplify bool, clip bool) (g []uint32, vtyp vectorTile.Tile_GeomType, err error) { if geometry == nil { return nil, vectorTile.Tile_UNKNOWN, ErrNilGeometryType @@ -592,7 +592,12 @@ func encodeGeometry(ctx context.Context, geometry tegola.Geometry, tile *tegola. if err != nil { return nil, vectorTile.Tile_UNKNOWN, err } - ext := geom.NewExtent([2]float64{pbb[0], pbb[1]}, [2]float64{pbb[2], pbb[3]}) + + // check if we need to clip and if we do build the extent + var ext *geom.Extent + if clip { + ext = geom.NewExtent([2]float64{pbb[0], pbb[1]}, [2]float64{pbb[2], pbb[3]}) + } geometry, err = validate.CleanGeometry(ctx, sg, ext) if err != nil { diff --git a/mvt/feature_internal_test.go b/mvt/feature_internal_test.go index be1f7d627..f6d7c9c62 100644 --- a/mvt/feature_internal_test.go +++ b/mvt/feature_internal_test.go @@ -83,7 +83,7 @@ func TestEncodeGeometry(t *testing.T) { fn := func(tc tcase) func(t *testing.T) { return func(t *testing.T) { - g, gtype, err := encodeGeometry(context.Background(), tc.geo, tile, true) + g, gtype, err := encodeGeometry(context.Background(), tc.geo, tile, true, true) if tc.eerr != err { t.Errorf("error, expected %v got %v", tc.eerr, err) } diff --git a/mvt/layer.go b/mvt/layer.go index 38fc9893f..a284265dc 100644 --- a/mvt/layer.go +++ b/mvt/layer.go @@ -56,6 +56,8 @@ type Layer struct { DontSimplify bool // MaxSimplificationZoom is the zoom level at which point simplification is turned off. if value is zero Max is set to 14. If you do not want to simplify at any level set DontSimplify to true. MaxSimplificationZoom uint + // DontClip truns off clipping for this layer. + DontClip bool } func valMapToVTileValue(valMap []interface{}) (vt []*vectorTile.Tile_Value) { @@ -84,7 +86,7 @@ func (l *Layer) VTileLayer(ctx context.Context, tile *tegola.Tile) (*vectorTile. simplify = simplify && tile.Z < l.MaxSimplificationZoom - vtf, err := f.VTileFeature(ctx, kmap, vmap, tile, simplify) + vtf, err := f.VTileFeature(ctx, kmap, vmap, tile, simplify, !l.DontClip) if err != nil { switch err { case context.Canceled: