Merge pull request #4504 from larsbrubaker/master

master
This commit is contained in:
Lars Brubaker 2019-05-06 20:11:37 -07:00 committed by GitHub
commit eab11f60ab
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 126 additions and 71 deletions

View file

@ -27,6 +27,7 @@ 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 System.Text;
using MatterHackers.Agg.Image;
@ -84,5 +85,14 @@ namespace MatterHackers.MatterControl
return sb.ToString();
}
public static IEnumerable<GCodeStream> InternalStreams(this GCodeStream context)
{
while (context is GCodeStream gCodeStream)
{
context = gCodeStream.InternalStream;
yield return context;
}
}
}
}

View file

@ -45,10 +45,19 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D
[DllImport("609_Boolean_bin.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int DeleteInt(ref IntPtr handle);
public static Mesh Do(Mesh inMeshA, Matrix4X4 matrixA,
Mesh inMeshB, Matrix4X4 matrixB,
int operation,
IProgress<ProgressStatus> reporter, double amountPerOperation, double percentCompleted, ProgressStatus progressStatus, CancellationToken cancellationToken)
public static Mesh Do(Mesh inMeshA,
Matrix4X4 matrixA,
// mesh B
Mesh inMeshB,
Matrix4X4 matrixB,
// operation
int operation,
// reporting
IProgress<ProgressStatus> reporter,
double amountPerOperation,
double percentCompleted,
ProgressStatus progressStatus,
CancellationToken cancellationToken)
{
var libiglExe = "libigl_boolean.exe";
if (File.Exists(libiglExe)
@ -67,12 +76,22 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D
vb = inMeshB.Vertices.ToDoubleArray(matrixB);
fb = inMeshB.Faces.ToIntArray();
int vcCount;
int fcCount;
DoBooleanOperation(va, va.Length, fa, fa.Length,
vb, vb.Length, fb, fb.Length,
DoBooleanOperation(va,
va.Length,
fa,
fa.Length,
// object B
vb,
vb.Length,
fb,
fb.Length,
// operation
operation,
out pVc, out vcCount, out pFc, out fcCount);
// results
out pVc,
out int vcCount,
out pFc,
out int fcCount);
var vcArray = new double[vcCount];
Marshal.Copy(pVc, vcArray, 0, vcCount);
@ -88,6 +107,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D
{
DeleteDouble(ref pVc);
}
if (pFc != IntPtr.Zero)
{
DeleteInt(ref pFc);
@ -107,44 +127,53 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D
switch (operation)
{
case 0:
return PolygonMesh.Csg.CsgOperations.Union(meshA, meshB, (status, progress0To1) =>
{
// Abort if flagged
cancellationToken.ThrowIfCancellationRequested();
return PolygonMesh.Csg.CsgOperations.Union(meshA,
meshB,
(status, progress0To1) =>
{
// Abort if flagged
cancellationToken.ThrowIfCancellationRequested();
progressStatus.Status = status;
progressStatus.Progress0To1 = percentCompleted + (amountPerOperation * progress0To1);
reporter?.Report(progressStatus);
}, cancellationToken);
progressStatus.Status = status;
progressStatus.Progress0To1 = percentCompleted + (amountPerOperation * progress0To1);
reporter?.Report(progressStatus);
},
cancellationToken);
case 1:
return PolygonMesh.Csg.CsgOperations.Subtract(meshA, meshB, (status, progress0To1) =>
{
// Abort if flagged
cancellationToken.ThrowIfCancellationRequested();
return PolygonMesh.Csg.CsgOperations.Subtract(meshA,
meshB,
(status, progress0To1) =>
{
// Abort if flagged
cancellationToken.ThrowIfCancellationRequested();
progressStatus.Status = status;
progressStatus.Progress0To1 = percentCompleted + (amountPerOperation * progress0To1);
reporter?.Report(progressStatus);
}, cancellationToken);
progressStatus.Status = status;
progressStatus.Progress0To1 = percentCompleted + (amountPerOperation * progress0To1);
reporter?.Report(progressStatus);
},
cancellationToken);
case 2:
return PolygonMesh.Csg.CsgOperations.Intersect(meshA, meshB, (status, progress0To1) =>
{
// Abort if flagged
cancellationToken.ThrowIfCancellationRequested();
return PolygonMesh.Csg.CsgOperations.Intersect(meshA,
meshB,
(status, progress0To1) =>
{
// Abort if flagged
cancellationToken.ThrowIfCancellationRequested();
progressStatus.Status = status;
progressStatus.Progress0To1 = percentCompleted + (amountPerOperation * progress0To1);
reporter.Report(progressStatus);
}, cancellationToken);
progressStatus.Status = status;
progressStatus.Progress0To1 = percentCompleted + (amountPerOperation * progress0To1);
reporter.Report(progressStatus);
},
cancellationToken);
}
return null;
}
[DllImport("609_Boolean_bin.dll", CallingConvention = CallingConvention.Cdecl)]
public extern static void DoBooleanOperation(
public static extern void DoBooleanOperation(
double[] va, int vaCount, int[] fa, int faCount,
double[] vb, int vbCount, int[] fb, int fbCount,
int opperation,

View file

@ -173,6 +173,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D
this.Children.Add(SourceContainer.Clone());
SourceContainer.Visible = false;
}
return;
}
@ -197,8 +198,10 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D
double amountPerOperation = 1.0 / totalOperations;
double percentCompleted = 0;
ProgressStatus progressStatus = new ProgressStatus();
progressStatus.Status = "Do CSG";
var progressStatus = new ProgressStatus
{
Status = "Do CSG"
};
foreach (var keep in keepVisibleItems)
{
var resultsMesh = keep.Mesh;
@ -206,9 +209,19 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D
foreach (var remove in removeVisibleItems)
{
resultsMesh = BooleanProcessing.Do(resultsMesh, keepWorldMatrix,
remove.Mesh, remove.WorldMatrix(SourceContainer),
1, reporter, amountPerOperation, percentCompleted, progressStatus, cancellationToken);
resultsMesh = BooleanProcessing.Do(resultsMesh,
keepWorldMatrix,
// other mesh
remove.Mesh,
remove.WorldMatrix(SourceContainer),
// operation type
1,
// reporting
reporter,
amountPerOperation,
percentCompleted,
progressStatus,
cancellationToken);
// after the first time we get a result the results mesh is in the right coordinate space
keepWorldMatrix = Matrix4X4.Identity;

View file

@ -40,15 +40,16 @@ namespace MatterHackers.MatterControl.PrinterCommunication.Io
{
private readonly string completedBeforeGCodeString = "; COMPLETED_BEFORE_GCODE";
private int activeTool;
private int extruderCount = 0;
private readonly int extruderCount = 0;
private PrinterMove lastDestination = PrinterMove.Unknown;
private string postSwitchLine;
private double preSwitchFeedRate;
private Vector3 preSwitchPosition;
private IGCodeLineReader gcodeLineReader;
private GCodeMemoryFile gCodeMemoryFile;
private QueuedCommandsStream queuedCommandsStream;
private int requestedTool;
private readonly IGCodeLineReader gcodeLineReader;
private readonly GCodeMemoryFile gCodeMemoryFile;
private readonly QueuedCommandsStream queuedCommandsStream;
public int RequestedTool { get; set; }
private enum SendStates
{
@ -58,8 +59,8 @@ namespace MatterHackers.MatterControl.PrinterCommunication.Io
}
private SendStates sendState = SendStates.Normal;
private double[] targetTemps = new double[4];
private Queue<string> queuedCommands = new Queue<string>();
private readonly double[] targetTemps = new double[4];
private readonly Queue<string> queuedCommands = new Queue<string>();
public ToolChangeStream(PrinterConfig printer, GCodeStream internalStream, QueuedCommandsStream queuedCommandsStream, IGCodeLineReader gcodeLineReader)
: base(printer, internalStream)
@ -69,6 +70,7 @@ namespace MatterHackers.MatterControl.PrinterCommunication.Io
{
this.gCodeMemoryFile = gcodeLineReader.GCodeFile as GCodeMemoryFile;
}
this.queuedCommandsStream = queuedCommandsStream;
extruderCount = printer.Settings.GetValue<int>(SettingsKey.extruder_count);
activeTool = printer.Connection.ActiveExtruderIndex;
@ -103,7 +105,7 @@ namespace MatterHackers.MatterControl.PrinterCommunication.Io
// get the temp we are setting
GCodeFile.GetFirstNumberAfter("S", lineToSend, ref toolTemp);
// set it to the tool we will be changing to
requestedToolForTempChange = requestedTool;
requestedToolForTempChange = RequestedTool;
// check if this command contains a tool specification
GCodeFile.GetFirstNumberAfter("T", lineToSend, ref requestedToolForTempChange);
@ -121,7 +123,7 @@ namespace MatterHackers.MatterControl.PrinterCommunication.Io
if (lineToSend == completedBeforeGCodeString)
{
activeTool = requestedTool;
activeTool = RequestedTool;
sendState = SendStates.Normal;
QueueAfterGCode();
}
@ -139,12 +141,12 @@ namespace MatterHackers.MatterControl.PrinterCommunication.Io
}
// if we are waiting to switch to the next tool
else if (activeTool != requestedTool)
else if (activeTool != RequestedTool)
{
// if this command does not include the extruder to switch to, than we need to switch before sending it
if (!lineNoComment.Contains("T"))
{
queuedCommands.Enqueue($"T{requestedTool}");
queuedCommands.Enqueue($"T{RequestedTool}");
}
// For smoothie, switch back to the extrude we were using before the temp change (smoothie switches to the specified extruder, marlin repetier do not)
@ -167,9 +169,9 @@ namespace MatterHackers.MatterControl.PrinterCommunication.Io
// we have switch back to our starting tool without a move
// change back to normal processing and don't change tools
sendState = SendStates.Normal;
var lastRequestedTool = requestedTool;
var lastRequestedTool = RequestedTool;
// set the requested tool
requestedTool = changeCommandTool;
RequestedTool = changeCommandTool;
// don't send the change are we are on the right tool now
return $"; switch back without move from T{lastRequestedTool} to T{activeTool}";
}
@ -180,9 +182,9 @@ namespace MatterHackers.MatterControl.PrinterCommunication.Io
{
sendState = SendStates.WaitingForMove;
// set the requested tool
requestedTool = changeCommandTool;
RequestedTool = changeCommandTool;
// don't queue the tool change until after the before gcode has been sent
return $"; waiting for move on T{requestedTool}";
return $"; waiting for move on T{RequestedTool}";
}
}
}
@ -190,7 +192,7 @@ namespace MatterHackers.MatterControl.PrinterCommunication.Io
// if it is only an extrusion move
if (sendState == SendStates.WaitingForMove
&& activeTool != requestedTool // is different than the last extruder set
&& activeTool != RequestedTool // is different than the last extruder set
&& (lineNoComment.StartsWith("G0 ") || lineNoComment.StartsWith("G1 ")) // is a G1 or G0
&& lineNoComment.Contains("E") // it is an extrusion move
// and have no other position information
@ -203,7 +205,7 @@ namespace MatterHackers.MatterControl.PrinterCommunication.Io
if (GCodeFile.GetFirstNumberAfter("E", lineNoComment, ref ePosition))
{
// switch extruders
queuedCommands.Enqueue($"T{requestedTool}");
queuedCommands.Enqueue($"T{RequestedTool}");
// if we know the current E position before the switch
// set the E value to the previous E value.
@ -270,7 +272,7 @@ namespace MatterHackers.MatterControl.PrinterCommunication.Io
// we do not switch tools again, turn off any that are not currently printing
for (int i = 0; i < extruderCount; i++)
{
if (i != requestedTool
if (i != RequestedTool
&& i != activeTool)
{
gcode.AppendLine($"M104 T{i} S0");
@ -310,16 +312,16 @@ namespace MatterHackers.MatterControl.PrinterCommunication.Io
// check if any extruders need to start heating back up
for (int i = 0; i < extruderCount; i++)
{
var nextToolChange = NextToolChange(i);
var (toolIndex, time) = NextToolChange(i);
var targetTemp = targetTemps[i];
var setTempLine = $"M104 T{i} S{targetTemp}";
if (nextToolChange.toolIndex >= 0
&& nextToolChange.time < timeToReheat
if (toolIndex >= 0
&& time < timeToReheat
&& printer.Connection.GetTargetHotendTemperature(i) != targetTemp
&& line != setTempLine)
{
printer.Connection.SetTargetHotendTemperature(i, targetTemp);
//queuedCommands.Enqueue(setTempLine);
// queuedCommands.Enqueue(setTempLine);
}
}
}
@ -327,7 +329,7 @@ namespace MatterHackers.MatterControl.PrinterCommunication.Io
private void QueueAfterGCode()
{
string afterGcodeToQueue = "";
switch (requestedTool)
switch (RequestedTool)
{
case 0:
afterGcodeToQueue = printer.Settings.GetValue(SettingsKey.toolchange_gcode).Replace("\\n", "\n");
@ -357,13 +359,13 @@ namespace MatterHackers.MatterControl.PrinterCommunication.Io
var gcode = new StringBuilder();
// If the printer is heating, make sure we are at temp before switching extruders
var nextToolTargetTemp = targetTemps[requestedTool];
var currentPrinterTargeTemp = printer.Connection.GetTargetHotendTemperature(requestedTool);
var nextToolTargetTemp = targetTemps[RequestedTool];
var currentPrinterTargeTemp = printer.Connection.GetTargetHotendTemperature(RequestedTool);
if (currentPrinterTargeTemp > 0
&& printer.Connection.GetActualHotendTemperature(requestedTool) < nextToolTargetTemp - 3)
&& printer.Connection.GetActualHotendTemperature(RequestedTool) < nextToolTargetTemp - 3)
{
// ensure our next tool is at temp (the one we are switching to)
gcode.AppendLine($"M109 T{requestedTool} S{nextToolTargetTemp}");
gcode.AppendLine($"M109 T{RequestedTool} S{nextToolTargetTemp}");
}
if (afterGcodeToQueue.Trim().Length > 0)
@ -400,14 +402,14 @@ namespace MatterHackers.MatterControl.PrinterCommunication.Io
{
// check if there is a travel
if (sendState == SendStates.WaitingForMove
&& activeTool != requestedTool // is different than the last extruder set
&& activeTool != RequestedTool // is different than the last extruder set
&& (lineNoComment.StartsWith("G0 ") || lineNoComment.StartsWith("G1 ")) // is a G1 or G0
&& (lineNoComment.Contains("X") || lineNoComment.Contains("Y") || lineNoComment.Contains("Z"))) // has a move axis in it
{
postSwitchLine = lineIn;
string beforeGcodeToQueue = "";
switch (requestedTool)
switch (RequestedTool)
{
case 0:
beforeGcodeToQueue = printer.Settings.GetValue(SettingsKey.before_toolchange_gcode).Replace("\\n", "\n");
@ -433,7 +435,7 @@ namespace MatterHackers.MatterControl.PrinterCommunication.Io
ManageCoolDownAndOffTemps(gcode);
// send the actual tool change
gcode.AppendLine($"T{requestedTool}");
gcode.AppendLine($"T{RequestedTool}");
// send the marker to let us know we have sent the before gcode
gcode.AppendLine(completedBeforeGCodeString);

View file

@ -1327,7 +1327,8 @@ You will then need to logout and log back in to the computer for the changes to
if (moveAmountMm != 0)
{
// TODO: Long term we need to track the active extruder and make requiresToolChange be driven by the extruder you're actually on
bool requiresToolChange = extruderNumber != ActiveExtruderIndex;
bool requiresToolChange = extruderNumber != ActiveExtruderIndex
|| TotalGCodeStream.InternalStreams().OfType<ToolChangeStream>().FirstOrDefault().RequestedTool != ActiveExtruderIndex;
SetMovementToRelative();

@ -1 +1 @@
Subproject commit a52e2a218a7d3efb1546a2edfe1b37488d26100d
Subproject commit 22750d5a2afc91c4eea323c364ef05200211560b