wdtinc / mapbox-vector-tile-java

Java Mapbox Vector Tile Library for Encoding/Decoding
Apache License 2.0
148 stars 73 forks source link

Grid lines visible in geometry #5

Closed wlievens closed 7 years ago

wlievens commented 7 years ago

I'm using LeafletJS with the Leaflet.VectorGrid plugin on the client and mapbox-vector-tile-java in the backend. The JTS geometry is fed in the backend by joining all polygons found in the envelope into a GeometryCollection and passing that to JtsAdapter.createTileGeom(). I hope that is the correct way to do it, the documentation is a little sparse on this.

Now, when I view my map in Leaflet I see these vertical and horizontal lines on the vector tile boundaries. I know 100% they are tile boundaries because they multiply when I zoom in.

My geometry is not intersected at the input level, so they geometry I put in the collection may exceed the envelope (but never be entirely outside it).

I have posted this to the Leaflet.VecctorGrid repository, they seem to think it's an issue in the backend (see github issue link). Any ideas on how to resolve this?

https://github.com/Leaflet/Leaflet.VectorGrid/issues/108

image

ShibaBandit commented 7 years ago

We can try out a scenario / option supporting clipping outside the tile boundary by some buffer distance. It would be correct to say that the tiles are clipped on the boundary.

Question: How are you styling the vector tiles? I imagine clipping on the boundary might be causing issues with styles that use an outline on the geometry?

ShibaBandit commented 7 years ago

Another question... does the leaflet plugin use the protobuf id field at all for reconstructing polygons?

wlievens commented 7 years ago

The leaflet plugin's documentation tells me there should indeed be a buffer around the tile envelope, and if I'm correct there's no parameter for specifying that.

wlievens commented 7 years ago

As for the id fieldn do not know for suee, but I do see polygons highlighted as one feature, so they are matched somehow.

ShibaBandit commented 7 years ago

Do you want to try the clip_buffering branch at https://github.com/wdtinc/mapbox-vector-tile-java/tree/clip_buffering ? There is a new overload for JtsAdapter#createTileGeom() that supports passing in a clipping envelope as a new parameter.

    /**
     * <p>Create geometry clipped and then converted to MVT 'extent' coordinates. Result
     * contains both clipped geometry (intersection) and transformed geometry for encoding to MVT.</p>
     *
     * <p>Allows specifying separate tile and clipping coordinates. {@code clipEnvelope} can be bigger than
     * {@code tileEnvelope} to have geometry exist outside the MVT tile extent.</p>
     *
     * @param g original 'source' geometry, passed through {@link #flatFeatureList(Geometry)}
     * @param tileEnvelope world coordinate bounds for tile, used for transforms
     * @param clipEnvelope world coordinates to clip tile by
     * @param geomFactory creates a geometry for the tile envelope
     * @param mvtLayerParams specifies vector tile properties
     * @param filter geometry values that fail filter after transforms are removed
     * @return tile geometry result
     * @see TileGeomResult
     */
    public static TileGeomResult createTileGeom(List<Geometry> g,
                                                Envelope tileEnvelope,
                                                Envelope clipEnvelope,
                                                GeometryFactory geomFactory,
                                                MvtLayerParams mvtLayerParams,
                                                IGeometryFilter filter) {
    ...

I've created an example test in MvtBuiltTest#testBufferedPolygon()


        // Create input geometry
        final GeometryFactory geomFactory = new GeometryFactory();
        final Geometry inputGeom = buildPolygon(RANDOM, 200, geomFactory);

        // Build tile envelope - 1 quadrant of the world
        final double tileWidth = WORLD_SIZE * .5d;
        final double tileHeight = WORLD_SIZE * .5d;
        final Envelope tileEnvelope = new Envelope(0d, tileWidth, 0d, tileHeight);

        // Build clip envelope - (10 * 2)% buffered area of the tile envelope
        final Envelope clipEnvelope = new Envelope(tileEnvelope);
        final double bufferWidth = tileWidth * .1f;
        final double bufferHeight = tileHeight * .1f;
        clipEnvelope.expandBy(bufferWidth, bufferHeight);

        // Build buffered MVT tile geometry
        final TileGeomResult bufferedTileGeom = JtsAdapter.createTileGeom(
                JtsAdapter.flatFeatureList(inputGeom),
                tileEnvelope, clipEnvelope, geomFactory,
                DEFAULT_MVT_PARAMS, ACCEPT_ALL_FILTER);

        // Create MVT layer
        final VectorTile.Tile mvt = encodeMvt(DEFAULT_MVT_PARAMS, bufferedTileGeom);
ShibaBandit commented 7 years ago

Screenshot shows original random geometry hull (dark green), tile geometry (brown), clip geometry (light green).

screen shot 2017-07-05 at 2 01 43 pm
wlievens commented 7 years ago

I tried your clip branch and it works! Thanks for taking care of this so quickly, I hope we'll see this code in a new mainline release soon.

ShibaBandit commented 7 years ago

Should be able to push this to maven central soon as a new version soon in combination with some new README info.

ShibaBandit commented 7 years ago

Closed via https://github.com/wdtinc/mapbox-vector-tile-java/pull/6