fpvectorial: Fixes DXF reading of SPLINE and LWPOLYLINE and adds better debug info

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@1546 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
sekelsenmat
2011-04-02 17:01:28 +00:00
parent d28e47e741
commit 0101aea6b7
4 changed files with 60 additions and 38 deletions

View File

@@ -50,6 +50,15 @@ type
Destructor Destroy; override; Destructor Destroy; override;
end; end;
TSPLineElement = record
X, Y: Double;
KnotValue: Integer;
end;
TLWPOLYLINEElement = record
X, Y: Double;
end;
{ TDXFTokenizer } { TDXFTokenizer }
TDXFTokenizer = class TDXFTokenizer = class
@@ -71,7 +80,7 @@ type
ANGDIR: Integer; ANGDIR: Integer;
INSBASE, EXTMIN, EXTMAX, LIMMIN, LIMMAX: T3DPoint; INSBASE, EXTMIN, EXTMAX, LIMMIN, LIMMAX: T3DPoint;
// Calculated HEADER data // Calculated HEADER data
DOC_OFFSET: T3DPoint; DOC_OFFSET: T3DPoint; // The DOC_OFFSET compensates for documents with huge coordinates
// For building the POLYLINE objects which is composed of multiple records // For building the POLYLINE objects which is composed of multiple records
IsReadingPolyline: Boolean; IsReadingPolyline: Boolean;
PolylineX, PolylineY: array of Double; PolylineX, PolylineY: array of Double;
@@ -908,14 +917,14 @@ begin
AData.AddText(PosX, PosY, PosZ, '', Round(FontSize), Str); AData.AddText(PosX, PosY, PosZ, '', Round(FontSize), Str);
end; end;
//{$define FPVECTORIALDEBUG_LWPOLYLINE} {.$define FPVECTORIALDEBUG_LWPOLYLINE}
procedure TvDXFVectorialReader.ReadENTITIES_LWPOLYLINE(ATokens: TDXFTokens; procedure TvDXFVectorialReader.ReadENTITIES_LWPOLYLINE(ATokens: TDXFTokens;
AData: TvVectorialDocument); AData: TvVectorialDocument);
var var
CurToken: TDXFToken; CurToken: TDXFToken;
i, curPoint: Integer; i, curPoint: Integer;
// LINE // LINE
LineX, LineY, LineZ: array of Double; LWPolyline: array of TLWPOLYLINEElement;
begin begin
curPoint := -1; curPoint := -1;
@@ -937,29 +946,26 @@ begin
begin begin
// Starting a new point // Starting a new point
Inc(curPoint); Inc(curPoint);
SetLength(LineX, curPoint+1); SetLength(LWPolyline, curPoint+1);
SetLength(LineY, curPoint+1);
// SetLength(LineZ, curPoint+1);
LineX[curPoint] := CurToken.FloatValue - DOC_OFFSET.X; LWPolyline[curPoint].X := CurToken.FloatValue - DOC_OFFSET.X;
end; end;
20: LineY[curPoint] := CurToken.FloatValue - DOC_OFFSET.Y; 20: LWPolyline[curPoint].Y := CurToken.FloatValue - DOC_OFFSET.Y;
// 30: LineZ[curPoint] := CurToken.FloatValue;
end; end;
end; end;
// And now write it // And now write it
if curPoint >= 0 then // otherwise the polyline is empty of points if curPoint >= 0 then // otherwise the polyline is empty of points
begin begin
AData.StartPath(LineX[0], LineY[0]); AData.StartPath(LWPolyline[0].X, LWPolyline[0].Y);
{$ifdef FPVECTORIALDEBUG_LWPOLYLINE} {$ifdef FPVECTORIALDEBUG_LWPOLYLINE}
Write(Format('LWPOLYLINE %f,%f', [LineX[0], LineY[0]])); Write(Format('LWPOLYLINE ID=%d %f,%f', [AData.PathCount-1, LWPolyline[0].X, LWPolyline[0].Y]));
{$endif} {$endif}
for i := 1 to curPoint do for i := 1 to curPoint do
begin begin
AData.AddLineToPath(LineX[i], LineX[i]); AData.AddLineToPath(LWPolyline[i].X, LWPolyline[i].Y);
{$ifdef FPVECTORIALDEBUG_LWPOLYLINE} {$ifdef FPVECTORIALDEBUG_LWPOLYLINE}
Write(Format(' %f,%f', [LineX[i], LineX[i]])); Write(Format(' %f,%f', [LWPolyline[i].X, LWPolyline[i].Y]));
{$endif} {$endif}
end; end;
{$ifdef FPVECTORIALDEBUG_LWPOLYLINE} {$ifdef FPVECTORIALDEBUG_LWPOLYLINE}
@@ -969,14 +975,14 @@ begin
end; end;
end; end;
{$define FPVECTORIALDEBUG_SPLINE} {.$define FPVECTORIALDEBUG_SPLINE}
procedure TvDXFVectorialReader.ReadENTITIES_SPLINE(ATokens: TDXFTokens; procedure TvDXFVectorialReader.ReadENTITIES_SPLINE(ATokens: TDXFTokens;
AData: TvVectorialDocument); AData: TvVectorialDocument);
var var
CurToken: TDXFToken; CurToken: TDXFToken;
i, curPoint: Integer; i, curPoint: Integer;
// LINE // LINE
LineX, LineY{, LineZ}: array of Double; SPLine: array of TSPLineElement;
begin begin
curPoint := -1; curPoint := -1;
@@ -998,29 +1004,26 @@ begin
begin begin
// Starting a new point // Starting a new point
Inc(curPoint); Inc(curPoint);
SetLength(LineX, curPoint+1); SetLength(SPLine, curPoint+1);
SetLength(LineY, curPoint+1);
// SetLength(LineZ, curPoint+1);
LineX[curPoint] := CurToken.FloatValue - DOC_OFFSET.X; SPLine[curPoint].X := CurToken.FloatValue - DOC_OFFSET.X;
end; end;
20: LineY[curPoint] := CurToken.FloatValue - DOC_OFFSET.Y; 20: SPLine[curPoint].Y := CurToken.FloatValue - DOC_OFFSET.Y;
// 30: LineZ[curPoint] := CurToken.FloatValue;
end; end;
end; end;
// And now write it // And now write it
if curPoint >= 0 then // otherwise the polyline is empty of points if curPoint >= 0 then // otherwise the polyline is empty of points
begin begin
AData.StartPath(LineX[0], LineY[0]); AData.StartPath(SPLine[0].X, SPLine[0].Y);
{$ifdef FPVECTORIALDEBUG_SPLINE} {$ifdef FPVECTORIALDEBUG_SPLINE}
Write(Format('SPLINE %f,%f', [LineX[0], LineY[0]])); Write(Format('SPLINE ID=%d %f,%f', [AData.PathCount-1, SPLine[0].X, SPLine[0].Y]));
{$endif} {$endif}
for i := 1 to curPoint do for i := 1 to curPoint do
begin begin
AData.AddLineToPath(LineX[i], LineX[i]); AData.AddLineToPath(SPLine[i].X, SPLine[i].Y);
{$ifdef FPVECTORIALDEBUG_SPLINE} {$ifdef FPVECTORIALDEBUG_SPLINE}
Write(Format(' %f,%f', [LineX[i], LineX[i]])); Write(Format(' %f,%f', [SPLine[i].X, SPLine[i].Y]));
{$endif} {$endif}
end; end;
{$ifdef FPVECTORIALDEBUG_SPLINE} {$ifdef FPVECTORIALDEBUG_SPLINE}

View File

@@ -94,6 +94,7 @@ end;
DrawFPVectorialToCanvas(ASource, ADest, 0, ASource.Height, 1.0, -1.0); DrawFPVectorialToCanvas(ASource, ADest, 0, ASource.Height, 1.0, -1.0);
} }
{.$define FPVECTORIAL_TOCANVAS_DEBUG}
procedure DrawFPVectorialToCanvas(ASource: TvVectorialDocument; procedure DrawFPVectorialToCanvas(ASource: TvVectorialDocument;
{$ifdef USE_LCL_CANVAS} {$ifdef USE_LCL_CANVAS}
ADest: TCanvas; ADest: TCanvas;
@@ -138,7 +139,7 @@ var
Points: array of TPoint; Points: array of TPoint;
UpperDim, LowerDim: T3DPoint; UpperDim, LowerDim: T3DPoint;
begin begin
{$ifdef FPVECTORIALDEBUG} {$ifdef FPVECTORIAL_TOCANVAS_DEBUG}
WriteLn(':>DrawFPVectorialToCanvas'); WriteLn(':>DrawFPVectorialToCanvas');
{$endif} {$endif}
@@ -154,6 +155,10 @@ begin
//WriteLn('i = ', i); //WriteLn('i = ', i);
ASource.Paths[i].PrepareForSequentialReading; ASource.Paths[i].PrepareForSequentialReading;
{$ifdef FPVECTORIAL_TOCANVAS_DEBUG}
Write(Format('[Path] ID=%d', [i]));
{$endif}
for j := 0 to ASource.Paths[i].Len - 1 do for j := 0 to ASource.Paths[i].Len - 1 do
begin begin
//WriteLn('j = ', j); //WriteLn('j = ', j);
@@ -163,10 +168,16 @@ begin
stMoveTo: stMoveTo:
begin begin
ADest.MoveTo(CoordToCanvasX(Cur2DSegment.X), CoordToCanvasY(Cur2DSegment.Y)); ADest.MoveTo(CoordToCanvasX(Cur2DSegment.X), CoordToCanvasY(Cur2DSegment.Y));
{$ifdef FPVECTORIAL_TOCANVAS_DEBUG}
Write(Format(' M%d,%d', [CoordToCanvasX(Cur2DSegment.X), CoordToCanvasY(Cur2DSegment.Y)]));
{$endif}
end; end;
st2DLine, st3DLine: st2DLine, st3DLine:
begin begin
ADest.LineTo(CoordToCanvasX(Cur2DSegment.X), CoordToCanvasY(Cur2DSegment.Y)); ADest.LineTo(CoordToCanvasX(Cur2DSegment.X), CoordToCanvasY(Cur2DSegment.Y));
{$ifdef FPVECTORIAL_TOCANVAS_DEBUG}
Write(Format(' L%d,%d', [CoordToCanvasX(Cur2DSegment.X), CoordToCanvasY(Cur2DSegment.Y)]));
{$endif}
end; end;
{ To draw a bezier we need to divide the interval in parts and make { To draw a bezier we need to divide the interval in parts and make
lines between this parts } lines between this parts }
@@ -189,6 +200,9 @@ begin
end; end;
end; end;
end; end;
{$ifdef FPVECTORIAL_TOCANVAS_DEBUG}
WriteLn('');
{$endif}
end; end;
// Draws all entities // Draws all entities

View File

@@ -11,7 +11,7 @@ object frmFPVViewer: TfrmFPVViewer
LCLVersion = '0.9.31' LCLVersion = '0.9.31'
object editFileName: TFileNameEdit object editFileName: TFileNameEdit
Left = 8 Left = 8
Height = 25 Height = 22
Top = 8 Top = 8
Width = 304 Width = 304
DialogOptions = [] DialogOptions = []
@@ -33,7 +33,7 @@ object frmFPVViewer: TfrmFPVViewer
end end
object spinScale: TFloatSpinEdit object spinScale: TFloatSpinEdit
Left = 72 Left = 72
Height = 25 Height = 16
Top = 72 Top = 72
Width = 168 Width = 168
DecimalPlaces = 6 DecimalPlaces = 6
@@ -45,9 +45,9 @@ object frmFPVViewer: TfrmFPVViewer
end end
object Label1: TLabel object Label1: TLabel
Left = 8 Left = 8
Height = 18 Height = 17
Top = 79 Top = 79
Width = 58 Width = 56
Caption = 'Scale by:' Caption = 'Scale by:'
ParentColor = False ParentColor = False
end end
@@ -76,8 +76,8 @@ object frmFPVViewer: TfrmFPVViewer
object pageViewer: TPage object pageViewer: TPage
end end
object Page2: TPage object Page2: TPage
ClientWidth = 132 ClientWidth = 264
ClientHeight = 156 ClientHeight = 312
object DXFTreeView: TTreeView object DXFTreeView: TTreeView
Left = 8 Left = 8
Height = 313 Height = 313

View File

@@ -50,6 +50,10 @@ uses
{ TfrmFPVViewer } { TfrmFPVViewer }
procedure TfrmFPVViewer.btnVisualizeClick(Sender: TObject); procedure TfrmFPVViewer.btnVisualizeClick(Sender: TObject);
const
FPVVIEWER_MAX_IMAGE_SIZE = 1000;
FPVVIEWER_MIN_IMAGE_SIZE = 100;
FPVVIEWER_SPACE_FOR_NEGATIVE_COORDS = 100;
var var
Vec: TvVectorialDocument; Vec: TvVectorialDocument;
CanvasSize: TPoint; CanvasSize: TPoint;
@@ -67,12 +71,13 @@ begin
// We need to be robust, because sometimes the document size won't be given // We need to be robust, because sometimes the document size won't be given
// also give up drawing everything if we need more then 4MB of RAM for the image // also give up drawing everything if we need more then 4MB of RAM for the image
if Vec.Width * spinScale.Value > 1000 then CanvasSize.X := 1000 // and also give some space in the image to allow for negative coordinates
else if Vec.Width < 100 then CanvasSize.X := Drawer.Width if Vec.Width * spinScale.Value > FPVVIEWER_MAX_IMAGE_SIZE then CanvasSize.X := FPVVIEWER_MAX_IMAGE_SIZE
else if Vec.Width < FPVVIEWER_MIN_IMAGE_SIZE then CanvasSize.X := Drawer.Width
else CanvasSize.X := Round(Vec.Width * spinScale.Value); else CanvasSize.X := Round(Vec.Width * spinScale.Value);
if Vec.Height * spinScale.Value > 1000 then CanvasSize.Y := 1000 if Vec.Height * spinScale.Value > FPVVIEWER_MAX_IMAGE_SIZE then CanvasSize.Y := FPVVIEWER_MAX_IMAGE_SIZE
else if Vec.Height < 100 then CanvasSize.Y := Drawer.Height else if Vec.Height < FPVVIEWER_MIN_IMAGE_SIZE then CanvasSize.Y := Drawer.Height
else CanvasSize.Y := Round(Vec.Height * spinScale.Value); else CanvasSize.Y := Round(Vec.Height * spinScale.Value);
Drawer.Drawing.Width := CanvasSize.X; Drawer.Drawing.Width := CanvasSize.X;
@@ -83,8 +88,8 @@ begin
DrawFPVectorialToCanvas( DrawFPVectorialToCanvas(
Vec, Vec,
Drawer.Drawing.Canvas, Drawer.Drawing.Canvas,
0, FPVVIEWER_SPACE_FOR_NEGATIVE_COORDS,
Drawer.Drawing.Height, Drawer.Drawing.Height - FPVVIEWER_SPACE_FOR_NEGATIVE_COORDS,
spinScale.Value, spinScale.Value,
-1 * spinScale.Value); -1 * spinScale.Value);
Drawer.Invalidate; Drawer.Invalidate;