Skip to content

Conversation

SoftwareMechanic
Copy link
Contributor

added geojson support as overlay and tilesplugin

@SoftwareMechanic SoftwareMechanic changed the title Feature/geojson Add GeoJSON format support Sep 5, 2025
@gkjohnson gkjohnson linked an issue Sep 5, 2025 that may be closed by this pull request
@gkjohnson gkjohnson added this to the v0.4.16 milestone Sep 9, 2025
Copy link
Contributor

@gkjohnson gkjohnson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is great to see - and a really nice approach to overlaying and generating it.

Can you explain your use case a bit? Are you planning to have multiple polygons with multiple colors? One potential issue I see is that multiple colored geojson data sets will require separate layers of images which could cause a bit of an explosion of memory.

One thought I had is that the geojson could be converted to SVG and then you'd have all the flexibility of SVG scalability and CSS styling. This geojson2svg package supports Geojson > SVG conversion. Who know's how the performance may be affected, though 🤔 Something to explore in the future.

edit And sorry for the commit rework. I wanted to remove the dependency on #1302 so we can get this merged separately if needed.

'https://www.gstatic.com/draco/v1/decoders/',
);

const geojson = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the source for this polygon data?

Copy link
Contributor Author

@SoftwareMechanic SoftwareMechanic Sep 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bacino_varenna_aggregato4326.json
I have this local file geojson (in order to load it here on Github, I had to change the extension from .geojson to .json), I wanted to try to have both an url or a geojson object.
the reasons for geojson object was because I wanted to start thinking about a "drawPlugin",
but also because maybe the front end developer could handle a conversion of it to the accepted EPSG,
in any case if just URL is provided, we should make sure that the geojson is defined in supported EPSG codes looking at 'crs.properties.name' of the object.

what do you think about this?
we can just keep the url if you prefer, to make it coherent with the library


const geojsonOverlay = new GeoJSONTilesOverlay( {

levels: 14, // choose max zoom to rasterize overlay ( 12- 14 typical )
Copy link
Contributor

@gkjohnson gkjohnson Sep 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an interesting new case - this is a good solution for now. It may be worth adjusting overlays so that they can load up to whatever maximum resolution the underlying tile set is at in order to more easily support these kinds of dynamically generated / flexible types of data sets.

edit created #1310

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

absolutely agree, I think that somehow we should maybe have access to the levels defined for the plugin the geojson is onto in order to manage that dynamically.
or hardcode an high number of levels if the prop is not provided?

@SoftwareMechanic
Copy link
Contributor Author

SoftwareMechanic commented Sep 9, 2025

This is great to see - and a really nice approach to overlaying and generating it.
thank you so much, I appreciate.

Can you explain your use case a bit?

In my use case, for the project I'm working on, I'd like the user to upload any geojson for a specific project (in supported EPSG, of course; the platform I'm working on could eventually convert them to the desired EPSG in the future), and these geojsons should be overlaid on a globe/basemap (photorealistic tiles, cesium globe, or whatever "base layer" the user wishes). One of the purposes of the geojson is to highlight, for example, the valley affected by a specific infrastructure (such as a bridge), so that the user can not only better see the area for whatever reason, but also understand, for example, whether a heavy rainfall (provided by a WMS) is within the area of ​​interest or not, perhaps causing a flood, and so on.

Are you planning to have multiple polygons with multiple colors? One potential issue I see is that multiple colored geojson data sets will require separate layers of images which could cause a bit of an explosion of memory.

that would be possible, I didn't think about it honestly, we could have colors for each feature, similarly to what is possible to do with your geojson library for three.js.

about having multiple datasets, yes I understand that drawing on multiple canvas can be heavy if multiple data sets are there, in that case, I would consider, if possible, to have only one data set with multiple datasets, in order to create and draw using only one canvas per time, maybe having an Api from GeoJSONTilesOverlay/Plugin, to add a dataset and manage the "merge" of datasets behind the scene, or I would consider to test your suggestion about SVG.
if the SVG solution would work and is more performant, I'd keep that solution as the definitive, and even more simple maybe.

honestly I already made some tests with SVG but I have to dig more, I will consider that converter you linked me, or drawing them directly as I did in my last commit.

I think that the advantage you see in using SVG is to don't have to worry about levels and redrawing images, in order to gain performance, am I right? I agree with that eventually 🚀 , but with current implementation svgs are created whenever it would create other images format, eventually we should keep track of the memory and cpu usage to see what is the best approach, and how to optimize it.

@gkjohnson
Copy link
Contributor

in supported EPSG, of course; the platform I'm working on could eventually convert them to the desired EPSG in the future

As far as I understand, GeoJSON does not support custom CRS. The values should always be in latitude / longitude which will be universal. To that end the "GeoJSONImageSource" shouldn't need a custom CRS other than to adjust the implicit tiling scheme. Though I think that's probably not needed for this.

that would be possible, I didn't think about it honestly, we could have colors for each feature

For reference it looks like Mapbox provides a custom styling system for things like this but it would be nice to avoid adding an overly complex styling system.

I think that the advantage you see in using SVG is to don't have to worry about levels and redrawing images, in order to gain performance, am I right?

Unfortunately in order to render SVG in WebGL (or WebGPU afaik) you still have to rasterize the SVG data to a texture, so you will still have to deal with levels and the texture generation. But SVG is a good standard for these kinds of vector images and supports declarative styling out of the box rather than requiring a custom one. Once concern I have is that this will be slower, though, because of the complexity of the styles, but it will require some testing.

Merge branch 'feature/geojson' of https://github.com/SoftwareMechanic/3DTilesRendererJS into feature/geojson

It looks like you've pulled and merged the cherry picked and rebased version of the branch I made into your local version, which has brought back all the styling changes I fixed. I can force push my version of the branch again but you'll need to pull it and overwrite your local version. Alternatively we can wait until #1302 is merged and you can fix up the styling issues in this branch then. The diff is otherwise too complex to understand now, unfortunately. Let me know what you'd like to do!

@SoftwareMechanic
Copy link
Contributor Author

As far as I understand, GeoJSON does not support custom CRS. The values should always be in latitude / longitude which will be universal. To that end the "GeoJSONImageSource" shouldn't need a custom CRS other than to adjust the implicit tiling scheme. Though I think that's probably not needed for this.

Once it happened that I received a .geojson file in EPSG:3003, but that was in fact an exception, and not even the Cesium Viewer can render it by default, so I agree to treat them as latitude longitude coordinates, maybe we can just write a line in the docs or in a comment in the example about this

For reference it looks like Mapbox provides a custom styling system for things like this but it would be nice to avoid adding an overly complex styling system.

I agree, I would not add another 'rendering' layer, not for now at least. the more is simple the better it is imo.

Unfortunately in order to render SVG in WebGL (or WebGPU afaik) you still have to rasterize the SVG data to a texture, so you will still have to deal with levels and the texture generation. But SVG is a good standard for these kinds of vector images and supports declarative styling out of the box rather than requiring a custom one. Once concern I have is that this will be slower, though, because of the complexity of the styles, but it will require some testing.

that was in fact my doubt about webGL, but I agree that using SVG is better for drawing and styling, and can lead us to have a good and modular management of the styling eventually.

It looks like you've pulled and merged the cherry picked and rebased version of the branch I made into your local version, which has brought back all the styling changes I fixed. I can force push my version of the branch again but you'll need to pull it and overwrite your local version. Alternatively we can wait until #1302 is merged and you can fix up the styling issues in this branch then. The diff is otherwise too complex to understand now, unfortunately. Let me know what you'd like to do!

🙈 I am sorry I messed up with GH desktop.
you can forse push and I will overwrite my local version, my bad!

Copy link
Contributor

@gkjohnson gkjohnson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added some initial comments. I'll take a look at the drawing code later this week.

geojson = null,
url = null, // URL or GeoJson object can be provided
tileDimension = 256,
bounds = [ - 180, - 90, 180, 90 ],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of passing "bounds" into the image source it would be best to calculate the bounds of the geojson object so it's a tight bounds (including some margin to account for stroke thickness, etc.

Copy link
Contributor Author

@SoftwareMechanic SoftwareMechanic Sep 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for the moment in this new commit I will set the bounds like for other image sources using the crs bounds, but if using the bounds limited to the entity can optimize the process, I would like to implement this, even in #1302 , a lot of WMS services like geojson use only a small portion of the map to display data in there.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if using the bounds limited to the entity can optimize the process, I would like to implement this

Calling TilingScheme.setContentBounds tells the tiling instance that any tiles that do not include that content bounds in its range is non existent and should not be loaded. This prevents unnecessary data loading and prevents render targets for overlays from being generated - saving memory and performance.

even in #1302 , a lot of WMS services like geojson use only a small portion of the map to display data in there.

I'd added this in some of the WMSImageSource updates - the constructor takes a contentBounds field (which can be derived from the EX_GeographicBoundingBox in the WMS capabilities XML) and is used to set the content bounds of tiling here (with the full CRS range used as a fallback).

Copy link
Contributor Author

@SoftwareMechanic SoftwareMechanic Sep 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is awesome!! thank you for confirm me this

I tried setting the bounds, but seems that if I don't use very large offset, the geojson won't be even rendered, in the last commit I added a method to get the bounds from geojson, but it's usage is commented out as it's not working as expected, I would expect to don't even need to use an offset, but maybe I didn't get something about this

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like there may actually be an issue with this that's appeared after some recent changes. I made #1320 to track it can can take care of it after this is merged.

Comment on lines 57 to 68
const res = await this.fetchData( this.url );
// fetchData should return a Response-like object
// allow both Response and plain object (in case overlay fetch returns parsed JSON)
if ( res && typeof res.json === 'function' ) {

this.geojson = await res.json();

} else if ( res ) {

this.geojson = res;

}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What case are you imagining where fetchData will return pre-parsed JSON? I think it should be okay to assume this is performing a typical fetch in this case.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found out that it works parsing the data but also without parsing it, you can try i.e. with this public geojson used in 'url' parameter: italy municipalities
(it's a bit heavy as geojson, but I just used the first one I found)

but I think that the best thing to do is to parse it anyway, what do you think?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if I completely follow. Calling fetchData is expected to return a Request object, not a normal Javascript Object that could be GeoJSON - so the expectation is that we will always need to call "res.json()" here unless I'm missing something?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

now I got it, I am sorry I didn't understand what you mean (sometimes my english lacks), bear with me
that was a distraction error in the code, will be fixed!

Comment on lines 70 to 75
} catch ( e ) {

console.warn( 'GeoJSONImageSource: failed to fetch geojson from url', this.url, e );
// continue, but without geojson no tiles will be produced

}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should just let this init function throw an error so it can be handled elsewhere if needed. This is what the other image sources do.

…son), fix for level generation and parsing.

added also a commented parameter in the example, in order to test the system with a public geojson url
… gain performance, tested but not confirmed

not completely successful, as it need a big offset in order to render the geojson
SoftwareMechanic and others added 2 commits September 16, 2025 02:27
… made sure to use all "type" of geojson, canvas rounding to integer
@gkjohnson
Copy link
Contributor

Thanks for the updates! I'll plan to make a few changes to simplify the code in some places. For now I think we can remove the SVG path, as well. We can always come back to this PR to get it in the history if needed.

@gkjohnson
Copy link
Contributor

gkjohnson commented Sep 18, 2025

Thanks! I'm going to merge this and move it into the examples/src folder, for now. I think there are still some open questions to be worked out regarding multiple geojson assets, styling, etc. Once some of these things are worked out we can move it in to core! I'll actually just leave this undocumented, for now, until some of the issues are worked out.

Thank you again for all the work on this.

@gkjohnson gkjohnson merged commit 1292a42 into NASA-AMMOS:master Sep 18, 2025
1 check passed
@SoftwareMechanic
Copy link
Contributor Author

thanks to you for all the support and the help!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add Support WMS Tiled Image Format and GeoJSON
2 participants