diff --git a/MatterControlLib/DesignTools/SupportGenerator.cs b/MatterControlLib/DesignTools/SupportGenerator.cs index f57bbbdfb..67e02030b 100644 --- a/MatterControlLib/DesignTools/SupportGenerator.cs +++ b/MatterControlLib/DesignTools/SupportGenerator.cs @@ -171,24 +171,29 @@ namespace MatterHackers.MatterControl.DesignTools progress?.Report(status); // Get visible meshes for each of them - var supportCandidates = scene.Children.SelectMany(i => i.VisibleMeshes()); + var allBedItems = scene.Children.SelectMany(i => i.VisibleMeshes()); + AxisAlignedBoundingBox suppoortBounds = AxisAlignedBoundingBox.Empty(); if (selectedItem != null) { - supportCandidates = selectedItem.VisibleMeshes(); + foreach (var candidate in selectedItem.VisibleMeshes()) + { + suppoortBounds += candidate.GetAxisAlignedBoundingBox(candidate.Matrix.Inverted * candidate.WorldMatrix()); + } } - - AxisAlignedBoundingBox allBounds = AxisAlignedBoundingBox.Empty(); - foreach (var candidate in supportCandidates) + else { - allBounds += candidate.GetAxisAlignedBoundingBox(candidate.Matrix.Inverted * candidate.WorldMatrix()); + foreach (var candidate in allBedItems) + { + suppoortBounds += candidate.GetAxisAlignedBoundingBox(candidate.Matrix.Inverted * candidate.WorldMatrix()); + } } // create the gird of possible support - var gridBounds = new RectangleDouble(Math.Floor((double)(allBounds.MinXYZ.X / PillarSize)), - Math.Floor((double)(allBounds.MinXYZ.Y / PillarSize)), - Math.Ceiling(allBounds.MaxXYZ.X / PillarSize), - Math.Ceiling(allBounds.MaxXYZ.Y / PillarSize)); + var gridBounds = new RectangleDouble(Math.Floor((double)(suppoortBounds.MinXYZ.X / PillarSize)), + Math.Floor((double)(suppoortBounds.MinXYZ.Y / PillarSize)), + Math.Ceiling(suppoortBounds.MaxXYZ.X / PillarSize), + Math.Ceiling(suppoortBounds.MaxXYZ.Y / PillarSize)); var partBounds = new RectangleDouble(gridBounds.Left * PillarSize, gridBounds.Bottom * PillarSize, gridBounds.Right * PillarSize, @@ -209,7 +214,7 @@ namespace MatterHackers.MatterControl.DesignTools // get all the support plane intersections status.Status = "Trace"; progress?.Report(status); - var detectedPlanes = DetectRequiredSupportByTracing(gridBounds, supportCandidates); + var detectedPlanes = DetectRequiredSupportByTracing(gridBounds, allBedItems); status.Status = "Columns"; progress?.Report(status); @@ -374,7 +379,7 @@ namespace MatterHackers.MatterControl.DesignTools do { lastBottom = i; - // find all open arreas in the list and add support + // find all open areas in the list and add support i = GetNextBottom(i, planes); if (i >= 0) { @@ -400,6 +405,9 @@ namespace MatterHackers.MatterControl.DesignTools private Dictionary<(int x, int y), List<(double z, bool bottom)>> DetectRequiredSupportByTracing(RectangleDouble gridBounds, IEnumerable supportCandidates) { + var allBounds = supportCandidates.GetAxisAlignedBoundingBox(); + var rayStartZ = allBounds.MinXYZ.Z - 1; + var traceData = GetTraceData(supportCandidates); // keep a list of all the detected planes in each support column @@ -428,7 +436,7 @@ namespace MatterHackers.MatterControl.DesignTools var xPos = (gridBounds.Left + x) * PillarSize + halfPillar + (xOffset * halfPillar); // detect all the bottom plans (surfaces that might need support - var upRay = new Ray(new Vector3(xPos + .000013, yPos - .00027, -.001), Vector3.UnitZ, intersectionType: IntersectionType.FrontFace); + var upRay = new Ray(new Vector3(xPos + .000013, yPos - .00027, rayStartZ), Vector3.UnitZ, intersectionType: IntersectionType.FrontFace); do { upHit = traceData.GetClosestIntersection(upRay); @@ -442,7 +450,7 @@ namespace MatterHackers.MatterControl.DesignTools } while (upHit != null); // detect all the up plans (surfaces that will have support on top of them) - upRay = new Ray(new Vector3(xPos + .000013, yPos - .00027, 0), Vector3.UnitZ, intersectionType: IntersectionType.BackFace); + upRay = new Ray(new Vector3(xPos + .000013, yPos - .00027, rayStartZ), Vector3.UnitZ, intersectionType: IntersectionType.BackFace); do { upHit = traceData.GetClosestIntersection(upRay); @@ -557,7 +565,7 @@ namespace MatterHackers.MatterControl.DesignTools supportVerts = new List(); supportFaces = new FaceList(); - // find all the down faces from the support cindidates + // find all the down faces from the support candidates AddSupportFaces(supportCandidates, supportVerts, supportFaces, diff --git a/Submodules/agg-sharp b/Submodules/agg-sharp index cb96dfcfa..913fd3720 160000 --- a/Submodules/agg-sharp +++ b/Submodules/agg-sharp @@ -1 +1 @@ -Subproject commit cb96dfcfa70f2b89a05a055a593ccf73cbd98635 +Subproject commit 913fd3720ab662e4e439ecd7672afde0580b4e1e diff --git a/Tests/MatterControl.Tests/MatterControl/SupportGeneratorTests.cs b/Tests/MatterControl.Tests/MatterControl/SupportGeneratorTests.cs index 19f00bf70..04bf2e706 100644 --- a/Tests/MatterControl.Tests/MatterControl/SupportGeneratorTests.cs +++ b/Tests/MatterControl.Tests/MatterControl/SupportGeneratorTests.cs @@ -80,6 +80,27 @@ namespace MatterControl.Tests.MatterControl } } + // make a single cube in the bed and ensure that no support is generated + // _________ + // | | + // __| |__ + // |_______| + // + { + InteractiveScene scene = new InteractiveScene(); + + var cube = await CubeObject3D.Create(20, 20, 20); + var aabb = cube.GetAxisAlignedBoundingBox(); + // move it so the bottom is 15 above the bed + cube.Matrix = Matrix4X4.CreateTranslation(0, 0, -aabb.MinXYZ.Z - 5); + scene.Children.Add(cube); + + var supportGenerator = new SupportGenerator(scene, minimumSupportHeight); + supportGenerator.SupportType = SupportGenerator.SupportGenerationType.From_Bed; + await supportGenerator.Create(null, CancellationToken.None); + Assert.AreEqual(1, scene.Children.Count, "We should not have added any support"); + } + // make a cube on the bed and single cube in the air and ensure that support is not generated // _________ // | | @@ -95,14 +116,14 @@ namespace MatterControl.Tests.MatterControl var cubeOnBed = await CubeObject3D.Create(20, 20, 20); var aabbBed = cubeOnBed.GetAxisAlignedBoundingBox(); // move it so the bottom is 15 above the bed - cubeOnBed.Matrix = Matrix4X4.CreateTranslation(0, 0, -aabbBed.MinXYZ.Z); + cubeOnBed.Matrix = Matrix4X4.CreateTranslation(0, 0, -aabbBed.MinXYZ.Z - 5); scene.Children.Add(cubeOnBed); - var cubeInAair = await CubeObject3D.Create(20, 20, 20); - var aabbAir = cubeInAair.GetAxisAlignedBoundingBox(); + var cubeInAir = await CubeObject3D.Create(20, 20, 20); + var aabbAir = cubeInAir.GetAxisAlignedBoundingBox(); // move it so the bottom is 15 above the bed - cubeInAair.Matrix = Matrix4X4.CreateTranslation(0, 0, -aabbAir.MinXYZ.Z + 25); - scene.Children.Add(cubeInAair); + cubeInAir.Matrix = Matrix4X4.CreateTranslation(0, 0, -aabbAir.MinXYZ.Z + 25); + scene.Children.Add(cubeInAir); var supportGenerator = new SupportGenerator(scene, minimumSupportHeight); supportGenerator.SupportType = SupportGenerator.SupportGenerationType.From_Bed; @@ -110,7 +131,38 @@ namespace MatterControl.Tests.MatterControl Assert.AreEqual(2, scene.Children.Count, "We should not have added support"); } - // make a cube on the bed and another cube exactily on top of it and ensure that support is not generated + // make a single cube in the bed and another cube on top, ensure that no support is generated + // _________ + // | | + // | | + // |_______| + // _________ + // | | + // __| |__ + // |_______| + // + { + InteractiveScene scene = new InteractiveScene(); + + var cubeOnBed = await CubeObject3D.Create(20, 20, 20); + var aabbBed = cubeOnBed.GetAxisAlignedBoundingBox(); + // move it so the bottom is 15 above the bed + cubeOnBed.Matrix = Matrix4X4.CreateTranslation(0, 0, -aabbBed.MinXYZ.Z); + scene.Children.Add(cubeOnBed); + + var cubeInAir = await CubeObject3D.Create(20, 20, 20); + var aabbAir = cubeInAir.GetAxisAlignedBoundingBox(); + // move it so the bottom is 15 above the bed + cubeInAir.Matrix = Matrix4X4.CreateTranslation(0, 0, -aabbAir.MinXYZ.Z + 25); + scene.Children.Add(cubeInAir); + + var supportGenerator = new SupportGenerator(scene, minimumSupportHeight); + supportGenerator.SupportType = SupportGenerator.SupportGenerationType.From_Bed; + await supportGenerator.Create(null, CancellationToken.None); + Assert.AreEqual(2, scene.Children.Count, "We should not have added support"); + } + + // make a cube on the bed and another cube exactly on top of it and ensure that support is not generated // _________ // | | // | | @@ -127,11 +179,11 @@ namespace MatterControl.Tests.MatterControl cubeOnBed.Matrix = Matrix4X4.CreateTranslation(0, 0, -aabbBed.MinXYZ.Z); scene.Children.Add(cubeOnBed); - var cubeInAair = await CubeObject3D.Create(20, 20, 20); - var aabbAir = cubeInAair.GetAxisAlignedBoundingBox(); + var cubeInAir = await CubeObject3D.Create(20, 20, 20); + var aabbAir = cubeInAir.GetAxisAlignedBoundingBox(); // move it so the bottom is 15 above the bed - cubeInAair.Matrix = Matrix4X4.CreateTranslation(0, 0, -aabbAir.MinXYZ.Z + 20); - scene.Children.Add(cubeInAair); + cubeInAir.Matrix = Matrix4X4.CreateTranslation(0, 0, -aabbAir.MinXYZ.Z + 20); + scene.Children.Add(cubeInAir); var supportGenerator = new SupportGenerator(scene, minimumSupportHeight); supportGenerator.SupportType = SupportGenerator.SupportGenerationType.From_Bed; @@ -155,11 +207,43 @@ namespace MatterControl.Tests.MatterControl cubeOnBed.Matrix = Matrix4X4.CreateTranslation(0, 0, -aabbBed.MinXYZ.Z); scene.Children.Add(cubeOnBed); - var cubeInAair = await CubeObject3D.Create(20, 20, 20); - var aabbAir = cubeInAair.GetAxisAlignedBoundingBox(); + var cubeInAir = await CubeObject3D.Create(20, 20, 20); + var aabbAir = cubeInAir.GetAxisAlignedBoundingBox(); // move it so the bottom is 15 above the bed - cubeInAair.Matrix = Matrix4X4.CreateTranslation(0, 0, -aabbAir.MinXYZ.Z + 15); - scene.Children.Add(cubeInAair); + cubeInAir.Matrix = Matrix4X4.CreateTranslation(0, 0, -aabbAir.MinXYZ.Z + 15); + scene.Children.Add(cubeInAir); + + var supportGenerator = new SupportGenerator(scene, minimumSupportHeight); + supportGenerator.SupportType = SupportGenerator.SupportGenerationType.From_Bed; + await supportGenerator.Create(null, CancellationToken.None); + Assert.AreEqual(2, scene.Children.Count, "We should not have added support"); + } + + // Make a cube on the bed and single cube in the air that intersects it. + // SELECT the cube on top + // Ensure that support is not generated. + // _________ + // | | + // |______ | // top cube actually exactly on top of bottom cube + // ||______|| + // | | + //___|_______|___ + { + InteractiveScene scene = new InteractiveScene(); + + var cubeOnBed = await CubeObject3D.Create(20, 20, 20); + var aabbBed = cubeOnBed.GetAxisAlignedBoundingBox(); + // move it so the bottom is 15 above the bed + cubeOnBed.Matrix = Matrix4X4.CreateTranslation(0, 0, -aabbBed.MinXYZ.Z); + scene.Children.Add(cubeOnBed); + + var cubeInAir = await CubeObject3D.Create(20, 20, 20); + var aabbAir = cubeInAir.GetAxisAlignedBoundingBox(); + // move it so the bottom is 15 above the bed + cubeInAir.Matrix = Matrix4X4.CreateTranslation(0, 0, -aabbAir.MinXYZ.Z + 15); + scene.Children.Add(cubeInAir); + + scene.SelectedItem = cubeInAir; var supportGenerator = new SupportGenerator(scene, minimumSupportHeight); supportGenerator.SupportType = SupportGenerator.SupportGenerationType.From_Bed; @@ -259,11 +343,11 @@ namespace MatterControl.Tests.MatterControl cubeOnBed.Matrix = Matrix4X4.CreateTranslation(0, 0, -aabbBed.MinXYZ.Z); scene.Children.Add(cubeOnBed); - var cubeInAair = await CubeObject3D.Create(20, 20, 20); - var aabbAir = cubeInAair.GetAxisAlignedBoundingBox(); + var cubeInAir = await CubeObject3D.Create(20, 20, 20); + var aabbAir = cubeInAir.GetAxisAlignedBoundingBox(); // move it so the bottom is 15 above the bed - cubeInAair.Matrix = Matrix4X4.CreateTranslation(0, 0, -aabbAir.MinXYZ.Z + 25); - scene.Children.Add(cubeInAair); + cubeInAir.Matrix = Matrix4X4.CreateTranslation(0, 0, -aabbAir.MinXYZ.Z + 25); + scene.Children.Add(cubeInAir); var supportGenerator = new SupportGenerator(scene, minimumSupportHeight); supportGenerator.SupportType = SupportGenerator.SupportGenerationType.Normal; @@ -292,11 +376,11 @@ namespace MatterControl.Tests.MatterControl cubeOnBed.Matrix = Matrix4X4.CreateTranslation(0, 0, -aabbBed.MinXYZ.Z); scene.Children.Add(cubeOnBed); - var cubeInAair = await CubeObject3D.Create(20, 20, 20); - var aabbAir = cubeInAair.GetAxisAlignedBoundingBox(); + var cubeInAir = await CubeObject3D.Create(20, 20, 20); + var aabbAir = cubeInAir.GetAxisAlignedBoundingBox(); // move it so the bottom is 15 above the bed - cubeInAair.Matrix = Matrix4X4.CreateTranslation(0, 0, -aabbAir.MinXYZ.Z + 15); - scene.Children.Add(cubeInAair); + cubeInAir.Matrix = Matrix4X4.CreateTranslation(0, 0, -aabbAir.MinXYZ.Z + 15); + scene.Children.Add(cubeInAir); var supportGenerator = new SupportGenerator(scene, minimumSupportHeight); supportGenerator.SupportType = SupportGenerator.SupportGenerationType.Normal; @@ -304,7 +388,7 @@ namespace MatterControl.Tests.MatterControl Assert.AreEqual(2, scene.Children.Count, "We should not have added support"); } - // make a cube on the bed and another cube exactily on top of it and ensure that support is not generated + // make a cube on the bed and another cube exactly on top of it and ensure that support is not generated // _________ // | | // | | @@ -321,11 +405,11 @@ namespace MatterControl.Tests.MatterControl cubeOnBed.Matrix = Matrix4X4.CreateTranslation(0, 0, -aabbBed.MinXYZ.Z); scene.Children.Add(cubeOnBed); - var cubeInAair = await CubeObject3D.Create(20, 20, 20); - var aabbAir = cubeInAair.GetAxisAlignedBoundingBox(); + var cubeInAir = await CubeObject3D.Create(20, 20, 20); + var aabbAir = cubeInAir.GetAxisAlignedBoundingBox(); // move it so the bottom is 15 above the bed - cubeInAair.Matrix = Matrix4X4.CreateTranslation(0, 0, -aabbAir.MinXYZ.Z + 20); - scene.Children.Add(cubeInAair); + cubeInAir.Matrix = Matrix4X4.CreateTranslation(0, 0, -aabbAir.MinXYZ.Z + 20); + scene.Children.Add(cubeInAir); var supportGenerator = new SupportGenerator(scene, minimumSupportHeight); supportGenerator.SupportType = SupportGenerator.SupportGenerationType.From_Bed;