mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-07-29 15:36:47 +02:00
fpvectorial: Adds support for radial/diametral dimensions in both generic fpvectorial and in the DXF reader
git-svn-id: trunk@39186 -
This commit is contained in:
parent
2c2ab8a509
commit
74b95eaefd
@ -1138,7 +1138,7 @@ Group codes Description
|
||||
220, 230 DXF: Y and Z values of extrusion direction (optional)
|
||||
3 Dimension style name
|
||||
|
||||
Aligned Dimension Group Codes
|
||||
*Aligned Dimension Group Codes
|
||||
|
||||
100 Subclass marker (AcDbAlignedDimension)
|
||||
12 Insertion point for clones of a dimension-Baseline and Continue (in OCS) DXF: X value; APP: 3D point
|
||||
@ -1152,6 +1152,18 @@ Aligned Dimension Group Codes
|
||||
| |
|
||||
| |
|
||||
X->14,24 X->13,23
|
||||
|
||||
*Radial and Diameter Dimension Group Codes
|
||||
http://www.autodesk.com/techpubs/autocad/acadr14/dxf/index.htm
|
||||
|
||||
100 Subclass marker (AcDbRadialDimension or AcDbDiametricDimension)
|
||||
15 Definition point for diameter, radius, and angular dimensions (in WCS). DXF: X value; APP: 3D point
|
||||
25, 35 DXF: Y and Z values of definition point for diameter, radius, and angular dimensions (in WCS).
|
||||
40 Leader length for radius and diameter dimensions.
|
||||
|
||||
The point (15,25,35) specifies the first point of the dimension line on the circle/arc
|
||||
and the point (10,20,30) specifies the point opposite the first point.
|
||||
The point (11,21,31) specifies the midpoint of the dimension text.
|
||||
}
|
||||
procedure TvDXFVectorialReader.ReadENTITIES_DIMENSION(ATokens: TDXFTokens;
|
||||
AData: TvVectorialPage; ADoc: TvVectorialDocument);
|
||||
@ -1160,7 +1172,10 @@ var
|
||||
i: Integer;
|
||||
// DIMENSION
|
||||
BaseLeft, BaseRight, DimensionRight, DimensionLeft, TmpPoint: T3DPoint;
|
||||
lCenter, Dim1, Dim5: T3DPoint;
|
||||
IsAlignedDimension: Boolean = False;
|
||||
IsRadialDimension: Boolean = False;
|
||||
IsDiametricDimension: Boolean = False;
|
||||
begin
|
||||
// Initial values
|
||||
BaseLeft.X := 0;
|
||||
@ -1178,7 +1193,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] then
|
||||
if CurToken.GroupCode in [10, 20, 30, 11, 21, 31, 13, 23, 33, 14, 24, 34, 15, 25, 35] then
|
||||
begin
|
||||
CurToken.FloatValue := StrToFloat(Trim(CurToken.StrValue), FPointSeparator);
|
||||
end;
|
||||
@ -1187,15 +1202,23 @@ begin
|
||||
10: DimensionRight.X := CurToken.FloatValue;
|
||||
20: DimensionRight.Y := CurToken.FloatValue;
|
||||
30: DimensionRight.Z := CurToken.FloatValue;
|
||||
11: Dim1.X := CurToken.FloatValue;
|
||||
21: Dim1.Y := CurToken.FloatValue;
|
||||
31: Dim1.Z := CurToken.FloatValue;
|
||||
13: BaseRight.X := CurToken.FloatValue;
|
||||
23: BaseRight.Y := CurToken.FloatValue;
|
||||
33: BaseRight.Z := CurToken.FloatValue;
|
||||
14: BaseLeft.X := CurToken.FloatValue;
|
||||
24: BaseLeft.Y := CurToken.FloatValue;
|
||||
34: BaseLeft.Z := CurToken.FloatValue;
|
||||
15: Dim5.X := CurToken.FloatValue;
|
||||
25: Dim5.Y := CurToken.FloatValue;
|
||||
35: Dim5.Z := CurToken.FloatValue;
|
||||
100:
|
||||
begin
|
||||
if CurToken.StrValue = 'AcDbAlignedDimension' then IsAlignedDimension := True;
|
||||
if CurToken.StrValue = 'AcDbAlignedDimension' then IsAlignedDimension := True
|
||||
else if CurToken.StrValue = 'AcDbRadialDimension' then IsRadialDimension := True
|
||||
else if CurToken.StrValue = 'AcDbDiametricDimension' then IsDiametricDimension := True;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
@ -1257,6 +1280,28 @@ begin
|
||||
end;
|
||||
|
||||
AData.AddAlignedDimension(BaseLeft, BaseRight, DimensionLeft, DimensionRight);
|
||||
end
|
||||
// Radius and Diameters are very similar
|
||||
else if IsRadialDimension or IsDiametricDimension then
|
||||
begin
|
||||
if IsRadialDimension then
|
||||
begin
|
||||
lCenter.X := DimensionRight.X;
|
||||
lCenter.Y := DimensionRight.Y;
|
||||
DimensionLeft.X := Dim5.X;
|
||||
DimensionLeft.Y := Dim5.Y;
|
||||
end
|
||||
else
|
||||
begin
|
||||
lCenter.X := Dim1.X;
|
||||
lCenter.Y := Dim1.Y;
|
||||
DimensionLeft.X := Dim5.X;
|
||||
DimensionLeft.Y := Dim5.Y;
|
||||
DimensionRight.X := DimensionRight.X;
|
||||
DimensionRight.Y := DimensionRight.Y;
|
||||
end;
|
||||
|
||||
AData.AddRadialDimension(IsDiametricDimension, lCenter, DimensionLeft, DimensionRight);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
@ -337,6 +337,21 @@ type
|
||||
ADestY: Integer = 0; AMulX: Double = 1.0; AMulY: Double = 1.0); override;
|
||||
end;
|
||||
|
||||
{@@
|
||||
|
||||
}
|
||||
|
||||
{ TvRadialDimension }
|
||||
|
||||
TvRadialDimension = class(TvEntityWithPen)
|
||||
public
|
||||
// Mandatory fields
|
||||
IsDiameter: Boolean; // If false, it is a radius, if true, it is a diameter
|
||||
Center, DimensionLeft, DimensionRight: T3DPoint; // Diameter uses both, Radius uses only DImensionLeft
|
||||
procedure Render(ADest: TFPCustomCanvas; ADestX: Integer = 0;
|
||||
ADestY: Integer = 0; AMulX: Double = 1.0; AMulY: Double = 1.0); override;
|
||||
end;
|
||||
|
||||
{@@
|
||||
Vectorial images can contain raster images inside them and this entity
|
||||
represents this.
|
||||
@ -614,6 +629,7 @@ type
|
||||
function AddInsert(AX, AY, AZ: Double; ABlock: TvBlock): TvInsert;
|
||||
// Dimensions
|
||||
procedure AddAlignedDimension(BaseLeft, BaseRight, DimLeft, DimRight: T3DPoint);
|
||||
procedure AddRadialDimension(AIsDiameter: Boolean; ACenter, ADimLeft, ADimRight: T3DPoint);
|
||||
//
|
||||
function AddPoint(AX, AY, AZ: Double): TvPoint;
|
||||
{ Debug methods }
|
||||
@ -1615,6 +1631,93 @@ begin
|
||||
ADest.TextOut(CoordToCanvasX(CurDim.BaseLeft.X), CoordToCanvasY(CurDim.BaseLeft.Y), 'BL');}
|
||||
end;
|
||||
|
||||
{ TvRadialDimension }
|
||||
|
||||
procedure TvRadialDimension.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
|
||||
Points: array of TPoint;
|
||||
lAngle, lRadius: Double;
|
||||
{$ifdef USE_LCL_CANVAS}
|
||||
ALCLDest: TCanvas absolute ADest;
|
||||
{$endif}
|
||||
begin
|
||||
// The size of the radius of the circle
|
||||
lRadius := sqrt(sqr(Center.X - DimensionLeft.X) + sqr(Center.Y - DimensionLeft.Y));
|
||||
// The angle to the first dimension
|
||||
lAngle := arctan((DimensionLeft.Y - Center.Y) / (DimensionLeft.X - Center.X));
|
||||
|
||||
// Get an arrow in the right part of the circle
|
||||
SetLength(Points, 3);
|
||||
ADest.Brush.FPColor := colBlack;
|
||||
ADest.Brush.Style := bsSolid;
|
||||
Points[0] := Point(CoordToCanvasX(Center.X + lRadius), CoordToCanvasY(Center.Y));
|
||||
Points[1] := Point(CoordToCanvasX(Center.X + lRadius*0.8), CoordToCanvasY(Center.Y - lRadius*0.1));
|
||||
Points[2] := Point(CoordToCanvasX(Center.X + lRadius*0.8), CoordToCanvasY(Center.Y + lRadius*0.1));
|
||||
// Now rotate it to the actual position
|
||||
Points[0] := Rotate2DPoint(Points[0], Point(CoordToCanvasX(Center.X), CoordToCanvasY(Center.Y)), lAngle);
|
||||
Points[1] := Rotate2DPoint(Points[1], Point(CoordToCanvasX(Center.X), CoordToCanvasY(Center.Y)), lAngle);
|
||||
Points[2] := Rotate2DPoint(Points[2], Point(CoordToCanvasX(Center.X), CoordToCanvasY(Center.Y)), lAngle);
|
||||
|
||||
if not IsDiameter then
|
||||
begin
|
||||
// Basic line
|
||||
ADest.MoveTo(CoordToCanvasX(Center.X), CoordToCanvasY(Center.Y));
|
||||
ADest.LineTo(CoordToCanvasX(DimensionLeft.X), CoordToCanvasY(DimensionLeft.Y));
|
||||
|
||||
// Draw the arrow
|
||||
ADest.Polygon(Points);
|
||||
ADest.Brush.Style := bsClear;
|
||||
|
||||
// Dimension text
|
||||
Points[0].X := CoordToCanvasX(Center.X);
|
||||
Points[0].Y := CoordToCanvasY(Center.Y);
|
||||
ADest.Font.Size := 10;
|
||||
ADest.TextOut(Points[0].X, Points[0].Y, Format('%.1f', [lRadius]));
|
||||
end
|
||||
else
|
||||
begin
|
||||
// Basic line
|
||||
ADest.MoveTo(CoordToCanvasX(DimensionLeft.X), CoordToCanvasY(DimensionLeft.Y));
|
||||
ADest.LineTo(CoordToCanvasX(DimensionRight.X), CoordToCanvasY(DimensionRight.Y));
|
||||
|
||||
// Draw the first arrow
|
||||
ADest.Polygon(Points);
|
||||
ADest.Brush.Style := bsClear;
|
||||
|
||||
// And the second
|
||||
Points[0] := Point(CoordToCanvasX(Center.X + lRadius), CoordToCanvasY(Center.Y));
|
||||
Points[1] := Point(CoordToCanvasX(Center.X + lRadius*0.8), CoordToCanvasY(Center.Y - lRadius*0.1));
|
||||
Points[2] := Point(CoordToCanvasX(Center.X + lRadius*0.8), CoordToCanvasY(Center.Y + lRadius*0.1));
|
||||
// Now rotate it to the actual position
|
||||
Points[0] := Rotate2DPoint(Points[0], Point(CoordToCanvasX(Center.X), CoordToCanvasY(Center.Y)), lAngle + Pi);
|
||||
Points[1] := Rotate2DPoint(Points[1], Point(CoordToCanvasX(Center.X), CoordToCanvasY(Center.Y)), lAngle + Pi);
|
||||
Points[2] := Rotate2DPoint(Points[2], Point(CoordToCanvasX(Center.X), CoordToCanvasY(Center.Y)), lAngle + Pi);
|
||||
//
|
||||
ADest.Polygon(Points);
|
||||
ADest.Brush.Style := bsClear;
|
||||
|
||||
// Dimension text
|
||||
Points[0].X := CoordToCanvasX(Center.X);
|
||||
Points[0].Y := CoordToCanvasY(Center.Y);
|
||||
ADest.Font.Size := 10;
|
||||
ADest.TextOut(Points[0].X, Points[0].Y, Format('%.1f', [lRadius * 2]));
|
||||
end;
|
||||
|
||||
SetLength(Points, 0);
|
||||
end;
|
||||
|
||||
{ TvRasterImage }
|
||||
|
||||
procedure TvRasterImage.InitializeWithConvertionOf3DPointsToHeightMap(APage: TvVectorialPage; AWidth, AHeight: Integer);
|
||||
@ -2733,6 +2836,19 @@ begin
|
||||
AddEntity(lDim);
|
||||
end;
|
||||
|
||||
procedure TvVectorialPage.AddRadialDimension(AIsDiameter: Boolean; ACenter,
|
||||
ADimLeft, ADimRight: T3DPoint);
|
||||
var
|
||||
lDim: TvRadialDimension;
|
||||
begin
|
||||
lDim := TvRadialDimension.Create;
|
||||
lDim.IsDiameter := AIsDiameter;
|
||||
lDim.Center := ACenter;
|
||||
lDim.DimensionLeft := ADimLeft;
|
||||
lDim.DimensionRight := ADimRight;
|
||||
AddEntity(lDim);
|
||||
end;
|
||||
|
||||
function TvVectorialPage.AddPoint(AX, AY, AZ: Double): TvPoint;
|
||||
var
|
||||
lPoint: TvPoint;
|
||||
|
@ -46,7 +46,8 @@ procedure EllipticalArcToBezier(Xc, Yc, Rx, Ry, startAngle, endAngle: Double; va
|
||||
procedure CircularArcToBezier(Xc, Yc, R, startAngle, endAngle: Double; var P1, P2, P3, P4: T3DPoint);
|
||||
procedure AddBezierToPoints(P1, P2, P3, P4: T3DPoint; var Points: TPointsArray);
|
||||
procedure ConvertPathToPoints(APath: TPath; ADestX, ADestY: Integer; AMulX, AMulY: Double; var Points: TPointsArray);
|
||||
function Rotate2DPoint(P,Fix :TPoint; alpha:double): TPoint;
|
||||
function Rotate2DPoint(P, Fix: TPoint; alpha:double): TPoint;
|
||||
function Rotate3DPointInXY(P, Fix: T3DPoint; alpha:double): T3DPoint;
|
||||
// LCL-related routines
|
||||
{$ifdef USE_LCL_CANVAS}
|
||||
function ConvertPathToRegion(APath: TPath; ADestX, ADestY: Integer; AMulX, AMulY: Double): HRGN;
|
||||
@ -274,6 +275,7 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
// Rotates a point P around Fix
|
||||
function Rotate2DPoint(P,Fix :TPoint; alpha:double): TPoint;
|
||||
var
|
||||
sinus, cosinus : Extended;
|
||||
@ -285,6 +287,18 @@ begin
|
||||
result.y := Round(-p.x*sinus + p.y*cosinus) + Fix.y;
|
||||
end;
|
||||
|
||||
// Rotates a point P around Fix
|
||||
function Rotate3DPointInXY(P, Fix: T3DPoint; alpha:double): T3DPoint;
|
||||
var
|
||||
sinus, cosinus : Extended;
|
||||
begin
|
||||
SinCos(alpha, sinus, cosinus);
|
||||
P.x := P.x - Fix.x;
|
||||
P.y := P.y - Fix.y;
|
||||
result.x := Round(p.x*cosinus + p.y*sinus) + fix.x;
|
||||
result.y := Round(-p.x*sinus + p.y*cosinus) + Fix.y;
|
||||
end;
|
||||
|
||||
{$ifdef USE_LCL_CANVAS}
|
||||
function ConvertPathToRegion(APath: TPath; ADestX, ADestY: Integer; AMulX, AMulY: Double): HRGN;
|
||||
var
|
||||
|
Loading…
Reference in New Issue
Block a user