Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add getBounds() method to geoJSON sources #5394

Open
AbelVM opened this issue Jan 23, 2025 · 5 comments · May be fixed by #5403
Open

Add getBounds() method to geoJSON sources #5394

AbelVM opened this issue Jan 23, 2025 · 5 comments · May be fixed by #5403

Comments

@AbelVM
Copy link

AbelVM commented Jan 23, 2025

As requested in the Slack thread linked below

https://osmus.slack.com/archives/C01G3D28DAB/p1737627086709479

The code would be as follows

async function _getbounds() {
	const bounds = new maplibregl.LngLatBounds();
	const data = await this.getData();
	const features = data.features;
	features.forEach(function(feature) {
		const c = feature.geometry.coordinates.flat(Infinity);
		for(let i = 0; i < c.length - 1; i += 2){
			bounds.extend([c[i], c[i+1]]);
		}	
	});
	return bounds;
}

maplibregl.GeoJSONSource.prototype.getBounds = _getbounds;

It works regardless the geometry type, or even with mixed geometry types. Testing it with the Add multiple geometries from one GeoJSON source

const mysource = map.getSource('national-park');
> $ {id: 'national-park', type: 'geojson', minzoom: 0, maxzoom: 18, tileSize: 512, }

const bounds = await mysource.getBounds()
> V {_sw: Dc, _ne: Dc}

JSON.stringify(bounds)
> '{"_sw":{"lng":-121.577415,"lat":40.409124},"_ne":{"lng":-121.246768,"lat":40.584978}}'

EDITED: simpler for loop, more performant

@HarelM
Copy link
Collaborator

HarelM commented Jan 24, 2025

I think this can be made to be an example, not sure it's worth the maintenance overhead. But I might be too strict... Your call...

@AbelVM
Copy link
Author

AbelVM commented Jan 24, 2025

IMHO, it's quite a trivial block of code that

  • shouldn't require much maintenance, as its dependencies are quite limited to core classes and methods that shouldn't change in time
  • easy to implement in trunk
  • it's compatible with any type of geoJSON geometries, even when mixed in the same file or geometry collections
  • enables the classical feature zoom to layer for geoJSON sources (the only source which bounds might be known without messing with the arbitrary metadata)

From my point of view, the benefits of adding this method are way above the costs 😄

NOTE: I've updated the snippet I made yesterday in a 5-minute break so that it can avoid extra, unneeded, steps

@AbelVM
Copy link
Author

AbelVM commented Jan 24, 2025

Faster (and ES6+) version

async function _getbounds() {
	const bounds = new maplibregl.LngLatBounds();
	const data = await this.getData();
	const coordinates = data.features
		.map(f => f.geometry.coordinates.flat(Infinity))
		.reduce((acc,cur) => [...acc, ...cur],[]);
	for(let i = 0; i < coordinates.length - 1; i += 2){
		bounds.extend([coordinates[i], coordinates[i+1]]);
	}
	return bounds;
}

maplibregl.GeoJSONSource.prototype.getBounds = _getbounds;

@HarelM
Copy link
Collaborator

HarelM commented Jan 24, 2025

As I said, feel free to open a PR, I don't have strong feelings either way...

@AbelVM AbelVM linked a pull request Jan 24, 2025 that will close this issue
@AbelVM
Copy link
Author

AbelVM commented Jan 24, 2025

Done: #5403

🤓

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 a pull request may close this issue.

2 participants