Why does PointsMaterial size does not correspond with geographic grid cell size?


I am developing a 2D visualization tool for large gridded datasets (e.g. population grid of europe). Which uses a PerspectiveCamera and sets the z position of all points as 0.

I am drawing the xmin and ymin coordinates of each cell and I am trying to define the size of each Three.js point as the size of each cell in the units of its geographic projection.

For example I have a 5km² dataset in the EPSG 3035 coordinate reference system, which means that PointsMaterial.size should be 5000 (as the coordinates are in meters). However the cells are smaller than expected and I cant seem to work out why.

I have attached an image showing what I mean:

I can fix the issue for a specific dataset by playing around with the size value until the cells are sized correctly… for example:

…but the problem is that the visualization tool will have to accept datasets from different coordinate systems, meaning that I would need to find a way of adjusting the size dynamically for each system.

Point sizes for EPSG:3035 seem to be the right size if I multiply the ‘real’ size by 2.5 (5000*2.5), whereas EPSG:4326 for example needs to be multiplied by 4.

I have pointAttenuation enabled so I have a feeling that it might have something to do with it the scaling function it uses: size * ( scale / - mvPosition.z ); found here

Any ideas?

My camera is defined as: new PerspectiveCamera(50, width/height, 0.1, cellSize*1000);
…where cellSize is 5000.

TLDR: If the geographic distance between two point locations in a three.js scene is 5000 why does a Three.Points geometry not fill this space if PointsMaterial.size is set to 5000?

Have you considered to render with an orthographic camera?

Why? In this case the perspective projection will affect the final point size.

My application is based on this tutorial: https://observablehq.com/@grantcuster/using-three-js-for-2d-data-visualization which is why I use the perspective camera.

Without point attenuation the points stay the same size (in pixels) when I zoom in (like in the tutorial above). What I want is for the cells to grow in size as you zoom into the map. This is what i want. …but without having to change the cell size for each EPSG system.

I cant seem to get orthographic camera to work because i’m not sure how to define the left/right/top/bottom parameters. With perspective it was just a case of setting its position and lookAt() as specific coordinates (with position z as the ‘far’ value and lookAt() z as 0), but with orthographic im struggling. The projected bounds of EPSG:3035 for example are: 2426378.0132, 1528101.2618, 6293974.6215, 5446513.5222 but I cant work out how to define the camera frustrum to show this.

Docs have an example for that:

var camera = new THREE.OrthographicCamera( width / - 2, width / 2, height / 2, height / - 2, 1, 1000 );
scene.add( camera );

where width and height could be your canvas width and height, for example - then you automatically get the units to be pixels.

lets see, so the object width is 6293974 - 2426378 = 3867596 units? you could set orthographic camera width to that, and then do camera.position.x = (6293974 + 2426378) / 2; to get it on screen, I guess (and same for y)

If i use the following settings for orthographic camera it crashes the browser:

     let width = 6293974 - 2426378;
     let height = 5446513 - 1528101;
     let left = width / -2;
     let right = width / 2;
     let top = height / 2;
     let bottom = height / -2;
     camera = new OrthographicCamera(left, right, top, bottom, 1, 2000);

     let x = (6293974 + 2426378) / 2
     let y = (5446513 + 1528101) / 2 
     let z = 1000;
     camera.position.set(x, y, z);

I am pretty sure your model crashes it, not the camera. I guess you just cant show all of it at once without doing some LOD


you somehow managed to outpput huge points size, so there is massive overdraw. I had a situation like that, but instead of crashing it would just freeze.

I still dont understand why you would use an orthographic camera for this? Nothing I have tried with the orthographic camera has worked. Is it because I center the camera to geographic coordinates? eg ( 4369000, 2834000, 30000000)

This is what im after: https://eurostat.github.io/GridViz/examples/basic/index.html but I need to fix the scaling of the points so that if I define point size as 5km (5000) then it will appear in threejs as 5000 and then change size appropriately when changing the camera’s z position.

At the moment im looking into custom vertex and fragment shaders but its quite verbose for a noob like me.