- Issue MatterHackers/MCCentral#5077 PrintLevelingData reloaded for each line in gcode file
170 lines
5.6 KiB
C#
170 lines
5.6 KiB
C#
/*
|
|
Copyright (c) 2019, Lars Brubaker
|
|
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.Collections.Generic;
|
|
using System.Linq;
|
|
using MatterHackers.MatterControl.ConfigurationPage.PrintLeveling;
|
|
using MatterHackers.MatterControl.SlicerConfiguration;
|
|
using MatterHackers.PolygonMesh;
|
|
using MatterHackers.VectorMath;
|
|
|
|
namespace MatterHackers.MatterControl.PartPreviewWindow
|
|
{
|
|
public class LevelingMeshVisualizer
|
|
{
|
|
public static Mesh BuildMeshFromLevelingData(PrinterConfig printer)
|
|
{
|
|
PrintLevelingData levelingData = printer.Settings.Helpers.PrintLevelingData;
|
|
var currentLevelingFunctions = new LevelingFunctions(printer, levelingData);
|
|
|
|
var vertices = new List<Vector3Float>();
|
|
|
|
var pointCounts = new Dictionary<Vector3Float, int>();
|
|
|
|
var points = new int[3];
|
|
|
|
var faces = new FaceList();
|
|
|
|
// Add top faces
|
|
foreach (var region in currentLevelingFunctions.Regions)
|
|
{
|
|
int i = 0;
|
|
|
|
foreach (var point in new[] { new Vector3Float(region.V0), new Vector3Float(region.V1), new Vector3Float(region.V2) })
|
|
{
|
|
int index = vertices.IndexOf(point);
|
|
if (index == -1)
|
|
{
|
|
index = vertices.Count;
|
|
vertices.Add(point);
|
|
}
|
|
|
|
if (!pointCounts.TryGetValue(point, out int pointCount))
|
|
{
|
|
pointCount = 0;
|
|
}
|
|
|
|
pointCounts[point] = pointCount + 1;
|
|
|
|
points[i++] = index;
|
|
}
|
|
|
|
faces.Add(new Face(points[0], points[2], points[1], vertices));
|
|
}
|
|
|
|
List<Vector3Float> outerPoints = GetOuterPoints(vertices, pointCounts, printer.Bed.BedCenter);
|
|
|
|
// Add reflected hull points at the bed - reflected point for item in negative z should be the negative value
|
|
var reflectedVertices = outerPoints.Select(h => new Vector3Float(h.X, h.Y, h.Z > 0 ? 0 : h.Z)).ToList();
|
|
vertices.AddRange(reflectedVertices);
|
|
|
|
int lastReflected = vertices.IndexOf(reflectedVertices.Last());
|
|
|
|
int currIndex, reflectedIndex, nextIndex = -1;
|
|
|
|
var anchorIndex = vertices.IndexOf(reflectedVertices.First());
|
|
|
|
// Loop over all outer points, reflecting a point onto the bed and stitching the current, reflect and next points together
|
|
for (var i = 0; i < outerPoints.Count; i++)
|
|
{
|
|
var point = outerPoints[i];
|
|
var reflected = reflectedVertices[i];
|
|
|
|
bool lastIndex = (i == outerPoints.Count - 1);
|
|
|
|
Vector3Float nextPoint = lastIndex ? outerPoints.First() : outerPoints[i + 1];
|
|
|
|
currIndex = vertices.IndexOf(point);
|
|
nextIndex = vertices.IndexOf(nextPoint);
|
|
reflectedIndex = vertices.IndexOf(reflected);
|
|
|
|
Face faceA, faceB;
|
|
|
|
// Add face back to previous
|
|
faces.Add(faceB = new Face(currIndex, lastReflected, reflectedIndex, vertices));
|
|
|
|
// Add face for current
|
|
faces.Add(faceA = new Face(currIndex, reflectedIndex, nextIndex, vertices));
|
|
|
|
lastReflected = reflectedIndex;
|
|
}
|
|
|
|
// Add bottom faces
|
|
foreach (var region in currentLevelingFunctions.Regions)
|
|
{
|
|
int i = 0;
|
|
|
|
foreach (var point in new[] { GetReflected(region.V0), GetReflected(region.V1), GetReflected(region.V2) })
|
|
{
|
|
int index = vertices.IndexOf(point);
|
|
if (index == -1)
|
|
{
|
|
index = vertices.Count;
|
|
vertices.Add(point);
|
|
}
|
|
|
|
points[i++] = index;
|
|
}
|
|
|
|
faces.Add(new Face(points[0], points[1], points[2], vertices));
|
|
}
|
|
|
|
return new Mesh(vertices, faces);
|
|
}
|
|
|
|
private static Vector3Float GetReflected(Vector3 point)
|
|
{
|
|
return new Vector3Float(point.X, point.Y, (point.Z > 0) ? 0 : point.Z);
|
|
}
|
|
|
|
private static List<Vector3Float> GetOuterPoints(List<Vector3Float> vertices, Dictionary<Vector3Float, int> pointCounts, Vector2 bedCenter)
|
|
{
|
|
// Filter to only outer points
|
|
var outerPointsOnly = pointCounts.Where(kvp => kvp.Value <= 3).Select(kvp => kvp.Key).ToList();
|
|
var outerPoints = vertices.Where(p => outerPointsOnly.Contains(p)).ToList();
|
|
|
|
// Project to points with their computed angles and lengths
|
|
var computed = outerPoints.Select(p =>
|
|
{
|
|
var point = new Vector2(p) - bedCenter;
|
|
|
|
return new
|
|
{
|
|
Point = p,
|
|
Angle = point.GetAngle(),
|
|
Lenth = point.Length
|
|
};
|
|
});
|
|
|
|
// Return the original points ordered by angle/length
|
|
var ordered = computed.OrderBy(c => c.Angle).ThenBy(c => c.Lenth);
|
|
return ordered.Select(c => c.Point).ToList();
|
|
}
|
|
}
|
|
}
|