Calculate the volume of a model by calculating the sum of volumes of all meshes.
This commit is contained in:
parent
7372b40c3a
commit
2593bbba4e
@ -52,7 +52,7 @@ import { MeshInstanceId, MeshInstance } from './model/meshinstance.js';
|
||||
import { GetMeshType, CalculateTriangleNormal, TransformMesh, FlipMeshTrianglesOrientation, MeshType } from './model/meshutils.js';
|
||||
import { Model } from './model/model.js';
|
||||
import { FinalizeModel, CheckModel } from './model/modelfinalization.js';
|
||||
import { IsModelEmpty, GetBoundingBox, GetTopology, IsSolid, HasDefaultMaterial, ReplaceDefaultMaterialColor } from './model/modelutils.js';
|
||||
import { IsModelEmpty, GetBoundingBox, GetTopology, IsTwoManifold, HasDefaultMaterial, ReplaceDefaultMaterialColor } from './model/modelutils.js';
|
||||
import { Node, NodeType } from './model/node.js';
|
||||
import { Object3D, ModelObject3D } from './model/object.js';
|
||||
import { Property, PropertyGroup, PropertyToString, PropertyType } from './model/property.js';
|
||||
@ -242,7 +242,7 @@ export {
|
||||
IsModelEmpty,
|
||||
GetBoundingBox,
|
||||
GetTopology,
|
||||
IsSolid,
|
||||
IsTwoManifold,
|
||||
HasDefaultMaterial,
|
||||
ReplaceDefaultMaterialColor,
|
||||
Node,
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { BoundingBoxCalculator3D } from '../geometry/box3d.js';
|
||||
import { Octree } from '../geometry/octree.js';
|
||||
import { GetMeshType, MeshType } from './meshutils.js';
|
||||
import { Model } from './model.js';
|
||||
import { Topology } from './topology.js';
|
||||
|
||||
export function IsModelEmpty (model)
|
||||
@ -48,7 +49,7 @@ export function GetTopology (object3D)
|
||||
return topology;
|
||||
}
|
||||
|
||||
export function IsSolid (object3D)
|
||||
export function IsTwoManifold (object3D)
|
||||
{
|
||||
function GetEdgeOrientationInTriangle (topology, triangleIndex, edgeIndex)
|
||||
{
|
||||
@ -68,28 +69,30 @@ export function IsSolid (object3D)
|
||||
return null;
|
||||
}
|
||||
|
||||
const topology = GetTopology (object3D);
|
||||
for (let edgeIndex = 0; edgeIndex < topology.edges.length; edgeIndex++) {
|
||||
const edge = topology.edges[edgeIndex];
|
||||
let triCount = edge.triangles.length;
|
||||
if (triCount === 0 || triCount % 2 !== 0) {
|
||||
return false;
|
||||
}
|
||||
let edgesDirection = 0;
|
||||
for (let triIndex = 0; triIndex < edge.triangles.length; triIndex++) {
|
||||
const triangleIndex = edge.triangles[triIndex];
|
||||
const edgeOrientation = GetEdgeOrientationInTriangle (topology, triangleIndex, edgeIndex);
|
||||
if (edgeOrientation) {
|
||||
edgesDirection += 1;
|
||||
} else {
|
||||
edgesDirection -= 1;
|
||||
if (object3D instanceof Model) {
|
||||
let isSolid = true;
|
||||
object3D.EnumerateMeshInstances ((meshInstance) => {
|
||||
if (isSolid) {
|
||||
isSolid = IsTwoManifold (meshInstance);
|
||||
}
|
||||
});
|
||||
return isSolid;
|
||||
} else {
|
||||
const topology = GetTopology (object3D);
|
||||
for (let edgeIndex = 0; edgeIndex < topology.edges.length; edgeIndex++) {
|
||||
const edge = topology.edges[edgeIndex];
|
||||
if (edge.triangles.length !== 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let edgeOrientation1 = GetEdgeOrientationInTriangle (topology, edge.triangles[0], edgeIndex);
|
||||
let edgeOrientation2 = GetEdgeOrientationInTriangle (topology, edge.triangles[1], edgeIndex);
|
||||
if (edgeOrientation1 === null || edgeOrientation2 === null || edgeOrientation1 === edgeOrientation2) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (edgesDirection !== 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
export function HasDefaultMaterial (model)
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { CoordDistance3D, CrossVector3D, DotVector3D } from '../geometry/coord3d.js';
|
||||
import { Model } from './model.js';
|
||||
|
||||
export function GetTriangleArea (v0, v1, v2)
|
||||
{
|
||||
@ -20,11 +21,19 @@ export function GetTetrahedronSignedVolume (v0, v1, v2)
|
||||
|
||||
export function CalculateVolume (object3D)
|
||||
{
|
||||
let volume = 0.0;
|
||||
object3D.EnumerateTriangleVertices ((v0, v1, v2) => {
|
||||
volume += GetTetrahedronSignedVolume (v0, v1, v2);
|
||||
});
|
||||
return volume;
|
||||
if (object3D instanceof Model) {
|
||||
let volume = 0.0;
|
||||
object3D.EnumerateMeshInstances ((meshInstance) => {
|
||||
volume += CalculateVolume (meshInstance);
|
||||
});
|
||||
return volume;
|
||||
} else {
|
||||
let volume = 0.0;
|
||||
object3D.EnumerateTriangleVertices ((v0, v1, v2) => {
|
||||
volume += GetTetrahedronSignedVolume (v0, v1, v2);
|
||||
});
|
||||
return volume;
|
||||
}
|
||||
}
|
||||
|
||||
export function CalculateSurfaceArea (object3D)
|
||||
|
||||
@ -76,6 +76,7 @@ export class Topology
|
||||
}
|
||||
|
||||
let triangleIndex = this.triangles.length;
|
||||
|
||||
let triangle = new TopologyTriangle ();
|
||||
triangle.triEdge1 = this.AddTriangleEdge (vertex1, vertex2);
|
||||
triangle.triEdge2 = this.AddTriangleEdge (vertex2, vertex3);
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { RunTaskAsync } from '../engine/core/taskrunner.js';
|
||||
import { SubCoord3D } from '../engine/geometry/coord3d.js';
|
||||
import { GetBoundingBox, IsSolid } from '../engine/model/modelutils.js';
|
||||
import { GetBoundingBox, IsTwoManifold } from '../engine/model/modelutils.js';
|
||||
import { CalculateVolume, CalculateSurfaceArea } from '../engine/model/quantities.js';
|
||||
import { Property, PropertyToString, PropertyType } from '../engine/model/property.js';
|
||||
import { AddDiv, AddDomElement, ClearDomElement } from '../engine/viewer/domutils.js';
|
||||
@ -39,7 +39,7 @@ export class SidebarDetailsPanel extends SidebarPanel
|
||||
this.AddProperty (table, new Property (PropertyType.Number, 'Size Y', size.y));
|
||||
this.AddProperty (table, new Property (PropertyType.Number, 'Size Z', size.z));
|
||||
this.AddCalculatedProperty (table, 'Volume', () => {
|
||||
if (!IsSolid (object3D)) {
|
||||
if (!IsTwoManifold (object3D)) {
|
||||
return null;
|
||||
}
|
||||
const volume = CalculateVolume (object3D);
|
||||
|
||||
@ -10,6 +10,7 @@ import geometry_test from './tests/geometry_test.js';
|
||||
import meshbuffer_test from './tests/meshbuffer_test.js';
|
||||
import mesh_test from './tests/mesh_test.js';
|
||||
import modelutils_test from './tests/modelutils_test.js';
|
||||
import topology_test from './tests/topology_test.js';
|
||||
import node_test from './tests/node_test.js';
|
||||
import model_test from './tests/model_test.js';
|
||||
import quantities_test from './tests/quantities_test.js';
|
||||
@ -41,6 +42,7 @@ geometry_test ();
|
||||
meshbuffer_test ();
|
||||
mesh_test ();
|
||||
modelutils_test ();
|
||||
topology_test ();
|
||||
node_test ();
|
||||
model_test ();
|
||||
quantities_test ();
|
||||
|
||||
@ -7,7 +7,7 @@ export default function suite ()
|
||||
describe ('Generator', function () {
|
||||
it ('Cuboid with Default Parameters', function () {
|
||||
const cuboid = OV.GenerateCuboid (null, 1.0, 1.0, 1.0);
|
||||
assert.ok (OV.IsSolid (cuboid));
|
||||
assert.ok (OV.IsTwoManifold (cuboid));
|
||||
assert.ok (OV.IsEqual (OV.CalculateVolume (cuboid), 1.0));
|
||||
});
|
||||
|
||||
@ -22,53 +22,53 @@ describe ('Generator', function () {
|
||||
|
||||
it ('Cylinder with Default Parameters', function () {
|
||||
const cylinder = OV.GenerateCylinder (null, 0.5, 1.0, 25, false);
|
||||
assert.ok (OV.IsSolid (cylinder));
|
||||
assert.ok (OV.IsTwoManifold (cylinder));
|
||||
assert.ok (OV.IsEqualEps (OV.CalculateVolume (cylinder), Math.PI * 0.5 * 0.5 * 1.0, 0.1));
|
||||
});
|
||||
|
||||
it ('Cone with Default Parameters', function () {
|
||||
const cone = OV.GenerateCone (null, 0.2, 0.5, 1.0, 20, false);
|
||||
assert.ok (OV.IsSolid (cone));
|
||||
assert.ok (OV.IsTwoManifold (cone));
|
||||
assert.ok (OV.IsEqualEps (OV.CalculateVolume (cone), Math.PI / 3.0 * 1.0 * (0.2 * 0.2 + 0.2 * 0.5 + 0.5 * 0.5), 0.1));
|
||||
});
|
||||
|
||||
it ('Cone Zero Top', function () {
|
||||
const cone = OV.GenerateCone (null, 0.0, 0.5, 1.0, 20, false);
|
||||
assert.ok (OV.IsSolid (cone));
|
||||
assert.ok (OV.IsTwoManifold (cone));
|
||||
assert.ok (OV.IsEqualEps (OV.CalculateVolume (cone), 0.5 * 0.5 * Math.PI * 1.0 / 3.0, 1.0));
|
||||
});
|
||||
|
||||
it ('Cone Zero Bottom', function () {
|
||||
const cone = OV.GenerateCone (null, 0.5, 0.0, 1.0, 20, false);
|
||||
assert.ok (OV.IsSolid (cone));
|
||||
assert.ok (OV.IsTwoManifold (cone));
|
||||
assert.ok (OV.IsEqualEps (OV.CalculateVolume (cone), 0.5 * 0.5 * Math.PI * 1.0 / 3.0, 1.0));
|
||||
});
|
||||
|
||||
it ('Sphere with Default Parameters', function () {
|
||||
const cylinder = OV.GenerateSphere (null, 0.5, 20, false);
|
||||
assert.ok (OV.IsSolid (cylinder));
|
||||
assert.ok (OV.IsTwoManifold (cylinder));
|
||||
assert.ok (OV.IsEqualEps (OV.CalculateVolume (cylinder), Math.PI * 0.5 * 0.5 * 0.5 * 4.0 / 3.0, 0.1));
|
||||
});
|
||||
|
||||
it ('Platonic Solids', function () {
|
||||
let tetrahedron = OV.GeneratePlatonicSolid (null, 'tetrahedron', 1.0);
|
||||
assert.ok (OV.IsSolid (tetrahedron));
|
||||
assert.ok (OV.IsTwoManifold (tetrahedron));
|
||||
assert.ok (OV.IsEqual (OV.CalculateVolume (tetrahedron), 0.5132002392796676));
|
||||
|
||||
let hexahedron = OV.GeneratePlatonicSolid (null, 'hexahedron', 1.0);
|
||||
assert.ok (OV.IsSolid (hexahedron));
|
||||
assert.ok (OV.IsTwoManifold (hexahedron));
|
||||
assert.ok (OV.IsEqual (OV.CalculateVolume (hexahedron), 1.5396007178390028));
|
||||
|
||||
let octahedron = OV.GeneratePlatonicSolid (null, 'octahedron', 1.0);
|
||||
assert.ok (OV.IsSolid (octahedron));
|
||||
assert.ok (OV.IsTwoManifold (octahedron));
|
||||
assert.ok (OV.IsEqual (OV.CalculateVolume (octahedron), 1.3333333333333333));
|
||||
|
||||
let dodecahedron = OV.GeneratePlatonicSolid (null, 'dodecahedron', 1.0);
|
||||
assert.ok (OV.IsSolid (dodecahedron));
|
||||
assert.ok (OV.IsTwoManifold (dodecahedron));
|
||||
assert.ok (OV.IsEqual (OV.CalculateVolume (dodecahedron), 2.7851638631226248));
|
||||
|
||||
let icosahedron = OV.GeneratePlatonicSolid (null, 'icosahedron', 1.0);
|
||||
assert.ok (OV.IsSolid (icosahedron));
|
||||
assert.ok (OV.IsTwoManifold (icosahedron));
|
||||
assert.ok (OV.IsEqual (OV.CalculateVolume (icosahedron), 2.5361507101204093));
|
||||
});
|
||||
});
|
||||
|
||||
@ -115,7 +115,7 @@ describe ('O3dv Importer', function () {
|
||||
assert.strictEqual (model.MeshCount (), 5);
|
||||
assert.strictEqual (model.MeshInstanceCount (), 5);
|
||||
|
||||
assert.ok (OV.IsSolid (model));
|
||||
assert.ok (OV.IsTwoManifold (model));
|
||||
assert.ok (OV.IsEqual (OV.CalculateVolume (model), 8.707448863695035));
|
||||
assert.ok (OV.IsEqual (OV.CalculateSurfaceArea (model), 39.636169009449105));
|
||||
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import * as assert from 'assert';
|
||||
import * as OV from '../../source/engine/main.js';
|
||||
import { GetModelWithOneMesh, GetTetrahedronMesh, GetTwoCubesConnectingInOneEdgeModel, GetTwoCubesConnectingInOneFaceModel, GetTwoCubesConnectingInOneVertexModel } from '../utils/testutils.js';
|
||||
|
||||
export default function suite ()
|
||||
{
|
||||
@ -55,80 +54,6 @@ describe ('Model Utils', function () {
|
||||
assert.ok (OV.CoordIsEqual3D (modelBounds.min, new OV.Coord3D (0.0, 0.0, 0.0)));
|
||||
assert.ok (OV.CoordIsEqual3D (modelBounds.max, new OV.Coord3D (1.0, 1.0, 1.0)));
|
||||
});
|
||||
|
||||
it ('Tetrahedron Topology Calculation', function () {
|
||||
let tetrahedron = GetModelWithOneMesh (GetTetrahedronMesh ());
|
||||
let topology = OV.GetTopology (tetrahedron);
|
||||
assert.ok (OV.IsSolid (tetrahedron));
|
||||
assert.strictEqual (topology.vertices.length, 4);
|
||||
assert.strictEqual (topology.edges.length, 6);
|
||||
assert.strictEqual (topology.triangleEdges.length, 4 * 3);
|
||||
assert.strictEqual (topology.triangles.length, 4);
|
||||
for (let i = 0; i < topology.vertices.length; i++) {
|
||||
assert.strictEqual (topology.vertices[i].edges.length, 3);
|
||||
assert.strictEqual (topology.vertices[i].triangles.length, 3);
|
||||
}
|
||||
for (let i = 0; i < topology.edges.length; i++) {
|
||||
assert.strictEqual (topology.edges[i].triangles.length, 2);
|
||||
}
|
||||
});
|
||||
|
||||
it ('Cube Topology Calculation', function () {
|
||||
let cube = GetModelWithOneMesh (OV.GenerateCuboid (null, 1.0, 1.0, 1.0));
|
||||
assert.ok (OV.IsSolid (cube));
|
||||
|
||||
let topology = OV.GetTopology (cube);
|
||||
assert.strictEqual (topology.vertices.length, 8);
|
||||
assert.strictEqual (topology.edges.length, 12 + 6);
|
||||
assert.strictEqual (topology.triangleEdges.length, 6 * 2 * 3);
|
||||
assert.strictEqual (topology.triangles.length, 6 * 2);
|
||||
|
||||
let verticesWith4Triangles = 0;
|
||||
let verticesWith5Triangles = 0;
|
||||
let verticesWith4Edges = 0;
|
||||
let verticesWith5Edges = 0;
|
||||
for (let i = 0; i < topology.vertices.length; i++) {
|
||||
if (topology.vertices[i].triangles.length == 4) {
|
||||
verticesWith4Triangles += 1;
|
||||
} else if (topology.vertices[i].triangles.length == 5) {
|
||||
verticesWith5Triangles += 1;
|
||||
}
|
||||
if (topology.vertices[i].edges.length == 4) {
|
||||
verticesWith4Edges += 1;
|
||||
} else if (topology.vertices[i].edges.length == 5) {
|
||||
verticesWith5Edges += 1;
|
||||
}
|
||||
}
|
||||
assert.strictEqual (verticesWith4Triangles, 4);
|
||||
assert.strictEqual (verticesWith5Triangles, 4);
|
||||
assert.strictEqual (verticesWith4Edges, 4);
|
||||
assert.strictEqual (verticesWith5Edges, 4);
|
||||
|
||||
for (let i = 0; i < topology.edges.length; i++) {
|
||||
assert.strictEqual (topology.edges[i].triangles.length, 2);
|
||||
}
|
||||
});
|
||||
|
||||
it ('Two Cubes Connecting in One Vertex Topology Calculation', function () {
|
||||
const model = GetTwoCubesConnectingInOneVertexModel ();
|
||||
let topology = OV.GetTopology (model);
|
||||
assert.strictEqual (topology.vertices.length, 15);
|
||||
assert.ok (OV.IsSolid (model));
|
||||
});
|
||||
|
||||
it ('Two Cubes Connecting in One Edge Topology Calculation', function () {
|
||||
const model = GetTwoCubesConnectingInOneEdgeModel ();
|
||||
let topology = OV.GetTopology (model);
|
||||
assert.strictEqual (topology.vertices.length, 14);
|
||||
assert.ok (OV.IsSolid (model));
|
||||
});
|
||||
|
||||
it ('Two Cubes Connecting in One Face Topology Calculation', function () {
|
||||
const model = GetTwoCubesConnectingInOneFaceModel ();
|
||||
let topology = OV.GetTopology (model);
|
||||
assert.strictEqual (topology.vertices.length, 12);
|
||||
assert.ok (OV.IsSolid (model));
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@ -9,8 +9,8 @@ describe ('Quantities', function () {
|
||||
it ('Cube Volume Calculation', function () {
|
||||
const mesh = OV.GenerateCuboid (null, 1.0, 1.0, 1.0);
|
||||
const model = GetModelWithOneMesh (mesh);
|
||||
assert.ok (OV.IsSolid (mesh));
|
||||
assert.ok (OV.IsSolid (model));
|
||||
assert.ok (OV.IsTwoManifold (mesh));
|
||||
assert.ok (OV.IsTwoManifold (model));
|
||||
assert.ok (OV.IsEqual (OV.CalculateVolume (mesh), 1.0));
|
||||
assert.ok (OV.IsEqual (OV.CalculateVolume (model), 1.0));
|
||||
});
|
||||
@ -18,24 +18,24 @@ describe ('Quantities', function () {
|
||||
it ('Cube with Missing Face Volume Calculation', function () {
|
||||
const mesh = GetCubeWithOneMissingFaceMesh ();
|
||||
const model = GetModelWithOneMesh (mesh);
|
||||
assert.ok (!OV.IsSolid (model));
|
||||
assert.ok (!OV.IsTwoManifold (model));
|
||||
});
|
||||
|
||||
it ('Two Cubes Connecting in One Vertex Volume Calculation', function () {
|
||||
const model = GetTwoCubesConnectingInOneVertexModel ();
|
||||
assert.ok (OV.IsSolid (model));
|
||||
assert.ok (OV.IsTwoManifold (model));
|
||||
assert.ok (OV.IsEqual (OV.CalculateVolume (model), 2.0));
|
||||
});
|
||||
|
||||
it ('Two Cubes Connecting in One Edge Volume Calculation', function () {
|
||||
const model = GetTwoCubesConnectingInOneEdgeModel ();
|
||||
assert.ok (OV.IsSolid (model));
|
||||
assert.ok (OV.IsTwoManifold (model));
|
||||
assert.ok (OV.IsEqual (OV.CalculateVolume (model), 2.0));
|
||||
});
|
||||
|
||||
it ('Two Cubes Connecting in One Face Volume Calculation', function () {
|
||||
const model = GetTwoCubesConnectingInOneFaceModel ();
|
||||
assert.ok (OV.IsSolid (model));
|
||||
assert.ok (OV.IsTwoManifold (model));
|
||||
assert.ok (OV.IsEqual (OV.CalculateVolume (model), 2.0));
|
||||
});
|
||||
|
||||
@ -62,15 +62,15 @@ describe ('Quantities', function () {
|
||||
mesh.AddTriangle (new OV.Triangle (4, 5, 6));
|
||||
mesh.AddTriangle (new OV.Triangle (4, 7, 6));
|
||||
const model = GetModelWithOneMesh (mesh);
|
||||
assert.ok (!OV.IsSolid (mesh));
|
||||
assert.ok (!OV.IsSolid (model));
|
||||
assert.ok (!OV.IsTwoManifold (mesh));
|
||||
assert.ok (!OV.IsTwoManifold (model));
|
||||
});
|
||||
|
||||
it ('Cube Surface Area Calculation', function () {
|
||||
const mesh = OV.GenerateCuboid (null, 1.0, 1.0, 1.0);
|
||||
const model = GetModelWithOneMesh (mesh);
|
||||
assert.ok (OV.IsSolid (mesh));
|
||||
assert.ok (OV.IsSolid (model));
|
||||
assert.ok (OV.IsTwoManifold (mesh));
|
||||
assert.ok (OV.IsTwoManifold (model));
|
||||
assert.ok (OV.IsEqual (OV.CalculateSurfaceArea (mesh), 6.0));
|
||||
assert.ok (OV.IsEqual (OV.CalculateSurfaceArea (model), 6.0));
|
||||
});
|
||||
@ -78,8 +78,8 @@ describe ('Quantities', function () {
|
||||
it ('Cube with Missing Face Surface Area Calculation', function () {
|
||||
const mesh = GetCubeWithOneMissingFaceMesh ();
|
||||
const model = GetModelWithOneMesh (mesh);
|
||||
assert.ok (!OV.IsSolid (mesh));
|
||||
assert.ok (!OV.IsSolid (model));
|
||||
assert.ok (!OV.IsTwoManifold (mesh));
|
||||
assert.ok (!OV.IsTwoManifold (model));
|
||||
assert.ok (OV.IsEqual (OV.CalculateSurfaceArea (mesh), 5.0));
|
||||
assert.ok (OV.IsEqual (OV.CalculateSurfaceArea (model), 5.0));
|
||||
});
|
||||
@ -88,8 +88,8 @@ describe ('Quantities', function () {
|
||||
const edgeLength = OV.CoordDistance3D (new OV.Coord3D (1.0, 1.0, 1.0), new OV.Coord3D (-1.0, -1.0, 1.0));
|
||||
const mesh = GetTetrahedronMesh ();
|
||||
const model = GetModelWithOneMesh (mesh);
|
||||
assert.ok (OV.IsSolid (mesh));
|
||||
assert.ok (OV.IsSolid (model));
|
||||
assert.ok (OV.IsTwoManifold (mesh));
|
||||
assert.ok (OV.IsTwoManifold (model));
|
||||
assert.ok (OV.IsEqual (OV.CalculateVolume (mesh), Math.pow (edgeLength, 3.0) / (6.0 * Math.sqrt (2))));
|
||||
assert.ok (OV.IsEqual (OV.CalculateVolume (model), Math.pow (edgeLength, 3.0) / (6.0 * Math.sqrt (2))));
|
||||
});
|
||||
@ -98,8 +98,8 @@ describe ('Quantities', function () {
|
||||
const edgeLength = OV.CoordDistance3D (new OV.Coord3D (1.0, 1.0, 1.0), new OV.Coord3D (-1.0, -1.0, 1.0));
|
||||
const mesh = GetTetrahedronMesh ();
|
||||
const model = GetModelWithOneMesh (mesh);
|
||||
assert.ok (OV.IsSolid (mesh));
|
||||
assert.ok (OV.IsSolid (model));
|
||||
assert.ok (OV.IsTwoManifold (mesh));
|
||||
assert.ok (OV.IsTwoManifold (model));
|
||||
assert.ok (OV.IsEqual (OV.CalculateSurfaceArea (mesh), Math.sqrt (3) * Math.pow (edgeLength, 2.0)));
|
||||
assert.ok (OV.IsEqual (OV.CalculateSurfaceArea (model), Math.sqrt (3) * Math.pow (edgeLength, 2.0)));
|
||||
});
|
||||
@ -110,7 +110,7 @@ describe ('Quantities', function () {
|
||||
let node = new OV.Node ();
|
||||
node.SetTransformation (transformation);
|
||||
const meshInstance = new OV.MeshInstance (null, node, mesh);
|
||||
assert.ok (OV.IsSolid (meshInstance));
|
||||
assert.ok (OV.IsTwoManifold (meshInstance));
|
||||
assert.ok (OV.IsEqual (OV.CalculateVolume (meshInstance), 8.0));
|
||||
assert.ok (OV.IsEqual (OV.CalculateSurfaceArea (meshInstance), 24.0));
|
||||
});
|
||||
|
||||
84
test/tests/topology_test.js
Normal file
84
test/tests/topology_test.js
Normal file
@ -0,0 +1,84 @@
|
||||
import * as assert from 'assert';
|
||||
import * as OV from '../../source/engine/main.js';
|
||||
import { GetModelWithOneMesh, GetTetrahedronMesh, GetTwoCubesConnectingInOneEdgeModel, GetTwoCubesConnectingInOneFaceModel, GetTwoCubesConnectingInOneVertexModel } from '../utils/testutils.js';
|
||||
|
||||
export default function suite ()
|
||||
{
|
||||
|
||||
describe ('Topology', function () {
|
||||
it ('Tetrahedron Topology Calculation', function () {
|
||||
let tetrahedron = GetModelWithOneMesh (GetTetrahedronMesh ());
|
||||
let topology = OV.GetTopology (tetrahedron);
|
||||
assert.ok (OV.IsTwoManifold (tetrahedron));
|
||||
assert.strictEqual (topology.vertices.length, 4);
|
||||
assert.strictEqual (topology.edges.length, 6);
|
||||
assert.strictEqual (topology.triangleEdges.length, 4 * 3);
|
||||
assert.strictEqual (topology.triangles.length, 4);
|
||||
for (let i = 0; i < topology.vertices.length; i++) {
|
||||
assert.strictEqual (topology.vertices[i].edges.length, 3);
|
||||
assert.strictEqual (topology.vertices[i].triangles.length, 3);
|
||||
}
|
||||
for (let i = 0; i < topology.edges.length; i++) {
|
||||
assert.strictEqual (topology.edges[i].triangles.length, 2);
|
||||
}
|
||||
});
|
||||
|
||||
it ('Cube Topology Calculation', function () {
|
||||
let cube = GetModelWithOneMesh (OV.GenerateCuboid (null, 1.0, 1.0, 1.0));
|
||||
assert.ok (OV.IsTwoManifold (cube));
|
||||
|
||||
let topology = OV.GetTopology (cube);
|
||||
assert.strictEqual (topology.vertices.length, 8);
|
||||
assert.strictEqual (topology.edges.length, 12 + 6);
|
||||
assert.strictEqual (topology.triangleEdges.length, 6 * 2 * 3);
|
||||
assert.strictEqual (topology.triangles.length, 6 * 2);
|
||||
|
||||
let verticesWith4Triangles = 0;
|
||||
let verticesWith5Triangles = 0;
|
||||
let verticesWith4Edges = 0;
|
||||
let verticesWith5Edges = 0;
|
||||
for (let i = 0; i < topology.vertices.length; i++) {
|
||||
if (topology.vertices[i].triangles.length == 4) {
|
||||
verticesWith4Triangles += 1;
|
||||
} else if (topology.vertices[i].triangles.length == 5) {
|
||||
verticesWith5Triangles += 1;
|
||||
}
|
||||
if (topology.vertices[i].edges.length == 4) {
|
||||
verticesWith4Edges += 1;
|
||||
} else if (topology.vertices[i].edges.length == 5) {
|
||||
verticesWith5Edges += 1;
|
||||
}
|
||||
}
|
||||
assert.strictEqual (verticesWith4Triangles, 4);
|
||||
assert.strictEqual (verticesWith5Triangles, 4);
|
||||
assert.strictEqual (verticesWith4Edges, 4);
|
||||
assert.strictEqual (verticesWith5Edges, 4);
|
||||
|
||||
for (let i = 0; i < topology.edges.length; i++) {
|
||||
assert.strictEqual (topology.edges[i].triangles.length, 2);
|
||||
}
|
||||
});
|
||||
|
||||
it ('Two Cubes Connecting in One Vertex Topology Calculation', function () {
|
||||
const model = GetTwoCubesConnectingInOneVertexModel ();
|
||||
let topology = OV.GetTopology (model);
|
||||
assert.strictEqual (topology.vertices.length, 15);
|
||||
assert.ok (OV.IsTwoManifold (model));
|
||||
});
|
||||
|
||||
it ('Two Cubes Connecting in One Edge Topology Calculation', function () {
|
||||
const model = GetTwoCubesConnectingInOneEdgeModel ();
|
||||
let topology = OV.GetTopology (model);
|
||||
assert.strictEqual (topology.vertices.length, 14);
|
||||
assert.ok (OV.IsTwoManifold (model));
|
||||
});
|
||||
|
||||
it ('Two Cubes Connecting in One Face Topology Calculation', function () {
|
||||
const model = GetTwoCubesConnectingInOneFaceModel ();
|
||||
let topology = OV.GetTopology (model);
|
||||
assert.strictEqual (topology.vertices.length, 12);
|
||||
assert.ok (OV.IsTwoManifold (model));
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user