Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I draw geoJSON in three.js as a mesh and not a line, and fill with color?

I'm making a globe in three.js and will be adding some data layers. All of the layers will be created from geoJSON. I have set it up so that the globe (the first data file, which is of countries) shows up as lines. This uses ThreeGeoJSON.

globe with lines

However, I do not want just outlines. I'd like to fill the countries with color.

My current project can be seen here: http://bl.ocks.org/jhubley/321232d4ccefefcdc53218fd0adccac5

The code is here: https://gist.github.com/jhubley/321232d4ccefefcdc53218fd0adccac5

I tried to create a new function that would render the polygons and multipolygons as meshes instead of lines. That function is as follows:

    function drawShape(x_values, y_values, z_values, options) {
        var shape_geom = new THREE.BoxGeometry();
        createVertexForEachPoint(shape_geom, x_values, y_values, z_values);

        var shape_material = new THREE.MeshBasicMaterial( {color: 0xffff00 } );
        var shape = new THREE.Mesh(shape_geom, shape_material);
        scene.add(shape);

        clearArrays();
    }

Unfortunately, nothing shows up when I use that. There are no errors in the console to help me understand why.

Can anyone explain how I could set up the countries so that they can be filled? Any advice or pointers would be very much appreciated.

like image 621
sprucegoose Avatar asked Sep 02 '25 16:09

sprucegoose


1 Answers

As @mlkn said you have to use triangles to fill a mesh.

I messed around a little:

function drawLine(x_values, y_values, z_values, options) {
  // container
  var obj = new THREE.Object3D();

  // lines
  var line_geom = new THREE.Geometry();
  createVertexForEachPoint(line_geom, x_values, y_values, z_values);
  var line_material = new THREE.LineBasicMaterial({
    color: 'yellow'
  });

  var line = new THREE.Line(line_geom, line_material);

  obj.add(line);

  // mesh
  var mesh_geom = new THREE.Geometry();
  createVertexForEachPoint(mesh_geom, x_values, y_values, z_values);
  var mesh_material = new THREE.MeshBasicMaterial({
    color: 'blue',
    side: THREE.DoubleSide
  });
  var mesh = new THREE.Mesh(mesh_geom, mesh_material);

  obj.add(mesh);

  scene.add(obj);

  clearArrays();
}

The Object3D obj is wrapping both lines and meshes.

Faces (triangles) are created here:

function createVertexForEachPoint(object_geometry, values_axis1, values_axis2, values_axis3) {
    for (var i = 0; i < values_axis1.length; i++) {
        object_geometry.vertices.push(new THREE.Vector3(values_axis1[i],
            values_axis2[i], values_axis3[i]));

        object_geometry.faces.push(new THREE.Face3(0, i + 1, i)); // <- add faces
    }
}

The result is bit of a mess, I don't know if because of the data or the vertex order/generation.

Demo:

  • https://gist.github.com/marcopompili/f5e071ce646c5cf3d600828ace734ce7
  • http://bl.ocks.org/marcopompili/f5e071ce646c5cf3d600828ace734ce7

That threeGeoJSON is poorly written IMO, without structure, as an example you just need to change the name of var scene = ... to var myscene = ... and the whole lib stop working, that's poor design.

Also there's a high amount of CPU usage, probably too many draw calls.

like image 136
Marcs Avatar answered Sep 05 '25 04:09

Marcs