Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions CadRevealComposer.Tests/BoundingBoxTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ namespace CadRevealComposer.Tests;

using System.Drawing;
using System.Numerics;
using CadRevealComposer.Utils;

public class BoundingBoxTests
{
Expand Down Expand Up @@ -66,4 +67,69 @@ public void Extents_ReturnsSizeInAllDimensions()
var extents = new Vector3(3, 3, 3);
Assert.That(boundingBox.Extents, Is.EqualTo(extents));
}

[Test]
public void CreateBoundingBoxMesh_GivenABoundingBox_ValidateTheOutputMesh()
{
// Create randomizer
var rand = new Random();

// Create true bounding box, based on random lengths for x, y, z, as well as random position, r
var xyz = GenRandomVec3(20.0, -5.0);
var r = GenRandomVec3(100.0, 50.0);
var trueBoundingBox = new BoundingBox(r - xyz * 0.5f, r + xyz * 0.5f);

// Create the bounding box mesh (ToBoxMesh is the method we want to test)
var boundingBoxMesh = trueBoundingBox.ToBoxMesh(0.01f);

// Verify that all vertices within the generated mesh is on the true bounding box
// (assures we cannot have a "rotated" Mesh with a bounding box matching the true bounding box)
const float tolerance = 1.0e-4f;
var tolerance3 = new Vector3(tolerance, tolerance, tolerance);
foreach (Vector3 p in boundingBoxMesh.Vertices)
{
Assert.Multiple(() =>
{
Assert.That(
IsWithinBox(p, new BoundingBox(trueBoundingBox.Min - tolerance3, trueBoundingBox.Max + tolerance3)),
Is.True
);
Assert.That(
IsWithinBox(p, new BoundingBox(trueBoundingBox.Min + tolerance3, trueBoundingBox.Max - tolerance3)),
Is.False
);
});
}

// Make sure the bounding box of the Mesh matches the true bounding box
var boundingBoxOfMesh = boundingBoxMesh.CalculateAxisAlignedBoundingBox();
Assert.That(
boundingBoxOfMesh,
Is.EqualTo(trueBoundingBox)
.Using<BoundingBox>(
(x, y) =>
x.Min.EqualsWithinTolerance(y.Min, tolerance) && x.Max.EqualsWithinTolerance(y.Max, tolerance)
)
);
return;

// Define lambda functions
Vector3 GenRandomVec3(double maxSize, double offset) =>
new Vector3(
(float)(maxSize * rand.NextDouble() - offset),
(float)(maxSize * rand.NextDouble() - offset),
(float)(maxSize * rand.NextDouble() - offset)
);

bool IsWithinBox(Vector3 coordinate, BoundingBox bbox)
{
if (coordinate.X < bbox.Min.X || coordinate.X > bbox.Max.X)
return false;
if (coordinate.Y < bbox.Min.Y || coordinate.Y > bbox.Max.Y)
return false;
if (coordinate.Z < bbox.Min.Z || coordinate.Z > bbox.Max.Z)
return false;
return true;
}
}
}
31 changes: 31 additions & 0 deletions CadRevealComposer/CadRevealNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ namespace CadRevealComposer;
using System.Numerics;
using Primitives;
using ProtoBuf;
using Tessellation;
using Utils;

[ProtoContract(SkipConstructor = true)]
Expand Down Expand Up @@ -49,6 +50,36 @@ public Box ToBoxPrimitive(uint treeIndex, Color color)
return new Box(matrix, treeIndex, color, this);
}

/// <summary>
/// Creates a Mesh <see cref="Mesh"/> representing the bounding box coordinates.
/// </summary>
/// <returns>Mesh representing the bounding box.</returns>
public Mesh ToBoxMesh(float error)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need a mesh instead of just creating a Box primitive?

{
Vector3[] boundingBoxVertices = new Vector3[8];

Vector3 d = Max - Min;
boundingBoxVertices[0] = Min;
boundingBoxVertices[1] = Min + new Vector3(d.X, 0.0f, 0.0f);
boundingBoxVertices[2] = Min + new Vector3(0.0f, d.Y, 0.0f);
boundingBoxVertices[3] = Min + new Vector3(d.X, d.Y, 0.0f);

boundingBoxVertices[4] = Min + new Vector3(0.0f, 0.0f, d.Z);
boundingBoxVertices[5] = Min + new Vector3(d.X, 0.0f, d.Z);
boundingBoxVertices[6] = Min + new Vector3(0.0f, d.Y, d.Z);
boundingBoxVertices[7] = Min + new Vector3(d.X, d.Y, d.Z);

var indices = new List<uint>();
indices.AddRange([0, 2, 3, 0, 3, 1]); // Indices for two triangles along the X-Y-near plane of the bounding box
indices.AddRange([0, 1, 4, 1, 5, 4]); // Indices for two triangles along the X-Z-near plane of the bounding box
indices.AddRange([0, 6, 2, 0, 4, 6]); // Indices for two triangles along the Y-Z-near plane of the bounding box
indices.AddRange([3, 2, 6, 3, 6, 7]); // Indices for two triangles along the X-Z-far plane of the bounding box
indices.AddRange([3, 5, 1, 3, 7, 1]); // Indices for two triangles along the Y-Z-far plane of the bounding box
indices.AddRange([4, 5, 7, 4, 7, 6]); // Indices for two triangles along the X-Y-far plane of the bounding box

return new Mesh(boundingBoxVertices, indices.ToArray(), error);
}

/// <summary>
/// Check if bounding box of this node is equal to other bounding box
/// </summary>
Expand Down