From f465727e02478ec950e17057f0f5712f80a2e27a Mon Sep 17 00:00:00 2001 From: Lars Brubaker Date: Tue, 22 Jan 2019 11:35:47 -0800 Subject: [PATCH] Fixing mirror to keep good normals moved support generator to a better place started work on support tests issue: MatterHackers/MCCentral#4873 validate mirror on y flipping --- .../DesignTools/Operations/MirrorObject3D.cs | 2 - .../DesignTools/SupportGenerator.cs | 336 ++++++++++++++++++ .../Library/Export/GCodeExport.cs | 1 + .../PartPreviewWindow/GenerateSupportPanel.cs | 313 +--------------- Submodules/agg-sharp | 2 +- .../MatterControl.Tests.csproj | 1 + .../MatterControl/SupportGeneratorTests.cs | 47 +++ 7 files changed, 402 insertions(+), 300 deletions(-) create mode 100644 MatterControlLib/DesignTools/SupportGenerator.cs create mode 100644 Tests/MatterControl.Tests/MatterControl/SupportGeneratorTests.cs diff --git a/MatterControlLib/DesignTools/Operations/MirrorObject3D.cs b/MatterControlLib/DesignTools/Operations/MirrorObject3D.cs index bafc7c20e..a14cc1149 100644 --- a/MatterControlLib/DesignTools/Operations/MirrorObject3D.cs +++ b/MatterControlLib/DesignTools/Operations/MirrorObject3D.cs @@ -88,8 +88,6 @@ namespace MatterHackers.MatterControl.DesignTools item.meshCopy.Mesh.Transform(meshCopyToThis * mirrorMatrix * meshCopyToThis.Inverted); item.meshCopy.Mesh.ReverseFaces(); - item.meshCopy.Mesh.CalculateNormals(); - item.meshCopy.Mesh.MarkAsChanged(); } this.Matrix = oldMatrix; diff --git a/MatterControlLib/DesignTools/SupportGenerator.cs b/MatterControlLib/DesignTools/SupportGenerator.cs new file mode 100644 index 000000000..967574e2b --- /dev/null +++ b/MatterControlLib/DesignTools/SupportGenerator.cs @@ -0,0 +1,336 @@ +/* +Copyright (c) 2019, Lars Brubaker, John Lewin +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using MatterHackers.Agg; +using MatterHackers.DataConverters3D; +using MatterHackers.PolygonMesh; +using MatterHackers.RayTracer; +using MatterHackers.VectorMath; + +namespace MatterHackers.MatterControl.DesignTools +{ + public static class FaceListExtensions + { + public static IPrimitive CreateTraceData(this FaceList faceList, List vertexList, int maxRecursion = int.MaxValue) + { + var allPolys = new List(); + + foreach (var face in faceList) + { + allPolys.Add(new TriangleShape(vertexList[face.v0], vertexList[face.v1], vertexList[face.v2], null)); + } + + return BoundingVolumeHierarchy.CreateNewHierachy(allPolys, maxRecursion); + } + + public static IPrimitive CreateTraceData(this FaceList faceList, List vertexList, int maxRecursion = int.MaxValue) + { + var allPolys = new List(); + + foreach (var face in faceList) + { + allPolys.Add(new TriangleShape(vertexList[face.v0], vertexList[face.v1], vertexList[face.v2], null)); + } + + return BoundingVolumeHierarchy.CreateNewHierachy(allPolys, maxRecursion); + } + } + + [HideFromTreeViewAttribute, Immutable] + public class GeneratedSupportObject3D : Object3D + { + public GeneratedSupportObject3D() + { + OutputType = PrintOutputTypes.Support; + } + } + + public class SupportGenerator + { + private InteractiveScene scene; + + public SupportGenerator(InteractiveScene scene) + { + this.scene = scene; + } + + public double MaxOverHangAngle + { + get + { + if (UserSettings.Instance.get(UserSettingsKey.SupportMaxOverHangAngle) == null) + { + return 45; + } + var value = UserSettings.Instance.GetValue(UserSettingsKey.SupportMaxOverHangAngle); + if (value < 0) + { + return 0; + } + if (value > 90) + { + value = 90; + } + + return value; + } + + set + { + UserSettings.Instance.set(UserSettingsKey.SupportMaxOverHangAngle, value.ToString()); + } + } + + public double PillarSize + { + get + { + var value = UserSettings.Instance.GetValue(UserSettingsKey.SupportPillarSize); + if (value < 1.5) + { + return 1.5; + } + + return value; + } + set + { + UserSettings.Instance.set(UserSettingsKey.SupportPillarSize, value.ToString()); + } + } + + /// + /// The amount to reduce the pillars so they are separated in the 3D view + /// + private double reduceAmount => .99; + + public Task Create(IProgress progress, CancellationToken cancelationToken) + { + // Get visible meshes for each of them + var visibleMeshes = scene.Children.SelectMany(i => i.VisibleMeshes()); + + var selectedItem = scene.SelectedItem; + if (selectedItem != null) + { + visibleMeshes = selectedItem.VisibleMeshes(); + } + + var supportCandidates = visibleMeshes.Where(i => i.OutputType != PrintOutputTypes.Support); + + // find all the faces that are candidates for support + var upVerts = new List(); + var upFaces = new FaceList(); + var downVerts = new List(); + var downFaces = new FaceList(); + foreach (var item in supportCandidates) + { + var matrix = item.WorldMatrix(scene); + for (int faceIndex = 0; faceIndex < item.Mesh.Faces.Count; faceIndex++) + { + var face0Normal = item.Mesh.Faces[faceIndex].normal.TransformNormal(matrix).GetNormal(); + var angle = MathHelper.RadiansToDegrees(Math.Acos(face0Normal.Dot(-Vector3Float.UnitZ))); + + if (angle <= MaxOverHangAngle) + { + var face = item.Mesh.Faces[faceIndex]; + var verts = new int[] { face.v0, face.v1, face.v2 }; + var fc = downVerts.Count; + downVerts.Add(item.Mesh.Vertices[face.v0].Transform(matrix)); + downVerts.Add(item.Mesh.Vertices[face.v1].Transform(matrix)); + downVerts.Add(item.Mesh.Vertices[face.v2].Transform(matrix)); + + downFaces.Add(fc, fc + 1, fc + 2, downVerts); + } + + if (angle > 0) + { + var face = item.Mesh.Faces[faceIndex]; + var verts = new int[] { face.v0, face.v1, face.v2 }; + var fc = upFaces.Count; + upVerts.Add(item.Mesh.Vertices[face.v0].Transform(matrix)); + upVerts.Add(item.Mesh.Vertices[face.v1].Transform(matrix)); + upVerts.Add(item.Mesh.Vertices[face.v2].Transform(matrix)); + + upFaces.Add(fc, fc + 1, fc + 2, upVerts); + } + } + } + + if (downFaces.Count > 0) + { + var downTraceData = downFaces.CreateTraceData(downVerts); + var upTraceData = upFaces.CreateTraceData(upVerts); + + // get the bounds of all verts + var bounds = downVerts.Bounds(); + + // create the gird of possible support + var gridBounds = new RectangleDouble(Math.Floor((double)(bounds.MinXYZ.X / PillarSize)), + Math.Floor((double)(bounds.MinXYZ.Y / PillarSize)), + Math.Ceiling(bounds.MaxXYZ.X / PillarSize), + Math.Ceiling(bounds.MaxXYZ.Y / PillarSize)); + + var supportGrid = new List>((int)(gridBounds.Width * gridBounds.Height)); + + IObject3D holder = new Object3D(); + + // at the center of every grid item add in a list of all the top faces to look down from + for (int y = 0; y < gridBounds.Height; y++) + { + var yPos = (gridBounds.Bottom + y) * PillarSize; + for (int x = 0; x < gridBounds.Width; x++) + { + var xPos = (gridBounds.Left + x) * PillarSize; + IntersectInfo upHit = null; + var upRay = new Ray(new Vector3(xPos, yPos, 0), Vector3.UnitZ, intersectionType: IntersectionType.Both); + do + { + upHit = downTraceData.GetClosestIntersection(upRay); + if (upHit != null) + { + // we found a ceiling above this spot, look down from that to find the first floor + var downRay = new Ray(new Vector3(upHit.HitPosition.X, upHit.HitPosition.Y, upHit.HitPosition.Z - .001), -Vector3.UnitZ, intersectionType: IntersectionType.Both); + var downHit = upTraceData.GetClosestIntersection(downRay); + if (downHit != null) + { + AddSupportColumn(holder, downHit.HitPosition.X, downHit.HitPosition.Y, downHit.HitPosition.Z, upHit.HitPosition.Z); + } + else + { + // did not find a hit, go to the bed + AddSupportColumn(holder, upHit.HitPosition.X, upHit.HitPosition.Y, upRay.origin.Z, upHit.HitPosition.Z); + } + + // make a new ray just past the last hit to keep looking for up hits + upRay = new Ray(new Vector3(xPos, yPos, upHit.HitPosition.Z + .001), Vector3.UnitZ, intersectionType: IntersectionType.Both); + } + } while (upHit != null); + } + } + + // foreach face set the support heights in the overlapped support grid + // foreach grid column that has data + // trace down from the top to the first bottom hit (or bed) + // add a support column + var first = downFaces.First(); + var position = downVerts[first.v0]; + //AddSupportColumn(position.X, position.Y, position.Z, 0); + + scene.Children.Modify(list => + { + list.AddRange(holder.Children); + }); + } + + // this is the theory for regions rather than pillars + // separate the faces into face patch groups (these are the new support tops) + // project all the vertices of each patch group down until they hit an up face in the scene (or 0) + // make a new patch group at the z of the hit (these will be the bottoms) + // find the outline of the patch groups (these will be the walls of the top and bottom patches + // make a new mesh object with the top, bottom and walls, add it to the scene and mark it as support + + return Task.CompletedTask; + } + + public void RemoveExisting() + { + var existingSupports = scene.Children.Where(i => i.GetType() == typeof(GeneratedSupportObject3D)); + + scene.Children.Modify((list) => + { + foreach (var item in existingSupports) + { + list.Remove(item); + } + }); + } + + public bool RequiresSupport() + { + bool supportInScene = scene.VisibleMeshes().Any(i => i.WorldOutputType() == PrintOutputTypes.Support); + if (!supportInScene) + { + // there is no support in the scene check if there are faces that require support + var supportCandidates = scene.VisibleMeshes().Where(i => i.OutputType != PrintOutputTypes.Support); + + // find all the faces that are candidates for support + foreach (var item in supportCandidates) + { + var matrix = item.WorldMatrix(scene); + for (int faceIndex = 0; faceIndex < item.Mesh.Faces.Count; faceIndex++) + { + bool aboveBed = false; + var face = item.Mesh.Faces[faceIndex]; + var verts = new int[] { face.v0, face.v1, face.v2 }; + foreach (var vertex in verts) + { + if (item.Mesh.Vertices[vertex].Transform(matrix).Z > .01) + { + aboveBed = true; + break; + } + } + if (aboveBed) + { + var face0Normal = item.Mesh.Faces[faceIndex].normal.TransformNormal(matrix).GetNormal(); + var angle = MathHelper.RadiansToDegrees(Math.Acos(face0Normal.Dot(-Vector3Float.UnitZ))); + + if (angle < MaxOverHangAngle) + { + // TODO: consider how much area all supported polygons represent + return true; + } + } + } + } + } + + return false; + } + + private void AddSupportColumn(IObject3D holder, double gridX, double gridY, double bottomZ, double topZ) + { + if (topZ - bottomZ < .01) + { + // less than 10 micros high, don't ad it + return; + } + holder.Children.Add(new GeneratedSupportObject3D() + { + Mesh = PlatonicSolids.CreateCube(PillarSize - reduceAmount, PillarSize - reduceAmount, topZ - bottomZ), + Matrix = Matrix4X4.CreateTranslation(gridX, gridY, bottomZ + (topZ - bottomZ) / 2) + }); + } + } +} \ No newline at end of file diff --git a/MatterControlLib/Library/Export/GCodeExport.cs b/MatterControlLib/Library/Export/GCodeExport.cs index 9d0be476f..56b2fd979 100644 --- a/MatterControlLib/Library/Export/GCodeExport.cs +++ b/MatterControlLib/Library/Export/GCodeExport.cs @@ -40,6 +40,7 @@ using MatterHackers.Agg.Platform; using MatterHackers.Agg.UI; using MatterHackers.DataConverters3D; using MatterHackers.Localizations; +using MatterHackers.MatterControl.DesignTools; using MatterHackers.MatterControl.PartPreviewWindow; using MatterHackers.MatterControl.PrinterCommunication.Io; using MatterHackers.MatterControl.PrintQueue; diff --git a/MatterControlLib/PartPreviewWindow/GenerateSupportPanel.cs b/MatterControlLib/PartPreviewWindow/GenerateSupportPanel.cs index abca92bae..611c0f786 100644 --- a/MatterControlLib/PartPreviewWindow/GenerateSupportPanel.cs +++ b/MatterControlLib/PartPreviewWindow/GenerateSupportPanel.cs @@ -27,10 +27,7 @@ of the authors and should not be interpreted as representing official policies, either expressed or implied, of the FreeBSD Project. */ -using System; using System.Collections.Generic; -using System.Linq; -using System.Threading; using System.Threading.Tasks; using MatterHackers.Agg; using MatterHackers.Agg.UI; @@ -45,42 +42,6 @@ using MatterHackers.VectorMath; namespace MatterHackers.MatterControl.PartPreviewWindow { - public static class FaceListExtensions - { - public static IPrimitive CreateTraceData(this FaceList faceList, List vertexList, int maxRecursion = int.MaxValue) - { - var allPolys = new List(); - - foreach (var face in faceList) - { - allPolys.Add(new TriangleShape(vertexList[face.v0], vertexList[face.v1], vertexList[face.v2], null)); - } - - return BoundingVolumeHierarchy.CreateNewHierachy(allPolys, maxRecursion); - } - - public static IPrimitive CreateTraceData(this FaceList faceList, List vertexList, int maxRecursion = int.MaxValue) - { - var allPolys = new List(); - - foreach (var face in faceList) - { - allPolys.Add(new TriangleShape(vertexList[face.v0], vertexList[face.v1], vertexList[face.v2], null)); - } - - return BoundingVolumeHierarchy.CreateNewHierachy(allPolys, maxRecursion); - } - } - - [HideFromTreeViewAttribute, Immutable] - public class GeneratedSupportObject3D : Object3D - { - public GeneratedSupportObject3D() - { - OutputType = PrintOutputTypes.Support; - } - } - public class GenerateSupportPanel : FlowLayoutWidget { private SupportGenerator supportGenerator; @@ -161,6 +122,22 @@ namespace MatterHackers.MatterControl.PartPreviewWindow theme.ApplyPrimaryActionStyle(generateButton); } + public override void OnKeyDown(KeyEventArgs keyEvent) + { + if (!keyEvent.Handled) + { + switch (keyEvent.KeyCode) + { + case Keys.Enter: + Rebuild(); + keyEvent.Handled = true; + break; + } + } + + base.OnKeyDown(keyEvent); + } + private Task Rebuild() { return ApplicationController.Instance.Tasks.Execute( @@ -169,262 +146,4 @@ namespace MatterHackers.MatterControl.PartPreviewWindow ); } } - - public class SupportGenerator - { - private InteractiveScene scene; - - public SupportGenerator(InteractiveScene scene) - { - this.scene = scene; - } - - public double MaxOverHangAngle - { - get - { - if (UserSettings.Instance.get(UserSettingsKey.SupportMaxOverHangAngle) == null) - { - return 45; - } - var value = UserSettings.Instance.GetValue(UserSettingsKey.SupportMaxOverHangAngle); - if (value < 0) - { - return 0; - } - if (value > 90) - { - value = 90; - } - - return value; - } - - set - { - UserSettings.Instance.set(UserSettingsKey.SupportMaxOverHangAngle, value.ToString()); - } - } - - public double PillarSize - { - get - { - var value = UserSettings.Instance.GetValue(UserSettingsKey.SupportPillarSize); - if (value < 1.5) - { - return 1.5; - } - - return value; - } - set - { - UserSettings.Instance.set(UserSettingsKey.SupportPillarSize, value.ToString()); - } - } - - /// - /// The amount to reduce the pillars so they are separated in the 3D view - /// - private double reduceAmount => .99; - - public Task Create(IProgress progress, CancellationToken cancelationToken) - { - // Get visible meshes for each of them - var visibleMeshes = scene.Children.SelectMany(i => i.VisibleMeshes()); - - var selectedItem = scene.SelectedItem; - if (selectedItem != null) - { - visibleMeshes = selectedItem.VisibleMeshes(); - } - - var supportCandidates = visibleMeshes.Where(i => i.OutputType != PrintOutputTypes.Support); - - // find all the faces that are candidates for support - var upVerts = new List(); - var upFaces = new FaceList(); - var downVerts = new List(); - var downFaces = new FaceList(); - foreach (var item in supportCandidates) - { - var matrix = item.WorldMatrix(scene); - for (int faceIndex = 0; faceIndex < item.Mesh.Faces.Count; faceIndex++) - { - var face0Normal = item.Mesh.Faces[faceIndex].normal.TransformNormal(matrix).GetNormal(); - var angle = MathHelper.RadiansToDegrees(Math.Acos(face0Normal.Dot(-Vector3Float.UnitZ))); - - if (angle <= MaxOverHangAngle) - { - var face = item.Mesh.Faces[faceIndex]; - var verts = new int[] { face.v0, face.v1, face.v2 }; - var fc = downVerts.Count; - downVerts.Add(item.Mesh.Vertices[face.v0].Transform(matrix)); - downVerts.Add(item.Mesh.Vertices[face.v1].Transform(matrix)); - downVerts.Add(item.Mesh.Vertices[face.v2].Transform(matrix)); - - downFaces.Add(fc, fc + 1, fc + 2, downVerts); - } - - if (angle > 0) - { - var face = item.Mesh.Faces[faceIndex]; - var verts = new int[] { face.v0, face.v1, face.v2 }; - var fc = upFaces.Count; - upVerts.Add(item.Mesh.Vertices[face.v0].Transform(matrix)); - upVerts.Add(item.Mesh.Vertices[face.v1].Transform(matrix)); - upVerts.Add(item.Mesh.Vertices[face.v2].Transform(matrix)); - - upFaces.Add(fc, fc + 1, fc + 2, upVerts); - } - } - } - - if (downFaces.Count > 0) - { - var downTraceData = downFaces.CreateTraceData(downVerts, 0); - var upTraceData = upFaces.CreateTraceData(upVerts, 0); - - // get the bounds of all verts - var bounds = downVerts.Bounds(); - - // create the gird of possible support - var gridBounds = new RectangleDouble(Math.Floor((double)(bounds.MinXYZ.X / PillarSize)), - Math.Floor((double)(bounds.MinXYZ.Y / PillarSize)), - Math.Ceiling(bounds.MaxXYZ.X / PillarSize), - Math.Ceiling(bounds.MaxXYZ.Y / PillarSize)); - - var supportGrid = new List>((int)(gridBounds.Width * gridBounds.Height)); - - IObject3D holder = new Object3D(); - - // at the center of every grid item add in a list of all the top faces to look down from - for (int y = 0; y < gridBounds.Height; y++) - { - var yPos = (gridBounds.Bottom + y) * PillarSize; - for (int x = 0; x < gridBounds.Width; x++) - { - var xPos = (gridBounds.Left + x) * PillarSize; - IntersectInfo upHit = null; - var upRay = new Ray(new Vector3(xPos, yPos, 0), Vector3.UnitZ, intersectionType: IntersectionType.Both); - do - { - upHit = downTraceData.GetClosestIntersection(upRay); - if (upHit != null) - { - // we found a ceiling above this spot, look down from that to find the first floor - var downRay = new Ray(new Vector3(upHit.HitPosition.X, upHit.HitPosition.Y, upHit.HitPosition.Z - .001), -Vector3.UnitZ, intersectionType: IntersectionType.Both); - var downHit = upTraceData.GetClosestIntersection(downRay); - if (downHit != null) - { - AddSupportColumn(holder, downHit.HitPosition.X, downHit.HitPosition.Y, downHit.HitPosition.Z, upHit.HitPosition.Z); - } - else - { - // did not find a hit, go to the bed - AddSupportColumn(holder, upHit.HitPosition.X, upHit.HitPosition.Y, upRay.origin.Z, upHit.HitPosition.Z); - } - - // make a new ray just past the last hit to keep looking for up hits - upRay = new Ray(new Vector3(xPos, yPos, upHit.HitPosition.Z + .001), Vector3.UnitZ, intersectionType: IntersectionType.Both); - } - } while (upHit != null); - } - } - - // foreach face set the support heights in the overlapped support grid - // foreach grid column that has data - // trace down from the top to the first bottom hit (or bed) - // add a support column - var first = downFaces.First(); - var position = downVerts[first.v0]; - //AddSupportColumn(position.X, position.Y, position.Z, 0); - - scene.Children.Modify(list => - { - list.AddRange(holder.Children); - }); - } - - // this is the theory for regions rather than pillars - // separate the faces into face patch groups (these are the new support tops) - // project all the vertices of each patch group down until they hit an up face in the scene (or 0) - // make a new patch group at the z of the hit (these will be the bottoms) - // find the outline of the patch groups (these will be the walls of the top and bottom patches - // make a new mesh object with the top, bottom and walls, add it to the scene and mark it as support - - return Task.CompletedTask; - } - - public void RemoveExisting() - { - var existingSupports = scene.Children.Where(i => i.GetType() == typeof(GeneratedSupportObject3D)); - - scene.Children.Modify((list) => - { - foreach (var item in existingSupports) - { - list.Remove(item); - } - }); - } - - public bool RequiresSupport() - { - bool supportInScene = scene.VisibleMeshes().Any(i => i.WorldOutputType() == PrintOutputTypes.Support); - if (!supportInScene) - { - // there is no support in the scene check if there are faces that require support - var supportCandidates = scene.VisibleMeshes().Where(i => i.OutputType != PrintOutputTypes.Support); - - // find all the faces that are candidates for support - foreach (var item in supportCandidates) - { - var matrix = item.WorldMatrix(scene); - for (int faceIndex = 0; faceIndex < item.Mesh.Faces.Count; faceIndex++) - { - bool aboveBed = false; - var face = item.Mesh.Faces[faceIndex]; - var verts = new int[] { face.v0, face.v1, face.v2 }; - foreach (var vertex in verts) - { - if (item.Mesh.Vertices[vertex].Transform(matrix).Z > .01) - { - aboveBed = true; - break; - } - } - if (aboveBed) - { - var face0Normal = item.Mesh.Faces[faceIndex].normal.TransformNormal(matrix).GetNormal(); - var angle = MathHelper.RadiansToDegrees(Math.Acos(face0Normal.Dot(-Vector3Float.UnitZ))); - - if (angle < MaxOverHangAngle) - { - // TODO: consider how much area all supported polygons represent - return true; - } - } - } - } - } - - return false; - } - - private void AddSupportColumn(IObject3D holder, double gridX, double gridY, double bottomZ, double topZ) - { - if (topZ - bottomZ < .01) - { - // less than 10 micros high, don't ad it - return; - } - holder.Children.Add(new GeneratedSupportObject3D() - { - Mesh = PlatonicSolids.CreateCube(PillarSize - reduceAmount, PillarSize - reduceAmount, topZ - bottomZ), - Matrix = Matrix4X4.CreateTranslation(gridX, gridY, bottomZ + (topZ - bottomZ) / 2) - }); - } - } } \ No newline at end of file diff --git a/Submodules/agg-sharp b/Submodules/agg-sharp index c9136949a..a569521e6 160000 --- a/Submodules/agg-sharp +++ b/Submodules/agg-sharp @@ -1 +1 @@ -Subproject commit c9136949a147eee728294b80aeb752432cf3222d +Subproject commit a569521e61caab785d2bfc533cf1dee8a169a2ed diff --git a/Tests/MatterControl.Tests/MatterControl.Tests.csproj b/Tests/MatterControl.Tests/MatterControl.Tests.csproj index 89ca30e92..7c0499f5e 100644 --- a/Tests/MatterControl.Tests/MatterControl.Tests.csproj +++ b/Tests/MatterControl.Tests/MatterControl.Tests.csproj @@ -65,6 +65,7 @@ + diff --git a/Tests/MatterControl.Tests/MatterControl/SupportGeneratorTests.cs b/Tests/MatterControl.Tests/MatterControl/SupportGeneratorTests.cs new file mode 100644 index 000000000..833d8533f --- /dev/null +++ b/Tests/MatterControl.Tests/MatterControl/SupportGeneratorTests.cs @@ -0,0 +1,47 @@ +/* +Copyright (c) 2016, Lars Brubaker, John Lewin +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + +using MatterHackers.DataConverters3D; +using MatterHackers.MatterControl.DesignTools; +using NUnit.Framework; + +namespace MatterControl.Tests.MatterControl +{ + [TestFixture] + public class SupportGeneratorTests + { + [Test, Category("InteractiveScene")] + public void SupportExtentsTests() + { + // make a cube in the air and ensure that no mater where it is placed, support is always under the entire extents + InteractiveScene scene = new InteractiveScene(); + var supportGenerator = new SupportGenerator(scene); + } + } +}