mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-02 12:17:21 +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)
|
220, 230 DXF: Y and Z values of extrusion direction (optional)
|
||||||
3 Dimension style name
|
3 Dimension style name
|
||||||
|
|
||||||
Aligned Dimension Group Codes
|
*Aligned Dimension Group Codes
|
||||||
|
|
||||||
100 Subclass marker (AcDbAlignedDimension)
|
100 Subclass marker (AcDbAlignedDimension)
|
||||||
12 Insertion point for clones of a dimension-Baseline and Continue (in OCS) DXF: X value; APP: 3D point
|
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
|
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;
|
procedure TvDXFVectorialReader.ReadENTITIES_DIMENSION(ATokens: TDXFTokens;
|
||||||
AData: TvVectorialPage; ADoc: TvVectorialDocument);
|
AData: TvVectorialPage; ADoc: TvVectorialDocument);
|
||||||
@ -1160,7 +1172,10 @@ var
|
|||||||
i: Integer;
|
i: Integer;
|
||||||
// DIMENSION
|
// DIMENSION
|
||||||
BaseLeft, BaseRight, DimensionRight, DimensionLeft, TmpPoint: T3DPoint;
|
BaseLeft, BaseRight, DimensionRight, DimensionLeft, TmpPoint: T3DPoint;
|
||||||
|
lCenter, Dim1, Dim5: T3DPoint;
|
||||||
IsAlignedDimension: Boolean = False;
|
IsAlignedDimension: Boolean = False;
|
||||||
|
IsRadialDimension: Boolean = False;
|
||||||
|
IsDiametricDimension: Boolean = False;
|
||||||
begin
|
begin
|
||||||
// Initial values
|
// Initial values
|
||||||
BaseLeft.X := 0;
|
BaseLeft.X := 0;
|
||||||
@ -1178,7 +1193,7 @@ begin
|
|||||||
CurToken := TDXFToken(ATokens.Items[i]);
|
CurToken := TDXFToken(ATokens.Items[i]);
|
||||||
|
|
||||||
// Avoid an exception by previously checking if the conversion can be made
|
// 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
|
begin
|
||||||
CurToken.FloatValue := StrToFloat(Trim(CurToken.StrValue), FPointSeparator);
|
CurToken.FloatValue := StrToFloat(Trim(CurToken.StrValue), FPointSeparator);
|
||||||
end;
|
end;
|
||||||
@ -1187,15 +1202,23 @@ begin
|
|||||||
10: DimensionRight.X := CurToken.FloatValue;
|
10: DimensionRight.X := CurToken.FloatValue;
|
||||||
20: DimensionRight.Y := CurToken.FloatValue;
|
20: DimensionRight.Y := CurToken.FloatValue;
|
||||||
30: DimensionRight.Z := 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;
|
13: BaseRight.X := CurToken.FloatValue;
|
||||||
23: BaseRight.Y := CurToken.FloatValue;
|
23: BaseRight.Y := CurToken.FloatValue;
|
||||||
33: BaseRight.Z := CurToken.FloatValue;
|
33: BaseRight.Z := CurToken.FloatValue;
|
||||||
14: BaseLeft.X := CurToken.FloatValue;
|
14: BaseLeft.X := CurToken.FloatValue;
|
||||||
24: BaseLeft.Y := CurToken.FloatValue;
|
24: BaseLeft.Y := CurToken.FloatValue;
|
||||||
34: BaseLeft.Z := CurToken.FloatValue;
|
34: BaseLeft.Z := CurToken.FloatValue;
|
||||||
|
15: Dim5.X := CurToken.FloatValue;
|
||||||
|
25: Dim5.Y := CurToken.FloatValue;
|
||||||
|
35: Dim5.Z := CurToken.FloatValue;
|
||||||
100:
|
100:
|
||||||
begin
|
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;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -1257,6 +1280,28 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
AData.AddAlignedDimension(BaseLeft, BaseRight, DimensionLeft, DimensionRight);
|
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;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -337,6 +337,21 @@ type
|
|||||||
ADestY: Integer = 0; AMulX: Double = 1.0; AMulY: Double = 1.0); override;
|
ADestY: Integer = 0; AMulX: Double = 1.0; AMulY: Double = 1.0); override;
|
||||||
end;
|
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
|
Vectorial images can contain raster images inside them and this entity
|
||||||
represents this.
|
represents this.
|
||||||
@ -614,6 +629,7 @@ type
|
|||||||
function AddInsert(AX, AY, AZ: Double; ABlock: TvBlock): TvInsert;
|
function AddInsert(AX, AY, AZ: Double; ABlock: TvBlock): TvInsert;
|
||||||
// Dimensions
|
// Dimensions
|
||||||
procedure AddAlignedDimension(BaseLeft, BaseRight, DimLeft, DimRight: T3DPoint);
|
procedure AddAlignedDimension(BaseLeft, BaseRight, DimLeft, DimRight: T3DPoint);
|
||||||
|
procedure AddRadialDimension(AIsDiameter: Boolean; ACenter, ADimLeft, ADimRight: T3DPoint);
|
||||||
//
|
//
|
||||||
function AddPoint(AX, AY, AZ: Double): TvPoint;
|
function AddPoint(AX, AY, AZ: Double): TvPoint;
|
||||||
{ Debug methods }
|
{ Debug methods }
|
||||||
@ -1615,6 +1631,93 @@ begin
|
|||||||
ADest.TextOut(CoordToCanvasX(CurDim.BaseLeft.X), CoordToCanvasY(CurDim.BaseLeft.Y), 'BL');}
|
ADest.TextOut(CoordToCanvasX(CurDim.BaseLeft.X), CoordToCanvasY(CurDim.BaseLeft.Y), 'BL');}
|
||||||
end;
|
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 }
|
{ TvRasterImage }
|
||||||
|
|
||||||
procedure TvRasterImage.InitializeWithConvertionOf3DPointsToHeightMap(APage: TvVectorialPage; AWidth, AHeight: Integer);
|
procedure TvRasterImage.InitializeWithConvertionOf3DPointsToHeightMap(APage: TvVectorialPage; AWidth, AHeight: Integer);
|
||||||
@ -2733,6 +2836,19 @@ begin
|
|||||||
AddEntity(lDim);
|
AddEntity(lDim);
|
||||||
end;
|
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;
|
function TvVectorialPage.AddPoint(AX, AY, AZ: Double): TvPoint;
|
||||||
var
|
var
|
||||||
lPoint: TvPoint;
|
lPoint: TvPoint;
|
||||||
|
@ -47,6 +47,7 @@ procedure CircularArcToBezier(Xc, Yc, R, startAngle, endAngle: Double; var P1, P
|
|||||||
procedure AddBezierToPoints(P1, P2, P3, P4: T3DPoint; var Points: TPointsArray);
|
procedure AddBezierToPoints(P1, P2, P3, P4: T3DPoint; var Points: TPointsArray);
|
||||||
procedure ConvertPathToPoints(APath: TPath; ADestX, ADestY: Integer; AMulX, AMulY: Double; 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
|
// LCL-related routines
|
||||||
{$ifdef USE_LCL_CANVAS}
|
{$ifdef USE_LCL_CANVAS}
|
||||||
function ConvertPathToRegion(APath: TPath; ADestX, ADestY: Integer; AMulX, AMulY: Double): HRGN;
|
function ConvertPathToRegion(APath: TPath; ADestX, ADestY: Integer; AMulX, AMulY: Double): HRGN;
|
||||||
@ -274,6 +275,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
// Rotates a point P around Fix
|
||||||
function Rotate2DPoint(P,Fix :TPoint; alpha:double): TPoint;
|
function Rotate2DPoint(P,Fix :TPoint; alpha:double): TPoint;
|
||||||
var
|
var
|
||||||
sinus, cosinus : Extended;
|
sinus, cosinus : Extended;
|
||||||
@ -285,6 +287,18 @@ begin
|
|||||||
result.y := Round(-p.x*sinus + p.y*cosinus) + Fix.y;
|
result.y := Round(-p.x*sinus + p.y*cosinus) + Fix.y;
|
||||||
end;
|
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}
|
{$ifdef USE_LCL_CANVAS}
|
||||||
function ConvertPathToRegion(APath: TPath; ADestX, ADestY: Integer; AMulX, AMulY: Double): HRGN;
|
function ConvertPathToRegion(APath: TPath; ADestX, ADestY: Integer; AMulX, AMulY: Double): HRGN;
|
||||||
var
|
var
|
||||||
|
Loading…
Reference in New Issue
Block a user