mirror of
				https://gitlab.com/freepascal.org/lazarus/lazarus.git
				synced 2025-10-31 17:21:34 +01: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
	 sekelsenmat
						sekelsenmat