diff --git a/DesignTools/Operations/Object3DExtensions.cs b/DesignTools/Operations/Object3DExtensions.cs index b5c901f5d..c39ea4ae5 100644 --- a/DesignTools/Operations/Object3DExtensions.cs +++ b/DesignTools/Operations/Object3DExtensions.cs @@ -64,6 +64,31 @@ namespace MatterHackers.MatterControl.DesignTools.Operations return resultsA; } + public static IObject3D Plus(this IObject3D a, IObject3D b) + { + var results = new Object3D(); + + results.Children.Add(a.Clone()); + results.Children.Add(b.Clone()); + + return results; + } + + public static double XSize(this IObject3D item) + { + return item.GetAxisAlignedBoundingBox().XSize; + } + + public static double YSize(this IObject3D item) + { + return item.GetAxisAlignedBoundingBox().YSize; + } + + public static double ZSize(this IObject3D item) + { + return item.GetAxisAlignedBoundingBox().ZSize; + } + public static void AddSelectionAsChildren(this InteractiveScene scene, IObject3D newParent) { if (scene.HasSelection) diff --git a/DesignTools/Primitives/CubeObject3D.cs b/DesignTools/Primitives/CubeObject3D.cs index 5fdd31f0e..f1b5fb721 100644 --- a/DesignTools/Primitives/CubeObject3D.cs +++ b/DesignTools/Primitives/CubeObject3D.cs @@ -32,110 +32,20 @@ using MatterHackers.PolygonMesh; namespace MatterHackers.MatterControl.DesignTools { - /* - -public class ChairFoot2 : MatterCadObject3D -{ - public ChairFoot() - { - Rebuild(); - } - - [DisplayName("Angle")] - public double AngleDegrees { get; set; } = 3; - - // these are the public variables that would be edited - [DisplayName("Final")] - public bool FinalPart { get; set; } = true; - - [DisplayName("Height")] - public double HeightFromFloorToBottomOfLeg { get; set; } = 10; - - [DisplayName("Inner Size")] - public double InnerSize { get; set; } = 20; - - [DisplayName("Reach")] - public double InsideReach { get; set; } = 10; - - [DisplayName("Outer Size")] - public double OuterSize { get; set; } = 22; - - public void Rebuild() - { - // This would be better expressed as the desired offset height (height from ground to bottom of chair leg). - double angleRadians = MathHelper.DegreesToRadians(AngleDegrees); - double extraHeightForRotation = Math.Sinh(angleRadians) * OuterSize; // get the distance to clip off the extra bottom - double unclippedFootHeight = HeightFromFloorToBottomOfLeg + extraHeightForRotation; - - if (FinalPart) - { - Box chairFootBox = new Box(OuterSize, OuterSize, unclippedFootHeight); - //chairFootBox.BevelEdge(Edge.LeftBack, 2); - //chairFootBox.BevelEdge(Edge.LeftFront, 2); - //chairFootBox.BevelEdge(Edge.RightBack, 2); - //chairFootBox.BevelEdge(Edge.RightFront, 2); - IObject3D chairFoot = chairFootBox; - - IObject3D ring = new Cylinder(InnerSize / 2 - 1, InsideReach, 30); - ring -= new Cylinder(ring.XSize / 2 - 2, ring.ZSize + 1, 30); - - IObject3D fins = new Box(3, 1, ring.ZSize); - fins = new Translate(fins, 0, 1) + new Translate(fins, 0, -1); - fins -= new Align(new Rotate(new Box(5, 5, 5), 0, MathHelper.DegreesToRadians(45)), Face.Bottom | Face.Left, fins, Face.Top | Face.Left, 0, 0, -fins.XSize); - fins = new Translate(fins, InnerSize / 2 - .1); - - ring += new Rotate(fins, 0, 0, MathHelper.DegreesToRadians(45)); - ring += new Rotate(fins, 0, 0, MathHelper.DegreesToRadians(45 + 90)); - ring += new Rotate(fins, 0, 0, MathHelper.DegreesToRadians(45 + 180)); - ring += new Rotate(fins, 0, 0, MathHelper.DegreesToRadians(45 - 90)); - - chairFoot += new Align(ring, Face.Bottom, chairFoot, Face.Top, 0, 0, -.1); - - chairFoot = new Rotate(chairFoot, 0, angleRadians, 0); - IObject3D clipBox = new Align(new Box(OuterSize * 2, OuterSize * 2, unclippedFootHeight), Face.Top, chairFoot, Face.Bottom, 0, 0, extraHeightForRotation); - chairFoot -= clipBox; - chairFoot = new Translate(chairFoot, 0, 0, clipBox.GetAxisAlignedBoundingBox().maxXYZ.Z); - - this.Mesh = CsgToMesh.Convert(chairFoot); - } - else // fit part - { - double baseHeight = 3; - double insideHeight = 4; - Box chairFootBox = new Box(OuterSize, OuterSize, baseHeight); - chairFootBox.BevelEdge(Edge.LeftBack, 2); - chairFootBox.BevelEdge(Edge.LeftFront, 2); - chairFootBox.BevelEdge(Edge.RightBack, 2); - chairFootBox.BevelEdge(Edge.RightFront, 2); - IObject3D chairFoot = chairFootBox; - - IObject3D ring = new Cylinder(InnerSize / 2 - 1, insideHeight, 30); - ring -= new Cylinder(ring.XSize / 2 - 2, ring.ZSize + 1, 30); - - IObject3D fins = new Box(3, 1, ring.ZSize); - fins = new Translate(fins, 0, 1) + new Translate(fins, 0, -1); - fins -= new Align(new Rotate(new Box(5, 5, 5), 0, MathHelper.DegreesToRadians(45)), Face.Bottom | Face.Left, fins, Face.Top | Face.Left, 0, 0, -fins.XSize); - fins = new Translate(fins, InnerSize / 2 - .1); - - ring += new Rotate(fins, 0, 0, MathHelper.DegreesToRadians(45)); - ring += new Rotate(fins, 0, 0, MathHelper.DegreesToRadians(45 + 90)); - ring += new Rotate(fins, 0, 0, MathHelper.DegreesToRadians(45 + 180)); - ring += new Rotate(fins, 0, 0, MathHelper.DegreesToRadians(45 - 90)); - - chairFoot += new Align(ring, Face.Bottom, chairFoot, Face.Top, 0, 0, -.1); - - this.Mesh = CsgToMesh.Convert(chairFoot); - } - } -} -*/ - public class CubeObject3D : Object3D, IRebuildable { public CubeObject3D() { } + public CubeObject3D(double width, double depth, double height) + { + Width = width; + Depth = depth; + Height = height; + Rebuild(); + } + public override string ActiveEditor => "PublicPropertyEditor"; public double Width { get; set; } = 20; diff --git a/DesignTools/Primitives/CylinderObject3D.cs b/DesignTools/Primitives/CylinderObject3D.cs index 0bc4d358b..923fc425b 100644 --- a/DesignTools/Primitives/CylinderObject3D.cs +++ b/DesignTools/Primitives/CylinderObject3D.cs @@ -43,6 +43,15 @@ namespace MatterHackers.MatterControl.DesignTools { } + public CylinderObject3D(double diameter, double height, int sides) + { + Diameter = diameter; + Height = height; + Sides = sides; + + Rebuild(); + } + public static CylinderObject3D Create() { var item = new CylinderObject3D(); @@ -60,10 +69,10 @@ namespace MatterHackers.MatterControl.DesignTools var aabb = this.GetAxisAlignedBoundingBox(); var path = new VertexStorage(); - path.MoveTo(0, 0); - path.LineTo(Diameter / 2, 0); - path.LineTo(Diameter / 2, Height); - path.LineTo(0, Height); + path.MoveTo(0, -Height / 2); + path.LineTo(Diameter / 2, -Height / 2); + path.LineTo(Diameter / 2, Height / 2); + path.LineTo(0, Height / 2); Mesh = VertexSourceToMesh.Revolve(path, Sides); diff --git a/Library/Export/StlExport.cs b/Library/Export/StlExport.cs index bc37cd313..5bb30e2b8 100644 --- a/Library/Export/StlExport.cs +++ b/Library/Export/StlExport.cs @@ -58,7 +58,7 @@ namespace MatterHackers.MatterControl.Library.Export public Task Generate(IEnumerable libraryItems, string outputPath) { - if (libraryItems.OfType().FirstOrDefault() is ILibraryAssetStream libraryItem) + if (libraryItems.OfType().FirstOrDefault() is ILibraryAsset libraryItem) { return MeshExport.ExportMesh(libraryItem, outputPath); } diff --git a/PartPreviewWindow/SelectedObjectPanel.cs b/PartPreviewWindow/SelectedObjectPanel.cs index 3539801a2..213afd59a 100644 --- a/PartPreviewWindow/SelectedObjectPanel.cs +++ b/PartPreviewWindow/SelectedObjectPanel.cs @@ -129,6 +129,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow BackgroundColor = theme.MinimalShade, Margin = theme.ButtonSpacing }; + scene.SelectionChanged += (s, e) => editButton.Enabled = scene.SelectedItem?.CanEdit == true; editButton.Click += async (s, e) => { var bed = new BedConfig(); diff --git a/PartPreviewWindow/View3D/Actions/CombineEditor.cs b/PartPreviewWindow/View3D/Actions/CombineEditor.cs index 6aff54524..f76aaee2e 100644 --- a/PartPreviewWindow/View3D/Actions/CombineEditor.cs +++ b/PartPreviewWindow/View3D/Actions/CombineEditor.cs @@ -76,57 +76,68 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D private void ProcessBooleans(IObject3D group) { + // spin up a task to remove holes from the objects in the group ApplicationController.Instance.Tasks.Execute( - "Processing Booleans".Localize(), - (reporter, cancellationToken) => - { - var progressStatus = new ProgressStatus(); - reporter.Report(progressStatus); - - var participants = group.DescendantsAndSelf().Where((obj) => obj.OwnerID == group.ID); - - if (participants.Count() > 1) + "Combine".Localize(), + (reporter, cancellationToken) => { - var first = participants.First(); + var progressStatus = new ProgressStatus(); + reporter.Report(progressStatus); - var totalOperations = participants.Count()-1; - double amountPerOperation = 1.0 / totalOperations; - double percentCompleted = 0; + var participants = group.Descendants().Where(o => o.OwnerID == group.ID).ToList(); - foreach (var remove in participants) + if (participants.Count() > 1) { - if (remove != first) - { - var transformedRemove = Mesh.Copy(remove.Mesh, CancellationToken.None); - transformedRemove.Transform(remove.WorldMatrix()); - - var transformedKeep = Mesh.Copy(first.Mesh, CancellationToken.None); - transformedKeep.Transform(first.WorldMatrix()); - - transformedKeep = PolygonMesh.Csg.CsgOperations.Union(transformedKeep, transformedRemove, (status, progress0To1) => - { - // Abort if flagged - cancellationToken.ThrowIfCancellationRequested(); - - progressStatus.Status = status; - progressStatus.Progress0To1 = percentCompleted + amountPerOperation * progress0To1; - reporter.Report(progressStatus); - }, cancellationToken); - var inverse = first.WorldMatrix(); - inverse.Invert(); - transformedKeep.Transform(inverse); - first.Mesh = transformedKeep; - remove.Visible = false; - - percentCompleted += amountPerOperation; - progressStatus.Progress0To1 = percentCompleted; - reporter.Report(progressStatus); - } + Combine(participants, cancellationToken, reporter); } - } + return Task.CompletedTask; + }); + } - return Task.CompletedTask; - }); + public static void Combine(List participants) + { + Combine(participants, CancellationToken.None, null); + } + + public static void Combine(List participants, CancellationToken cancellationToken, IProgress reporter) + { + var first = participants.First(); + + var totalOperations = participants.Count() - 1; + double amountPerOperation = 1.0 / totalOperations; + double percentCompleted = 0; + + ProgressStatus progressStatus = new ProgressStatus(); + foreach (var remove in participants) + { + if (remove != first) + { + var transformedRemove = Mesh.Copy(remove.Mesh, CancellationToken.None); + transformedRemove.Transform(remove.WorldMatrix()); + + var transformedKeep = Mesh.Copy(first.Mesh, CancellationToken.None); + transformedKeep.Transform(first.WorldMatrix()); + + transformedKeep = PolygonMesh.Csg.CsgOperations.Union(transformedKeep, transformedRemove, (status, progress0To1) => + { + // Abort if flagged + cancellationToken.ThrowIfCancellationRequested(); + + progressStatus.Status = status; + progressStatus.Progress0To1 = percentCompleted + amountPerOperation * progress0To1; + reporter.Report(progressStatus); + }, cancellationToken); + var inverse = first.WorldMatrix(); + inverse.Invert(); + transformedKeep.Transform(inverse); + first.Mesh = transformedKeep; + remove.Visible = false; + + percentCompleted += amountPerOperation; + progressStatus.Progress0To1 = percentCompleted; + reporter.Report(progressStatus); + } + } } } } diff --git a/Submodules/agg-sharp b/Submodules/agg-sharp index bea8649f3..c82ba50c8 160000 --- a/Submodules/agg-sharp +++ b/Submodules/agg-sharp @@ -1 +1 @@ -Subproject commit bea8649f3e1545c106b93e7bb9c2d18dec7c0332 +Subproject commit c82ba50c84e6e8f24f2d4fffcd4a9404fc0bd889