Real Time Graphing
The Tsp_Axis has properties and method to control axis limits.
property Min : double
Min is the lowest value an axis
property Max : double
Max is the highest value an axis
Used to set Min and Max at once. The minimal value of the m1 and m2 will be assigned to the Min and maximal to the Max.
Used to change Min and Max on value of aDelta with 'frozen' ticks position.The aim is to permit smooth scroll of plot, without ticks jumps. Procedure is especially useful for the program which emulates transient recorder.
property AutoMin : boolean default False
The AutoMin property controls if axis will adjust the Min value automatically to based on the minimum value of its associated data series.
property AutoMax : boolean
The AutoMax property controls if axis will adjust the Max value automatically to based on the maximum value of its associated data series.
There are some features. Suppose we try to set new value to the Min, while this value greater then current Max, this value will be assigned to the Max instead of Min. If then you set new value to Max you will have incorrect Min value (Min value did not changed). To avoid this problem, use SetMinMax method, if you want to assign arbitrary values to the Min and Max at once. Notice, changing properties Min or/and Max will reset the AutoMin or/and AutoMax to False.
The axis limits also changed after zooming or panning of the plot by the mouse (z&p). This processes did not change AutoMin and AutoMax. Shift+Click on the plot will restore limits after z&p if properties Min and Max was not changed by another way after z&p.
There are no many kinds of data series. But you can write it yourself, and they will
match your needs. Inherit it from Tsp_DataSeries component and implement 1 procedure and 4
╥ procedure Draw; virtual;
╥ function GetXMin(var V:double):boolean; virtual;
╥ function GetXMax(var V:double):boolean; virtual;
╥ function GetYMin(var V:double):boolean; virtual;
╥ function GetYMax(var V:double):boolean; virtual;
Draw procedure called by parent plot to draw series. In this procedure you place code which draws your data on plot DCanvas. Get?Min and Get?Max functions are used by parent plot during auto scaling process. In this procedures you can find minimal or maximal value of your data and assign it to variable V. Function must return True if they set valid value to the V, otherwise they must return False. For example if data series has no data you cannot set valid value to the V.
There is also procedure which is reserved to draw Legends of the plot series.
procedure DrawLegendMarker(const LCanvas:TCanvas, MR:TRect); virtual;
It should paints series marker (for example line and point marker image) on LCanvas using rectangle MR. Of course you should also implement data storage which are drawn by series. See sgr_data.pas and sgr_def.hlp for more details.
If you agree to store data in variant array there is more simple way. Derive Data Series from Tsp_XYDataSeries. See how Tsp_XYLine and Tsp_SpectrLines were derived from Tsp_XYDataSeries in sgr_data.pas. Both class inherited data storage interface from Tsp_XYDataSeries but implemented different data presentation on plot. Tsp_XYLine.Draw procedure paints lines between data points and/or points markers.
On other side if you need XYLine data presentation, but want to have another data storage then derive your series from Tsp_DrawPoints. The simplest way is to use Tsp_ndsXYLine
Some times I need mark visually some points on plot. First I use OnDrawField and OnDrawEnd handlers, but now I implements plot marker. There are Tsp_LineMarker and Tsp_ImageMarker in the current version. Tsp_LineMarker draws "infinite" vertical or horizontal line. For example to show X=0 and Y=0 lines as quasi axis you can create 2 LineMarker of vertical and horizontal type with Position=0.0. In this case you will have two line on plot field. One from the top to bottom at X=0 and second from the left to right at Y=0. Tsp_ImageMarker can be used to mark point and so on. Notice one exotic way to use it as background map under trajectory of motion (of course trajectory is given by data series). It can be done with Tsp_ImageMarker, place it and assign Picture property metafile with map image, set property WhenDraw =dmBeforeSeries and you will have background image which is scaled and moved same as data.
Plot has 2 areas - Field and Around Area. Field is area surrounded by 4 axis. The data series are painted on the Field. The axis caption, ticks and ticks label are painted on the Around Area.
Sequence of draw operations to create plot image
╥ Fill Around Area by Color
╥ Draw axis
╥ IntersectClipRect(DCanvas, FieldRect)
╥ Fill Field by FieldColor
╥ Process OnFieldDraw event
╥ Draw Grids
╥ Draw plot markers with WhenDraw=dmBeforeSeries
╥ Draw series
╥ Draw plot markers with WhenDraw=dmAfterSeries
╥ Process OnDrawEnd event
╥ Draw border
during operation selected by color custom draw procedures are called.
Custom draw rules
This rules apply for Data Series Draw procedure and OnFieldDraw, OnDrawEnd and OnDrawCustomPoint event handlers. They must
╥ use DCanvas to draw
╥ use DWidth as plot width, DHeight as plot height
╥ do not change MapMode or Clipping Region of the DCanvas
╥ do not change plot Font property
Custom draw tips
Use FieldRect if you need to know Field position on the plot image.
Use P2V and V2P axis methods to convert position to value and back.
There is no special print method of component. You can draw plot on the printer canvas using method DrawPlot(CC : TCanvas; W, H : integer) and of course you would create user interface to control how to print plot. But there is special dialog form (sgr_sprint.pas) in sgr_demo program. You can look it as example of plot printing through metafile and simple preview. Note that it is important to set true-type font to Font property for correct print scaling.
The Tsp_XYPlot and Tsp_XYLine have special features to help data graphing in real time
or to suppress flickering. This features are:
╥ property Tsp_XYPlot.BufferedDisplay
╥ procedure Tsp_XYDataSeries.AddXYArrays(pX,pY:pointer; n:integer);
╥ property Tsp_XYDataSeries.LockInvalidate
╥ procedure Tsp_XYLine.QuickAddXY(aX,aY:double);
If data rate is relatively slow (<10 1/sec) it simplest way set BufferedDisplay=True to draw plot throughout internal buffer and have flicker free paint. To add data point by point and immediately reflect changes on screen use procedure AddXY(aX,aY:double). This procedure add values at the end of series data and update Plot (not invalidate but update!).
If it is not enough, then use procedure AddXYArrays(pX,pY:pointer; n:integer) to add data by portion of several (n) points. In this case the plot will invalidate only one time for several (n) points. Notice, there is also property LockInvalidate, set it to True and use AddXY several times and then set LockInvalidate to False.
At last, to have maximum visualisation data rate, use procedure QuickAddXY(aX,aY:double). It adds values at end of data storage like AddXY, but does not spend time to update Plot, instead of that it directly draw next line segment or/and last point, but because of that the AutoMin and AutoMax are ignored.
Sergei. P. Pod'yachev. Novosibirsk, Russia.