What is the best way to render geoJSON as a mesh instead of a line in three.js, and apply a color fill to it?

Currently working on a three.js globe project that involves adding data layers using geoJSON. The initial layer, representing countries, is displayed as lines thanks to ThreeGeoJSON.

https://i.sstatic.net/nuBkR.png

However, I am aiming to go beyond just outlines and fill the countries with color.

You can view my ongoing project here: http://bl.ocks.org/jhubley/321232d4ccefefcdc53218fd0adccac5

The code for this project can be found here: https://gist.github.com/jhubley/321232d4ccefefcdc53218fd0adccac5

I have attempted to create a new function that would render polygons and multipolygons as meshes instead of lines. Here is the function:

    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 appears when using this function. There are no console errors to provide insight into the issue.

If anyone has suggestions on how I could successfully fill the countries, I would greatly appreciate any advice or guidance.

Answer №1

According to @mlkn, utilizing triangles is essential for filling a mesh.

I experimented with the concept:

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 serves as a wrapper for both lines and meshes.

This is where faces (triangles) are generated:

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 outcome appears somewhat chaotic, possibly due to issues with the data or vertex arrangement/generation.

Check out the demo links below:

In my opinion, the threeGeoJSON code lacks structure, evidenced by minor changes causing it to stop functioning. This indicates poor design.

Furthermore, there seems to be excessive CPU usage, potentially stemming from an abundance of draw calls.

Answer №2

Creating a filled shape from segments involves outlining them and connecting them with triangles, as explained further in webgl draw modes here.

To display a filled country on a globe, you must triangulate the set of segments. There are various methods to achieve this, with pre-written code like the earcut implementation found here.

One potential challenge is the size of the resulting polygons after triangulation. If large triangles are produced and then transformed into spherical coordinates, they may appear flat. One solution could involve using displacement mapping or subdividing triangles based on their area.

It's important to note that triangulation can be resource-intensive, so if it doesn't need to be done in real-time, consider preparing geometry offline. For dynamic data, utilizing a webworker or an efficient non-JavaScript server can help optimize performance.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Submitting form by clicking a link on the page

To submit a POST request with "amount=1" without displaying it in the URL, I need the site to send this request when any link on the site is clicked. This JavaScript code achieves that with a GET request: window.onload = function () { document.body.oncli ...

The continual appearance of "No file found" persists when utilizing the $redirectRoute

My goal is to make one of the links on my website lead to another page within the site. Below is one of the two links found on my index.html page: <html ng-app="myApp"> . . . <body> <h1>My Home Page</h1> ...

javascript detect when two div elements are overlapping

On my webpage, I have implemented the effect.shrink() function. However, when clicking quickly on the page, the div tags start overlapping with other elements. What is the best way to solve this issue? I am using both scriptaculous.js and prototype.js fo ...

Exploring the intricacies of managing nested data in a Firebase Database (web)

I understand this question may have similarities to others already asked, so my apologies in advance. I am seeking a clear, up-to-date solution that aligns with my expectations. https://i.sstatic.net/dQ9ih.jpg If I have an object labeled "Item One", how ...

Create PDF and Excel files using Javascript on the client side

Are there any client-side Javascript frameworks that are comparable to Jasper Report in Java? I need to be able to generate both PDF and Excel files on the client side (browser) without relying on server-side processing. While I've come across Ja ...

Creating a custom event for every reference within a Vuejs for loop

I'm working with a loop of data and have a modal for each iteration <div ref="vuemodal-{{loop.index}}"> Each modal is a bootstrap modal, and I want to bind an event to them that triggers whenever the modal is closed mounted(){ Obj ...

Clearing Time Field Input in Safari

Recently, I've been utilizing the following HTML input element: <input type="time"> While testing it in both Chrome and Safari, I noticed that the clear field (cross button) is absent when using Safari. How can I make the cross button appear i ...

Incorporate a corner box feature to bring attention to the typed.js functionality

I have successfully integrated typed.js into my project and now I am looking to replicate the highlighted text with an excel-like box in one corner. I've managed to get the text typing out while also adding an SVG for the box in HTML, but I'm hav ...

Creating a JSON array using looping technique

I am attempting to construct a JSON array using a loop where the input className and value will serve as the JSON obj and key. However, I am facing difficulties in creating one and cannot seem to locate any resources on how to do so. Below is an example sn ...

Incorporate new class into preexisting modules from external library

I am currently working on expanding Phaser by incorporating a new module called Phaser.Physics.Box2D. While Phaser already utilizes this module internally, it is an additional plugin and I am determined to create my own version. TypeScript is the language ...

What is the method to obtain the content height of individual pages in Android, with or without the use of JavaScript?

I am facing an issue while trying to retrieve the content height of each webpage consecutively. When I load pages separately, I can successfully get the height of each page. However, when I attempt to fetch the content height continuously for webpages in a ...

Mastering the Art of Mocking DOM Methods with Jest

What is the best way to simulate this code snippet using Jest : useEffect(() => { document .getElementById('firstname') ?.querySelector('input-field') ?.setAttribute('type', &apos ...

Identifying whether a Alphabet or a Digit has been Pressed - JavaScript

I understand that it is possible to detect if a key has been pressed and identify which key was pressed using JavaScript. In order to check if a key is down or pressed, jQuery can be utilized with ease: $( "#some id" ).keydown(function() or $( "#m" ). ...

Checking the efficiency of Graphql API

Currently, I am in the process of optimizing key features within my Node.js API which incorporates GraphQL. This API serves as a proxy, receiving requests from various sources and forwarding them to multiple APIs based on the request. I am interested in ...

"JavaScript that doesn't rely on a specific browser

Why does this code behave differently across browsers? What modifications are needed to ensure consistent behavior in all of them? In Firefox, it functions correctly, using the URL /some/path/?searchedText=sometext. However, in IE, nothing happens when cli ...

Numerous instances of Codemirror

I have the ability to generate and exhibit multiple dynamic codemirror instances, however, I am having trouble referencing them using the code snippet below. I suspect that the problem lies in creating a dynamic function name (not entirely sure how to ac ...

Steps to implementing a function just before a form is submitted

Imagine a scenario where you have the following HTML form: <form action="myurl.com" method="post" id="myForm"> <input type="number" name="number" class="numberInput"> <input type="number" name="number"> <input type="submit ...

What is the process for changing the output paper size to A4 in React Native (expo android)?

Using React Native to develop an Android app for billing purposes, I encountered an issue with the output paper size being 216mmX279mm instead of the standard PDF size of 210mmX297mm. Utilizing expo-print and printToFileAsync from expo, I aim to achieve a ...

Implement Clip Function with Gradient Effect in JavaScript on Canvas

Trying to incorporate the clip() function within the canvas element to create a unique effect, similar to the one shown in the image. I have successfully achieved a circular clip, but I am now aiming for a gradient effect as seen in the example. How can th ...

Receiving reliable information from an API in my Node server without experiencing any disruptions

A node server is being utilized to retrieve trades data from Binance. With more than a thousand pairs for which trades need to be fetched, the function takes some time to execute completely. To ensure that new data keeps coming in while the server is live ...