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

What projection is used for the ThreeJS coordinate system? #981

Closed
Krassnig opened this issue Feb 7, 2024 · 7 comments
Closed

What projection is used for the ThreeJS coordinate system? #981

Krassnig opened this issue Feb 7, 2024 · 7 comments
Labels
triage me I really want to be triaged. type: question Request for information or clarification. Not an issue.

Comments

@Krassnig
Copy link

Krassnig commented Feb 7, 2024

Hello,
I'm currently struggling with placing a few geometries and I can't quite figure out the coordinate system used.

Although the comment https://github.com/googlemaps/js-three/blob/main/src/util.ts#L89-L96
states that it is (WebMercator (EPSG:3857) --> WGS84) I get different result when I put a coordinate into epsg.io:
https://epsg.io/transform#s_srs=3857&t_srs=4326&x=1820541.7625204&y=6134799.8559301
vs.
xyToLatLng([ 1820541.7625204194 , 6134799.8559301235 ]) -> { lat: 48.20880202465933 , lng: 16.372499716642768 }

epsg.io: 48.1677013 16.354205
xyToLL : 48.2088020 16.372499

It would be really great if you could help me!
Thank you!

@Krassnig Krassnig added triage me I really want to be triaged. type: question Request for information or clarification. Not an issue. labels Feb 7, 2024
@wangela
Copy link
Member

wangela commented Feb 7, 2024

If you would like to upvote the priority of this issue, please comment below or react on the original post above with 👍 so we can see what is popular when we triage.

@Krassnig Thank you for opening this issue. 🙏
Please check out these other resources that might help you get to a resolution in the meantime:

This is an automated message, feel free to ignore.

@usefulthink
Copy link
Contributor

First of all, where did you get the x/y values from? And, are you using an anchor point for the three.js overlay?
If you got those by raycasting the three.js scene, at what zoomlevel did you read them?

@Krassnig
Copy link
Author

Krassnig commented Feb 7, 2024

Thank you for helping me!

I got the coordinates from the google maps click event (lat lng) and converted it into a ThreeJS coordinate using overlay.latLngAltitudeToVector3.
I used the anchor point 0, 0, 0.
No raycasting (yet).

The code below is a minimal reproduction:

const loader = new Loader({ apiKey: API_KEY });
await loader.importLibrary('maps');

const map = new google.maps.Map(document.getElementById('map')!, {
	center: { lat: 48.20877521256814, lng: 16.372467530134163 }, // central Vienna
	zoom: 20,
	mapId: '15431d2b469f209e',
	disableDefaultUI: false
});

const overlay = new ThreeJSOverlayView({
	anchor: { lat: 0, lng: 0, altitude: 0 },
	map,
	upAxis: 'Z',
});

map.addListener('click', (e: any) => {
	const vec =  overlay.latLngAltitudeToVector3({ lat: e.latLng.lat(), lng: e.latLng.lng(), altitude: 0 });
	const backlatlng = xyToLatLng([vec.x, vec.y]);
	console.log('xyToLatLng([', vec.x, ',', vec.y, ']) = { lat:', backlatlng.lat, ', lng: ', backlatlng.lng, ' }');
	
	// xyToLatLng([ 1820541.7625204194 , 6134799.8559301235 ]) -> { lat: 48.20880202465933 , lng:  16.372499716642768  }
	// epsg.io using EPSG:3857    1820541.7625204194 , 6134799.8559301235 -> 48.1677013 16.354205
});

// taken from https://github.com/googlemaps/js-three/blob/main/src/util.ts#L89-L96
/**
 * Converts WebMercator meters to WGS84 latitude/longitude.
 * (WebMercator (EPSG:3857) --> WGS84)
 */
function xyToLatLng(p: number[]): google.maps.LatLngLiteral {
	const EARTH_RADIUS = 6371010.0;
	const [x, y] = p;
  
	return {
	  lat: radToDeg(Math.PI * 0.5 - 2.0 * Math.atan(Math.exp(-y / EARTH_RADIUS))),
	  lng: radToDeg(x) / EARTH_RADIUS,
	};
  }

function radToDeg(radians: number) {
	return radians / Math.PI * 180;
}

Click anywhere in the world and then take the console output of vec.x and vec.y and then put that into epsg.io as described above.

The functions overlay.latLngAltitudeToVector3 and xyToLatLng both work correctly in the sense that the click translates to the correct position in the ThreeJS coordinate space and a ThreeJS coordinate can be correctly converted to lat lng.

@usefulthink
Copy link
Contributor

ok, so the main question is about the discrepancy between the numbers you get from epsg.io and this library?

@Krassnig
Copy link
Author

Krassnig commented Feb 7, 2024

I am not sure? I tried to import a few geometries from GLTF files and it always ends up in the wrong spot. I have also tried a bunch of other projections as well 😅, but I just can't figure it out.
I though about it some more. The question is not exactly about the discrepancy.

I was expecting it to be some kind of common projection? Is it not?
Maybe my understanding is lacking or I made a mistake and that is why the result from epsg.io does not match the output from xyToLatLng? The difference between xyToLatLng and epsg.io matches the difference between the expected and actual positions of the geometries I am trying to add.

Fundamentally, I just want to know if I can use a predefined projection or if I have to transform my geometries to EPSG:4326 and then further transform them with latLngToXY https://github.com/googlemaps/js-three/blob/fe5a22a1dd73e3fb72ddfe13af28c02a7aee78d3/src/util.ts#L78C17-L78C27?

@usefulthink
Copy link
Contributor

I think I just remembered what was special about the projections used here (I don't know why it is that way, but I've had my formulae confirmed by the engineers who built the WebGlOverlayView at google). The original "Web Mercator" / EPSG:3857 projection uses an earth radius of 6,378,137 meters, and the implementation used here uses a radius of 6,371,010 meters (I believe this is some sort of result of using the s2 geometry library internally).

I haven't done the math but I'm ready to believe this could be the reason for discrepancies.

@Krassnig
Copy link
Author

Thank you very much for your help!
Thanks to this I got it work using built in projection functions. I had to first transform the geometries to 4326 and then use the projection below.

+proj=merc +a=6371010 +b=6371010 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defs +type=crs

In hindsight it kind of is right there in the code 😅.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
triage me I really want to be triaged. type: question Request for information or clarification. Not an issue.
Projects
None yet
Development

No branches or pull requests

3 participants