Merge pull request #4457 from larsbrubaker/master

master
This commit is contained in:
Lars Brubaker 2019-04-25 16:26:08 -07:00 committed by GitHub
commit 72da60062a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 1256 additions and 392 deletions

View file

@ -33,7 +33,6 @@ using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using MatterHackers.Agg;
using MatterHackers.Agg.Image;
using MatterHackers.DataConverters3D;
using MatterHackers.MatterControl.PartPreviewWindow;
using MatterHackers.PolygonMesh;
@ -42,46 +41,11 @@ using MatterHackers.VectorMath;
namespace MatterHackers.MatterControl.DesignTools
{
public static class FaceListExtensions
{
public static IPrimitive CreateTraceData(this FaceList faceList, List<Vector3> vertexList, int maxRecursion = int.MaxValue)
{
var allPolys = new List<IPrimitive>();
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<Vector3Float> vertexList, int maxRecursion = int.MaxValue)
{
var allPolys = new List<IPrimitive>();
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 double minimumSupportHeight;
private InteractiveScene scene;
private readonly InteractiveScene scene;
private readonly double minimumSupportHeight;
public SupportGenerator(InteractiveScene scene, double minimumSupportHeight)
{
@ -89,7 +53,16 @@ namespace MatterHackers.MatterControl.DesignTools
this.scene = scene;
}
public enum SupportGenerationType { Normal, From_Bed }
public enum SupportGenerationType
{
Normal,
From_Bed
}
/// <summary>
/// Gets the amount to reduce the pillars so they are separated in the 3D view.
/// </summary>
public static double ColumnReduceAmount => 1;
public double MaxOverHangAngle
{
@ -99,11 +72,13 @@ namespace MatterHackers.MatterControl.DesignTools
{
return 45;
}
var value = UserSettings.Instance.GetValue<double>(UserSettingsKey.SupportMaxOverHangAngle);
if (value < 0)
{
return 0;
}
if (value > 90)
{
value = 90;
@ -130,6 +105,7 @@ namespace MatterHackers.MatterControl.DesignTools
return value;
}
set
{
UserSettings.Instance.set(UserSettingsKey.SupportPillarSize, value.ToString());
@ -155,10 +131,17 @@ namespace MatterHackers.MatterControl.DesignTools
}
}
/// <summary>
/// The amount to reduce the pillars so they are separated in the 3D view
/// </summary>
public static double ColumnReduceAmount => 1;
public static IPrimitive CreateTraceData(FaceList faceList, List<Vector3Float> vertexList, int maxRecursion = int.MaxValue)
{
var allPolys = new List<IPrimitive>();
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 Task Create(IProgress<ProgressStatus> progress, CancellationToken cancelationToken)
{
@ -166,14 +149,16 @@ namespace MatterHackers.MatterControl.DesignTools
using (new SelectionMaintainer(scene))
{
ProgressStatus status = new ProgressStatus();
status.Status = "Enter";
var status = new ProgressStatus
{
Status = "Enter"
};
progress?.Report(status);
// Get visible meshes for each of them
// Get visible meshes for each of them
var allBedItems = scene.Children.SelectMany(i => i.VisibleMeshes());
AxisAlignedBoundingBox suppoortBounds = AxisAlignedBoundingBox.Empty();
var suppoortBounds = AxisAlignedBoundingBox.Empty();
if (selectedItem != null)
{
foreach (var candidate in selectedItem.VisibleMeshes())
@ -289,6 +274,7 @@ namespace MatterHackers.MatterControl.DesignTools
break;
}
}
if (aboveBed)
{
var face0Normal = item.Mesh.Faces[faceIndex].normal.TransformNormal(matrix).GetNormal();
@ -314,6 +300,7 @@ namespace MatterHackers.MatterControl.DesignTools
// less than 10 micros high, don't ad it
return;
}
var support = new GeneratedSupportObject3D()
{
Mesh = PlatonicSolids.CreateCube(1, 1, 1)
@ -326,80 +313,37 @@ namespace MatterHackers.MatterControl.DesignTools
holder.Children.Add(support);
}
private void AddSupportColumns(RectangleDouble gridBounds, Dictionary<(int x, int y), List<(double z, bool bottom)>> detectedPlanes)
private void AddSupportColumns(RectangleDouble gridBounds, Dictionary<(int x, int y), SupportColumn> supportGrid)
{
IObject3D supportColumnsToAdd = new Object3D();
bool fromBed = SupportType == SupportGenerationType.From_Bed;
var halfPillar = PillarSize / 2;
foreach (var kvp in detectedPlanes)
foreach (var kvp in supportGrid)
{
var planes = kvp.Value;
var supportColumnData = kvp.Value;
if (planes.Count == 0)
if (supportColumnData.Count == 0)
{
continue;
}
planes.Sort((a, b) =>
{
return a.z.CompareTo(b.z);
});
var yPos = (gridBounds.Bottom + kvp.Key.y) * PillarSize + halfPillar;
var xPos = (gridBounds.Left + kvp.Key.x) * PillarSize + halfPillar;
if (fromBed)
{
var nextPlaneIsBottom = planes.Count > 1 && planes[1].bottom;
if (!nextPlaneIsBottom // if the next plane is a top, we don't have any space from the bed to the part to put support
|| planes[1].z > minimumSupportHeight) // if the next plane is a bottom and is not far enough away, there is no space to put any support
// if the next plane is a bottom and is not far enough away, there is no space to put any support
if (supportColumnData[0].start < minimumSupportHeight
&& supportColumnData[0].end > minimumSupportHeight)
{
var firstBottomAboveBed = GetNextBottom(0, planes, minimumSupportHeight);
if (firstBottomAboveBed >= 0)
{
AddSupportColumn(supportColumnsToAdd, xPos, yPos, 0, planes[firstBottomAboveBed].z + .01);
}
AddSupportColumn(supportColumnsToAdd, xPos, yPos, 0, supportColumnData[0].end + .01);
}
}
else
{
int i = 0;
double lastTopZ = 0;
int lastBottom = -1;
var nextPlaneIsBottom = planes.Count > 1 && planes[1].bottom;
// if the next plane (the one above the bed) is a bottom, we have a part on the bed and will not generate support
if (nextPlaneIsBottom && planes[1].z <= minimumSupportHeight)
foreach (var (start, end) in supportColumnData)
{
// go up to the next top
i = GetNextTop(i, planes, minimumSupportHeight);
if (i >= 0)
{
lastTopZ = planes[i].z;
}
}
while (i != -1
&& i != lastBottom
&& i < planes.Count)
{
lastBottom = i;
// find all open areas in the list and add support
i = GetNextBottom(i, planes, minimumSupportHeight);
if (i >= 0)
{
if (i < planes.Count
&& planes[i].bottom)
{
AddSupportColumn(supportColumnsToAdd, xPos, yPos, lastTopZ, planes[i].z);
}
i = GetNextTop(i + 1, planes, minimumSupportHeight);
if (i >= 0
&& i < planes.Count)
{
lastTopZ = planes[i].z;
}
}
AddSupportColumn(supportColumnsToAdd, xPos, yPos, start, end);
}
}
}
@ -407,7 +351,32 @@ namespace MatterHackers.MatterControl.DesignTools
scene.UndoBuffer.AddAndDo(new InsertCommand(scene, supportColumnsToAdd.Children, false));
}
private Dictionary<(int x, int y), List<(double z, bool bottom)>> DetectRequiredSupportByTracing(RectangleDouble gridBounds, IEnumerable<IObject3D> supportCandidates)
private void AddSupportFaces(IEnumerable<IObject3D> supportCandidates, List<Vector3Float> supportVerts, FaceList supportFaces)
{
foreach (var item in supportCandidates)
{
// add all the faces
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 face = item.Mesh.Faces[faceIndex];
var verts = new int[] { face.v0, face.v1, face.v2 };
var p0 = item.Mesh.Vertices[face.v0].Transform(matrix);
var p1 = item.Mesh.Vertices[face.v1].Transform(matrix);
var p2 = item.Mesh.Vertices[face.v2].Transform(matrix);
var vc = supportVerts.Count;
supportVerts.Add(p0);
supportVerts.Add(p1);
supportVerts.Add(p2);
supportFaces.Add(vc, vc + 1, vc + 2, face0Normal);
}
}
}
private Dictionary<(int x, int y), SupportColumn> DetectRequiredSupportByTracing(RectangleDouble gridBounds, IEnumerable<IObject3D> supportCandidates)
{
var allBounds = supportCandidates.GetAxisAlignedBoundingBox();
var rayStartZ = allBounds.MinXYZ.Z - 1;
@ -415,148 +384,81 @@ namespace MatterHackers.MatterControl.DesignTools
var traceData = GetTraceData(supportCandidates);
// keep a list of all the detected planes in each support column
var detectedPlanes = new Dictionary<(int x, int y), List<(double z, bool bottom)>>();
var supportColumnData = new Dictionary<(int x, int y), SupportColumn>();
int gridWidth = (int)gridBounds.Width;
int gridHeight = (int)gridBounds.Height;
var offset = new Vector3(.000013, .00027, 0);
// 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 < gridHeight; y++)
{
for (int x = 0; x < gridWidth; x++)
{
// add a single plane at the bed so we always know the bed is a top
detectedPlanes.Add((x, y), new List<(double z, bool bottom)>());
detectedPlanes[(x, y)].Add((0, false));
IntersectInfo upHit = null;
var supportColumn = new SupportColumn(minimumSupportHeight);
supportColumnData.Add((x, y), supportColumn);
// create support plans at this xy
for (double yOffset = -1; yOffset <= 1; yOffset++)
{
for (double xOffset = -1; xOffset <= 1; xOffset++)
{
var thisTracePlanes = new HitPlanes(minimumSupportHeight);
var halfPillar = PillarSize / 2;
var yPos = (gridBounds.Bottom + y) * PillarSize + halfPillar + (yOffset * halfPillar);
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, rayStartZ), Vector3.UnitZ, intersectionType: IntersectionType.FrontFace);
var upRay = new Ray(new Vector3(xPos, yPos, rayStartZ) + offset, Vector3.UnitZ, intersectionType: IntersectionType.FrontFace);
IntersectInfo upHit;
do
{
upHit = traceData.GetClosestIntersection(upRay);
if (upHit != null)
{
detectedPlanes[(x, y)].Add((upHit.HitPosition.Z, true));
var angle = MathHelper.RadiansToDegrees(Math.Acos(upHit.normalAtHit.Dot(-Vector3.UnitZ)));
thisTracePlanes.Add(new HitPlane(upHit.HitPosition.Z, angle));
// 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.FrontFace);
upRay = new Ray(new Vector3(xPos, yPos, upHit.HitPosition.Z + .001) + offset, Vector3.UnitZ, intersectionType: IntersectionType.FrontFace);
}
} while (upHit != null);
}
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, rayStartZ), Vector3.UnitZ, intersectionType: IntersectionType.BackFace);
upRay = new Ray(new Vector3(xPos, yPos, rayStartZ) + offset, Vector3.UnitZ, intersectionType: IntersectionType.BackFace);
do
{
upHit = traceData.GetClosestIntersection(upRay);
if (upHit != null)
{
detectedPlanes[(x, y)].Add((upHit.HitPosition.Z, false));
var angle = MathHelper.RadiansToDegrees(Math.Acos(upHit.normalAtHit.Dot(-Vector3.UnitZ)));
thisTracePlanes.Add(new HitPlane(upHit.HitPosition.Z, angle));
// 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.BackFace);
upRay = new Ray(new Vector3(xPos, yPos, upHit.HitPosition.Z + .001) + offset, Vector3.UnitZ, intersectionType: IntersectionType.BackFace);
}
} while (upHit != null);
}
while (upHit != null);
var debugPlanes = new HitPlanes(minimumSupportHeight);
debugPlanes.AddRange(thisTracePlanes);
debugPlanes.Sort(MaxOverHangAngle);
var lineSupport = new SupportColumn(thisTracePlanes, minimumSupportHeight, MaxOverHangAngle);
if (lineSupport.Count > 0)
{
int a = 0;
}
supportColumn.Union(lineSupport);
}
}
}
}
return detectedPlanes;
}
public static int GetNextBottom(int i, List<(double z, bool bottom)> planes, double skipDist)
{
while (i < planes.Count)
{
// if we are on a bottom
if (planes[i].bottom)
{
// move up to the next plane and re-evaluate
i++;
}
else // we are on a top
{
// if the next plane is a bottom and more than skipDistanc away
if (i + 1 < planes.Count
&& planes[i + 1].bottom
&& planes[i + 1].z > planes[i].z + skipDist)
{
// this is the next bottom we are looking for
return i + 1;
}
else // move up to the next plane and re-evaluate
{
i++;
}
}
}
return -1;
}
public static int GetNextTop(int i, List<(double z, bool bottom)> planes, double skipDist)
{
if (!planes[i].bottom)
{
// skip the one we are
i++;
}
while (i < planes.Count)
{
// if we are on a bottom
if (planes[i].bottom)
{
// move up to the next plane and re-evaluate
i++;
}
else // we are on a top
{
// if the next plane is a bottom and more than skipDistanc away
if (i + 1 < planes.Count
&& planes[i + 1].bottom
&& planes[i + 1].z > planes[i].z + skipDist)
{
// this is the next top we are looking for
return i;
}
else // move up to the next plane and re-evaluate
{
i++;
}
}
}
return -1;
}
// function to get all the columns that need support generation
private IEnumerable<(int x, int y)> GetSupportCorrodinates(ImageBuffer supportNeededImage)
{
var buffer = supportNeededImage.GetBuffer();
// check if the image has any alpha set to something other than 255
for (int y = 0; y < supportNeededImage.Height; y++)
{
var yOffset = supportNeededImage.GetBufferOffsetY(y);
for (int x = 0; x < supportNeededImage.Width; x++)
{
// get the alpha at this pixel
//if (buffer[yOffset + x] > 0)
{
yield return (x, y);
}
}
}
return supportColumnData;
}
private IPrimitive GetTraceData(IEnumerable<IObject3D> supportCandidates)
@ -568,48 +470,387 @@ namespace MatterHackers.MatterControl.DesignTools
supportVerts = new List<Vector3Float>();
supportFaces = new FaceList();
// find all the down faces from the support candidates
// find all the faces from the support candidates
AddSupportFaces(supportCandidates,
supportVerts,
supportFaces,
(angle) => angle <= MaxOverHangAngle);
supportFaces);
// find all the up faces from everything on the bed
AddSupportFaces(scene.Children.SelectMany(i => i.VisibleMeshes()),
supportVerts,
supportFaces,
(angle) => angle >= 90);
return supportFaces.CreateTraceData(supportVerts);
return CreateTraceData(supportFaces, supportVerts);
}
private void AddSupportFaces(IEnumerable<IObject3D> supportCandidates, List<Vector3Float> supportVerts, FaceList supportFaces, Func<double, bool> doAdd)
public struct HitPlane
{
foreach (var item in supportCandidates)
public double Z;
public HitPlane(double z, bool bottom)
: this(z, bottom ? 0 : 180)
{
// add all the down faces to supportNeededImage
var matrix = item.WorldMatrix(scene);
for (int faceIndex = 0; faceIndex < item.Mesh.Faces.Count; faceIndex++)
}
public HitPlane(double z, double angle)
{
this.Z = z;
this.Angle = angle;
}
public bool Bottom(double maxOverHangAngle = 45)
{
return Angle <= maxOverHangAngle;
}
public double Angle { get; set; }
public bool Top(double maxOverHangAngle = 45)
{
return Angle > maxOverHangAngle;
}
public override string ToString()
{
return $"Z={Z:0.###} {(Bottom(45) ? "Bottom" : "Top")}";
}
}
[HideFromTreeViewAttribute, Immutable]
public class GeneratedSupportObject3D : Object3D
{
public GeneratedSupportObject3D()
{
OutputType = PrintOutputTypes.Support;
}
}
public class SupportColumn : List<(double start, double end)>
{
private readonly double minimumSupportHeight;
/// <summary>
/// Initializes a new instance of the <see cref="SupportColumn"/> class.
/// </summary>
/// <param name="minimumSupportHeight">The minimum distance between support regions.</param>
public SupportColumn(double minimumSupportHeight)
{
this.minimumSupportHeight = minimumSupportHeight;
}
/// <summary>
/// Initializes a new instance of the <see cref="SupportColumn"/> class.
/// </summary>
/// <param name="inputPlanes">The planes to consider while creating the support regions.</param>
/// <param name="minimumSupportHeight">The minimum distance between support regions.</param>
/// <param name="maxOverHangAngle">The maximum angle that will be treated as a bottom.</param>
public SupportColumn(HitPlanes inputPlanes, double minimumSupportHeight, double maxOverHangAngle = 45)
: this(minimumSupportHeight)
{
var hitPlanes = new HitPlanes(inputPlanes.MinimumSupportHeight);
hitPlanes.AddRange(inputPlanes);
hitPlanes.Simplify(maxOverHangAngle);
var i = 0;
var currentTop = 0.0;
// if the first bottom is more than the min distance
if (hitPlanes.Count > 1 && hitPlanes[i].Z <= minimumSupportHeight)
{
var face0Normal = item.Mesh.Faces[faceIndex].normal.TransformNormal(matrix).GetNormal();
var angle = MathHelper.RadiansToDegrees(Math.Acos(face0Normal.Dot(-Vector3Float.UnitZ)));
currentTop = hitPlanes[i + 1].Z;
i += 2;
}
if (doAdd(angle))
for (; i < hitPlanes.Count / 2 * 2; i += 2)
{
if (hitPlanes[i].Z > currentTop + minimumSupportHeight)
{
var face = item.Mesh.Faces[faceIndex];
var verts = new int[] { face.v0, face.v1, face.v2 };
var p0 = item.Mesh.Vertices[face.v0].Transform(matrix);
var p1 = item.Mesh.Vertices[face.v1].Transform(matrix);
var p2 = item.Mesh.Vertices[face.v2].Transform(matrix);
var vc = supportVerts.Count;
supportVerts.Add(p0);
supportVerts.Add(p1);
supportVerts.Add(p2);
this.Add((currentTop, hitPlanes[i].Z));
currentTop = hitPlanes[i + 1].Z;
}
}
}
supportFaces.Add(vc, vc + 1, vc + 2, face0Normal);
public void Union(SupportColumn other)
{
if (this.Count == 0)
{
this.AddRange(other);
return;
}
// merge them, considering minimumSupportHeight
for (int i = 0; i < this.Count; i++)
{
for (int j = 0; j < other.Count; j++)
{
// check if they overlap and other is not completely contained in this
if (this[i].start <= other[j].end + minimumSupportHeight
&& this[i].end >= other[j].start - minimumSupportHeight
&& (this[i].start > other[j].start || this[i].end < other[j].end))
{
// set this range to be the union
this[i] = (Math.Min(this[i].start, other[j].start),
Math.Max(this[i].end, other[j].end));
// fix up the planes in this
this.RemoveOverLaps();
// and start at the beginning again
i--;
// drop out of the j loop
break;
}
else if (this[i].end < other[j].start
&& i < this.Count - 1
&& this[i + 1].start > other[j].end)
{
// we are beyond the end of this
// add every additional set and return
this.Insert(i + 1, other[j]);
this.RemoveOverLaps();
i--;
// drop out of the j loop
break;
}
}
}
}
private void RemoveOverLaps()
{
// merge them, considering minimumSupportHeight
for (int i = 0; i < this.Count; i++)
{
for (int j = i + 1; j < this.Count; j++)
{
// check this is an overlap with the next segment
if (this[i].start <= this[j].end + minimumSupportHeight
&& this[i].end >= this[j].start - minimumSupportHeight
&& (this[i].start >= this[j].start || this[i].end <= this[j].end))
{
// set this range to be the union
this[i] = (Math.Min(this[i].start, this[j].start),
Math.Max(this[i].end, this[j].end));
// fix up the planes in this
this.RemoveAt(j);
// and start at the beginning again
i--;
// drop out of the j loop
break;
}
}
}
}
}
public class HitPlanes : List<HitPlane>
{
public double MinimumSupportHeight { get; private set; }
public HitPlanes(double minimumSupportHeight)
{
this.MinimumSupportHeight = minimumSupportHeight;
}
public int GetNextBottom(int i, double maxOverHangAngle = 45)
{
while (i < this.Count)
{
// if we are on a bottom
if (this[i].Bottom(maxOverHangAngle))
{
// move up to the next plane and re-evaluate
i++;
}
else // we are on a top
{
// if the next plane is a bottom and more than minimumSupportHeight away
if (i + 1 < this.Count
&& this[i + 1].Bottom(maxOverHangAngle)
&& this[i + 1].Z > this[i].Z + MinimumSupportHeight)
{
// this is the next bottom we are looking for
return i + 1;
}
else // move up to the next plane and re-evaluate
{
i++;
}
}
}
return -1;
}
public int GetNextTop(int start, double maxOverHangAngle = 45)
{
var i = start;
if (this.Count > 0
&& !this[i].Bottom(maxOverHangAngle))
{
// skip the one we are
i++;
}
return AdvanceToTop(i, start, maxOverHangAngle);
}
public new void Sort()
{
throw new NotImplementedException("Call Sort(double maxOverHangAngle) instead");
}
public void Sort(double maxOverHangAngle)
{
this.Sort((a, b) =>
{
// one is a top and the other is a bottom, sort by tops first
if (((a.Top(maxOverHangAngle) && b.Bottom(maxOverHangAngle)) || (a.Bottom(maxOverHangAngle) && b.Top(maxOverHangAngle)))
&& a.Z < b.Z + MinimumSupportHeight / 2
&& a.Z > b.Z - MinimumSupportHeight / 2)
{
return a.Top(MinimumSupportHeight) ? 1 : -1;
}
return a.Z.CompareTo(b.Z);
});
}
/// <summary>
/// Modify the list to have Bottom - Top, Bottom - Top items exactly.
/// Remove any internal Planes that are not required. This may reduce the set to no items.
/// </summary>
/// <param name="maxOverHangAngle">The max angle to consider a bottom.</param>
public void Simplify(double maxOverHangAngle = 45)
{
// sort the list on Z
this.Sort(maxOverHangAngle);
var highestPlane = double.NegativeInfinity;
var lastRemoveWasBottom = false;
// remove anything that is below 0
while (Count > 0
&& this[0].Z < 0)
{
if (this[0].Z > highestPlane)
{
highestPlane = this[0].Z;
lastRemoveWasBottom = this[0].Bottom(maxOverHangAngle);
}
this.RemoveAt(0);
}
// if the first item is a top then add a bottom at 0
if ((Count > 0 && this[0].Top(maxOverHangAngle)
&& this[0].Z > 0)
|| lastRemoveWasBottom)
{
this.Insert(0, new HitPlane(0, true));
}
// if the first item is still a top, remove it
while (Count > 0
&& this[0].Top(maxOverHangAngle))
{
this.RemoveAt(0);
}
// remove any items that are between a bottom and a top
int currentBottom = 0;
while (Count > currentBottom
&& currentBottom != -1)
{
var top = GetNextTop(currentBottom, maxOverHangAngle);
if (top != -1)
{
// remove everything between the bottom and the top
for (int i = top - 1; i > currentBottom; i--)
{
this.RemoveAt(i);
}
top = currentBottom + 1;
if (this[top].Z - this[currentBottom].Z < MinimumSupportHeight)
{
// also remove the top
this.RemoveAt(top);
}
else
{
// move the bottom up past the current top
currentBottom = GetNextBottom(top, maxOverHangAngle);
// remove everything between the bottom and the new top
if (currentBottom != -1)
{
for (int i = currentBottom - 1; i > top; i--)
{
this.RemoveAt(i);
}
}
currentBottom = top + 1;
}
}
else // not another top
{
// if the last plane is a bottom add a top above it at the minimum distance
if (this.Count > 0
&& this[this.Count - 1].Bottom(maxOverHangAngle))
{
var topHeight = this[this.Count - 1].Z + MinimumSupportHeight;
// remove all the bottoms from current up to last (but keep the actual last)
for (int i = this.Count - 1; i > currentBottom; i--)
{
this.RemoveAt(i);
}
// add a top
this.Add(new HitPlane(topHeight, false));
}
break;
}
}
}
private int AdvanceToTop(int i, int start, double maxOverHangAngle)
{
while (i < this.Count)
{
// if we are on a bottom
if (this[i].Bottom(maxOverHangAngle))
{
// move up to the next plane and re-evaluate
i++;
}
else // we are on a top
{
// if the next plane is a bottom and more than minimumSupportHeight away
if (i + 1 < this.Count
&& this[i + 1].Bottom(maxOverHangAngle)
&& this[i + 1].Z > this[i].Z + MinimumSupportHeight)
{
// this is the next top we are looking for
return i;
}
else // move up to the next plane and re-evaluate
{
// if we started on a bottom
// and we are the last top
// and we are far enough away from the start bottom
if (this[start].Bottom(maxOverHangAngle)
&& i == this.Count - 1
&& this[i].Z - this[start].Z > MinimumSupportHeight)
{
// we are on the last top of the part and have move up from some other part
return i;
}
i++;
}
}
}
return -1;
}
}
}
}

View file

@ -447,7 +447,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
foreach (var child in sceneContext.Scene.Children)
{
if (child is GeneratedSupportObject3D)
if (child is SupportGenerator.GeneratedSupportObject3D)
{
continue;
}

View file

@ -176,7 +176,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
// TODO: Use existing AssetsPath property
string assetsDirectory = Path.Combine(ApplicationDataStorage.Instance.ApplicationLibraryDataPath, "Assets");
var itemWorldMatrix = item.WorldMatrix();
if (item is GeneratedSupportObject3D generatedSupportObject3D)
if (item is SupportGenerator.GeneratedSupportObject3D generatedSupportObject3D)
{
// grow the support columns by the amount they are reduced by
var aabb = item.GetAxisAlignedBoundingBox();

@ -1 +1 @@
Subproject commit 95d5991cf3325b19dec5b1ece1fad940989a7039
Subproject commit cd05ff5df6b486fcf3bae2bcef848021a52d1046

@ -1 +1 @@
Subproject commit 42e6652050dfce45e2c158509839db15eb8a5886
Subproject commit da3b47918b41e20d1bdd9c477cf9a09325cf6a9a