2d scale implementation for Legend?

1,180 views
Skip to first unread message

Kirk A

unread,
Jan 28, 2015, 2:48:17 PM1/28/15
to cesiu...@googlegroups.com
In the well-constrained 2D case, is there a canned implementation for a scale indicator, such as a printed map legend would typically provide? (I want to provide measurement context for the user, similar to miles/kilometers per inch -- not zoom levels.)

Arguably, this might vary by projection. However, I am not seeking cartographic correctness, just simply an approximate indication of scale as users interact with the zoom controls.

I would like to see something similar in the 2.5D and 3D models, but I understand that the differing constraints make the problem more challenging.

Thank you,
-Kirk

Kevin Ring

unread,
Jan 28, 2015, 5:31:55 PM1/28/15
to cesiu...@googlegroups.com
Hi Kirk,

Cesium doesn't have any sort of built-in scale indicator, but you can grab the one we wrote for National Map.  The code is here (Apache 2.0 license):


You can see what it looks like here:

Kevin

--
You received this message because you are subscribed to the Google Groups "cesium-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cesium-dev+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--

Kevin Ring

unread,
Jan 28, 2015, 5:34:58 PM1/28/15
to cesiu...@googlegroups.com
I should mention that this works in 3D only.  Adapting it for 2D and Columbus View is probably not too difficult.

Kirk A

unread,
Jan 29, 2015, 8:20:07 AM1/29/15
to cesiu...@googlegroups.com
Kevin,

Thank you very much for sharing your implementation!

-Kirk

j...@jayblanchard.net

unread,
Feb 20, 2015, 11:18:14 AM2/20/15
to cesiu...@googlegroups.com
Kevin,

Did you move this repo? I am interested in this.

Thanks!

Jay

Hyper Sonic

unread,
Feb 20, 2015, 12:02:22 PM2/20/15
to cesiu...@googlegroups.com, j...@jayblanchard.net
I see that the 2D scale display refers to the terrain between the camera and Earth's center, which is matches the view if the camera pitch is at or near -90 degrees. This is probably how most 2D scales operate, as most people don't tilt the view I suppose.

What would be neat is when the camera is tilted have a 2D scale on all 4 corners of the screen and one in the middle. If that's going overboard, perhaps just the standard 'below the camera' scale and one for the center of the screen when tilted.

Kevin Ring

unread,
Feb 21, 2015, 12:14:36 AM2/21/15
to cesiu...@googlegroups.com

Hi Jay,

No, the repo is in the same place, but the code has been merged to master and the phil-ui branch has been deleted.  If it's not obvious how to update the URLs, let me know and I'll send them through next time I'm on a real computer.

Kevin

Hyper Sonic

unread,
Feb 21, 2015, 12:25:39 AM2/21/15
to cesiu...@googlegroups.com

Hyper Sonic

unread,
Feb 21, 2015, 12:50:35 AM2/21/15
to cesiu...@googlegroups.com
Awesome, instead of adding a function yourself to calculate the shortest distance along the curved surface (such as from  http://www.movable-type.co.uk/scripts/latlong.html ) There's a Cesium function that'll calculate this for you:

geodesic.setEndPoints(leftCartographic, rightCartographic);
var pixelDistance = geodesic.surfaceDistance;

I see that I was wrong, the 2 rays cast are at the bottom center of the screen. I'm surprised they are only 1 pixel apart, but I suppose that is sufficient. Most of the time the bottom center of the screen shows the Earth, but if you zoom way out and pitch way down the rays won't intersect the Earth. However, this is a rare case from which I doubt many will be using to measure.

Kevin Ring

unread,
Feb 21, 2015, 12:52:36 AM2/21/15
to cesiu...@googlegroups.com

Right, National Map just hides the scale widget when the bottom center two pixels don't hit anything.  It's good enough for our purposes.

--

gowtham.m...@gmail.com

unread,
Apr 22, 2015, 6:15:29 AM4/22/15
to cesiu...@googlegroups.com
Hi Kevin,

Can you please tell me what changes I need to make to work it in 2D and 2.5D?

Thanks,
Gowtham.

Hyper Sonic

unread,
Apr 22, 2015, 11:45:38 AM4/22/15
to cesiu...@googlegroups.com, gowtham.m...@gmail.com
For 2D screen width in meters is:
viewer.scene.camera.frustum.right-viewer.scene.camera.frustum.left
screen height in meters is:
viewer.scene.camera.frustum.top-viewer.scene.camera.frustum.bottom
To determine pixelDistance divide screen width in meters by viewer.canvas.clientWidth

For CV('2.5D') it's mostly the same as 3D, except the part where you determine the distance between leftPosition and rightPosition. Since the world is flat and not curved it's a simple straight line distance computation rather than curved distance computation. So I believe you'd just have to change these 4 lines
var leftCartographic = globe.ellipsoid.cartesianToCartographic(leftPosition);
var rightCartographic = globe.ellipsoid.cartesianToCartographic(rightPosition);

geodesic.setEndPoints(leftCartographic, rightCartographic);
var pixelDistance = geodesic.surfaceDistance;
Determine the distance vector by subtracting leftPosition and rightPosition, and pixelDistance is the magnitude of that vector.

Add viewer.scene.mode checks to determine which method to use.

Hyper Sonic

unread,
Apr 23, 2015, 1:50:22 PM4/23/15
to cesiu...@googlegroups.com, gowtham.m...@gmail.com
On second thought, although that will get you the actual displayed distance, flat maps of Earth are warped. The Equator on a flat map is 40 Mega Meters which is the circumference. However, the Artic circle's circumference is about 16 Mega Meters yet it is stretched out at 40 Mega Meters. So the horizontal warp depends on the latitude. Vertical is warped in a different manner. So just use the same code as 3D. CV represents the curved Earth although it is displayed in a warped fashion.

gowtham.m...@gmail.com

unread,
May 1, 2015, 2:43:34 AM5/1/15
to cesiu...@googlegroups.com
Hi Kevin,
I am able to implement navigation controls and compass for 3D but it's not working for 2D and 2.5D. I need your help in implementing it for 2D and 2.5 D. Did you implemented it for 2D and 2.5D also? If not can you guide me on this?
Thanks in advance,
Gowtham.

Kevin Ring

unread,
May 1, 2015, 2:52:11 AM5/1/15
to cesiu...@googlegroups.com
Hi Gowtham,

No, sorry, I didn't implement it for 2D and 2.5D.  In the main project I work on, we use Leaflet instead of Cesium's 2D.

I'm afraid I can't tell you offhand how to make it work.  I would have to figure it out myself.

Kevin

--
You received this message because you are subscribed to the Google Groups "cesium-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cesium-dev+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Hyper Sonic

unread,
May 1, 2015, 1:56:36 PM5/1/15
to cesiu...@googlegroups.com
Getting positions in Columbus

pickEllipsoid https://github.com/AnalyticalGraphicsInc/cesium/blob/master/Source/Scene/Camera.js#L1920
This is similar to what I had here when picking the 2D plane.

However regular and WC coordinates don't match in Columbus mode, WC is 'swizzled'
And getPickRayPerspective https://github.com/AnalyticalGraphicsInc/cesium/blob/master/Source/Scene/Camera.js#L1949 uses the swizzled WC coordinates, which produces a swizzled ray.
To make things less confusing you can un-swizzle the ray
function unSwizzle(cart)
{
        var temp=cart.z;
        cart.z=cart.x; //X to Z
        cart.x=cart.y; //Y to X
        cart.y=temp; //Z to Y
}
ray
.origin=unSwizzle(ray.origin);
ray
.direction=unSwizzle(ray.direction);

So first get 2 rays one pixel apart on the bottom of the screen using camera.getPickRay , un-swizzle them, then

//get point on ground in Cartesian (unswizzled)
var CC3=Cesium.Cartesian3;
var steps=camera.position.z/(-myRay.direction.z);
var vec=new CC3();desCarte=new CC3();
CC3
.multiplyByScalar(myRay.direction,steps,vec);
CC3
.add(myRay.position,vec,desCarte);

This next part is similar to this function

//Cartesian to Cartographic (for Columbus and 2D unswizzled)
function yToLat(y)
{
   
var neg=1;if(y<0){neg=-1;}y=Math.abs(y);
   
var halfheight = Math.PI * 6378137 / 2; //width/2/2;
   
var ratio = y / halfheight;
   
return ratio * (Math.PI/2) * neg;
}
desCarto
= new Cesium.Cartographic();
desCarto
.longitude=desCarte.x / 6378137;
desCarto
.latitude=yToLat(desCarte.y);
desCarto
.height=desCarte.z;

Once you have both of your Cartographic points you can figure the distance (this is from https://github.com/NICTA/nationalmap/blob/master/src/ViewModels/DistanceLegendViewModel.js )
var leftCartographic = globe.ellipsoid.cartesianToCartographic(leftPosition);
var rightCartographic = globe.ellipsoid.cartesianToCartographic(rightPosition);
geodesic
.setEndPoints(leftCartographic, rightCartographic);
var pixelDistance = geodesic.surfaceDistance;

Kevin Ring

unread,
May 1, 2015, 7:28:29 PM5/1/15
to cesiu...@googlegroups.com
Hi Hyper,

We reorganized things in National Map quite a bit over the past couple of days.  The code you're looking for is now here:


Kevin

--
You received this message because you are subscribed to the Google Groups "cesium-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cesium-dev+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Hyper Sonic

unread,
May 2, 2015, 5:56:40 AM5/2/15
to cesiu...@googlegroups.com
Thanks for the updated link Kevin! From DistanceLegendViewModel.js the 2 rays are 1 pixel apart
var left = scene.camera.getPickRay(new Cartesian2((width / 2) | 0, height - 1));
var right = scene.camera.getPickRay(new Cartesian2(1 + (width / 2) | 0, height - 1));
This should work well for Columbus as well as 3D.

gowtham.m...@gmail.com

unread,
May 4, 2015, 1:14:19 PM5/4/15
to cesiu...@googlegroups.com
Hi Kevin,
As per the implementation of scale legend in DistanceLegendViewModel.js geodesic.surfaceDistance is the actual distance between two points in cesium map. For what purpose you are using distances array and you are taking values like 1,2,3,5.. 10,20,30,50.. like that. Could you please explain me about this?

Thanks,
Gowtham.
On Thursday, January 29, 2015 at 1:18:17 AM UTC+5:30, Kirk A wrote:

Hyper Sonic

unread,
May 4, 2015, 1:23:27 PM5/4/15
to cesiu...@googlegroups.com, gowtham.m...@gmail.com
https://github.com/TerriaJS/terriajs/blob/master/lib/ViewModels/DistanceLegendViewModel.js#L122
// Find the first distance that makes the scale bar less than 100 pixels.

You can check it out at http://nationalmap.nicta.com.au/
The legend bar is on the bottom right.

gowtham.m...@gmail.com

unread,
May 22, 2015, 1:03:38 AM5/22/15
to cesiu...@googlegroups.com
Hi Kevin,
Need your help in showing location bar for 2D map view. For 3D and 2.5D it's working fine. Could you please tell me what changes I need to make it work for 2D (showing lat,long and elevation)?

On Thursday, January 29, 2015 at 1:18:17 AM UTC+5:30, Kirk A wrote:

Kevin Ring

unread,
May 22, 2015, 1:06:24 AM5/22/15
to cesiu...@googlegroups.com
Hi,

I wouldn't expect it to be any different from 2.5D, really.  What's going wrong?

Kevin

--
You received this message because you are subscribed to the Google Groups "cesium-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cesium-dev+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

gowtham.m...@gmail.com

unread,
May 22, 2015, 1:22:22 AM5/22/15
to cesiu...@googlegroups.com
Hi Kevin,
pickTriangle is coming as undefined in locationbarviewmodel.js for 2D.

Thanks,

sas...@gmail.com

unread,
Sep 23, 2015, 4:43:09 AM9/23/15
to cesium-dev
Hi,

Which Cesium API should I use if the scale indicator can be recalculated instantly when the attitude of camera changed?

Hyper Sonic於 2015年5月2日星期六 UTC+8下午5時56分40秒寫道:
Message has been deleted
Message has been deleted

sas...@gmail.com

unread,
Sep 23, 2015, 5:34:23 AM9/23/15
to cesium-dev, gowtham.m...@gmail.com
Hi Gowtham,

My requests is similar to yours. Could you provide your source code for my reference? Looking forward your response~

gowtham.m...@gmail.com於 2015年5月22日星期五 UTC+8下午1時22分22秒寫道:
Reply all
Reply to author
Forward
0 new messages