TAChart: Optimize GetNearestPoint for the case of sorted source and at least linear on X point distance

git-svn-id: trunk@38853 -
This commit is contained in:
ask 2012-09-27 12:10:33 +00:00
parent f33a977acb
commit c66a6f83f6
3 changed files with 34 additions and 7 deletions

View File

@ -33,6 +33,7 @@ const
type
TNearestPointParams = record
FDistFunc: TPointDistFunc;
FOptimizeX: Boolean;
FPoint: TPoint;
FRadius: Integer;
end;
@ -1013,14 +1014,32 @@ end;
function TBasicPointSeries.GetNearestPoint(
const AParams: TNearestPointParams;
out AResults: TNearestPointResults): Boolean;
function GetGrabBound(ARadius: Integer): Double;
begin
if IsRotated then
Result := ParentChart.YImageToGraph(AParams.FPoint.Y + ARadius)
else
Result := ParentChart.XImageToGraph(AParams.FPoint.X + ARadius);
Result := GraphToAxisX(Result);
end;
var
dist, i: Integer;
dist, i, lb, ub: Integer;
pt: TPoint;
sp: TDoublePoint;
begin
AResults.FDist := Sqr(AParams.FRadius) + 1;
AResults.FIndex := -1;
for i := 0 to Count - 1 do begin
if AParams.FOptimizeX then
Source.FindBounds(
GetGrabBound(-AParams.FRadius),
GetGrabBound( AParams.FRadius), lb, ub)
else begin
lb := 0;
ub := Count - 1;
end;
for i := lb to ub do begin
sp := Source[i]^.Point;
if IsNan(sp) then continue;
// Since axis transformation may be non-linear, the distance should be

View File

@ -644,19 +644,25 @@ function TDrawFuncHelper.GetNearestPoint(
const AParams: TNearestPointParams;
out AResults: TNearestPointResults): Boolean;
var
x, r: Integer;
x: Integer;
r: TDoubleInterval;
begin
AResults.FIndex := -1;
AResults.FDist := Sqr(AParams.FRadius) + 1;
FNearestPointParams := @AParams;
FNearestPointResults := @AResults;
x := TPointBoolArr(AParams.FPoint)[FSeries.IsRotated];
r := IfThen(FSeries.IsRotated, -1, 1) * AParams.FRadius;
with AParams do
if FOptimizeX then begin
x := TPointBoolArr(FPoint)[FSeries.IsRotated];
r := DoubleInterval(FImageToGraph(x - FRadius), FImageToGraph(x + FRadius));
EnsureOrder(r.FStart, r.FEnd);
end
else
r := DoubleInterval(NegInfinity, SafeInfinity);
with XRange do
ForEachPoint(
Max(FImageToGraph(x - r), FStart),
Min(FImageToGraph(x + r), FEnd),
Max(r.FStart, FStart), Min(r.FEnd, FEnd),
@CheckForNearestPoint, @CheckForNearestPoint);
Result := AResults.FDist < Sqr(AParams.FRadius) + 1;

View File

@ -1169,6 +1169,7 @@ begin
p.FDistFunc := DIST_FUNCS[FChart.ReticuleMode];
p.FPoint := APoint;
p.FRadius := Trunc(Sqrt(MaxInt));
p.FOptimizeX := false;
for s in CustomSeries(FChart) do
if
(not (s is TBasicPointSeries) or TBasicPointSeries(s).UseReticule) and
@ -1463,6 +1464,7 @@ begin
p.FDistFunc := DIST_FUNCS[DistanceMode];
p.FPoint := APoint;
p.FRadius := GrabRadius;
p.FOptimizeX := DistanceMode <> cdmOnlyY;
best.FDist := MaxInt;
for s in CustomSeries(FChart, FAffectedSeries.AsBooleans(FChart.SeriesCount)) do
if