From c2a8ed5762d67d4eacb2b26f85a84cfb20379fa4 Mon Sep 17 00:00:00 2001 From: Lars Brubaker Date: Fri, 20 Aug 2021 09:57:38 -0700 Subject: [PATCH] New ImageConverter has reached first ship candidate --- .../ApplicationView/SceneOperations.cs | 2 - .../DesignTools/Attributes/SliderAttribute.cs | 48 +++++++++++++++++++ .../DesignTools/LithophaneObject3D.cs | 2 +- .../DesignTools/Obsolete/CurveObject3D.cs | 4 +- .../DesignTools/Operations/CurveObject3D_2.cs | 4 +- .../DesignTools/Operations/CurveObject3D_3.cs | 4 +- .../Operations/Image/ImageToPathObject3D.cs | 4 +- .../Operations/Image/ImageToPathObject3D_2.cs | 47 +++++++++++++----- .../PartPreviewWindow/SelectedObjectPanel.cs | 6 ++- 9 files changed, 95 insertions(+), 26 deletions(-) create mode 100644 MatterControlLib/DesignTools/Attributes/SliderAttribute.cs diff --git a/MatterControlLib/ApplicationView/SceneOperations.cs b/MatterControlLib/ApplicationView/SceneOperations.cs index 922469221..480700aed 100644 --- a/MatterControlLib/ApplicationView/SceneOperations.cs +++ b/MatterControlLib/ApplicationView/SceneOperations.cs @@ -322,8 +322,6 @@ namespace MatterHackers.MatterControl "$.Children.Children.Children.Children.AnalysisType", "$.Children.Children.Children.Children.TransparencyMessage", "$.Children.Children.Children.Children.Histogram", - "$.Children.Children.Height", - "$.Children.Children.Children.SmoothDistance", "$.Children", } }; diff --git a/MatterControlLib/DesignTools/Attributes/SliderAttribute.cs b/MatterControlLib/DesignTools/Attributes/SliderAttribute.cs new file mode 100644 index 000000000..f82742540 --- /dev/null +++ b/MatterControlLib/DesignTools/Attributes/SliderAttribute.cs @@ -0,0 +1,48 @@ +/* +Copyright (c) 2018, 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; + +namespace MatterHackers.MatterControl.DesignTools +{ + [AttributeUsage(AttributeTargets.Property)] + public class SliderAttribute : Attribute + { + public SliderAttribute(double min, double max, double increment) + { + this.Min = min; + this.Max = max; + this.Incement = increment; + } + + public double Min { get; set; } + public double Max { get; set; } + public double Incement { get; set; } + } +} \ No newline at end of file diff --git a/MatterControlLib/DesignTools/LithophaneObject3D.cs b/MatterControlLib/DesignTools/LithophaneObject3D.cs index c2677bdd0..2d4c54479 100644 --- a/MatterControlLib/DesignTools/LithophaneObject3D.cs +++ b/MatterControlLib/DesignTools/LithophaneObject3D.cs @@ -57,7 +57,7 @@ namespace MatterHackers.MatterControl.Plugins.Lithophane [DisplayName("Pixels Per mm"), Range(0.5, 3, ErrorMessage = "Value for {0} must be between {1} and {2}.")] public double PixelsPerMM { get; set; } = 1.5; - [Range(0.5, 3, ErrorMessage = "Value for {0} must be between {1} and {2}.")] + [Slider(0.5, 3, .2)] public double Height { get; set; } = 2.5; public int Width { get; set; } = 150; diff --git a/MatterControlLib/DesignTools/Obsolete/CurveObject3D.cs b/MatterControlLib/DesignTools/Obsolete/CurveObject3D.cs index d735969c8..e6eb9373d 100644 --- a/MatterControlLib/DesignTools/Obsolete/CurveObject3D.cs +++ b/MatterControlLib/DesignTools/Obsolete/CurveObject3D.cs @@ -68,11 +68,11 @@ namespace MatterHackers.MatterControl.DesignTools public double Diameter { get; set; } = double.MinValue; - [Range(3, 360, ErrorMessage = "Value for {0} must be between {1} and {2}.")] + [Slider(3, 360, 1)] [Description("Ensures the rotated part has a minimum number of sides per complete rotation")] public double MinSidesPerRotation { get; set; } = 3; - [Range(0, 100, ErrorMessage = "Value for {0} must be between {1} and {2}.")] + [Slider(0, 100, 1)] [Description("Where to start the bend as a percent of the width of the part")] public double StartPercent { get; set; } = 50; diff --git a/MatterControlLib/DesignTools/Operations/CurveObject3D_2.cs b/MatterControlLib/DesignTools/Operations/CurveObject3D_2.cs index c5d4f2e72..908622cc3 100644 --- a/MatterControlLib/DesignTools/Operations/CurveObject3D_2.cs +++ b/MatterControlLib/DesignTools/Operations/CurveObject3D_2.cs @@ -64,11 +64,11 @@ namespace MatterHackers.MatterControl.DesignTools public double Diameter { get; set; } = double.MaxValue; - [Range(3, 360, ErrorMessage = "Value for {0} must be between {1} and {2}.")] + [Slider(3, 360, 1)] [Description("Ensures the rotated part has a minimum number of sides per complete rotation")] public double MinSidesPerRotation { get; set; } = 30; - [Range(0, 100, ErrorMessage = "Value for {0} must be between {1} and {2}.")] + [Slider(0, 100, 1)] [Description("Where to start the bend as a percent of the width of the part")] public double StartPercent { get; set; } = 50; diff --git a/MatterControlLib/DesignTools/Operations/CurveObject3D_3.cs b/MatterControlLib/DesignTools/Operations/CurveObject3D_3.cs index 0cce436ba..7fe5853db 100644 --- a/MatterControlLib/DesignTools/Operations/CurveObject3D_3.cs +++ b/MatterControlLib/DesignTools/Operations/CurveObject3D_3.cs @@ -86,7 +86,7 @@ namespace MatterHackers.MatterControl.DesignTools [DescriptionImage("https://lh3.googleusercontent.com/h-s2FyBKO5etYDr_9YSLtGmGmQTcmSGMu4p0mRqX4_7Z62Ndn2QRLoFICC6X9scbhr1EP29RiYRj4EmhLMUwiNTAG-PIiFbzI_jAses")] public BendDirections BendDirection { get; set; } = BendDirections.Bend_Up; - [Range(0, 100, ErrorMessage = "Value for {0} must be between {1} and {2}.")] + [Slider(0, 100, 1)] [Description("Where to start the bend as a percent from the left side")] [DescriptionImage("https://lh3.googleusercontent.com/eOeWjr98uz_E924PnNaXrasepv15nWEuvhqH-jbaQyvrOVdX5MHXF00HdZQGC8NLpJc9ok1sToMtyPx1wnnDgFwTTGA5MjoMFu612AY1")] public double StartPercent { get; set; } = 50; @@ -95,7 +95,7 @@ namespace MatterHackers.MatterControl.DesignTools [Description("Split the mesh so it has enough geometry to create a smooth curve")] public bool SplitMesh { get; set; } = true; - [Range(3, 360, ErrorMessage = "Value for {0} must be between {1} and {2}.")] + [Slider(3, 360, 1)] [Description("Ensures the rotated part has a minimum number of sides per complete rotation")] [DescriptionImage("https://lh3.googleusercontent.com/p9MyKu3AFP55PnobUKZQPqf6iAx11GzXyX-25f1ddrUnfCt8KFGd1YtHOR5HqfO0mhlX2ZVciZV4Yn0Kzfm43SErOS_xzgsESTu9scux")] public double MinSidesPerRotation { get; set; } = 30; diff --git a/MatterControlLib/DesignTools/Operations/Image/ImageToPathObject3D.cs b/MatterControlLib/DesignTools/Operations/Image/ImageToPathObject3D.cs index 47fd2ff6e..957524931 100644 --- a/MatterControlLib/DesignTools/Operations/Image/ImageToPathObject3D.cs +++ b/MatterControlLib/DesignTools/Operations/Image/ImageToPathObject3D.cs @@ -173,10 +173,10 @@ namespace MatterHackers.MatterControl.DesignTools [JsonIgnore] private ImageBuffer Image => this.Descendants().FirstOrDefault()?.Image; - [Range(0, 1, ErrorMessage = "Value for {0} must be between {1} and {2}.")] + [Slider(0, 1, .05)] public DoubleOrExpression RangeStart { get; set; } = .1; - [Range(0, 1, ErrorMessage = "Value for {0} must be between {1} and {2}.")] + [Slider(0, 1, .05)] public DoubleOrExpression RangeEnd { get; set; } = 1; public IVertexSource VertexSource { get; set; } = new VertexStorage(); diff --git a/MatterControlLib/DesignTools/Operations/Image/ImageToPathObject3D_2.cs b/MatterControlLib/DesignTools/Operations/Image/ImageToPathObject3D_2.cs index 76a093256..a1f398f7b 100644 --- a/MatterControlLib/DesignTools/Operations/Image/ImageToPathObject3D_2.cs +++ b/MatterControlLib/DesignTools/Operations/Image/ImageToPathObject3D_2.cs @@ -116,7 +116,7 @@ namespace MatterHackers.MatterControl.DesignTools } - private AnalysisTypes _featureDetector = AnalysisTypes.Intensity; + private AnalysisTypes _featureDetector = AnalysisTypes.Intensity; [EnumDisplay(Mode = EnumDisplayAttribute.PresentationMode.Tabs)] public AnalysisTypes AnalysisType { @@ -162,6 +162,10 @@ namespace MatterHackers.MatterControl.DesignTools [DisplayName("Select Range")] public Histogram Histogram { get; set; } = new Histogram(); + [Slider(0, 10, 1)] + [Description("The minimum area each loop needs to be for inclusion")] + public double MinSurfaceArea {get; set; } = 1; + public IVertexSource VertexSource { get; set; } = new VertexStorage(); public void AddObject3DControls(Object3DControlsLayer object3DControlsLayer) @@ -181,7 +185,7 @@ namespace MatterHackers.MatterControl.DesignTools this.FlattenToPathObject(undoBuffer); } - public void GenerateMarchingSquaresAndLines(Action progressReporter, ImageBuffer image, IThresholdFunction thresholdFunction) + public void GenerateMarchingSquaresAndLines(Action progressReporter, ImageBuffer image, IThresholdFunction thresholdFunction, int minimumSurfaceArea) { if (image != null) { @@ -200,34 +204,48 @@ namespace MatterHackers.MatterControl.DesignTools int pixelsToIntPointsScale = 1000; var lineLoops = marchingSquaresData.CreateLineLoops(pixelsToIntPointsScale); + if (minimumSurfaceArea > 0) + { + for(int i=lineLoops.Count - 1; i >=0; i--) + { + var area = Math.Abs(Clipper.Area(lineLoops[i])); + if (area < minimumSurfaceArea) + { + lineLoops.RemoveAt(i); + } + } + } + progressReporter?.Invoke(.15, null); var min = new IntPoint(-10, -10); var max = new IntPoint(10 + image.Width * pixelsToIntPointsScale, 10 + image.Height * pixelsToIntPointsScale); - var boundingPoly = new Polygon(); - boundingPoly.Add(min); - boundingPoly.Add(new IntPoint(min.X, max.Y)); - boundingPoly.Add(max); - boundingPoly.Add(new IntPoint(max.X, min.Y)); + var boundingPoly = new Polygon + { + min, + new IntPoint(min.X, max.Y), + max, + new IntPoint(max.X, min.Y) + }; // now clip the polygons to get the inside and outside polys var clipper = new Clipper(); clipper.AddPaths(lineLoops, PolyType.ptSubject, true); clipper.AddPath(boundingPoly, PolyType.ptClip, true); - var polygonShape = new Polygons(); + var polygonShapes = new Polygons(); progressReporter?.Invoke(.3, null); - clipper.Execute(ClipType.ctIntersection, polygonShape); + clipper.Execute(ClipType.ctIntersection, polygonShapes); progressReporter?.Invoke(.55, null); - polygonShape = Clipper.CleanPolygons(polygonShape, 100); + polygonShapes = Clipper.CleanPolygons(polygonShapes, 100); progressReporter?.Invoke(.75, null); - VertexStorage rawVectorShape = polygonShape.PolygonToPathStorage(); + VertexStorage rawVectorShape = polygonShapes.PolygonToPathStorage(); var aabb = this.VisibleMeshes().FirstOrDefault().GetAxisAlignedBoundingBox(); var xScale = aabb.XSize / image.Width; @@ -295,7 +313,8 @@ namespace MatterHackers.MatterControl.DesignTools reporter.Report(progressStatus); }, SourceImage, - new AlphaFunction()); + new AlphaFunction(), + (int)(MinSurfaceArea * 1000)); break; case AnalysisTypes.Colors: @@ -308,7 +327,8 @@ namespace MatterHackers.MatterControl.DesignTools reporter.Report(progressStatus); }, alphaImage, - new AlphaFunction()); + new AlphaFunction(), + (int)(Math.Pow(MinSurfaceArea * 1000, 2))); break; } @@ -334,6 +354,7 @@ namespace MatterHackers.MatterControl.DesignTools public void UpdateControls(PublicPropertyChange change) { change.SetRowVisible(nameof(Histogram), () => AnalysisType != AnalysisTypes.Transparency); + change.SetRowVisible(nameof(MinSurfaceArea), () => AnalysisType != AnalysisTypes.Transparency); change.SetRowVisible(nameof(TransparencyMessage), () => AnalysisType == AnalysisTypes.Transparency); } } diff --git a/MatterControlLib/PartPreviewWindow/SelectedObjectPanel.cs b/MatterControlLib/PartPreviewWindow/SelectedObjectPanel.cs index 66d87e5ff..046c2ccb6 100644 --- a/MatterControlLib/PartPreviewWindow/SelectedObjectPanel.cs +++ b/MatterControlLib/PartPreviewWindow/SelectedObjectPanel.cs @@ -305,6 +305,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow if (selectedItem is ComponentObject3D componentObject && componentObject.Finalized) { + var context = new PPEContext(); PublicPropertyEditor.AddUnlockLinkIfRequired(selectedItem, editorPanel, theme); foreach (var selector in componentObject.SurfacedEditors) { @@ -356,8 +357,6 @@ namespace MatterHackers.MatterControl.PartPreviewWindow } else if (JsonPathContext.ReflectionValueSystem.LastMemberValue is ReflectionTarget reflectionTarget) { - var context = new PPEContext(); - if (reflectionTarget.Source is IObject3D editedChild) { context.item = editedChild; @@ -374,6 +373,9 @@ namespace MatterHackers.MatterControl.PartPreviewWindow { editorPanel.AddChild(editor); } + + // Init with custom 'UpdateControls' hooks + (context.item as IPropertyGridModifier)?.UpdateControls(new PublicPropertyChange(context, "Update_Button")); } } }