Comments (19)
I have created a very crude (sorry) demo project to demonstrate the issues reading tippecanoe input.
If you open Main.java and change boolean passThrough = true
to false
you should see the "com.vividsolutions.jts.geom.TopologyException: unable to assign hole to a shell" errors.
It should work with "./gradlew run" - but the default is to just spew out input without parsing (no error but an mbtiles that should look ok with mbview).
Note: I was using tippecanoe v1.12.5
from mapbox-vector-tile-java.
@snodnipper Regarding the TopologyException, looks like some of the input geometry is invalid, so it likely won't work with JTS intersection (make tile geometry). You can check this with:
for(Geometry g : geoms) {
if(!g.isValid()) {
LOGGER.log(Level.SEVERE, "geometry invalid - " + g);
}
if(!g.isSimple()) {
LOGGER.log(Level.SEVERE, "geometry not simple - " + g);
}
}
The 'toString()' of a JTS geometry is WKT, so you can paste it into a viewer like QGIS with plugins.
Also, since you're reading an MVT, you don't have to recreate the geometry with...
JtsAdapter.createTileGeom()
...since coordinates are ready. You'll be transforming the geometry into something else since createTileGeom will invert the Y axis again.
I did notice that on the first MVT POLYGON I read out it had a negative area from CGAlgorithms.signedArea(r.getCoordinates()) so I can already see that I'm discarding initial rings, which may be leading to the invalid geometry.
I can try this again with altered handling where I accept negative initial rings as a exterior shell and see what happens...
from mapbox-vector-tile-java.
Thanks for trying it. I will probably make some API changes to support reading this style of MultiPolygon rather than being strict and expecting positive area first. Hope to have this implemented soon as time allows.
from mapbox-vector-tile-java.
Thanks @snodnipper. I'm tracking this in mapbox/tippecanoe#295 now.
from mapbox-vector-tile-java.
I'll check it out.
from mapbox-vector-tile-java.
Cheers, using the MB JS tooling I get the following from the MVT.
[ [ { x: 2059, y: 2048 },
{ x: 2048, y: 2048 },
{ x: 2059, y: 2037 },
{ x: 2059, y: 2048 } ],
[ { x: 2037, y: 2059 },
{ x: 2037, y: 2048 },
{ x: 2048, y: 2048 },
{ x: 2037, y: 2059 } ] ]
At 0,0 ->
{"type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[[[[0.966796875,0],[0,0],[0.966796875,0.9667509997666457],[0.966796875,0]]],[[[-0.966796875,-0.9667509997666315],[-0.966796875,0],[0,0],[-0.966796875,-0.9667509997666315]]]]},"properties":{},"id":1}
from mapbox-vector-tile-java.
The current polygon parsing is intended to match the 2.1 spec (https://github.com/mapbox/vector-tile-spec/tree/master/2.1), where
4.3.4.4. Polygon Geometry Type
...
An exterior ring is DEFINED as a linear ring having a positive area as calculated by applying the surveyor's formula to the vertices of the polygon in tile coordinates. In the tile coordinate system (with the Y axis positive down and X axis positive to the right) this makes the exterior ring's winding order appear clockwise.An interior ring is DEFINED as a linear ring having a negative area as calculated by applying the surveyor's formula to the vertices of the polygon in tile coordinates. In the tile coordinate system (with the Y axis positive down and X axis positive to the right) this makes the interior ring's winding order appear counterclockwise.
I stepped through the mapbox polygon example and noticed I was coming up with negative areas for both rings using JTS (MvtReader#classifyRings()):
CGAlgorithms.signedArea()
So right now what's happening is the coordinates come out matching to what you posted above (thanks for posting those it was helpful), but the rings are discarded as interior when the parser was expecting an initial exterior.
from mapbox-vector-tile-java.
I think the Mapbox parsers are more generous and will accept negative-signed-area outer rings if an outer ring has not been encountered yet because they're trying to be compatible with loosely-defined 1.0 MultiPolygon features? https://mapbox.github.io/earcut/ accepts it when the outer ring is null, a condition that I believe is outside the spec (AFAIK).
Is accepting this type of MultiPolygon a feature that you think will be needed in your project?
from mapbox-vector-tile-java.
Thanks for looking into that. My immediate thoughts are that it would be a great addition to support this type of MultiPolygon as tippecanoe still appears to output v1* data afaik.
The tippecanoe data failures led me to check out the tests and add some mapbox test tiles...only for us to discover the legacy data version.
As for using this type of polygon in the projects I am involved with...I'll need to create thousands of polygons from GML/shapefile/geojson. I think my first point of call would be to see what is involved in getting tippecanoe to output 2.1 tiles - but my gut is telling me it would already be done if that was a trivial change.
If this lib could parse older data then that would certainly be helpful for immediate needs - as the JS toolset appears to handle these geometries.
Let me know if you have any recommendations for creating v2.1 compliant data easily from GIS data (e.g. geojson).
* I assumed it would be updated pretty quickly to the latest spec version but from initial inspection that does not appear to be the case.
from mapbox-vector-tile-java.
I can look into a way to support the initial negative area ring case, but I'm not sure if that will completely solve it since I haven't done a 1.0 MVT parser. Is your tippecanoe output sharable?
from mapbox-vector-tile-java.
Here's an example in another Mapbox project that has been corrected as of June 9th for encoding 2.0 MVT winding order - https://github.com/mapbox/geojson-vt/blob/master/src/tile.js
function rewind(ring, clockwise) {
var area = signedArea(ring);
if (area < 0 === clockwise) ring.reverse();
}
function signedArea(ring) {
var sum = 0;
for (var i = 0, len = ring.length, j = len - 1, p1, p2; i < len; j = i++) {
p1 = ring[i];
p2 = ring[j];
sum += (p2[0] - p1[0]) * (p1[1] + p2[1]);
}
return sum;
}
I may ask on tippecanoe if they are enforcing this ordering or planning to.
from mapbox-vector-tile-java.
Tippecanoe has claimed to produce v2 tiles since 03d5c897
(Apr 25) and has intended to get winding correct since 5dc9f503
(Oct 7). If you are getting incorrect tiles, I would appreciate a sample of the GeoJSON and tippecanoe flags you are using so I can fix it.
from mapbox-vector-tile-java.
@ShibaBandit I have created a tippecanoe demo project using free data.
Perhaps it will be useful if I create a small project to read the MBTiles output and parse the geometries using your lib. I see @mourner says it produces 2.1 geometries. At the very least it would make a simple demo.
I would like to rule out a couple of things. Firstly that the geometries under test are only from Tippecanoe (and not, say, Mapbox Studio Classic) and secondly the data - I experienced issues with premium data.
@ericfischer thanks for the info.
from mapbox-vector-tile-java.
@snodnipper Do you want to check out the neg_ring_exteriors branch and see if it fixes your issues? So was that output from tippecanoe? If so that could be an example to provide @ericfischer with negative exterior rings.
from mapbox-vector-tile-java.
Thanks @ShibaBandit for that and sorry for the delay in getting back.
I have updated the demo to use the latest code and the output looks much better - much appreciated.
The only issue from JTS seems to be this error:
[main] ERROR com.wdtinc.mapbox_vector_tile.adapt.jts.JtsAdapter - side location conflict [ (3082.0, 2608.0, NaN) ]
com.vividsolutions.jts.geom.TopologyException: side location conflict [ (3082.0, 2608.0, NaN) ]
at com.vividsolutions.jts.geomgraph.EdgeEndStar.propagateSideLabels(EdgeEndStar.java:300)
at com.vividsolutions.jts.geomgraph.EdgeEndStar.computeLabelling(EdgeEndStar.java:139)
at com.vividsolutions.jts.geomgraph.DirectedEdgeStar.computeLabelling(DirectedEdgeStar.java:127)
at com.vividsolutions.jts.operation.overlay.OverlayOp.computeLabelling(OverlayOp.java:440)
at com.vividsolutions.jts.operation.overlay.OverlayOp.computeOverlay(OverlayOp.java:240)
at com.vividsolutions.jts.operation.overlay.OverlayOp.getResultGeometry(OverlayOp.java:189)
at com.vividsolutions.jts.operation.overlay.OverlayOp.overlayOp(OverlayOp.java:92)
at com.vividsolutions.jts.operation.overlay.snap.SnapIfNeededOverlayOp.getResultGeometry(SnapIfNeededOverlayOp.java:96)
at com.vividsolutions.jts.operation.overlay.snap.SnapIfNeededOverlayOp.overlayOp(SnapIfNeededOverlayOp.java:58)
at com.vividsolutions.jts.geom.Geometry.intersection(Geometry.java:1338)
at com.wdtinc.mapbox_vector_tile.adapt.jts.JtsAdapter.flatIntersection(JtsAdapter.java:141)
at com.wdtinc.mapbox_vector_tile.adapt.jts.JtsAdapter.createTileGeom(JtsAdapter.java:84)
at uk.os.wdtinc.demo.Main.lambda$main$1(Main.java:66)
All source data is from tippecanoe so it sounds like it could be an issue.
I have also translated some of their vector-tile-js code into java, where I could create valid multipolygon geojson - more for interests sake. I haven't attempted to put that output into the JTS or the ESRI geom library but it might be interesting in thrashing out such issues.
UPDATE: JtsAdapter.createTileGeom was erroneously called and that caused the error.
Thanks for sorting that issue.
Would you rather we investigate the tippecanoe rather than include this change in the lib?
from mapbox-vector-tile-java.
@snodnipper If you want, you can post your inputs / outputs somewhere in this issue (re-open) - mapbox/tippecanoe#285 ... or create your own. I don't do much c++ so I prob won't do a pull request. Totally up to you if you want to pursue it.
from mapbox-vector-tile-java.
If you have specific examples of polygons that Tippecanoe is getting wrong, please do post the source GeoJSON and the tippecanoe options you are using here or in a Tippecanoe issue so I can fix whatever is going wrong. Thanks!
from mapbox-vector-tile-java.
@ericfischer - I'll try and get some (isolated) data together to you in the coming days.
If you need to shoot ahead then you can check out the geojson created by this project. Changing z12 to 5 (from memory) will show relatively few geoms inc. invalid ones afaik.
from mapbox-vector-tile-java.
Merged support into master in #2
from mapbox-vector-tile-java.
Related Issues (20)
- Android API Level 15 compatibility HOT 14
- Decoding tiles from Thunderforest results in InvalidProtocolBufferException HOT 4
- Polygons crossing the Antimeridian HOT 17
- Layer Equality Failure HOT 2
- Issue with mvt generation for polygon geometry HOT 3
- Issue with mvt generation for line geometry HOT 4
- How to add JtsLayer(or VectorTile.Tile) object to android mapbox map? HOT 1
- how to add vector to mapbox android HOT 1
- Performance tuning HOT 4
- Upgrade to locationtech JTS core 1.16.1 HOT 6
- Locationtech JTS core to 1.15.1 HOT 1
- Polygon orientation HOT 6
- JtsAdapter calculate polygon area wrong
- JtsAdapter is swallowing it's exception HOT 2
- Decoding Vector Tile file into a geoGSON file
- LinearRing HOT 1
- Was 3.1.1 ever pushed? HOT 8
- Question: createTileGeom Envelope/MvtLayerParams
- Upgrade to JTS 1.17.0 HOT 10
- Failure to parse when there is MULTILINESTRING HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from mapbox-vector-tile-java.