diff --git a/applications/fpvviewer/fpvectorialsrc/dxfvectorialreader.pas b/applications/fpvviewer/fpvectorialsrc/dxfvectorialreader.pas index e1964aeb3..021707745 100644 --- a/applications/fpvviewer/fpvectorialsrc/dxfvectorialreader.pas +++ b/applications/fpvviewer/fpvectorialsrc/dxfvectorialreader.pas @@ -29,7 +29,7 @@ unit dxfvectorialreader; interface uses - Classes, SysUtils, + Classes, SysUtils, Math, fpvectorial; type @@ -69,6 +69,9 @@ type // HEADER data ANGBASE: Double; ANGDIR: Integer; + INSBASE, EXTMIN, EXTMAX, LIMMIN, LIMMAX: T3DPoint; + // Calculated HEADER data + DOC_OFFSET: T3DPoint; // function SeparateString(AString: string; ASeparator: Char): T10Strings; procedure ReadHEADER(ATokens: TDXFTokens; AData: TvVectorialDocument); @@ -328,6 +331,7 @@ procedure TvDXFVectorialReader.ReadHEADER(ATokens: TDXFTokens; var i, j: Integer; CurToken: TDXFToken; + CurField: P3DPoint; begin i := 0; while i < ATokens.Count do @@ -346,8 +350,16 @@ begin Inc(i); end // This indicates the size of the document - else if CurToken.StrValue = '$LIMMAX' then + else if (CurToken.StrValue = '$INSBASE') or + (CurToken.StrValue = '$EXTMIN') or (CurToken.StrValue = '$EXTMAX') or + (CurToken.StrValue = '$LIMMIN') or (CurToken.StrValue = '$LIMMAX') then begin + if (CurToken.StrValue = '$INSBASE') then CurField := @INSBASE + else if (CurToken.StrValue = '$EXTMIN') then CurField := @EXTMIN + else if (CurToken.StrValue = '$EXTMAX') then CurField := @EXTMAX + else if (CurToken.StrValue = '$LIMMIN') then CurField := @LIMMIN + else if (CurToken.StrValue = '$LIMMAX') then CurField := @LIMMAX; + // Check the next 2 items and verify if they are the values of the size of the document for j := 0 to 1 do begin @@ -355,12 +367,12 @@ begin case CurToken.GroupCode of 10: begin; - aData.Width := StrToFloat(CurToken.StrValue, FPointSeparator); + CurField^.X := StrToFloat(CurToken.StrValue, FPointSeparator); Inc(i); end; 20: begin - aData.Height := StrToFloat(CurToken.StrValue, FPointSeparator); + CurField^.Y := StrToFloat(CurToken.StrValue, FPointSeparator); Inc(i); end; end; @@ -369,6 +381,37 @@ begin Inc(i); end; + + // After getting all the data, we can try to make so sense out of it + + // Sometimes EXTMIN comes as 10^20 and EXTMAX as -10^20, which makes no sence + // In these cases we need to ignore them. + if (EXTMIN.X > 100000) or (EXTMIN.X < -100000) or (EXTMAX.X > 100000) or (EXTMAX.X < -100000) then + begin + DOC_OFFSET.X := 0; + DOC_OFFSET.Y := 0; + + AData.Width := LIMMAX.X; + AData.Height := LIMMAX.Y; + end + else + begin + // The size of the document seams to be given by: + // DOC_SIZE = min(EXTMAX, LIMMAX) - DOC_OFFSET; + // if EXTMIN is <> -infinite then DOC_OFFSET = EXTMIN else DOC_OFFSET = (0, 0) + // We will shift the whole document so that it has only positive coordinates and + // DOC_OFFSET will be utilized for that + + if EXTMIN.X > -100 then + begin + DOC_OFFSET.X := EXTMIN.X; + DOC_OFFSET.Y := EXTMIN.Y; + end + else FillChar(DOC_OFFSET, sizeof(T3DPoint), #0); + + AData.Width := min(EXTMAX.X, LIMMAX.X) - DOC_OFFSET.X; + AData.Height := min(EXTMAX.Y, LIMMAX.Y) - DOC_OFFSET.Y; + end; end; procedure TvDXFVectorialReader.ReadENTITIES(ATokens: TDXFTokens; AData: TvVectorialDocument); @@ -487,6 +530,9 @@ begin end; end; + CenterX := CenterX - DOC_OFFSET.X; + CenterY := CenterY - DOC_OFFSET.Y; + {$ifdef FPVECTORIALDEBUG} WriteLn(Format('Adding Arc Center=%f,%f Radius=%f StartAngle=%f EndAngle=%f', [CenterX, CenterY, Radius, StartAngle, EndAngle])); diff --git a/applications/fpvviewer/fpvectorialsrc/fpvectorial.pas b/applications/fpvviewer/fpvectorialsrc/fpvectorial.pas index bbc3bf1e8..928b001d1 100644 --- a/applications/fpvviewer/fpvectorialsrc/fpvectorial.pas +++ b/applications/fpvviewer/fpvectorialsrc/fpvectorial.pas @@ -43,6 +43,8 @@ type X, Y, Z: Double; end; + P3DPoint = ^T3DPoint; + TSegmentType = ( st2DLine, st2DBezier, st3DLine, st3DBezier, stMoveTo); diff --git a/applications/fpvviewer/fpvv_mainform.pas b/applications/fpvviewer/fpvv_mainform.pas index 193496580..353faad42 100644 --- a/applications/fpvviewer/fpvv_mainform.pas +++ b/applications/fpvviewer/fpvv_mainform.pas @@ -52,6 +52,7 @@ uses procedure TfrmFPVViewer.btnVisualizeClick(Sender: TObject); var Vec: TvVectorialDocument; + CanvasSize: TPoint; begin // First check the in input //if not CheckInput() then Exit; @@ -65,11 +66,17 @@ begin Vec.ReadFromFile(editFileName.FileName, vfDXF); // We need to be robust, because sometimes the document size won't be given - if Vec.Width < 100 then Vec.Width := Drawer.Width; - if Vec.Height < 100 then Vec.Height := Drawer.Height; + // 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 + else if Vec.Width < 100 then CanvasSize.X := Drawer.Width + else CanvasSize.X := Round(Vec.Width * spinScale.Value); - Drawer.Drawing.Width := Round(Vec.Width * spinScale.Value); - Drawer.Drawing.Height := Round(Vec.Height * spinScale.Value); + if Vec.Height * spinScale.Value > 1000 then CanvasSize.Y := 1000 + else if Vec.Height < 100 then CanvasSize.Y := Drawer.Height + else CanvasSize.Y := Round(Vec.Height * spinScale.Value); + + Drawer.Drawing.Width := CanvasSize.X; + Drawer.Drawing.Height := CanvasSize.Y; Drawer.Drawing.Canvas.Brush.Color := clWhite; Drawer.Drawing.Canvas.Brush.Style := bsSolid; Drawer.Drawing.Canvas.FillRect(0, 0, Drawer.Drawing.Width, Drawer.Drawing.Height);