From bdef08756a726bbbec99061f475431866ce40429 Mon Sep 17 00:00:00 2001 From: Viktor Kovacs Date: Mon, 17 May 2021 16:05:52 +0200 Subject: [PATCH] Code for surface area and volume calculation. --- sandbox/embed_selfhost_fullscreen.html | 1 + sandbox/embed_selfhost_multiple.html | 1 + sandbox/embed_selfhost_single.html | 1 + sandbox/embed_selfhost_single_scroll.html | 1 + source/model/modelutils.js | 34 +++++++++++++----- source/model/quantities.js | 38 ++++++++++++++++++++ test/tests/modelutils_test.js | 35 +------------------ test/tests/quantities_test.js | 42 +++++++++++++++++++++++ test/utils/testutils.js | 24 +++++++++++++ tools/config.json | 1 + website/embed.html | 1 + website/index.html | 1 + 12 files changed, 138 insertions(+), 42 deletions(-) create mode 100644 source/model/quantities.js create mode 100644 test/tests/quantities_test.js diff --git a/sandbox/embed_selfhost_fullscreen.html b/sandbox/embed_selfhost_fullscreen.html index 9523c96..9dc03bb 100644 --- a/sandbox/embed_selfhost_fullscreen.html +++ b/sandbox/embed_selfhost_fullscreen.html @@ -31,6 +31,7 @@ + diff --git a/sandbox/embed_selfhost_multiple.html b/sandbox/embed_selfhost_multiple.html index 8c17a7e..2ea6dfc 100644 --- a/sandbox/embed_selfhost_multiple.html +++ b/sandbox/embed_selfhost_multiple.html @@ -32,6 +32,7 @@ + diff --git a/sandbox/embed_selfhost_single.html b/sandbox/embed_selfhost_single.html index 305cc9d..f7fd6d8 100644 --- a/sandbox/embed_selfhost_single.html +++ b/sandbox/embed_selfhost_single.html @@ -31,6 +31,7 @@ + diff --git a/sandbox/embed_selfhost_single_scroll.html b/sandbox/embed_selfhost_single_scroll.html index 915c37e..55bbb66 100644 --- a/sandbox/embed_selfhost_single_scroll.html +++ b/sandbox/embed_selfhost_single_scroll.html @@ -31,6 +31,7 @@ + diff --git a/source/model/modelutils.js b/source/model/modelutils.js index ade114f..de3b5af 100644 --- a/source/model/modelutils.js +++ b/source/model/modelutils.js @@ -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; +}; diff --git a/source/model/quantities.js b/source/model/quantities.js new file mode 100644 index 0000000..78e938f --- /dev/null +++ b/source/model/quantities.js @@ -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; +}; diff --git a/test/tests/modelutils_test.js b/test/tests/modelutils_test.js index 563dcbd..54d47de 100644 --- a/test/tests/modelutils_test.js +++ b/test/tests/modelutils_test.js @@ -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); } - }); + }); }); diff --git a/test/tests/quantities_test.js b/test/tests/quantities_test.js new file mode 100644 index 0000000..537bf81 --- /dev/null +++ b/test/tests/quantities_test.js @@ -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))); + }); +}); diff --git a/test/utils/testutils.js b/test/utils/testutils.js index 8d247aa..6ffcd62 100644 --- a/test/utils/testutils.js +++ b/test/utils/testutils.js @@ -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 (); diff --git a/tools/config.json b/tools/config.json index d44a042..368d2b6 100644 --- a/tools/config.json +++ b/tools/config.json @@ -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", diff --git a/website/embed.html b/website/embed.html index ee3aabc..2c2a928 100644 --- a/website/embed.html +++ b/website/embed.html @@ -40,6 +40,7 @@ + diff --git a/website/index.html b/website/index.html index b3d3b8c..ee66f05 100644 --- a/website/index.html +++ b/website/index.html @@ -40,6 +40,7 @@ +