Getting image path generation and extrude working with rebuild
This commit is contained in:
parent
ae6864a6da
commit
46dc1210be
17 changed files with 787 additions and 20 deletions
|
|
@ -789,6 +789,58 @@ namespace MatterHackers.MatterControl
|
|||
this.Graph = new GraphConfig();
|
||||
this.Library.ContentProviders.Add(new[] { "stl", "obj", "amf", "mcx" }, new MeshContentProvider());
|
||||
this.Library.ContentProviders.Add("gcode", new GCodeContentProvider());
|
||||
this.Library.ContentProviders.Add(new[] { "png", "gif", "jpg", "jpeg" }, new ImageContentProvider());
|
||||
|
||||
this.Graph.RegisterOperation(
|
||||
typeof(ImageObject3D),
|
||||
"Image to Path".Localize(),
|
||||
(sceneItem, scene) =>
|
||||
{
|
||||
if (sceneItem is IObject3D imageObject)
|
||||
{
|
||||
var path = new ImageToPath();
|
||||
sceneItem.WrapWith(path, scene);
|
||||
path.Rebuild(null);
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
},
|
||||
(sceneItem) => true,
|
||||
(sceneItem) => true);
|
||||
|
||||
this.Graph.RegisterOperation(
|
||||
typeof(IPathObject),
|
||||
"Linear Extrude".Localize(),
|
||||
(sceneItem, scene) =>
|
||||
{
|
||||
if (sceneItem is IPathObject imageObject)
|
||||
{
|
||||
var extrued = new LinearExtrude();
|
||||
sceneItem.WrapWith(extrued, scene);
|
||||
extrued.Rebuild(null);
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
},
|
||||
(sceneItem) => true,
|
||||
(sceneItem) => true);
|
||||
|
||||
this.Graph.RegisterOperation(
|
||||
typeof(IPathObject),
|
||||
"Smooth Path".Localize(),
|
||||
(sceneItem, scene) =>
|
||||
{
|
||||
if (sceneItem is IPathObject imageObject)
|
||||
{
|
||||
var smoothPath = new SmoothPath();
|
||||
sceneItem.WrapWith(smoothPath, scene);
|
||||
smoothPath.Rebuild(null);
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
},
|
||||
(sceneItem) => true,
|
||||
(sceneItem) => true);
|
||||
|
||||
ActiveSliceSettings.SettingChanged.RegisterEvent((s, e) =>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ namespace MatterHackers.MatterControl.Plugins.Lithophane
|
|||
|
||||
public Vector3 ImageOffset { get; private set; } = Vector3.Zero;
|
||||
|
||||
public void Rebuild(UndoBuffer undoBuffer)
|
||||
public override void Rebuild(UndoBuffer undoBuffer)
|
||||
{
|
||||
this.DebugDepth("Rebuild");
|
||||
var activeImage = AggContext.ImageIO.LoadImage(this.Image.AssetPath);
|
||||
|
|
|
|||
79
DesignTools/Operations/Image/AlphaThresholdFunction.cs
Normal file
79
DesignTools/Operations/Image/AlphaThresholdFunction.cs
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
Copyright (c) 2017, 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 MatterHackers.Agg;
|
||||
|
||||
namespace MatterHackers.MatterControl.DesignTools
|
||||
{
|
||||
public class AlphaThresholdFunction : IThresholdFunction
|
||||
{
|
||||
protected int start0To255 = 120;
|
||||
protected int end0To255 = 255;
|
||||
|
||||
public AlphaThresholdFunction()
|
||||
{
|
||||
}
|
||||
|
||||
public AlphaThresholdFunction(int start, int end)
|
||||
{
|
||||
this.start0To255 = start;
|
||||
this.end0To255 = end;
|
||||
}
|
||||
|
||||
public double Threshold0To1(Color color)
|
||||
{
|
||||
return GetThresholded0To1(color.Alpha0To255);
|
||||
}
|
||||
|
||||
protected double GetThresholded0To1(int inValue0To255)
|
||||
{
|
||||
double outValue = 0;
|
||||
if (inValue0To255 < start0To255)
|
||||
{
|
||||
outValue = 0;
|
||||
}
|
||||
else if (inValue0To255 > end0To255)
|
||||
{
|
||||
outValue = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
outValue = (double)(inValue0To255 - start0To255) / (double)(end0To255 - start0To255);
|
||||
|
||||
if (outValue < 0 || outValue > 255)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
|
||||
return outValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
38
DesignTools/Operations/Image/IThresholdFunction.cs
Normal file
38
DesignTools/Operations/Image/IThresholdFunction.cs
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
Copyright (c) 2017, 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.Agg;
|
||||
|
||||
namespace MatterHackers.MatterControl.DesignTools
|
||||
{
|
||||
public interface IThresholdFunction
|
||||
{
|
||||
double Threshold0To1(Color color);
|
||||
}
|
||||
}
|
||||
256
DesignTools/Operations/Image/ImageToPath.cs
Normal file
256
DesignTools/Operations/Image/ImageToPath.cs
Normal file
|
|
@ -0,0 +1,256 @@
|
|||
/*
|
||||
Copyright (c) 2017, 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 ClipperLib;
|
||||
using MatterHackers.Agg;
|
||||
using MatterHackers.Agg.Image;
|
||||
using MatterHackers.Agg.Platform;
|
||||
using MatterHackers.Agg.Transform;
|
||||
using MatterHackers.Agg.VertexSource;
|
||||
using MatterHackers.DataConverters3D;
|
||||
using MatterHackers.Localizations;
|
||||
using MatterHackers.MarchingSquares;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MatterHackers.MatterControl.DesignTools
|
||||
{
|
||||
using MatterHackers.Agg.UI;
|
||||
using MatterHackers.RenderOpenGl.OpenGl;
|
||||
using MatterHackers.VectorMath;
|
||||
using Polygon = List<IntPoint>;
|
||||
using Polygons = List<List<IntPoint>>;
|
||||
|
||||
public class ImageToPath : Object3D, IPublicPropertyObject, IPathObject, IEditorDraw
|
||||
{
|
||||
private static ImageBuffer generatingThumbnailIcon = AggContext.StaticData.LoadIcon(Path.Combine("building_thumbnail_40x40.png"));
|
||||
|
||||
public ImageToPath()
|
||||
{
|
||||
Name = "Path".Localize();
|
||||
}
|
||||
|
||||
public enum ThresholdFunctions { Intensity, Alpha, Hue }
|
||||
|
||||
public override bool CanRemove => true;
|
||||
|
||||
public ThresholdFunctions FeatureDetector { get; set; } = ThresholdFunctions.Intensity;
|
||||
public int EndThreshold { get; internal set; } = 255;
|
||||
public int StartThreshold { get; internal set; } = 120;
|
||||
|
||||
[JsonIgnore]
|
||||
public IVertexSource VertexSource { get; set; } = new VertexStorage();
|
||||
|
||||
[JsonIgnore]
|
||||
private ImageBuffer Image
|
||||
{
|
||||
get
|
||||
{
|
||||
var item = this.Descendants().Where((d) => d is ImageObject3D).FirstOrDefault();
|
||||
if (item is ImageObject3D imageItem)
|
||||
{
|
||||
return imageItem.Image;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private IThresholdFunction ThresholdFunction
|
||||
{
|
||||
get
|
||||
{
|
||||
switch (FeatureDetector)
|
||||
{
|
||||
case ThresholdFunctions.Intensity:
|
||||
return new MapOnMaxIntensity(StartThreshold, EndThreshold);
|
||||
|
||||
case ThresholdFunctions.Alpha:
|
||||
return new AlphaThresholdFunction(StartThreshold, EndThreshold);
|
||||
|
||||
case ThresholdFunctions.Hue:
|
||||
break;
|
||||
}
|
||||
|
||||
return new MapOnMaxIntensity(StartThreshold, EndThreshold);
|
||||
}
|
||||
}
|
||||
|
||||
public void DrawEditor(object sender, DrawEventArgs e)
|
||||
{
|
||||
bool first = true;
|
||||
Vector2 lastPosition = Vector2.Zero;
|
||||
var aabb = this.VisibleMeshes().FirstOrDefault().GetAxisAlignedBoundingBox();
|
||||
foreach (var vertex in VertexSource.Vertices())
|
||||
{
|
||||
var position = vertex.position;
|
||||
if (first)
|
||||
{
|
||||
first = false;
|
||||
GL.PushMatrix();
|
||||
GL.PushAttrib(AttribMask.EnableBit);
|
||||
GL.MultMatrix(this.WorldMatrix().GetAsFloatArray());
|
||||
|
||||
GL.Disable(EnableCap.Texture2D);
|
||||
GL.Disable(EnableCap.Blend);
|
||||
|
||||
GL.Begin(BeginMode.Lines);
|
||||
GL.Color4(255, 0, 0, 255);
|
||||
}
|
||||
|
||||
if (vertex.IsLineTo)
|
||||
{
|
||||
GL.Vertex3(lastPosition.X, lastPosition.Y, aabb.maxXYZ.Z + 0.002);
|
||||
GL.Vertex3(position.X, position.Y, aabb.maxXYZ.Z + 0.002);
|
||||
}
|
||||
|
||||
lastPosition = position;
|
||||
}
|
||||
|
||||
// if we drew anything
|
||||
if (!first)
|
||||
{
|
||||
GL.End();
|
||||
GL.PopAttrib();
|
||||
GL.PopMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
public void GenerateMarchingSquaresAndLines(Action<double, string> progressReporter, ImageBuffer image, IThresholdFunction thresholdFunction)
|
||||
{
|
||||
if (image != null)
|
||||
{
|
||||
// Regenerate outline
|
||||
var marchingSquaresData = new MarchingSquaresByte(
|
||||
image,
|
||||
thresholdFunction.Threshold0To1,
|
||||
0);
|
||||
|
||||
progressReporter?.Invoke(0, "Creating Outline");
|
||||
|
||||
marchingSquaresData.CreateLineSegments();
|
||||
progressReporter?.Invoke(.1, null);
|
||||
|
||||
int pixelsToIntPointsScale = 1000;
|
||||
var lineLoops = marchingSquaresData.CreateLineLoops(pixelsToIntPointsScale);
|
||||
|
||||
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));
|
||||
|
||||
// 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();
|
||||
progressReporter?.Invoke(.3, null);
|
||||
|
||||
clipper.Execute(ClipType.ctIntersection, polygonShape);
|
||||
|
||||
progressReporter?.Invoke(.55, null);
|
||||
|
||||
polygonShape = Clipper.CleanPolygons(polygonShape, 100);
|
||||
|
||||
progressReporter?.Invoke(.75, null);
|
||||
|
||||
VertexStorage rawVectorShape = PlatingHelper.PolygonToPathStorage(polygonShape);
|
||||
|
||||
var aabb = this.VisibleMeshes().FirstOrDefault().GetAxisAlignedBoundingBox();
|
||||
var xScale = aabb.XSize / image.Width;
|
||||
|
||||
var affine = Affine.NewScaling(1.0 / pixelsToIntPointsScale * xScale);
|
||||
affine *= Affine.NewTranslation(-aabb.XSize / 2, -aabb.YSize / 2);
|
||||
|
||||
this.VertexSource = new VertexSourceApplyTransform(rawVectorShape, affine);
|
||||
|
||||
progressReporter?.Invoke(1, null);
|
||||
|
||||
Invalidate(new InvalidateArgs(this, InvalidateType.Path));
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnInvalidate(InvalidateArgs invalidateType)
|
||||
{
|
||||
if (invalidateType.InvalidateType.HasFlag(InvalidateType.Image)
|
||||
&& invalidateType.Source != this
|
||||
&& !RebuildSuspended)
|
||||
{
|
||||
Rebuild(null);
|
||||
}
|
||||
else
|
||||
{
|
||||
base.OnInvalidate(invalidateType);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Rebuild(UndoBuffer undoBuffer)
|
||||
{
|
||||
SuspendRebuild();
|
||||
|
||||
// Make a fast simple path
|
||||
this.GenerateMarchingSquaresAndLines(null, generatingThumbnailIcon, new MapOnMaxIntensity());
|
||||
|
||||
// now create a long running task to process the image
|
||||
ApplicationController.Instance.Tasks.Execute(
|
||||
"Extrude Image".Localize(),
|
||||
(reporter, cancellationToken) =>
|
||||
{
|
||||
var progressStatus = new ProgressStatus();
|
||||
this.GenerateMarchingSquaresAndLines(
|
||||
(progress0to1, status) =>
|
||||
{
|
||||
progressStatus.Progress0To1 = progress0to1;
|
||||
progressStatus.Status = status;
|
||||
reporter.Report(progressStatus);
|
||||
},
|
||||
Image,
|
||||
ThresholdFunction);
|
||||
|
||||
return Task.CompletedTask;
|
||||
});
|
||||
|
||||
ResumeRebuild();
|
||||
|
||||
Invalidate(new InvalidateArgs(this, InvalidateType.Path));
|
||||
base.Rebuild(undoBuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
90
DesignTools/Operations/Image/LinearExtrude.cs
Normal file
90
DesignTools/Operations/Image/LinearExtrude.cs
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
Copyright (c) 2017, 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.Agg.VertexSource;
|
||||
using MatterHackers.DataConverters3D;
|
||||
using Newtonsoft.Json;
|
||||
using System.Linq;
|
||||
|
||||
namespace MatterHackers.MatterControl.DesignTools
|
||||
{
|
||||
using MatterHackers.Agg.UI;
|
||||
using MatterHackers.Localizations;
|
||||
|
||||
public class LinearExtrude : Object3D, IPublicPropertyObject
|
||||
{
|
||||
public double Height { get; set; } = 5;
|
||||
|
||||
[JsonIgnore]
|
||||
private IVertexSource VertexSource
|
||||
{
|
||||
get
|
||||
{
|
||||
var item = this.Descendants().Where((d) => d is IPathObject).FirstOrDefault();
|
||||
if (item is IPathObject pathItem)
|
||||
{
|
||||
return pathItem.VertexSource;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public LinearExtrude()
|
||||
{
|
||||
Name = "Linear Extrude".Localize();
|
||||
}
|
||||
|
||||
public override void OnInvalidate(InvalidateArgs invalidateType)
|
||||
{
|
||||
if ((invalidateType.InvalidateType.HasFlag(InvalidateType.Content)
|
||||
|| invalidateType.InvalidateType.HasFlag(InvalidateType.Matrix)
|
||||
|| invalidateType.InvalidateType.HasFlag(InvalidateType.Path))
|
||||
&& invalidateType.Source != this
|
||||
&& !RebuildSuspended)
|
||||
{
|
||||
Rebuild(null);
|
||||
}
|
||||
else
|
||||
{
|
||||
base.OnInvalidate(invalidateType);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Rebuild(UndoBuffer undoBuffer)
|
||||
{
|
||||
SuspendRebuild();
|
||||
Mesh = VertexSourceToMesh.Extrude(this.VertexSource, Height);
|
||||
ResumeRebuild();
|
||||
|
||||
Invalidate(new InvalidateArgs(this, InvalidateType.Mesh));
|
||||
base.Rebuild(undoBuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
83
DesignTools/Operations/Image/MapOnMaxIntensity.cs
Normal file
83
DesignTools/Operations/Image/MapOnMaxIntensity.cs
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
Copyright (c) 2017, 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 MatterHackers.Agg;
|
||||
|
||||
namespace MatterHackers.MatterControl.DesignTools
|
||||
{
|
||||
public class MapOnMaxIntensity : IThresholdFunction
|
||||
{
|
||||
protected int start0To255 = 120;
|
||||
protected int end0To255 = 255;
|
||||
|
||||
public MapOnMaxIntensity()
|
||||
{
|
||||
}
|
||||
|
||||
public MapOnMaxIntensity(int start, int end)
|
||||
{
|
||||
this.start0To255 = start;
|
||||
this.end0To255 = end;
|
||||
}
|
||||
|
||||
public double Threshold0To1(Color color)
|
||||
{
|
||||
// this is on I from HSI
|
||||
return GetThresholded0To1((color.red + color.blue + color.green) / 3);
|
||||
|
||||
// this is on L from HSL
|
||||
//return GetThresholded0To1(Math.Max(color.red, Math.Max(color.blue, color.green)));
|
||||
}
|
||||
|
||||
protected double GetThresholded0To1(int inValue0To255)
|
||||
{
|
||||
double outValue = 0;
|
||||
if (inValue0To255 < start0To255)
|
||||
{
|
||||
outValue = 0;
|
||||
}
|
||||
else if (inValue0To255 > end0To255)
|
||||
{
|
||||
outValue = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
outValue = (double)(inValue0To255 - start0To255) / (double)(end0To255 - start0To255);
|
||||
|
||||
if (outValue < 0 || outValue > 255)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
|
||||
return outValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -109,8 +109,8 @@ namespace MatterHackers.MatterControl.DesignTools.Operations
|
|||
|
||||
private static VertexStorage CombinePaths(IVertexSource a, IVertexSource b, ClipType clipType)
|
||||
{
|
||||
List<List<IntPoint>> aPolys = VertexSourceToClipperPolygons.CreatePolygons(a);
|
||||
List<List<IntPoint>> bPolys = VertexSourceToClipperPolygons.CreatePolygons(b);
|
||||
List<List<IntPoint>> aPolys = a.CreatePolygons();
|
||||
List<List<IntPoint>> bPolys = b.CreatePolygons();
|
||||
|
||||
Clipper clipper = new Clipper();
|
||||
|
||||
|
|
@ -122,7 +122,7 @@ namespace MatterHackers.MatterControl.DesignTools.Operations
|
|||
|
||||
Clipper.CleanPolygons(intersectedPolys);
|
||||
|
||||
VertexStorage output = VertexSourceToClipperPolygons.CreateVertexStorage(intersectedPolys);
|
||||
VertexStorage output = intersectedPolys.CreateVertexStorage();
|
||||
|
||||
output.Add(0, 0, ShapePath.FlagsAndCommand.Stop);
|
||||
|
||||
|
|
@ -131,7 +131,7 @@ namespace MatterHackers.MatterControl.DesignTools.Operations
|
|||
|
||||
public static VertexStorage Offset(this IVertexSource a, double distance)
|
||||
{
|
||||
List<List<IntPoint>> aPolys = VertexSourceToClipperPolygons.CreatePolygons(a);
|
||||
List<List<IntPoint>> aPolys = a.CreatePolygons();
|
||||
|
||||
ClipperOffset offseter = new ClipperOffset();
|
||||
offseter.AddPaths(aPolys, JoinType.jtMiter, EndType.etClosedPolygon);
|
||||
|
|
@ -140,7 +140,7 @@ namespace MatterHackers.MatterControl.DesignTools.Operations
|
|||
|
||||
Clipper.CleanPolygons(solution);
|
||||
|
||||
VertexStorage output = VertexSourceToClipperPolygons.CreateVertexStorage(solution);
|
||||
VertexStorage output = solution.CreateVertexStorage();
|
||||
|
||||
output.Add(0, 0, ShapePath.FlagsAndCommand.Stop);
|
||||
|
||||
|
|
@ -217,6 +217,7 @@ namespace MatterHackers.MatterControl.DesignTools.Operations
|
|||
|
||||
public static void WrapWith(this IObject3D originalItem, IObject3D wrapper, InteractiveScene scene)
|
||||
{
|
||||
originalItem.SuspendRebuild();
|
||||
originalItem.Parent.Children.Modify(list =>
|
||||
{
|
||||
list.Remove(originalItem);
|
||||
|
|
@ -230,6 +231,7 @@ namespace MatterHackers.MatterControl.DesignTools.Operations
|
|||
});
|
||||
|
||||
scene.SelectedItem = wrapper;
|
||||
originalItem.ResumeRebuild();
|
||||
}
|
||||
|
||||
public static Matrix4X4 ApplyAtBoundsCenter(this IObject3D objectWithBounds, Matrix4X4 transformToApply)
|
||||
|
|
|
|||
|
|
@ -31,28 +31,75 @@ using System.Collections.Generic;
|
|||
using ClipperLib;
|
||||
using MatterHackers.Agg.UI;
|
||||
using MatterHackers.DataConverters3D;
|
||||
using MatterHackers.Localizations;
|
||||
using MatterHackers.VectorMath;
|
||||
|
||||
namespace MatterHackers.MatterControl.DesignTools.Operations
|
||||
{
|
||||
using MatterHackers.Agg.VertexSource;
|
||||
using MatterHackers.DataConverters2D;
|
||||
using Newtonsoft.Json;
|
||||
using System.Linq;
|
||||
using Polygon = List<IntPoint>;
|
||||
using Polygons = List<List<IntPoint>>;
|
||||
|
||||
public class SmoothPath : Object3D, IPublicPropertyObject
|
||||
public class SmoothPath : Object3D, IPublicPropertyObject, IPathObject
|
||||
{
|
||||
public Polygons PathData;
|
||||
|
||||
[JsonIgnore]
|
||||
public IVertexSource VertexSource
|
||||
{
|
||||
get
|
||||
{
|
||||
var vertexSourc = this.Children.OfType<IPathObject>().FirstOrDefault();
|
||||
return vertexSourc?.VertexSource;
|
||||
}
|
||||
set
|
||||
{
|
||||
var vertexSourc = this.Children.OfType<IPathObject>().FirstOrDefault();
|
||||
if(vertexSourc != null)
|
||||
{
|
||||
vertexSourc.VertexSource = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public SmoothPath()
|
||||
{
|
||||
Name = "Smooth Path".Localize();
|
||||
}
|
||||
|
||||
public void Rebuild(UndoBuffer undoBuffer)
|
||||
public override void OnInvalidate(InvalidateArgs invalidateType)
|
||||
{
|
||||
if ((invalidateType.InvalidateType.HasFlag(InvalidateType.Content)
|
||||
|| invalidateType.InvalidateType.HasFlag(InvalidateType.Matrix)
|
||||
|| invalidateType.InvalidateType.HasFlag(InvalidateType.Path))
|
||||
&& invalidateType.Source != this
|
||||
&& !RebuildSuspended)
|
||||
{
|
||||
Rebuild(null);
|
||||
}
|
||||
else
|
||||
{
|
||||
base.OnInvalidate(invalidateType);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Rebuild(UndoBuffer undoBuffer)
|
||||
{
|
||||
this.DebugDepth("Rebuild");
|
||||
SuspendRebuild();
|
||||
DoSmoothing();
|
||||
ResumeRebuild();
|
||||
|
||||
Invalidate(new InvalidateArgs(this, InvalidateType.Path));
|
||||
}
|
||||
|
||||
public static Polygons DoSmoothing(Polygons inputPolygons, long maxDist = 300, int interations = 3, bool closedPath = true)
|
||||
public void DoSmoothing(long maxDist = 300, int interations = 3, bool closedPath = true)
|
||||
{
|
||||
var inputPolygons = VertexSource.CreatePolygons();
|
||||
|
||||
Polygons outputPolygons = new Polygons();
|
||||
foreach (Polygon inputPolygon in inputPolygons)
|
||||
{
|
||||
|
|
@ -97,7 +144,7 @@ namespace MatterHackers.MatterControl.DesignTools.Operations
|
|||
outputPolygons.Add(smoothedPositions);
|
||||
}
|
||||
|
||||
return outputPolygons;
|
||||
VertexSource = outputPolygons.CreateVertexStorage();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -74,7 +74,7 @@ namespace MatterHackers.MatterControl.DesignTools
|
|||
var vertexSource = this.VertexSource ?? this.Parent.Children.OfType<IPathObject>().FirstOrDefault().VertexSource;
|
||||
|
||||
// Convert VertexSource into expected Polygons
|
||||
Polygons polygonShape = (vertexSource == null) ? null : VertexSourceToClipperPolygons.CreatePolygons(vertexSource);
|
||||
Polygons polygonShape = (vertexSource == null) ? null : vertexSource.CreatePolygons();
|
||||
|
||||
GenerateBase(polygonShape);
|
||||
|
||||
|
|
|
|||
|
|
@ -83,8 +83,6 @@ namespace MatterHackers.MatterControl.DesignTools
|
|||
{
|
||||
_image = InvertLightness.DoInvertLightness(_image);
|
||||
}
|
||||
|
||||
base.Mesh = this.InitMesh() ?? PlatonicSolids.CreateCube(100, 100, 0.2);
|
||||
}
|
||||
else // bad load
|
||||
{
|
||||
|
|
@ -94,6 +92,14 @@ namespace MatterHackers.MatterControl.DesignTools
|
|||
graphics2D.DrawString("Bad Load", 100, 100);
|
||||
|
||||
}
|
||||
|
||||
// we don't want to invalidate on the mesh chage
|
||||
SuspendRebuild();
|
||||
base.Mesh = this.InitMesh() ?? PlatonicSolids.CreateCube(100, 100, 0.2);
|
||||
ResumeRebuild();
|
||||
|
||||
// send the invalidate on image change
|
||||
this.OnInvalidate(new InvalidateArgs(this, InvalidateType.Image));
|
||||
}
|
||||
|
||||
return _image;
|
||||
|
|
@ -110,7 +116,7 @@ namespace MatterHackers.MatterControl.DesignTools
|
|||
_invert = value;
|
||||
_image = null;
|
||||
|
||||
this.OnInvalidate(new InvalidateArgs(this, InvalidateType.Content));
|
||||
this.OnInvalidate(new InvalidateArgs(this, InvalidateType.Image));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
107
Library/ContentProviders/ImageContentProvider.cs
Normal file
107
Library/ContentProviders/ImageContentProvider.cs
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
Copyright (c) 2017, 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.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MatterHackers.Agg.Image;
|
||||
using MatterHackers.Agg.Platform;
|
||||
using MatterHackers.DataConverters3D;
|
||||
using MatterHackers.MatterControl.Library;
|
||||
|
||||
namespace MatterHackers.MatterControl.DesignTools
|
||||
{
|
||||
/// <summary>
|
||||
/// Loads IObject3D and thumbnails for ImageBuffer based ILibraryItem objects
|
||||
/// </summary>
|
||||
public class ImageContentProvider : ISceneContentProvider
|
||||
{
|
||||
public async Task<IObject3D> CreateItem(ILibraryItem item, Action<double, string> reporter)
|
||||
{
|
||||
return await Task.Run(async () =>
|
||||
{
|
||||
var imageBuffer = await this.LoadImage(item);
|
||||
if (imageBuffer != null)
|
||||
{
|
||||
string assetPath = "";
|
||||
|
||||
if (item is FileSystemFileItem fileItem)
|
||||
{
|
||||
assetPath = fileItem.Path;
|
||||
}
|
||||
else if (item is ILibraryAssetStream streamInterface)
|
||||
{
|
||||
using (var streamAndLength = await streamInterface.GetStream(null))
|
||||
{
|
||||
assetPath = AssetObject3D.AssetManager.StoreStream(streamAndLength.Stream, Path.GetExtension(streamInterface.FileName));
|
||||
}
|
||||
}
|
||||
|
||||
return new ImageObject3D()
|
||||
{
|
||||
AssetPath = assetPath,
|
||||
Name = "Image"
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private async Task<ImageBuffer> LoadImage(ILibraryItem item)
|
||||
{
|
||||
// Load the image at its native size, let the caller scale or resize
|
||||
if (item is ILibraryAssetStream streamInterface)
|
||||
{
|
||||
using (var streamAndLength = await streamInterface.GetStream(null))
|
||||
{
|
||||
var imageBuffer = new ImageBuffer();
|
||||
if (AggContext.ImageIO.LoadImageData(streamAndLength.Stream, imageBuffer))
|
||||
{
|
||||
imageBuffer.SetRecieveBlender(new BlenderPreMultBGRA());
|
||||
return imageBuffer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public async Task GetThumbnail(ILibraryItem item, int width, int height, ThumbnailSetter imageCallback)
|
||||
{
|
||||
var imageBuffer = await LoadImage(item);
|
||||
imageCallback(imageBuffer, raytracedImage: true);
|
||||
}
|
||||
|
||||
public ImageBuffer DefaultImage => AggContext.StaticData.LoadIcon("140.png");
|
||||
}
|
||||
}
|
||||
|
|
@ -43,6 +43,7 @@ namespace MatterHackers.MatterControl.Library
|
|||
{
|
||||
public PrintQueueContainer()
|
||||
{
|
||||
this.IsProtected = false;
|
||||
this.ChildContainers = new List<ILibraryContainerLink>();
|
||||
this.Items = new List<ILibraryItem>();
|
||||
this.Name = "Print Queue".Localize();
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ namespace MatterHackers.GCodeVisualizer
|
|||
if (moveLength > .1) // we get truncation errors from the slice engine when the length is very small, so don't do them
|
||||
{
|
||||
double area = extrusionVolumeMm3 / moveLength;
|
||||
width = area / layerHeight;
|
||||
width = area / layerHeight * 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -92,11 +92,17 @@
|
|||
<Compile Include="DesignTools\EditableTypes\DirectionAxis.cs" />
|
||||
<Compile Include="DesignTools\EditableTypes\DirectionVector.cs" />
|
||||
<Compile Include="DesignTools\Operations\Group3D.cs" />
|
||||
<Compile Include="DesignTools\Operations\Image\AlphaThresholdFunction.cs" />
|
||||
<Compile Include="DesignTools\Operations\Image\ImageToPath.cs" />
|
||||
<Compile Include="DesignTools\Operations\Image\IThresholdFunction.cs" />
|
||||
<Compile Include="DesignTools\Operations\Image\LinearExtrude.cs" />
|
||||
<Compile Include="DesignTools\Operations\Image\MapOnMaxIntensity.cs" />
|
||||
<Compile Include="DesignTools\Operations\OperationSource.cs" />
|
||||
<Compile Include="DesignTools\Operations\PinchObject3D.cs" />
|
||||
<Compile Include="DesignTools\Primitives\CubeObject3D.cs" />
|
||||
<Compile Include="DesignTools\Primitives\HalfCylinderObject3D.cs" />
|
||||
<Compile Include="DesignTools\Primitives\HalfWedgeObject3D.cs" />
|
||||
<Compile Include="Library\ContentProviders\ImageContentProvider.cs" />
|
||||
<Compile Include="Library\Providers\MatterControl\LibraryCollectionContainer.cs" />
|
||||
<Compile Include="Library\Providers\MatterControl\PartHistoryContainer.cs" />
|
||||
<Compile Include="Library\Providers\MatterControl\RootHistoryContainer.cs" />
|
||||
|
|
@ -149,7 +155,7 @@
|
|||
<Compile Include="DesignTools\Operations\Object3DExtensions.cs" />
|
||||
<Compile Include="DesignTools\Operations\Rotate.cs" />
|
||||
<Compile Include="DesignTools\Operations\Scale.cs" />
|
||||
<Compile Include="DesignTools\Operations\SmoothPath.cs" />
|
||||
<Compile Include="DesignTools\Operations\Path\SmoothPath.cs" />
|
||||
<Compile Include="DesignTools\Primitives\BaseObject3D.cs" />
|
||||
<Compile Include="DesignTools\Primitives\ImageObject3D.cs" />
|
||||
<Compile Include="DesignTools\Primitives\RingObject3D.cs" />
|
||||
|
|
|
|||
|
|
@ -106,11 +106,11 @@ namespace MatterHackers.MatterControl.DesignTools
|
|||
}
|
||||
|
||||
// add in the invert checkbox and change image button
|
||||
var addButton = new TextButton("Change".Localize(), theme)
|
||||
var changeButton = new TextButton("Change".Localize(), theme)
|
||||
{
|
||||
BackgroundColor = theme.MinimalShade
|
||||
};
|
||||
addButton.Click += (sender, e) =>
|
||||
changeButton.Click += (sender, e) =>
|
||||
{
|
||||
UiThread.RunOnIdle(() =>
|
||||
{
|
||||
|
|
@ -159,7 +159,7 @@ namespace MatterHackers.MatterControl.DesignTools
|
|||
|
||||
row.AddChild(new HorizontalSpacer());
|
||||
|
||||
row.AddChild(addButton);
|
||||
row.AddChild(changeButton);
|
||||
|
||||
imageObject.Invalidated += (s, e) =>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit e7a8e3284d916ed35fd804ef96d0e3eeaa0a0455
|
||||
Subproject commit e75912fda2c41da2a18d9c4e43a5879c580b2695
|
||||
Loading…
Add table
Add a link
Reference in a new issue