From 2f7921bcf1d2931daff6f2f16428a4b28bcb6f54 Mon Sep 17 00:00:00 2001 From: wp Date: Sat, 14 Jan 2017 23:53:03 +0000 Subject: [PATCH] TAChart: Activate NearestPointTargets in TFieldSeries. git-svn-id: trunk@53945 - --- components/tachart/tageometry.pas | 28 +++++++++++++++ components/tachart/tamultiseries.pas | 51 +++++++++++++++++++++++----- components/tachart/tatools.pas | 3 ++ 3 files changed, 73 insertions(+), 9 deletions(-) diff --git a/components/tachart/tageometry.pas b/components/tachart/tageometry.pas index 459a273c05..ba6c42a2c3 100644 --- a/components/tachart/tageometry.pas +++ b/components/tachart/tageometry.pas @@ -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 diff --git a/components/tachart/tamultiseries.pas b/components/tachart/tamultiseries.pas index fdbf615563..f88c02651a 100644 --- a/components/tachart/tamultiseries.pas +++ b/components/tachart/tamultiseries.pas @@ -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; diff --git a/components/tachart/tatools.pas b/components/tachart/tatools.pas index 424e033300..5f696d5b8c 100644 --- a/components/tachart/tatools.pas +++ b/components/tachart/tatools.pas @@ -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;