-
-
Notifications
You must be signed in to change notification settings - Fork 184
-
Problem:
I want to generate a limited area, it could be a country, county, city, etc. However, limited extracts are always messy since extraction works based on cells and not exact bounds geometry. There are always lines, polygons and points extending over the intended area.
I need crisp cut-off on exact geometry, for example a county border which I have as a geoJSON.
In other words: geometry outside gets omitted, any geometry extending over bounds is cut to bounds (lines, polygons).
What I've done:
I've been playing around with this for few days now, so my steps taken are the first ideas. I'm manually converting the geoJSON coordinates to double[]. Then, at the start of the program, before any processors run, I convert it to Geometry like this:
public static Geometry createPolygonFromCoordArray(double[] c) { Coordinate[] coords = new Coordinate[c.length / 2]; for (int i = 0; i < coords.length; i++) { int ii = i * 2; coords[i] = new Coordinate(c[ii], c[ii + 1]); } return GeoUtils.latLonToWorldCoords(GeoUtils.JTS_FACTORY.createPolygon(coords)); }
I then pass the bounds geometry to all layer processors as an argument:
var landuse = new Landuse(bounds); registerHandler(landuse); registerSourceHandler("osm", landuse::processOsm);
When features are processed, I check if they are in bounds and omit if necessary:
if (!this.bounds.covers(feat.getGeometry())) { // only omitting at the moment, nothing is cut into bounds feat.omit(); return; }
Questions:
- Is there an utility or few to load geoJSON from file and convert it to
Geometry? - Since planetiler already has bounds feature.. How to detect geometry is partially outside the bounds and how to cut it?
- Is there a more intelligent/convenient way to cut all features in a layer to certain bounds or is my idea the way to go?
Thanks!
Beta Was this translation helpful? Give feedback.
All reactions
Maybe you can take some inspiration from the protomaps Clip.java file:
Replies: 1 comment 5 replies
-
Maybe you can take some inspiration from the protomaps Clip.java file:
Beta Was this translation helpful? Give feedback.
All reactions
-
Yeah this utility should do exactly what you want by post-processing tiles on the border of your polygon to remove any data outside. If it turns out to be generally useful maybe we could upstream it into planetiler?
Beta Was this translation helpful? Give feedback.
All reactions
-
That's very useful, thanks! I'll definitely find some inspiration from that and it seems to contain all the answers.
How ever I plan to use it more granually while processing the features, I won't benefit from global post-processing. Random example: a county contains all the details while rest of the country/world has borders, county/country names and very high-level landuse.
--clip option would definitely be useful for general use. I would personally love to see some one-liner planetiler API to have this functionality but it might be too specific use case, not use, I can make my own in any case..
Example:
// GeoJSON Geometry hopefully cached for repeated use feat = ClipUtils.clip(feat, "path/to/bounds.geojson");
Beta Was this translation helpful? Give feedback.
All reactions
-
I did hit one roadblock, I can't seem to figure out how to update existing FeatureCollector.Feature geometry.
@msbarry Is there a way?
If not, my alternative is to do the clipping on SourceFeature.worldGeometry() and use collector.geometry(name, clipped) instead of collector.line(), collector.point() etc.
collector.geometry(name, clipped) unfortunately has one side effect, for example with roads. Since I'm not telling that it's collector.line(), unnecessary polygons end up in output with closed loop road lines. Looks like I need to start using line(), polygon(), etc on SourceFeature instead of just worldGeometry().
Beta Was this translation helpful? Give feedback.
All reactions
-
I still think your best bet would be to modify Clip.java. This method does the post-processing: https://github.com/protomaps/basemaps/blob/main/tiles/src/main/java/com/protomaps/basemap/postprocess/Clip.java#L120-L157 - you could modify it to only clip certain layers or even give it a Predicate that tells it which features to clip and if you have multiple geometries for different features you could stack them, each with a different geojson/layer/feature predicate.
If you want to do it in process step then the only way to provide a custom geometry is features.geometry(layer, geometry). You could check sourceFeature.isPoint() or canBeLine or canBePolygon first too.
Beta Was this translation helpful? Give feedback.
All reactions
-
I appreciate all the tips and help, learned a lot.
Beta Was this translation helpful? Give feedback.