Calculating the volume of an STL file mesh using three.js

I'm currently trying to figure out how to determine the volume of an STL file. I've successfully managed to obtain the dimensions of the model using

var box = new THREE.Box3().setFromObject( mesh );
var sizes = box.getSize();

However, when it comes to actually calculating the volume, I'm struggling to grasp the concept. To load the model, I use

var loader = new THREE.STLLoader();
loader.load(stlFileURL, function ( geometry ) {});

Could someone please provide guidance on how to approach this task? My implementation is in javascript.

Answer №1

Discover the solution using the algorithm mentioned in my comment.

The volume calculation in the code snippet is done without any scaling applied.

Furthermore, I have included a basic validation to ensure the accuracy of the algorithm by calculating the volume of a hollow cylinder. Since THREE.STLLoader() provides a non-indexed geometry, I have converted the cylinder's geometry to non-indexed as well.

Explore related discussions here

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.01, 1000);
camera.position.setScalar(20);
var renderer = new THREE.WebGLRenderer();
renderer.setClearColor(0x404040);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

var controls = new THREE.OrbitControls(camera, renderer.domElement);

var loader = new THREE.STLLoader();
loader.load('https://threejs.org/examples/models/stl/binary/pr2_head_pan.stl', function(geometry) {

  var mesh = new THREE.Mesh(geometry, new THREE.MeshBasicMaterial({
    color: 0xff00ff,
    wireframe: true
  }));
  mesh.rotation.set(-Math.PI / 2, 0, 0);
  mesh.scale.setScalar(100);
  scene.add(mesh);

  console.log("The volume of the STL file is: " + getVolume(geometry));
});

// Compare with known volume:
var hollowCylinderGeom = new THREE.LatheBufferGeometry([
  new THREE.Vector2(1, 0),
  new THREE.Vector2(2, 0),
  new THREE.Vector2(2, 2),
  new THREE.Vector2(1, 2),
  new THREE.Vector2(1, 0)
], 90).toNonIndexed();
console.log("Pre-calculated volume of a hollow cylinder (PI * (R^2 - r^2) * h): " + Math.PI * (Math.pow(2, 2) - Math.pow(1, 2)) * 2);
console.log("Computed volume of a hollow cylinder: " + getVolume(hollowCylinderGeom));


function getVolume(geometry) {

  let position = geometry.attributes.position;
  let faces = position.count / 3;
  let sum = 0;
  let p1 = new THREE.Vector3(),
    p2 = new THREE.Vector3(),
    p3 = new THREE.Vector3();
  for (let i = 0; i < faces; i++) {
    p1.fromBufferAttribute(position, i * 3 + 0);
    p2.fromBufferAttribute(position, i * 3 + 1);
    p3.fromBufferAttribute(position, i * 3 + 2);
    sum += signedVolumeOfTriangle(p1, p2, p3);
  }
  return sum;

}

function signedVolumeOfTriangle(p1, p2, p3) {
  return p1.dot(p2.cross(p3)) / 6.0;
}

renderer.setAnimationLoop(() => {
  renderer.render(scene, camera);
});
body {
  overflow: hidden;
  margin: 0;
}
<script src="https://threejs.org/build/three.min.js"></script>
<script src="https://threejs.org/examples/js/loaders/STLLoader.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>

Answer №2

Solving this particular problem can be quite challenging. A possible approach is to break down the object into multiple convex polyhedra and calculate the volumes of each.

Alternatively, you could voxelize the object and tally up the interior voxels to approximate its volume, although the accuracy would be influenced by the voxelization resolution.

Edit: prisoner849 came up with a fantastic solution!

Answer №3

I've been grappling with the same issue, but haven't made any progress yet.

One approach that caught my attention is building upon the concept of voxelization as suggested by @manthrax.

The idea here is to voxelize the data into an octree structure.

If the cube still intersects with multiple triangles, we could further delve into sub-dividing the octree until we reach a level where only one triangle is cut through,
At this point, we can determine the volume of the cube using the method described in:


Upon understanding prisoner849's solution, It becomes evident that this approach is no longer as promising as his solution.

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

Is there a way to capture the stdout and stderr output from a WebAssembly module that has been generated using Emscripten in JavaScript?

In my C++ code snippet below: #include <iostream> int main() { std::cout << "Hello World!" << std::endl; return 0; } I compile the code using: emcc -s ENVIRONMENT=shell -s WASM=1 -s MODULARIZE=1 main.cpp -o main.js This c ...

Input form and select form collide in conflict when the "Enter" key is activated

My search box includes input forms and a select form with various options. The issue arises when using the place autocomplete feature from Google Maps alongside the select form. When the enter key is pressed after entering a location in the autocomplete fi ...

Problem detected in id modification

My JavaScript function is triggered with an onChange event, which works fine when there's only one. <input class="form-control" type="text" onchange="opert(<?php echo $fetch["id_prod"] ?>,1)" id="name" value="<?php echo $fetch["name_prod" ...

Issue with specific route causing server to throw 500 error

Recently, I have been working on a small school project that involves creating our own API and connecting it to an Angular front end. While following some tutorials, I encountered an issue where my application started throwing internal server error 500 af ...

Retrieve coordinates of the clicked location with RichMarker in the Google Maps JavaScript API v3

I followed the solution provided here for richmarker.js After implementing it, when I use my_rich_marker.addListener('click', function(event) { console.log(event); //undefined } What I am trying to achieve is to access event.latLng of the ...

The PHP Comet feature is causing the page to experience delays in reloading

Hello, I am working on implementing comet functionality using PHP and jQuery. The comet starts with every page load, but this seems to be causing a significant delay in loading any page on the website, taking about 10 seconds. It appears as though the page ...

What is the method for replacing browser bundle sources using Rollup?

Is it possible to use rollup to swap out a specific source with another source in an NPM package when creating a browser bundle? The source in question is loaded dynamically using import('./relativeFile.js') (I need this to be replaced). I attem ...

Changing the prefix for a guild can be done without needing a complete restart, while adding a new guild to my database inexplicably requires one

I have set up a code that adds guilds to the database with default settings when they join. If the guild decides to change the prefix, it updates successfully and they can immediately start using it. However, there is an issue where I have to restart the b ...

Engage in a conversation with a specific individual on the internet using node.js

Looking to implement a chat feature with specific online users similar to Facebook or Gmail using node.js and socket.io. Can anyone assist me with this? Thanks in advance! Client.html <html> <head> <title>My Chat App</title> <d ...

How can I trigger a function when a user clicks on an object in a three.js scene?

After researching extensively on various platforms, I have found that many methods are losing their effectiveness with newer versions of three.js. Are there any built-in methods available to address this issue? If not, are there any libraries specifically ...

Using JavaScript to assign function arguments based on arbitrary object values

I am facing a challenge with a collection of arbitrary functions and a method that takes a function name along with an object or array of parameters to call the respective function. The issue arises from the varying number of inputs in these functions, som ...

Learn how to iterate over a JSON object using TypeScript in Angular5 to generate an array of objects

Here is a sample JSON code that includes an array "Customers" with objects and arrays nested inside: This is my JSON code snippet: { "Customers": [ { "customerData": { "secondLastName": "Apale", "firstLastName": "Lara", ...

Surprising outcome encountered while trying to insert an item into a list

I'm a bit puzzled by the current situation where: let groupdetails = { groupName: "", }; const groupsArray = []; groupdetails.groupName = 'A' groupsArray.push(groupdetails) groupdetails.groupName = 'B' groupsAr ...

A guide on dynamically showcasing/summoning icons in react by utilizing array data

QUESTION: 1 (SOLVED!) https://i.stack.imgur.com/1M1K7.png What is the best way to display icons based on an array of data codes? const data = [{ img: '01d' }, { img: '02d' }] if(data) { data.map((item) => ( <img src={`./ ...

Creating a clickable color-changing grid: A step-by-step guide

In a grid of size 12 by 12, each corner will be clickable, selecting a 6x3 cell area starting from the corner. The selected cells will change color upon clicking any of the 4 corners. After selecting one corner, the remaining cells (126 cells) will be che ...

Adding a MTL texture to an OBJ in your three.js project is a simple process that can enhance

Hello! I am currently working on adding an MTL file to my OBJ in three.js. I had successfully loaded my OBJ and went back to address this issue. However, after adding the code to load the MTL file using MTLLoader, the code seems to be getting stuck at mt ...

Get information collectively in node.js

How can I retrieve 10 records from a MongoDB collection using NodeJs, with each batch containing 10 records? ...

I am trying to locate the source of the unexpected token error

Hi there! I've encountered a syntax error in my code, specifically pointing to the closing curly bracket right above the render method. The error message indicates that it's expecting a comma, but all my curly brackets seem to have opening and cl ...

Utilize JavaScript and jQuery to locate a particular character within a string and move it one position back in the sequence

Can you locate a particular character within a string and move it to the position before? For instance: Consider the following string: Kù Iù Mù The desired output is: ùK ùI ùM ...

Switching the phone formatting from JavaScript to TypeScript

Below is the JavaScript code that I am attempting to convert to TypeScript: /** * @param {string} value The value to be formatted into a phone number * @returns {string} */ export const formatPhoneString = (value) => { const areaCode = value.substr(0 ...