mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-05 02:56:03 +02:00
TAChart: Improved drawing speed of TColorMapSeries
This commit is contained in:
parent
45d350bfd2
commit
6cebac6b7b
@ -18,7 +18,7 @@ unit TAFuncSeries;
|
|||||||
interface
|
interface
|
||||||
|
|
||||||
uses
|
uses
|
||||||
Classes, Graphics, typ, Types,
|
Classes, Graphics, typ, Types, IntfGraphics,
|
||||||
TAChartUtils, TACustomFuncSeries, TACustomSeries, TACustomSource, TASources,
|
TAChartUtils, TACustomFuncSeries, TACustomSeries, TACustomSource, TASources,
|
||||||
TADrawUtils, TAFitUtils, TALegend, TATypes, TAFitLib, TAStyles, TAColorMap;
|
TADrawUtils, TAFitUtils, TALegend, TATypes, TAFitLib, TAStyles, TAColorMap;
|
||||||
|
|
||||||
@ -421,6 +421,7 @@ type
|
|||||||
FStepX: TFuncSeriesStep;
|
FStepX: TFuncSeriesStep;
|
||||||
FStepY: TFuncSeriesStep;
|
FStepY: TFuncSeriesStep;
|
||||||
FUseImage: TUseImage;
|
FUseImage: TUseImage;
|
||||||
|
FBufferImage: TLazIntfImage;
|
||||||
function GetBuiltinColorSource: TListChartSource;
|
function GetBuiltinColorSource: TListChartSource;
|
||||||
function GetBuiltinPalette: TColorMapPalette;
|
function GetBuiltinPalette: TColorMapPalette;
|
||||||
function GetColorSource: TCustomChartSource;
|
function GetColorSource: TCustomChartSource;
|
||||||
@ -441,9 +442,11 @@ type
|
|||||||
procedure SetUseImage(AValue: TUseImage);
|
procedure SetUseImage(AValue: TUseImage);
|
||||||
protected
|
protected
|
||||||
FMinZ, FMaxZ: Double;
|
FMinZ, FMaxZ: Double;
|
||||||
|
function BufferImageValid: Boolean;
|
||||||
procedure GetLegendItems(AItems: TChartLegendItems); override;
|
procedure GetLegendItems(AItems: TChartLegendItems); override;
|
||||||
procedure GetZRange(ARect: TRect; dx, dy: Integer);
|
procedure GetZRange(ARect: TRect; dx, dy: Integer);
|
||||||
class procedure GetXYCountNeeded(out AXCount, AYCount: Cardinal); virtual;
|
class procedure GetXYCountNeeded(out AXCount, AYCount: Cardinal); virtual;
|
||||||
|
procedure InvalidateBufferImage;
|
||||||
property BuiltinColorSource: TListChartSource read GetBuiltinColorSource;
|
property BuiltinColorSource: TListChartSource read GetBuiltinColorSource;
|
||||||
|
|
||||||
public
|
public
|
||||||
@ -452,8 +455,9 @@ type
|
|||||||
procedure Assign(ASource: TPersistent); override;
|
procedure Assign(ASource: TPersistent); override;
|
||||||
|
|
||||||
public
|
public
|
||||||
function FunctionValue(AX, AY: Double): Double; virtual;
|
procedure ClipRectChanged; override;
|
||||||
procedure Draw(ADrawer: IChartDrawer); override;
|
procedure Draw(ADrawer: IChartDrawer); override;
|
||||||
|
function FunctionValue(AX, AY: Double): Double; virtual;
|
||||||
function IsEmpty: Boolean; override;
|
function IsEmpty: Boolean; override;
|
||||||
published
|
published
|
||||||
property AxisIndexX;
|
property AxisIndexX;
|
||||||
@ -501,7 +505,7 @@ implementation
|
|||||||
|
|
||||||
uses
|
uses
|
||||||
{$IF FPC_FullVersion >= 30101}ipf{$ELSE}ipf_fix{$ENDIF},
|
{$IF FPC_FullVersion >= 30101}ipf{$ELSE}ipf_fix{$ENDIF},
|
||||||
GraphType, GraphUtil, IntfGraphics, Math, spe, StrUtils, SysUtils,
|
GraphType, GraphUtil, Math, spe, StrUtils, SysUtils,
|
||||||
TAChartStrConsts, TAGeometry, TAGraph, TAMath;
|
TAChartStrConsts, TAGeometry, TAGraph, TAMath;
|
||||||
|
|
||||||
const
|
const
|
||||||
@ -2474,6 +2478,7 @@ end;
|
|||||||
|
|
||||||
destructor TCustomColorMapSeries.Destroy;
|
destructor TCustomColorMapSeries.Destroy;
|
||||||
begin
|
begin
|
||||||
|
FreeAndNil(FBufferImage);
|
||||||
FreeAndNil(FColorMap);
|
FreeAndNil(FColorMap);
|
||||||
FreeAndNil(FBrush);
|
FreeAndNil(FBrush);
|
||||||
inherited Destroy;
|
inherited Destroy;
|
||||||
@ -2491,6 +2496,20 @@ begin
|
|||||||
inherited Assign(ASource);
|
inherited Assign(ASource);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ Returns whether there exists a buffer image of the color map at the moment. }
|
||||||
|
function TCustomColorMapSeries.BufferImageValid: Boolean;
|
||||||
|
begin
|
||||||
|
Result := Assigned(FBufferImage);
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ Is called by the chart when it detects a change in the clip rect (series area).
|
||||||
|
The ColorMapSeries must recalculate the buffer image afterwards in the
|
||||||
|
next paint event. }
|
||||||
|
procedure TCustomColorMapSeries.ClipRectChanged;
|
||||||
|
begin
|
||||||
|
InvalidateBufferImage;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TCustomColorMapSeries.Draw(ADrawer: IChartDrawer);
|
procedure TCustomColorMapSeries.Draw(ADrawer: IChartDrawer);
|
||||||
var
|
var
|
||||||
ext: TDoubleRect;
|
ext: TDoubleRect;
|
||||||
@ -2500,7 +2519,6 @@ var
|
|||||||
pt, next, offset: TPoint;
|
pt, next, offset: TPoint;
|
||||||
gp: TDoublePoint;
|
gp: TDoublePoint;
|
||||||
v: Double;
|
v: Double;
|
||||||
img: TLazIntfImage = nil;
|
|
||||||
rawImage: TRawImage;
|
rawImage: TRawImage;
|
||||||
optimize: Boolean;
|
optimize: Boolean;
|
||||||
x, y: Integer;
|
x, y: Integer;
|
||||||
@ -2528,8 +2546,18 @@ begin
|
|||||||
cmuiNever: optimize := false;
|
cmuiNever: optimize := false;
|
||||||
end;
|
end;
|
||||||
if optimize then
|
if optimize then
|
||||||
img := CreateLazIntfImage(rawImage, r.BottomRight - r.TopLeft)
|
begin
|
||||||
else begin
|
if BufferImageValid then
|
||||||
|
begin
|
||||||
|
ADrawer.PutImage(r.Left, r.Top, FBufferImage);
|
||||||
|
exit;
|
||||||
|
end else
|
||||||
|
begin
|
||||||
|
FBufferImage.Free;
|
||||||
|
FBufferImage := CreateLazIntfImage(rawImage, r.BottomRight - r.TopLeft)
|
||||||
|
end;
|
||||||
|
end else
|
||||||
|
begin
|
||||||
ADrawer.Brush := Brush;
|
ADrawer.Brush := Brush;
|
||||||
ADrawer.SetPenParams(psClear, clTAColor);
|
ADrawer.SetPenParams(psClear, clTAColor);
|
||||||
end;
|
end;
|
||||||
@ -2544,50 +2572,45 @@ begin
|
|||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
try
|
pt.Y := (r.Top div scaled_stepY - 1) * scaled_stepY + offset.Y mod scaled_stepY;
|
||||||
pt.Y := (r.Top div scaled_stepY - 1) * scaled_stepY + offset.Y mod scaled_stepY;
|
while pt.Y <= r.Bottom do begin
|
||||||
while pt.Y <= r.Bottom do begin
|
next.Y := pt.Y + scaled_stepY;
|
||||||
next.Y := pt.Y + scaled_stepY;
|
if next.Y <= r.Top then begin
|
||||||
if next.Y <= r.Top then begin
|
pt.Y := next.Y;
|
||||||
pt.Y := next.Y;
|
continue;
|
||||||
|
end;
|
||||||
|
pt.X := (r.Left div scaled_stepX - 1) * scaled_stepX + offset.X mod scaled_stepX;
|
||||||
|
while pt.X <= r.Right do begin
|
||||||
|
next.X := pt.X + scaled_stepX;
|
||||||
|
if next.X <= r.Left then begin
|
||||||
|
pt.X := next.X;
|
||||||
continue;
|
continue;
|
||||||
end;
|
end;
|
||||||
pt.X := (r.Left div scaled_stepX - 1) * scaled_stepX + offset.X mod scaled_stepX;
|
gp := GraphToAxis(ParentChart.ImageToGraph((pt + next) div 2));
|
||||||
while pt.X <= r.Right do begin
|
v := FunctionValue(gp.X, gp.Y);
|
||||||
next.X := pt.X + scaled_stepX;
|
cell := Rect(
|
||||||
if next.X <= r.Left then begin
|
Max(pt.X, r.Left), Max(pt.Y, r.Top),
|
||||||
pt.X := next.X;
|
Min(next.X, r.Right) + 1, Min(next.Y, r.Bottom) + 1);
|
||||||
continue;
|
if optimize then begin
|
||||||
end;
|
if ColorSource = nil then
|
||||||
gp := GraphToAxis(ParentChart.ImageToGraph((pt + next) div 2));
|
cellColor := Brush.Color
|
||||||
// if not (csDesigning in ComponentState) then
|
else
|
||||||
v := FunctionValue(gp.X, gp.Y);
|
cellColor := FColorMap.ColorByValue(v);
|
||||||
cell := Rect(
|
for y := cell.Top - r.Top to cell.Bottom - r.Top - 2 do
|
||||||
Max(pt.X, r.Left), Max(pt.Y, r.Top),
|
for x := cell.Left - r.Left to cell.Right - r.Left - 2 do
|
||||||
Min(next.X, r.Right) + 1, Min(next.Y, r.Bottom) + 1);
|
FBufferImage.TColors[x, y] := cellColor;
|
||||||
if optimize then begin
|
end
|
||||||
if ColorSource = nil then
|
else begin
|
||||||
cellColor := Brush.Color
|
if ColorSource <> nil then
|
||||||
else
|
ADrawer.BrushColor := FColorMap.ColorByValue(v);
|
||||||
cellColor := FColorMap.ColorByValue(v);
|
ADrawer.Rectangle(cell);
|
||||||
for y := cell.Top - r.Top to cell.Bottom - r.Top - 2 do
|
|
||||||
for x := cell.Left - r.Left to cell.Right - r.Left - 2 do
|
|
||||||
img.TColors[x, y] := cellColor;
|
|
||||||
end
|
|
||||||
else begin
|
|
||||||
if ColorSource <> nil then
|
|
||||||
ADrawer.BrushColor := FColorMap.ColorByValue(v);
|
|
||||||
ADrawer.Rectangle(cell);
|
|
||||||
end;
|
|
||||||
pt.X := next.X;
|
|
||||||
end;
|
end;
|
||||||
pt.Y := next.Y;
|
pt.X := next.X;
|
||||||
end;
|
end;
|
||||||
if optimize then
|
pt.Y := next.Y;
|
||||||
ADrawer.PutImage(r.Left, r.Top, img);
|
|
||||||
finally
|
|
||||||
FreeAndNil(img);
|
|
||||||
end;
|
end;
|
||||||
|
if optimize and BufferImageValid then
|
||||||
|
ADrawer.PutImage(r.Left, r.Top, FBufferImage);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TCustomColorMapSeries.FunctionValue(AX, AY: Double): Double;
|
function TCustomColorMapSeries.FunctionValue(AX, AY: Double): Double;
|
||||||
@ -2742,6 +2765,14 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ Destroys the current buffer image because some parameter affecting it has
|
||||||
|
changed. The buffer image will be recreated when the series is painted the
|
||||||
|
next time. }
|
||||||
|
procedure TCustomColorMapSeries.InvalidateBufferImage;
|
||||||
|
begin
|
||||||
|
FreeAndNil(FBufferImage);
|
||||||
|
end;
|
||||||
|
|
||||||
function TCustomColorMapSeries.IsEmpty: Boolean;
|
function TCustomColorMapSeries.IsEmpty: Boolean;
|
||||||
begin
|
begin
|
||||||
Result := true;
|
Result := true;
|
||||||
@ -2766,33 +2797,40 @@ procedure TCustomColorMapSeries.SetBrush(AValue: TBrush);
|
|||||||
begin
|
begin
|
||||||
if FBrush = AValue then exit;
|
if FBrush = AValue then exit;
|
||||||
FBrush := AValue;
|
FBrush := AValue;
|
||||||
|
InvalidateBufferImage;
|
||||||
UpdateParentChart;
|
UpdateParentChart;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TCustomColorMapSeries.SetBuiltinPalette(AValue: TColorMapPalette);
|
procedure TCustomColorMapSeries.SetBuiltinPalette(AValue: TColorMapPalette);
|
||||||
begin
|
begin
|
||||||
|
InvalidateBufferImage;
|
||||||
FColorMap.BuiltinPalette := AValue;
|
FColorMap.BuiltinPalette := AValue;
|
||||||
|
UpdateParentChart;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TCustomColorMapSeries.SetColorSource(AValue: TCustomChartSource);
|
procedure TCustomColorMapSeries.SetColorSource(AValue: TCustomChartSource);
|
||||||
begin
|
begin
|
||||||
|
InvalidateBufferImage;
|
||||||
FColorMap.ColorSource := AValue;
|
FColorMap.ColorSource := AValue;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TCustomColorMapSeries.SetInterpolate(AValue: Boolean);
|
procedure TCustomColorMapSeries.SetInterpolate(AValue: Boolean);
|
||||||
begin
|
begin
|
||||||
if GetInterpolate = AValue then exit;
|
if GetInterpolate = AValue then exit;
|
||||||
|
InvalidateBufferImage;
|
||||||
FColorMap.Interpolate := AValue;
|
FColorMap.Interpolate := AValue;
|
||||||
UpdateParentChart;
|
UpdateParentChart;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TCustomColorMapSeries.SetPaletteMax(AValue: Double);
|
procedure TCustomColorMapSeries.SetPaletteMax(AValue: Double);
|
||||||
begin
|
begin
|
||||||
|
InvalidateBufferImage;
|
||||||
FColorMap.PaletteMax := AValue;
|
FColorMap.PaletteMax := AValue;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TCustomColorMapSeries.SetPaletteMin(AValue: Double);
|
procedure TCustomColorMapSeries.SetPaletteMin(AValue: Double);
|
||||||
begin
|
begin
|
||||||
|
InvalidateBufferImage;
|
||||||
FColorMap.PaletteMin := AValue;
|
FColorMap.PaletteMin := AValue;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -2800,6 +2838,7 @@ procedure TCustomColorMapSeries.SetStepX(AValue: TFuncSeriesStep);
|
|||||||
begin
|
begin
|
||||||
if FStepX = AValue then exit;
|
if FStepX = AValue then exit;
|
||||||
FStepX := AValue;
|
FStepX := AValue;
|
||||||
|
InvalidateBufferImage;
|
||||||
UpdateParentChart;
|
UpdateParentChart;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -2807,6 +2846,7 @@ procedure TCustomColorMapSeries.SetStepY(AValue: TFuncSeriesStep);
|
|||||||
begin
|
begin
|
||||||
if FStepY = AValue then exit;
|
if FStepY = AValue then exit;
|
||||||
FStepY := AValue;
|
FStepY := AValue;
|
||||||
|
InvalidateBufferImage;
|
||||||
UpdateParentChart;
|
UpdateParentChart;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -2814,6 +2854,7 @@ procedure TCustomColorMapSeries.SetUseImage(AValue: TUseImage);
|
|||||||
begin
|
begin
|
||||||
if FUseImage = AValue then exit;
|
if FUseImage = AValue then exit;
|
||||||
FUseImage := AValue;
|
FUseImage := AValue;
|
||||||
|
InvalidateBufferImage;
|
||||||
UpdateParentChart;
|
UpdateParentChart;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -2846,6 +2887,7 @@ procedure TColorMapSeries.SetOnCalculate(AValue: TFuncCalculate3DEvent);
|
|||||||
begin
|
begin
|
||||||
if TMethod(FOnCalculate) = TMethod(AValue) then exit;
|
if TMethod(FOnCalculate) = TMethod(AValue) then exit;
|
||||||
FOnCalculate := AValue;
|
FOnCalculate := AValue;
|
||||||
|
InvalidateBufferImage;
|
||||||
UpdateParentChart;
|
UpdateParentChart;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -75,6 +75,7 @@ type
|
|||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
|
|
||||||
public
|
public
|
||||||
|
procedure ClipRectChanged; virtual; virtual;
|
||||||
procedure Draw(ADrawer: IChartDrawer); virtual; abstract;
|
procedure Draw(ADrawer: IChartDrawer); virtual; abstract;
|
||||||
function GetAxisBounds(AAxis: TChartAxis; out AMin, AMax: Double): boolean; virtual; abstract;
|
function GetAxisBounds(AAxis: TChartAxis; out AMin, AMax: Double): boolean; virtual; abstract;
|
||||||
function GetGraphBounds: TDoubleRect; virtual; abstract;
|
function GetGraphBounds: TDoubleRect; virtual; abstract;
|
||||||
@ -835,6 +836,8 @@ procedure TChart.DisplaySeries(ADrawer: IChartDrawer);
|
|||||||
begin
|
begin
|
||||||
try
|
try
|
||||||
ADrawer.SetTransparency(ATransparency);
|
ADrawer.SetTransparency(ATransparency);
|
||||||
|
if FClipRect <> FOldClipRect then
|
||||||
|
ASeries.ClipRectChanged;
|
||||||
ASeries.Draw(ADrawer);
|
ASeries.Draw(ADrawer);
|
||||||
except
|
except
|
||||||
ASeries.Active := false;
|
ASeries.Active := false;
|
||||||
@ -2052,6 +2055,11 @@ begin
|
|||||||
// empty
|
// empty
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TBasicChartSeries.ClipRectChanged;
|
||||||
|
begin
|
||||||
|
// empty
|
||||||
|
end;
|
||||||
|
|
||||||
destructor TBasicChartSeries.Destroy;
|
destructor TBasicChartSeries.Destroy;
|
||||||
begin
|
begin
|
||||||
if FChart <> nil then
|
if FChart <> nil then
|
||||||
|
Loading…
Reference in New Issue
Block a user