mirror of
				https://gitlab.com/freepascal.org/lazarus/lazarus.git
				synced 2025-10-31 06:21:38 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			237 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
			
		
		
	
	
			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.
 | |
| 
 | 
