mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-09-03 10:22:38 +02:00
fpvectorial: Adds support for the arrow entity in both generic fpvectorial and also DXF, and with a rendered directly in fpvectorial. Also fixes the text coordinates in DXF
git-svn-id: trunk@37235 -
This commit is contained in:
parent
a8077ac2d8
commit
43b9f71606
@ -30,7 +30,8 @@ interface
|
|||||||
|
|
||||||
uses
|
uses
|
||||||
Classes, SysUtils, Math,
|
Classes, SysUtils, Math,
|
||||||
fpvectorial, fpimage, fpvutils,
|
fpcanvas, fpimage,
|
||||||
|
fpvectorial, fpvutils,
|
||||||
lconvencoding;
|
lconvencoding;
|
||||||
|
|
||||||
type
|
type
|
||||||
@ -103,6 +104,7 @@ type
|
|||||||
procedure ReadENTITIES_VERTEX(ATokens: TDXFTokens; AData: TvVectorialPage; ADoc: TvVectorialDocument);
|
procedure ReadENTITIES_VERTEX(ATokens: TDXFTokens; AData: TvVectorialPage; ADoc: TvVectorialDocument);
|
||||||
procedure ReadENTITIES_SEQEND(ATokens: TDXFTokens; AData: TvVectorialPage; ADoc: TvVectorialDocument);
|
procedure ReadENTITIES_SEQEND(ATokens: TDXFTokens; AData: TvVectorialPage; ADoc: TvVectorialDocument);
|
||||||
procedure ReadENTITIES_MTEXT(ATokens: TDXFTokens; AData: TvVectorialPage; ADoc: TvVectorialDocument);
|
procedure ReadENTITIES_MTEXT(ATokens: TDXFTokens; AData: TvVectorialPage; ADoc: TvVectorialDocument);
|
||||||
|
procedure ReadENTITIES_LEADER(ATokens: TDXFTokens; AData: TvVectorialPage; ADoc: TvVectorialDocument);
|
||||||
procedure ReadENTITIES_POINT(ATokens: TDXFTokens; AData: TvVectorialPage; ADoc: TvVectorialDocument);
|
procedure ReadENTITIES_POINT(ATokens: TDXFTokens; AData: TvVectorialPage; ADoc: TvVectorialDocument);
|
||||||
function GetCoordinateValue(AStr: shortstring): Double;
|
function GetCoordinateValue(AStr: shortstring): Double;
|
||||||
function ConvertDXFStringToUTF8(AStr: string): string;
|
function ConvertDXFStringToUTF8(AStr: string): string;
|
||||||
@ -741,6 +743,7 @@ begin
|
|||||||
else if CurToken.StrValue = 'SPLINE' then ReadENTITIES_SPLINE(CurToken.Childs, AData, ADoc)
|
else if CurToken.StrValue = 'SPLINE' then ReadENTITIES_SPLINE(CurToken.Childs, AData, ADoc)
|
||||||
else if CurToken.StrValue = 'POINT' then ReadENTITIES_POINT(CurToken.Childs, AData, ADoc)
|
else if CurToken.StrValue = 'POINT' then ReadENTITIES_POINT(CurToken.Childs, AData, ADoc)
|
||||||
else if CurToken.StrValue = 'MTEXT' then ReadENTITIES_MTEXT(CurToken.Childs, AData, ADoc)
|
else if CurToken.StrValue = 'MTEXT' then ReadENTITIES_MTEXT(CurToken.Childs, AData, ADoc)
|
||||||
|
else if CurToken.StrValue = 'LEADER' then ReadENTITIES_LEADER(CurToken.Childs, AData, ADoc)
|
||||||
// A Polyline can have multiple child objects
|
// A Polyline can have multiple child objects
|
||||||
else if CurToken.StrValue = 'POLYLINE' then
|
else if CurToken.StrValue = 'POLYLINE' then
|
||||||
begin
|
begin
|
||||||
@ -1201,7 +1204,7 @@ begin
|
|||||||
|
|
||||||
// Position fixing for documents with negative coordinates
|
// Position fixing for documents with negative coordinates
|
||||||
PosX := PosX - DOC_OFFSET.X;
|
PosX := PosX - DOC_OFFSET.X;
|
||||||
PosY := PosY - DOC_OFFSET.Y;
|
PosY := PosY + FontSize - DOC_OFFSET.Y;
|
||||||
|
|
||||||
// Convert the string if necessary
|
// Convert the string if necessary
|
||||||
Str := ConvertDXFStringToUTF8(Str);
|
Str := ConvertDXFStringToUTF8(Str);
|
||||||
@ -1429,12 +1432,73 @@ begin
|
|||||||
|
|
||||||
// Position fixing for documents with negative coordinates
|
// Position fixing for documents with negative coordinates
|
||||||
PosX := PosX - DOC_OFFSET.X;
|
PosX := PosX - DOC_OFFSET.X;
|
||||||
PosY := PosY - DOC_OFFSET.Y;
|
PosY := PosY + FontSize - DOC_OFFSET.Y;
|
||||||
|
|
||||||
//
|
//
|
||||||
AData.AddText(PosX, PosY, 0, '', Round(FontSize), Str);
|
AData.AddText(PosX, PosY, 0, '', Round(FontSize), Str);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TvDXFVectorialReader.ReadENTITIES_LEADER(ATokens: TDXFTokens;
|
||||||
|
AData: TvVectorialPage; ADoc: TvVectorialDocument);
|
||||||
|
var
|
||||||
|
CurToken: TDXFToken;
|
||||||
|
i, curPoint: Integer;
|
||||||
|
lValueX, lValueY: Double;
|
||||||
|
lArrow: TvArrow;
|
||||||
|
begin
|
||||||
|
lArrow := TvArrow.Create;
|
||||||
|
curPoint := 0;
|
||||||
|
|
||||||
|
for i := 0 to ATokens.Count - 1 do
|
||||||
|
begin
|
||||||
|
// Now read and process the item name
|
||||||
|
CurToken := TDXFToken(ATokens.Items[i]);
|
||||||
|
|
||||||
|
// Avoid an exception by previously checking if the conversion can be made
|
||||||
|
if CurToken.GroupCode in [10, 20, 30, 11, 21, 31] then
|
||||||
|
begin
|
||||||
|
CurToken.FloatValue := StrToFloat(Trim(CurToken.StrValue), FPointSeparator);
|
||||||
|
end;
|
||||||
|
|
||||||
|
// Loads the coordinates
|
||||||
|
// With Position fixing for documents with negative coordinates
|
||||||
|
case CurToken.GroupCode of
|
||||||
|
10:
|
||||||
|
begin
|
||||||
|
// Starting a new point
|
||||||
|
Inc(curPoint);
|
||||||
|
|
||||||
|
lValueX := CurToken.FloatValue - DOC_OFFSET.X;
|
||||||
|
|
||||||
|
case curPoint of
|
||||||
|
1: lArrow.X := lValueX;
|
||||||
|
2: lArrow.Base.X := lValueX;
|
||||||
|
3: lArrow.ExtraLineBase.X := lValueX;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
20:
|
||||||
|
begin
|
||||||
|
lValueY := CurToken.FloatValue - DOC_OFFSET.Y;
|
||||||
|
|
||||||
|
case curPoint of
|
||||||
|
1: lArrow.Y := lValueY;
|
||||||
|
2: lArrow.Base.Y := lValueY;
|
||||||
|
3: lArrow.ExtraLineBase.Y := lValueY;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// Give a % of the line length to the arrow head
|
||||||
|
lArrow.ArrowLength := 0.2 * sqrt(sqr(lArrow.Base.Y - lArrow.Y) + sqr(lArrow.Base.X - lArrow.X));
|
||||||
|
lArrow.ArrowBaseLength := lArrow.ArrowLength / 2;
|
||||||
|
|
||||||
|
// And now write it
|
||||||
|
lArrow.HasExtraLine := True;
|
||||||
|
lArrow.Brush.Style := bsSolid;
|
||||||
|
AData.AddEntity(lArrow);
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TvDXFVectorialReader.ReadENTITIES_POINT(ATokens: TDXFTokens;
|
procedure TvDXFVectorialReader.ReadENTITIES_POINT(ATokens: TDXFTokens;
|
||||||
AData: TvVectorialPage; ADoc: TvVectorialDocument);
|
AData: TvVectorialPage; ADoc: TvVectorialDocument);
|
||||||
var
|
var
|
||||||
|
@ -197,6 +197,7 @@ type
|
|||||||
elements might be able to override this setting. }
|
elements might be able to override this setting. }
|
||||||
Pen: TvPen;
|
Pen: TvPen;
|
||||||
constructor Create; override;
|
constructor Create; override;
|
||||||
|
procedure ApplyPenToCanvas(ADest: TFPCustomCanvas);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TvEntityWithPenAndBrush }
|
{ TvEntityWithPenAndBrush }
|
||||||
@ -207,6 +208,7 @@ type
|
|||||||
elements might be able to override this setting. }
|
elements might be able to override this setting. }
|
||||||
Brush: TvBrush;
|
Brush: TvBrush;
|
||||||
constructor Create; override;
|
constructor Create; override;
|
||||||
|
procedure ApplyBrushToCanvas(ADest: TFPCustomCanvas);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
TvClipMode = (vcmNonzeroWindingRule, vcmEvenOddRule);
|
TvClipMode = (vcmNonzeroWindingRule, vcmEvenOddRule);
|
||||||
@ -320,6 +322,31 @@ type
|
|||||||
public
|
public
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TvArrow }
|
||||||
|
|
||||||
|
//
|
||||||
|
// The arrow look like this:
|
||||||
|
//
|
||||||
|
// A<------|B
|
||||||
|
// |
|
||||||
|
// |C
|
||||||
|
//
|
||||||
|
// A -> X,Y,Z
|
||||||
|
// B -> Base
|
||||||
|
// C -> ExtraLineBase, which exists if HasExtraLine=True
|
||||||
|
|
||||||
|
TvArrow = class(TvEntityWithPenAndBrush)
|
||||||
|
public
|
||||||
|
Base: T3DPoint;
|
||||||
|
HasExtraLine: Boolean;
|
||||||
|
ExtraLineBase: T3DPoint;
|
||||||
|
ArrowLength: Double;
|
||||||
|
ArrowBaseLength: Double;
|
||||||
|
procedure CalculateBoundingBox(ADest: TFPCustomCanvas; var ALeft, ATop, ARight, ABottom: Double); override;
|
||||||
|
procedure Render(ADest: TFPCustomCanvas; ADestX: Integer = 0;
|
||||||
|
ADestY: Integer = 0; AMulX: Double = 1.0; AMulY: Double = 1.0); override;
|
||||||
|
end;
|
||||||
|
|
||||||
{@@
|
{@@
|
||||||
The elements bellow describe a formula
|
The elements bellow describe a formula
|
||||||
|
|
||||||
@ -654,6 +681,13 @@ begin
|
|||||||
Pen.Color := colBlack;
|
Pen.Color := colBlack;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TvEntityWithPen.ApplyPenToCanvas(ADest: TFPCustomCanvas);
|
||||||
|
begin
|
||||||
|
ADest.Pen.FPColor := Pen.Color;
|
||||||
|
ADest.Pen.Width := Pen.Width;
|
||||||
|
ADest.Pen.Style := Pen.Style;
|
||||||
|
end;
|
||||||
|
|
||||||
{ TvEntityWithPenAndBrush }
|
{ TvEntityWithPenAndBrush }
|
||||||
|
|
||||||
constructor TvEntityWithPenAndBrush.Create;
|
constructor TvEntityWithPenAndBrush.Create;
|
||||||
@ -663,6 +697,12 @@ begin
|
|||||||
Brush.Color := colBlue;
|
Brush.Color := colBlue;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TvEntityWithPenAndBrush.ApplyBrushToCanvas(ADest: TFPCustomCanvas);
|
||||||
|
begin
|
||||||
|
ADest.Brush.FPColor := Brush.Color;
|
||||||
|
ADest.Brush.Style := Brush.Style;
|
||||||
|
end;
|
||||||
|
|
||||||
{ TvRasterImage }
|
{ TvRasterImage }
|
||||||
|
|
||||||
procedure TvRasterImage.InitializeWithConvertionOf3DPointsToHeightMap(APage: TvVectorialPage; AWidth, AHeight: Integer);
|
procedure TvRasterImage.InitializeWithConvertionOf3DPointsToHeightMap(APage: TvVectorialPage; AWidth, AHeight: Integer);
|
||||||
@ -710,6 +750,95 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TvArrow }
|
||||||
|
|
||||||
|
procedure TvArrow.CalculateBoundingBox(ADest: TFPCustomCanvas; var ALeft, ATop,
|
||||||
|
ARight, ABottom: Double);
|
||||||
|
begin
|
||||||
|
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TvArrow.Render(ADest: TFPCustomCanvas; ADestX: Integer;
|
||||||
|
ADestY: Integer; AMulX: Double; AMulY: Double);
|
||||||
|
|
||||||
|
function CoordToCanvasX(ACoord: Double): Integer;
|
||||||
|
begin
|
||||||
|
Result := Round(ADestX + AmulX * ACoord);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function CoordToCanvasY(ACoord: Double): Integer;
|
||||||
|
begin
|
||||||
|
Result := Round(ADestY + AmulY * ACoord);
|
||||||
|
end;
|
||||||
|
|
||||||
|
var
|
||||||
|
lArrow, lBase, lExtraBase: TPoint;
|
||||||
|
lPointD, lPointE, lPointF: T3DPoint;
|
||||||
|
lPoints: array[0..2] of TPoint;
|
||||||
|
AlfaAngle: Double;
|
||||||
|
begin
|
||||||
|
ApplyPenToCanvas(ADest);
|
||||||
|
ApplyBrushToCanvas(ADest);
|
||||||
|
|
||||||
|
lArrow.X := CoordToCanvasX(X);
|
||||||
|
lArrow.Y := CoordToCanvasY(Y);
|
||||||
|
lBase.X := CoordToCanvasX(Base.X);
|
||||||
|
lBase.Y := CoordToCanvasY(Base.Y);
|
||||||
|
lExtraBase.X := CoordToCanvasX(ExtraLineBase.X);
|
||||||
|
lExtraBase.Y := CoordToCanvasY(ExtraLineBase.Y);
|
||||||
|
|
||||||
|
// Start with the lines
|
||||||
|
|
||||||
|
ADest.Line(lArrow, lBase);
|
||||||
|
|
||||||
|
if HasExtraLine then
|
||||||
|
ADest.Line(lBase, lExtraBase);
|
||||||
|
|
||||||
|
// Now draw the arrow head
|
||||||
|
lPoints[0].X := CoordToCanvasX(X);
|
||||||
|
lPoints[0].Y := CoordToCanvasY(Y);
|
||||||
|
//
|
||||||
|
// Here a lot of trigonometry comes to play, it is hard to explain in text, but in essence
|
||||||
|
//
|
||||||
|
// A line L is formed by the points A (Arrow head) and B (Base)
|
||||||
|
// Our smaller triangle starts at a point D in this line which has length ArrowLength counting from A
|
||||||
|
// This forms a rectangle triangle with a line paralel to the X axis
|
||||||
|
// Alfa is the angle between A and the line parallel to the X axis
|
||||||
|
//
|
||||||
|
// This brings this equations:
|
||||||
|
// AlfaAngle := arctg((B.Y - A.Y) / (B.X - A.X));
|
||||||
|
// Sin(Alfa) := (D.Y - A.Y) / ArrowLength
|
||||||
|
// Cos(Alfa) := (D.X - A.X) / ArrowLength
|
||||||
|
//
|
||||||
|
// Then at this point D we start a line perpendicular to the line L
|
||||||
|
// And with this line we progress a length of ArrowBaseLength/2
|
||||||
|
// This line, the D point and a line parallel to the Y axis for another
|
||||||
|
// rectangle triangle with the same Alfa angle at the point D
|
||||||
|
// The point at the end of the hipotenuse of this triangle is our point E
|
||||||
|
// So we have more equations:
|
||||||
|
//
|
||||||
|
// Sin(Alfa) := (E.x - D.X) / (ArrowBaseLength/2)
|
||||||
|
// Cos(Alfa) := (E.Y - D.Y) / (ArrowBaseLength/2)
|
||||||
|
//
|
||||||
|
// And the same in the opposite direction for our point F:
|
||||||
|
//
|
||||||
|
// Sin(Alfa) := (D.X - F.X) / (ArrowBaseLength/2)
|
||||||
|
// Cos(Alfa) := (D.Y - F.Y) / (ArrowBaseLength/2)
|
||||||
|
//
|
||||||
|
AlfaAngle := ArcTan((Base.Y - Y) / (Base.X - X));
|
||||||
|
lPointD.Y := Sin(AlfaAngle) * ArrowLength + Y;
|
||||||
|
lPointD.X := Cos(AlfaAngle) * ArrowLength + X;
|
||||||
|
lPointE.X := Sin(AlfaAngle) * (ArrowBaseLength/2) + lPointD.X;
|
||||||
|
lPointE.Y := Cos(AlfaAngle) * (ArrowBaseLength/2) + lPointD.Y;
|
||||||
|
lPointF.X := - Sin(AlfaAngle) * (ArrowBaseLength/2) + lPointD.X;
|
||||||
|
lPointF.Y := - Cos(AlfaAngle) * (ArrowBaseLength/2) + lPointD.Y;
|
||||||
|
lPoints[1].X := CoordToCanvasX(lPointE.X);
|
||||||
|
lPoints[1].Y := CoordToCanvasY(lPointE.Y);
|
||||||
|
lPoints[2].X := CoordToCanvasX(lPointF.X);
|
||||||
|
lPoints[2].Y := CoordToCanvasY(lPointF.Y);
|
||||||
|
ADest.Polygon(lPoints);
|
||||||
|
end;
|
||||||
|
|
||||||
{ TvFormulaElement }
|
{ TvFormulaElement }
|
||||||
|
|
||||||
function TvFormulaElement.CalculateHeight: Single;
|
function TvFormulaElement.CalculateHeight: Single;
|
||||||
|
Loading…
Reference in New Issue
Block a user