📄 teemapseries.pas
字号:
{******************************************}
{ TeeChart Map Series }
{ Copyright (c) 2000-2007 by David Berneda }
{ All Rights Reserved }
{******************************************}
unit TeeMapSeries;
{$I TeeDefs.inc}
interface
Uses {$IFNDEF LINUX}
Windows, Messages,
{$ENDIF}
SysUtils, Classes,
{$IFDEF CLX}
QGraphics, Types,
{$ELSE}
Graphics,
{$IFDEF D6}
Types,
{$ENDIF}
{$ENDIF}
TeEngine, TeCanvas, TeeProcs, TeeSurfa;
type
TTeePolygon=class;
TPolygonSeries=class(TChartSeries)
protected
Procedure DrawLegendShape(ValueIndex:Integer; Const Rect:TRect); override;
Procedure NotifyValue(ValueEvent:TValueEvent; ValueIndex:Integer); override;
procedure PrepareLegendCanvas(ValueIndex:Integer; Var BackColor:TColor;
Var BrushStyle:TBrushStyle); override;
Procedure SetActive(Value:Boolean); override;
Procedure SetSeriesColor(AColor:TColor); override;
public
Procedure FillSampleValues(NumValues:Integer); override;
Function Polygon:TTeePolygon; {$IFDEF D9}inline;{$ENDIF}
end;
TMapSeries=class;
TTeePolygon=class(TCollectionItem)
private
FClosed : Boolean;
FGradient : TChartGradient;
FParentBrush : Boolean;
FParentPen : Boolean;
FPoints : TPolygonSeries;
FTransparency: TTeeTransparency;
{$IFDEF CLR}
procedure CanvasChanged(Sender: TObject);
{$ENDIF}
function GetBrush: TChartBrush;
function GetColor: TColor;
function GetGradient: TChartGradient;
function GetPen: TChartPen;
Function GetText:String;
function GetTransparent: Boolean;
function GetZ: Double;
function PointRect:TRect;
procedure SetBrush(const Value: TChartBrush);
procedure SetClosed(const Value: Boolean);
procedure SetColor(const Value: TColor);
procedure SetGradient(const Value: TChartGradient);
procedure SetParentBrush(const Value: Boolean);
procedure SetParentPen(const Value: Boolean);
procedure SetPen(const Value: TChartPen);
Procedure SetText(Const Value:String);
procedure SetTransparency(const Value: TTeeTransparency);
procedure SetTransparent(const Value: Boolean);
procedure SetZ(const Value: Double);
protected
IPoints : TPointArray;
procedure DefineProperties(Filer: TFiler); override;
procedure DoDraw(ACanvas:TCanvas3D; Index:Integer; AColor:TColor;
ATransp:TTeeTransparency; DrawGradient:Boolean);
public
ParentSeries : TMapSeries;
Constructor Create(Collection:TCollection); override;
Destructor Destroy; override;
Function AddXY(Const Point:TFloatPoint):Integer; overload;
Function AddXY(Const X,Y:Double):Integer; overload;
Procedure Draw(ACanvas:TCanvas3D; ValueIndex:Integer);
Function GetPoints:TPointArray;
Function Visible:Boolean;
Function Bounds:TRect;
property Points:TPolygonSeries read FPoints;
published
property Brush:TChartBrush read GetBrush write SetBrush;
property Closed:Boolean read FClosed write SetClosed default True;
property Color:TColor read GetColor write SetColor default clWhite;
property Gradient:TChartGradient read GetGradient write SetGradient;
property ParentBrush:Boolean read FParentBrush write SetParentBrush default True;
property ParentPen:Boolean read FParentPen write SetParentPen default True;
property Pen:TChartPen read GetPen write SetPen;
property Text:String read GetText write SetText;
property Transparency:TTeeTransparency read FTransparency write SetTransparency default 0;
property Transparent:Boolean read GetTransparent write SetTransparent default False;
property Z:Double read GetZ write SetZ;
end;
TTeePolygonList=class(TOwnedCollection)
private
Procedure Delete(Start,Quantity:Integer); overload;
Function Get(Index:Integer):TTeePolygon; {$IFDEF D10}inline;{$ENDIF} // 7.05
function GetByName(const AName: String): TTeePolygon;
Procedure Put(Index:Integer; Const Value:TTeePolygon);
public
Function Add:TTeePolygon;
Function Owner:TMapSeries; {$IFDEF D10}inline;{$ENDIF}
property Polygon[Index:Integer]:TTeePolygon read Get write Put; default;
property ByName[const AName:String]:TTeePolygon read GetByName; // 7.0
end;
TMapSeries=class(TCustom3DPaletteSeries)
private
FPointSize : Integer;
FShadow : TTeeShadow;
FShapes : TTeePolygonList;
FTransparency : TTeeTransparency;
FTransparent : Boolean;
I3DList : Array of TTeePolygon;
Function CompareOrder(a,b:Integer):Integer;
Function GetPolygon(Index:Integer):TTeePolygon; {$IFDEF D10}inline;{$ENDIF} // 7.05
procedure SetPointSize(const Value: Integer);
procedure SetShadow(const Value: TTeeShadow);
procedure SetShapes(const Value: TTeePolygonList);
procedure SetTransparency(const Value:TTeeTransparency);
procedure SetTransparent(const Value:Boolean);
Procedure SwapPolygon(a,b:Integer);
protected
CanSaveData : Boolean;
Procedure AddSampleValues(NumValues:Integer; OnlyMandatory:Boolean=False); override;
Procedure CalcHorizMargins(Var LeftMargin,RightMargin:Integer); override;
procedure CalcSelectionPos(ValueIndex:Integer; out X,Y:Integer); override;
Procedure CalcVerticalMargins(Var TopMargin,BottomMargin:Integer); override;
class procedure CreateSubGallery(AddSubChart: TChartSubGalleryProc); override;
procedure DefineProperties(Filer: TFiler); override;
Procedure DrawAllValues; override;
Procedure DrawMark( ValueIndex:Integer; Const St:String;
APosition:TSeriesMarkPosition); override;
Procedure DrawValue(ValueIndex:Integer); override;
Procedure GalleryChanged3D(Is3D:Boolean); override;
class Function GetEditorClass:String; override;
procedure PrepareForGallery(IsEnabled:Boolean); override;
class procedure SetSubGallery(ASeries: TChartSeries; Index: Integer); override;
public
Constructor Create(AOwner:TComponent); override;
Destructor Destroy; override;
procedure Assign(Source:TPersistent); override;
Procedure Clear; override;
Function Clicked(x,y:Integer):Integer; override;
Procedure Delete(ValueIndex:Integer); overload; override;
Procedure Delete(Start,Quantity:Integer; RemoveGap:Boolean=False); overload; override;
Function MaxXValue:Double; override;
Function MaxYValue:Double; override;
Function MinXValue:Double; override;
Function MinYValue:Double; override;
Function NumSampleValues:Integer; override;
procedure SwapValueIndex(a,b:Integer); override;
property Polygon[Index:Integer]:TTeePolygon read GetPolygon; default; // 7.0
published
{ Published declarations }
property Active;
property ColorSource;
property Cursor;
property HorizAxis;
property Marks;
property ParentChart;
property DataSource;
property PercentFormat;
property SeriesColor;
property ShowInLegend;
property Title;
property ValueFormat;
property VertAxis;
property XLabelsSource;
property Brush;
property EndColor;
property MidColor;
property LegendEvery;
property Pen;
property PaletteMin;
property PaletteStep;
property PaletteSteps;
property PointSize:Integer read FPointSize write SetPointSize default 1;
property Shadow:TTeeShadow read FShadow write SetShadow;
property Shapes:TTeePolygonList read FShapes write SetShapes;
property StartColor;
property Transparent:Boolean read FTransparent write SetTransparent default False;
property Transparency:TTeeTransparency read FTransparency write SetTransparency default 0;
property UseColorRange;
property UsePalette;
property UsePaletteMin;
property TimesZOrder;
property XValues;
property YValues;
property ZValues;
{ events }
property AfterDrawValues;
property BeforeDrawValues;
property OnAfterAdd;
property OnBeforeAdd;
property OnClearValues;
property OnClick;
property OnDblClick;
property OnGetColor;
property OnGetMarkText;
property OnMouseEnter;
property OnMouseLeave;
end;
function PolygonArea(const P:TPointArray): Double;
function PolygonCentroid(const P:TPointArray):TPointFloat;
implementation
Uses Math,
{$IFDEF CLR}
Variants,
{$ENDIF}
TeeConst, TeeProCo, Chart;
{$IFNDEF CLR}
type
TSeriesAccess=class(TCustomChartElement);
{$ENDIF}
{ TTeePolygon }
constructor TTeePolygon.Create(Collection: TCollection);
begin
inherited;
ParentSeries:=TTeePolygonList(Collection).Owner as TMapSeries;
FClosed:=True;
FPoints:=TPolygonSeries.Create(nil); // 7.0
FPoints.Tag:={$IFDEF CLR}Variant{$ELSE}Integer{$ENDIF}(Self);
FPoints.XValues.Order:=loNone;
FPoints.ShowInLegend:=False;
FParentPen:=True;
FParentBrush:=True;
FTransparency:=ParentSeries.Transparency;
while ParentSeries.Count<ParentSeries.Shapes.Count do // 8.0
ParentSeries.AddXY(0,0);
end;
Destructor TTeePolygon.Destroy;
begin
IPoints:=nil;
FPoints.Tag:=0;
FPoints.Free;
FGradient.Free;
inherited;
end;
function TTeePolygon.AddXY(const Point:TFloatPoint): Integer;
begin
result:=FPoints.AddXY(Point.X,Point.Y);
end;
function TTeePolygon.AddXY(const X,Y: Double): Integer;
begin
result:=FPoints.AddXY(X,Y);
end;
{ return the array of Points in screen (pixel) coordinates }
Function TTeePolygon.GetPoints:TPointArray;
var t : Integer;
tmpHoriz : TChartAxis;
tmpVert : TChartAxis;
tmpX : TChartValues;
tmpY : TChartValues;
tmpCount : Integer;
begin
tmpCount:=FPoints.Count;
SetLength(IPoints,tmpCount);
result:=TPointArray(IPoints);
tmpHoriz:=ParentSeries.GetHorizAxis;
tmpVert:=ParentSeries.GetVertAxis;
tmpX:=FPoints.XValues.Value;
tmpY:=FPoints.YValues.Value;
for t:=0 to tmpCount-1 do
begin
result[t].X:=tmpHoriz.CalcPosValue(tmpX[t]);
result[t].Y:=tmpVert.CalcPosValue(tmpY[t]);
end;
end;
// Returns True if the polygon contains points that lie inside
// the chart "ChartRect" (the visible chart area).
Function TTeePolygon.Visible:Boolean;
// optimized version of InteresectRect
function ContainsRect(R1:TRect; const R2:TRect): Boolean;
begin
if R2.Left > R1.Left then R1.Left := R2.Left;
if R2.Right < R1.Right then R1.Right := R2.Right;
if R2.Top > R1.Top then R1.Top := R2.Top;
if R2.Bottom < R1.Bottom then R1.Bottom := R2.Bottom;
result := not ((R1.Right < R1.Left) or (R1.Bottom < R1.Top));
end;
var tmpR : TRect;
tmpChart : TCustomAxisPanel;
begin
tmpChart:=ParentSeries.ParentChart;
result:=not tmpChart.ClipPoints;
if not result then
begin
with ParentSeries.GetHorizAxis do
begin
tmpR.Left:=CalcPosValue(FPoints.XValues.MinValue);
tmpR.Right:=CalcPosValue(FPoints.XValues.MaxValue);
if Inverted then
SwapInteger(tmpR.Left,tmpR.Right); // 7.01
end;
with ParentSeries.GetVertAxis do
begin
tmpR.Top:=CalcPosValue(FPoints.YValues.MaxValue);
tmpR.Bottom:=CalcPosValue(FPoints.YValues.MinValue);
if Inverted then
SwapInteger(tmpR.Top,tmpR.Bottom); // 7.01
end;
result:=ContainsRect(tmpChart.ChartRect, tmpR);
end;
end;
function TTeePolygon.PointRect:TRect;
var tmpA : Integer;
tmpB : Integer;
begin
tmpA:=((ParentSeries.PointSize+1) div 2)-1;
if (ParentSeries.PointSize+1) mod 2 = 0 then
tmpB:=tmpA+1
else
tmpB:=tmpA+2;
with result do
begin
Left:=IPoints[0].X-tmpA;
Top:=IPoints[0].Y-tmpA;
Right:=IPoints[0].X+tmpB;
Bottom:=IPoints[0].Y+tmpB;
end;
end;
procedure TTeePolygon.DoDraw(ACanvas:TCanvas3D; Index:Integer; AColor:TColor;
ATransp:TTeeTransparency; DrawGradient:Boolean);
var tmpIs3D : Boolean;
tmpBlend : TTeeBlend;
tmpZ : Integer;
tmpP : TPointArray;
tmpR : TRect;
begin
tmpP:=nil;
tmpIs3D:=ParentSeries.ParentChart.View3D;
// Calculate "Z" depth position
if tmpIs3D then tmpZ:=ParentSeries.CalcZPos(Index)
else tmpZ:=0;
if ATransp>0 then
begin
if tmpIs3D then
begin
tmpP:=ACanvas.Calc3DPoints(IPoints,tmpZ);
try
tmpR:=PolygonBounds(tmpP);
finally
tmpP:=nil;
end;
end
else
tmpR:=PolygonBounds(IPoints);
tmpBlend:=ACanvas.BeginBlending(tmpR {ACanvas.RectFromRectZ(tmpR,tmpZ)},ATransp)
end
else
tmpBlend:=nil;
// Fill background with gradient...
if DrawGradient and Assigned(FGradient) and FGradient.Visible
and ParentSeries.ParentChart.CanClip then
begin
Gradient.Draw(ACanvas,IPoints,tmpZ,tmpIs3D);
ACanvas.Brush.Style:=bsClear;
end;
// Draw the shape...
with ACanvas do
begin
// Special case for shapes with just a single point
if FPoints.Count=1 then
if ParentSeries.PointSize>1 then
begin
if ParentSeries.PointSize<3 then
Pen.Style:=psClear;
if tmpIs3D then
Rectangle(PointRect,tmpZ)
else
Rectangle(PointRect);
end
else
if tmpIs3D then
Pixels3D[IPoints[0].X,IPoints[0].Y,tmpZ]:=AColor
else
Pixels[IPoints[0].X,IPoints[0].Y]:=AColor
else
// Normal polygon shapes...
if tmpIs3D then
begin
if Self.Closed then
PolygonWithZ(IPoints,tmpZ)
else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -