Code for surface area and volume calculation.
This commit is contained in:
parent
2343351279
commit
bdef08756a
@ -31,6 +31,7 @@
|
||||
<script type="text/javascript" src="../source/model/topology.js"></script>
|
||||
<script type="text/javascript" src="../source/model/modelutils.js"></script>
|
||||
<script type="text/javascript" src="../source/model/modelfinalization.js"></script>
|
||||
<script type="text/javascript" src="../source/model/quantities.js"></script>
|
||||
<script type="text/javascript" src="../source/import/importerutils.js"></script>
|
||||
<script type="text/javascript" src="../source/import/importerbase.js"></script>
|
||||
<script type="text/javascript" src="../source/import/importerobj.js"></script>
|
||||
|
||||
@ -32,6 +32,7 @@
|
||||
<script type="text/javascript" src="../source/model/topology.js"></script>
|
||||
<script type="text/javascript" src="../source/model/modelutils.js"></script>
|
||||
<script type="text/javascript" src="../source/model/modelfinalization.js"></script>
|
||||
<script type="text/javascript" src="../source/model/quantities.js"></script>
|
||||
<script type="text/javascript" src="../source/import/importerutils.js"></script>
|
||||
<script type="text/javascript" src="../source/import/importerbase.js"></script>
|
||||
<script type="text/javascript" src="../source/import/importerobj.js"></script>
|
||||
|
||||
@ -31,6 +31,7 @@
|
||||
<script type="text/javascript" src="../source/model/topology.js"></script>
|
||||
<script type="text/javascript" src="../source/model/modelutils.js"></script>
|
||||
<script type="text/javascript" src="../source/model/modelfinalization.js"></script>
|
||||
<script type="text/javascript" src="../source/model/quantities.js"></script>
|
||||
<script type="text/javascript" src="../source/import/importerutils.js"></script>
|
||||
<script type="text/javascript" src="../source/import/importerbase.js"></script>
|
||||
<script type="text/javascript" src="../source/import/importerobj.js"></script>
|
||||
|
||||
@ -31,6 +31,7 @@
|
||||
<script type="text/javascript" src="../source/model/topology.js"></script>
|
||||
<script type="text/javascript" src="../source/model/modelutils.js"></script>
|
||||
<script type="text/javascript" src="../source/model/modelfinalization.js"></script>
|
||||
<script type="text/javascript" src="../source/model/quantities.js"></script>
|
||||
<script type="text/javascript" src="../source/import/importerutils.js"></script>
|
||||
<script type="text/javascript" src="../source/import/importerbase.js"></script>
|
||||
<script type="text/javascript" src="../source/import/importerobj.js"></script>
|
||||
|
||||
@ -174,17 +174,22 @@ OV.EnumerateModelVerticesAndTriangles = function (model, callbacks)
|
||||
}
|
||||
};
|
||||
|
||||
OV.EnumerateMeshTriangles = function (mesh, onTriangle)
|
||||
{
|
||||
for (let triangleIndex = 0; triangleIndex < mesh.TriangleCount (); triangleIndex++) {
|
||||
let triangle = mesh.GetTriangle (triangleIndex);
|
||||
let v0 = mesh.GetVertex (triangle.v0);
|
||||
let v1 = mesh.GetVertex (triangle.v1);
|
||||
let v2 = mesh.GetVertex (triangle.v2);
|
||||
onTriangle (v0, v1, v2);
|
||||
}
|
||||
};
|
||||
|
||||
OV.EnumerateModelTriangles = function (model, onTriangle)
|
||||
{
|
||||
for (let meshIndex = 0; meshIndex < model.MeshCount (); meshIndex++) {
|
||||
let mesh = model.GetMesh (meshIndex);
|
||||
for (let triangleIndex = 0; triangleIndex < mesh.TriangleCount (); triangleIndex++) {
|
||||
let triangle = mesh.GetTriangle (triangleIndex);
|
||||
let v0 = mesh.GetVertex (triangle.v0);
|
||||
let v1 = mesh.GetVertex (triangle.v1);
|
||||
let v2 = mesh.GetVertex (triangle.v2);
|
||||
onTriangle (v0, v1, v2);
|
||||
}
|
||||
OV.EnumerateMeshTriangles (mesh, onTriangle);
|
||||
}
|
||||
};
|
||||
|
||||
@ -203,6 +208,7 @@ OV.EnumerateModelTrianglesWithNormals = function (model, onTriangle)
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
OV.GetMeshBoundingBox = function (mesh)
|
||||
{
|
||||
let calculator = new OV.BoundingBoxCalculator3D ();
|
||||
@ -238,7 +244,7 @@ OV.GetModelTopology = function (model)
|
||||
return index;
|
||||
}
|
||||
|
||||
let boundingBox = OV.GetModelBoundingBox (model);
|
||||
const boundingBox = OV.GetModelBoundingBox (model);
|
||||
let octree = new OV.Octree (boundingBox);
|
||||
let topology = new OV.Topology ();
|
||||
|
||||
@ -250,3 +256,15 @@ OV.GetModelTopology = function (model)
|
||||
});
|
||||
return topology;
|
||||
};
|
||||
|
||||
OV.IsModelSolid = function (model)
|
||||
{
|
||||
const topology = OV.GetModelTopology (model);
|
||||
for (let i = 0; i < topology.edges.length; i++) {
|
||||
const edge = topology.edges[i];
|
||||
if (edge.triangles.length !== 2) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
38
source/model/quantities.js
Normal file
38
source/model/quantities.js
Normal file
@ -0,0 +1,38 @@
|
||||
OV.GetTriangleArea = function (v0, v1, v2)
|
||||
{
|
||||
const a = OV.CoordDistance3D (v0, v1);
|
||||
const b = OV.CoordDistance3D (v1, v2);
|
||||
const c = OV.CoordDistance3D (v0, v2);
|
||||
const s = (a + b + c) / 2.0;
|
||||
const areaSquare = s * (s - a) * (s - b) * (s - c);
|
||||
if (areaSquare < 0.0) {
|
||||
return 0.0;
|
||||
}
|
||||
return Math.sqrt (areaSquare);
|
||||
};
|
||||
|
||||
OV.GetTriangleSignedVolume = function (v0, v1, v2)
|
||||
{
|
||||
return OV.DotVector3D (v0, OV.CrossVector3D (v1, v2)) / 6.0;
|
||||
};
|
||||
|
||||
OV.CalculateModelVolume = function (model)
|
||||
{
|
||||
if (!OV.IsModelSolid (model)) {
|
||||
return null;
|
||||
}
|
||||
let volume = 0.0;
|
||||
OV.EnumerateModelTriangles (model, function (v0, v1, v2) {
|
||||
volume += OV.GetTriangleSignedVolume (v0, v1, v2);
|
||||
});
|
||||
return volume;
|
||||
};
|
||||
|
||||
OV.CalculateModelSurfaceArea = function (model)
|
||||
{
|
||||
let surface = 0.0;
|
||||
OV.EnumerateModelTriangles (model, function (v0, v1, v2) {
|
||||
surface += OV.GetTriangleArea (v0, v1, v2);
|
||||
});
|
||||
return surface;
|
||||
};
|
||||
@ -114,39 +114,6 @@ describe ('Model Utils', function () {
|
||||
assert (OV.CoordIsEqual3D (mesh2Bounds.max, new OV.Coord3D (1.0, 1.0, 1.0)));
|
||||
});
|
||||
|
||||
it ('Mesh Volume Calculation', function () {
|
||||
function GetTriangleArea (v0, v1, v2)
|
||||
{
|
||||
let a = OV.CoordDistance3D (v0, v1);
|
||||
let b = OV.CoordDistance3D (v1, v2);
|
||||
let c = OV.CoordDistance3D (v0, v2);
|
||||
let s = (a + b + c) / 2.0;
|
||||
let areaSquare = s * (s - a) * (s - b) * (s - c);
|
||||
if (areaSquare < 0.0) {
|
||||
return 0.0;
|
||||
}
|
||||
return Math.sqrt (areaSquare);
|
||||
}
|
||||
|
||||
var model = testUtils.GetModelWithOneMesh (testUtils.GetCubeMesh ());
|
||||
let surface = 0.0;
|
||||
let volume = 0.0;
|
||||
for (let i = 0; i < model.MeshCount (); i++) {
|
||||
let mesh = model.GetMesh (i);
|
||||
for (j = 0; j < mesh.TriangleCount (); j++) {
|
||||
let triangle = mesh.GetTriangle (j);
|
||||
let v0 = mesh.GetVertex (triangle.v0);
|
||||
let v1 = mesh.GetVertex (triangle.v1);
|
||||
let v2 = mesh.GetVertex (triangle.v2);
|
||||
surface += GetTriangleArea (v0, v1, v2);
|
||||
let signedVolume = OV.DotVector3D (v0, OV.CrossVector3D (v1, v2)) / 6.0;
|
||||
volume += signedVolume;
|
||||
}
|
||||
}
|
||||
assert (OV.IsEqual (volume, 1.0));
|
||||
assert (OV.IsEqual (surface, 6.0));
|
||||
});
|
||||
|
||||
it ('Tetrahedron Topology Calculation', function () {
|
||||
let tetrahedron = testUtils.GetModelWithOneMesh (testUtils.GetTetrahedronMesh ());
|
||||
let topology = OV.GetModelTopology (tetrahedron);
|
||||
@ -195,5 +162,5 @@ describe ('Model Utils', function () {
|
||||
for (let i = 0; i < topology.edges.length; i++) {
|
||||
assert.strictEqual (topology.edges[i].triangles.length, 2);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
42
test/tests/quantities_test.js
Normal file
42
test/tests/quantities_test.js
Normal file
@ -0,0 +1,42 @@
|
||||
var assert = require ('assert');
|
||||
var testUtils = require ('../utils/testutils.js');
|
||||
|
||||
describe ('Quantities', function () {
|
||||
it ('Cube Volume Calculation', function () {
|
||||
const model = testUtils.GetModelWithOneMesh (testUtils.GetCubeMesh ());
|
||||
const volume = OV.CalculateModelVolume (model);
|
||||
assert (OV.IsEqual (volume, 1.0));
|
||||
});
|
||||
|
||||
it ('Cube with Missing Face Volume Calculation', function () {
|
||||
const model = testUtils.GetModelWithOneMesh (testUtils.GetCubeWithOneMissingFaceMesh ());
|
||||
const volume = OV.CalculateModelVolume (model);
|
||||
assert.strictEqual (volume, null);
|
||||
});
|
||||
|
||||
it ('Cube Surface Area Calculation', function () {
|
||||
const model = testUtils.GetModelWithOneMesh (testUtils.GetCubeMesh ());
|
||||
const surface = OV.CalculateModelSurfaceArea (model);
|
||||
assert (OV.IsEqual (surface, 6.0));
|
||||
});
|
||||
|
||||
it ('Cube with Missing Face Surface Area Calculation', function () {
|
||||
const model = testUtils.GetModelWithOneMesh (testUtils.GetCubeWithOneMissingFaceMesh ());
|
||||
const surface = OV.CalculateModelSurfaceArea (model);
|
||||
assert (OV.IsEqual (surface, 5.0));
|
||||
});
|
||||
|
||||
it ('Tetrahedron Volume Calculation', function () {
|
||||
let edgeLength = OV.CoordDistance3D (new OV.Coord3D (1.0, 1.0, 1.0), new OV.Coord3D (-1.0, -1.0, 1.0));
|
||||
const model = testUtils.GetModelWithOneMesh (testUtils.GetTetrahedronMesh ());
|
||||
const volume = OV.CalculateModelVolume (model);
|
||||
assert (OV.IsEqual (volume, Math.pow (edgeLength, 3.0) / (6.0 * Math.sqrt (2))));
|
||||
});
|
||||
|
||||
it ('Tetrahedron Surface Area Calculation', function () {
|
||||
let edgeLength = OV.CoordDistance3D (new OV.Coord3D (1.0, 1.0, 1.0), new OV.Coord3D (-1.0, -1.0, 1.0));
|
||||
const model = testUtils.GetModelWithOneMesh (testUtils.GetTetrahedronMesh ());
|
||||
const surface = OV.CalculateModelSurfaceArea (model);
|
||||
assert (OV.IsEqual (surface, Math.sqrt (3) * Math.pow (edgeLength, 2.0)));
|
||||
});
|
||||
});
|
||||
@ -163,6 +163,30 @@ module.exports =
|
||||
return cube;
|
||||
},
|
||||
|
||||
GetCubeWithOneMissingFaceMesh ()
|
||||
{
|
||||
var cube = new OV.Mesh ();
|
||||
cube.AddVertex (new OV.Coord3D (0.0, 0.0, 0.0));
|
||||
cube.AddVertex (new OV.Coord3D (1.0, 0.0, 0.0));
|
||||
cube.AddVertex (new OV.Coord3D (1.0, 1.0, 0.0));
|
||||
cube.AddVertex (new OV.Coord3D (0.0, 1.0, 0.0));
|
||||
cube.AddVertex (new OV.Coord3D (0.0, 0.0, 1.0));
|
||||
cube.AddVertex (new OV.Coord3D (1.0, 0.0, 1.0));
|
||||
cube.AddVertex (new OV.Coord3D (1.0, 1.0, 1.0));
|
||||
cube.AddVertex (new OV.Coord3D (0.0, 1.0, 1.0));
|
||||
cube.AddTriangle (new OV.Triangle (0, 1, 5));
|
||||
cube.AddTriangle (new OV.Triangle (0, 5, 4));
|
||||
cube.AddTriangle (new OV.Triangle (1, 2, 6));
|
||||
cube.AddTriangle (new OV.Triangle (1, 6, 5));
|
||||
cube.AddTriangle (new OV.Triangle (2, 3, 7));
|
||||
cube.AddTriangle (new OV.Triangle (2, 7, 6));
|
||||
cube.AddTriangle (new OV.Triangle (3, 0, 4));
|
||||
cube.AddTriangle (new OV.Triangle (3, 4, 7));
|
||||
cube.AddTriangle (new OV.Triangle (0, 3, 2));
|
||||
cube.AddTriangle (new OV.Triangle (0, 2, 1));
|
||||
return cube;
|
||||
},
|
||||
|
||||
GetTetrahedronMesh ()
|
||||
{
|
||||
var tetrahedron = new OV.Mesh ();
|
||||
|
||||
@ -27,6 +27,7 @@
|
||||
"source/model/topology.js",
|
||||
"source/model/modelutils.js",
|
||||
"source/model/modelfinalization.js",
|
||||
"source/model/quantities.js",
|
||||
"source/import/importerutils.js",
|
||||
"source/import/importerbase.js",
|
||||
"source/import/importerobj.js",
|
||||
|
||||
@ -40,6 +40,7 @@
|
||||
<script type="text/javascript" src="../source/model/topology.js"></script>
|
||||
<script type="text/javascript" src="../source/model/modelutils.js"></script>
|
||||
<script type="text/javascript" src="../source/model/modelfinalization.js"></script>
|
||||
<script type="text/javascript" src="../source/model/quantities.js"></script>
|
||||
<script type="text/javascript" src="../source/import/importerutils.js"></script>
|
||||
<script type="text/javascript" src="../source/import/importerbase.js"></script>
|
||||
<script type="text/javascript" src="../source/import/importerobj.js"></script>
|
||||
|
||||
@ -40,6 +40,7 @@
|
||||
<script type="text/javascript" src="../source/model/topology.js"></script>
|
||||
<script type="text/javascript" src="../source/model/modelutils.js"></script>
|
||||
<script type="text/javascript" src="../source/model/modelfinalization.js"></script>
|
||||
<script type="text/javascript" src="../source/model/quantities.js"></script>
|
||||
<script type="text/javascript" src="../source/import/importerutils.js"></script>
|
||||
<script type="text/javascript" src="../source/import/importerbase.js"></script>
|
||||
<script type="text/javascript" src="../source/import/importerobj.js"></script>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user