Last active
December 18, 2019 13:52
-
-
Save juliendargelos/efa54269f81439cbfe11a49f94de6f0a to your computer and use it in GitHub Desktop.
Utils for computing three geometries volume
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
export function computeVolume(geometry) { | |
return isBufferGeometry(geometry) | |
? computeBufferGeometryVolume(geometry) | |
: computeGeometryVolume(geometry) | |
} | |
export function computeBufferGeometryVolume(geometry) { | |
return geometry.index | |
? computeIndexedBufferGeometryVolume(geometry) | |
: computeNotIndexedBufferGeometryVolume(geometry) | |
} | |
export function computeGeometryVolume(geometry) { | |
return geometry.faces.length | |
? computeIndexedGeometryVolume(geometry) | |
: computeNotIndexedGeometryVolume(geometry) | |
} | |
export function computeIndexedGeometryVolume(geometry) { | |
const vertices = geometry.vertices | |
let p1, p2, p3 | |
return Math.abs(geometry.faces.reduce((sum, { a, b, c }) => { | |
p1 = vertices[a] | |
p2 = vertices[b] | |
p3 = vertices[c] | |
return sum + computeTriangleSignedVolume( | |
p1.x, p1.y, p1.z, | |
p2.x, p2.y, p2.z, | |
p3.x, p3.y, p3.z | |
) | |
}, 0)) | |
} | |
export function computeNotIndexedGeometryVolume(geometry) { | |
const vertices = geometry.vertices | |
const length = vertices.length | |
let sum = 0 | |
let p1, p2, p3 | |
for (var i = 0; i < length; i += 3) { | |
p1 = vertices[i] | |
p2 = vertices[i + 1] | |
p3 = vertices[i + 2] | |
sum += computeTriangleSignedVolume( | |
p1.x, p1.y, p1.z, | |
p2.x, p2.y, p2.z, | |
p3.x, p3.y, p3.z | |
) | |
} | |
return Math.abs(sum) | |
} | |
export function computeIndexedBufferGeometryVolume(geometry) { | |
const vertices = geometry.attributes.position.array | |
const indices = geometry.index.array | |
const length = indices.length | |
let sum = 0 | |
let a, b, c | |
for (var i = 0; i < length; i += 3) { | |
a = indices[i] * 3 | |
b = indices[i + 1] * 3 | |
c = indices[i + 2] * 3 | |
sum += computeTriangleSignedVolume( | |
vertices[a], vertices[a + 1], vertices[a + 2], | |
vertices[b], vertices[b + 1], vertices[b + 2], | |
vertices[c], vertices[c + 1], vertices[c + 2] | |
) | |
} | |
return Math.abs(sum) | |
} | |
export function computeNotIndexedBufferGeometryVolume(geometry) { | |
const vertices = geometry.attributes.position.array | |
const length = vertices.length | |
let sum = 0 | |
for (var index = 0; index < length; index += 9) { | |
sum += computeTriangleSignedVolume( | |
vertices[index ], vertices[index + 1], vertices[index + 3], | |
vertices[index + 4], vertices[index + 5], vertices[index + 6], | |
vertices[index + 7], vertices[index + 8], vertices[index + 9] | |
) | |
} | |
return Math.abs(sum) | |
} | |
export function isBufferGeometry(geometry) { | |
return geometry.isBufferGeometry | |
} | |
function computeTriangleSignedVolume(x1, y1, z1, x2, y2, z2, x3, y3, z3) { | |
const v321 = x3 * y2 * z1 | |
const v231 = x2 * y3 * z1 | |
const v312 = x3 * y1 * z2 | |
const v132 = x1 * y3 * z2 | |
const v213 = x2 * y1 * z3 | |
const v123 = x1 * y2 * z3 | |
return (-v321 + v231 + v312 - v132 - v213 + v123) / 6 | |
} |
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
import { Geometry, BufferGeometry, Vector3 } from 'three' | |
export function computeVolume(geometry: Geometry | BufferGeometry): number { | |
return isBufferGeometry(geometry) | |
? computeBufferGeometryVolume(geometry) | |
: computeGeometryVolume(geometry) | |
} | |
export function computeBufferGeometryVolume(geometry: BufferGeometry): number { | |
return geometry.index | |
? computeIndexedBufferGeometryVolume(geometry) | |
: computeNotIndexedBufferGeometryVolume(geometry) | |
} | |
export function computeGeometryVolume(geometry: Geometry): number { | |
return geometry.faces.length | |
? computeIndexedGeometryVolume(geometry) | |
: computeNotIndexedGeometryVolume(geometry) | |
} | |
export function computeIndexedGeometryVolume(geometry: Geometry): number { | |
const vertices = geometry.vertices | |
let p1: Vector3 | |
let p2: Vector3 | |
let p3: Vector3 | |
return Math.abs(geometry.faces.reduce((sum, { a, b, c }) => { | |
p1 = vertices[a] | |
p2 = vertices[b] | |
p3 = vertices[c] | |
return sum + computeTriangleSignedVolume( | |
p1.x, p1.y, p1.z, | |
p2.x, p2.y, p2.z, | |
p3.x, p3.y, p3.z | |
) | |
}, 0)) | |
} | |
export function computeNotIndexedGeometryVolume(geometry: Geometry): number { | |
const vertices = geometry.vertices | |
const length = vertices.length | |
let sum = 0 | |
let p1: Vector3 | |
let p2: Vector3 | |
let p3: Vector3 | |
for (var i = 0; i < length; i += 3) { | |
p1 = vertices[i] | |
p2 = vertices[i + 1] | |
p3 = vertices[i + 2] | |
sum += computeTriangleSignedVolume( | |
p1.x, p1.y, p1.z, | |
p2.x, p2.y, p2.z, | |
p3.x, p3.y, p3.z | |
) | |
} | |
return Math.abs(sum) | |
} | |
export function computeIndexedBufferGeometryVolume( | |
geometry: BufferGeometry | |
): number { | |
const vertices = geometry.attributes.position.array | |
const indices = geometry.index.array | |
const length = indices.length | |
let sum = 0 | |
let a: number | |
let b: number | |
let c: number | |
for (var i = 0; i < length; i += 3) { | |
a = indices[i] * 3 | |
b = indices[i + 1] * 3 | |
c = indices[i + 2] * 3 | |
sum += computeTriangleSignedVolume( | |
vertices[a], vertices[a + 1], vertices[a + 2], | |
vertices[b], vertices[b + 1], vertices[b + 2], | |
vertices[c], vertices[c + 1], vertices[c + 2] | |
) | |
} | |
return Math.abs(sum) | |
} | |
export function computeNotIndexedBufferGeometryVolume( | |
geometry: BufferGeometry | |
): number { | |
const vertices = geometry.attributes.position.array | |
const length = vertices.length | |
let sum = 0 | |
for (var index = 0; index < length; index += 9) { | |
sum += computeTriangleSignedVolume( | |
vertices[index ], vertices[index + 1], vertices[index + 3], | |
vertices[index + 4], vertices[index + 5], vertices[index + 6], | |
vertices[index + 7], vertices[index + 8], vertices[index + 9], | |
) | |
} | |
return Math.abs(sum) | |
} | |
export function isBufferGeometry( | |
geometry: Geometry | BufferGeometry | |
): geometry is BufferGeometry { | |
return (geometry as BufferGeometry).isBufferGeometry | |
} | |
function computeTriangleSignedVolume( | |
x1: number, y1: number, z1: number, | |
x2: number, y2: number, z2: number, | |
x3: number, y3: number, z3: number | |
): number { | |
const v321 = x3 * y2 * z1 | |
const v231 = x2 * y3 * z1 | |
const v312 = x3 * y1 * z2 | |
const v132 = x1 * y3 * z2 | |
const v213 = x2 * y1 * z3 | |
const v123 = x1 * y2 * z3 | |
return (-v321 + v231 + v312 - v132 - v213 + v123) / 6 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Implementation based on Frank Krueger's Stack Overflow answer.
See Efficient feature extraction for 2D/3D objects in mesh representation by Cha Zhang and Tsuhan Chen.