fpvectorial: Fix rendering of elliptical arc path segments.

git-svn-id: trunk@52895 -
This commit is contained in:
wp 2016-08-30 21:33:39 +00:00
parent ba13893b95
commit 0ed4960cd0
4 changed files with 30 additions and 12 deletions

View File

@ -316,6 +316,8 @@ type
{ TPathSegment } { TPathSegment }
TPathSegment = class TPathSegment = class
protected
FPath: TPath;
public public
SegmentType: TSegmentType; SegmentType: TSegmentType;
// Fields for linking the list // Fields for linking the list
@ -332,6 +334,8 @@ type
function GenerateDebugTree(ADestRoutine: TvDebugAddItemProc; APageItem: Pointer): Pointer; virtual; function GenerateDebugTree(ADestRoutine: TvDebugAddItemProc; APageItem: Pointer): Pointer; virtual;
// rendering // rendering
procedure AddToPoints(ADestX, ADestY: Integer; AMulX, AMulY: Double; var Points: TPointsArray); virtual; procedure AddToPoints(ADestX, ADestY: Integer; AMulX, AMulY: Double; var Points: TPointsArray); virtual;
// helper methods
function UseTopLeftCoordinates: Boolean;
end; end;
{@@ {@@
@ -2907,6 +2911,7 @@ var
xstart, ystart: Double; xstart, ystart: Double;
n: Integer; n: Integer;
done: Boolean; done: Boolean;
clockwise: Boolean;
begin begin
n := 0; n := 0;
SetLength(Points, BUFSIZE); SetLength(Points, BUFSIZE);
@ -2918,21 +2923,25 @@ begin
tstart := CalcEllipsePointAngle(xstart, ystart, RX, RY, CX, CY, XRotation); tstart := CalcEllipsePointAngle(xstart, ystart, RX, RY, CX, CY, XRotation);
tend := CalcEllipsePointAngle(X, Y, RX, RY, CX, CY, XRotation); tend := CalcEllipsePointAngle(X, Y, RX, RY, CX, CY, XRotation);
// wp: Something's wrong here: I think "clockwise" is the other way round... // Flip clockwise flag in case of top/left coordinates
clockwise := ClockwiseArcFlag xor UseTopLeftCoordinates;
if ClockwiseArcFlag then if clockwise then
begin // tend must be larger than tstart begin
if tend < tstart then tend := TWO_PI + tend; // clockwise --> angle decreases --> tstart must be > tend
end else begin // tend must be smaller than tstart
if tstart < tend then tstart := TWO_PI + tstart;
dt := -dt; dt := -dt;
if tstart < tend then tstart := TWO_PI + tstart;
end else
begin
// counter-clockwise --> angle increases --> tstart must be < tend
if tend < tstart then tend := TWO_PI + tend;
end; end;
done := false; done := false;
t := tstart; t := tstart;
while not done do begin while not done do begin
if (ClockwiseArcFlag and (t > tend)) or if (clockwise and (t < tend)) or // angle decreases
(not ClockwiseArcFlag and (t < tend)) then (not clockwise and (t > tend)) then // angle increases
begin begin
t := tend; t := tend;
done := true; done := true;
@ -2941,7 +2950,7 @@ begin
SetLength(Points, Length(Points) + BUFSIZE); SetLength(Points, Length(Points) + BUFSIZE);
CalcEllipsePoint(t, RX, RY, CX, CY, XRotation, Points[n].x, Points[n].y); CalcEllipsePoint(t, RX, RY, CX, CY, XRotation, Points[n].x, Points[n].y);
inc(n); inc(n);
t := t + dt; // Note: dt is <0 in counter-clockwise case t := t + dt; // Note: dt is < 0 in clockwise case
end; end;
SetLength(Points, n); SetLength(Points, n);
end; end;
@ -3345,6 +3354,11 @@ begin
// Override by descendants // Override by descendants
end; end;
function TPathSegment.UseTopLeftCoordinates: Boolean;
begin
Result := (FPath <> nil) and FPath.FPage.UseTopLeftCoordinates;
end;
{ T2DSegment } { T2DSegment }
@ -4796,6 +4810,8 @@ procedure TPath.AppendSegment(ASegment: TPathSegment);
var var
L: Integer; L: Integer;
begin begin
ASegment.FPath := self;
// Check if we are the first segment in the tmp path // Check if we are the first segment in the tmp path
if PointsEnd = nil then if PointsEnd = nil then
begin begin

View File

@ -553,7 +553,7 @@ begin
// Rotate ellipse back to align its major axis with the x axis // Rotate ellipse back to align its major axis with the x axis
P := Rotate3dPointInXY(Make3dPoint(x-cx, y-cy, 0), Make3dPoint(0, 0, 0), phi); P := Rotate3dPointInXY(Make3dPoint(x-cx, y-cy, 0), Make3dPoint(0, 0, 0), phi);
// Correctly speaking, above line should use -phi, instead of phi. But // Correctly speaking, above line should use -phi, instead of phi. But
// Make3DPointInXY seems to define the angle in the opposite way. // Rotate3DPointInXY seems to define the angle in the opposite way.
Result := arctan2(P.Y/ry, P.X/rx); Result := arctan2(P.Y/ry, P.X/rx);
if Result < 0 then Result := TWO_PI + Result; if Result < 0 then Result := TWO_PI + Result;
end; end;

View File

@ -418,7 +418,7 @@ begin
TRenderParams.Create(@Render_SelfIntersectingPoly_GradientFill_NonZeroWinding, 'selfintersecting_poly_gradient_nzw.png')); TRenderParams.Create(@Render_SelfIntersectingPoly_GradientFill_NonZeroWinding, 'selfintersecting_poly_gradient_nzw.png'));
node0 := Tree.Items.AddChild(nil, 'Arcs'); node0 := Tree.Items.AddChild(nil, 'Arcs');
node := Tree.Items.AddChild(node0, 'clockwise "1" --> "2"'); node := Tree.Items.AddChild(node0, 'clockwise from point 1 to point 2');
Tree.Items.AddChildObject(node, 'Quarter circle in quadrant I', Tree.Items.AddChildObject(node, 'Quarter circle in quadrant I',
TRenderParams.Create(@Render_Arc_CW_Q1, 'arc_cw_q1.png')); TRenderParams.Create(@Render_Arc_CW_Q1, 'arc_cw_q1.png'));
Tree.Items.AddChildObject(node, 'Quarter circle in quadrant I+II', Tree.Items.AddChildObject(node, 'Quarter circle in quadrant I+II',
@ -435,7 +435,7 @@ begin
TRenderParams.Create(@Render_Arc_CW_Q4, 'arc_cw_q4.png')); TRenderParams.Create(@Render_Arc_CW_Q4, 'arc_cw_q4.png'));
Tree.Items.AddChildObject(node, 'Quarter circle in quadrant IV+I', Tree.Items.AddChildObject(node, 'Quarter circle in quadrant IV+I',
TRenderParams.Create(@Render_Arc_CW_Q41, 'arc_cw_q41.png')); TRenderParams.Create(@Render_Arc_CW_Q41, 'arc_cw_q41.png'));
node := Tree.Items.AddChild(node0, 'counterclockwise "1" --> "2"'); node := Tree.Items.AddChild(node0, 'counterclockwise from point 1 to point 2');
Tree.Items.AddChildObject(node, 'Quarter circle in quadrant I', Tree.Items.AddChildObject(node, 'Quarter circle in quadrant I',
TRenderParams.Create(@Render_Arc_CCW_Q1, 'arc_ccw_q1.png')); TRenderParams.Create(@Render_Arc_CCW_Q1, 'arc_ccw_q1.png'));
Tree.Items.AddChildObject(node, 'Quarter circle in quadrant I+II', Tree.Items.AddChildObject(node, 'Quarter circle in quadrant I+II',

View File

@ -154,12 +154,14 @@ begin
txt.Value.Add('1'); txt.Value.Add('1');
txt.X := X1; txt.X := X1;
txt.Y := Y1; txt.Y := Y1;
txt.Font.Color := colRed;
APage.AddEntity(txt); APage.AddEntity(txt);
txt := TvText.Create(APage); txt := TvText.Create(APage);
txt.Value.Add('2'); txt.Value.Add('2');
txt.X := X2; txt.X := X2;
txt.Y := Y2; txt.Y := Y2;
txt.Font.Color := colRed;
APage.AddEntity(txt); APage.AddEntity(txt);
end; end;