home *** CD-ROM | disk | FTP | other *** search
/ Delphi 5 for Professionals / DELPHI5.iso / AddOns / Components / TEECHART / Src Code / TEEPOLAR.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1998-10-24  |  24.8 KB  |  847 lines

  1. {*********************************************}
  2. { TeeChart Delphi Component Library           }
  3. {    Polar and Radar Series Components        }
  4. { Copyright (c) 1995-1998 by David Berneda    }
  5. { All rights reserved                         }
  6. {*********************************************}
  7. {$I teedefs.inc}
  8. unit TeePolar;
  9.  
  10. interface
  11.  
  12. uses
  13.   SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
  14.   Forms, TeEngine, Chart, Series, TeCanvas;
  15.  
  16. Const TeePolarDegreeSymbol:Char='║';
  17.  
  18. type
  19.   TCustomPolarSeries = class(TCircledSeries)
  20.   private
  21.     FBrush            : TChartBrush;
  22.     FCircleLabels     : Boolean;
  23.     FCircleLabelsFont : TFont;
  24.     FCircleLabelsRot  : Boolean;
  25.     FCirclePen        : TChartPen;
  26.     FCloseCircle      : Boolean;
  27.     FPen              : TChartPen;
  28.     FPointer          : TSeriesPointer;
  29.  
  30.     { Private declarations }
  31.     OldX              : Longint;
  32.     OldY              : Longint;
  33.     IMaxValuesCount   : Longint;
  34.     Procedure CalcXYPos( ValueIndex:Longint;
  35.                          Const ARadius:Double; Var X,Y:{$IFDEF D2C1}Longint{$ELSE}Integer{$ENDIF});
  36.     Procedure FillTriangle(Const A,B:TPoint; Z:Integer);
  37.     Function GetAngleIncrement:Double;
  38.     Function GetRadiusIncrement:Double;
  39.     Function GetRadiusValues:TChartValueList;
  40.     Function GetAngleValues:TChartValueList;
  41.     Function IsFontStored:Boolean;
  42.     Function IsRadiusStored:Boolean;
  43.     Procedure SetAngleIncrement(Const Value:Double);
  44.     Procedure SetAngleValues(Value:TChartValueList);
  45.     Procedure SetBrush(Value:TChartBrush);
  46.     Procedure SetCircleLabels(Value:Boolean);
  47.     Procedure SetCircleLabelsFont(Value:TFont);
  48.     procedure SetCirclePen(Value:TChartPen);
  49.     Procedure SetCloseCircle(Value:Boolean);
  50.     Procedure SetLabelsRotated(Value:Boolean);
  51.     Procedure SetPen(Value:TChartPen);
  52.     Procedure SetPointer(Value:TSeriesPointer);
  53.     Procedure SetRadiusIncrement(Const Value:Double);
  54.     Procedure SetRadiusValues(Value:TChartValueList);
  55.   protected
  56.     { Protected declarations }
  57.     Procedure SetParentChart(Value:TCustomAxisPanel); override;
  58.     Procedure DoBeforeDrawValues; override;
  59.     Procedure DrawAllValues; override;
  60.     Procedure DrawPolarCircle(HalfWidth,HalfHeight,Z:Integer);
  61.     procedure DrawValue(ValueIndex:Longint); override;
  62.     Function GetCircleLabel(Const AngleOrIndex:Double):String; virtual;
  63.     procedure LinePrepareCanvas(ValueIndex:Longint);
  64.     Procedure SetSeriesColor(AColor:TColor); override;
  65.   public
  66.     { Public declarations }
  67.     Constructor Create(AOwner: TComponent); override;
  68.     Destructor Destroy; override;
  69.     Procedure Assign(Source:TPersistent); override;
  70.     Function CalcXPos(ValueIndex:Longint):Integer; override;
  71.     Function CalcYPos(ValueIndex:Longint):Integer; override;
  72.     Function Clicked(x,y:Integer):Longint; override;
  73.     Procedure DrawLegendShape(ValueIndex:Longint; Const Rect:TRect); override;
  74.     Procedure DrawRing(Const Value:Double; Z:Integer);
  75.     Function  GetEditorClass:String; override;
  76.     Procedure PrepareForGallery(IsEnabled:Boolean); override;
  77.  
  78.     { to be Published declarations }
  79.     property AngleIncrement:Double read GetAngleIncrement write SetAngleIncrement;
  80.     property AngleValues:TChartValueList read GetAngleValues write SetAngleValues;
  81.     property Brush:TChartBrush read FBrush write SetBrush;
  82.     property CircleLabels:Boolean read FCircleLabels write SetCircleLabels default False;
  83.     property CircleLabelsFont:TFont read FCircleLabelsFont write SetCircleLabelsFont stored IsFontStored;
  84.     property CircleLabelsRotated:Boolean read FCircleLabelsRot
  85.                                          write SetLabelsRotated default False;
  86.     property CirclePen:TChartPen read FCirclePen write SetCirclePen;
  87.     property CloseCircle:Boolean read FCloseCircle
  88.                                  write SetCloseCircle default True;
  89.     property Pen:TChartPen read FPen write SetPen;
  90.     property Pointer:TSeriesPointer read FPointer write SetPointer;
  91.     property RadiusIncrement:Double read GetRadiusIncrement write SetRadiusIncrement;
  92.     property RadiusValues:TChartValueList read GetRadiusValues write SetRadiusValues
  93.                                           stored IsRadiusStored;
  94.   end;
  95.  
  96.   TPolarSeries = class(TCustomPolarSeries)
  97.   public
  98.     Function AddPolar( Const Angle,Value:Double;
  99.                        Const ALabel:String{$IFDEF D4}=''{$ENDIF};
  100.                        AColor:TColor{$IFDEF D4}=clTeeColor{$ENDIF}):Longint;
  101.     Procedure FillSampleValues(NumValues:Longint); override;
  102.   published
  103.     { Published declarations }
  104.     property AngleIncrement;
  105.     property AngleValues;
  106.     property Brush;
  107.     property CircleBackColor;
  108.     property CircleLabels;
  109.     property CircleLabelsFont;
  110.     property CircleLabelsRotated;
  111.     property CirclePen;
  112.     property CloseCircle;
  113.     property Pen;
  114.     property Pointer;
  115.     property RadiusIncrement;
  116.     property RadiusValues;
  117.     property RotationAngle;
  118.   end;
  119.  
  120.   TRadarSeries=class(TCustomPolarSeries)
  121.   protected
  122.     Procedure DoBeforeDrawChart; override;
  123.     Function GetCircleLabel(Const AngleOrIndex:Double):String; override;
  124.   public
  125.     Procedure FillSampleValues(NumValues:Longint); override;
  126.     Procedure PrepareForGallery(IsEnabled:Boolean); override;
  127.   published
  128.     { Published declarations }
  129.     property Brush;
  130.     property CircleBackColor;
  131.     property CircleLabels;
  132.     property CircleLabelsFont;
  133.     property CircleLabelsRotated;
  134.     property CirclePen;
  135.     property CloseCircle;
  136.     property Pen;
  137.     property Pointer;
  138.     property RadiusIncrement;
  139.     property RadiusValues;
  140.   end;
  141.  
  142. implementation
  143.  
  144. Uses TeeProCo,TeeConst,TeeProcs;
  145.  
  146. Const TeeMsg_RadiusValues='Radius'; { <-- dont translate ! }
  147.  
  148. { TCustomPolarSeries }
  149. Constructor TCustomPolarSeries.Create(AOwner: TComponent);
  150. begin
  151.   inherited Create(AOwner);
  152.   IMaxValuesCount:=0;
  153.   FCloseCircle := True;
  154.   FPointer     := TSeriesPointer.Create(Self);
  155.   FPen         := CreateChartPen;
  156.   YValues.Name := TeeMsg_RadiusValues;
  157.   FCirclePen   := CreateChartPen;
  158.   FBrush       := TChartBrush.Create(CanvasChanged);
  159.   FBrush.Style:=bsClear;
  160.   FCircleLabels:= False;
  161.   FCircleLabelsRot:=False;
  162.   FCircleLabelsFont:=CreateDefaultFont(CanvasChanged);
  163.   {$IFDEF TEETRIAL}
  164.   TeeTrial(ComponentState);
  165.   {$ENDIF}
  166. end;
  167.  
  168. Destructor TCustomPolarSeries.Destroy;
  169. Begin
  170.   FCircleLabelsFont.Free;
  171.   FBrush.Free;
  172.   FPen.Free;
  173.   FPointer.Free;
  174.   FCirclePen.Free;
  175.   inherited Destroy;
  176. end;
  177.  
  178. Procedure TCustomPolarSeries.SetParentChart(Value:TCustomAxisPanel);
  179. Begin
  180.   inherited SetParentChart(Value);
  181.   if (ParentChart<>nil) and (csDesigning in ComponentState) then
  182.      ParentChart.View3D:=False;
  183. end;
  184.  
  185. Procedure TCustomPolarSeries.SetCloseCircle(Value:Boolean);
  186. begin
  187.   SetBooleanProperty(FCloseCircle,Value);
  188. end;
  189.  
  190. Procedure TCustomPolarSeries.SetLabelsRotated(Value:Boolean);
  191. begin
  192.   SetBooleanProperty(FCircleLabelsRot,Value);
  193. end;
  194.  
  195. procedure TCustomPolarSeries.SetBrush(Value:TChartBrush);
  196. begin
  197.   FBrush.Assign(Value);
  198. end;
  199.  
  200. procedure TCustomPolarSeries.SetCirclePen(Value:TChartPen);
  201. begin
  202.   FCirclePen.Assign(Value);
  203. end;
  204.  
  205. Procedure TCustomPolarSeries.DrawPolarCircle(HalfWidth,HalfHeight,Z:Integer);
  206. var OldP : TPoint;
  207.     P    : TPoint;
  208.     tmp  : Double;
  209.     t    : Integer;
  210. begin
  211.   With ParentChart.Canvas do
  212.   begin
  213.     if IMaxValuesCount=0 then
  214.        EllipseWithZ( CircleXCenter-HalfWidth,CircleYCenter-HalfHeight,
  215.                      CircleXCenter+HalfWidth,CircleYCenter+HalfHeight, Z)
  216.     else
  217.     begin
  218.       tmp:=piDegree*360.0/IMaxValuesCount;
  219.       AngleToPos(0,HalfWidth,HalfHeight,OldP.X,OldP.Y);
  220.       MoveTo3D(OldP.X,OldP.Y,Z);
  221.       for t:=0 to IMaxValuesCount do
  222.       begin
  223.         AngleToPos(t*tmp,HalfWidth,HalfHeight,P.X,P.Y);
  224.         if Brush.Style<>bsClear then FillTriangle(OldP,P,Z);
  225.         LineTo3D(P.X,P.Y,Z);
  226.         OldP:=P;
  227.       end;
  228.     end;
  229.   end;
  230. end;
  231.  
  232. Function TCustomPolarSeries.GetCircleLabel(Const AngleOrIndex:Double):String;
  233. begin
  234.   result:=FloatToStr(AngleOrIndex)+TeePolarDegreeSymbol;
  235. end;
  236.  
  237. Procedure TCustomPolarSeries.DoBeforeDrawValues;
  238.  
  239.     Procedure SetGridCanvas(Axis:TChartAxis);
  240.     Begin
  241.       with ParentChart,Canvas do
  242.       begin
  243.         Brush.Style:=bsClear;
  244.         BackMode:=cbmTransparent;
  245.         Pen.Assign(Axis.Grid);
  246.         CheckPenWidth(Pen);
  247.         if Pen.Color=clTeeColor then Pen.Color:=clGray;
  248.       end;
  249.     end;
  250.  
  251.     Procedure DrawAngleLabel(Angle:Double);
  252.     var X,Y:{$IFDEF D2C1}Longint{$ELSE}Integer{$ENDIF};
  253.     var tmpHeight : Integer;
  254.         tmpWidth  : Integer;
  255.         tmp       : Double;
  256.         tmp2      : Double;
  257.     begin
  258.       ParentChart.FontCanvas(FCircleLabelsFont);
  259.       With ParentChart.Canvas do
  260.       begin
  261.         tmpHeight:=FontHeight;
  262.         if Angle>=360 then Angle:=Angle-360;
  263.         tmp:=Angle;
  264.         if FCircleLabelsRot then
  265.         begin
  266.           if (tmp>90) and (tmp<270) then tmp2:=Angle-3
  267.                                     else tmp2:=Angle+2;
  268.         end
  269.         else tmp2:=Angle;
  270.         AngleToPos((tmp2)*PiDegree,XRadius+2,YRadius+2,X,Y);
  271.         Angle:=Angle+RotationAngle;
  272.         if Angle>=360 then Angle:=Angle-360;
  273.         if FCircleLabelsRot then
  274.         begin
  275.           if (Angle>90) and (Angle<270) then
  276.           begin
  277.             TextAlign:=ta_Right;
  278.             Angle:=Angle+180;
  279.           end
  280.           else TextAlign:=ta_Left;
  281.           RotateLabel3D(X,Y,EndZ,GetCircleLabel(tmp),Round(Angle));
  282.         end
  283.         else
  284.         begin
  285.           if (Angle=0) or (Angle=180) then Dec(Y,tmpHeight div 2)
  286.           else
  287.           if (Angle>0) and (Angle<180) then Dec(Y,tmpHeight);
  288.           if (Angle=90) or (Angle=270) then TextAlign:=ta_Center
  289.           else
  290.           if (Angle>90) and (Angle<270) then TextAlign:=ta_Right
  291.                                         else TextAlign:=ta_Left;
  292.           tmpWidth:=TextWidth('0') div 2;
  293.           if Angle=0 then Inc(x,tmpWidth) else
  294.           if Angle=180 then Dec(x,tmpWidth);
  295.           TextOut3D(X,Y,EndZ,GetCircleLabel(tmp));
  296.         end;
  297.       end;
  298.     end;
  299.  
  300. var tmpValue     : Double;
  301.     tmpIncrement : Double;
  302.  
  303.     Procedure DrawYGrid;
  304.  
  305.       Procedure InternalDrawGrid;
  306.       begin
  307.         DrawRing(tmpValue,EndZ);
  308.         tmpValue:=tmpValue-tmpIncrement;
  309.       end;
  310.  
  311.     Begin
  312.       With GetVertAxis do
  313.       if Grid.Visible then
  314.       begin
  315.         tmpIncrement:=CalcIncrement;
  316.         if tmpIncrement>0 then
  317.         begin
  318.           SetGridCanvas(GetVertAxis);
  319.           tmpValue:=Maximum/tmpIncrement;
  320.           if (Abs(tmpValue)<MaxLongint) and
  321.              (Abs((Maximum-Minimum)/tmpIncrement)<10000) then
  322.           Begin
  323.             if RoundFirstLabel then tmpValue:=tmpIncrement*Trunc(tmpValue)
  324.                                else tmpValue:=Maximum;
  325.             if LabelsOnAxis then
  326.             begin
  327.               While tmpValue>Maximum do tmpValue:=tmpValue-tmpIncrement;
  328.               While tmpValue>=Minimum do InternalDrawGrid;
  329.             end
  330.             else
  331.             begin
  332.               While tmpValue>=Maximum do tmpValue:=tmpValue-tmpIncrement;
  333.               While tmpValue>Minimum do InternalDrawGrid;
  334.             end;
  335.           end;
  336.         end;
  337.       end;
  338.     end;
  339.  
  340.     Procedure DrawXGrid;
  341.     var tmpX,tmpY:{$IFDEF D2C1}Longint{$ELSE}Integer{$ENDIF};
  342.     Begin
  343.       With GetHorizAxis do
  344.       if Grid.Visible or Self.FCircleLabels then
  345.       begin
  346.         tmpIncrement:=Increment;
  347.         if tmpIncrement<=0 then tmpIncrement:=10.0;
  348.         SetGridCanvas(GetHorizAxis);
  349.         tmpValue:=360;
  350.         While tmpValue>=0 do
  351.         begin
  352.           if FCircleLabels then DrawAngleLabel(tmpValue);
  353.           if Grid.Visible then
  354.           begin
  355.             AngleToPos(piDegree*tmpValue,XRadius,YRadius,tmpX,tmpY);
  356.             ParentChart.Canvas.LineWithZ(CircleXCenter,CircleYCenter,tmpX,tmpY,EndZ);
  357.           end;
  358.           tmpValue:=tmpValue-tmpIncrement;
  359.         end;
  360.       end;
  361.     end;
  362.  
  363.   Procedure DrawAxis;
  364.   Var tmp : Integer;
  365.   begin
  366.     DrawXGrid;
  367.     DrawYGrid;
  368.     With ParentChart do
  369.     begin
  370.       With RightAxis do
  371.       if Visible then
  372.       begin
  373.         tmp:=CircleXCenter+SizeTickAxis;
  374.         CustomDrawMinMaxStartEnd( tmp,tmp+SizeLabels,CircleXCenter,False,
  375.                                   LeftAxis.Minimum,LeftAxis.Maximum,LeftAxis.Increment,
  376.                                   CircleYCenter-YRadius,CircleYCenter);
  377.       end;
  378.       if IMaxValuesCount=0 then
  379.       begin
  380.         With LeftAxis do
  381.         if Visible then
  382.         begin
  383.           InternalSetInverted(True);
  384.           tmp:=CircleXCenter-SizeTickAxis;
  385.           CustomDrawStartEnd( tmp,tmp-SizeLabels,CircleXCenter,False,
  386.                               CircleYCenter,CircleYCenter+YRadius);
  387.           InternalSetInverted(False);
  388.         end;
  389.         With TopAxis do
  390.         if Visible then
  391.         begin
  392.           InternalSetInverted(True);
  393.           tmp:=CircleYCenter-SizeTickAxis;
  394.           CustomDrawMinMaxStartEnd( tmp,tmp-SizeLabels,CircleYCenter,False,
  395.                                     LeftAxis.Minimum,LeftAxis.Maximum,LeftAxis.Increment,
  396.                                     CircleXCenter-XRadius,CircleXCenter);
  397.           InternalSetInverted(False);
  398.         end;
  399.         With BottomAxis do
  400.         if Visible then
  401.         begin
  402.           tmp:=CircleYCenter+SizeTickAxis;
  403.           CustomDrawMinMaxStartEnd( tmp,tmp+SizeLabels,CircleYCenter,False,
  404.                                     LeftAxis.Minimum,LeftAxis.Maximum,LeftAxis.Increment,
  405.                                     CircleXCenter,CircleXCenter+XRadius);
  406.         end;
  407.       end;
  408.     end;
  409.   end;
  410.  
  411.   Procedure DrawCircle;
  412.   begin
  413.     With ParentChart.Canvas do
  414.     Begin
  415.       if CircleBackColor=clTeeColor then Brush.Style:=bsClear
  416.       else
  417.       begin
  418.         Brush.Style:=bsSolid;
  419.         Brush.Color:=CalcCircleBackColor;
  420.       end;
  421.       AssignVisiblePen(FCirclePen);
  422.       DrawPolarCircle(CircleWidth div 2,CircleHeight div 2,EndZ);
  423.     end;
  424.   end;
  425.  
  426. var t   : Integer;
  427.     tmp : Integer;
  428. Begin
  429.   With ParentChart do
  430.   for t:=0 to SeriesCount-1 do
  431.   if (Series[t].Active) and (Series[t] is Self.ClassType) then
  432.      if Series[t]=Self then
  433.      begin
  434.        if FCircleLabels then
  435.        begin
  436.          FontCanvas(FCircleLabelsFont);
  437.          With ChartRect do
  438.          begin
  439.            tmp:=Canvas.FontHeight+2;
  440.            Inc(Top,tmp);
  441.            Dec(Bottom,tmp);
  442.            tmp:=Canvas.TextWidth('360');
  443.            Inc(Left,tmp);
  444.            Dec(Right,tmp);
  445.          end;
  446.        end;
  447.        break;
  448.      end;
  449.   inherited DoBeforeDrawValues;
  450.   With ParentChart do
  451.   for t:=0 to SeriesCount-1 do
  452.   if (Series[t].Active) and (Series[t] is Self.ClassType) then
  453.      if Series[t]=Self then
  454.      begin
  455.        DrawCircle;
  456.        DrawAxis;
  457.      end
  458.      else
  459.      With TCustomPolarSeries(Series[t]) do
  460.      begin
  461.        CustomXRadius:=Self.XRadius;
  462.        CustomYRadius:=Self.YRadius;
  463.      end;
  464. end;
  465.  
  466. Procedure TCustomPolarSeries.CalcXYPos( ValueIndex:Longint;
  467.                                         Const ARadius:Double;
  468.                                         Var X,Y:{$IFDEF D2C1}Longint{$ELSE}Integer{$ENDIF});
  469. var tmp       : Double;
  470.     tmpRadius : Double;
  471.     {$IFDEF D1}
  472.     tmpX      : Integer;
  473.     tmpY      : Integer;
  474.     {$ENDIF}
  475. begin
  476.   With GetVertAxis do tmp:=Maximum-Minimum;
  477.   if tmp=0 then
  478.   begin
  479.     X:=0;
  480.     Y:=0;
  481.   end
  482.   else
  483.   begin
  484.     tmpRadius:=(YValue[ValueIndex]-GetVertAxis.Minimum)*ARadius/tmp;
  485.     {$IFNDEF D1}
  486.     AngleToPos( piDegree*XValue[ValueIndex],tmpRadius,tmpRadius,X,Y );
  487.     {$ELSE}
  488.     AngleToPos( piDegree*XValue[ValueIndex],tmpRadius,tmpRadius,tmpX,tmpY );
  489.     X:=tmpX;
  490.     Y:=tmpY;
  491.     {$ENDIF}
  492.   end;
  493. end;
  494.  
  495. Function TCustomPolarSeries.CalcYPos(ValueIndex:Longint):Integer;
  496. var tmpX:{$IFDEF D2C1}Longint{$ELSE}Integer{$ENDIF};
  497. begin
  498.   CalcXYPos(ValueIndex,YRadius,tmpX,{$IFDEF D2C1}Longint(result){$ELSE}result{$ENDIF});
  499. end;
  500.  
  501. Function TCustomPolarSeries.CalcXPos(ValueIndex:Longint):Integer;
  502. var tmpY:{$IFDEF D2C1}Longint{$ELSE}Integer{$ENDIF};
  503. begin
  504.   CalcXYPos(ValueIndex,XRadius,{$IFDEF D2C1}Longint(result){$ELSE}result{$ENDIF},tmpY);
  505. end;
  506.  
  507. procedure TCustomPolarSeries.LinePrepareCanvas(ValueIndex:Longint);
  508. begin
  509.   With ParentChart.Canvas do
  510.   begin
  511.     AssignVisiblePen(Self.FPen);
  512.     if Self.FPen.Visible then
  513.        if ValueIndex=-1 then Pen.Color:=SeriesColor
  514.                         else Pen.Color:=ValueColor[ValueIndex];
  515.     BackMode:=cbmTransparent;
  516.   end;
  517. end;
  518.  
  519. Procedure TCustomPolarSeries.FillTriangle(Const A,B:TPoint; Z:Integer);
  520. var tmpStyle:TPenStyle;
  521. begin
  522.   With ParentChart.Canvas do
  523.   begin
  524.     tmpStyle:=Pen.Style;
  525.     Pen.Style:=psClear;
  526.     TriangleWithZ(A,B,Point(CircleXCenter,CircleYCenter),Z);
  527.     Pen.Style:=tmpStyle;
  528.   end;
  529. end;
  530.  
  531. procedure TCustomPolarSeries.DrawValue(ValueIndex:Longint);
  532. var X        : LongInt;
  533.     Y        : LongInt;
  534.  
  535.   Procedure TryFillTriangle;
  536.   begin
  537.     if FBrush.Style<>bsClear then
  538.     begin
  539.       ParentChart.Canvas.Brush.Assign(FBrush);
  540.       FillTriangle(Point(OldX,OldY),Point(X,Y),StartZ);
  541.     end;
  542.   end;
  543.  
  544. begin
  545.   X:=CalcXPos(ValueIndex);
  546.   Y:=CalcYPos(ValueIndex);
  547.   LinePrepareCanvas(ValueIndex);
  548.   With ParentChart.Canvas do
  549.   if ValueIndex=FirstValueIndex then MoveTo3D(X,Y,StartZ)  { <-- first point }
  550.   else
  551.   begin
  552.     if (X<>OldX) or (Y<>OldY) then
  553.     begin
  554.       TryFillTriangle;
  555.       LineTo3D(X,Y,StartZ);
  556.     end;
  557.     if (ValueIndex=LastValueIndex) and FCloseCircle then
  558.     begin
  559.       Pen.Color:=ValueColor[0];
  560.       OldX:=X;
  561.       OldY:=Y;
  562.       X:=CalcXPos(0);
  563.       Y:=CalcYPos(0);
  564.       TryFillTriangle;
  565.       LineTo3D(X,Y,StartZ);
  566.       X:=OldX;
  567.       Y:=OldY;
  568.     end;
  569.   end;
  570.   OldX:=X;
  571.   OldY:=Y;
  572. end;
  573.  
  574. Procedure TCustomPolarSeries.DrawAllValues;
  575. var t        : LongInt;
  576.     tmpColor : TColor;
  577. begin
  578.   inherited DrawAllValues;
  579.   With FPointer do
  580.   if Visible then
  581.     for t:=FirstValueIndex to LastValueIndex do
  582.     begin
  583.       tmpColor:=ValueColor[t];
  584.       PrepareCanvas(tmpColor);
  585.       Draw(CalcXPos(t),CalcYPos(t),tmpColor,Style);
  586.     end;
  587. end;
  588.  
  589. Procedure TCustomPolarSeries.SetSeriesColor(AColor:TColor);
  590. begin
  591.   inherited SetSeriesColor(AColor);
  592.   FPen.Color:=AColor;
  593. end;
  594.  
  595. Procedure TCustomPolarSeries.SetPen(Value:TChartPen);
  596. Begin
  597.   FPen.Assign(Value);
  598. end;
  599.  
  600. Procedure TCustomPolarSeries.SetPointer(Value:TSeriesPointer);
  601. Begin
  602.   FPointer.Assign(Value);
  603. end;
  604.  
  605. Procedure TCustomPolarSeries.SetCircleLabels(Value:Boolean);
  606. Begin
  607.   SetBooleanProperty(FCircleLabels,Value);
  608. end;
  609.  
  610. Procedure TCustomPolarSeries.SetCircleLabelsFont(Value:TFont);
  611. begin
  612.   FCircleLabelsFont.Assign(Value);
  613. end;
  614.  
  615. Function TCustomPolarSeries.IsFontStored:Boolean;
  616. begin
  617.   result:=not IsDefaultFont(FCircleLabelsFont);
  618. end;
  619.  
  620. Function TCustomPolarSeries.GetEditorClass:String;
  621. Begin
  622.   result:='TPolarSeriesEditor'; { <-- dont translate ! }
  623. end;
  624.  
  625. { The BottomAxis is used in Angle axis }
  626. Function TCustomPolarSeries.GetAngleIncrement:Double;
  627. Const MinAngle=10;
  628. begin
  629.   if ParentChart=nil then result:=MinAngle
  630.   else
  631.   begin
  632.     result:=GetHorizAxis.Increment;
  633.     if result=0 then result:=MinAngle;
  634.   end;
  635. end;
  636.  
  637. { The BottomAxis is used in Angle axis }
  638. Procedure TCustomPolarSeries.SetAngleIncrement(Const Value:Double);
  639. begin
  640.   if ParentChart<>nil then GetHorizAxis.Increment:=Value;
  641. end;
  642.  
  643. { The LeftAxis is used in Radius axis }
  644. Function TCustomPolarSeries.GetRadiusIncrement:Double;
  645. begin
  646.   if ParentChart=nil then result:=0
  647.                      else result:=GetVertAxis.Increment;
  648. end;
  649.  
  650. { The LeftAxis is used in Radius axis }
  651. Procedure TCustomPolarSeries.SetRadiusIncrement(Const Value:Double);
  652. begin
  653.   if ParentChart<>nil then GetVertAxis.Increment:=Value;
  654. end;
  655.  
  656. Function TCustomPolarSeries.Clicked(x,y:Integer):Longint;
  657. var t:Longint;
  658. begin
  659.   if (ParentChart<>nil) then ParentChart.Canvas.Calculate2DPosition(x,y,StartZ);
  660.   result:=inherited Clicked(x,y);
  661.   if (result=-1) and (FirstValueIndex>-1) and (LastValueIndex>-1) then
  662.     if FPointer.Visible then
  663.     for t:=FirstValueIndex to LastValueIndex do
  664.         if (Abs(CalcXPos(t)-X)<FPointer.HorizSize) and
  665.            (Abs(CalcYPos(t)-Y)<FPointer.VertSize) then
  666.         begin
  667.           result:=t;
  668.           break;
  669.         end;
  670. end;
  671.  
  672. Procedure TCustomPolarSeries.DrawLegendShape(ValueIndex:Longint; Const Rect:TRect);
  673. var tmpColor : TColor;
  674. begin
  675.   if FPen.Visible then
  676.   begin
  677.     LinePrepareCanvas(ValueIndex);
  678.     With Rect do ParentChart.Canvas.DoHorizLine(Left,Right,(Top+Bottom) div 2);
  679.   end;
  680.   if FPointer.Visible then
  681.   begin
  682.     if ValueIndex=-1 then tmpColor:=SeriesColor
  683.                      else tmpColor:=ValueColor[ValueIndex];
  684.     FPointer.DrawLegendShape(tmpColor,Rect,FPen.Visible);
  685.   end
  686.   else
  687.   if not FPen.Visible then
  688.      inherited DrawLegendShape(ValueIndex,Rect)
  689. end;
  690.  
  691. { Used to draw inside circles (grid) (or radar grid lines) }
  692. { Can be used also to custom draw circles at specific values }
  693. Procedure TCustomPolarSeries.DrawRing(Const Value:Double; Z:Integer);
  694. Var tmp  : Double;
  695. begin
  696.   with GetVertAxis do
  697.   begin
  698.     tmp:=Maximum-Minimum;
  699.     if tmp<>0 then
  700.     begin
  701.       tmp :=(Value-Minimum)/tmp;
  702.       DrawPolarCircle(Round(tmp*XRadius),Round(tmp*YRadius),Z);
  703.     end;
  704.   end;
  705. end;
  706.  
  707. Procedure TCustomPolarSeries.Assign(Source:TPersistent);
  708. begin
  709.   if Source is TCustomPolarSeries then
  710.   With TCustomPolarSeries(Source) do
  711.   begin
  712.     Self.FCircleLabels  := FCircleLabels;
  713.     Self.FCircleLabelsFont.Assign(FCircleLabelsFont);
  714.     Self.FCircleLabelsRot:=FCircleLabelsRot;
  715.     Self.FBrush.Assign(FBrush);
  716.     Self.FCirclePen.Assign(FCirclePen);
  717.     Self.FCloseCircle  := FCloseCircle;
  718.     Self.FPen.Assign(FPen);
  719.     Self.FPointer.Assign(FPointer);
  720.   end;
  721.   inherited Assign(Source);
  722. end;
  723.  
  724. Function TCustomPolarSeries.GetRadiusValues:TChartValueList;
  725. begin
  726.   result:=YValues;
  727. end;
  728.  
  729. Procedure TCustomPolarSeries.SetRadiusValues(Value:TChartValueList);
  730. begin
  731.   SetYValues(Value); { overrides the default YValues }
  732. end;
  733.  
  734. Function TCustomPolarSeries.IsRadiusStored:Boolean;
  735. begin
  736.   With YValues do
  737.   result:=(Name<>TeeMsg_RadiusValues) or DateTime or (Multiplier<>1) or
  738.           (Order<>loNone) or (ValueSource<>'');
  739. end;
  740.  
  741. Function TCustomPolarSeries.GetAngleValues:TChartValueList;
  742. begin
  743.   result:=XValues;
  744. end;
  745.  
  746. Procedure TCustomPolarSeries.SetAngleValues(Value:TChartValueList);
  747. begin
  748.   SetXValues(Value); { overrides the default XValues }
  749. end;
  750.  
  751. Procedure TCustomPolarSeries.PrepareForGallery(IsEnabled:Boolean);
  752. Begin
  753.   inherited PrepareForGallery(IsEnabled);
  754.   Circled:=True;
  755.   With ParentChart do
  756.   begin
  757.     Chart3DPercent:=5;
  758.     RightAxis.Labels:=False;
  759.     TopAxis.Labels:=False;
  760.     With View3DOptions do
  761.     begin
  762.       Orthogonal:=False;
  763.       Elevation:=360;
  764.       Zoom:=90;
  765.     end;
  766.   end;
  767. end;
  768.  
  769. { TPolarSeries }
  770. Function TPolarSeries.AddPolar( Const Angle,Value:Double;
  771.                                 Const ALabel:String;
  772.                                 AColor:TColor):Longint;
  773. begin
  774.   result:=AddXY(Angle,Value,ALabel,AColor);
  775. end;
  776.  
  777. Procedure TPolarSeries.FillSampleValues(NumValues:Longint);
  778. var t   : Longint;
  779.     tmp : Double;
  780. Begin
  781.   Clear;
  782.   tmp:=360.0/NumValues;
  783.   for t:=1 to NumValues do
  784.       AddPolar( t*tmp,                      { <-- Angle }
  785.                 1+Random(ChartSamplesMax)  { <-- Value (Radius) }
  786.                 {$IFNDEF D4},'', clTeeColor{$ENDIF});
  787.   RefreshSeries;
  788. end;
  789.  
  790. { TRadarSeries }
  791. Procedure TRadarSeries.DoBeforeDrawChart;
  792. var t   : Integer;
  793.     tmp : Double;
  794. begin
  795.   {$IFDEF TEETRIAL}
  796.   TeeTrial(ComponentState);
  797.   {$ENDIF}
  798.   inherited DoBeforeDrawChart;
  799.   RotationAngle:=90;
  800.   IMaxValuesCount:=ParentChart.GetMaxValuesCount;
  801.   if IMaxValuesCount>0 then
  802.   begin
  803.     tmp:=360.0/IMaxValuesCount;
  804.     AngleIncrement:=tmp;
  805.     for t:=0 to Count-1 do SetXValue(t,t*tmp);
  806.   end;
  807. end;
  808.  
  809. Procedure TRadarSeries.FillSampleValues(NumValues:Longint);
  810. Const RadarSampleStr:Array[0..4] of String=
  811.          ( TeeMsg_PieSample1,TeeMsg_PieSample2,TeeMsg_PieSample3,
  812.            TeeMsg_PieSample4,TeeMsg_PieSample5);
  813. var t:Integer;
  814. begin
  815.   Randomize;
  816.   Clear;
  817.   for t:=0 to 4 do Add(Random(1000),RadarSampleStr[t]{$IFNDEF D4},clTeeColor{$ENDIF});
  818.   RefreshSeries;
  819. end;
  820.  
  821. Procedure TRadarSeries.PrepareForGallery(IsEnabled:Boolean);
  822. Begin
  823.   inherited PrepareForGallery(IsEnabled);
  824.   FillSampleValues(NumSampleValues);
  825. end;
  826.  
  827. Function TRadarSeries.GetCircleLabel(Const AngleOrIndex:Double):String;
  828. begin
  829.   result:=GetXLabel(XValues.Locate(AngleOrIndex));
  830. end;
  831.  
  832. Procedure TeePolarRadarExitProc; far;
  833. begin
  834.   UnRegisterTeeSeries([TPolarSeries,TRadarSeries]);
  835. end;
  836.  
  837. initialization
  838.   RegisterTeeSeries(TPolarSeries,TeeMsg_GalleryPolar,TeeMsg_GalleryExtended,2);
  839.   RegisterTeeSeries(TRadarSeries,TeeMsg_GalleryRadar,TeeMsg_GalleryExtended,2);
  840. {$IFDEF D1}
  841.   AddExitProc(TeePolarRadarExitProc);
  842. {$ELSE}
  843. finalization
  844.   TeePolarRadarExitProc;
  845. {$ENDIF}
  846. end.
  847.