[GIS] Adding Geometry to a mapbox vector tile using java library

javajts-topology-suitevector-tiles

I'm attempting to make a mapbox vector tile to be used in leafletjs. I have a couple of layers I need to do with this, but I started with a point layer since I thought it would be easier.

I am using the mapbox-vector-tile-java library, but the documentation is pretty slim so I've struggled with figuring out the process to use it.

I have the following code that I got from it's github documentation.

IGeometryFilter acceptAllGeomFilter = geometry -> true;
Envelope tileEnvelope = new Envelope(bb.east, bb.west, bb.south, bb.north); // TODO: Your tile extent here
MvtLayerParams layerParams = new MvtLayerParams(); // Default extent

Geometry jtsGeom = gf.toGeometry(tileEnvelope);
TileGeomResult tileGeom = JtsAdapter.createTileGeom(
        jtsGeom , // Your geometry
        tileEnvelope,
        gf,
        layerParams,
        acceptAllGeomFilter);

VectorTile.Tile.Builder tileBuilder = VectorTile.Tile.newBuilder();
VectorTile.Tile.Layer.Builder layerBuilder = MvtLayerBuild.newLayerBuilder("myLayerName", layerParams);

MvtLayerProps layerProps = new MvtLayerProps();
IUserDataConverter userDataConverter = new UserDataKeyValueMapConverter();
List<VectorTile.Tile.Feature> features = JtsAdapter.toFeatures(tileGeom.mvtGeoms, layerProps, userDataConverter);


MvtLayerBuild.writeProps(layerBuilder, layerProps);
VectorTile.Tile mvt = tileBuilder.build();
try {
    String str = new String(mvt.toByteArray(), "UTF-8");
    System.out.println(str);
} catch (UnsupportedEncodingException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

I have a set of point data in an ArrayList, but I can't see anything that takes a Point object. Originally, I used the GeometryFactory.createMultiPoint() method before I figured out that it just returns a multipoint object, but does not add those points to the GeometryFactory object.

What do I need to do to add my Points so they are included in the mapbox vector tile output? Subsequently, is that process going to be the same when I am making a layer of multi line features?

Edit:

The points I'm trying to use are a ArrayList currently, but I can change it to any structure that will work.

ArrayList<Point> pts = new ArrayList<Point>();
Point pt = null;
while( rs.next()) {
    points.add(rs.getString(1));
    pointData += rs.getString(1);
    pt = gf.createPoint(new Coordinate(rs.getDouble(3), rs.getDouble(2)));
    pts.add(pt);
    pt = null;
}

Solution:

With the help from @ShibaBandit, I came up with the following solution. They pointed me to a convenience class (MvtEncoder) and other documentation that led me to a much simpler solution.

Final Code:

    Collection<Geometry> geom = new ArrayList<Geometry>(points);
    JtsLayer layer = new JtsLayer("points", geom);

    JtsMvt mvt = new JtsMvt(layer);

    byte[] ba = MvtEncoder.encode(mvt);

Best Answer

It's assuming you are using JTS in your application logic and provides an adapter to convert it to MVTs. JTS uses a class hierarchy of different geometry types that inherit from the 'Geometry' class. In order to add your points to the MVT, you'll likely want to have them as JTS Geometry objects.

In that README example:

  • 'jtsGeom' contains your JTS global/world geometry that needs to be encoded into a tile
  • 'tileEnvelope' contains the tile bounds to clip the world geometry to
  • The method JtsAdapter#createTileGeom() clips your world geometry to the tile bounds, converts the geometry coordinates to 'local' 'MVT coordinates' and returns a structure with the clipped geometry (global/world coordinates) and the tile geometry (local coordinates).

Example - MVT Build Unit Test

Related JavaDoc:

/**
 * Create geometry clipped and then converted to MVT 'extent' coordinates. Result
 * contains both clipped geometry (intersection) and transformed geometry for encoding to MVT.
 *
 * <p>Uses the same tile and clipping coordinates. May cause rendering issues on boundaries for polygons
 * or line geometry depending on styling.</p>
 *
 * @param g original 'source' geometry
 * @param tileEnvelope world coordinate bounds for tile
 * @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(Geometry g,
                                            Envelope tileEnvelope,
                                            GeometryFactory geomFactory,
                                            MvtLayerParams mvtLayerParams,
                                            IGeometryFilter filter) {
    return createTileGeom(flatFeatureList(g), tileEnvelope, geomFactory,
            mvtLayerParams, filter);
}


/**
 * <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>Uses the same tile and clipping coordinates. May cause rendering issues on boundaries for polygons
 * or line geometry depending on styling.</p>
 *
 * @param g original 'source' geometry, passed through {@link #flatFeatureList(Geometry)}
 * @param tileEnvelope world coordinate bounds for tile
 * @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,
                                            GeometryFactory geomFactory,
                                            MvtLayerParams mvtLayerParams,
                                            IGeometryFilter filter) {
    return createTileGeom(g, tileEnvelope, tileEnvelope, geomFactory, mvtLayerParams, filter);
}

Please let me know if you have additional questions.

Edit: Upgraded documentation some on main readme, hope that helps. Might have to refresh the page.

Edit 2: Sounds like an issue creating JTS Geometry? You may want to checkout some examples of how to create JTS Geometry: