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 type
TNearestPointParams = record TNearestPointParams = record
FDistFunc: TPointDistFunc; FDistFunc: TPointDistFunc;
FOptimizeX: Boolean;
FPoint: TPoint; FPoint: TPoint;
FRadius: Integer; FRadius: Integer;
end; end;
@ -1013,14 +1014,32 @@ end;
function TBasicPointSeries.GetNearestPoint( function TBasicPointSeries.GetNearestPoint(
const AParams: TNearestPointParams; const AParams: TNearestPointParams;
out AResults: TNearestPointResults): Boolean; 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 var
dist, i: Integer; dist, i, lb, ub: Integer;
pt: TPoint; pt: TPoint;
sp: TDoublePoint; sp: TDoublePoint;
begin begin
AResults.FDist := Sqr(AParams.FRadius) + 1; AResults.FDist := Sqr(AParams.FRadius) + 1;
AResults.FIndex := -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; sp := Source[i]^.Point;
if IsNan(sp) then continue; if IsNan(sp) then continue;
// Since axis transformation may be non-linear, the distance should be // Since axis transformation may be non-linear, the distance should be

View File

@ -644,19 +644,25 @@ function TDrawFuncHelper.GetNearestPoint(
const AParams: TNearestPointParams; const AParams: TNearestPointParams;
out AResults: TNearestPointResults): Boolean; out AResults: TNearestPointResults): Boolean;
var var
x, r: Integer; x: Integer;
r: TDoubleInterval;
begin begin
AResults.FIndex := -1; AResults.FIndex := -1;
AResults.FDist := Sqr(AParams.FRadius) + 1; AResults.FDist := Sqr(AParams.FRadius) + 1;
FNearestPointParams := @AParams; FNearestPointParams := @AParams;
FNearestPointResults := @AResults; FNearestPointResults := @AResults;
x := TPointBoolArr(AParams.FPoint)[FSeries.IsRotated]; with AParams do
r := IfThen(FSeries.IsRotated, -1, 1) * AParams.FRadius; 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 with XRange do
ForEachPoint( ForEachPoint(
Max(FImageToGraph(x - r), FStart), Max(r.FStart, FStart), Min(r.FEnd, FEnd),
Min(FImageToGraph(x + r), FEnd),
@CheckForNearestPoint, @CheckForNearestPoint); @CheckForNearestPoint, @CheckForNearestPoint);
Result := AResults.FDist < Sqr(AParams.FRadius) + 1; Result := AResults.FDist < Sqr(AParams.FRadius) + 1;

View File

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