2017-06-21 23:26:20 -07:00
|
|
|
|
/*
|
|
|
|
|
|
Copyright (c) 2014, 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.
|
|
|
|
|
|
*/
|
|
|
|
|
|
#define MULTI_THREAD
|
|
|
|
|
|
|
|
|
|
|
|
using MatterHackers.Agg;
|
|
|
|
|
|
using MatterHackers.VectorMath;
|
|
|
|
|
|
using System;
|
|
|
|
|
|
using System.IO;
|
|
|
|
|
|
|
2018-01-05 12:44:57 -08:00
|
|
|
|
namespace MatterControl.Printing
|
2017-06-21 23:26:20 -07:00
|
|
|
|
{
|
|
|
|
|
|
public class GCodeFileStreamed : GCodeFile
|
|
|
|
|
|
{
|
|
|
|
|
|
private StreamReader openGcodeStream;
|
|
|
|
|
|
object locker = new object();
|
|
|
|
|
|
|
|
|
|
|
|
private bool readLastLineOfFile = false;
|
|
|
|
|
|
private int readLineCount = 0;
|
|
|
|
|
|
private const int MaxLinesToBuffer = 128;
|
2018-07-19 15:34:02 -07:00
|
|
|
|
|
2017-06-21 23:26:20 -07:00
|
|
|
|
private PrinterMachineInstruction[] readLinesRingBuffer = new PrinterMachineInstruction[MaxLinesToBuffer];
|
|
|
|
|
|
|
|
|
|
|
|
public GCodeFileStreamed(string fileName)
|
2018-07-19 15:34:02 -07:00
|
|
|
|
: this (new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
|
|
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public GCodeFileStreamed(Stream inStream)
|
2017-06-21 23:26:20 -07:00
|
|
|
|
{
|
|
|
|
|
|
openGcodeStream = new StreamReader(inStream);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
~GCodeFileStreamed()
|
|
|
|
|
|
{
|
|
|
|
|
|
CloseStream();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void CloseStream()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (openGcodeStream != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
openGcodeStream.Close();
|
|
|
|
|
|
openGcodeStream = null;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public override int LineCount
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
if (openGcodeStream != null
|
|
|
|
|
|
&& !readLastLineOfFile)
|
|
|
|
|
|
{
|
|
|
|
|
|
return Math.Max(readLineCount + 1, (int)(openGcodeStream.BaseStream.Length / 14));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return readLineCount;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public long ByteCount
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
if (openGcodeStream != null
|
|
|
|
|
|
&& !readLastLineOfFile)
|
|
|
|
|
|
{
|
|
|
|
|
|
return openGcodeStream.BaseStream.Length;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public long BytePosition
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
if (openGcodeStream != null
|
|
|
|
|
|
&& !readLastLineOfFile)
|
|
|
|
|
|
{
|
|
|
|
|
|
return openGcodeStream.BaseStream.Position;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public override double TotalSecondsInPrint
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
// We don't know, so we always return -1 used to identify as streaming.
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public override void Clear()
|
|
|
|
|
|
{
|
|
|
|
|
|
CloseStream();
|
|
|
|
|
|
|
|
|
|
|
|
readLastLineOfFile = false;
|
|
|
|
|
|
readLineCount = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public override Vector2 GetWeightedCenter()
|
|
|
|
|
|
{
|
|
|
|
|
|
throw new NotImplementedException("A streamed GCode file should not need to do this. Please validate the code that is calling this.");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public override RectangleDouble GetBounds()
|
|
|
|
|
|
{
|
|
|
|
|
|
throw new NotImplementedException("A streamed GCode file should not need to do this. Please validate the code that is calling this.");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public override double GetFilamentCubicMm(double filamentDiameter)
|
|
|
|
|
|
{
|
|
|
|
|
|
throw new NotImplementedException("A streamed GCode file should not need to do this. Please validate the code that is calling this.");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public override bool IsExtruding(int instructionIndexToCheck)
|
|
|
|
|
|
{
|
|
|
|
|
|
throw new NotImplementedException();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-05-08 15:19:06 -07:00
|
|
|
|
public override double GetLayerHeight(int layerIndex)
|
2017-06-21 23:26:20 -07:00
|
|
|
|
{
|
|
|
|
|
|
throw new NotImplementedException();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-05-09 15:27:31 -07:00
|
|
|
|
public override double GetLayerTop(int layerIndex)
|
2017-06-21 23:26:20 -07:00
|
|
|
|
{
|
|
|
|
|
|
throw new NotImplementedException();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public override double GetFilamentUsedMm(double filamentDiameter)
|
|
|
|
|
|
{
|
|
|
|
|
|
throw new NotImplementedException();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-05-03 10:19:19 -07:00
|
|
|
|
public override int GetLastFanSpeed(int layerIndex)
|
|
|
|
|
|
{
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public override double PercentComplete(int instructionIndex)
|
2017-06-21 23:26:20 -07:00
|
|
|
|
{
|
|
|
|
|
|
lock(locker)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (openGcodeStream != null
|
|
|
|
|
|
&& openGcodeStream.BaseStream.Length > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
return (double)openGcodeStream.BaseStream.Position / (double)openGcodeStream.BaseStream.Length * 100.0;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return 100;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-05-30 16:42:17 -07:00
|
|
|
|
public override int GetFirstLayerInstruction(int layerIndex)
|
2017-06-21 23:26:20 -07:00
|
|
|
|
{
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public override double GetFilamentDiameter()
|
|
|
|
|
|
{
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public override double GetFilamentWeightGrams(double filamentDiameterMm, double density)
|
|
|
|
|
|
{
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public override int GetLayerIndex(int instructionIndex)
|
|
|
|
|
|
{
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2017-06-29 13:35:44 -07:00
|
|
|
|
public override int LayerCount
|
2017-06-21 23:26:20 -07:00
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private double feedRateMmPerMin = 0;
|
|
|
|
|
|
private Vector3 lastPrinterPosition = new Vector3();
|
|
|
|
|
|
private double lastEPosition = 0;
|
|
|
|
|
|
|
|
|
|
|
|
public override PrinterMachineInstruction Instruction(int index)
|
|
|
|
|
|
{
|
|
|
|
|
|
lock(locker)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (index < readLineCount - MaxLinesToBuffer)
|
|
|
|
|
|
{
|
|
|
|
|
|
throw new Exception("You are asking for a line we no longer have buffered");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
while (index >= readLineCount)
|
|
|
|
|
|
{
|
|
|
|
|
|
string line = openGcodeStream.ReadLine();
|
|
|
|
|
|
if (line == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
readLastLineOfFile = true;
|
|
|
|
|
|
line = "";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int ringBufferIndex = readLineCount % MaxLinesToBuffer;
|
|
|
|
|
|
readLinesRingBuffer[ringBufferIndex] = new PrinterMachineInstruction(line);
|
|
|
|
|
|
|
|
|
|
|
|
string lineToParse = line.ToUpper().Trim();
|
|
|
|
|
|
if (lineToParse.StartsWith("G0") || lineToParse.StartsWith("G1"))
|
|
|
|
|
|
{
|
|
|
|
|
|
double newFeedRateMmPerMin = 0;
|
|
|
|
|
|
if (GetFirstNumberAfter("F", lineToParse, ref newFeedRateMmPerMin))
|
|
|
|
|
|
{
|
|
|
|
|
|
feedRateMmPerMin = newFeedRateMmPerMin;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Vector3 attemptedDestination = lastPrinterPosition;
|
2017-10-31 12:51:16 -07:00
|
|
|
|
GetFirstNumberAfter("X", lineToParse, ref attemptedDestination.X);
|
|
|
|
|
|
GetFirstNumberAfter("Y", lineToParse, ref attemptedDestination.Y);
|
|
|
|
|
|
GetFirstNumberAfter("Z", lineToParse, ref attemptedDestination.Z);
|
2017-06-21 23:26:20 -07:00
|
|
|
|
|
|
|
|
|
|
double ePosition = lastEPosition;
|
|
|
|
|
|
GetFirstNumberAfter("E", lineToParse, ref ePosition);
|
|
|
|
|
|
|
|
|
|
|
|
lastPrinterPosition = attemptedDestination;
|
|
|
|
|
|
lastEPosition = ePosition;
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (lineToParse.StartsWith("G92"))
|
|
|
|
|
|
{
|
|
|
|
|
|
double ePosition = 0;
|
|
|
|
|
|
if (GetFirstNumberAfter("E", lineToParse, ref ePosition))
|
|
|
|
|
|
{
|
|
|
|
|
|
lastEPosition = ePosition;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
readLineCount++;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return readLinesRingBuffer[index % MaxLinesToBuffer];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2019-05-19 20:10:28 -07:00
|
|
|
|
public override double Ratio0to1IntoContainedLayerSeconds(int instructionIndex)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (ByteCount > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
return BytePosition / (double)ByteCount;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public override double Ratio0to1IntoContainedLayerInstruction(int instructionIndex)
|
2017-06-21 23:26:20 -07:00
|
|
|
|
{
|
2019-03-14 11:45:49 -07:00
|
|
|
|
if (ByteCount > 0)
|
2017-06-21 23:26:20 -07:00
|
|
|
|
{
|
|
|
|
|
|
return BytePosition / (double)ByteCount;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|