-
-
Save scriptify/80bcb8f4f3e878c5f064cc48dc905017 to your computer and use it in GitHub Desktop.
//determinant of matrix a | |
function det(a) { | |
return ( | |
a[0][0] * a[1][1] * a[2][2] + | |
a[0][1] * a[1][2] * a[2][0] + | |
a[0][2] * a[1][0] * a[2][1] - | |
a[0][2] * a[1][1] * a[2][0] - | |
a[0][1] * a[1][0] * a[2][2] - | |
a[0][0] * a[1][2] * a[2][1] | |
); | |
} | |
//unit normal vector of plane defined by points a, b, and c | |
function unit_normal(a, b, c) { | |
let x = det([[1, a[1], a[2]], [1, b[1], b[2]], [1, c[1], c[2]]]); | |
let y = det([[a[0], 1, a[2]], [b[0], 1, b[2]], [c[0], 1, c[2]]]); | |
let z = det([[a[0], a[1], 1], [b[0], b[1], 1], [c[0], c[1], 1]]); | |
let magnitude = Math.pow( | |
Math.pow(x, 2) + Math.pow(y, 2) + Math.pow(z, 2), | |
0.5 | |
); | |
return [x / magnitude, y / magnitude, z / magnitude]; | |
} | |
// dot product of vectors a and b | |
function dot(a, b) { | |
return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; | |
} | |
// cross product of vectors a and b | |
function cross(a, b) { | |
let x = a[1] * b[2] - a[2] * b[1]; | |
let y = a[2] * b[0] - a[0] * b[2]; | |
let z = a[0] * b[1] - a[1] * b[0]; | |
return [x, y, z]; | |
} | |
// area of polygon poly | |
export default function calculatePolygonArea(poly) { | |
if (poly.length < 3) { | |
console.log("not a plane - no area"); | |
return 0; | |
} else { | |
let total = [0, 0, 0]; | |
for (let i = 0; i < poly.length; i++) { | |
var vi1 = poly[i]; | |
if (i === poly.length - 1) { | |
var vi2 = poly[0]; | |
} else { | |
var vi2 = poly[i + 1]; | |
} | |
let prod = cross(vi1, vi2); | |
total[0] = total[0] + prod[0]; | |
total[1] = total[1] + prod[1]; | |
total[2] = total[2] + prod[2]; | |
} | |
let result = dot(total, unit_normal(poly[0], poly[1], poly[2])); | |
return Math.abs(result / 2); | |
} | |
} |
Hello,
do you need a 2D or 3D area measurement? Because our team and me observed that this algorithm didn't really work as expected in 3D space. For that to work, you first need to create a 3D mesh of all points and then calculate the real surface. For that purpose, I created a WASM port of powercrust. This is still very experimental though.
Hi,
I want to measure a the spaces and areas of rooftops. Due to the different angles roofs can have, the area measurement in potree does not fit. If I am understanding correctly, the area is calculated only from x and y coordinates in potree?
Isn't it possible to calculate the right area for 3 points in x,y,z very easily? This wouldn't be as convenient as a complete polygon, but it would be a useful start.
I have thought about it furthermore... Isn't It possible to define an vector plane with the first 3 points and then project the other points on this plane (if the points aren't too far away, of course). Then the calculation would be the same as in the x,y plane like potree already do. Mathematically is this not a big problem, but I don't know how to implement this into potree.
And if I understood your code correctly you have already implemented the calculation of the area of the triangle of 3 points.
Maybe you could help me to get the code running in potree, this would be a starting point for me to implement a calculation of more than 3 points, if they are near the first vectore plane.
This seems to work pretty well, too. https://math.stackexchange.com/questions/3207981/caculate-area-of-polygon-in-3d
Calculated polygons in excel with this formula. If the points aren't to far away from the plane this should work pretty well.
Hello Maximilian Torggler,
I recently stumbled over the area measurement problem in the Potree Desktop Viewer. I'm not very firm in Javascript development, but I want to use your improvement to get the right area measurements. Can you please tell me how to change/add these calculation?
Thank you very much,have a nice weekend and greetingz.
Dominik