|
@@ -152,7 +152,7 @@ type
|
|
|
|
|
|
TvEntity = class
|
|
|
public
|
|
|
- X, Y: Double;
|
|
|
+ X, Y, Z: Double;
|
|
|
{@@ The global Pen for the entire entity. In the case of paths, individual
|
|
|
elements might be able to override this setting. }
|
|
|
Pen: TvPen;
|
|
@@ -265,19 +265,16 @@ type
|
|
|
|
|
|
TvCustomVectorialWriter = class;
|
|
|
TvCustomVectorialReader = class;
|
|
|
+ TvVectorialPage = class;
|
|
|
|
|
|
{ TvVectorialDocument }
|
|
|
|
|
|
TvVectorialDocument = class
|
|
|
private
|
|
|
- FEntities: TFPList;
|
|
|
- FTmpPath: TPath;
|
|
|
- FTmpText: TvText;
|
|
|
- procedure RemoveCallback(data, arg: pointer);
|
|
|
+ FPages: TFPList;
|
|
|
+ FCurrentPageIndex: Integer;
|
|
|
function CreateVectorialWriter(AFormat: TvVectorialFormat): TvCustomVectorialWriter;
|
|
|
function CreateVectorialReader(AFormat: TvVectorialFormat): TvCustomVectorialReader;
|
|
|
- procedure ClearTmpPath();
|
|
|
- procedure AppendSegmentToTmpPath(ASegment: TPathSegment);
|
|
|
public
|
|
|
Width, Height: Double; // in millimeters
|
|
|
Name: string;
|
|
@@ -302,9 +299,34 @@ type
|
|
|
function GetDetailedFileFormat(): string;
|
|
|
procedure GuessDocumentSize();
|
|
|
procedure GuessGoodZoomLevel(AScreenSize: Integer = 500);
|
|
|
+ { Page methods }
|
|
|
+ function GetPage(AIndex: Integer): TvVectorialPage;
|
|
|
+ function GetPageCount: Integer;
|
|
|
+ function GetCurrentPage: TvVectorialPage;
|
|
|
+ procedure SetCurrentPage(AIndex: Integer);
|
|
|
+ function AddPage(): TvVectorialPage;
|
|
|
+ { Data removing methods }
|
|
|
+ procedure Clear; virtual;
|
|
|
+ end;
|
|
|
+
|
|
|
+ { TvVectorialPage }
|
|
|
+
|
|
|
+ TvVectorialPage = class
|
|
|
+ private
|
|
|
+ FEntities: TFPList;
|
|
|
+ FTmpPath: TPath;
|
|
|
+ FTmpText: TvText;
|
|
|
+ //procedure RemoveCallback(data, arg: pointer);
|
|
|
+ procedure ClearTmpPath();
|
|
|
+ procedure AppendSegmentToTmpPath(ASegment: TPathSegment);
|
|
|
+ public
|
|
|
+ Width, Height: Double; // in millimeters
|
|
|
+ Owner: TvVectorialDocument;
|
|
|
+ { Base methods }
|
|
|
+ constructor Create(AOwner: TvVectorialDocument); virtual;
|
|
|
+ destructor Destroy; override;
|
|
|
+ procedure Assign(ASource: TvVectorialPage);
|
|
|
{ Data reading methods }
|
|
|
- function GetPath(ANum: Cardinal): TPath;
|
|
|
- function GetPathCount: Integer;
|
|
|
function GetEntity(ANum: Cardinal): TvEntity;
|
|
|
function GetEntitiesCount: Integer;
|
|
|
function FindAndSelectEntity(Pos: TPoint): TvFindEntityResult;
|
|
@@ -329,16 +351,14 @@ type
|
|
|
procedure SetPenWidth(AWidth: Integer);
|
|
|
procedure SetClipPath(AClipPath: TPath; AClipMode: TvClipMode);
|
|
|
procedure EndPath();
|
|
|
- procedure AddText(AX, AY: Double; FontName: string; FontSize: integer; AText: utf8string); overload;
|
|
|
+ procedure AddText(AX, AY, AZ: Double; FontName: string; FontSize: integer; AText: utf8string); overload;
|
|
|
procedure AddText(AX, AY: Double; AStr: utf8string); overload;
|
|
|
+ procedure AddText(AX, AY, AZ: 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 }
|
|
|
- property PathCount: Integer read GetPathCount;
|
|
|
- property Paths[Index: Cardinal]: TPath read GetPath;
|
|
|
end;
|
|
|
|
|
|
{@@ TvVectorialReader class reference type }
|
|
@@ -490,156 +510,105 @@ begin
|
|
|
Result.Z := 0;
|
|
|
end;
|
|
|
|
|
|
-{ TvText }
|
|
|
-
|
|
|
-constructor TvText.Create;
|
|
|
-begin
|
|
|
- inherited Create;
|
|
|
- Value := TStringList.Create;
|
|
|
-end;
|
|
|
-
|
|
|
-destructor TvText.Destroy;
|
|
|
-begin
|
|
|
- Value.Free;
|
|
|
- inherited Destroy;
|
|
|
-end;
|
|
|
+{ TvVectorialPage }
|
|
|
|
|
|
-function TvText.TryToSelect(APos: TPoint): TvFindEntityResult;
|
|
|
+procedure TvVectorialPage.ClearTmpPath;
|
|
|
var
|
|
|
- lProximityFactor: Integer;
|
|
|
+ segment, oldsegment: TPathSegment;
|
|
|
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;
|
|
|
+ FTmpPath.Points := nil;
|
|
|
+ FTmpPath.PointsEnd := nil;
|
|
|
+ FTmpPath.Len := 0;
|
|
|
+ FTmpPath.Brush.Color := colBlue;
|
|
|
+ FTmpPath.Brush.Style := bsClear;
|
|
|
+ FTmpPath.Pen.Color := colBlack;
|
|
|
+ FTmpPath.Pen.Style := psSolid;
|
|
|
+ FTmpPath.Pen.Width := 1;
|
|
|
end;
|
|
|
|
|
|
-{ TvEntity }
|
|
|
-
|
|
|
-constructor TvEntity.Create;
|
|
|
+procedure TvVectorialPage.AppendSegmentToTmpPath(ASegment: TPathSegment);
|
|
|
begin
|
|
|
- Pen.Style := psSolid;
|
|
|
- Pen.Color := colBlack;
|
|
|
- Brush.Style := bsClear;
|
|
|
- Brush.Color := colBlue;
|
|
|
+ FTmpPath.AppendSegment(ASegment);
|
|
|
end;
|
|
|
|
|
|
-procedure TvEntity.CalculateBoundingBox(var ALeft, ATop, ARight, ABottom: Double);
|
|
|
+constructor TvVectorialPage.Create(AOwner: TvVectorialDocument);
|
|
|
begin
|
|
|
- ALeft := 0;
|
|
|
- ATop := 0;
|
|
|
- ARight := 0;
|
|
|
- ABottom := 0;
|
|
|
-end;
|
|
|
+ inherited Create;
|
|
|
|
|
|
-procedure TvEntity.ExpandBoundingBox(var ALeft, ATop, ARight, ABottom: Double);
|
|
|
-var
|
|
|
- lLeft, lTop, lRight, lBottom: Double;
|
|
|
-begin
|
|
|
- CalculateBoundingBox(lLeft, lTop, lRight, lBottom);
|
|
|
- if lLeft < ALeft then ALeft := lLeft;
|
|
|
- if lTop < ATop then ATop := lTop;
|
|
|
- if lRight > ARight then ARight := lRight;
|
|
|
- if lBottom > ABottom then ABottom := lBottom;
|
|
|
+ FEntities := TFPList.Create;
|
|
|
+ FTmpPath := TPath.Create;
|
|
|
+ Owner := AOwner;
|
|
|
end;
|
|
|
|
|
|
-function TvEntity.TryToSelect(APos: TPoint): TvFindEntityResult;
|
|
|
+destructor TvVectorialPage.Destroy;
|
|
|
begin
|
|
|
- Result := vfrNotFound;
|
|
|
-end;
|
|
|
+ Clear;
|
|
|
|
|
|
-procedure TvEntity.Translate(ADeltaX, ADeltaY: Integer);
|
|
|
-begin
|
|
|
- X := X + ADeltaX;
|
|
|
- Y := Y + ADeltaY;
|
|
|
-end;
|
|
|
+ FEntities.Free;
|
|
|
|
|
|
-{ TvEllipse }
|
|
|
+ inherited Destroy;
|
|
|
+end;
|
|
|
|
|
|
-procedure TvEllipse.CalculateBoundingRectangle;
|
|
|
+procedure TvVectorialPage.Assign(ASource: TvVectorialPage);
|
|
|
var
|
|
|
- t, tmp: Double;
|
|
|
+ i: Integer;
|
|
|
begin
|
|
|
- {
|
|
|
- To calculate the bounding rectangle we can do this:
|
|
|
-
|
|
|
- Ellipse equations:You could try using the parametrized equations for an ellipse rotated at an arbitrary angle:
|
|
|
+ Clear;
|
|
|
|
|
|
- x = CenterX + MajorHalfAxis*cos(t)*cos(Angle) - MinorHalfAxis*sin(t)*sin(Angle)
|
|
|
- y = CenterY + MinorHalfAxis*sin(t)*cos(Angle) + MajorHalfAxis*cos(t)*sin(Angle)
|
|
|
+ for i := 0 to ASource.GetEntitiesCount - 1 do
|
|
|
+ Self.AddEntity(ASource.GetEntity(i));
|
|
|
+end;
|
|
|
|
|
|
- You can then differentiate and solve for gradient = 0:
|
|
|
- 0 = dx/dt = -MajorHalfAxis*sin(t)*cos(Angle) - MinorHalfAxis*cos(t)*sin(Angle)
|
|
|
- =>
|
|
|
- tan(t) = -MinorHalfAxis*tan(Angle)/MajorHalfAxis
|
|
|
- =>
|
|
|
- t = cotang(-MinorHalfAxis*tan(Angle)/MajorHalfAxis)
|
|
|
+function TvVectorialPage.GetEntity(ANum: Cardinal): TvEntity;
|
|
|
+begin
|
|
|
+ if ANum >= FEntities.Count then raise Exception.Create('TvVectorialDocument.GetEntity: Entity number out of bounds');
|
|
|
|
|
|
- On the other axis:
|
|
|
+ if FEntities.Items[ANum] = nil then raise Exception.Create('TvVectorialDocument.GetEntity: Invalid Entity number');
|
|
|
|
|
|
- 0 = dy/dt = b*cos(t)*cos(phi) - a*sin(t)*sin(phi)
|
|
|
- =>
|
|
|
- tan(t) = b*cot(phi)/a
|
|
|
- }
|
|
|
- t := cotan(-MinorHalfAxis*tan(Angle)/MajorHalfAxis);
|
|
|
- tmp := X + MajorHalfAxis*cos(t)*cos(Angle) - MinorHalfAxis*sin(t)*sin(Angle);
|
|
|
- BoundingRect.Right := Round(tmp);
|
|
|
+ Result := TvEntity(FEntities.Items[ANum]);
|
|
|
end;
|
|
|
|
|
|
-{ TsWorksheet }
|
|
|
-
|
|
|
-{@@
|
|
|
- Helper method for clearing the records in a spreadsheet.
|
|
|
-}
|
|
|
-procedure TvVectorialDocument.RemoveCallback(data, arg: pointer);
|
|
|
+function TvVectorialPage.GetEntitiesCount: Integer;
|
|
|
begin
|
|
|
-{ if data <> nil then
|
|
|
- begin
|
|
|
- ldata := PObject(data);
|
|
|
- ldata^.Free;
|
|
|
- end;}
|
|
|
+ Result := FEntities.Count;
|
|
|
end;
|
|
|
|
|
|
-{@@
|
|
|
- Constructor.
|
|
|
-}
|
|
|
-constructor TvVectorialDocument.Create;
|
|
|
+function TvVectorialPage.FindAndSelectEntity(Pos: TPoint): TvFindEntityResult;
|
|
|
+var
|
|
|
+ lEntity: TvEntity;
|
|
|
+ i: Integer;
|
|
|
begin
|
|
|
- inherited Create;
|
|
|
-
|
|
|
- FEntities := TFPList.Create;
|
|
|
- FTmpPath := TPath.Create;
|
|
|
-end;
|
|
|
+ Result := vfrNotFound;
|
|
|
|
|
|
-{@@
|
|
|
- Destructor.
|
|
|
-}
|
|
|
-destructor TvVectorialDocument.Destroy;
|
|
|
-begin
|
|
|
- Clear;
|
|
|
+ for i := 0 to GetEntitiesCount() - 1 do
|
|
|
+ begin
|
|
|
+ lEntity := GetEntity(i);
|
|
|
|
|
|
- FEntities.Free;
|
|
|
+ Result := lEntity.TryToSelect(Pos);
|
|
|
|
|
|
- inherited Destroy;
|
|
|
+ if Result <> vfrNotFound then
|
|
|
+ begin
|
|
|
+ Owner.SelectedvElement := lEntity;
|
|
|
+ Exit;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
end;
|
|
|
|
|
|
-procedure TvVectorialDocument.Assign(ASource: TvVectorialDocument);
|
|
|
-var
|
|
|
- i: Integer;
|
|
|
+procedure TvVectorialPage.Clear;
|
|
|
begin
|
|
|
- Clear;
|
|
|
-
|
|
|
- for i := 0 to ASource.GetEntitiesCount - 1 do
|
|
|
- Self.AddEntity(ASource.GetEntity(i));
|
|
|
+ FEntities.Clear();
|
|
|
end;
|
|
|
|
|
|
-procedure TvVectorialDocument.AssignTo(ADest: TvVectorialDocument);
|
|
|
+{@@
|
|
|
+ Adds an entity to the document and returns it's current index
|
|
|
+}
|
|
|
+function TvVectorialPage.AddEntity(AEntity: TvEntity): Integer;
|
|
|
begin
|
|
|
- ADest.Assign(Self);
|
|
|
+ Result := FEntities.Count;
|
|
|
+ FEntities.Add(Pointer(AEntity));
|
|
|
end;
|
|
|
|
|
|
-procedure TvVectorialDocument.AddPathCopyMem(APath: TPath);
|
|
|
+procedure TvVectorialPage.AddPathCopyMem(APath: TPath);
|
|
|
var
|
|
|
lPath: TPath;
|
|
|
Len: Integer;
|
|
@@ -657,7 +626,7 @@ end;
|
|
|
|
|
|
@see EndPath, AddPointToPath
|
|
|
}
|
|
|
-procedure TvVectorialDocument.StartPath(AX, AY: Double);
|
|
|
+procedure TvVectorialPage.StartPath(AX, AY: Double);
|
|
|
var
|
|
|
segment: T2DSegment;
|
|
|
begin
|
|
@@ -673,12 +642,12 @@ begin
|
|
|
FTmpPath.PointsEnd := segment;
|
|
|
end;
|
|
|
|
|
|
-procedure TvVectorialDocument.StartPath();
|
|
|
+procedure TvVectorialPage.StartPath;
|
|
|
begin
|
|
|
ClearTmpPath();
|
|
|
end;
|
|
|
|
|
|
-procedure TvVectorialDocument.AddMoveToPath(AX, AY: Double);
|
|
|
+procedure TvVectorialPage.AddMoveToPath(AX, AY: Double);
|
|
|
var
|
|
|
segment: T2DSegment;
|
|
|
begin
|
|
@@ -700,7 +669,7 @@ end;
|
|
|
|
|
|
@see StartPath, EndPath
|
|
|
}
|
|
|
-procedure TvVectorialDocument.AddLineToPath(AX, AY: Double);
|
|
|
+procedure TvVectorialPage.AddLineToPath(AX, AY: Double);
|
|
|
var
|
|
|
segment: T2DSegment;
|
|
|
begin
|
|
@@ -712,7 +681,7 @@ begin
|
|
|
AppendSegmentToTmpPath(segment);
|
|
|
end;
|
|
|
|
|
|
-procedure TvVectorialDocument.AddLineToPath(AX, AY: Double; AColor: TFPColor);
|
|
|
+procedure TvVectorialPage.AddLineToPath(AX, AY: Double; AColor: TFPColor);
|
|
|
var
|
|
|
segment: T2DSegmentWithPen;
|
|
|
begin
|
|
@@ -725,7 +694,7 @@ begin
|
|
|
AppendSegmentToTmpPath(segment);
|
|
|
end;
|
|
|
|
|
|
-procedure TvVectorialDocument.AddLineToPath(AX, AY, AZ: Double);
|
|
|
+procedure TvVectorialPage.AddLineToPath(AX, AY, AZ: Double);
|
|
|
var
|
|
|
segment: T3DSegment;
|
|
|
begin
|
|
@@ -741,7 +710,7 @@ end;
|
|
|
{@@
|
|
|
Gets the current Pen Pos in the temporary path
|
|
|
}
|
|
|
-procedure TvVectorialDocument.GetCurrentPathPenPos(var AX, AY: Double);
|
|
|
+procedure TvVectorialPage.GetCurrentPathPenPos(var AX, AY: Double);
|
|
|
begin
|
|
|
// Check if we are the first segment in the tmp path
|
|
|
if FTmpPath.PointsEnd = nil then raise Exception.Create('[TvVectorialDocument.GetCurrentPathPenPos] One cannot obtain the Pen Pos if there are no segments in the temporary path');
|
|
@@ -755,8 +724,7 @@ end;
|
|
|
and it goes throw the control points [AX1, AY1] and [AX2, AY2] and ends
|
|
|
in [AX3, AY3].
|
|
|
}
|
|
|
-procedure TvVectorialDocument.AddBezierToPath(AX1, AY1, AX2, AY2, AX3,
|
|
|
- AY3: Double);
|
|
|
+procedure TvVectorialPage.AddBezierToPath(AX1, AY1, AX2, AY2, AX3, AY3: Double);
|
|
|
var
|
|
|
segment: T2DBezierSegment;
|
|
|
begin
|
|
@@ -772,8 +740,7 @@ begin
|
|
|
AppendSegmentToTmpPath(segment);
|
|
|
end;
|
|
|
|
|
|
-procedure TvVectorialDocument.AddBezierToPath(AX1, AY1, AZ1, AX2, AY2, AZ2,
|
|
|
- AX3, AY3, AZ3: Double);
|
|
|
+procedure TvVectorialPage.AddBezierToPath(AX1, AY1, AZ1, AX2, AY2, AZ2, AX3, AY3, AZ3: Double);
|
|
|
var
|
|
|
segment: T3DBezierSegment;
|
|
|
begin
|
|
@@ -792,33 +759,32 @@ begin
|
|
|
AppendSegmentToTmpPath(segment);
|
|
|
end;
|
|
|
|
|
|
-procedure TvVectorialDocument.SetBrushColor(AColor: TFPColor);
|
|
|
+procedure TvVectorialPage.SetBrushColor(AColor: TFPColor);
|
|
|
begin
|
|
|
FTmPPath.Brush.Color := AColor;
|
|
|
end;
|
|
|
|
|
|
-procedure TvVectorialDocument.SetBrushStyle(AStyle: TFPBrushStyle);
|
|
|
+procedure TvVectorialPage.SetBrushStyle(AStyle: TFPBrushStyle);
|
|
|
begin
|
|
|
FTmPPath.Brush.Style := AStyle;
|
|
|
end;
|
|
|
|
|
|
-procedure TvVectorialDocument.SetPenColor(AColor: TFPColor);
|
|
|
+procedure TvVectorialPage.SetPenColor(AColor: TFPColor);
|
|
|
begin
|
|
|
FTmPPath.Pen.Color := AColor;
|
|
|
end;
|
|
|
|
|
|
-procedure TvVectorialDocument.SetPenStyle(AStyle: TFPPenStyle);
|
|
|
+procedure TvVectorialPage.SetPenStyle(AStyle: TFPPenStyle);
|
|
|
begin
|
|
|
FTmPPath.Pen.Style := AStyle;
|
|
|
end;
|
|
|
|
|
|
-procedure TvVectorialDocument.SetPenWidth(AWidth: Integer);
|
|
|
+procedure TvVectorialPage.SetPenWidth(AWidth: Integer);
|
|
|
begin
|
|
|
FTmPPath.Pen.Width := AWidth;
|
|
|
end;
|
|
|
|
|
|
-procedure TvVectorialDocument.SetClipPath(AClipPath: TPath;
|
|
|
- AClipMode: TvClipMode);
|
|
|
+procedure TvVectorialPage.SetClipPath(AClipPath: TPath; AClipMode: TvClipMode);
|
|
|
begin
|
|
|
FTmPPath.ClipPath := AClipPath;
|
|
|
FTmPPath.ClipMode := AClipMode;
|
|
@@ -834,14 +800,15 @@ end;
|
|
|
|
|
|
@see StartPath, AddPointToPath
|
|
|
}
|
|
|
-procedure TvVectorialDocument.EndPath();
|
|
|
+procedure TvVectorialPage.EndPath;
|
|
|
begin
|
|
|
if FTmPPath.Len = 0 then Exit;
|
|
|
AddPathCopyMem(FTmPPath);
|
|
|
ClearTmpPath();
|
|
|
end;
|
|
|
|
|
|
-procedure TvVectorialDocument.AddText(AX, AY: Double; FontName: string; FontSize: integer; AText: utf8string);
|
|
|
+procedure TvVectorialPage.AddText(AX, AY, AZ: Double; FontName: string;
|
|
|
+ FontSize: integer; AText: utf8string);
|
|
|
var
|
|
|
lText: TvText;
|
|
|
begin
|
|
@@ -849,17 +816,23 @@ begin
|
|
|
lText.Value.Text := 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: Double; AStr: utf8string);
|
|
|
+procedure TvVectorialPage.AddText(AX, AY: Double; AStr: utf8string);
|
|
|
begin
|
|
|
- AddText(AX, AY, '', 10, AStr);
|
|
|
+ AddText(AX, AY, 0, '', 10, AStr);
|
|
|
end;
|
|
|
|
|
|
-procedure TvVectorialDocument.AddCircle(ACenterX, ACenterY, ARadius: Double);
|
|
|
+procedure TvVectorialPage.AddText(AX, AY, AZ: Double; AStr: utf8string);
|
|
|
+begin
|
|
|
+ AddText(AX, AY, AZ, '', 10, AStr);
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TvVectorialPage.AddCircle(ACenterX, ACenterY, ARadius: Double);
|
|
|
var
|
|
|
lCircle: TvCircle;
|
|
|
begin
|
|
@@ -870,8 +843,8 @@ begin
|
|
|
AddEntity(lCircle);
|
|
|
end;
|
|
|
|
|
|
-procedure TvVectorialDocument.AddCircularArc(ACenterX, ACenterY,
|
|
|
- ARadius, AStartAngle, AEndAngle: Double; AColor: TFPColor);
|
|
|
+procedure TvVectorialPage.AddCircularArc(ACenterX, ACenterY, ARadius,
|
|
|
+ AStartAngle, AEndAngle: Double; AColor: TFPColor);
|
|
|
var
|
|
|
lCircularArc: TvCircularArc;
|
|
|
begin
|
|
@@ -885,8 +858,8 @@ begin
|
|
|
AddEntity(lCircularArc);
|
|
|
end;
|
|
|
|
|
|
-procedure TvVectorialDocument.AddEllipse(CenterX, CenterY,
|
|
|
- MajorHalfAxis, MinorHalfAxis, Angle: Double);
|
|
|
+procedure TvVectorialPage.AddEllipse(CenterX, CenterY, MajorHalfAxis,
|
|
|
+ MinorHalfAxis, Angle: Double);
|
|
|
var
|
|
|
lEllipse: TvEllipse;
|
|
|
begin
|
|
@@ -899,17 +872,9 @@ begin
|
|
|
AddEntity(lEllipse);
|
|
|
end;
|
|
|
|
|
|
-{@@
|
|
|
- Adds an entity to the document and returns it's current index
|
|
|
-}
|
|
|
-function TvVectorialDocument.AddEntity(AEntity: TvEntity): Integer;
|
|
|
-begin
|
|
|
- Result := FEntities.Count;
|
|
|
- FEntities.Add(Pointer(AEntity));
|
|
|
-end;
|
|
|
|
|
|
-procedure TvVectorialDocument.AddAlignedDimension(BaseLeft, BaseRight,
|
|
|
- DimLeft, DimRight: T3DPoint);
|
|
|
+procedure TvVectorialPage.AddAlignedDimension(BaseLeft, BaseRight, DimLeft,
|
|
|
+ DimRight: T3DPoint);
|
|
|
var
|
|
|
lDim: TvAlignedDimension;
|
|
|
begin
|
|
@@ -921,6 +886,142 @@ begin
|
|
|
AddEntity(lDim);
|
|
|
end;
|
|
|
|
|
|
+{ TvText }
|
|
|
+
|
|
|
+constructor TvText.Create;
|
|
|
+begin
|
|
|
+ inherited Create;
|
|
|
+ Value := TStringList.Create;
|
|
|
+end;
|
|
|
+
|
|
|
+destructor TvText.Destroy;
|
|
|
+begin
|
|
|
+ Value.Free;
|
|
|
+ inherited Destroy;
|
|
|
+end;
|
|
|
+
|
|
|
+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;
|
|
|
+begin
|
|
|
+ Pen.Style := psSolid;
|
|
|
+ Pen.Color := colBlack;
|
|
|
+ Brush.Style := bsClear;
|
|
|
+ Brush.Color := colBlue;
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TvEntity.CalculateBoundingBox(var ALeft, ATop, ARight, ABottom: Double);
|
|
|
+begin
|
|
|
+ ALeft := 0;
|
|
|
+ ATop := 0;
|
|
|
+ ARight := 0;
|
|
|
+ ABottom := 0;
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TvEntity.ExpandBoundingBox(var ALeft, ATop, ARight, ABottom: Double);
|
|
|
+var
|
|
|
+ lLeft, lTop, lRight, lBottom: Double;
|
|
|
+begin
|
|
|
+ CalculateBoundingBox(lLeft, lTop, lRight, lBottom);
|
|
|
+ if lLeft < ALeft then ALeft := lLeft;
|
|
|
+ if lTop < ATop then ATop := lTop;
|
|
|
+ if lRight > ARight then ARight := lRight;
|
|
|
+ if lBottom > ABottom then ABottom := lBottom;
|
|
|
+end;
|
|
|
+
|
|
|
+function TvEntity.TryToSelect(APos: TPoint): TvFindEntityResult;
|
|
|
+begin
|
|
|
+ Result := vfrNotFound;
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TvEntity.Translate(ADeltaX, ADeltaY: Integer);
|
|
|
+begin
|
|
|
+ X := X + ADeltaX;
|
|
|
+ Y := Y + ADeltaY;
|
|
|
+end;
|
|
|
+
|
|
|
+{ TvEllipse }
|
|
|
+
|
|
|
+procedure TvEllipse.CalculateBoundingRectangle;
|
|
|
+var
|
|
|
+ t, tmp: Double;
|
|
|
+begin
|
|
|
+ {
|
|
|
+ To calculate the bounding rectangle we can do this:
|
|
|
+
|
|
|
+ Ellipse equations:You could try using the parametrized equations for an ellipse rotated at an arbitrary angle:
|
|
|
+
|
|
|
+ x = CenterX + MajorHalfAxis*cos(t)*cos(Angle) - MinorHalfAxis*sin(t)*sin(Angle)
|
|
|
+ y = CenterY + MinorHalfAxis*sin(t)*cos(Angle) + MajorHalfAxis*cos(t)*sin(Angle)
|
|
|
+
|
|
|
+ You can then differentiate and solve for gradient = 0:
|
|
|
+ 0 = dx/dt = -MajorHalfAxis*sin(t)*cos(Angle) - MinorHalfAxis*cos(t)*sin(Angle)
|
|
|
+ =>
|
|
|
+ tan(t) = -MinorHalfAxis*tan(Angle)/MajorHalfAxis
|
|
|
+ =>
|
|
|
+ t = cotang(-MinorHalfAxis*tan(Angle)/MajorHalfAxis)
|
|
|
+
|
|
|
+ On the other axis:
|
|
|
+
|
|
|
+ 0 = dy/dt = b*cos(t)*cos(phi) - a*sin(t)*sin(phi)
|
|
|
+ =>
|
|
|
+ tan(t) = b*cot(phi)/a
|
|
|
+ }
|
|
|
+ t := cotan(-MinorHalfAxis*tan(Angle)/MajorHalfAxis);
|
|
|
+ tmp := X + MajorHalfAxis*cos(t)*cos(Angle) - MinorHalfAxis*sin(t)*sin(Angle);
|
|
|
+ BoundingRect.Right := Round(tmp);
|
|
|
+end;
|
|
|
+
|
|
|
+{ TsWorksheet }
|
|
|
+
|
|
|
+{@@
|
|
|
+ Constructor.
|
|
|
+}
|
|
|
+constructor TvVectorialDocument.Create;
|
|
|
+begin
|
|
|
+ inherited Create;
|
|
|
+
|
|
|
+ FPages := TFPList.Create;
|
|
|
+end;
|
|
|
+
|
|
|
+{@@
|
|
|
+ Destructor.
|
|
|
+}
|
|
|
+destructor TvVectorialDocument.Destroy;
|
|
|
+begin
|
|
|
+ Clear;
|
|
|
+
|
|
|
+ FPages.Free;
|
|
|
+
|
|
|
+ inherited Destroy;
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TvVectorialDocument.Assign(ASource: TvVectorialDocument);
|
|
|
+//var
|
|
|
+// i: Integer;
|
|
|
+begin
|
|
|
+// Clear;
|
|
|
+//
|
|
|
+// for i := 0 to ASource.GetEntitiesCount - 1 do
|
|
|
+// Self.AddEntity(ASource.GetEntity(i));
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TvVectorialDocument.AssignTo(ADest: TvVectorialDocument);
|
|
|
+begin
|
|
|
+ ADest.Assign(Self);
|
|
|
+end;
|
|
|
+
|
|
|
{@@
|
|
|
Convenience method which creates the correct
|
|
|
writer object for a given vector graphics document format.
|
|
@@ -965,25 +1066,6 @@ begin
|
|
|
if Result = nil then raise Exception.Create('Unsupported vector graphics format.');
|
|
|
end;
|
|
|
|
|
|
-procedure TvVectorialDocument.ClearTmpPath();
|
|
|
-var
|
|
|
- segment, oldsegment: TPathSegment;
|
|
|
-begin
|
|
|
- FTmpPath.Points := nil;
|
|
|
- FTmpPath.PointsEnd := nil;
|
|
|
- FTmpPath.Len := 0;
|
|
|
- FTmpPath.Brush.Color := colBlue;
|
|
|
- FTmpPath.Brush.Style := bsClear;
|
|
|
- FTmpPath.Pen.Color := colBlack;
|
|
|
- FTmpPath.Pen.Style := psSolid;
|
|
|
- FTmpPath.Pen.Width := 1;
|
|
|
-end;
|
|
|
-
|
|
|
-procedure TvVectorialDocument.AppendSegmentToTmpPath(ASegment: TPathSegment);
|
|
|
-begin
|
|
|
- FTmpPath.AppendSegment(ASegment);
|
|
|
-end;
|
|
|
-
|
|
|
{@@
|
|
|
Writes the document to a file.
|
|
|
|
|
@@ -1130,19 +1212,24 @@ end;
|
|
|
|
|
|
procedure TvVectorialDocument.GuessDocumentSize();
|
|
|
var
|
|
|
- i: Integer;
|
|
|
+ i, j: Integer;
|
|
|
lEntity: TvEntity;
|
|
|
lLeft, lTop, lRight, lBottom: Double;
|
|
|
+ CurPage: TvVectorialPage;
|
|
|
begin
|
|
|
lLeft := 0;
|
|
|
lTop := 0;
|
|
|
lRight := 0;
|
|
|
lBottom := 0;
|
|
|
|
|
|
- for i := 0 to GetEntitiesCount() - 1 do
|
|
|
+ for j := 0 to GetPageCount()-1 do
|
|
|
begin
|
|
|
- lEntity := GetEntity(I);
|
|
|
- lEntity.ExpandBoundingBox(lLeft, lTop, lRight, lBottom);
|
|
|
+ CurPage := GetPage(j);
|
|
|
+ for i := 0 to CurPage.GetEntitiesCount() - 1 do
|
|
|
+ begin
|
|
|
+ lEntity := CurPage.GetEntity(I);
|
|
|
+ lEntity.ExpandBoundingBox(lLeft, lTop, lRight, lBottom);
|
|
|
+ end;
|
|
|
end;
|
|
|
|
|
|
Width := lRight - lLeft;
|
|
@@ -1154,68 +1241,34 @@ begin
|
|
|
ZoomLevel := AScreenSize / Height;
|
|
|
end;
|
|
|
|
|
|
-function TvVectorialDocument.GetPath(ANum: Cardinal): TPath;
|
|
|
-var
|
|
|
- i: Integer;
|
|
|
- Index: Integer = - 1;
|
|
|
+function TvVectorialDocument.GetPage(AIndex: Integer): TvVectorialPage;
|
|
|
begin
|
|
|
- Result := nil;
|
|
|
-
|
|
|
- if ANum >= FEntities.Count then raise Exception.Create('TvVectorialDocument.GetPath: Path number out of bounds');
|
|
|
-
|
|
|
- for i := 0 to FEntities.Count - 1 do
|
|
|
- begin
|
|
|
- if TvEntity(FEntities.Items[i]) is TPath then
|
|
|
- begin
|
|
|
- Inc(Index);
|
|
|
- if Index = ANum then Result := TPath(FEntities.Items[i]);
|
|
|
- end;
|
|
|
- end;
|
|
|
+ Result := TvVectorialPage(FPages.Items[AIndex]);
|
|
|
end;
|
|
|
|
|
|
-function TvVectorialDocument.GetPathCount: Integer;
|
|
|
-var
|
|
|
- i: Integer;
|
|
|
+function TvVectorialDocument.GetPageCount: Integer;
|
|
|
begin
|
|
|
- Result := 0;
|
|
|
-
|
|
|
- for i := 0 to FEntities.Count - 1 do
|
|
|
- if TvEntity(FEntities.Items[i]) is TPath then Inc(Result);
|
|
|
+ Result := FPages.Count;
|
|
|
end;
|
|
|
|
|
|
-function TvVectorialDocument.GetEntity(ANum: Cardinal): TvEntity;
|
|
|
+function TvVectorialDocument.GetCurrentPage: TvVectorialPage;
|
|
|
begin
|
|
|
- if ANum >= FEntities.Count then raise Exception.Create('TvVectorialDocument.GetEntity: Entity number out of bounds');
|
|
|
-
|
|
|
- if FEntities.Items[ANum] = nil then raise Exception.Create('TvVectorialDocument.GetEntity: Invalid Entity number');
|
|
|
-
|
|
|
- Result := TvEntity(FEntities.Items[ANum]);
|
|
|
+ if FCurrentPageIndex >= 0 then
|
|
|
+ Result := GetPage(FCurrentPageIndex)
|
|
|
+ else
|
|
|
+ Result := nil;
|
|
|
end;
|
|
|
|
|
|
-function TvVectorialDocument.GetEntitiesCount: Integer;
|
|
|
+procedure TvVectorialDocument.SetCurrentPage(AIndex: Integer);
|
|
|
begin
|
|
|
- Result := FEntities.Count;
|
|
|
+ FCurrentPageIndex := AIndex;
|
|
|
end;
|
|
|
|
|
|
-function TvVectorialDocument.FindAndSelectEntity(Pos: TPoint): TvFindEntityResult;
|
|
|
-var
|
|
|
- lEntity: TvEntity;
|
|
|
- i: Integer;
|
|
|
+function TvVectorialDocument.AddPage: TvVectorialPage;
|
|
|
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;
|
|
|
+ Result := TvVectorialPage.Create(Self);
|
|
|
+ FPages.Add(Result);
|
|
|
+ if FCurrentPageIndex < 0 then FCurrentPageIndex := FPages.Count-1;
|
|
|
end;
|
|
|
|
|
|
{@@
|
|
@@ -1223,7 +1276,6 @@ end;
|
|
|
}
|
|
|
procedure TvVectorialDocument.Clear;
|
|
|
begin
|
|
|
- FEntities.Clear();
|
|
|
end;
|
|
|
|
|
|
{ TvCustomVectorialReader }
|