mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-18 12:49:42 +02:00
fpvectorial: Finishes the basic implementation for arc dimensions in fpvectorial base and the DXF reader
git-svn-id: trunk@40601 -
This commit is contained in:
parent
2b2a84006d
commit
114a0f6e2d
@ -1288,7 +1288,9 @@ var
|
||||
i: Integer;
|
||||
// DIMENSION
|
||||
BaseLeft, BaseRight, DimensionRight, DimensionLeft, lCenter, lTextPos, TmpPoint: T3DPoint;
|
||||
TmpDimensionRight, TmpDimensionLeft: T3DPoint;
|
||||
Dim0, Dim1, Dim3, Dim4, Dim5, Dim6: T3DPoint;
|
||||
lAngleLeft, lAngleRight, al, bl, lRadius, lBaskaraDelta, ae, be, ce: Double;
|
||||
DXFDimensionType: TDXFDimensionType = ddtUnknown;
|
||||
begin
|
||||
// Initial values
|
||||
@ -1308,7 +1310,7 @@ begin
|
||||
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, 13, 23, 33, 14, 24, 34, 15, 25, 35] then
|
||||
if CurToken.GroupCode in [10, 20, 30, 11, 21, 31, 13, 23, 33, 14, 24, 34, 15, 25, 35, 16, 26, 36] then
|
||||
begin
|
||||
CurToken.FloatValue := StrToFloat(Trim(CurToken.StrValue), FPointSeparator);
|
||||
end;
|
||||
@ -1365,6 +1367,9 @@ begin
|
||||
{$ifdef FPVECTORIALDEBUG}
|
||||
// WriteLn(Format('Adding Line from %f,%f to %f,%f', [LineStartX, LineStartY, LineEndX, LineEndY]));
|
||||
{$endif}
|
||||
// -----------------------------------------------
|
||||
// Aligned dimension
|
||||
// -----------------------------------------------
|
||||
if DXFDimensionType = ddtAligned then
|
||||
begin
|
||||
// Now make sure that we actually that BaseLeft is to the left of BaseRight
|
||||
@ -1419,7 +1424,9 @@ begin
|
||||
|
||||
Result := AData.AddAlignedDimension(BaseLeft, BaseRight, DimensionLeft, DimensionRight, AOnlyCreate);
|
||||
end
|
||||
// -----------------------------------------------
|
||||
// Radius and Diameters are very similar
|
||||
// -----------------------------------------------
|
||||
else if DXFDimensionType in [ddtRadial, ddtDiametric] then
|
||||
begin
|
||||
if DXFDimensionType = ddtRadial then
|
||||
@ -1437,17 +1444,72 @@ begin
|
||||
|
||||
Result := AData.AddRadialDimension(DXFDimensionType = ddtDiametric, lCenter, DimensionLeft, DimensionRight, AOnlyCreate);
|
||||
end
|
||||
// -----------------------------------------------
|
||||
// A arc dimension
|
||||
// -----------------------------------------------
|
||||
else if DXFDimensionType = ddt2LineAngular then
|
||||
begin
|
||||
BaseLeft := Dim5;
|
||||
BaseRight := Dim3;
|
||||
DimensionLeft := Dim0;
|
||||
DimensionRight := Dim4;
|
||||
lCenter := Dim6;
|
||||
lTextPos := Dim1;
|
||||
|
||||
Result := AData.AddArcDimension(BaseLeft, BaseRight, DimensionLeft, DimensionRight, lCenter, lTextPos, AOnlyCreate);
|
||||
// Sometimes Dim0 and Dim3 are the base, but sometimes Dim4 and Dim5 are the base!
|
||||
// So we need to check which points are nearer o.O
|
||||
// I plotted the given points to come to this conclusion
|
||||
// and it doesn't match the provided example image:
|
||||
// http://docs.autodesk.com/ACD/2013/RUS/images/GUID-E2F42FD3-2684-4F50-88A9-3AF3A5824FF1-low.png
|
||||
// but it works. The pairs of points in the same line are 3,4 and 0,5
|
||||
if Abs(Dim0.X-Dim3.X)+Abs(Dim0.Y-Dim3.Y) < Abs(Dim5.X-Dim4.X)+Abs(Dim5.Y-Dim4.Y) then
|
||||
begin
|
||||
BaseLeft := Dim0;
|
||||
BaseRight := Dim3;
|
||||
TmpDimensionLeft := Dim5;
|
||||
TmpDimensionRight := Dim4;
|
||||
end
|
||||
else
|
||||
begin
|
||||
BaseLeft := Dim4;
|
||||
BaseRight := Dim5;
|
||||
TmpDimensionLeft := Dim3;
|
||||
TmpDimensionRight := Dim0;
|
||||
end;
|
||||
|
||||
// Calculate where the arc hits the left and right lines to obtain DimensionLeft and DimensionRight
|
||||
// Left line is: Y = al.X + bl
|
||||
// Circle equation for the arc is (X - BaseLeft.X)^2 + (Y - BaseLeft.Y)^2 = R^2
|
||||
// This goes to a second degree equation of ae * X^2 + be * X + ce = 0
|
||||
lAngleLeft := arctan(Abs(BaseLeft.Y-TmpDimensionLeft.Y)/Abs(BaseLeft.X-TmpDimensionLeft.X));
|
||||
if TmpDimensionLeft.X<BaseLeft.X then lAngleLeft := Pi-lAngleLeft;
|
||||
lRadius := sqrt(sqr(lCenter.Y-BaseLeft.Y) + sqr(lCenter.X-BaseLeft.X));
|
||||
al := Tan(lAngleLeft);
|
||||
bl := BaseLeft.Y - al * BaseLeft.X;
|
||||
ae := 1 + al*al;
|
||||
be := -2 * BaseLeft.X + 2 * al * bl - 2 * al * BaseLeft.Y;
|
||||
ce := sqr(BaseLeft.X)+bl*bl-2*bl*BaseLeft.Y+sqr(BaseLeft.Y)-lRadius*lRadius;
|
||||
lBaskaraDelta := be*be-4*ae*ce;
|
||||
// The equation has 2 solutions, get the one nearest to TmpDimension
|
||||
DimensionLeft.X := (-be+sqrt(lBaskaraDelta)) / (2 * ae);
|
||||
DimensionLeft.Y := (-be-sqrt(lBaskaraDelta)) / (2 * ae);
|
||||
if Abs(DimensionLeft.X-TmpDimensionLeft.X)>Abs(DimensionLeft.Y-TmpDimensionLeft.X)then
|
||||
DimensionLeft.X := DimensionLeft.Y;
|
||||
DimensionLeft.Y := al * DimensionLeft.X + bl;
|
||||
|
||||
lAngleRight := arctan(Abs(BaseRight.Y-TmpDimensionRight.Y)/Abs(BaseRight.X-TmpDimensionRight.X));
|
||||
if TmpDimensionRight.X<BaseRight.X then lAngleRight := Pi-lAngleRight;
|
||||
al := Tan(lAngleRight);
|
||||
bl := BaseRight.Y - al * BaseRight.X;
|
||||
ae := 1 + al*al;
|
||||
be := -2 * BaseRight.X + 2 * al * bl - 2 * al * BaseRight.Y;
|
||||
ce := sqr(BaseRight.X)+bl*bl-2*bl*BaseRight.Y+sqr(BaseRight.Y)-lRadius*lRadius;
|
||||
lBaskaraDelta := be*be-4*ae*ce;
|
||||
// The equation has 2 solutions, get the one nearest to TmpDimension
|
||||
DimensionRight.X := (-be+sqrt(lBaskaraDelta)) / (2 * ae);
|
||||
DimensionRight.Y := (-be-sqrt(lBaskaraDelta)) / (2 * ae);
|
||||
if Abs(DimensionRight.X-TmpDimensionRight.X)>Abs(DimensionRight.Y-TmpDimensionRight.X)then
|
||||
DimensionRight.X := DimensionRight.Y;
|
||||
DimensionRight.Y := al * DimensionRight.X + bl;
|
||||
|
||||
Result := AData.AddArcDimension(180*Abs(lAngleRight-lAngleLeft)/Pi,
|
||||
lRadius, BaseLeft, BaseRight, DimensionLeft, DimensionRight, lTextPos, AOnlyCreate);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
@ -463,8 +463,8 @@ type
|
||||
TvArcDimension = class(TvEntityWithPen)
|
||||
public
|
||||
// Mandatory fields
|
||||
ArcValue: Double;
|
||||
DimArcPos, TextPos, BaseLeft, BaseRight, DimensionLeft, DimensionRight: T3DPoint;
|
||||
ArcValue, ArcRadius: Double; // ArcValue is in degrees
|
||||
TextPos, BaseLeft, BaseRight, DimensionLeft, DimensionRight: T3DPoint;
|
||||
procedure Render(ADest: TFPCustomCanvas; ARenderInfo: TvRenderInfo; ADestX: Integer = 0;
|
||||
ADestY: Integer = 0; AMulX: Double = 1.0; AMulY: Double = 1.0); override;
|
||||
function GenerateDebugTree(ADestRoutine: TvDebugAddItemProc; APageItem: Pointer): Pointer; override;
|
||||
@ -788,7 +788,7 @@ type
|
||||
// Dimensions
|
||||
function AddAlignedDimension(BaseLeft, BaseRight, DimLeft, DimRight: T3DPoint; AOnlyCreate: Boolean = False): TvAlignedDimension;
|
||||
function AddRadialDimension(AIsDiameter: Boolean; ACenter, ADimLeft, ADimRight: T3DPoint; AOnlyCreate: Boolean = False): TvRadialDimension;
|
||||
function AddArcDimension(ABaseLeft, ABaseRight, ADimLeft, ADimRight, ADimArcPos, ATextPos: T3DPoint; AOnlyCreate: Boolean = False): TvArcDimension;
|
||||
function AddArcDimension(AArcValue, AArcRadius: Double; ABaseLeft, ABaseRight, ADimLeft, ADimRight, ATextPos: T3DPoint; AOnlyCreate: Boolean): TvArcDimension;
|
||||
//
|
||||
function AddPoint(AX, AY, AZ: Double): TvPoint;
|
||||
{ Drawing methods }
|
||||
@ -2374,19 +2374,28 @@ var
|
||||
Points: array of TPoint;
|
||||
lAngleLeft, lAngleRight: Double;
|
||||
lTriangleCenter, lTriangleCorner, lCanvasDim: TPoint;
|
||||
{$ifdef USE_LCL_CANVAS}
|
||||
ALCLDest: TCanvas absolute ADest;
|
||||
{$endif}
|
||||
begin
|
||||
ADest.Pen.FPColor := colYellow;//AdjustColorToBackground(colBlack, ARenderInfo);
|
||||
ADest.Pen.Width := 1;
|
||||
ADest.Pen.Style := psSolid;
|
||||
|
||||
// Get an arrow in the right part of the circle
|
||||
SetLength(Points, 3);
|
||||
ADest.Line(CoordToCanvasX(BaseLeft.X), CoordToCanvasY(BaseLeft.Y), CoordToCanvasX(DimensionLeft.X), CoordToCanvasY(DimensionLeft.Y));
|
||||
ADest.Line(CoordToCanvasX(BaseRight.X), CoordToCanvasY(BaseRight.Y), CoordToCanvasX(DimensionRight.X), CoordToCanvasY(DimensionRight.Y));
|
||||
// Debug lines
|
||||
//ADest.Line(CoordToCanvasX(BaseLeft.X), CoordToCanvasY(BaseLeft.Y), CoordToCanvasX(DimensionLeft.X), CoordToCanvasY(DimensionLeft.Y));
|
||||
//ADest.Line(CoordToCanvasX(BaseRight.X), CoordToCanvasY(BaseRight.Y), CoordToCanvasX(DimensionRight.X), CoordToCanvasY(DimensionRight.Y));
|
||||
|
||||
// Now the arc
|
||||
ALCLDest.Arc(
|
||||
CoordToCanvasX(BaseLeft.X - ArcRadius), CoordToCanvasY(BaseLeft.Y - ArcRadius),
|
||||
CoordToCanvasX(BaseLeft.X + ArcRadius), CoordToCanvasY(BaseLeft.Y + ArcRadius),
|
||||
CoordToCanvasX(DimensionRight.X), CoordToCanvasY(DimensionRight.Y),
|
||||
CoordToCanvasX(DimensionLeft.X), CoordToCanvasY(DimensionLeft.Y));
|
||||
|
||||
// Now the arrows
|
||||
SetLength(Points, 3);
|
||||
ADest.Brush.FPColor := AdjustColorToBackground(colBlack, ARenderInfo);
|
||||
{ ADest.Brush.FPColor := AdjustColorToBackground(colBlack, ARenderInfo);
|
||||
ADest.Brush.Style := bsSolid;
|
||||
|
||||
// Angle of the line of BaseLeft->DimensionLeft
|
||||
@ -2402,16 +2411,15 @@ begin
|
||||
lTriangleCorner := Rotate2DPoint(lTriangleCenter, lCanvasDim, - Pi * 10 / 180);
|
||||
Points[2] := Point(lTriangleCorner.X, lTriangleCorner.Y);
|
||||
ADest.Polygon(Points);
|
||||
ADest.Brush.Style := bsClear;
|
||||
ADest.Brush.Style := bsClear; }
|
||||
|
||||
// Dimension text
|
||||
{ Points[0].X := CoordToCanvasX((DimensionLeft.X+DimensionRight.X)/2);
|
||||
Points[0].Y := CoordToCanvasY(DimensionLeft.Y);
|
||||
LowerDim.X := DimensionRight.X-DimensionLeft.X;
|
||||
Points[0].X := CoordToCanvasX(TextPos.X);
|
||||
Points[0].Y := CoordToCanvasY(TextPos.Y);
|
||||
ADest.Font.Size := 10;
|
||||
ADest.Font.Orientation := 0;
|
||||
ADest.Font.FPColor := AdjustColorToBackground(colBlack, ARenderInfo);
|
||||
ADest.TextOut(Points[0].X, Points[0].Y-Round(ADest.Font.Size*1.5), Format('%.1f', [LowerDim.X]));}
|
||||
ADest.Font.FPColor := colYellow;//AdjustColorToBackground(colBlack, ARenderInfo);
|
||||
ADest.TextOut(Points[0].X, Points[0].Y-Round(ADest.Font.Size*1.5), Format('%.1f', [ArcValue]));
|
||||
end;
|
||||
|
||||
function TvArcDimension.GenerateDebugTree(ADestRoutine: TvDebugAddItemProc;
|
||||
@ -2422,8 +2430,8 @@ var
|
||||
begin
|
||||
Result := inherited GenerateDebugTree(ADestRoutine, APageItem);
|
||||
// Add the font debug info in a sub-item
|
||||
lStr := Format('[TvArcDimension] DimArcPos=%f %f TextPos=%f %f BaseLeft=%f %f BaseRight=%f %f DimensionLeft=%f %f DimensionRight=%f %f',
|
||||
[DimArcPos.X, DimArcPos.Y,
|
||||
lStr := Format('[TvArcDimension] ArcValue=%f ArcRadius=%f TextPos=%f %f BaseLeft=%f %f BaseRight=%f %f DimensionLeft=%f %f DimensionRight=%f %f',
|
||||
[ArcValue, ArcRadius,
|
||||
TextPos.X, TextPos.Y,
|
||||
BaseLeft.X, BaseLeft.Y,
|
||||
BaseRight.X, BaseRight.Y,
|
||||
@ -3707,7 +3715,7 @@ begin
|
||||
if not AOnlyCreate then AddEntity(lDim);
|
||||
end;
|
||||
|
||||
function TvVectorialPage.AddArcDimension(ABaseLeft, ABaseRight, ADimLeft, ADimRight, ADimArcPos, ATextPos: T3DPoint; AOnlyCreate: Boolean): TvArcDimension;
|
||||
function TvVectorialPage.AddArcDimension(AArcValue, AArcRadius: Double; ABaseLeft, ABaseRight, ADimLeft, ADimRight, ATextPos: T3DPoint; AOnlyCreate: Boolean): TvArcDimension;
|
||||
var
|
||||
lDim: TvArcDimension;
|
||||
begin
|
||||
@ -3716,7 +3724,8 @@ begin
|
||||
lDim.BaseRight := ABaseRight;
|
||||
lDim.DimensionLeft := ADimLeft;
|
||||
lDim.DimensionRight := ADimRight;
|
||||
lDim.DimArcPos := ADimArcPos;
|
||||
lDim.ArcRadius := AArcRadius;
|
||||
lDim.ArcValue := AArcValue;
|
||||
lDim.TextPos := ATextPos;
|
||||
Result := lDim;
|
||||
if not AOnlyCreate then AddEntity(lDim);
|
||||
|
Loading…
Reference in New Issue
Block a user