Created
September 20, 2019 10:57
-
-
Save scriptify/80bcb8f4f3e878c5f064cc48dc905017 to your computer and use it in GitHub Desktop.
Calculates the area of a polygon in 3D space
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//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); | |
} | |
} |
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.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.