1

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);
1

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:

9
  • I read and looked at all of that so either something isn't working for me or I lack some understanding. I have List<Points>. I couldn't find a way to add those points to my Geometry jtsGeom object.
    – MacAnthony
    Jan 24 '18 at 22:39
  • Checkout edit 2, added information on creating JTS Geometry, that may be your issue. Jan 25 '18 at 2:20
  • Sorry for the delay in getting back to this. I was pulled onto another project. I think I'm getting closer and your last point is right. Making a geometry collection of multiple point objects would definitely work. All the code I see, though, take a geometry array to create the geometry collection and not points, so I'm uncertain how to either convert my points to geometry where they would work, or get it accept a list/array of points. Does that make sense? I feel like this should be easy and I'm just not understanding something.
    – MacAnthony
    Feb 6 '18 at 18:01
  • 1
  • 1
    Thanks! I believe I got it working to the extent that this question covers. I'm still working on getting the browser to request and accept the mvt data, but I'm moving forward! I'm going to update the question with the solution.
    – MacAnthony
    Feb 8 '18 at 20:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.