Вверх ↑
Этот топик читают: Гость
Ответов: 139
Рейтинг: 4
#1: 2011-04-27 11:07:57 ЛС | профиль | цитата
Почему-то рисуется кривой график

code_23576.txt
карма: 0

0
файлы: 1code_23576.txt [1.1KB] [556]
vip
#1.1контекстная реклама от партнеров
Администрация
Ответов: 15294
Рейтинг: 1518
#2: 2011-04-27 12:39:19 ЛС | профиль | цитата
в чем кривость?
карма: 26
0
Ответов: 139
Рейтинг: 4
#3: 2011-04-27 16:08:41 ЛС | профиль | цитата
График выглядкт, примерно, как буква Т, сначало идет наклонная линия и затем сверху прямая линия, так что одной точке по оси Х соответствуют две точки по Y. Или это у меня что-то с HiAsm?
------------ Дoбавленo в 16.08:
Забыл добавить- подправил для себя код Plotter, что бы график рисовался с небольшим отступом на 1 от краев области графика. Место исправления пометил так //Исправление!
#pas
unit hiPlotter;

interface

{$I share.inc}

uses Windows,Share,Win,Kol;

type
TRPoint = record
x,y:real;
end;

THIPlotter = class;
TSeries = class
Parent:THIPlotter;
Values:array of TRPoint;
Count:integer;
Size:integer;
Color:TColor;
MaxValues:integer;

// onChangeSeries:TEvents;

constructor Create;
destructor Destroy; override;
procedure Add(valY, valX:real); virtual;
procedure Clear;
procedure Draw(Canvas:PCanvas; startX,startY,fX,fY:real; VSpace, HSpace:integer); virtual; abstract;
function graphMinY:real; virtual;
function graphMaxY:real; virtual;
function graphMinX:real; virtual;
function graphMaxX:real; virtual;
end;
THIPlotter = class(THIWin)
private
Bmp:PBitmap;
FSeries:PList;
FRgn:HRGN;

FGrid:integer;

FStartPos,FBPos:TPoint;
FBeginMove:byte;

procedure _OnClick( Sender: PObj );
procedure _OnSize( Sender: PObj );
procedure _OnPaint( Sender: PControl; DC: HDC );
procedure DrawBmp;
function graphMinY:real;
function graphMaxY:real;
function graphMinX:real;
function graphMaxX:real;
procedure SetGrid(Value:integer);

function GetSeries(index:integer):TSeries;
function GetSeriesCount:integer;
protected
procedure _onMouseDown(Sender: PControl; var Mouse: TMouseEventData); override;
procedure _onMouseMove(Sender: PControl; var Mouse: TMouseEventData); override;
procedure _onMouseUp(Sender: PControl; var Mouse: TMouseEventData); override;
procedure _onMouseWheel(Sender: PControl; var Mouse: TMouseEventData); override;
public
_prop_GridColor:TColor;
_prop_BorderColor:TColor;
_prop_AxisColor:TColor;
_prop_Step:real;
_prop_MinH:real;
_prop_MaxH:real;
_prop_MinW:real;
_prop_MaxW:real;
_prop_LeftMargin:integer;
_prop_RightMargin:integer;
_prop_TopMargin:integer;
_prop_BottomMargin:integer;
_prop_FileName:string;
_prop_MouseControl:boolean;

_data_FileName:THI_Event;

onMouseDown:TEvents;
onMouseUp:TEvents;
onMouseMove:TEvents;

constructor Create(Parent:PControl);
procedure Init; override;
destructor Destroy; override;
procedure _work_doClear(var _Data:TData; Index:word);
procedure _work_doSaveToFile(var _Data:TData; Index:word);
procedure _var_MinX(var _Data:TData; Index:word);
procedure _var_MaxX(var _Data:TData; Index:word);
procedure _var_MinY(var _Data:TData; Index:word);
procedure _var_MaxY(var _Data:TData; Index:word);

function getInterfacePlotter:THIPlotter;

procedure AddSeries(s:TSeries);
procedure RemoveSeries(s:TSeries);
procedure ReDraw;

function AbsToGraphY(v:real):real;
function AbsToGraphX(v:real):real;

property _prop_Grid:integer write SetGrid;
property Series[index:integer]:TSeries read GetSeries;
property SeriesCount:integer read GetSeriesCount;
end;

implementation

constructor TSeries.Create;
begin
inherited;
// onChangeSeries := TEvents.create;
end;

destructor TSeries.Destroy;
begin
// onChangeSeries.Destroy;
inherited;
end;

procedure TSeries.Add;
begin
if(MaxValues > 0)and(Count = MaxValues)then
begin
Move(Values[1],Values[0],sizeof(TRPoint)*(Count-1));
end
else
begin
inc(Count);
SetLength(Values,Count);
end;

with Values[Count-1] do
begin
Y := valY;
X := valX;
end;
// onChangeSeries.Event(self);
end;

procedure TSeries.Clear;
begin
Count := 0;
SetLength(Values,Count);
// onChangeSeries.Event(self);
end;

function TSeries.graphMinY:real;
var i:integer;
begin
if Count = 0 then
Result := 0
else
begin
Result := Values[0].Y;
for i := 1 to Count-1 do
if Values[i].Y < Result then
Result := Values[i].y;
end;
end;

function TSeries.graphMaxY:real;
var i:integer;
begin
if Count = 0 then
Result := 0
else
begin
Result := Values[0].Y;
for i := 1 to Count-1 do
if Values[i].Y > Result then
Result := Values[i].y;
end;
end;

function TSeries.graphMinX:real;
var i:integer;
begin
if Count = 0 then
Result := 0
else
begin
Result := Values[0].X;
for i := 1 to Count-1 do
if Values[i].X < Result then
Result := Values[i].x;
end;
end;

function TSeries.graphMaxX:real;
var i:integer;
begin
if Count = 0 then
Result := 0
else
begin
Result := Values[0].X;
for i := 1 to Count-1 do
if Values[i].X > Result then


Result := Values[i].x;
end;
end;

//---------------------------- PLOTTER -----------------------------------------

constructor THIPlotter.Create;
begin
inherited Create(Parent);
Control := NewPaintbox(Parent);
Bmp := NewBitmap(0,0);
FSeries := NewList;
_prop_MouseCapture := true;
onMouseDown := TEvents.Create;
onMouseUp := TEvents.Create;
onMouseMove := TEvents.Create;
end;

destructor THIPlotter.Destroy;
var i:integer;
begin
onMouseDown.Destroy;
onMouseUp.Destroy;
onMouseMove.Destroy;
DeleteObject(FRgn);
Bmp.free;
for i := 0 to SeriesCount - 1 do
Series[i].Parent := nil;
FSeries.Free;
inherited;
end;

procedure THIPlotter.Init;
begin
inherited;
with Control{$ifndef F_P}^{$endif} do
begin
OnClick := _OnClick;
OnPaint := _OnPaint;
OnResize := _OnSize;
end;

_OnSize(Control);
end;

function THIPlotter.getInterfacePlotter:THIPlotter;
begin
Result := self;
end;

procedure THIPlotter._OnSize;
begin
Bmp.Width := max(control.Width,1);
Bmp.Height := max(Control.Height,1);
DeleteObject(FRgn);
FRgn := CreateRectRgn(0,0,Bmp.Width,Bmp.Height);
DrawBmp;
// Control.Invalidate;
end;

function THIPlotter.GetSeries(index:integer):TSeries;
begin
Result := TSeries(FSeries.Items[index]);
end;

function THIPlotter.GetSeriesCount:integer;
begin
Result := FSeries.Count;
end;

procedure THIPlotter._onMouseDown;
begin
inherited;
FStartPos.x := Mouse.x;
FStartPos.y := Mouse.y;
FBPos := FStartPos;
SetFocus(Control.handle);

onMouseDown.event(@Mouse);

if not _prop_MouseControl then exit;

if Mouse.Button = mbMiddle then
FBeginMove := 1
else if(Mouse.Button = mbLeft)and(GetKeyState(VK_CONTROL) < 0) then
FBeginMove := 2
else FBeginMove := 0;
if(_prop_MaxH = 0)and(_prop_MinH = 0)then
begin
_prop_MaxH := graphMaxY;
_prop_MinH := graphMinY;
end;
if(_prop_MaxW = 0)and(_prop_MinW = 0)then
begin
_prop_MaxW := graphMaxX;
_prop_MinW := graphMinX;
end;
end;

procedure THIPlotter._onMouseUp;
var dy,h:real;
begin
inherited;
case FBeginMove of
2:
begin
Control.Canvas.Pen.PenMode := pmXor;
Control.Canvas.Rectangle(FBPos.x, FBPos.y, FStartPos.x, FStartPos.y);

dy := (_prop_MaxH - _prop_MinH)/(Control.Height - _prop_BottomMargin - _prop_TopMargin);
h := _prop_MaxH - _prop_MinH;
if FBPos.y < FStartPos.y then
begin
_prop_MaxH := _prop_MinH + h - (FBPos.y - _prop_TopMargin)*dy;
_prop_MinH := _prop_MinH + h - (FStartPos.y - _prop_TopMargin)*dy;
end
else
begin
_prop_MaxH := 0;
_prop_MinH := 0;
_prop_MaxH := graphMaxY;
_prop_MinH := graphMinY;
end;

dy := (_prop_MaxW - _prop_MinW)/(Control.Width - _prop_LeftMargin - _prop_RightMargin);
if FBPos.x < FStartPos.x then
begin
_prop_MaxW := _prop_MinW + (FStartPos.x - _prop_LeftMargin)*dy;
_prop_MinW := _prop_MinW + (FBPos.x - _prop_LeftMargin)*dy;
end
else
begin
_prop_MaxW := 0;
_prop_MinW := 0;
_prop_MaxW := graphMaxX;
_prop_MinW := graphMinX;
end;
ReDraw;
end;
end;
FBeginMove := 0;
onMouseUp.event(@Mouse);
end;

procedure THIPlotter._onMouseMove;
var dy:real;
begin
inherited;
case FBeginMove of
1:
begin
dy := (_prop_MaxH - _prop_MinH)/(Control.Height - _prop_BottomMargin - _prop_TopMargin);
_prop_MaxH := _prop_MaxH + (Mouse.y - FStartPos.y)*dy;
_prop_MinH := _prop_MinH + (Mouse.y - FStartPos.y)*dy;

dy := (_prop_MaxW - _prop_MinW)/(Control.Width - _prop_LeftMargin - _prop_RightMargin);
_prop_MaxW := _prop_MaxW - (Mouse.x - FStartPos.x)*dy;
_prop_MinW := _prop_MinW - (Mouse.x - FStartPos.x)*dy;
ReDraw;
end;
2:
begin
Control.Canvas.Pen.PenMode := pmXor;
Control.Canvas.Rectangle(FBPos.x, FBPos.y, FStartPos.x, FStartPos.y);
Control.Canvas.Rectangle(FBPos.x, FBPos.y, Mouse.x, Mouse.y);
end;
end;
FStartPos.x := Mouse.x;
FStartPos.y := Mouse.y;

onMouseMove.event(@Mouse);
end;

procedure THIPlotter._onMouseWheel;
var h:real;
i:real;
begin
inherited;
if not _prop_MouseControl then exit;
i := (integer(Mouse.Shift) / $1000)*0.0001;

h := _prop_MaxH - (_prop_MaxH - _prop_MinH) * (FStartPos.y - _prop_TopMargin)/(Control.Height - _prop_TopMargin - _prop_BottomMargin);
_prop_MaxH := _prop_MaxH - i*(_prop_MaxH - h);
_prop_MinH := _prop_MinH - i*(_prop_MinH - h);

h := _prop_MinW + (_prop_MaxW - _prop_MinW) * (FStartPos.x - _prop_LeftMargin)/(Control.Width - _prop_LeftMargin - _prop_RightMargin);
_prop_MaxW := _prop_MaxW - i*(_prop_MaxW - h);
_prop_MinW := _prop_MinW - i*(_prop_MinW - h);

ReDraw;
end;

procedure THIPlotter.AddSeries;
begin
s.Parent := self;
FSeries.Add(s);
end;

procedure THIPlotter.RemoveSeries(s:TSeries);
begin
FSeries.Delete(FSeries.IndexOf(s));
s.Destroy;
end;

procedure THIPlotter.ReDraw;
begin
// DrawBmp;
Control.Invalidate;
end;

procedure THIPlotter._work_doSaveToFile;
begin
DrawBmp;
Bmp.SaveToFile(ReadString(_Data, _data_FileName, _prop_FileName));
end;

procedure THIPlotter._work_doClear;
var i:integer;
begin
for i := 0 to SeriesCount - 1 do
Series[i].Clear;
Control.Invalidate;
end;

procedure THIPlotter._OnClick;
begin

end;

procedure THIPlotter._OnPaint;
begin
DrawBmp;
Bmp.Draw(DC,0,0);
end;

procedure THIPlotter.SetGrid;
begin
FGrid := max(1,Value);
end;

function THIPlotter.graphMinY:real;
var i:integer;
r:real;
begin
if SeriesCount = 0 then
Result := 0
else
if _prop_MinH <> 0 Then Result := _prop_MinH Else
begin
Result := $FFFFFF;
for i := 0 to SeriesCount-1 do
if Series[i].Count > 0 then
begin
r := Series[i].graphMinY;
if r < Result then

//Исправление!
Result := r - 1;
end;
if Result = $FFFFFF then
Result := 0;
end;
end;

function THIPlotter.graphMaxY:real;
var i:integer;
r:real;
begin
if SeriesCount = 0 then
Result := 0
else
if _prop_MaxH <> 0 Then Result := _prop_MaxH Else
begin
Result := -$FFFFFF;
for i := 0 to SeriesCount-1 do
if Series[i].Count > 0 then
begin
r := Series[i].graphMaxY;
if r > Result then

//Исправление!
Result := r + 1;
end;
if Result = -$FFFFFF then
Result := 0;
end;
end;

function THIPlotter.graphMinX:real;
var i:integer;
r:real;
begin
if SeriesCount = 0 then
Result := 0
else
if _prop_MinW <> 0 Then Result := _prop_MinW Else
begin
Result := $FFFFFF;
for i := 0 to SeriesCount-1 do
if Series[i].Count > 0 then
begin
r := Series[i].graphMinX;
if r < Result then

Result := r;
end;
if Result = $FFFFFF then
Result := 0;
end;
end;

function THIPlotter.graphMaxX:real;
var i:integer;
r:real;
begin
if SeriesCount = 0 then
Result := 0
else
if _prop_MaxW <> 0 Then Result := _prop_MaxW Else
begin
Result := -$FFFFFF;
for i := 0 to SeriesCount-1 do
if Series[i].Count > 0 then
begin
r := Series[i].graphMaxX;
if r > Result then
Result := r;
end;
if Result = -$FFFFFF then
Result := 0;
end;
end;

function Max(r1,r2:real):real;
begin
if r1 > r2 then
Result := r1
else Result := r2;
end;

procedure THIPlotter.DrawBmp;
var t:integer;
x,dx:real;
_Grid,ix:real;
FY,FX:real;
fstartY,fstartX:real;
VSpace,HSpace:integer;
r:TRect;
s:string;
rg:HRGN;
begin
{$ifdef F_P}
with Bmp,Canvas do
{$else}
with Bmp^,Canvas^ do
{$endif}
begin
Font.FontHeight := 8;
Brush.Color := Control.Color;
Brush.BrushStyle := bsSolid;
r.left := 0;
r.top := 0;
r.right := Width;
r.bottom := Height;
FillRect(r);
VSpace := Width - _prop_LeftMargin - _prop_RightMargin;
HSpace := Height - _prop_TopMargin - _prop_BottomMargin;

Pen.Color := _prop_GridColor;
Font.Color := _prop_AxisColor;
Pen.PenStyle := psDot;

fstartY := graphMinY;
FY := graphMaxY - fstartY;
if FY = 0 then FY := 1;
fstartX := graphMinX;
FX := graphMaxX - fstartX;
if FX = 0 then FX := 1;

//---------------------------- X Axis ------------------------------------
dx := FX/FGrid;
_Grid := max(1,VSpace/FGrid);
x := fstartX;
if _Grid > 10 then
TextOut(_prop_LeftMargin-2,Height - _prop_BottomMargin + 1,Double2Str(Round(x*100)/100));
ix := _prop_LeftMargin + _Grid;;
while ix < Width - _prop_RightMargin + 1 do
begin
MoveTo(Round(ix),_prop_TopMargin);
LineTo(Round(ix),Height - _prop_BottomMargin);
x := x + dx;
if _Grid > 10 then
begin
s := Double2Str(Round(x*100)/100);
r.left := Round(ix);
r.top := Height - _prop_BottomMargin + 1;
r.bottom := r.top + 20;
r.right := 0;
DrawText(s,r,DT_CALCRECT);
t := (r.right - r.left) shr 1;
dec(r.left, t);
dec(r.right, t);
DrawText(s,r,0);
end;
ix := ix + _Grid;
end;

//---------------------------- Y Axis ------------------------------------
dx := FY/FGrid;
_Grid := max(1,HSpace/FGrid);
x := fstartY;
ix := Height - _prop_BottomMargin;
while ix > _prop_TopMargin-1 do
begin
if x <> fstartY then
begin
MoveTo(_prop_LeftMargin,Round(ix));
LineTo(Width - _prop_RightMargin,Round(ix));
end;
if _Grid > 12 then
begin
s := Double2Str(Round(x*100)/100);
r.left := 2;
r.top := Round(ix);
r.bottom := 0;
r.right := 0;
DrawText(s,r,DT_CALCRECT);
t := r.right - r.left;
r.right := _prop_LeftMargin - 4;
r.left := r.right - t;
t := (r.bottom - r.top) shr 1;
dec(r.top, t);
dec(r.bottom, t);
DrawText(s,r,0);
end;
x := x + dx;
ix := ix - _Grid;
end;

//---------------------------- Series ------------------------------------
rg := CreateRectRgn(_prop_LeftMargin,_prop_TopMargin,_prop_LeftMargin + VSpace,_prop_TopMargin + HSpace);
SelectObject(Handle, rg);
for t := 0 to SeriesCount-1 do
Series[t].Draw(Canvas, fstartX, fstartY, FX, FY, VSpace, HSpace);
SelectObject(Handle, FRgn);
DeleteObject(rg);

Pen.Color := _prop_BorderColor;
Pen.PenStyle := psSolid;
Pen.PenWidth := 1;
Brush.BrushStyle := bsClear;
Rectangle(_prop_LeftMargin,_prop_TopMargin,Width - _prop_RightMargin,Height - _prop_BottomMargin);
end;
end;

function THIPlotter.AbsToGraphY(v:real):real;
var FY,fstartY:real;
HSpace:integer;
begin
fstartY := graphMinY;
FY := graphMaxY - fstartY;
HSpace := Bmp.Height - _prop_TopMargin - _prop_BottomMargin;
Result := (HSpace + _prop_TopMargin - v)*FY/HSpace + fstartY;
end;

function THIPlotter.AbsToGraphX(v:real):real;
var FX,fstartX:real;
VSpace:integer;
begin
fstartX := graphMinX;
FX := graphMaxX - fstartX;
VSpace := Bmp.Width - _prop_LeftMargin - _prop_RightMargin;
Result := FX - ((VSpace + _prop_LeftMargin - v)*FX/VSpace - fstartX);
end;

procedure THIPlotter._var_MinY;
begin
dtReal(_Data,graphMinY);
end;

procedure THIPlotter._var_MaxY;
begin
dtReal(_Data,graphMaxY);
end;

procedure THIPlotter._var_MinX;
begin
dtReal(_Data,graphMinX);
end;

procedure THIPlotter._var_MaxX;
begin
dtReal(_Data,graphMaxX);
end;

end.
карма: 0

0
Ответов: 8887
Рейтинг: 823
#4: 2011-04-27 17:09:49 ЛС | профиль | цитата
pav, какие данные, такой и график, вот он, плавненький и приятный code_23581.txt
карма: 19

0
файлы: 1code_23581.txt [949B] [492]
Ответов: 139
Рейтинг: 4
#5: 2011-04-27 18:24:32 ЛС | профиль | цитата
Леонид, Вам нужен красивый эллипс , а мне то что выдает программа - по оси X время, а по оси Y температура, причем промежутки времени могут изменяться, например, из-за остановки программы.
P.S.
Данные предварительно сохраняются в файл, а затем можно посмотреть как менялась температура за сутки.
карма: 0

0
Ответов: 8887
Рейтинг: 823
#6: 2011-04-27 20:01:06 ЛС | профиль | цитата
pav,
Леонид писал(а):
какие данные, такой и график
У Вас 9.1-9.9 нолик пропущен, а далее 9.16... поэтому график и зигзаг делал. code_23582.txt
карма: 19

0
файлы: 1code_23582.txt [359B] [413]
Администрация
Ответов: 15294
Рейтинг: 1518
#7: 2011-04-27 20:03:36 ЛС | профиль | цитата
pav, вам совершенно верно подсказывают:
Леонид писал(а):
какие данные, такой и график


вы на свои данные внимательно смотрели? Это для вас 8.1 - 8 часов 1 минута, а для проттера это 8 целых и 1 десятая. Думаю дальше сами разберетесь.
карма: 26
0
Ответов: 139
Рейтинг: 4
#8: 2011-04-27 20:48:39 ЛС | профиль | цитата
Спасибо за помощь, понял
карма: 0

0
8
Сообщение
...
Прикрепленные файлы
(файлы не залиты)