You've already forked lazarus-ccr
fpvectorial: Removes unused Z coordinates and makes the entity classes smarter, adds support for searching for elements
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@1808 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -590,7 +590,7 @@ begin
|
||||
WriteLn(Format('Adding Arc Center=%f,%f Radius=%f StartAngle=%f EndAngle=%f',
|
||||
[CenterX, CenterY, Radius, StartAngle, EndAngle]));
|
||||
{$endif}
|
||||
AData.AddCircularArc(CenterX, CenterY, CenterZ, Radius, StartAngle, EndAngle, LColor);
|
||||
AData.AddCircularArc(CenterX, CenterY, Radius, StartAngle, EndAngle, LColor);
|
||||
end;
|
||||
|
||||
{
|
||||
@ -638,8 +638,7 @@ begin
|
||||
CircleCenterX := CircleCenterX - DOC_OFFSET.X;
|
||||
CircleCenterY := CircleCenterY - DOC_OFFSET.Y;
|
||||
|
||||
AData.AddCircle(CircleCenterX, CircleCenterY,
|
||||
CircleCenterZ, CircleRadius);
|
||||
AData.AddCircle(CircleCenterX, CircleCenterY, CircleRadius);
|
||||
end;
|
||||
|
||||
{
|
||||
@ -845,7 +844,7 @@ begin
|
||||
CenterY := CenterY - DOC_OFFSET.Y;
|
||||
|
||||
//
|
||||
AData.AddEllipse(CenterX, CenterY, CenterZ, MajorHalfAxis, MinorHalfAxis, Angle);
|
||||
AData.AddEllipse(CenterX, CenterY, MajorHalfAxis, MinorHalfAxis, Angle);
|
||||
end;
|
||||
|
||||
{
|
||||
@ -916,7 +915,7 @@ begin
|
||||
PosY := PosY - DOC_OFFSET.Y;
|
||||
|
||||
//
|
||||
AData.AddText(PosX, PosY, PosZ, '', Round(FontSize), Str);
|
||||
AData.AddText(PosX, PosY, '', Round(FontSize), Str);
|
||||
end;
|
||||
|
||||
{.$define FPVECTORIALDEBUG_LWPOLYLINE}
|
||||
@ -1141,7 +1140,7 @@ begin
|
||||
PosY := PosY - DOC_OFFSET.Y;
|
||||
|
||||
//
|
||||
AData.AddText(PosX, PosY, PosZ, '', Round(FontSize), Str);
|
||||
AData.AddText(PosX, PosY, '', Round(FontSize), Str);
|
||||
end;
|
||||
|
||||
procedure TvDXFVectorialReader.ReadENTITIES_POINT(ATokens: TDXFTokens;
|
||||
@ -1179,8 +1178,7 @@ begin
|
||||
CircleCenterX := CircleCenterX - DOC_OFFSET.X;
|
||||
CircleCenterY := CircleCenterY - DOC_OFFSET.Y;
|
||||
|
||||
AData.AddCircle(CircleCenterX, CircleCenterY,
|
||||
CircleCenterZ, CircleRadius);
|
||||
AData.AddCircle(CircleCenterX, CircleCenterY, CircleRadius);
|
||||
end;
|
||||
|
||||
function TvDXFVectorialReader.GetCoordinateValue(AStr: shortstring): Double;
|
||||
|
@ -139,6 +139,8 @@ type
|
||||
X3, Y3, Z3: Double;
|
||||
end;
|
||||
|
||||
TvFindEntityResult = (vfrNotFound, vfrFound, vfrSubpartFound);
|
||||
|
||||
{ Now all elements }
|
||||
|
||||
{@@
|
||||
@ -150,6 +152,7 @@ type
|
||||
|
||||
TvEntity = class
|
||||
public
|
||||
X, Y: Double;
|
||||
{@@ The global Pen for the entire entity. In the case of paths, individual
|
||||
elements might be able to override this setting. }
|
||||
Pen: TvPen;
|
||||
@ -159,6 +162,7 @@ type
|
||||
constructor Create; virtual;
|
||||
procedure CalculateBoundingBox(var ALeft, ATop, ARight, ABottom: Double); virtual;
|
||||
procedure ExpandBoundingBox(var ALeft, ATop, ARight, ABottom: Double);
|
||||
function TryToSelect(APos: TPoint): TvFindEntityResult; virtual;
|
||||
end;
|
||||
|
||||
TvClipMode = (vcmNonzeroWindingRule, vcmEvenOddRule);
|
||||
@ -174,30 +178,34 @@ type
|
||||
procedure PrepareForSequentialReading;
|
||||
function Next(): TPathSegment;
|
||||
procedure CalculateBoundingBox(var ALeft, ATop, ARight, ABottom: Double); override;
|
||||
procedure AppendSegment(ASegment: TPathSegment);
|
||||
end;
|
||||
|
||||
{@@
|
||||
TvText represents a text entity.
|
||||
}
|
||||
|
||||
{ TvText }
|
||||
|
||||
TvText = class(TvEntity)
|
||||
public
|
||||
X, Y, Z: Double; // Z is ignored in 2D formats
|
||||
Value: utf8string;
|
||||
Font: TvFont;
|
||||
function TryToSelect(APos: TPoint): TvFindEntityResult; override;
|
||||
end;
|
||||
|
||||
{@@
|
||||
}
|
||||
TvCircle = class(TvEntity)
|
||||
public
|
||||
CenterX, CenterY, CenterZ, Radius: Double;
|
||||
Radius: Double;
|
||||
end;
|
||||
|
||||
{@@
|
||||
}
|
||||
TvCircularArc = class(TvEntity)
|
||||
public
|
||||
CenterX, CenterY, CenterZ, Radius: Double;
|
||||
Radius: Double;
|
||||
{@@ The Angle is measured in degrees in relation to the positive X axis }
|
||||
StartAngle, EndAngle: Double;
|
||||
end;
|
||||
@ -207,7 +215,7 @@ type
|
||||
TvEllipse = class(TvEntity)
|
||||
public
|
||||
// Mandatory fields
|
||||
CenterX, CenterY, CenterZ, MajorHalfAxis, MinorHalfAxis: Double;
|
||||
MajorHalfAxis, MinorHalfAxis: Double;
|
||||
{@@ The Angle is measured in degrees in relation to the positive X axis }
|
||||
Angle: Double;
|
||||
// Calculated fields
|
||||
@ -272,6 +280,8 @@ type
|
||||
Name: string;
|
||||
// User-Interface information
|
||||
ZoomLevel: Double; // 1 = 100%
|
||||
{ Selection fields }
|
||||
SelectedvElement: TvEntity;
|
||||
{ Base methods }
|
||||
constructor Create; virtual;
|
||||
destructor Destroy; override;
|
||||
@ -294,10 +304,11 @@ type
|
||||
function GetPathCount: Integer;
|
||||
function GetEntity(ANum: Cardinal): TvEntity;
|
||||
function GetEntitiesCount: Integer;
|
||||
function FindAndSelectEntity(Pos: TPoint): TvFindEntityResult;
|
||||
{ Data removing methods }
|
||||
procedure Clear; virtual;
|
||||
{ Data writing methods }
|
||||
procedure AddEntity(AEntity: TvEntity);
|
||||
function AddEntity(AEntity: TvEntity): Integer;
|
||||
procedure AddPathCopyMem(APath: TPath);
|
||||
procedure StartPath(AX, AY: Double); overload;
|
||||
procedure StartPath(); overload;
|
||||
@ -315,11 +326,11 @@ type
|
||||
procedure SetPenWidth(AWidth: Integer);
|
||||
procedure SetClipPath(AClipPath: TPath; AClipMode: TvClipMode);
|
||||
procedure EndPath();
|
||||
procedure AddText(AX, AY, AZ: Double; FontName: string; FontSize: integer; AText: utf8string); overload;
|
||||
procedure AddText(AX, AY, AZ: Double; AStr: utf8string); overload;
|
||||
procedure AddCircle(ACenterX, ACenterY, ACenterZ, ARadius: Double);
|
||||
procedure AddCircularArc(ACenterX, ACenterY, ACenterZ, ARadius, AStartAngle, AEndAngle: Double; AColor: TFPColor);
|
||||
procedure AddEllipse(CenterX, CenterY, CenterZ, MajorHalfAxis, MinorHalfAxis, Angle: Double);
|
||||
procedure AddText(AX, AY: Double; FontName: string; FontSize: integer; AText: utf8string); overload;
|
||||
procedure AddText(AX, AY: Double; AStr: utf8string); overload;
|
||||
procedure AddCircle(ACenterX, ACenterY, ARadius: Double);
|
||||
procedure AddCircularArc(ACenterX, ACenterY, ARadius, AStartAngle, AEndAngle: Double; AColor: TFPColor);
|
||||
procedure AddEllipse(CenterX, CenterY, MajorHalfAxis, MinorHalfAxis, Angle: Double);
|
||||
// Dimensions
|
||||
procedure AddAlignedDimension(BaseLeft, BaseRight, DimLeft, DimRight: T3DPoint);
|
||||
{ properties }
|
||||
@ -476,6 +487,19 @@ begin
|
||||
Result.Z := 0;
|
||||
end;
|
||||
|
||||
{ TvText }
|
||||
|
||||
function TvText.TryToSelect(APos: TPoint): TvFindEntityResult;
|
||||
var
|
||||
lProximityFactor: Integer;
|
||||
begin
|
||||
lProximityFactor := 5;
|
||||
if (APos.X > X - lProximityFactor) and (APos.X < X + lProximityFactor)
|
||||
and (APos.Y > Y - lProximityFactor) and (APos.Y < Y + lProximityFactor) then
|
||||
Result := vfrFound
|
||||
else Result := vfrNotFound;
|
||||
end;
|
||||
|
||||
{ TvEntity }
|
||||
|
||||
constructor TvEntity.Create;
|
||||
@ -505,6 +529,11 @@ begin
|
||||
if lBottom > ABottom then ABottom := lBottom;
|
||||
end;
|
||||
|
||||
function TvEntity.TryToSelect(APos: TPoint): TvFindEntityResult;
|
||||
begin
|
||||
Result := vfrNotFound;
|
||||
end;
|
||||
|
||||
{ TvEllipse }
|
||||
|
||||
procedure TvEllipse.CalculateBoundingRectangle;
|
||||
@ -533,7 +562,7 @@ begin
|
||||
tan(t) = b*cot(phi)/a
|
||||
}
|
||||
t := cotan(-MinorHalfAxis*tan(Angle)/MajorHalfAxis);
|
||||
tmp := CenterX + MajorHalfAxis*cos(t)*cos(Angle) - MinorHalfAxis*sin(t)*sin(Angle);
|
||||
tmp := X + MajorHalfAxis*cos(t)*cos(Angle) - MinorHalfAxis*sin(t)*sin(Angle);
|
||||
BoundingRect.Right := Round(tmp);
|
||||
end;
|
||||
|
||||
@ -791,7 +820,7 @@ begin
|
||||
ClearTmpPath();
|
||||
end;
|
||||
|
||||
procedure TvVectorialDocument.AddText(AX, AY, AZ: Double; FontName: string; FontSize: integer; AText: utf8string);
|
||||
procedure TvVectorialDocument.AddText(AX, AY: Double; FontName: string; FontSize: integer; AText: utf8string);
|
||||
var
|
||||
lText: TvText;
|
||||
begin
|
||||
@ -799,38 +828,35 @@ begin
|
||||
lText.Value := AText;
|
||||
lText.X := AX;
|
||||
lText.Y := AY;
|
||||
lText.Z := AZ;
|
||||
lText.Font.Name := FontName;
|
||||
lText.Font.Size := FontSize;
|
||||
AddEntity(lText);
|
||||
end;
|
||||
|
||||
procedure TvVectorialDocument.AddText(AX, AY, AZ: Double; AStr: utf8string);
|
||||
procedure TvVectorialDocument.AddText(AX, AY: Double; AStr: utf8string);
|
||||
begin
|
||||
AddText(AX, AY, AZ, '', 10, AStr);
|
||||
AddText(AX, AY, '', 10, AStr);
|
||||
end;
|
||||
|
||||
procedure TvVectorialDocument.AddCircle(ACenterX, ACenterY, ACenterZ, ARadius: Double);
|
||||
procedure TvVectorialDocument.AddCircle(ACenterX, ACenterY, ARadius: Double);
|
||||
var
|
||||
lCircle: TvCircle;
|
||||
begin
|
||||
lCircle := TvCircle.Create;
|
||||
lCircle.CenterX := ACenterX;
|
||||
lCircle.CenterY := ACenterY;
|
||||
lCircle.CenterZ := ACenterZ;
|
||||
lCircle.X := ACenterX;
|
||||
lCircle.Y := ACenterY;
|
||||
lCircle.Radius := ARadius;
|
||||
AddEntity(lCircle);
|
||||
end;
|
||||
|
||||
procedure TvVectorialDocument.AddCircularArc(ACenterX, ACenterY, ACenterZ,
|
||||
procedure TvVectorialDocument.AddCircularArc(ACenterX, ACenterY,
|
||||
ARadius, AStartAngle, AEndAngle: Double; AColor: TFPColor);
|
||||
var
|
||||
lCircularArc: TvCircularArc;
|
||||
begin
|
||||
lCircularArc := TvCircularArc.Create;
|
||||
lCircularArc.CenterX := ACenterX;
|
||||
lCircularArc.CenterY := ACenterY;
|
||||
lCircularArc.CenterZ := ACenterZ;
|
||||
lCircularArc.X := ACenterX;
|
||||
lCircularArc.Y := ACenterY;
|
||||
lCircularArc.Radius := ARadius;
|
||||
lCircularArc.StartAngle := AStartAngle;
|
||||
lCircularArc.EndAngle := AEndAngle;
|
||||
@ -838,15 +864,14 @@ begin
|
||||
AddEntity(lCircularArc);
|
||||
end;
|
||||
|
||||
procedure TvVectorialDocument.AddEllipse(CenterX, CenterY, CenterZ,
|
||||
procedure TvVectorialDocument.AddEllipse(CenterX, CenterY,
|
||||
MajorHalfAxis, MinorHalfAxis, Angle: Double);
|
||||
var
|
||||
lEllipse: TvEllipse;
|
||||
begin
|
||||
lEllipse := TvEllipse.Create;
|
||||
lEllipse.CenterX := CenterX;
|
||||
lEllipse.CenterY := CenterY;
|
||||
lEllipse.CenterZ := CenterZ;
|
||||
lEllipse.X := CenterX;
|
||||
lEllipse.Y := CenterY;
|
||||
lEllipse.MajorHalfAxis := MajorHalfAxis;
|
||||
lEllipse.MinorHalfAxis := MinorHalfAxis;
|
||||
lEllipse.Angle := Angle;
|
||||
@ -854,10 +879,11 @@ begin
|
||||
end;
|
||||
|
||||
{@@
|
||||
Don't free the passed TvText because it will be added directly to the list
|
||||
Adds an entity to the document and returns it's current index
|
||||
}
|
||||
procedure TvVectorialDocument.AddEntity(AEntity: TvEntity);
|
||||
function TvVectorialDocument.AddEntity(AEntity: TvEntity): Integer;
|
||||
begin
|
||||
Result := FEntities.Count;
|
||||
FEntities.Add(Pointer(AEntity));
|
||||
end;
|
||||
|
||||
@ -933,28 +959,8 @@ begin
|
||||
end;
|
||||
|
||||
procedure TvVectorialDocument.AppendSegmentToTmpPath(ASegment: TPathSegment);
|
||||
var
|
||||
L: Integer;
|
||||
begin
|
||||
// Check if we are the first segment in the tmp path
|
||||
if FTmpPath.PointsEnd = nil then
|
||||
begin
|
||||
if FTmpPath.Len <> 0 then
|
||||
Exception.Create('[TvVectorialDocument.AppendSegmentToTmpPath]' + Str_Error_Nil_Path);
|
||||
|
||||
FTmpPath.Points := ASegment;
|
||||
FTmpPath.PointsEnd := ASegment;
|
||||
FTmpPath.Len := 1;
|
||||
Exit;
|
||||
end;
|
||||
|
||||
L := FTmpPath.Len;
|
||||
Inc(FTmpPath.Len);
|
||||
|
||||
// Adds the element to the end of the list
|
||||
FTmpPath.PointsEnd.Next := ASegment;
|
||||
ASegment.Previous := FTmpPath.PointsEnd;
|
||||
FTmpPath.PointsEnd := ASegment;
|
||||
FTmpPath.AppendSegment(ASegment);
|
||||
end;
|
||||
|
||||
{@@
|
||||
@ -1170,6 +1176,27 @@ begin
|
||||
Result := FEntities.Count;
|
||||
end;
|
||||
|
||||
function TvVectorialDocument.FindAndSelectEntity(Pos: TPoint): TvFindEntityResult;
|
||||
var
|
||||
lEntity: TvEntity;
|
||||
i: Integer;
|
||||
begin
|
||||
Result := vfrNotFound;
|
||||
|
||||
for i := 0 to GetEntitiesCount() - 1 do
|
||||
begin
|
||||
lEntity := GetEntity(i);
|
||||
|
||||
Result := lEntity.TryToSelect(Pos);
|
||||
|
||||
if Result <> vfrNotFound then
|
||||
begin
|
||||
SelectedvElement := lEntity;
|
||||
Exit;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
{@@
|
||||
Clears all data in the document
|
||||
}
|
||||
@ -1347,6 +1374,31 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TPath.AppendSegment(ASegment: TPathSegment);
|
||||
var
|
||||
L: Integer;
|
||||
begin
|
||||
// Check if we are the first segment in the tmp path
|
||||
if PointsEnd = nil then
|
||||
begin
|
||||
if Len <> 0 then
|
||||
Exception.Create('[TPath.AppendSegment] Assertion failed Len <> 0 with PointsEnd = nil');
|
||||
|
||||
Points := ASegment;
|
||||
PointsEnd := ASegment;
|
||||
Len := 1;
|
||||
Exit;
|
||||
end;
|
||||
|
||||
L := Len;
|
||||
Inc(Len);
|
||||
|
||||
// Adds the element to the end of the list
|
||||
PointsEnd.Next := ASegment;
|
||||
ASegment.Previous := PointsEnd;
|
||||
PointsEnd := ASegment;
|
||||
end;
|
||||
|
||||
finalization
|
||||
|
||||
SetLength(GvVectorialFormats, 0);
|
||||
|
@ -65,8 +65,8 @@ begin
|
||||
y2 := CurEllipse.BoundingRect.Bottom;
|
||||
|
||||
dk := Round(0.654 * Abs(y2-y1));
|
||||
f.x := Round(CurEllipse.CenterX);
|
||||
f.y := Round(CurEllipse.CenterY - 1);
|
||||
f.x := Round(CurEllipse.X);
|
||||
f.y := Round(CurEllipse.Y - 1);
|
||||
PointList[0] := Rotate2DPoint(Point(x1, f.y), f, CurEllipse.Angle) ; // Startpoint
|
||||
PointList[1] := Rotate2DPoint(Point(x1, f.y - dk), f, CurEllipse.Angle);
|
||||
//Controlpoint of Startpoint first part
|
||||
@ -353,10 +353,10 @@ begin
|
||||
begin
|
||||
CurCircle := CurEntity as TvCircle;
|
||||
ADest.Ellipse(
|
||||
CoordToCanvasX(CurCircle.CenterX - CurCircle.Radius),
|
||||
CoordToCanvasY(CurCircle.CenterY - CurCircle.Radius),
|
||||
CoordToCanvasX(CurCircle.CenterX + CurCircle.Radius),
|
||||
CoordToCanvasY(CurCircle.CenterY + CurCircle.Radius)
|
||||
CoordToCanvasX(CurCircle.X - CurCircle.Radius),
|
||||
CoordToCanvasY(CurCircle.Y - CurCircle.Radius),
|
||||
CoordToCanvasX(CurCircle.X + CurCircle.Radius),
|
||||
CoordToCanvasY(CurCircle.Y + CurCircle.Radius)
|
||||
);
|
||||
end
|
||||
else if CurEntity is TvEllipse then
|
||||
@ -370,10 +370,10 @@ begin
|
||||
{$ifdef USE_LCL_CANVAS}
|
||||
// ToDo: Consider a X axis inversion
|
||||
// If the Y axis is inverted, then we need to mirror our angles as well
|
||||
BoundsLeft := CoordToCanvasX(CurArc.CenterX - CurArc.Radius);
|
||||
BoundsTop := CoordToCanvasY(CurArc.CenterY - CurArc.Radius);
|
||||
BoundsRight := CoordToCanvasX(CurArc.CenterX + CurArc.Radius);
|
||||
BoundsBottom := CoordToCanvasY(CurArc.CenterY + CurArc.Radius);
|
||||
BoundsLeft := CoordToCanvasX(CurArc.X - CurArc.Radius);
|
||||
BoundsTop := CoordToCanvasY(CurArc.Y - CurArc.Radius);
|
||||
BoundsRight := CoordToCanvasX(CurArc.X + CurArc.Radius);
|
||||
BoundsBottom := CoordToCanvasY(CurArc.Y + CurArc.Radius);
|
||||
{if AMulY > 0 then
|
||||
begin}
|
||||
FinalStartAngle := CurArc.StartAngle;
|
||||
|
Reference in New Issue
Block a user