How to change a longitude-latitude grid into other grids such as hexagonal grids from the bottom

Hi, everyone,I am a graduate student from China. I am fascinated by the excellent
performance of the Cesium on the web side and the idea of its opening and free

However, there is one thing that I couldn’t figure out, the division of
the grid

In Cesium, the grid is divided bases on longitude, latitude, and the
form of layers. I am not sure about my way of understanding and expressing this
idea, but what I am trying to do is to change a longitude-latitude
grid into other grids from the bottom. Such as a global discrete grid which is
similar to a hexagonal grid or a triangular grid. I have no clue.


When you say “the grid is divided based on longitude, latitude” in Cesium, what are you referring to? How terrain and satellite imagery load? Or something else?

CesiumJS has mechanisms to take imagery and reproject it on the globe with a Web mercator or geographic projection, but you could write your own tiling scheme based on one of those:

Unless you’re referring to something else.

I have a tough problem. First of all, I am really excited to receive your reply. I have found a solution to the problem I asked you half a month ago, but I found some new problems in the process of using Cesium to conduct research. I will discuss them in detail below. Warning: the article is long and messy.

My research direction is Discrete Global Grid Systems, so I used Cesium to draw DQG, a subdivision method proposed by my postgraduate tutor, as shown in the following picture: so beautiful!

But as I narrowed the distance, the problem arose, camera position:Cartesian3.fromDegrees(109, 35,5000000):

If you zoom in a little more, the problem becomes obvious, camera position:Cartesian3.fromDegrees(109, 35, 3000000):

I found out why: the OrientedBoundingBox of these undrawn grids don’t intersect with the six planes of Camera.frustum. But

these boxes are already in the Camera.frustum and why the intersection is -1,means that outside. as shown in the following figure:

The green are the six planes of Camera.frustum. The red is the OrientedBoundingBox of undrawn grids. We’ve seen the red OrintedBoundingBox in the frustum, why the intersection is -1??? The code:

tile.boundingBox = OrientedBoundingBox.fromRectangle(tile.rectangle, 0.0, 0.0);

var cullingVolume = camera.frustum.computeCullingVolume(camera.positionWC, camera.directionWC, camera.upWC);

var intersection = cullingVolume.computeVisibility(tile.boundingBox);

the result of intersection is -1.

Finally I found the reason: boundingVolume.intersectPlane was miscalculated.

boundingVolume.intersectPlane in CullingVolume.prototype.cumputeVisibility in CullingVolume.js. The code:

var result = boundingVolume.intersectPlane(Plane.fromCartesian4(planes[k], scratchPlane));

After struggling for days, I finally found the culprit:

Cartesian3.fromCartesian4(coefficients, scratchNormal)

In Plane.fromCartesian4().The Plane.fromCartesian4() source code:

Plane.fromCartesian4 = function(coefficients, result) {

var normal = Cartesian3.fromCartesian4(coefficients, scratchNormal);
    var distance = coefficients.w;

if (!CesiumMath.equalsEpsilon(Cartesian3.magnitude(normal), 1.0, CesiumMath.EPSILON6)) {
    throw new DeveloperError('normal must be normalized.');
    if (!defined(result)) {
        return new Plane(normal, distance);
    Cartesian3.clone(normal, result.normal);
    result.distance = distance;
    return result;


The Cartesian3.fromCartesian4() source code:

Cartesian3.fromCartesian4 = Cartesian3.clone;

Cartesian3.prototype.clone = function(result) {
return Cartesian3.clone(this, result);

Cartesian3.clone = function(cartesian, result) {
if (!defined(cartesian)) {
return undefined;
if (!defined(result)) {
return new Cartesian3(cartesian.x, cartesian.y, cartesian.z);

result.x = cartesian.x;
result.y = cartesian.y;
result.z = cartesian.z;

return result;


So I added a little code to test Cartesian3.fromCartesian4()’s problems: print coefficients and normal. And their x y z should be the same.

var count = 0;

Plane.fromCartesian4 = function(coefficients, result) {
*//>>includeStart(‘debug’, pragmas.debug);

  • Check.typeOf.object(‘coefficients’, coefficients);
    // test code begin:
  • var normal = Cartesian3.fromCartesian4(coefficients, scratchNormal);*
  • var distance = coefficients.w;
    //>>includeStart(‘debug’, pragmas.debug);
  • if (!CesiumMath.equalsEpsilon(Cartesian3.magnitude(normal), 1.0, CesiumMath.EPSILON6)) {
    throw new DeveloperError(‘normal must be normalized.’);
  • if (!defined(result)) {
    return new Plane(normal, distance);
    Cartesian3.clone(normal, result.normal);
    result.distance = distance;
    return result;

But their do not have the same x y z. When the screen pixels are 1920x903 :

when the screen pixels are 1280x833 :

The four children QuadTree grid of red rectangle mean that their father gird is intersect or inside with the camera.frustum.

normal = Cartesian3.fromCartesian4(cofficients, result) , I want to know the reason why normal.x != cofficients.x normal.y != cofficients.y

and normal.z != cofficients.z. (However I found that although normal != cofficients, the value of normal is not random. So I think that there must be rules in Cesium)

Please forgive me for disturbing you and my poooooooor English.

Looking forward to your reply.

Zhang Yaoyuan


In case you haven’t seen it, this might be an easier approach to creating a custom grid in CesiumJS, to just create a custom imagery provider. This PR does that to create a hexagonal grid: