I am trying to calulate the area of a plane of 3d object (.stl mesh object) n
in three.js. By selecting it with a mouse click.
For example this area:
We know that all ‘triangles’ that make up the surface of the plane (since it is an .stl) are attached at the same angle, if the angle changes in comparison to the last triangle, we know that this triangle is not part of the plane anymore.
So knowing this is a property of the surface we are trying to calulate, we can use this in combination with some form of three.js Raycaster to select and calculate an area (by adding all the area’s of the triangles with the correct properties together).
For now, we don’t need to worry about the size of the selected surface (for example trying to find a ‘plane’ on a curved surface wouldn’t be valid, but we do not need to worry about that now)
How would I go about trying to find the area and plane in three.js. How should I set up the raycaster. Or more specifically, how do I start reading the .stl format’s ‘triangles’.
Minimal working example of my current code (with working .stl file included), it can be run using a simple live server, for example in VS Code using Ritwick Dey’s plugin, no extra plugins/libraries needed, since it’s ‘normal’ HTML/JS.
The only requirement is that we select the point we are trying to calculate in three.js and give the area (selected triangles) a different colour, in three.js, when they are selected. Any other calculations needed could be done in some kind of backend (Python, Node.js or anything else really), but I see no obvious way of transporting such complicated data between programs.
My minimal reproduction code, see my abovementioned github link for the .stl file used in my picture:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Stackoverflow Example</title>
<link rel="stylesheet" type="text/css" href="../style/render.css">
</head>
<body>
<script src="https://rawcdn.githack.com/mrdoob/three.js/r117/build/three.min.js"></script>
<script src="https://rawcdn.githack.com/mrdoob/three.js/r117/examples/js/loaders/STLLoader.js"></script>
<script src="https://rawcdn.githack.com/mrdoob/three.js/r117/examples/js/controls/OrbitControls.js"></script>
<script>
function init() {
// Setup some basic stuff
scene = new THREE.Scene();
scene.background = new THREE.Color(0xdddddd);
// Setup Camera
camera = new THREE.PerspectiveCamera(40, window.innerWidth / window.innerHeight, 1, 5000);
// Setup renerer and add to page
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
window.addEventListener('resize', onWindowResize, false);
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
// Setup Camera Position
camera.rotation.y = 45 / 180 * Math.PI;
camera.position.x = 800;
camera.position.y = 100;
camera.position.z = 1000;
// Add Camera Control through orbit.js
let controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.addEventListener('change', renderer);
// Add some basic ambient lighting (Does light all parts equally and does not cast shadows)
hlight = new THREE.AmbientLight(0x404040, 20);
scene.add(hlight);
//Add some point lights to simulate real lights
light = new THREE.PointLight(0xc4c4c4, 1, 10000);
light.position.set(0, 300, 500);
scene.add(light);
light2 = new THREE.PointLight(0xc4c4c4, 1, 10000);
light2.position.set(500, 100, 0);
scene.add(light2);
light3 = new THREE.PointLight(0xc4c4c4, 1, 10000);
light3.position.set(0, 100, -500);
scene.add(light3);
light4 = new THREE.PointLight(0xc4c4c4, 1, 10000);
light4.position.set(-500, 300, 0);
scene.add(light4);
controls.update();
// Animation Script
function animate() {
renderer.render(scene, camera);
requestAnimationFrame(animate);
}
// Setup GLTF Loader and load in obj
let loader = new THREE.STLLoader();
loader.load('example.stl', function (geometry) {
// console.log(gltf);
var material = new THREE.MeshPhongMaterial({
color: 0x171717,
shininess: 200
});
var mesh = new THREE.Mesh(geometry, material);
mesh.castShadow = true;
mesh.receiveShadow = true;
mesh.position.set(0, 0, 0);
scene.add(mesh);
renderer.render(scene, camera)
animate();
});
}
// Call method for starting init
init();
</script>
</body>
</html>
EDIT:
Example of my intended output, but in Fusion 360 instead of three.js (Note, the original file is a .stl but since three.js doesn’t allow for part viewing, it is converted to .stl in the backend)
Example of the ‘triangles’ in a .stl file
P.S. I am referring to the surface I want to calculate as ‘planes’ I know this isn’t the correct term in three.js, but I have been using the word plane for lack of a better term.