TAChart: Activate NearestPointTargets in TFieldSeries.

git-svn-id: trunk@53945 -
This commit is contained in:
wp 2017-01-14 23:53:03 +00:00
parent 8af43e0c0b
commit 2f7921bcf1
3 changed files with 73 additions and 9 deletions

View File

@ -44,6 +44,7 @@ type
function CopyPoints(
APoints: array of TPoint; AStartIndex, ANumPts: Integer): TPointArray;
function DotProduct(A, B: TDoublePoint): Double;
function DoublePoint(AX, AY: Double): TDoublePoint; inline; overload;
function DoublePoint(const AP: TPoint): TDoublePoint; inline; overload;
function DoubleRect(AX1, AY1, AX2, AY2: Double): TDoubleRect; inline;
@ -76,6 +77,8 @@ 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 ProjToLine(const P, A, B: TDoublePoint): TDoublePoint; overload;
function ProjToLine(const P, A, B: TPoint): TPoint; overload;
function ProjToRect(
const APt: TDoublePoint; const ARect: TDoubleRect): TDoublePoint;
function RectIntersectsRect(
@ -124,6 +127,11 @@ begin
Result[i] := APoints[i + AStartIndex];
end;
function DotProduct(A, B: TDoublePoint): Double;
begin
Result := A.X * B.X + A.Y + B.Y;
end;
function DoublePoint(AX, AY: Double): TDoublePoint; inline;
begin
Result.X := AX;
@ -561,6 +569,26 @@ begin
end;
end;
function ProjToLine(const P, A,B: TDoublePoint): TDoublePoint;
var
v, s: TDoublePoint;
begin
if P = A then
Result := A
else if P = B then
Result := B
else begin
s := B - A;
v := P - A;
Result := A + s * (DotProduct(v, s) / DotProduct(s, s));
end;
end;
function ProjToLine(const P, A, B: TPoint): TPoint;
begin
Result := RoundPoint(ProjToLine(DoublePoint(P), DoublePoint(A), DoublePoint(B)));
end;
function ProjToRect(
const APt: TDoublePoint; const ARect: TDoubleRect): TDoublePoint;
begin

View File

@ -1357,8 +1357,10 @@ begin
end else begin
for i := 0 to Count - 1 do
if GetVectorPoints(i, p1, p2) then begin
p1 := DoublePoint(AxisToGraphX(p1.X), AxisToGraphY(p1.Y));
p2 := DoublePoint(AxisToGraphX(p2.X), AxisToGraphY(p2.Y));
p1 := AxisToGraph(p1);
p2 := AxisToGraph(p2);
//p1 := DoublePoint(AxisToGraphX(p1.X), AxisToGraphY(p1.Y));
//p2 := DoublePoint(AxisToGraphX(p2.X), AxisToGraphY(p2.Y));
lPen.Color := GetColor(i);
DrawVector(ADrawer, p1, p2, lPen);
end;
@ -1422,13 +1424,16 @@ end;
function TFieldSeries.GetNearestPoint(const AParams: TNearestPointParams;
out AResults: TNearestPointResults): Boolean;
var
dist, i: Integer;
dist, d, i, xidx, yidx: Integer;
pt1, pt2: TPoint;
sp1, sp2: TDoublePoint;
R: TRect;
img: TPoint;
begin
AResults.FDist := Sqr(AParams.FRadius) + 1;
AResults.FIndex := -1;
AResults.FXIndex := 0;
AResults.FYIndex := 0;
for i := 0 to Count - 1 do begin
if not GetVectorPoints(i, sp1, sp2) then
Continue;
@ -1438,16 +1443,44 @@ begin
// At first we check if the point is in the rect spanned by the vector.
R := Rect(pt1.x, pt1.y, pt2.x, pt2.y);
NormalizeRect(R);
R.TopLeft := R.TopLeft - Point(AParams.FRadius, AParams.FRadius);
R.BottomRight := R.BottomRight + Point(AParams.FRadius, AParams.FRadius);
ExpandRect(R, Point(AParams.FRadius, AParams.FRadius));
if not IsPointInRect(AParams.FPoint, R) then continue;
// Calculate distance of point from line
dist := PointLineDist(AParams.FPoint, pt1, pt2);
dist := MaxInt;
xidx := -1;
yidx := -1;
if (nptPoint in AParams.FTargets) then begin
dist := AParams.FDistFunc(AParams.FPoint, pt1);
xidx := 0;
yidx := 0;
img := pt1;
end;
if (AParams.FTargets * [nptXList, nptYList] <> []) then begin
d := AParams.FDistFunc(AParams.FPoint, pt2);
if d < dist then begin
dist := d;
xidx := 1;
yidx := 1;
img := pt2;
end;
end;
if (nptCustom in AParams.FTargets) then begin
d := PointLineDist(AParams.FPoint, pt1, pt2); // distance of point from line
if d < dist then begin
dist := d;
xidx := -1;
yidx := -1;
img := ProjToLine(AParams.FPoint, pt1, pt2);
end;
end;
if dist >= AParams.FRadius then continue;
AResults.FDist := dist;
AResults.FIndex := i;
AResults.FImg := (pt1 + pt2) div 2;
AResults.FValue := Source.Item[i]^.Point;
AResults.FXIndex := xidx;
AResults.FYIndex := yidx;
AResults.FImg := img;
AResults.FValue := Source[i]^.Point;
break;
end;
Result := AResults.FIndex >= 0;

View File

@ -411,6 +411,7 @@ type
strict protected
FNearestGraphPoint: TDoublePoint;
FPointIndex: Integer;
FXIndex: Integer;
FYIndex: Integer;
FSeries: TBasicChartSeries;
procedure FindNearestPoint(APoint: TPoint);
@ -426,6 +427,7 @@ type
property NearestGraphPoint: TDoublePoint read FNearestGraphPoint;
property PointIndex: Integer read FPointIndex;
property Series: TBasicChartSeries read FSeries;
property XIndex: Integer read FXIndex;
property YIndex: Integer read FYIndex;
published
property AffectedSeries: String
@ -1676,6 +1678,7 @@ begin
if best.FDist = MaxInt then exit;
FSeries := bestS;
FPointIndex := best.FIndex;
FXIndex := best.FXIndex;
FYIndex := best.FYIndex;
FNearestGraphPoint := FChart.ImageToGraph(best.FImg);
end;