From cce795332f5e2f99c5454cbca9aeae5982336321 Mon Sep 17 00:00:00 2001 From: Michael Smith Date: Sun, 21 Feb 2016 01:22:44 -0800 Subject: [PATCH] Basic Bounds implementations for most transforms and booleans + some test updates. --- OSCADSharp/OSCADSharp.ConsoleTests/Program.cs | 12 +++---- .../Booleans/DifferenceTests.cs | 9 +++++ .../Booleans/IntersectionTests.cs | 9 +++++ .../Booleans/UnionTests.cs | 16 +++++++++ .../OSCADSharp.UnitTests.csproj | 1 + .../Transforms/MinkowskiTests.cs | 10 +++++- .../Transforms/MirrorTests.cs | 19 ++++++++++ .../Transforms/ResizeTests.cs | 10 ++++++ .../Transforms/ScaleTests.cs | 15 ++++++++ .../Transforms/TranslateTests.cs | 26 ++++++++++++++ OSCADSharp/OSCADSharp/Booleans/Difference.cs | 6 ++++ .../OSCADSharp/Booleans/Intersection.cs | 6 ++++ .../Scripting/MultiBlockStatementObject.cs | 35 ++++++++++++++++++- OSCADSharp/OSCADSharp/Spatial/Bounds.cs | 20 +++++++++++ .../OSCADSharp/Transforms/ColoredObject.cs | 2 +- .../Transforms/MinkowskiedObject.cs | 6 ++++ .../OSCADSharp/Transforms/MirroredObject.cs | 18 +++++++++- .../OSCADSharp/Transforms/ResizedObject.cs | 9 ++++- .../OSCADSharp/Transforms/RotatedObject.cs | 4 ++- .../OSCADSharp/Transforms/ScaledObject.cs | 3 +- .../OSCADSharp/Transforms/TranslatedObject.cs | 3 +- 21 files changed, 225 insertions(+), 14 deletions(-) create mode 100644 OSCADSharp/OSCADSharp.UnitTests/Transforms/TranslateTests.cs diff --git a/OSCADSharp/OSCADSharp.ConsoleTests/Program.cs b/OSCADSharp/OSCADSharp.ConsoleTests/Program.cs index 9e1edc4..10bc5b0 100644 --- a/OSCADSharp/OSCADSharp.ConsoleTests/Program.cs +++ b/OSCADSharp/OSCADSharp.ConsoleTests/Program.cs @@ -13,13 +13,13 @@ namespace OSCADSharp.ConsoleTests { static void Main(string[] args) { - var obj = new Text3D("BBBB", 16); + var obj = new Cube(5, 10, 20) + new Sphere(10).Translate(-10, 5, 0); - var pos = obj.Position(); - var cyl1 = new Cylinder(1, 100, true).Translate(pos); - var cyl2 = new Cylinder(1, 100, true).Rotate(0, 90, 0).Translate(pos); - var cyl3 = new Cylinder(1, 100, true).Rotate(90, 0, 0).Translate(pos); - var axisHelper = cyl1.Union(cyl2, cyl3).Color("Red"); + //var pos = obj.Position(); + //var cyl1 = new Cylinder(1, 100, true).Translate(pos); + //var cyl2 = new Cylinder(1, 100, true).Rotate(0, 90, 0).Translate(pos); + //var cyl3 = new Cylinder(1, 100, true).Rotate(90, 0, 0).Translate(pos); + //var axisHelper = cyl1.Union(cyl2, cyl3).Color("Red"); var topCorner = new Sphere().Translate(obj.Bounds().TopRight); var botCorner = new Sphere().Translate(obj.Bounds().BottomLeft); diff --git a/OSCADSharp/OSCADSharp.UnitTests/Booleans/DifferenceTests.cs b/OSCADSharp/OSCADSharp.UnitTests/Booleans/DifferenceTests.cs index 10aeaa1..d6c822e 100644 --- a/OSCADSharp/OSCADSharp.UnitTests/Booleans/DifferenceTests.cs +++ b/OSCADSharp/OSCADSharp.UnitTests/Booleans/DifferenceTests.cs @@ -25,6 +25,15 @@ namespace OSCADSharp.UnitTests Assert.AreEqual(sphere.Position(), diff.Position()); } + [TestMethod] + public void Difference_BoundsYieldsBoundsOfFirstChild() + { + var sphere = new Sphere().Translate(.25, .25, 1); + var diff = sphere.Difference(new Cube()); + + Assert.AreEqual(sphere.Bounds(), diff.Bounds()); + } + [TestMethod] public void Difference_MinusOperatorCreatesDifferenceObject() { diff --git a/OSCADSharp/OSCADSharp.UnitTests/Booleans/IntersectionTests.cs b/OSCADSharp/OSCADSharp.UnitTests/Booleans/IntersectionTests.cs index fadd682..07a562b 100644 --- a/OSCADSharp/OSCADSharp.UnitTests/Booleans/IntersectionTests.cs +++ b/OSCADSharp/OSCADSharp.UnitTests/Booleans/IntersectionTests.cs @@ -15,5 +15,14 @@ namespace OSCADSharp.UnitTests var pos = obj.Position(); } + + [TestMethod] + [ExpectedException(typeof(NotSupportedException))] + public void Intersection_BoundsThrowsNotSupportedException() + { + var obj = new Sphere().Intersection(new Text3D("Sup")); + + var pos = obj.Bounds(); + } } } diff --git a/OSCADSharp/OSCADSharp.UnitTests/Booleans/UnionTests.cs b/OSCADSharp/OSCADSharp.UnitTests/Booleans/UnionTests.cs index 037d325..0ae5468 100644 --- a/OSCADSharp/OSCADSharp.UnitTests/Booleans/UnionTests.cs +++ b/OSCADSharp/OSCADSharp.UnitTests/Booleans/UnionTests.cs @@ -68,5 +68,21 @@ namespace OSCADSharp.UnitTests Assert.AreEqual(0, unionChildrenCount); } + + [TestMethod] + public void Union_BoundsForUnionedObjectsBecomeExtremitiesOfBoth() + { + var obj = new Cube(5, 10, 20) + new Sphere(10).Translate(-10, 5, 0); + + var bounds = obj.Bounds(); + + Assert.AreEqual(20, bounds.Z_Max); + Assert.AreEqual(10, bounds.Y_Max); + Assert.AreEqual(5, bounds.X_Max); + + Assert.AreEqual(-5, bounds.Z_Min); + Assert.AreEqual(0, bounds.Y_Min); + Assert.AreEqual(-15, bounds.X_Min); + } } } diff --git a/OSCADSharp/OSCADSharp.UnitTests/OSCADSharp.UnitTests.csproj b/OSCADSharp/OSCADSharp.UnitTests/OSCADSharp.UnitTests.csproj index 2a6184b..a1e5ecc 100644 --- a/OSCADSharp/OSCADSharp.UnitTests/OSCADSharp.UnitTests.csproj +++ b/OSCADSharp/OSCADSharp.UnitTests/OSCADSharp.UnitTests.csproj @@ -67,6 +67,7 @@ + diff --git a/OSCADSharp/OSCADSharp.UnitTests/Transforms/MinkowskiTests.cs b/OSCADSharp/OSCADSharp.UnitTests/Transforms/MinkowskiTests.cs index abbc9c7..072e840 100644 --- a/OSCADSharp/OSCADSharp.UnitTests/Transforms/MinkowskiTests.cs +++ b/OSCADSharp/OSCADSharp.UnitTests/Transforms/MinkowskiTests.cs @@ -11,9 +11,17 @@ namespace OSCADSharp.UnitTests [ExpectedException(typeof(NotSupportedException))] public void Minkowski_PositionThrowsNotSupportedException() { - var obj = new Cylinder().Intersection(new Sphere()).Translate(0, 5, 5); + var obj = new Cylinder().Minkowski(new Sphere()).Translate(0, 5, 5); var pos = obj.Position(); } + + [TestMethod] + [ExpectedException(typeof(NotSupportedException))] + public void Minkowski_BoundsThrowsNotSupportedException() + { + var obj = new Cylinder().Minkowski(new Sphere()).Translate(0, 5, 5); + obj.Bounds(); + } } } diff --git a/OSCADSharp/OSCADSharp.UnitTests/Transforms/MirrorTests.cs b/OSCADSharp/OSCADSharp.UnitTests/Transforms/MirrorTests.cs index dc2747b..ab16829 100644 --- a/OSCADSharp/OSCADSharp.UnitTests/Transforms/MirrorTests.cs +++ b/OSCADSharp/OSCADSharp.UnitTests/Transforms/MirrorTests.cs @@ -40,5 +40,24 @@ namespace OSCADSharp.UnitTests var pos = cube.Mirror(1, 1, 0).Position(); } + + [TestMethod] + public void Mirror_SingleAxisMirrorInvertsBounds() + { + OSCADObject cube = new Cube(5, 10, 20); + var boundsBefore = cube.Bounds(); + cube = cube.Mirror(0, 1, 0); + + Assert.AreEqual(cube.Bounds().Y_Max, boundsBefore.Y_Min); + } + + [TestMethod] + [ExpectedException(typeof(NotSupportedException))] + public void Mirror_MultiAxisBoundsThrowsNotSupportedException() + { + var cube = new Cube(5, 10, 20); + + var pos = cube.Mirror(1, 1, 0).Bounds(); + } } } diff --git a/OSCADSharp/OSCADSharp.UnitTests/Transforms/ResizeTests.cs b/OSCADSharp/OSCADSharp.UnitTests/Transforms/ResizeTests.cs index af993df..631bf68 100644 --- a/OSCADSharp/OSCADSharp.UnitTests/Transforms/ResizeTests.cs +++ b/OSCADSharp/OSCADSharp.UnitTests/Transforms/ResizeTests.cs @@ -18,5 +18,15 @@ namespace OSCADSharp.UnitTests.Transforms var pos = new Cube(5, 5, 20) .Translate(30, 0, 0).Rotate(0, 90, 0).Resize(2, 2, 2).Position(); } + + [TestMethod] + public void Resize_ResizeScalesBoundariesToFit() + { + var obj = new Cube(20, 20, 10).Resize(5, 5, 5); + + var bounds = obj.Bounds(); + Assert.AreEqual(new Vector3(5, 5, 5), bounds.TopRight); + Assert.AreEqual(new Vector3(0, 0, 0), bounds.BottomLeft); + } } } diff --git a/OSCADSharp/OSCADSharp.UnitTests/Transforms/ScaleTests.cs b/OSCADSharp/OSCADSharp.UnitTests/Transforms/ScaleTests.cs index efee6bb..537ef09 100644 --- a/OSCADSharp/OSCADSharp.UnitTests/Transforms/ScaleTests.cs +++ b/OSCADSharp/OSCADSharp.UnitTests/Transforms/ScaleTests.cs @@ -19,5 +19,20 @@ namespace OSCADSharp.UnitTests.Transforms Assert.AreEqual(new Vector3(20, 5, -65), obj.Position()); } + + [TestMethod] + public void Scale_BoundsScaleWithObject() + { + var obj = new Cube(5, 5, 5).Scale(2, 2, 3); + + var bounds = obj.Bounds(); + Assert.AreEqual(bounds.X_Max, 10); + Assert.AreEqual(bounds.Y_Max, 10); + Assert.AreEqual(bounds.Z_Max, 15); + + Assert.AreEqual(bounds.X_Min, 0); + Assert.AreEqual(bounds.Y_Min, 0); + Assert.AreEqual(bounds.Z_Min, 0); + } } } diff --git a/OSCADSharp/OSCADSharp.UnitTests/Transforms/TranslateTests.cs b/OSCADSharp/OSCADSharp.UnitTests/Transforms/TranslateTests.cs new file mode 100644 index 0000000..b915f53 --- /dev/null +++ b/OSCADSharp/OSCADSharp.UnitTests/Transforms/TranslateTests.cs @@ -0,0 +1,26 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using OSCADSharp.Solids; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace OSCADSharp.UnitTests.Transforms +{ + + [TestClass] + public class TranslateTests + { + [TestMethod] + public void Translate_BoundsMoveWhenObjectIsTranslated() + { + var cube = new Cube(); + var boundsBefore = cube.Bounds(); + var boundsAfter = cube.Translate(5, 2, 3).Bounds(); + + Assert.AreEqual(boundsAfter.TopRight, boundsBefore.TopRight + new Vector3(5, 2, 3)); + Assert.AreEqual(boundsAfter.BottomLeft, boundsBefore.BottomLeft + new Vector3(5, 2, 3)); + } + } +} diff --git a/OSCADSharp/OSCADSharp/Booleans/Difference.cs b/OSCADSharp/OSCADSharp/Booleans/Difference.cs index 6b00007..932b7a9 100644 --- a/OSCADSharp/OSCADSharp/Booleans/Difference.cs +++ b/OSCADSharp/OSCADSharp/Booleans/Difference.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; +using OSCADSharp.Spatial; namespace OSCADSharp.Booleans { @@ -24,5 +25,10 @@ namespace OSCADSharp.Booleans { return children[0].Position(); } + + public override Bounds Bounds() + { + return children[0].Bounds(); + } } } diff --git a/OSCADSharp/OSCADSharp/Booleans/Intersection.cs b/OSCADSharp/OSCADSharp/Booleans/Intersection.cs index f5c0f72..aaabfe2 100644 --- a/OSCADSharp/OSCADSharp/Booleans/Intersection.cs +++ b/OSCADSharp/OSCADSharp/Booleans/Intersection.cs @@ -1,4 +1,5 @@ using OSCADSharp.Scripting; +using OSCADSharp.Spatial; using System; using System.Collections.Generic; using System.Linq; @@ -24,5 +25,10 @@ namespace OSCADSharp.Booleans { throw new NotSupportedException("Position is not supported on Intersected objects."); } + + public override Bounds Bounds() + { + throw new NotSupportedException("Bounds is not supported on Intersected objects."); + } } } diff --git a/OSCADSharp/OSCADSharp/Scripting/MultiBlockStatementObject.cs b/OSCADSharp/OSCADSharp/Scripting/MultiBlockStatementObject.cs index 03a1d33..ce7c1ec 100644 --- a/OSCADSharp/OSCADSharp/Scripting/MultiBlockStatementObject.cs +++ b/OSCADSharp/OSCADSharp/Scripting/MultiBlockStatementObject.cs @@ -53,7 +53,40 @@ namespace OSCADSharp.Scripting public override Bounds Bounds() { - throw new NotImplementedException(); + var newBottomLeft = new Vector3(); + var newTopRight = new Vector3(); + + foreach (var child in this.children) + { + var bounds = child.Bounds(); + if (bounds.X_Min < newBottomLeft.X) + { + newBottomLeft.X = bounds.X_Min; + } + if (bounds.Y_Min < newBottomLeft.Y) + { + newBottomLeft.Y = bounds.Y_Min; + } + if (bounds.Z_Min < newBottomLeft.Z) + { + newBottomLeft.Z = bounds.Z_Min; + } + + if (bounds.X_Max > newTopRight.X) + { + newTopRight.X = bounds.X_Max; + } + if (bounds.Y_Max> newTopRight.Y) + { + newTopRight.Y = bounds.Y_Max; + } + if (bounds.Z_Max > newTopRight.Z) + { + newTopRight.Z = bounds.Z_Max; + } + } + + return new Bounds(newBottomLeft, newTopRight); } } } diff --git a/OSCADSharp/OSCADSharp/Spatial/Bounds.cs b/OSCADSharp/OSCADSharp/Spatial/Bounds.cs index fb21e39..e38ea48 100644 --- a/OSCADSharp/OSCADSharp/Spatial/Bounds.cs +++ b/OSCADSharp/OSCADSharp/Spatial/Bounds.cs @@ -64,5 +64,25 @@ namespace OSCADSharp.Spatial /// public double Z_Min { get { return TopRight.Z < BottomLeft.Z ? TopRight.Z : BottomLeft.Z; } } #endregion + + /// + /// Compares a set of bounds to another object + /// + /// + /// + public override bool Equals(object obj) + { + return obj.GetHashCode() == this.GetHashCode(); + } + + /// + /// Gets a hashcode based on the string representation of the vectors + /// that make up this set of bounds + /// + /// + public override int GetHashCode() + { + return String.Format("TR: {0}, BL: {1}", this.TopRight.ToString(), this.BottomLeft.ToString()).GetHashCode(); + } } } diff --git a/OSCADSharp/OSCADSharp/Transforms/ColoredObject.cs b/OSCADSharp/OSCADSharp/Transforms/ColoredObject.cs index d763ee2..7f7aae1 100644 --- a/OSCADSharp/OSCADSharp/Transforms/ColoredObject.cs +++ b/OSCADSharp/OSCADSharp/Transforms/ColoredObject.cs @@ -59,7 +59,7 @@ namespace OSCADSharp.Transforms public override Bounds Bounds() { - throw new NotImplementedException(); + return this.obj.Bounds(); } } } diff --git a/OSCADSharp/OSCADSharp/Transforms/MinkowskiedObject.cs b/OSCADSharp/OSCADSharp/Transforms/MinkowskiedObject.cs index 3b4693c..3b88499 100644 --- a/OSCADSharp/OSCADSharp/Transforms/MinkowskiedObject.cs +++ b/OSCADSharp/OSCADSharp/Transforms/MinkowskiedObject.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; +using OSCADSharp.Spatial; namespace OSCADSharp.Transforms { @@ -21,5 +22,10 @@ namespace OSCADSharp.Transforms { throw new NotSupportedException("Position is not supported on Minkowskied objects."); } + + public override Bounds Bounds() + { + throw new NotSupportedException("Bounds is not supported on Minkowskied objects."); + } } } diff --git a/OSCADSharp/OSCADSharp/Transforms/MirroredObject.cs b/OSCADSharp/OSCADSharp/Transforms/MirroredObject.cs index d8164c8..a38a938 100644 --- a/OSCADSharp/OSCADSharp/Transforms/MirroredObject.cs +++ b/OSCADSharp/OSCADSharp/Transforms/MirroredObject.cs @@ -75,9 +75,25 @@ namespace OSCADSharp.Transforms (this.Normal.Y != 0 && (this.Normal.X != 0 || this.Normal.Z != 0)); } + // TODO: As with Position, will yield incorrect positions if mirroring on multiple axes + // fix mirrored positions for multiple-axis mirroring public override Bounds Bounds() { - throw new NotImplementedException(); + if (this.isMoreThanOneAxis()) + { + throw new NotSupportedException("Getting the position of an object that's been mirrored on more than one axis is not currently supported."); + } + + var oldBounds = this.obj.Bounds(); + var newBottomLeft = new Vector3(this.Normal.X != 0 ? oldBounds.BottomLeft.X * -1 : oldBounds.BottomLeft.X, + this.Normal.Y != 0 ? oldBounds.BottomLeft.Y * -1 : oldBounds.BottomLeft.Y, + this.Normal.Z != 0 ? oldBounds.BottomLeft.Z * -1 : oldBounds.BottomLeft.Z); + + var newTopRight = new Vector3(this.Normal.X != 0 ? oldBounds.TopRight.X * -1 : oldBounds.TopRight.X, + this.Normal.Y != 0 ? oldBounds.TopRight.Y * -1 : oldBounds.TopRight.Y, + this.Normal.Z != 0 ? oldBounds.TopRight.Z * -1 : oldBounds.TopRight.Z); + + return new Bounds(newBottomLeft, newTopRight); } } } diff --git a/OSCADSharp/OSCADSharp/Transforms/ResizedObject.cs b/OSCADSharp/OSCADSharp/Transforms/ResizedObject.cs index cececcc..fc0d034 100644 --- a/OSCADSharp/OSCADSharp/Transforms/ResizedObject.cs +++ b/OSCADSharp/OSCADSharp/Transforms/ResizedObject.cs @@ -57,7 +57,14 @@ namespace OSCADSharp.Transforms public override Bounds Bounds() { - throw new NotImplementedException(); + var oldBounds = obj.Bounds(); + + double xScaleFactor = this.Size.X > 0 ? this.Size.X / Math.Abs(oldBounds.X_Max - oldBounds.X_Min) : 1; + double yScaleFactor = this.Size.Y > 0 ? this.Size.Y / Math.Abs(oldBounds.Y_Max - oldBounds.Y_Min) : 1; + double zScaleFactor = this.Size.Z > 0 ? this.Size.Z / Math.Abs(oldBounds.Z_Max - oldBounds.Z_Min) : 1; + Vector3 scaleMultiplier = new Vector3(xScaleFactor, yScaleFactor, zScaleFactor); + + return new Bounds(oldBounds.BottomLeft * scaleMultiplier, oldBounds.TopRight * scaleMultiplier); } } } diff --git a/OSCADSharp/OSCADSharp/Transforms/RotatedObject.cs b/OSCADSharp/OSCADSharp/Transforms/RotatedObject.cs index d93bff3..4dc01ce 100644 --- a/OSCADSharp/OSCADSharp/Transforms/RotatedObject.cs +++ b/OSCADSharp/OSCADSharp/Transforms/RotatedObject.cs @@ -57,7 +57,9 @@ namespace OSCADSharp.Transforms public override Bounds Bounds() { - throw new NotImplementedException(); + var oldBounds = obj.Bounds(); + return new Bounds(Matrix.GetRotatedPoint(oldBounds.BottomLeft, this.Angle.X, this.Angle.Y, this.Angle.Z), + Matrix.GetRotatedPoint(oldBounds.TopRight, this.Angle.X, this.Angle.Y, this.Angle.Z)); } } } diff --git a/OSCADSharp/OSCADSharp/Transforms/ScaledObject.cs b/OSCADSharp/OSCADSharp/Transforms/ScaledObject.cs index 6d7606d..138fd3f 100644 --- a/OSCADSharp/OSCADSharp/Transforms/ScaledObject.cs +++ b/OSCADSharp/OSCADSharp/Transforms/ScaledObject.cs @@ -57,7 +57,8 @@ namespace OSCADSharp.Transforms public override Bounds Bounds() { - throw new NotImplementedException(); + var oldBounds = obj.Bounds(); + return new Bounds(oldBounds.BottomLeft * this.ScaleFactor, oldBounds.TopRight * this.ScaleFactor); } } } diff --git a/OSCADSharp/OSCADSharp/Transforms/TranslatedObject.cs b/OSCADSharp/OSCADSharp/Transforms/TranslatedObject.cs index 5ba946a..25e672b 100644 --- a/OSCADSharp/OSCADSharp/Transforms/TranslatedObject.cs +++ b/OSCADSharp/OSCADSharp/Transforms/TranslatedObject.cs @@ -54,7 +54,8 @@ namespace OSCADSharp.Transforms public override Bounds Bounds() { - throw new NotImplementedException(); + var oldBounds = obj.Bounds(); + return new Bounds(oldBounds.BottomLeft + this.Vector, oldBounds.TopRight + this.Vector); } } }