TAChart: DataTools follow the connection lines of TLineSeries. Keep TLineSeries.LineType when ShowLines is toggled.

git-svn-id: trunk@63048 -
This commit is contained in:
wp 2020-04-22 20:18:34 +00:00
parent 455c23e3f7
commit e4de3e6dec
3 changed files with 103 additions and 4 deletions

View File

@ -77,7 +77,8 @@ function NextNumberSeq(
function PointDist(const A, B: TPoint): Integer; inline;
function PointDistX(const A, B: TPoint): Integer; inline;
function PointDistY(const A, B: TPoint): Integer; inline;
function PointLineDist(const P, A, B: TPoint): Integer;
function PointLineDist(const P, A, B: TPoint): Integer; overload;
function PointLineDist(const P, A,B: TPoint; out Q: TPoint; out Inside: Boolean): Integer; overload;
function ProjToLine(const P, A, B: TDoublePoint): TDoublePoint; overload;
function ProjToLine(const P, A, B: TPoint): TPoint; overload;
function ProjToRect(
@ -580,6 +581,36 @@ begin
end;
end;
function PointLineDist(const P, A,B: TPoint; out Q: TPoint;
out Inside: Boolean): Integer;
var
v, w: TPoint;
dot: Int64;
lv: Integer;
aq, bq: Integer;
begin
if A = B then begin
Result := PointDist(A, P);
Inside := false;
Q := A;
end else begin
v := B - A;
w := P - A;
dot := Int64(v.x) * w.x + Int64(v.y) * w.y;
lv := PointDist(A, B);
Q := (v * dot) div lv;
Result := PointDist(Q, w);
// Check whether the projection point Q is inside the A-B line.
// In this case the lengths AQ and BQ are shorter than AB.
aq := sqr(Q.x) + sqr(Q.y); // note: Q is seen from A, not from origin.
bq := PointDist(v, Q);
Inside := (aq <= lv) and (bq <= lv);
Q := Q + A;
end;
end;
function ProjToLine(const P, A,B: TDoublePoint): TDoublePoint;
var
v, s: TDoublePoint;

View File

@ -241,6 +241,7 @@ type
private
FLinePen: TPen;
FLineType: TLineType;
FOldLineType: TLineType;
FOnDrawPointer: TSeriesPointerDrawEvent;
FColorEach: TColorEachMode;
@ -263,6 +264,8 @@ type
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure Draw(ADrawer: IChartDrawer); override;
function GetNearestPoint(const AParams: TNearestPointParams;
out AResults: TNearestPointResults): Boolean; override;
published
property AxisIndexX;
property AxisIndexY;
@ -436,6 +439,7 @@ begin
FLinePen.OnChange := @StyleChanged;
FPointer := TSeriesPointer.Create(FChart);
SetPropDefaults(Self, ['LineType']);
FOldLineType := FLineType;
end;
destructor TLineSeries.Destroy;
@ -772,6 +776,67 @@ begin
end;
end;
function TLineSeries.GetNearestPoint(const AParams: TNearestPointParams;
out AResults: TNearestPointResults): Boolean;
var
pointIndex, levelIndex: Integer;
ip1, ip2, q: TPoint;
d, dmin: Integer;
isInside: Boolean;
ext: TDoubleRect;
begin
Result := false;
AResults.FDist := sqr(AParams.FRadius) + 1;
AResults.FIndex := -1;
AResults.FXIndex := 0;
AResults.FYIndex := 0;
Result := inherited;
if Result or (LineType <> ltFromPrevious) or
not ((nptCustom in AParams.FTargets) and (nptCustom in ToolTargets))
then
exit;
with Extent do begin
ext.a := AxisToGraph(a);
ext.b := AxisToGraph(b);
end;
NormalizeRect(ext);
// Do not do anything if the series extent does not intersect CurrentExtent.
if not RectIntersectsRect(ext, ParentChart.CurrentExtent) then
exit;
// Iterate through all points of the series and - if nptYList is in Targets -
// at all stack levels.
PrepareGraphPoints(ext, true);
dmin := AResults.FDist;
for levelIndex := 0 to Source.YCount-1 do begin
ip1 := ParentChart.GraphToImage(FGraphPoints[0]);
for pointIndex := 1 to FUpBound - FLoBound do begin
ip2 := ParentChart.GraphToImage(FGraphPoints[pointIndex]);
d := PointLineDist(AParams.FPoint, ip1, ip2, q, isInside);
if isInside and (d < dmin) then begin
dmin := d;
AResults.FIndex := -1; //pointIndex + FLoBound;
AResults.FYIndex := levelIndex;
AResults.FImg := q;
AResults.FValue := ParentChart.ImageToGraph(q);
end;
ip1 := ip2;
end;
if not ((nptYList in AParams.FTargets) and (nptYList in ToolTargets)) then
break;
UpdateGraphPoints(levelIndex, FStacked);
end;
if dmin < AResults.FDist then
begin
AResults.FDist := d;
Result := true;
end;
end;
function TLineSeries.GetSeriesColor: TColor;
begin
Result := FLinePen.Color;
@ -803,6 +868,7 @@ procedure TLineSeries.SetLineType(AValue: TLineType);
begin
if FLineType = AValue then exit;
FLineType := AValue;
FOldLineType := FLineType;
UpdateParentChart;
end;
@ -815,9 +881,11 @@ procedure TLineSeries.SetShowLines(Value: Boolean);
begin
if ShowLines = Value then exit;
if Value then
FLineType := ltFromPrevious
else
FLineType := FOldLineType
else begin
FOldLineType := FLineType;
FLineType := ltNone;
end;
UpdateParentChart;
end;

View File

@ -1874,7 +1874,7 @@ begin
best.FDist := MaxInt;
for s in CustomSeries(FChart, FAffectedSeries.AsBooleans(FChart.SeriesCount)) do
if
InBoundaryBox(s) and s.GetNearestPoint(p, cur) and
InBoundaryBox(s) and s.Active and s.GetNearestPoint(p, cur) and
PtInRect(FChart.ClipRect, cur.FImg) and (cur.FDist < best.FDist)
then begin
bestS := s;