1790 lines
52 KiB
Plaintext
1790 lines
52 KiB
Plaintext
unit utvclgraphics;
|
|
interface
|
|
uses utslvclauxiliary;
|
|
//tsl绘图库
|
|
//20240126
|
|
{
|
|
//////////////////绘图范例//////////////////////////
|
|
uses tslvcl,utvclgraphics;
|
|
app := initializeapplication();
|
|
app.createform(class(tfm),fm);
|
|
fm.show();
|
|
app.run();
|
|
type tfm = class(tvcform)
|
|
function create(aowner);
|
|
begin
|
|
inherited;
|
|
fg := new tcustomfigure(self);
|
|
fg.Caption := "hello1";
|
|
fg.parent := self;
|
|
fg.Align := alClient;
|
|
//////////设置坐标轴属性////////////////////////
|
|
axs := new tg_axes();
|
|
axs.figure := fg;
|
|
axs.title.text := "你好 plot ";
|
|
axs.title.fontinfo.size := 15;
|
|
axs.title.fontinfo.color := 0xff0000;
|
|
axs.x_label.text := "x fanli ";
|
|
|
|
axs.axises(1).tics_color := 0x0000ff;
|
|
axs.axises(1).fontinfo.size := 8;
|
|
|
|
axs.axises(1).lineinfo.color := 0x00ff00;
|
|
axs.grid(0).Width := 2;
|
|
axs.grid(0).color := 0x0ff0f0;
|
|
|
|
//设置线型属性
|
|
line := new tg_Polyline();
|
|
line.lineinfo.style := 4;
|
|
line.lineinfo.color := 0xff0000;
|
|
line.markinfo.bkcolor := 0x00ff00;
|
|
line.markinfo.color := 0x0000ff;
|
|
line.mark_mode := "on";
|
|
line.markinfo.size := 30;
|
|
line.markinfo.style := "pentagram";
|
|
line.polyline_style := "staircase";
|
|
d := array();
|
|
idx := 0;
|
|
for i:= -pi() to pi() step 0.2 do
|
|
begin
|
|
d[idx] := array(i,sin(i));
|
|
idx++;
|
|
end
|
|
line.data := d;
|
|
line.parent := axs;
|
|
end
|
|
fg;
|
|
end
|
|
|
|
}
|
|
type tcustomfigure = class(tcustomcontrol,tg_const) //绘图窗口
|
|
function create(AOwner);
|
|
begin
|
|
inherited;
|
|
faxeses := new tnumindexarray();
|
|
end
|
|
function paint();override; //绘制
|
|
begin
|
|
for i,v in faxeses.data do
|
|
begin
|
|
v.axes_paint_rect_changd();
|
|
v.paint(canvas);
|
|
end
|
|
end
|
|
function add_axes(axs);//添加
|
|
begin
|
|
if get_axes_idx(axs)>=0 then return ;
|
|
if fwilladdaxs and fwilladdaxs=axs then
|
|
begin
|
|
faxeses.unshift(axs);
|
|
fwilladdaxs := nil;
|
|
axs.figure := self(true);
|
|
return ;
|
|
end
|
|
if not(axs is class(tg_axes)) then return ;
|
|
fwilladdaxs := axs;
|
|
axs.figure := self(true);
|
|
end
|
|
function del_axes(axs); //移除
|
|
begin
|
|
idx := get_axes_idx(axs);
|
|
if not(idx>=0) then return ;
|
|
if fwilldelaxs and fwilldelaxs = axs then
|
|
begin
|
|
fwilldelaxs := nil;
|
|
faxeses.splice(idx,1);
|
|
axs.figure := nil;
|
|
return ;
|
|
end
|
|
fwilldelaxs := axs;
|
|
axs.figure := nil;
|
|
end
|
|
function Recycling();override;
|
|
begin
|
|
for i,v in faxeses.data do
|
|
begin
|
|
v.figure := nil;
|
|
end
|
|
inherited;
|
|
end
|
|
private
|
|
function get_axes_idx(axs);
|
|
begin
|
|
for i ,v in faxeses.data do
|
|
begin
|
|
if v=axs then
|
|
begin
|
|
return i;
|
|
end
|
|
end
|
|
return -1;
|
|
end
|
|
private
|
|
fwilladdaxs;
|
|
fwilldelaxs;
|
|
faxeses;
|
|
end
|
|
type tg_axis_main = class(tg_axis) //主轴
|
|
public
|
|
function create(pms);
|
|
begin
|
|
inherited;
|
|
end
|
|
protected
|
|
function get_axes();override;
|
|
begin
|
|
return faxes;
|
|
end
|
|
function set_axes(axs);override;
|
|
begin
|
|
faxes := axs;
|
|
end
|
|
private
|
|
[weakref] faxes;
|
|
end
|
|
type tg_label_axes = class(tg_label) //坐标系标签
|
|
public
|
|
function create(pms);
|
|
begin
|
|
inherited;
|
|
auto_position := tgc_on;
|
|
end
|
|
protected
|
|
function get_axes();override;
|
|
begin
|
|
return faxes;
|
|
end
|
|
function set_axes(axs);override;
|
|
begin
|
|
faxes := axs;
|
|
end
|
|
private
|
|
[weakref] faxes;
|
|
end
|
|
type tg_axis = class(tg_base) //轴对象
|
|
function create(pms);
|
|
begin
|
|
inherited;
|
|
fticksize := 12;
|
|
fsubticksize := 6;
|
|
ftics_direction := tgc_bottom; //
|
|
fxtics_coord := array(0,1,2,3);
|
|
ftcmin := 0;
|
|
ftcmax := 3;
|
|
ftccount := 3;
|
|
fxtics_coord_v := array(0,1,2,3);
|
|
fytics_coord := 0;
|
|
ftics_labels := array("0","1","2","3");
|
|
ftics_segment := tgc_on;
|
|
ftics_style := tgc_t_s_v;//"v";
|
|
fsub_tics := 2;
|
|
ftics_color := nil;
|
|
//"v". It's the default value, In this case, tics positions are given by the row factor xtics_coord for horizontal axis (ytics_coord for the vertical one).
|
|
//"r". In this case, tics positions are given by the vector [min,max,n] where n is the number of intervals.
|
|
//"i". In this case the vector given tics positions is of size 4, [k1,k2,a,n] then values are increasing between k1*10^a and k2*10^a, n is the number of intervals.
|
|
end
|
|
function executecommand(cmd,pm);virtual;
|
|
begin
|
|
case cmd of
|
|
"get_tics_value":return fxtics_coord_v;
|
|
|
|
end;
|
|
end
|
|
function paint(cvs);override;
|
|
begin
|
|
if not visible then return ;
|
|
subtks := array();
|
|
idx := 0;
|
|
if fsub_tics>1 then
|
|
begin
|
|
for i:= 0 to length(fxtics_coord_v)-2 do
|
|
begin
|
|
dx := (fxtics_coord_v[i+1]-fxtics_coord_v[i])/fsub_tics;
|
|
for j := 1 to (fsub_tics-1) do
|
|
begin
|
|
subtks[idx++] := fxtics_coord_v[i]+dx*j;
|
|
end
|
|
end
|
|
end
|
|
case ftics_direction of
|
|
tgc_top:
|
|
begin
|
|
draw_axis(cvs,subtks,1);
|
|
end
|
|
tgc_bottom:
|
|
begin
|
|
draw_axis(cvs,subtks,1+2);
|
|
end
|
|
tgc_left:
|
|
begin
|
|
draw_axis(cvs,subtks,0);
|
|
end
|
|
tgc_right:
|
|
begin
|
|
draw_axis(cvs,subtks,0+2);
|
|
end
|
|
|
|
end
|
|
end
|
|
protected
|
|
function check_parent(p);override;
|
|
begin
|
|
return (not(p)) or (p is class(tg_compound)) or (p is class(tg_axes));
|
|
end
|
|
published
|
|
/////////////////////////////////////
|
|
property tics_direction read ftics_direction write set_tics_direction;//= "top"
|
|
property xtics_coord read fxtics_coord write set_xtics_coord ;//= [2,3,4,5,6,7]
|
|
property ytics_coord read fytics_coord write set_ytics_coord ;//= 4
|
|
property tics_segment read ftics_segment write set_tics_segment; // true,false
|
|
property tics_color read ftics_color write set_tics_color; // -1
|
|
property tics_style read ftics_style write set_tics_style; // = "v"
|
|
property sub_tics read fsub_tics write set_sub_tics; // = 2
|
|
property tics_labels read ftics_labels write set_tics_labels; // = ["2","3","4","5","6","7"]
|
|
private
|
|
fticksize;
|
|
fsubticksize;
|
|
fxtics_coord_v;
|
|
ftcmin;
|
|
ftcmax;
|
|
ftccount;
|
|
///////////////////////////////
|
|
ftics_direction;
|
|
fxtics_coord;
|
|
fytics_coord;
|
|
fsub_tics;
|
|
ftics_color;
|
|
ftics_segment;
|
|
ftics_style;
|
|
ftics_labels;
|
|
//format_n ;//= ""
|
|
//fractional_font ;//= "off"
|
|
//clip_state ;//= "off"
|
|
//clip_box ;//= []
|
|
//user_data ;//= []
|
|
//tag ;//= ""
|
|
private
|
|
function draw_axis(cvs,subtks,flg);
|
|
begin
|
|
tklen := fticksize;
|
|
tklensub := fsubticksize;
|
|
vtic := flg .& 1 ;
|
|
vtic2 := (flg .&2)?1:-1;
|
|
|
|
cvs.pen.width := lineinfo.width;
|
|
cvs.pen.color := lineinfo.color;
|
|
cvs.pen.style := lineinfo.style;
|
|
|
|
cvs.font.color := fontinfo.color;
|
|
cvs.font.bkcolor := fontinfo.bkcolor;
|
|
cvs.font.width := fontinfo.size;
|
|
cvs.font.height := fontinfo.size*2;
|
|
|
|
if ftics_segment=tgc_on then
|
|
begin
|
|
for i,v in fxtics_coord_v do
|
|
begin
|
|
if vtic then
|
|
Coordinate_Mapping(v,fytics_coord,0,x,y);
|
|
else Coordinate_Mapping(fytics_coord,v,0,x,y);
|
|
if i=0 then
|
|
cvs.moveto(array(x,y));
|
|
else
|
|
cvs.lineto(array(x,y));
|
|
end
|
|
end
|
|
if ifnumber(ftics_color) then cvs.pen.color := ftics_color;
|
|
for i,v in fxtics_coord_v do
|
|
begin
|
|
if vtic then
|
|
Coordinate_Mapping(v,fytics_coord,0,x,y);
|
|
else Coordinate_Mapping(fytics_coord,v,0,x,y);
|
|
lbi := ftics_labels[i];
|
|
cvs.moveto(array(x,y));
|
|
sz := nil;
|
|
if lbi then
|
|
begin
|
|
sz := array((length(lbi))*fontinfo.size+4,fontinfo.size*2+4) ;//cvs.GetTextExtent(lbi);
|
|
end
|
|
if vtic then
|
|
begin
|
|
ny := y+(vtic2*tklen);
|
|
cvs.lineto(array(x,ny));
|
|
if sz then
|
|
begin
|
|
rec := array(x-sz[0]/2,0,x+sz[0]/2,0);
|
|
if ny>y then
|
|
begin
|
|
rec[1] := ny+5;
|
|
rec[3] := ny+sz[1]+5;
|
|
|
|
end else
|
|
begin
|
|
rec[1] := ny-sz[1]-5;
|
|
rec[3] := ny-5;
|
|
end
|
|
end
|
|
cvs.drawtext(lbi,rec);
|
|
end
|
|
else
|
|
begin
|
|
nx := x+(vtic2*tklen);
|
|
cvs.lineto(array(nx,y));
|
|
if sz then
|
|
begin
|
|
rec := array(0,y-sz[1]/2,0,y+sz[1]/2);
|
|
if nx>x then
|
|
begin
|
|
rec[0] := nx+5;
|
|
rec[2] := nx+sz[0]+5;
|
|
end else
|
|
begin
|
|
rec[0] := nx-sz[0]-5;
|
|
rec[2] := nx-5;
|
|
end
|
|
cvs.drawtext(lbi,rec);
|
|
end
|
|
|
|
end
|
|
//cvs.textout(lbi,array(x,y));
|
|
end
|
|
|
|
for i,v in subtks do
|
|
begin
|
|
if vtic then
|
|
Coordinate_Mapping(v,fytics_coord,0,x,y);
|
|
else Coordinate_Mapping(fytics_coord,v,0,x,y);
|
|
cvs.moveto(array(x,y));
|
|
if vtic then
|
|
cvs.lineto(array(x,y+(vtic2*tklensub)));
|
|
else
|
|
cvs.lineto(array(x+(vtic2*tklensub),y));
|
|
end
|
|
end
|
|
function set_tics_direction(v);
|
|
begin
|
|
if v<>ftics_direction and ( v in array(tgc_top,tgc_left,tgc_right,tgc_bottom)) then
|
|
begin
|
|
ftics_direction := v;
|
|
prop_changed("tics_direction",v);
|
|
end
|
|
end
|
|
function tc_to_label(v);
|
|
begin
|
|
return format("%.2f",v);//tostn(v);
|
|
end
|
|
function set_xtics_coord(v);
|
|
begin
|
|
if v<> fxtics_coord and ifarray(v) then
|
|
begin
|
|
case ftics_style of
|
|
tgc_t_s_v:
|
|
begin
|
|
lbs := array();
|
|
for i,vi in v do
|
|
begin
|
|
if not ifnumber(vi) then return ;
|
|
lbs[i] := tc_to_label(v);
|
|
end
|
|
ftcmin := minvalue(v);
|
|
ftcmax := maxvalue(v);
|
|
if ftcmin=ftcmax then return ;
|
|
ftccount := length(v)-1;
|
|
fxtics_coord := v;
|
|
fxtics_coord_v := v;
|
|
ftics_labels := lbs;
|
|
end
|
|
tgc_t_s_r:
|
|
begin
|
|
if not(v[0]<v[1] and v[2]>=1) then return ;
|
|
fxtics_coord := v;
|
|
ftcmin := v[0];
|
|
ftcmax :=v[1];
|
|
ftccount := v[2];
|
|
type_c_to_r();
|
|
end
|
|
|
|
end;
|
|
fxtics_coord := v;
|
|
prop_changed("xtics_coord",v);
|
|
end
|
|
end
|
|
function set_ytics_coord(v);
|
|
begin
|
|
if v<> fytics_coord then
|
|
begin
|
|
fytics_coord := v;
|
|
prop_changed("ytics_coord",v);
|
|
end
|
|
end
|
|
function set_tics_segment(v);
|
|
begin
|
|
nv := v?true:false;
|
|
if ftics_segment<>v then
|
|
begin
|
|
ftics_segment := v;
|
|
prop_changed("tics_segment",v);
|
|
end
|
|
end
|
|
function set_tics_color(v);
|
|
begin
|
|
nv := v?true:false;
|
|
if ftics_color<>v then
|
|
begin
|
|
ftics_color := v;
|
|
prop_changed("tics_color",v);
|
|
end
|
|
end
|
|
function set_tics_style(v);
|
|
begin
|
|
if v<>ftics_style and( v in array(tgc_t_s_v,tgc_t_s_r)) then
|
|
begin
|
|
ftics_style := v;
|
|
case v of
|
|
tgc_t_s_v:
|
|
begin
|
|
fxtics_coord := array();
|
|
for i,v in fxtics_coord_v do
|
|
begin
|
|
fxtics_coord[i] := v;
|
|
end
|
|
end
|
|
tgc_t_s_r:
|
|
begin
|
|
fxtics_coord := array();
|
|
fxtics_coord[0] := ftcmin;
|
|
fxtics_coord[1] := ftcmax;
|
|
fxtics_coord[2] := ftccount;
|
|
type_c_to_r();
|
|
end
|
|
end ;
|
|
prop_changed("tics_style",v);
|
|
end
|
|
end
|
|
function type_c_to_r();
|
|
begin
|
|
fxtics_coord_v := array();
|
|
ftics_labels := array();
|
|
vidx := 0;
|
|
for x := ftcmin to ftcmax step (ftcmax-ftcmin)/ftccount do
|
|
begin
|
|
fxtics_coord_v[vidx] := x;
|
|
ftics_labels[vidx] := tc_to_label(x);
|
|
vidx++;
|
|
end
|
|
if x>=ftcmax then
|
|
begin
|
|
fxtics_coord_v[vidx-1] := ftcmax ;
|
|
ftics_labels[vidx-1] := tc_to_label(ftcmax) ;
|
|
|
|
end else
|
|
begin
|
|
fxtics_coord_v[vidx] := ftcmax ;
|
|
ftics_labels[vidx] := tc_to_label(ftcmax) ;
|
|
end
|
|
|
|
end
|
|
function set_sub_tics(v);
|
|
begin
|
|
if v>=0 and v<>fsub_tics then
|
|
begin
|
|
fsub_tics := v;
|
|
prop_changed("sub_tics",v);
|
|
end
|
|
end
|
|
function set_tics_labels(v);
|
|
begin
|
|
if ifarray(v) and v<>ftics_labels then
|
|
begin
|
|
ftics_labels:=v;
|
|
prop_changed("tics_labels",v);
|
|
end
|
|
end
|
|
end
|
|
|
|
type tg_label =class(tg_base) //标签对象
|
|
function create(pms);
|
|
begin
|
|
inherited;
|
|
ftext := false;
|
|
fposition := array(0,0);
|
|
fauto_position_value := array(0,0);
|
|
ffill_mode := false;
|
|
ffont_angle := 0;
|
|
fauto_position := tgc_off;
|
|
fauto_rotation := false;
|
|
end
|
|
function paint(cvs);override;
|
|
begin
|
|
if not visible then return ;
|
|
if not ftext then return ;
|
|
cvs.font.width := fontinfo.size;
|
|
cvs.font.height := fontinfo.size*2;
|
|
cvs.font.color := fontinfo.color;
|
|
if fauto_position=tgc_on then
|
|
begin
|
|
p := fauto_position_value;
|
|
end else
|
|
begin
|
|
p := fposition;
|
|
end
|
|
if Coordinate_Mapping(p[0],p[1],0,x_,y_) then
|
|
begin
|
|
if ffont_angle<>0 then
|
|
begin
|
|
cvs.SaveDC();
|
|
cvs.trans(ffont_angle,x_,y_);
|
|
cvs.textout(ftext,array(0,0));
|
|
cvs.RestoreDC();
|
|
end else
|
|
cvs.textout(ftext,array(x_,y_));
|
|
end
|
|
end
|
|
protected
|
|
function check_parent(p);override;
|
|
begin
|
|
return (not p) or (p is class(tg_axis));
|
|
end
|
|
published
|
|
property text read ftext write set_text;//= ""
|
|
property position read fposition write set_positon;//[-27.697388,-1.7130177]
|
|
property auto_position read fauto_position write set_auto_position;//"on"
|
|
property auto_postion_value read fauto_position_value write fauto_position_value;//"on"
|
|
property auto_rotation read fauto_rotation write set_auto_rotation;//"on"
|
|
property font_angle read ffont_angle write set_font_angle;//90
|
|
//font_foreground ;//= 6
|
|
//foreground ;//= 9
|
|
//background ;//= 23
|
|
//fill_mode ;//= "off"
|
|
//font_style ;//= 6
|
|
//font_size ;//= 4
|
|
//fractional_font ;//= "off"
|
|
//font_angle ;//= 90
|
|
private
|
|
ftext;
|
|
fposition;
|
|
fauto_position_value;
|
|
ffont_angle;
|
|
fauto_position;
|
|
fauto_rotation;
|
|
private
|
|
function set_auto_position(v);
|
|
begin
|
|
if not(tgc_off=v or tgc_on=v) then return ;
|
|
if v<>fauto_position then
|
|
begin
|
|
fauto_position := v;
|
|
prop_changed("auto_postion",nil);
|
|
end
|
|
end
|
|
function set_font_angle(v);
|
|
begin
|
|
if v<>ffont_angle and ifnumber(v) then
|
|
begin
|
|
ffont_angle := v;
|
|
prop_changed("font_angle",v);
|
|
end
|
|
end
|
|
function set_text(v);
|
|
begin
|
|
if ifstring(v) and v<>ftext then
|
|
begin
|
|
ftext := v;
|
|
prop_changed("text",nil);
|
|
end
|
|
end
|
|
function set_positon(v);
|
|
begin
|
|
if ifarray(v) and ifnumber(v[0]) and ifnumber(v[1]) and v[0]<>fposition[0] and v[1]<>fposition[1] then
|
|
begin
|
|
fposition[0] :=v[0];
|
|
fposition[1] :=v[1];
|
|
fauto_position := tgc_off;
|
|
prop_changed("postion",v);
|
|
end
|
|
end
|
|
function set_auto_rotation(v);
|
|
begin
|
|
if fauto_rotation<>v and (v in array(tgc_on,tgc_off)) then
|
|
begin
|
|
fauto_rotation := v;
|
|
prop_changed("auto_rotation",v);
|
|
end
|
|
end
|
|
end
|
|
type tg_compound = class(tg_graph) //组合对象
|
|
function create(pms);
|
|
begin
|
|
inherited;
|
|
end
|
|
protected
|
|
function check_parent(p);override;
|
|
begin
|
|
return (not(p)) or (p is class(tg_compound)) or (p is class(tg_axes));
|
|
end
|
|
end
|
|
type tg_axes = class(tg_graph) //坐标系
|
|
private
|
|
[weakref]fFigure;
|
|
///////////////坐标辅助计算/////////////////////////
|
|
p_left;
|
|
p_top;
|
|
p_width;
|
|
p_height;
|
|
dx_min;
|
|
dx_max;
|
|
dx_len;
|
|
dy_min;
|
|
dy_max;
|
|
dy_len;
|
|
rt_x;
|
|
rt_y;
|
|
///////////////////////////////////////////
|
|
public
|
|
function Coordinate_unMapping(x,y,_x,_y,_z);override; //画布到坐标
|
|
begin
|
|
if not(fFigure and fFigure.HandleAllocated()) then return 0;
|
|
if faxes_reverse[0]=tgc_on then //x轴
|
|
begin
|
|
_x := fdata_bounds[0,0]-(x-p_left-p_width)/rt_x;
|
|
end else
|
|
begin
|
|
_x := (x-p_left)/rt_x+fdata_bounds[0,0];
|
|
end
|
|
if faxes_reverse[1]=tgc_on then //y轴
|
|
begin
|
|
_y := (y-p_top)/rt_y +fdata_bounds[1,0];
|
|
end else
|
|
begin
|
|
_y := fdata_bounds[1,0]-(y-p_top-p_height)/rt_y;
|
|
end
|
|
return true;
|
|
end
|
|
function Coordinate_Mapping(x,y,z,_x,_y);override; //坐标到画布
|
|
begin
|
|
if not(fFigure and fFigure.HandleAllocated()) then return 0;
|
|
if faxes_reverse[0]=tgc_on then //x轴
|
|
begin
|
|
_x := p_left+p_width-(x-fdata_bounds[0,0])*rt_x;
|
|
end else
|
|
begin
|
|
_x := (x-fdata_bounds[0,0])*rt_x+p_left;
|
|
end
|
|
if faxes_reverse[1]=tgc_on then //y轴
|
|
begin
|
|
_y := (y-fdata_bounds[1,0])*rt_y+p_top;
|
|
end else
|
|
begin
|
|
_y := p_top+p_height-(y-fdata_bounds[1,0])*rt_y;
|
|
end
|
|
return true;
|
|
end
|
|
function paint(cvs);override;
|
|
begin
|
|
if not visible then return ;
|
|
modify_coordinate_postion();
|
|
inherited;
|
|
paint_grid(cvs);
|
|
for i,v in faxes_objects do //绘制坐标
|
|
begin
|
|
v.paint(cvs);
|
|
end
|
|
modify_label_postion();
|
|
for i,v in array(ftitle,fx_label,fy_label) do //标签
|
|
begin
|
|
v.paint(cvs);
|
|
end
|
|
if fbox = tgc_on then
|
|
begin
|
|
cvs.moveto(array(p_left,p_top));
|
|
cvs.lineto(array(p_left+p_width,p_top));
|
|
cvs.lineto(array(p_left+p_width,p_top+p_height));
|
|
cvs.lineto(array(p_left,p_top+p_height));
|
|
cvs.lineto(array(p_left,p_top));
|
|
end
|
|
end
|
|
|
|
function axes_paint_rect_changd(); //绘制区域改变
|
|
begin
|
|
fr := fFigure.clientrect;
|
|
w := fr[2]-fr[0];
|
|
h := fr[3]-fr[1];
|
|
p_left := fr[0]+w*fmargins[0]+faxes_bounds[0];
|
|
p_top := fr[1]+h*fmargins[1]+faxes_bounds[1];
|
|
p_width := w*(1-fmargins[0]-fmargins[2])*faxes_bounds[2];
|
|
p_height := h*(1-fmargins[1]-fmargins[3])*faxes_bounds[3];
|
|
merge_graph_data_bounds();
|
|
axes_data_bounds_changed();
|
|
end
|
|
function axes_data_bounds_changed(); //数据区域
|
|
begin
|
|
dx_min := fdata_bounds[0,0];
|
|
dx_max := fdata_bounds[0,1];
|
|
dx_len := dx_max-dx_min;
|
|
dy_min := fdata_bounds[1,0];
|
|
dy_max := fdata_bounds[1,1];
|
|
dy_len := dy_max-dy_min;
|
|
rt_x := p_width/ dx_len;
|
|
rt_y := p_height/dy_len;
|
|
end
|
|
function merge_graph_data_bounds();//数据区域
|
|
begin
|
|
d := get_data_bounds();
|
|
fdata_bounds := d;
|
|
faxes_objects[0].xtics_coord := array(d[0,0],d[0,1],10);
|
|
faxes_objects[1].xtics_coord := array(d[1,0],d[1,1],10);
|
|
end
|
|
function create(pms);
|
|
begin
|
|
inherited;
|
|
fgrid := array();
|
|
for i:= 0 to 1 do
|
|
begin
|
|
gd := new tg_line_info();
|
|
gd.width := 0;
|
|
gd.Style := tgc_PS_DASH;
|
|
fgrid[i] := gd;
|
|
end
|
|
faxes_reverse := array(tgc_off,tgc_off,tgc_off);
|
|
fview := "2d";
|
|
fbox := tgc_off;
|
|
ffilled := tgc_off;
|
|
fx_location := tgc_bottom;
|
|
fy_location := tgc_left;
|
|
faxes_objects := array();
|
|
for i := 0 to 2 do
|
|
begin
|
|
axi := new tg_axis_main();
|
|
axi.tics_style := tgc_t_s_r;
|
|
case i of
|
|
0: axi.tics_direction := tgc_bottom;
|
|
1:axi.tics_direction := tgc_left;
|
|
2:axi.visible := false;
|
|
end ;
|
|
faxes_objects[i] := axi;
|
|
axi.axes := self(true);
|
|
end
|
|
|
|
ftitle := new tg_label_axes();
|
|
ftitle.axes := self(true);
|
|
fx_label := new tg_label_axes();
|
|
fx_label.axes := self(true);
|
|
fy_label := new tg_label_axes();
|
|
fy_label.axes := self(true);
|
|
fy_label.font_angle := pi()/2;
|
|
|
|
|
|
fauto_ticks := array("on","on","on");
|
|
fmargins := array(0.125,0.125,0.125,0.125);
|
|
faxes_bounds := array( 0,0,1,1);
|
|
fdata_bounds := array((0,1),(0,1),(0,1));
|
|
fzoom_box := array();
|
|
//FA vector containing the handles of all graphics objects children of the
|
|
//axes These graphics objects are of type
|
|
//"Compound", "Rectangle", "Polyline", "Segs", "Arc", "Grayplot",.. (see Compound_properties,
|
|
//rectangle_properties, champ_properties, axis_properties, polyline_properties, segs_properties,
|
|
//grayplot_properties, surface_properties, fec_properties, text_properties, legend_properties)
|
|
end
|
|
published
|
|
property figure read fFigure write SetFigure; //窗口
|
|
property view read fview write set_view; //立体
|
|
property axises read get_axises;//axes_visible ;//= ["on","on","on"]
|
|
property axes_reverse read gs_axes_reverse write gs_axes_reverse;//axes_reverse ;//= ["off","off","off"]
|
|
property x_location read fx_location write set_x_location;//'bottom
|
|
property y_location read fy_location write set_y_location;//'left
|
|
property title read ftitle;
|
|
property x_label read fx_label;
|
|
property y_label read fy_label;
|
|
property z_label read fz_label;
|
|
property auto_ticks read gs_auto_ticks write gs_auto_ticks;
|
|
property box read fbox write set_box;
|
|
property filled read ffilled write set_filled;
|
|
property sub_ticks read gs_sub_ticks write gs_sub_ticks;
|
|
//上下左右空白
|
|
property margins read gs_margins write gs_margins;
|
|
property axes_bounds read gs_axes_bounds write gs_axes_bounds;
|
|
property data_bounds read gs_data_bounds write gs_data_bounds;
|
|
property zoom_box read fzoom_box write fzoom_box;
|
|
//在窗口中的区域
|
|
|
|
//网格线
|
|
property grid read get_grid;
|
|
|
|
//grid ;//= [-1,-1]
|
|
//grid_position ;//= "background"
|
|
//grid_thickness ;//= [1,1]
|
|
//grid_style ;//= [7,7]
|
|
//x_ticks.locations ;//= matrix 21x1
|
|
//y_ticks.locations ;//= matrix 11x1
|
|
//z_ticks.locations ;//= []
|
|
//x_ticks.labels ;//= matrix 21x1
|
|
//y_ticks.labels ;//= matrix 11x1
|
|
//z_ticks.labels ;//= []
|
|
//ticks_format ;//= ["","",""]
|
|
//ticks_st ;//= [1,1,1;0,0,0]
|
|
//sub_ticks ;//= [1,1]
|
|
font_style ;//= 6
|
|
font_size ;//= 1
|
|
font_color ;//= -1
|
|
fractional_font ;//= "off"
|
|
|
|
//isoview ;//= "off"
|
|
//cube_scaling ;//= "off"
|
|
//rotation_angles ;//= [0,270]
|
|
//log_flags ;//= "nnn"
|
|
//tight_limits ;//= ["off","off","off"]
|
|
//zoom_box ;//= []
|
|
//auto_margins ;//= "on"
|
|
//auto_clear ;//= "off"
|
|
//auto_scale ;//= "on"
|
|
//auto_stretch ;//= "on"
|
|
|
|
//hidden_axis_color ;//= 4
|
|
//hiddencolor ;//= 4
|
|
//line_mode ;//= "on"
|
|
//line_style ;//= 1
|
|
//thickness ;//= 1
|
|
//mark_mode ;//= "off"
|
|
//mark_style ;//= 0
|
|
//mark_size_unit ;//= "tabulated"
|
|
//mark_size ;//= 0
|
|
//mark_foreground ;//= -1
|
|
//mark_background ;//= -2
|
|
//foreground ;//= -1
|
|
//background ;//= -2
|
|
//arc_drawing_method ;//= "lines"
|
|
//clip_state ;//= "clipgrf"
|
|
//clip_box ;//= []
|
|
protected
|
|
function get_axes();override;
|
|
begin
|
|
return self(true);
|
|
end
|
|
private
|
|
fgrid;
|
|
faxes_objects;
|
|
fzoom_box;
|
|
fmargins;
|
|
faxes_bounds ;//= [0,0,1,1]
|
|
fdata_bounds;
|
|
ffilled;
|
|
fauto_ticks;
|
|
ftitle;
|
|
fx_label;
|
|
fy_label;
|
|
fz_label;
|
|
fx_location;
|
|
fy_location;
|
|
fview;
|
|
fbox;
|
|
faxes_reverse;
|
|
private
|
|
fwilldelfigure;
|
|
fwilladdfigure;
|
|
function paint_grid(cvs);//绘制表格
|
|
begin
|
|
xg := fgrid[0];
|
|
if xg.width>0 and ifnumber(xg.color) then
|
|
begin
|
|
cvs.pen.width :=xg.width;
|
|
cvs.pen.color := xg.color;
|
|
cvs.pen.Style := xg.Style;
|
|
y1 := p_top;
|
|
y2 := p_top+p_height;
|
|
for i,v in faxes_objects[0].executecommand("get_tics_value") do
|
|
begin
|
|
if Coordinate_Mapping(v,0,0,_x,_y) then
|
|
begin
|
|
cvs.moveto(array(_x,y1));
|
|
cvs.lineto(array(_x,y2));
|
|
end
|
|
|
|
end
|
|
end
|
|
xg := fgrid[1];
|
|
if xg.width>0 and ifnumber(xg.color) then
|
|
begin
|
|
cvs.pen.width :=xg.width;
|
|
cvs.pen.color := xg.color;
|
|
cvs.pen.Style := xg.Style;
|
|
x1 := p_left;
|
|
x2 := p_left+p_width;
|
|
for i,v in faxes_objects[1].executecommand("get_tics_value") do
|
|
begin
|
|
if Coordinate_Mapping(0,v,0,_x,_y) then
|
|
begin
|
|
cvs.moveto(array(x1,_y));
|
|
cvs.lineto(array(x2,_y));
|
|
end
|
|
|
|
end
|
|
end
|
|
|
|
|
|
end
|
|
function get_tics(tk);
|
|
begin
|
|
r := array();
|
|
rd := tk.xtics_coord;
|
|
case tk.tics_style of
|
|
tgc_t_s_v:
|
|
begin
|
|
|
|
end
|
|
else //tgc_t_s_r:
|
|
begin
|
|
|
|
end
|
|
end
|
|
end
|
|
function modify_label_postion(); //修正标签位置
|
|
begin
|
|
if fx_label and fx_label.visible and fx_label.text then
|
|
begin
|
|
s := fx_label.text;
|
|
if s then
|
|
begin
|
|
x := p_left+(p_width-length(s)*10)/2;
|
|
Coordinate_unMapping(x,p_top+p_height+40,_x,_y,_z);
|
|
p := array(_x,_y);
|
|
fx_label.auto_postion_value := p;
|
|
end
|
|
end
|
|
if fy_label and fy_label.visible and fy_label.text then
|
|
begin
|
|
s := fy_label.text;
|
|
if s then
|
|
begin
|
|
y := p_top+(p_height-length(s)*10)/2;
|
|
if (fy_location= tgc_left) then x := p_left+p_width+40;
|
|
else
|
|
x := p_left-40;
|
|
Coordinate_unMapping(x,y,_x,_y,_z);
|
|
p := array(_x,_y);
|
|
fy_label.auto_postion_value := p;
|
|
end
|
|
end
|
|
if ftitle and ftitle.visible then
|
|
begin
|
|
s := ftitle.text;
|
|
if s then
|
|
begin
|
|
x := p_left+(p_width-length(s)*10)/2;
|
|
Coordinate_unMapping(x,p_top-40,_x,_y,_z);
|
|
p := array(_x,_y);
|
|
ftitle.auto_postion_value := p;
|
|
end
|
|
end
|
|
end
|
|
function modify_coordinate_postion();
|
|
begin
|
|
case fy_location of
|
|
tgc_left:
|
|
begin
|
|
faxes_objects[1].ytics_coord := fdata_bounds[0,(faxes_reverse[0] = tgc_on)];
|
|
end
|
|
tgc_right:
|
|
begin
|
|
faxes_objects[1].ytics_coord := fdata_bounds[0,(faxes_reverse[0]<> tgc_on)];
|
|
|
|
end
|
|
tgc_middle:
|
|
begin
|
|
faxes_objects[1].ytics_coord := fdata_bounds[0,0]+(fdata_bounds[0,1]-fdata_bounds[0,0])/2;
|
|
end
|
|
tgc_origin:
|
|
begin
|
|
faxes_objects[1].ytics_coord := 0;
|
|
end
|
|
end ;
|
|
case fx_location of
|
|
tgc_bottom:
|
|
begin
|
|
faxes_objects[0].ytics_coord := fdata_bounds[1,(faxes_reverse[1]= tgc_on)];
|
|
end
|
|
tgc_top:
|
|
begin
|
|
faxes_objects[0].ytics_coord := fdata_bounds[1,(faxes_reverse[1]<> tgc_on)];
|
|
end
|
|
tgc_middle:
|
|
begin
|
|
faxes_objects[0].ytics_coord := fdata_bounds[1,0]+(fdata_bounds[1,1]-fdata_bounds[1,0])/2;
|
|
end
|
|
tgc_origin:
|
|
begin
|
|
faxes_objects[0].ytics_coord := 0;
|
|
end
|
|
end ;
|
|
end
|
|
function SetFigure(v);
|
|
begin
|
|
if v=fFigure then return ;
|
|
if fwilladdfigure and fwilladdfigure=v then
|
|
begin
|
|
fwilladdfigure := nil;
|
|
fFigure := v;
|
|
v.add_axes(self(true));
|
|
return ;
|
|
end
|
|
if fwilldelfigure and fwilldelfigure=tp then
|
|
begin
|
|
fwilldelfigure := nil;
|
|
fFigure := nil;
|
|
v.del_axes(self(true));
|
|
return ;
|
|
end
|
|
tp := fFigure;
|
|
if tp then //删除
|
|
begin
|
|
fwilldelfigure := tp;
|
|
tp.del_axes(self(true));
|
|
fwilldelfigure := nil;
|
|
end
|
|
if v is class(tcustomfigure) then //添加
|
|
begin
|
|
fwilladdfigure := v;
|
|
v.add_axes(self(true));
|
|
fwilladdfigure := nil;
|
|
end else
|
|
begin
|
|
fFigure := nil;
|
|
end
|
|
end
|
|
function set_filled(v);
|
|
begin
|
|
if (v in array(tgc_on,tgc_off)) and v<>fbox then
|
|
begin
|
|
ffilled := v;
|
|
prop_changed("ffilled",v);
|
|
end
|
|
end
|
|
function set_box(v);
|
|
begin
|
|
if (v in array(tgc_box_on,tgc_box_on,tgc_box_half,tgc_box_hidden_axes)) and v<>fbox then
|
|
begin
|
|
fbox := v;
|
|
prop_changed("box",v);
|
|
end
|
|
end
|
|
function set_x_location(v);
|
|
begin
|
|
if v<>fx_location and ( v in array(tgc_bottom,tgc_top,tgc_middle,tgc_origin)) then
|
|
begin
|
|
fx_location := v;
|
|
if v=tgc_bottom or v=tgc_top then faxes_objects[0].tics_direction := v;
|
|
prop_changed("x_location",v);
|
|
end
|
|
end
|
|
function set_y_location(v);
|
|
begin
|
|
if v<>fy_location and ( v in array(tgc_left,tgc_right,tgc_middle,tgc_origin)) then
|
|
begin
|
|
fy_location := v;
|
|
if v=tgc_left or v=tgc_right then faxes_objects[1].tics_direction := v;
|
|
prop_changed("x_location",v);
|
|
end
|
|
end
|
|
function get_grid(idx);
|
|
begin
|
|
if idx=0 or idx=1 then return fgrid[idx];
|
|
end
|
|
function set_view(v);
|
|
begin
|
|
return ;
|
|
end
|
|
function gs_auto_ticks(idx,v);
|
|
begin
|
|
if v=tgc_on or v=tgc_off then
|
|
begin
|
|
if idx in array(0,1,2) then
|
|
begin
|
|
if fauto_ticks[idx]<>v then
|
|
begin
|
|
fauto_ticks[idx] := v;
|
|
prop_changed("auto_ticks",idx);
|
|
end
|
|
end
|
|
end else //get
|
|
begin
|
|
if idx in array(0,1,2) then return fauto_ticks[idx];
|
|
return fauto_ticks;
|
|
end
|
|
end
|
|
function get_axises(idx);
|
|
begin
|
|
if idx in array(0,1) then
|
|
begin
|
|
return faxes_objects[idx];
|
|
end
|
|
end
|
|
function gs_axes_bounds(idx,v);
|
|
begin
|
|
if ifarray(v) and ifnumber(v[0]) and ifnumber(v[1]) then
|
|
begin
|
|
if idx in array(0,1,2,3) then
|
|
begin
|
|
faxes_bounds[idx] := array(v[0],v[1]);
|
|
prop_changed("axes_bounds",idx);
|
|
end
|
|
end else //get
|
|
begin
|
|
if idx in array(0,1,2,3) then return faxes_bounds[idx];
|
|
return faxes_bounds;
|
|
end
|
|
end
|
|
function gs_data_bounds(idx,v);
|
|
begin
|
|
if ifarray(v) and ifnumber(v[0]) and ifnumber(v[1]) then
|
|
begin
|
|
if idx in array(0,1,2) then
|
|
begin
|
|
fdata_bounds[idx] := v;
|
|
prop_changed("data_bounds",idx);
|
|
end
|
|
end else //get
|
|
begin
|
|
if idx in array(0,1,2) then return fdata_bounds[idx];
|
|
return fdata_bounds;
|
|
end
|
|
end
|
|
|
|
function gs_axes_reverse(idx,v);
|
|
begin
|
|
if v=tgc_off or v=tgc_on then
|
|
begin
|
|
if idx in array(0,1,2) then
|
|
begin
|
|
faxes_reverse[idx] := v;
|
|
prop_changed("axes_reverse",idx);
|
|
end
|
|
end else //get
|
|
begin
|
|
if idx in array(0,1,2) then return faxes_reverse[idx];
|
|
return faxes_reverse;
|
|
end
|
|
end
|
|
function gs_margins(idx,v);
|
|
begin
|
|
if ifnumber(v) then
|
|
begin
|
|
if idx in array(0,1,2,3) then
|
|
begin
|
|
fmargins[idx] := v;
|
|
prop_changed("margins",idx);
|
|
end
|
|
end else //get
|
|
begin
|
|
if idx in array(0,1,2,3) then return fmargins[idx];
|
|
return fmargins;
|
|
end
|
|
end
|
|
function gs_sub_ticks(idx,v);
|
|
begin
|
|
if ifnumber(v) and (v>=0) then
|
|
begin
|
|
if idx in array(0,1,2) then
|
|
begin
|
|
faxes_objects[idx].sub_tics := v;
|
|
//prop_changed("axes_visible",idx);
|
|
end
|
|
end else //get
|
|
begin
|
|
if idx in array(0,1,2) then return faxes_objects[idx].sub_tics;
|
|
return array(faxes_objects[0].sub_tics,faxes_objects[1].sub_tics,faxes_objects[2].sub_tics);
|
|
end
|
|
end
|
|
|
|
end
|
|
type tg_tips = class(tg_base)
|
|
function create(pms);
|
|
begin
|
|
inherited;
|
|
finterp_mode := tgc_off;
|
|
fbox_mode := tgc_on;
|
|
fline_style := 0;
|
|
fforeground := -1;
|
|
fbackground := -2;
|
|
fmark_mode := tgc_on;
|
|
fmark_style := 11;
|
|
end
|
|
property interp_mode read finterp_mode write finterp_mode; //"on"
|
|
property box_mode read fbox_mode write fbox_mode; //"on"
|
|
private
|
|
fbox_mode;
|
|
finterp_mode;
|
|
//auto_orientation ;//= "on"
|
|
//orientation ;//= 3
|
|
//label_mode ;//= "on"
|
|
//data ;//= [66.064054,-1.3511706,0]
|
|
//display_components ;//= "xy"
|
|
//display_function ;//= ""
|
|
//text ;//= ["X:66.064";"Y:-1.351"]
|
|
//font_foreground ;//= -1
|
|
//font_style ;//= 6
|
|
//font_size ;//= 1
|
|
//detached_position ;//= []
|
|
//mark_size_unit ;//= "point"
|
|
//mark_size ;//= 8
|
|
//mark_foreground ;//= -3
|
|
//mark_background ;//= -2
|
|
|
|
end
|
|
type tg_legend = class(tg_base)
|
|
function create(pms);
|
|
begin
|
|
inherited;
|
|
end
|
|
//parent Axes
|
|
//text ;//= "y1"
|
|
//font_style ;//= 6
|
|
//font_size ;//= 1
|
|
//font_color ;//= -1
|
|
//fractional_font ;//= "off"
|
|
//links ;//= "Polyline" [] 数组
|
|
//legend_location ;//= "in_upper_right"
|
|
//position ;//= [0.7379099,0.1325]
|
|
//line_width ;//= 0.1
|
|
//line_mode ;//= "on"
|
|
//thickness ;//= 1
|
|
//foreground ;//= -1
|
|
//fill_mode ;//= "on"
|
|
//background ;//= -2
|
|
//marks_count ;//= 3
|
|
//clip_state ;//= "off"
|
|
//clip_box ;//= []
|
|
end
|
|
type tg_graph = class(tg_base)
|
|
function create(pms);
|
|
begin
|
|
inherited;
|
|
end
|
|
function get_data_bounds();virtual;
|
|
begin
|
|
d := zeros(3,2);
|
|
for i := 0 to NodeCount-1 do
|
|
begin
|
|
vi := GetNodeByIndex(i);
|
|
if vi is class(tg_graph) then
|
|
begin
|
|
bds := vi.get_data_bounds();
|
|
mg_bds(bds,d);
|
|
end
|
|
end
|
|
return d;
|
|
end
|
|
end
|
|
type tg_Polyline = class(tg_graph)
|
|
function create(pms);
|
|
begin
|
|
inherited;
|
|
fclosed := tgc_off;
|
|
//fmark_style :=tgc_mks_dot ;//= 9
|
|
//fmark_size_unit := "point";//= "point","tabulated"
|
|
//fmark_size :=0;//= 0
|
|
//fmark_foreground := 16;//= 16
|
|
//fmark_background := 15;//= 15
|
|
//fforeground := 33 ;//= 33
|
|
//fbackground := 26 ;//= 26
|
|
fline_mode := tgc_on;
|
|
fmark_mode := tgc_on;
|
|
fpolyline_style := tgc_LS_interpolated;// interpolated,staircase,barplot,arrowed,filled,bar
|
|
fbar_width := 0;
|
|
fdata_bounds := array((0,10),(0,10),(0,10));
|
|
end
|
|
function get_data_bounds();override;
|
|
begin
|
|
return fdata_bounds;
|
|
end
|
|
function paint(cvs);override;
|
|
begin
|
|
if not visible then return ;
|
|
xys := array();
|
|
if fline_mode=tgc_on then
|
|
begin
|
|
cvs.pen.Style := lineinfo.Style;
|
|
cvs.pen.color := lineinfo.color;
|
|
cvs.pen.width := lineinfo.width;
|
|
for i,v in fdata do
|
|
begin
|
|
if not Coordinate_Mapping(v[0],v[1],z,x,y) then return ;
|
|
xys[i] := array(integer(x),integer(y));
|
|
end
|
|
case fpolyline_style of
|
|
tgc_LS_staircase:
|
|
begin
|
|
last := array();
|
|
for i,v in xys do
|
|
begin
|
|
if i=0 then
|
|
begin
|
|
last := v;
|
|
cvs.moveto(v);
|
|
end else
|
|
begin
|
|
|
|
cvs.lineto(array(v[0],last[1]));
|
|
cvs.lineto(v);
|
|
last := v;
|
|
end
|
|
end
|
|
end
|
|
else
|
|
begin
|
|
cvs.draw_polyline().points(xys).draw();
|
|
end
|
|
end;
|
|
mk := markinfo;
|
|
if mark_mode=tgc_on and mk.size>2 then
|
|
begin
|
|
paint_marks(mk,cvs,xys);
|
|
|
|
end
|
|
end
|
|
end
|
|
|
|
property closed read fclosed write fclosed;//= "off"
|
|
//property mark_style read fmark_style write fmark_style;//= "dot"
|
|
//property mark_size_unit read fmark_size_unit write fmark_size_unit;//= "point"
|
|
//property mark_size read fmark_size write fmark_size;//= "0"
|
|
//property mark_foreground read fmark_foreground write fmark_foreground;//= "0"
|
|
//property foreground read fforeground write fforeground;//= "0"
|
|
//property mark_background read fmark_background write fmark_background;//= "0"
|
|
//property background read fbackground write fbackground;//= "0"
|
|
property line_mode read fline_mode write fline_mode;//= "0"
|
|
property mark_mode read fmark_mode write fmark_mode;//= "0"
|
|
property polyline_style read fpolyline_style write fpolyline_style;//= "0"
|
|
property bar_width read fbar_width write fbar_width;//= "0"
|
|
property data read fdata write set_data;
|
|
private
|
|
fdata_bounds;
|
|
fclosed;
|
|
fmark_size_unit;
|
|
fmark_style;
|
|
fmark_size;
|
|
fmark_foreground;
|
|
fmark_background;
|
|
fforeground;
|
|
fbackground;
|
|
fline_mode;
|
|
fmark_mode;
|
|
fpolyline_style;
|
|
fbar_width;
|
|
fdata;//数据
|
|
//datatips;//: ["Datatip";"Datatip"]
|
|
//datatip_display_mode;//: "always"
|
|
//display_function ;//= ""
|
|
//display_function_data ;//= []
|
|
//fill_mode ;//= "off"
|
|
//thickness ;//= 4
|
|
//arrow_size_factor ;//= 1
|
|
|
|
//interp_color_vector ;//= []
|
|
//interp_color_mode ;//= "off"
|
|
//colors ;//= []
|
|
|
|
//mark_offset ;//= 0
|
|
//mark_stride ;//= 1
|
|
//x_shift ;//= []
|
|
//y_shift ;//= []
|
|
//z_shift ;//= []
|
|
//bar_width ;//= 0
|
|
//clip_state ;//= "clipgrf"
|
|
//clip_box ;//= []
|
|
private
|
|
fx;
|
|
fy;
|
|
function set_data(d); //设置数据
|
|
begin
|
|
if d<>FData then
|
|
begin
|
|
FData := d;
|
|
fx := fdata[:,0];
|
|
fy := fdata[:,1];
|
|
fdata_bounds[0,0] := minvalue(fx);
|
|
fdata_bounds[1,0] := minvalue(fy);
|
|
fdata_bounds[0,1] := maxvalue(fx);
|
|
fdata_bounds[1,1] := maxvalue(fy);
|
|
prop_changed("data",v);
|
|
end
|
|
end
|
|
end
|
|
|
|
type tg_line_info = class(tg_const)
|
|
function create();
|
|
begin
|
|
fcolor := 0;
|
|
FWidth := 1;
|
|
FStyle := tgc_PS_SOLID;
|
|
end
|
|
property width read FWidth write fwidth;
|
|
property color read fcolor write fcolor;
|
|
property Style read FStyle write FStyle;
|
|
private
|
|
fwidth;
|
|
fcolor;
|
|
FStyle;
|
|
end
|
|
type tg_font_info = class(tg_const)
|
|
function create();
|
|
begin
|
|
fstyle := tgc_mks_dot;
|
|
fsize := 7;
|
|
fforeground := 0;
|
|
fbackground := nil;
|
|
end
|
|
property style read fstyle write fstyle;
|
|
property size read fsize write fsize;
|
|
property color read fforeground write fforeground;
|
|
property bkcolor read fbackground write fbackground;
|
|
private
|
|
fstyle;
|
|
fsize;
|
|
fsize_unit;
|
|
fforeground;
|
|
fbackground;
|
|
end
|
|
type tg_mark_info = class(tg_const)
|
|
function create();
|
|
begin
|
|
fstyle := tgc_mks_dot;
|
|
fsize := 0;
|
|
fsize_unit := tgc_mk_point;
|
|
fforeground := 0;
|
|
fbackground := 0xffffff;
|
|
end
|
|
property style read fstyle write fstyle;
|
|
property size read fsize write fsize;
|
|
property size_unit read fsize_unit write fsize_unit;
|
|
property color read fforeground write fforeground;
|
|
property bkcolor read fbackground write fbackground;
|
|
private
|
|
fstyle;
|
|
fsize;
|
|
fsize_unit;
|
|
fforeground;
|
|
fbackground;
|
|
end
|
|
type tg_base = class(TNode,tg_const) //基类,提供层次关系结构
|
|
public
|
|
function create(pms);
|
|
begin
|
|
class(TNode).create();
|
|
fvisibe := true;
|
|
flineinfo := new tg_line_info();
|
|
fmarkinfo := new tg_mark_info();
|
|
ffontinfo := new tg_font_info();
|
|
end
|
|
function Coordinate_Mapping(x,y,z,_x,_y);virtual;
|
|
begin
|
|
p := get_axes();
|
|
if p then return p.Coordinate_Mapping(x,y,z,_x,_y);
|
|
return false;
|
|
end
|
|
function Coordinate_unMapping(x,y,x_,y_,z_);virtual;
|
|
begin
|
|
p := get_axes;
|
|
if p then return p.Coordinate_unMapping(x,y,x_,y_,z_);
|
|
return false;
|
|
end
|
|
function executecommand(cmd,pm);virtual;
|
|
begin
|
|
|
|
end
|
|
function paint(cvs);virtual; //绘制
|
|
begin
|
|
if not visible then return ;
|
|
for i := 0 to NodeCount-1 do
|
|
begin
|
|
vi := GetNodeByIndex(i);
|
|
vi.paint(cvs);
|
|
end
|
|
end
|
|
published
|
|
property axes read get_axes write set_axes;
|
|
property visible read fvisibe write setvisible;
|
|
property lineinfo read flineinfo;
|
|
property markinfo read fmarkinfo;
|
|
property fontinfo read ffontinfo;
|
|
protected
|
|
function get_axes();virtual;
|
|
begin
|
|
p := parent;
|
|
if p then return p.axes;
|
|
end
|
|
function set_axes(axs);virtual;
|
|
begin
|
|
end
|
|
public
|
|
user_data;
|
|
tag;
|
|
protected
|
|
function check_parent(p);virtual; //父节点检查
|
|
begin
|
|
return true;
|
|
end
|
|
function prop_changed(n,v);virtual; //改变通知
|
|
begin
|
|
|
|
end
|
|
function SetParent(V);virtual;
|
|
begin
|
|
if not check_parent(p) then return ;
|
|
return inherited;
|
|
end
|
|
private
|
|
fvisibe;
|
|
flineinfo;
|
|
fmarkinfo;
|
|
ffontinfo;
|
|
function setvisible(v);//设置可见
|
|
begin
|
|
nv := v?true:false;
|
|
if nv<>fvisibe then
|
|
begin
|
|
fvisibe := nv;
|
|
prop_changed("visible",fvisibe);
|
|
end
|
|
end
|
|
end
|
|
type tg_const = class()
|
|
|
|
static const tgc_top = "top";
|
|
static const tgc_bottom = "bottom";
|
|
static const tgc_left = "left";
|
|
static const tgc_right = "right";
|
|
static const tgc_middle = "middle";
|
|
static const tgc_origin = "origin";
|
|
|
|
static const tgc_off = "off";
|
|
static const tgc_on = "on";
|
|
static const tgc_box_off = "off";
|
|
static const tgc_box_on = "on";
|
|
static const tgc_box_half = "half";
|
|
static const tgc_box_hidden_axes = "hidden_axes";
|
|
static const tgc_t_s_v = "v";
|
|
static const tgc_t_s_r = "r";
|
|
static const tgc_t_s_i = "i";
|
|
|
|
static const tgc_mks_dot = "dot"; //原点
|
|
static const tgc_mks_plus = "plus"; //加号
|
|
static const tgc_mks_star = "star"; //圈叉
|
|
static const tgc_mks_diamond = "diamond"; //正方形
|
|
static const tgc_mks_diamond_plus = "diamond_plus"; //正方形
|
|
static const tgc_mks_square = "square"; //正方形
|
|
static const tgc_mks_circle = "circle";//圆圈
|
|
static const tgc_mks_pentagram = "pentagram";//五角
|
|
static const tgc_mks_asterisk = "asterisk";//米字
|
|
static const tgc_mks_cross = "cross";//叉
|
|
static const tgc_mks_triangle_up = "triangle_up";
|
|
static const tgc_mks_triangle_down = "triangle_down";
|
|
static const tgc_mks_triangle_left = "triangle_left";
|
|
static const tgc_mks_triangle_right = "triangle_right";
|
|
|
|
static const tgc_mk_tabulated = "tabulated";
|
|
static const tgc_mk_point = "point";
|
|
|
|
static const tgc_dm_always = "always";
|
|
static const tgc_dm_mouseclick = "mouseclick";
|
|
static const tgc_dm_mouseover = "mouseover";
|
|
|
|
static const tgc_PS_SOLID=0x0;
|
|
static const tgc_PS_DASH=0x1;
|
|
static const tgc_PS_DOT=0x2;
|
|
static const tgc_PS_DASHDOT=0x3;
|
|
static const tgc_PS_DASHDOTDOT=0x4;
|
|
static const tgc_PS_NULL=0x5 ;
|
|
|
|
static const tgc_LS_interpolated="interpolated" ;
|
|
static const tgc_LS_staircase="staircase" ;
|
|
static const tgc_LS_arrowed="arrowed" ;
|
|
static const tgc_LS_barplot="barplot" ;
|
|
static const tgc_LS_filled="filled" ;
|
|
static const tgc_LS_bar="bar" ;
|
|
end
|
|
implementation
|
|
function mg_bds(bds,d);
|
|
begin
|
|
d[0,0] := min(bds[0,0],d[0,0]);
|
|
d[0,1] := max(bds[0,1],d[0,1]);
|
|
d[1,0] := min(bds[1,0],d[1,0]);
|
|
d[1,1] := max(bds[1,1],d[1,1]);
|
|
d[2,0] := min(bds[2,0],d[2,0]);
|
|
d[2,1] := max(bds[2,1],d[2,1]);
|
|
end
|
|
function p_trans(x,y,ag,_x,_y);
|
|
begin
|
|
_x := x*cos(ag)+y*sin(ag);
|
|
_y := -x*sin(ag)+y*cos(ag);
|
|
end
|
|
function paint_marks(mk,dc,xys);
|
|
begin
|
|
tp := mk.Style;
|
|
sz := mk.size;
|
|
a := integer(sz/2);
|
|
b := max(a,(sz-a));
|
|
a := b;
|
|
dc.pen.Style := 0;
|
|
dc.pen.color := mk.color;
|
|
dc.brush.color := mk.bkcolor;
|
|
case tp of
|
|
"pentagram":
|
|
begin
|
|
sp := dc.draw_polygon();
|
|
for i,v in xys do
|
|
begin
|
|
vv := array();
|
|
for ii := 0 to 11 do
|
|
begin
|
|
if (ii mod 2)=1 then
|
|
begin
|
|
p_trans(0,-a/2,(ii*36)/180*pi(),_x,_y);
|
|
end else
|
|
p_trans(0,-a,(ii*36)/180*pi(),_x,_y);
|
|
vv[ii] := array(v[0]+_x,v[1]+_y);
|
|
end
|
|
sp.points(vv).draw();
|
|
end
|
|
end
|
|
"triangle_up":
|
|
begin
|
|
sp := dc.draw_polygon();
|
|
for i,v in xys do
|
|
begin
|
|
v1 := array(v[0],v[1]-a);
|
|
p_trans(0,-a,120/180*pi(),_x,_y);
|
|
v2 := array(v[0]+_x,v[1]+_y);
|
|
p_trans(0,-a,-120/180*pi(),_x,_y);
|
|
v3 := array(v[0]+_x,v[1]+_y);
|
|
sp.points(array(v1,v3,v2)).draw();
|
|
end
|
|
end
|
|
"triangle_down":
|
|
begin
|
|
sp := dc.draw_polygon();
|
|
for i,v in xys do
|
|
begin
|
|
v1 := array(v[0],v[1]+a);
|
|
p_trans(0,a,120/180*pi(),_x,_y);
|
|
v2 := array(v[0]+_x,v[1]+_y);
|
|
p_trans(0,a,-120/180*pi(),_x,_y);
|
|
v3 := array(v[0]+_x,v[1]+_y);
|
|
sp.points(array(v1,v3,v2)).draw();
|
|
end
|
|
end
|
|
"triangle_left":
|
|
begin
|
|
sp := dc.draw_polygon();
|
|
for i,v in xys do
|
|
begin
|
|
v1 := array(v[0]-a,v[1]);
|
|
p_trans(-a,0,120/180*pi(),_x,_y);
|
|
v2 := array(v[0]+_x,v[1]+_y);
|
|
p_trans(-a,0,-120/180*pi(),_x,_y);
|
|
v3 := array(v[0]+_x,v[1]+_y);
|
|
sp.points(array(v1,v3,v2)).draw();
|
|
end
|
|
end
|
|
"triangle_right":
|
|
begin
|
|
sp := dc.draw_polygon();
|
|
for i,v in xys do
|
|
begin
|
|
v1 := array(v[0]+a,v[1]);
|
|
p_trans(a,0,120/180*pi(),_x,_y);
|
|
v2 := array(v[0]+_x,v[1]+_y);
|
|
p_trans(a,0,-120/180*pi(),_x,_y);
|
|
v3 := array(v[0]+_x,v[1]+_y);
|
|
sp.points(array(v1,v3,v2)).draw();
|
|
end
|
|
end
|
|
"diamond_plus":
|
|
begin
|
|
mk.Style := "diamond";
|
|
paint_marks(mk,dc,xys);
|
|
mk.Style := "plus";
|
|
paint_marks(mk,dc,xys);
|
|
mk.Style := "diamond_plus";
|
|
end
|
|
"diamond":
|
|
begin
|
|
sp := dc.draw_polygon();
|
|
for i,v in xys do
|
|
begin
|
|
x := v[0];
|
|
y := v[1];
|
|
v1 := array(x-a,y);
|
|
v2 := array(x+b,y);
|
|
v3 := array(x,y-a);
|
|
v4 := array(x,y+b);
|
|
sp.points(array(v1,v3,v2,v4)).draw();
|
|
|
|
end
|
|
end
|
|
"dot","circle","squre":
|
|
begin
|
|
if tp="dot" then
|
|
dc.brush.color := mk.color;
|
|
if tp="squre" then pse := dc.draw_rect();
|
|
else
|
|
pse := dc.draw_ellipse();
|
|
for i,v in xys do
|
|
begin
|
|
rec := array(v[0]-a,v[1]-a,v[0]+b,v[1]+b);
|
|
pse.rect(rec).draw();
|
|
end
|
|
end
|
|
"plus":
|
|
begin
|
|
for i,v in xys do
|
|
begin
|
|
x := v[0];
|
|
y := v[1];
|
|
v1 := array(x-a,y);
|
|
v2 := array(x+b,y);
|
|
v3 := array(x,y-a);
|
|
v4 := array(x,y+b);
|
|
dc.moveto(v1);
|
|
dc.lineto(v2);
|
|
dc.moveto(v3);
|
|
dc.lineto(v4);
|
|
end
|
|
end
|
|
"star":
|
|
begin
|
|
mk.Style := "circle";
|
|
paint_marks(mk,dc,xys);
|
|
mk.Style := "plus";
|
|
paint_marks(mk,dc,xys);
|
|
mk.Style := "star";
|
|
end
|
|
"cross":
|
|
begin
|
|
for i,v in xys do
|
|
begin
|
|
x := v[0];
|
|
y := v[1];
|
|
v1 := array(x-a,y-a);
|
|
v2 := array(x+b,y+b);
|
|
v3 := array(x+b,y-a);
|
|
v4 := array(x-a,y+b);
|
|
dc.moveto(v1);
|
|
dc.lineto(v2);
|
|
dc.moveto(v3);
|
|
dc.lineto(v4);
|
|
end
|
|
end
|
|
"asterisk":
|
|
begin
|
|
mk.Style := "cross";
|
|
paint_marks(mk,dc,xys);
|
|
mk.Style := "plus";
|
|
paint_marks(mk,dc,xys);
|
|
mk.Style := "asterisk";
|
|
end
|
|
end ;
|
|
end
|
|
initialization
|
|
|
|
finalization
|
|
|
|
end. |