Skip to content

Commit

Permalink
Merge branch 'feature_ids' of https://github.com/geomatico/java-vecto…
Browse files Browse the repository at this point in the history
…r-tile into geomatico-feature_ids
  • Loading branch information
halset committed Sep 18, 2018
2 parents dec3577 + 24fa594 commit 51ae3d6
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 5 deletions.
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,16 @@ encoder.addFeature("road", attributes, geometry);
byte[] encoded = encoder.encode();
```

or, specifying the feature id:

```java
VectorTileEncoder encoder = new VectorTileEncoder();
encoder.addFeature("road", attributes, geometry, id);
byte[] encoded = encoder.encode();
```

## Maven - with JTS from LocationTech
=======

```
<repository>
Expand Down
10 changes: 8 additions & 2 deletions src/main/java/no/ecc/vectortile/VectorTileDecoder.java
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ private Feature parseFeature(VectorTile.Tile.Feature feature) {
geometry = gf.createGeometryCollection(new Geometry[0]);
}

return new Feature(layerName, extent, geometry, Collections.unmodifiableMap(attributes));
return new Feature(layerName, extent, geometry, Collections.unmodifiableMap(attributes), feature.getId());
}

public void remove() {
Expand All @@ -344,20 +344,26 @@ public static final class Feature {

private final String layerName;
private final int extent;
private final long id;
private final Geometry geometry;
private final Map<String, Object> attributes;

public Feature(String layerName, int extent, Geometry geometry, Map<String, Object> attributes) {
public Feature(String layerName, int extent, Geometry geometry, Map<String, Object> attributes, long id) {
this.layerName = layerName;
this.extent = extent;
this.geometry = geometry;
this.attributes = attributes;
this.id = id;
}

public String getLayerName() {
return layerName;
}

public long getId() {
return id;
}

public int getExtent() {
return extent;
}
Expand Down
27 changes: 24 additions & 3 deletions src/main/java/no/ecc/vectortile/VectorTileEncoder.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ public class VectorTileEncoder {

private final boolean autoScale;

private long autoincrement;

private final boolean autoincrementIds;

/**
* Create a {@link VectorTileEncoder} with the default extent of 4096 and
* clip buffer of 8.
Expand All @@ -68,6 +72,10 @@ public VectorTileEncoder(int extent) {
this(extent, 8, true);
}

public VectorTileEncoder(int extent, int clipBuffer, boolean autoScale) {
this(extent, clipBuffer, autoScale, false);
}

/**
* Create a {@link VectorTileEncoder} with the given extent value.
* <p>
Expand All @@ -87,11 +95,14 @@ public VectorTileEncoder(int extent) {
* and will scale them automatically to the 0..extent-1 range
* before encoding. when false, the encoder expects coordinates
* in the 0..extent-1 range.
* @param autoincrementIds
*
*/
public VectorTileEncoder(int extent, int clipBuffer, boolean autoScale) {
public VectorTileEncoder(int extent, int clipBuffer, boolean autoScale, boolean autoincrementIds) {
this.extent = extent;
this.autoScale = autoScale;
this.autoincrementIds = autoincrementIds;
this.autoincrement = 1;

final int size = autoScale ? 256 : extent;
clipGeometry = createTileEnvelope(clipBuffer, size);
Expand All @@ -107,6 +118,9 @@ private static Geometry createTileEnvelope(int buffer, int size) {
return new GeometryFactory().createPolygon(coords);
}

public void addFeature(String layerName, Map<String, ?> attributes, Geometry geometry) {
this.addFeature(layerName, attributes, geometry, this.autoincrementIds ? this.autoincrement++ : -1);
}

/**
* Add a feature with layer name (typically feature type name), some
Expand All @@ -119,8 +133,9 @@ private static Geometry createTileEnvelope(int buffer, int size) {
* @param layerName
* @param attributes
* @param geometry
* @param id
*/
public void addFeature(String layerName, Map<String, ?> attributes, Geometry geometry) {
public void addFeature(String layerName, Map<String, ?> attributes, Geometry geometry, long id) {
// split up MultiPolygon and GeometryCollection (without subclasses)
if (geometry instanceof MultiPolygon || geometry.getClass().equals(GeometryCollection.class)) {
splitAndAddFeatures(layerName, attributes, (GeometryCollection) geometry);
Expand Down Expand Up @@ -163,6 +178,8 @@ public void addFeature(String layerName, Map<String, ?> attributes, Geometry geo

Feature feature = new Feature();
feature.geometry = geometry;
feature.id = id;
this.autoincrement = Math.max(this.autoincrement, id + 1);

for (Map.Entry<String, ?> e : attributes.entrySet()) {
// skip attribute without value
Expand Down Expand Up @@ -274,6 +291,10 @@ public byte[] encode() {
VectorTile.Tile.Feature.Builder featureBuilder = VectorTile.Tile.Feature.newBuilder();

featureBuilder.addAllTags(feature.tags);
if (feature.id >= 0) {
featureBuilder.setId(feature.id);
}

featureBuilder.setType(toGeomType(geometry));
featureBuilder.addAllGeometry(commands(geometry));

Expand Down Expand Up @@ -489,7 +510,7 @@ public List<Object> values() {
}

private static final class Feature {

long id;
Geometry geometry;
final List<Integer> tags = new ArrayList<Integer>();

Expand Down
80 changes: 80 additions & 0 deletions src/test/java/no/ecc/vectortile/VectorTileEncoderTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
Expand All @@ -31,6 +32,7 @@
import org.locationtech.jts.geom.Polygon;

import junit.framework.TestCase;
import no.ecc.vectortile.VectorTileDecoder.Feature;
import vector_tile.VectorTile;

public class VectorTileEncoderTest extends TestCase {
Expand Down Expand Up @@ -323,4 +325,82 @@ public void testAttributeTypes() throws IOException {
assertEquals("value6", decodedAttributes.get("key6"));
}

public void testProvidedIds() throws IOException {
VectorTileEncoder vtm = new VectorTileEncoder(256);

Geometry geometry = gf.createPoint(new Coordinate(3, 6));
Map<String, String> attributes = Collections.singletonMap("key1", "value1");
vtm.addFeature("DEPCNT", attributes, geometry, 50);

List<Feature> features = encodeDecodeFeatures(vtm);
assertEquals(1, features.size());
assertEquals(50, features.get(0).getId());
}

public void testAutoincrementIds() throws IOException {
VectorTileEncoder vtm = new VectorTileEncoder(256, 8, true, true);

for (int i = 0; i < 10; i++) {
Geometry geometry = gf.createPoint(new Coordinate(3 * i, 6 * i));
Map<String, String> attributes = Collections.singletonMap("key" + i, "value" + i);
vtm.addFeature("DEPCNT", attributes, geometry);
}

List<Feature> features = encodeDecodeFeatures(vtm);
for (int i = 0; i < features.size(); i++) {
assertEquals(i + 1, features.get(i).getId());
}
}

public void testProvidedAndAutoincrementIds() throws IOException {
VectorTileEncoder vtm = new VectorTileEncoder(256, 8, true, true);

Geometry geometry = gf.createPoint(new Coordinate(3, 6));
Map<String, String> attributes = Collections.singletonMap("key1", "value1");
vtm.addFeature("DEPCNT", attributes, geometry, 50);

geometry = gf.createPoint(new Coordinate(3, 6));
attributes = Collections.singletonMap("key1", "value1");
vtm.addFeature("DEPCNT", attributes, geometry);

geometry = gf.createPoint(new Coordinate(3, 6));
attributes = Collections.singletonMap("key1", "value1");
vtm.addFeature("DEPCNT", attributes, geometry, 27);

geometry = gf.createPoint(new Coordinate(3, 6));
attributes = Collections.singletonMap("key1", "value1");
vtm.addFeature("DEPCNT", attributes, geometry);

List<Feature> features = encodeDecodeFeatures(vtm);
assertEquals(4, features.size());
assertEquals(50, features.get(0).getId());
assertEquals(51, features.get(1).getId());
assertEquals(27, features.get(2).getId());
assertEquals(52, features.get(3).getId());
}

public void testNullIds() throws IOException {
VectorTileEncoder vtm = new VectorTileEncoder(256);

Geometry geometry = gf.createPoint(new Coordinate(3, 6));
Map<String, String> attributes = Collections.singletonMap("key1", "value1");
vtm.addFeature("DEPCNT", attributes, geometry, 50);

geometry = gf.createPoint(new Coordinate(3, 6));
attributes = Collections.singletonMap("key1", "value1");
vtm.addFeature("DEPCNT", attributes, geometry);

List<Feature> features = encodeDecodeFeatures(vtm);
assertEquals(2, features.size());
assertEquals(50, features.get(0).getId());
assertEquals(0, features.get(1).getId());
}

private List<Feature> encodeDecodeFeatures(VectorTileEncoder vtm) throws IOException {
byte[] encoded = vtm.encode();
assertNotSame(0, encoded.length);

VectorTileDecoder decoder = new VectorTileDecoder();
return decoder.decode(encoded, "DEPCNT").asList();
}
}

0 comments on commit 51ae3d6

Please sign in to comment.