paulmach / orb

Types and utilities for working with 2d geometry in Golang
MIT License
886 stars 103 forks source link

encoding/mvt fails on nil features #135

Closed polastre closed 7 months ago

polastre commented 1 year ago

When a layer has an empty feature, often due to clipping, it causes MarshalGzipped (and probably Marshal too) to fail with a null pointer panic. The panic is on accessing f.Geometry in the marshaller. On further investigation, this happens when the geometry or feature is nil.

My workflow looks a bit like this:

// get tileData from source
layers, err := mvt.UnmarshalGzipped(tileData)
if err != nil {
    return nil, err
}
layers.ProjectToWGS84(tileInfo)
layers.Clip(requestedTile.Bound())
layers.ProjectToTile(requestedTile)
data, err := mvt.MarshalGzipped(layers)

mvt.MarshalGzipped(layers) fails with a panic.

If I add a Prune function, something along the lines of:

func (l *Layer) Prune() {
    feats := []*geojson.Feature{}
    for _, f := range l.Features {
        if f != nil && f.Geometry != nil {
            feats = append(feats, f)
        }
    }
    l.Features = feats
}

then the tiles marshal and render correctly.

Can I suggest or open a PR to provide a Prune function for both mvt.Layer and mvt.Layers?

paulmach commented 8 months ago

Can these features just be skipped on encoding?

polastre commented 8 months ago

How would you propose skipping them in MarshalGzipped, which encodes the entire set?

paulmach commented 8 months ago

Nil features are "skipped" during encoding. Features clipped to empty/nil are remove from the features array during clipping https://github.com/paulmach/orb/pull/141

paulmach commented 7 months ago

I merged the above change, it is in v0.11.0

polastre commented 7 months ago

Perfect, that's a great solution. Thanks @paulmach!