lazarus/components/fpvectorial/avisocncgcodereader.pas
sekelsenmat fb8a2a5c4b Adding fpvectorial to the Lazarus repository
git-svn-id: trunk@33179 -
2011-10-30 16:41:36 +00:00

237 lines
5.6 KiB
ObjectPascal

{
Reads AvisoCNC G-Code
License: The same modified LGPL as the Free Pascal RTL
See the file COPYING.modifiedLGPL for more details
AUTHORS: Felipe Monteiro de Carvalho
Pedro Sol Pegorini L de Lima
}
unit avisocncgcodereader;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils,
fpvectorial;
type
{ Used by tcutils.SeparateString }
T10Strings = array[0..9] of shortstring;
{ TvAvisoCNCGCodeReader }
TvAvisoCNCGCodeReader = class(TvCustomVectorialReader)
private
LastX, LastY, LastZ: Double;
function SeparateString(AString: string; ASeparator: Char): T10Strings;
procedure ReadString(AStr: string; AData: TvVectorialPage);
function GetCoordinate(AStr: shortstring): Integer;
function GetCoordinateValue(AStr: shortstring): Double;
public
{ General reading methods }
procedure ReadFromStrings(AStrings: TStrings; AData: TvVectorialDocument); override;
end;
implementation
const
{ Coordinate constants }
INT_COORDINATE_NONE = 0;
INT_COORDINATE_X = 1;
INT_COORDINATE_Y = 2;
INT_COORDINATE_Z = 3;
{ GCode constants }
STR_GCODE_LINEAR_MOVE = 'G01';
STR_GCODE_STEPPER_MOVE = 'S01';
STR_GCODE_2DBEZIER_MOVE = 'B02';
STR_GCODE_3DBEZIER_MOVE = 'B03';
STR_GCODE_DRILL_UP = 'P01';
STR_GCODE_DRILL_DOWN = 'P02';
{ TvAvisoCNCGCodeReader }
{@@
Reads a string and separates it in substring
using ASeparator to delimite them.
Limits:
Number of substrings: 10 (indexed 0 to 9)
Length of each substring: 255 (they are shortstrings)
}
function TvAvisoCNCGCodeReader.SeparateString(AString: string; ASeparator: Char): T10Strings;
var
i, CurrentPart: Integer;
begin
CurrentPart := 0;
{ Clears the result }
for i := 0 to 9 do Result[i] := '';
{ Iterates througth the string, filling strings }
for i := 1 to Length(AString) do
begin
if Copy(AString, i, 1) = ASeparator then
begin
Inc(CurrentPart);
{ Verifies if the string capacity wasn't exceeded }
if CurrentPart > 9 then Exit;
end
else
Result[CurrentPart] := Result[CurrentPart] + Copy(AString, i, 1);
end;
end;
procedure TvAvisoCNCGCodeReader.ReadString(AStr: string;
AData: TvVectorialPage);
var
AParams: T10Strings;
DestX, DestY, DestZ: Double;
i: Integer;
begin
{$ifdef FPVECTORIALDEBUG}
WriteLn('TvAvisoCNCGCodeReader.ReadString ', AStr);
{$endif}
AParams := SeparateString(AStr, ' ');
{
Format may be:
G01 X3
G01 X3 Y4
G01 X3 Y4 Z2
}
if AParams[0] = STR_GCODE_DRILL_UP then
begin
AData.AddLineToPath(LastX, LastY, 0);
LastZ := 0;
end
else if AParams[0] = STR_GCODE_DRILL_DOWN then
begin
AData.AddLineToPath(LastX, LastY, 50);
LastZ := 50;
end
else if AParams[0] = STR_GCODE_LINEAR_MOVE then
begin
DestX := LastX;
DestY := LastY;
DestZ := LastZ;
for i := 1 to 3 do
begin
case GetCoordinate(AParams[i]) of
INT_COORDINATE_X: DestX := GetCoordinateValue(AParams[i]);
INT_COORDINATE_Y: DestY := GetCoordinateValue(AParams[i]);
INT_COORDINATE_Z: DestZ := GetCoordinateValue(AParams[i]);
else
// error
end;
end;
AData.AddLineToPath(DestX, DestY, DestZ);
LastX := DestX;
LastY := DestY;
LastZ := DestZ;
end
else if AParams[0] = STR_GCODE_2DBEZIER_MOVE then
begin
AData.AddBezierToPath(
GetCoordinateValue(AParams[1]),
GetCoordinateValue(AParams[2]),
GetCoordinateValue(AParams[3]),
GetCoordinateValue(AParams[4]),
GetCoordinateValue(AParams[5]),
GetCoordinateValue(AParams[6])
);
LastX := GetCoordinateValue(AParams[5]);
LastY := GetCoordinateValue(AParams[6]);
end
else if AParams[0] = STR_GCODE_3DBEZIER_MOVE then
begin
AData.AddBezierToPath(
GetCoordinateValue(AParams[1]),
GetCoordinateValue(AParams[2]),
GetCoordinateValue(AParams[3]),
GetCoordinateValue(AParams[4]),
GetCoordinateValue(AParams[5]),
GetCoordinateValue(AParams[6]),
GetCoordinateValue(AParams[7]),
GetCoordinateValue(AParams[8]),
GetCoordinateValue(AParams[9])
);
LastX := GetCoordinateValue(AParams[7]);
LastY := GetCoordinateValue(AParams[8]);
LastZ := GetCoordinateValue(AParams[9]);
end;
{else
begin
Ignore any of these codes:
STR_GCODE_STEPPER_MOVE
and anything else
end;}
end;
function TvAvisoCNCGCodeReader.GetCoordinate(AStr: shortstring): Integer;
begin
Result := INT_COORDINATE_NONE;
if AStr = '' then Exit
else if AStr[1] = 'X' then Result := INT_COORDINATE_X
else if AStr[1] = 'Y' then Result := INT_COORDINATE_Y
else if AStr[1] = 'Z' then Result := INT_COORDINATE_Z;
end;
function TvAvisoCNCGCodeReader.GetCoordinateValue(AStr: shortstring): Double;
begin
Result := 0.0;
if Length(AStr) <= 1 then Exit;
Result := StrToFloat(Copy(AStr, 2, Length(AStr) - 1));
end;
{@@
The information of each separate path is lost in G-Code files
Only one path uniting all of them is created when reading G-Code
}
procedure TvAvisoCNCGCodeReader.ReadFromStrings(AStrings: TStrings;
AData: TvVectorialDocument);
var
i: Integer;
FirstPage: TvVectorialPage;
begin
{$ifdef FPVECTORIALDEBUG}
WriteLn('TvAvisoCNCGCodeReader.ReadFromStrings AStrings = ', PtrInt(AStrings), ' AData = ', PtrInt(AData));
{$endif}
FirstPage := AData.AddPage();
FirstPage.StartPath(0, 0);
for i := 0 to AStrings.Count - 1 do
ReadString(AStrings.Strings[i], FirstPage);
{$ifdef FPVECTORIALDEBUG}
WriteLn('AData.EndPath');
{$endif}
FirstPage.EndPath();
end;
initialization
RegisterVectorialReader(TvAvisoCNCGCodeReader, vfGCodeAvisoCNCPrototipoV5);
end.