Add base enumerator class so meshes and models can be handled in the same way for calculations.

This commit is contained in:
Viktor Kovacs 2021-05-20 10:07:37 +02:00
parent e05d6c7fdb
commit a39de09715
11 changed files with 229 additions and 97 deletions

View File

@ -29,6 +29,7 @@
<script type="text/javascript" src="../source/model/meshbuffer.js"></script>
<script type="text/javascript" src="../source/model/model.js"></script>
<script type="text/javascript" src="../source/model/topology.js"></script>
<script type="text/javascript" src="../source/model/enumerator.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>

View File

@ -30,6 +30,7 @@
<script type="text/javascript" src="../source/model/meshbuffer.js"></script>
<script type="text/javascript" src="../source/model/model.js"></script>
<script type="text/javascript" src="../source/model/topology.js"></script>
<script type="text/javascript" src="../source/model/enumerator.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>

View File

@ -29,6 +29,7 @@
<script type="text/javascript" src="../source/model/meshbuffer.js"></script>
<script type="text/javascript" src="../source/model/model.js"></script>
<script type="text/javascript" src="../source/model/topology.js"></script>
<script type="text/javascript" src="../source/model/enumerator.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>

View File

@ -29,6 +29,7 @@
<script type="text/javascript" src="../source/model/meshbuffer.js"></script>
<script type="text/javascript" src="../source/model/model.js"></script>
<script type="text/javascript" src="../source/model/topology.js"></script>
<script type="text/javascript" src="../source/model/enumerator.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>

100
source/model/enumerator.js Normal file
View File

@ -0,0 +1,100 @@
OV.Enumerator = class
{
constructor ()
{
}
EnumerateVertices (onVertex)
{
}
EnumerateTriangles (onTriangle)
{
}
};
OV.MeshEnumerator = class extends OV.Enumerator
{
constructor (mesh)
{
super ();
this.mesh = mesh;
}
EnumerateVertices (onVertex)
{
for (let vertexIndex = 0; vertexIndex < this.mesh.VertexCount (); vertexIndex++) {
let vertex = this.mesh.GetVertex (vertexIndex);
onVertex (vertex);
}
}
EnumerateTriangles (onTriangle)
{
for (let triangleIndex = 0; triangleIndex < this.mesh.TriangleCount (); triangleIndex++) {
let triangle = this.mesh.GetTriangle (triangleIndex);
let v0 = this.mesh.GetVertex (triangle.v0);
let v1 = this.mesh.GetVertex (triangle.v1);
let v2 = this.mesh.GetVertex (triangle.v2);
onTriangle (v0, v1, v2);
}
}
};
OV.MeshEnumerator = class extends OV.Enumerator
{
constructor (mesh)
{
super ();
this.mesh = mesh;
}
EnumerateVertices (onVertex)
{
for (let vertexIndex = 0; vertexIndex < this.mesh.VertexCount (); vertexIndex++) {
let vertex = this.mesh.GetVertex (vertexIndex);
onVertex (vertex);
}
}
EnumerateTriangles (onTriangle)
{
for (let triangleIndex = 0; triangleIndex < this.mesh.TriangleCount (); triangleIndex++) {
let triangle = this.mesh.GetTriangle (triangleIndex);
let v0 = this.mesh.GetVertex (triangle.v0);
let v1 = this.mesh.GetVertex (triangle.v1);
let v2 = this.mesh.GetVertex (triangle.v2);
onTriangle (v0, v1, v2);
}
}
};
OV.ModelEnumerator = class extends OV.Enumerator
{
constructor (model)
{
super ();
this.model = model;
}
EnumerateVertices (onVertex)
{
for (let meshIndex = 0; meshIndex < this.model.MeshCount (); meshIndex++) {
let mesh = this.model.GetMesh (meshIndex);
let enumerator = new OV.MeshEnumerator (mesh);
enumerator.EnumerateVertices (onVertex);
}
}
EnumerateTriangles (onTriangle)
{
for (let meshIndex = 0; meshIndex < this.model.MeshCount (); meshIndex++) {
let mesh = this.model.GetMesh (meshIndex);
let enumerator = new OV.MeshEnumerator (mesh);
enumerator.EnumerateTriangles (onTriangle);
}
}
};

View File

@ -174,65 +174,37 @@ 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);
OV.EnumerateMeshTriangles (mesh, onTriangle);
}
};
OV.EnumerateModelTrianglesWithNormals = 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);
let enumerator = new OV.ModelEnumerator (model);
enumerator.EnumerateTriangles (function (v0, v1, v2) {
let normal = OV.CalculateTriangleNormal (v0, v1, v2);
onTriangle (v0, v1, v2, normal);
}
}
});
};
OV.GetBoundingBox = function (enumerator)
{
let calculator = new OV.BoundingBoxCalculator3D ();
enumerator.EnumerateVertices (function (vertex) {
calculator.AddPoint (vertex);
});
return calculator.GetBox ();
};
OV.GetMeshBoundingBox = function (mesh)
{
let calculator = new OV.BoundingBoxCalculator3D ();
for (let i = 0; i < mesh.VertexCount (); i++) {
let vertex = mesh.GetVertex (i);
calculator.AddPoint (vertex);
}
return calculator.GetBox ();
let enumerator = new OV.MeshEnumerator (mesh);
return OV.GetBoundingBox (enumerator);
};
OV.GetModelBoundingBox = function (model)
{
let calculator = new OV.BoundingBoxCalculator3D ();
for (let i = 0; i < model.MeshCount (); i++) {
let mesh = model.GetMesh (i);
for (let j = 0; j < mesh.VertexCount (); j++) {
let vertex = mesh.GetVertex (j);
calculator.AddPoint (vertex);
}
}
return calculator.GetBox ();
let enumerator = new OV.ModelEnumerator (model);
return OV.GetBoundingBox (enumerator);
};
OV.GetModelTopology = function (model)
OV.GetTopology = function (enumerator)
{
function GetVertexIndex (vertex, octree, topology)
{
@ -244,11 +216,11 @@ OV.GetModelTopology = function (model)
return index;
}
const boundingBox = OV.GetModelBoundingBox (model);
let boundingBox = OV.GetBoundingBox (enumerator);
let octree = new OV.Octree (boundingBox);
let topology = new OV.Topology ();
OV.EnumerateModelTriangles (model, function (v0, v1, v2) {
enumerator.EnumerateTriangles (function (v0, v1, v2) {
let v0Index = GetVertexIndex (v0, octree, topology);
let v1Index = GetVertexIndex (v1, octree, topology);
let v2Index = GetVertexIndex (v2, octree, topology);
@ -257,7 +229,19 @@ OV.GetModelTopology = function (model)
return topology;
};
OV.IsModelSolid = function (model)
OV.GetMeshTopology = function (mesh)
{
let enumerator = new OV.MeshEnumerator (mesh);
return OV.GetTopology (enumerator);
};
OV.GetModelTopology = function (model)
{
let enumerator = new OV.ModelEnumerator (model);
return OV.GetTopology (enumerator);
};
OV.IsSolid = function (enumerator)
{
function GetEdgeOrientationInTriangle (topology, triangleIndex, edgeIndex)
{
@ -277,7 +261,7 @@ OV.IsModelSolid = function (model)
return null;
}
const topology = OV.GetModelTopology (model);
const topology = OV.GetTopology (enumerator);
for (let edgeIndex = 0; edgeIndex < topology.edges.length; edgeIndex++) {
const edge = topology.edges[edgeIndex];
if (edge.triangles.length !== 2) {
@ -291,3 +275,15 @@ OV.IsModelSolid = function (model)
}
return true;
};
OV.IsMeshSolid = function (mesh)
{
let enumerator = new OV.MeshEnumerator (mesh);
return OV.IsSolid (enumerator);
};
OV.IsModelSolid = function (model)
{
let enumerator = new OV.ModelEnumerator (model);
return OV.IsSolid (enumerator);
};

View File

@ -16,23 +16,47 @@ OV.GetTetrahedronSignedVolume = function (v0, v1, v2)
return OV.DotVector3D (v0, OV.CrossVector3D (v1, v2)) / 6.0;
};
OV.CalculateModelVolume = function (model)
OV.CalculateVolume = function (enumerator)
{
if (!OV.IsModelSolid (model)) {
if (!OV.IsSolid (enumerator)) {
return null;
}
let volume = 0.0;
OV.EnumerateModelTriangles (model, function (v0, v1, v2) {
enumerator.EnumerateTriangles (function (v0, v1, v2) {
volume += OV.GetTetrahedronSignedVolume (v0, v1, v2);
});
return volume;
};
OV.CalculateModelSurfaceArea = function (model)
OV.CalculateMeshVolume = function (mesh)
{
let enumerator = new OV.MeshEnumerator (mesh);
return OV.CalculateVolume (enumerator);
};
OV.CalculateModelVolume = function (model)
{
let enumerator = new OV.ModelEnumerator (model);
return OV.CalculateVolume (enumerator);
};
OV.CalculateSurfaceArea = function (enumerator)
{
let surface = 0.0;
OV.EnumerateModelTriangles (model, function (v0, v1, v2) {
enumerator.EnumerateTriangles (function (v0, v1, v2) {
surface += OV.GetTriangleArea (v0, v1, v2);
});
return surface;
};
OV.CalculateMeshSurfaceArea = function (mesh)
{
let enumerator = new OV.MeshEnumerator (mesh);
return OV.CalculateSurfaceArea (enumerator);
};
OV.CalculateModelSurfaceArea = function (model)
{
let enumerator = new OV.ModelEnumerator (model);
return OV.CalculateSurfaceArea (enumerator);
};

View File

@ -3,67 +3,72 @@ 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));
const mesh = testUtils.GetCubeMesh ();
const model = testUtils.GetModelWithOneMesh (mesh);
assert (OV.IsEqual (OV.CalculateMeshVolume (mesh), 1.0));
assert (OV.IsEqual (OV.CalculateModelVolume (model), 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);
const mesh = testUtils.GetCubeWithOneMissingFaceMesh ();
const model = testUtils.GetModelWithOneMesh (mesh);
assert.strictEqual (OV.CalculateModelVolume (model), null);
});
it ('Cube with Wrongly Oriented Triangle Volume Calculation', function () {
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));
cube.AddTriangle (new OV.Triangle (4, 5, 6));
cube.AddTriangle (new OV.Triangle (4, 7, 6));
const model = testUtils.GetModelWithOneMesh (cube);
const volume = OV.CalculateModelVolume (model);
assert.strictEqual (volume, null);
var mesh = new OV.Mesh ();
mesh.AddVertex (new OV.Coord3D (0.0, 0.0, 0.0));
mesh.AddVertex (new OV.Coord3D (1.0, 0.0, 0.0));
mesh.AddVertex (new OV.Coord3D (1.0, 1.0, 0.0));
mesh.AddVertex (new OV.Coord3D (0.0, 1.0, 0.0));
mesh.AddVertex (new OV.Coord3D (0.0, 0.0, 1.0));
mesh.AddVertex (new OV.Coord3D (1.0, 0.0, 1.0));
mesh.AddVertex (new OV.Coord3D (1.0, 1.0, 1.0));
mesh.AddVertex (new OV.Coord3D (0.0, 1.0, 1.0));
mesh.AddTriangle (new OV.Triangle (0, 1, 5));
mesh.AddTriangle (new OV.Triangle (0, 5, 4));
mesh.AddTriangle (new OV.Triangle (1, 2, 6));
mesh.AddTriangle (new OV.Triangle (1, 6, 5));
mesh.AddTriangle (new OV.Triangle (2, 3, 7));
mesh.AddTriangle (new OV.Triangle (2, 7, 6));
mesh.AddTriangle (new OV.Triangle (3, 0, 4));
mesh.AddTriangle (new OV.Triangle (3, 4, 7));
mesh.AddTriangle (new OV.Triangle (0, 3, 2));
mesh.AddTriangle (new OV.Triangle (0, 2, 1));
mesh.AddTriangle (new OV.Triangle (4, 5, 6));
mesh.AddTriangle (new OV.Triangle (4, 7, 6));
const model = testUtils.GetModelWithOneMesh (mesh);
assert.strictEqual (OV.CalculateMeshVolume (mesh), null);
assert.strictEqual (OV.CalculateModelVolume (model), null);
});
it ('Cube Surface Area Calculation', function () {
const model = testUtils.GetModelWithOneMesh (testUtils.GetCubeMesh ());
const surface = OV.CalculateModelSurfaceArea (model);
assert (OV.IsEqual (surface, 6.0));
const mesh = testUtils.GetCubeMesh ();
const model = testUtils.GetModelWithOneMesh (mesh);
assert (OV.IsEqual (OV.CalculateMeshSurfaceArea (mesh), 6.0));
assert (OV.IsEqual (OV.CalculateModelSurfaceArea (model), 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));
const mesh = testUtils.GetCubeWithOneMissingFaceMesh ();
const model = testUtils.GetModelWithOneMesh (mesh);
assert (OV.IsEqual (OV.CalculateMeshSurfaceArea (mesh), 5.0));
assert (OV.IsEqual (OV.CalculateModelSurfaceArea (model), 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))));
const mesh = testUtils.GetTetrahedronMesh ();
const model = testUtils.GetModelWithOneMesh (mesh);
assert (OV.IsEqual (OV.CalculateMeshVolume (mesh), Math.pow (edgeLength, 3.0) / (6.0 * Math.sqrt (2))));
assert (OV.IsEqual (OV.CalculateModelVolume (model), 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)));
const mesh = testUtils.GetTetrahedronMesh ();
const model = testUtils.GetModelWithOneMesh (mesh);
assert (OV.IsEqual (OV.CalculateMeshSurfaceArea (mesh), Math.sqrt (3) * Math.pow (edgeLength, 2.0)));
assert (OV.IsEqual (OV.CalculateModelSurfaceArea (model), Math.sqrt (3) * Math.pow (edgeLength, 2.0)));
});
});

View File

@ -25,6 +25,7 @@
"source/model/meshbuffer.js",
"source/model/model.js",
"source/model/topology.js",
"source/model/enumerator.js",
"source/model/modelutils.js",
"source/model/modelfinalization.js",
"source/model/quantities.js",

View File

@ -38,6 +38,7 @@
<script type="text/javascript" src="../source/model/meshbuffer.js"></script>
<script type="text/javascript" src="../source/model/model.js"></script>
<script type="text/javascript" src="../source/model/topology.js"></script>
<script type="text/javascript" src="../source/model/enumerator.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>

View File

@ -38,6 +38,7 @@
<script type="text/javascript" src="../source/model/meshbuffer.js"></script>
<script type="text/javascript" src="../source/model/model.js"></script>
<script type="text/javascript" src="../source/model/topology.js"></script>
<script type="text/javascript" src="../source/model/enumerator.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>