5478 lines
170 KiB
Plaintext
5478 lines
170 KiB
Plaintext
unit utvclgraphics;
|
||
interface
|
||
uses utslvclauxiliary;
|
||
//tsl绘图库
|
||
//20240126
|
||
//20240204 添加说明
|
||
//20240220 三维绘图功能
|
||
//20240614 添加消息
|
||
{
|
||
tg_const 常量类型,作为所有类型的基类,提供常量别名
|
||
tg_canvas 绘图画布对象,该对象以窗口中的canvas为父类,并增加了辅助函数
|
||
axesclip() 限定到坐标系区域
|
||
axesunclip() 取消坐标系区域限定
|
||
axesrec 坐标系的范围
|
||
tg_line_info 画笔线型信息
|
||
Style 线型 tgc_PS_DOT tgc_PS_DASH tgc_PS_NULL tgc_PS_SOLID tgc_PS_DASHDOT tgc_PS_DASHDOTDOT
|
||
size 线宽度,像素
|
||
color 线颜色
|
||
bkcolor 线型封闭后的背景
|
||
tg_font_info 系统信息
|
||
size 字号,宽度的像素
|
||
color 字颜色
|
||
bkcolor 背景色
|
||
tg_mark_info 点标记信息
|
||
size 标记大小,像素
|
||
color 线颜色
|
||
bkcolor 背景色
|
||
|
||
tg_base 做个绘图类基类,提供一些基础功能,以及层次关系
|
||
层次关系:
|
||
parent: 设置或者父节点
|
||
nodecount 获取子节点数量
|
||
GetNodeByIndex 通过序号获取子节点
|
||
set_node_index(nd,idx) 设置子节点的序号
|
||
基础功能:
|
||
markinfo 标记信息 tg_mark_info 类型
|
||
lineinfo 画笔信息 tg_line_info 类型
|
||
line_mode 是否画线
|
||
mark_mode 是否画点的标记
|
||
clip_state 是否裁剪区域
|
||
zoom_to_xyz(x,y,z,var _x,var _y) 通过坐标点计算画布点位置
|
||
xyz_to_zoom(x,y,z,var x_,var y_,var z_) 通过画布点计算坐标点
|
||
set_lineinfo_to_canvas(cvs,peninfo) 设置当前画笔信息到画布
|
||
set_fontinfo_to_canvas(cvs,info) 设置当前字体信息到画布
|
||
paint(cvs);virtual;该函数由tg_figure的管理者在适当时候发起,并送入tg_canvas对象
|
||
addEventListener(etype,fun(e),ifCapture) //添加消息处理
|
||
removeEventListener(etype,fun(e),ifCapture) //移除消息处理
|
||
dispatchEvent(evt) ;//分发消息
|
||
|
||
tg_figure //坐标容器类,可以在上面放坐标系,设置坐标系的位置信息
|
||
add_axes(axes) 添加坐标系
|
||
del_axes(axes) 删除坐标系
|
||
executecommand(cmd,p); //命令行执行
|
||
paint(cvs); 送入画布,绘制各个图形,如果是窗口,在onpaint消息中调用该函数
|
||
属性:
|
||
rec_getter :function() 返回画布区域 array(左上右下)
|
||
fresh_caller: function() //刷新回调
|
||
|
||
tg_axes 坐标系类型,作为绘图的基础载体,以及位置关系的基准
|
||
属性:
|
||
title 标题 tg_label 类型
|
||
y_label y轴标签 tg_label 类型
|
||
x_label x轴标签 tg_label 类型
|
||
axises(idx) 0,1,2 分别获取对应的x,y,z轴 ,tg_axis 类型
|
||
axes_reverse(idx) := tgc_on|tgc_off 坐标轴是否反向,默认正向
|
||
auto_ticks(idx) := tgc_on|tgc_off 设置坐标轴刻度自动计算
|
||
margins 空白,array(左上右下),设置上下左右空白,tg_figure区域的百分比
|
||
axes_bounds := array(左,上,右,下) 坐标系的范围;扣除margins边界,按比例
|
||
data_bounds(idx) 获取或者设置数据范围 array((x0,x1),(y0,y1),(z0,z1)) ,设置之后 对应轴的数据显示范围不会随着数据改变改变,如果要改变 data_bounds(idx) :=tgc_off
|
||
x_location 坐标轴方向,tgc_bottom tgc_top,tgc_middle ,tgc_origin
|
||
y_location 坐标轴方向,tgc_left tgc_right,tgc_middle ,tgc_origin
|
||
box = tgc_on | tgc_off 是否有边框
|
||
grid(idx) 背景网格线属性, tg_line_info 对象,size为0的时候网格线消失
|
||
squred :=tgc_on|tgc_off 长宽等比例,适合于饼图等
|
||
|
||
tg_axis 坐标轴,可以在坐标系中放置任意多个坐标轴
|
||
tics_direction 坐标轴方向 tgc_direct_asc(坐标轴指向的左手方向) , tgc_direct_desc
|
||
tics_style 刻度类型 tgc_tics_v (设置值) tgc_tics_r ([x0,x1,inteval])
|
||
tics_coord 刻度,根据tics_style 确定 [2,3,4,5,6,7] 计算 [start,end,interval]
|
||
ytics_coord 位置,设置在另一个方向的位置,相对坐标系的数据位置,array(x,y,z),为对应三维坐标,x,y,z中为非数字的值表示该坐标轴在对应维度上面
|
||
tics_segment 是否有轴线
|
||
tics_color 刻度线颜色
|
||
sub_tics 子刻度个数
|
||
tics_labels 刻度值对应的标签,一维字符串数组
|
||
|
||
tg_label 标签,以axes作为父节点
|
||
text 文本
|
||
position 坐标系位置
|
||
auto_position 自动位置,在坐标轴标签中使用
|
||
font_angle 设置角度
|
||
其他字体相关的通过 fontinfo设置
|
||
tg_graph_base 图基类
|
||
get_data_bounds();virtual; //获取数据边界
|
||
tg_graph 图类型
|
||
get_data_tips(); //获得数据提示对象
|
||
get_legend_size(var w,var h);virtual; 获取图例中的大小
|
||
paint_legend(cvs,rec);virtual; //绘制图例
|
||
get_graph_data_by_idx(idx); //通过数据序号获取数据
|
||
graph_data 绘图数据;
|
||
|
||
tg_Polyline 线图,以tg_graph为父类
|
||
closed 是否封闭的图像
|
||
polyline_style 线类型, tgc_LS_interpolated tgc_LS_bar tgc_LS_filled tgc_LS_arrowed tgc_LS_barplot tgc_LS_staircase
|
||
bar_width 柱状图类型时候的宽度
|
||
tg_legend 图例
|
||
location 位置 tgc_in_upper_left tgc_in_lower_left ..... tgc_by_coordinates
|
||
position 定位为tgc_by_coordinates,设置具体位置 array(x,y)
|
||
line_mode 边框线
|
||
links 关联的绘图,tg_graph 数组
|
||
text 文本内容,字符串数组
|
||
tg_tips 数据点提示,父节点为tg_graph 对象
|
||
text 文本数组
|
||
data_idx 绑定数据序号
|
||
tg_text 文本展示
|
||
text 字符串数组
|
||
font_angle 角度
|
||
data array(x,y,z) 相对于坐标系的位置
|
||
|
||
tg_WinControl:绘图展示窗口对象,管理了一个 tg_figure 对象,在paint消息的时候构造tg_canvas 对象并调用tg_figrue的paint函数实现图形的绘制
|
||
其仅仅作为一个案例,用户可以按照其原理构造自己的画布对象,驱动绘制,得到图形
|
||
tg_picture: 图片容器,可以将图片保存为png
|
||
|
||
消息对象
|
||
tg_evt 基类
|
||
create(typename,pms) //构造函数
|
||
bubbles //是否冒泡,只读
|
||
currentTarget //当前绑定的对象,只读
|
||
target //目标对象,只读
|
||
stoppropagationed 否//已经调用 stoppropagation,只读
|
||
stopImmediatePropagationed //是否已经调用 stopImmediatePropagation,只读
|
||
eventPhase //只读,1,捕获,2到达目标,3,冒泡
|
||
timeStamp //只读,加载完成到现在的时间
|
||
eventtype //只读类型
|
||
isTrusted //true表示用户触发,false表示代码触发
|
||
init_params //初始化参数 数组
|
||
tg_evt_mouse
|
||
cvsx ,cvsy //画布位置
|
||
double 是否双击
|
||
button 左右,中 按键
|
||
ctrl ,shift //功能按键
|
||
tg_evt_custom
|
||
detail
|
||
目前提供 evt_mouse_up ,evt_mouse_down evt_mouse_move 三个消息
|
||
消息传播方式采用类似html对象的捕获和冒泡方式
|
||
捕获阶段,从figure对象向下一直传递到当目标对象
|
||
冒泡阶段,从目标对象向上传递到figure对象
|
||
}
|
||
{
|
||
//////////////////保存绘制的图片到png//////////////////////////
|
||
uses utvclgraphics;
|
||
fg := new tg_picture(800,800);
|
||
//////////设置坐标轴属性////////////////////////
|
||
axs := new tg_axes();
|
||
axs.box := false;
|
||
axs.figure := fg;
|
||
axs.title.text := "hello pie ";
|
||
axs.axises(1).visible:=false;
|
||
axs.axises(0).visible:= false;
|
||
axs.data_bounds(0) := array(-0.1,2.1);
|
||
axs.data_bounds(1) := array(-0.1,2.1);
|
||
axs.data_bounds(2) := array(-0.5,0.5);
|
||
args := array(
|
||
(pi()/4,pi()/3,0x0000ff),
|
||
(pi()/3,pi()/2,0x00ff00),
|
||
(pi()/2,pi()*3/2,0xff0000),
|
||
(pi()*3/2,pi()*9/4,0xff00ff)
|
||
|
||
);
|
||
prominentidx := 0; //凸显的块
|
||
prominentrate := 0.1; //凸显的块
|
||
for i,v in args do
|
||
begin
|
||
line := new tg_Polyline();
|
||
line.polyline_style := line.tgc_LS_filled;
|
||
line.closed := true;
|
||
c := (i=2)?1.1:1;
|
||
line.graph_data := 1+get_pie_lines(v[0],v[1],i=prominentidx,prominentrate);
|
||
line.lineinfo.bkcolor := v[2];
|
||
line.parent := axs;
|
||
end
|
||
fg.save_png(%% D:\test\ppt2.png%%); //保存
|
||
function get_pie_lines(arg1,arg2,prominent,prominentrate);
|
||
begin
|
||
stp := pi()/180;
|
||
d := 1;
|
||
r := array();
|
||
r[0] := array(0,0);
|
||
idx := 1;
|
||
for i:= arg1+(prominent?stp:0) to arg2-(prominent?stp:0) step stp do
|
||
begin
|
||
r[idx++] := array(sin(i),cos(i));
|
||
end
|
||
r[idx] :=array(0,0);
|
||
if prominent then
|
||
begin
|
||
rx := r[integer(idx/2)]*prominentrate;
|
||
for i := 0 to idx do
|
||
begin
|
||
r[i]+=rx;
|
||
end
|
||
end
|
||
return r;
|
||
end
|
||
//////////////////线图范例//////////////////////////
|
||
uses tslvcl,utvclgraphics;
|
||
app := initializeapplication();
|
||
app.createform(class(tfm),fm);
|
||
fm.show();
|
||
app.run();
|
||
type tfm = class(tvcform)
|
||
function create(aowner);
|
||
begin
|
||
inherited;
|
||
Caption := "line";
|
||
fg := new tg_WinControl(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 := line.tgc_mks_pentagram;
|
||
line.polyline_style := line.tgc_LS_staircase;
|
||
d := array();
|
||
idx := 0;
|
||
for i:= -pi() to pi() step 0.2 do
|
||
begin
|
||
d[idx] := array(i,sin(i));
|
||
idx++;
|
||
end
|
||
line.graph_data := d;
|
||
line.parent := axs;
|
||
end
|
||
fg;
|
||
end
|
||
//////////////////表面图范例///////////////////////////////////////
|
||
uses tslvcl,utvclgraphics;
|
||
app := initializeapplication();
|
||
app.createform(class(tfm),fm);
|
||
fm.show();
|
||
app.run();
|
||
type tfm = class(tvcform)
|
||
function create(aowner);
|
||
begin
|
||
inherited;
|
||
Caption := "surface";
|
||
fg := new tg_WinControl(self);
|
||
fg.Caption := "hello1";
|
||
fg.parent := self;
|
||
fg.Align := alClient;
|
||
//////////设置坐标轴属性////////////////////////
|
||
axs := new tg_axes();
|
||
t := pi()*60/180;
|
||
a := pi()*70/180;
|
||
axs.set_trans(a,t);
|
||
axs.box := true;
|
||
axs.figure := fg.figure;
|
||
axs.title.text := "你好 surface ";
|
||
axs.title.fontinfo.size := 15;
|
||
axs.title.fontinfo.color := 0xff0000;
|
||
axs.axises(1).tics_color := 0x0000ff;
|
||
axs.axises(1).fontinfo.size := 8;
|
||
axs.axises(1).lineinfo.color := 0x00ff00;
|
||
sf := new tg_my_surf();
|
||
sf.lineinfo.color := 0x0000ff;
|
||
sf.lineinfo.style := sf.tgc_BS_SOLID;
|
||
sf.graph_data := get_surf_data();
|
||
sf.parent := axs;
|
||
return ;
|
||
end
|
||
fg;
|
||
function c_3(x,y);
|
||
begin
|
||
return X - 3*X*sin(X)*cos(Y-4) ;
|
||
end
|
||
function get_surf_data();
|
||
begin
|
||
st1 := (12)/50;
|
||
vs1 := array(-10,st1)->2;
|
||
st2 := 10/50;
|
||
vs2 := array(-5,st2)->5;
|
||
d := array();
|
||
dlen := 0;
|
||
for i,vi in vs1 do
|
||
begin
|
||
for j,vj in vs2 do
|
||
begin
|
||
r := array();
|
||
x0 := vi;
|
||
y0 := vj;
|
||
x1 := vi+st1;
|
||
y1 := vj+st2;
|
||
v1 := array(x0,y0,c_3(x0,y0));
|
||
v2 := array(x1,y0,c_3(x1,y0));
|
||
v3 := array(x1,y1,c_3(x1,y1));
|
||
v4 := array(x0,y1,c_3(x0,y1));
|
||
d[dlen++] := array(v1,v2,v3,v4,v1);
|
||
end
|
||
end
|
||
return d;
|
||
end
|
||
end
|
||
type tg_my_surf = class(tg_graph) //绘图对象,包括数据,提示等内容
|
||
function create(pms);
|
||
begin
|
||
inherited;
|
||
lineinfo.bkcolor := 0x00f0f0;
|
||
end
|
||
function get_data_bounds();override;
|
||
begin
|
||
d := graph_data;
|
||
r := array((inf,-inf),(inf,-inf),(inf,-inf));
|
||
for i ,v in d do
|
||
begin
|
||
for j,vj in v do
|
||
begin
|
||
for k := 0 to 2 do
|
||
begin
|
||
r[k,0] := min(r[k,0],vj[k]);
|
||
r[k,1] := max(r[k,1],vj[k]);
|
||
end
|
||
end
|
||
end
|
||
for k := 0 to 2 do
|
||
begin
|
||
r[k,0] -= abs(r[k,0]*0.1);
|
||
r[k,1] += abs(r[k,1]*0.1);
|
||
end
|
||
return r;
|
||
end
|
||
function paint_legend(cvs,rec);virtual; //绘制图例
|
||
begin
|
||
end
|
||
function paint(cvs);override;
|
||
begin
|
||
d := graph_data;
|
||
cvs.axesclip();
|
||
set_lineinfo_to_canvas(cvs);
|
||
dp := cvs.draw_polygon();
|
||
bx := axes.zoom_box;
|
||
//cvs.pen.color := 0xff0000;
|
||
for i,v in d do
|
||
begin
|
||
ps := array();
|
||
flg := false;
|
||
zz := 0;
|
||
for j,vj in v do
|
||
begin
|
||
if vj[0]<bx[0,0] or vj[1]<bx[1,0] or vj[2]<bx[2,0] or vj[0]>bx[0,1] or vj[1]>bx[1,1] or vj[2]>bx[2,1] then
|
||
begin
|
||
flg := true;
|
||
break;
|
||
end
|
||
//zz:=vj[2];
|
||
zoom_to_xyz(vj[0],vj[1],vj[2],_x,_y,_z);
|
||
zz := vj[2];
|
||
ps[j] := array(_x,_y);
|
||
end
|
||
if flg then continue;
|
||
if zz>0 then cvs.brush.color := 0x00ff00;
|
||
else
|
||
cvs.brush.color := 0xff0000;
|
||
dp.points(ps).requiregdi().draw();
|
||
end
|
||
cvs.axesunclip();
|
||
end
|
||
end
|
||
//////////////////饼图范例///////////////////////////////////////////
|
||
uses tslvcl,utvclgraphics;
|
||
app := initializeapplication();
|
||
app.createform(class(tfm),fm);
|
||
fm.show();
|
||
app.run();
|
||
type tfm = class(tvcform)
|
||
function create(aowner);
|
||
begin
|
||
inherited;
|
||
caption := "pie";
|
||
width := 800;
|
||
Height := 800;
|
||
fg := new tg_WinControl(self);
|
||
fg.Caption := "hello1";
|
||
fg.parent := self;
|
||
fg.Align := alClient;
|
||
//////////设置坐标轴属性////////////////////////
|
||
axs := new tg_axes();
|
||
axs.box := true;
|
||
axs.figure := fg.figure;
|
||
axs.title.text := "hello pie ";
|
||
axs.axises(1).tics_color := 0x0000ff;
|
||
axs.axises(1).fontinfo.size := 8;
|
||
axs.data_bounds(0) := array(-0.1,2.1);
|
||
axs.data_bounds(1) := array(-0.1,2.1);
|
||
axs.data_bounds(2) := array(-0.5,0.5);
|
||
args := array(
|
||
(pi()/4,pi()/3,0x0000ff),
|
||
(pi()/3,pi()/2,0x00ff00),
|
||
(pi()/2,pi()*3/2,0xff0000),
|
||
(pi()*3/2,pi()*9/4,0xff00ff)
|
||
|
||
);
|
||
prominentidx := 0; //凸显的块
|
||
prominentrate := 0.1; //凸显的块
|
||
for i,v in args do
|
||
begin
|
||
line := new tg_Polyline();
|
||
line.polyline_style := line.tgc_LS_filled;
|
||
line.closed := true;
|
||
c := (i=2)?1.1:1;
|
||
line.graph_data := 1+get_pie_lines(v[0],v[1],i=prominentidx,prominentrate);
|
||
line.lineinfo.bkcolor := v[2];
|
||
line.parent := axs;
|
||
end
|
||
end
|
||
function get_pie_lines(arg1,arg2,prominent,prominentrate);
|
||
begin
|
||
stp := pi()/180;
|
||
d := 1;
|
||
r := array();
|
||
r[0] := array(0,0);
|
||
idx := 1;
|
||
for i:= arg1+(prominent?stp:0) to arg2-(prominent?stp:0) step stp do
|
||
begin
|
||
r[idx++] := array(sin(i),cos(i));
|
||
end
|
||
r[idx] :=array(0,0);
|
||
if prominent then
|
||
begin
|
||
rx := r[integer(idx/2)]*prominentrate;
|
||
for i := 0 to idx do
|
||
begin
|
||
r[i]+=rx;
|
||
end
|
||
end
|
||
return r;
|
||
end
|
||
fg;
|
||
end
|
||
///////////////////////////消息处理///////////////////////////////////////////////////
|
||
uses tslvcl,utvclgraphics;
|
||
app := initializeapplication();
|
||
app.createform(class(tfm),fm);
|
||
fm.show();
|
||
app.run();
|
||
type tfm = class(tvcform)
|
||
function create(aowner);
|
||
begin
|
||
inherited;
|
||
fgwnd := new tg_WinControl(self);
|
||
fgwnd.Caption := "hello event";
|
||
fgwnd.parent := self;
|
||
fgwnd.Align := alClient;
|
||
fg := fgwnd.figure;
|
||
axs := new tg_axes();
|
||
axs.figure := fg;
|
||
axs.title.text := "你好 event ";
|
||
line := new tg_Polyline();
|
||
line.parent := axs;
|
||
line.lineinfo.Width := 3;
|
||
line.lineinfo.bkcolor := 0xff00f0;
|
||
line.lineinfo.color := 0xff0000;
|
||
line.markinfo.bkcolor := 0x00ff00;
|
||
line.markinfo.color := 0x0000ff;
|
||
line.line_mode := 1;
|
||
line.markinfo.size := 20;
|
||
line.mark_mode := true;
|
||
line.markinfo.style := line.tgc_mks_pentagram;
|
||
line.polyline_style := line.tgc_LS_interpolated;//"bar";
|
||
d2 := array();
|
||
idx := 0;
|
||
for i:= -pi() to pi() step 0.3 do
|
||
begin
|
||
d2[idx++] := array(i,sin(i+pi()/2));
|
||
end
|
||
line.graph_data := d2;
|
||
|
||
gtx := new tg_text();
|
||
gtx.font_angle := pi()/4;
|
||
//////////////命中处理///////////////
|
||
gtx.onhit_at := function(o,d)begin
|
||
x := d["cvsx"];
|
||
y := d["cvsy"];
|
||
return o.ExecuteCommand("point_in_text",array(x,y));
|
||
end
|
||
gtx.lineinfo.bkcolor := 0x00ff00;
|
||
gtx.parent :=line;
|
||
gtx.text := array("按住鼠标左键","移动我");
|
||
gtx.data := array(0.3,0.2);
|
||
//处理鼠标按下
|
||
gtx.addEventListener("mouse_down",function(e)begin
|
||
fdragtext := e.target;
|
||
ftextinitpos := fdragtext.data;
|
||
x := e.cvsx;y := e.cvsy;
|
||
fdragtext.xyz_to_zoom(x,y,0,x1,y1);
|
||
fmousedownpos := array(x1,y1);
|
||
end);
|
||
//移动标签
|
||
fg.addEventListener("mouse_move",function(e)begin
|
||
if fdragtext then
|
||
begin
|
||
e.stoppropagation();
|
||
x := e.cvsx;
|
||
y := e.cvsy;
|
||
fdragtext.xyz_to_zoom(x,y,0,x1,y1);
|
||
dxdata := ftextinitpos+ array(x1-fmousedownpos[0],y1-fmousedownpos[1]);
|
||
fdragtext.data := dxdata;
|
||
end
|
||
end ,true);
|
||
//处理鼠标松开
|
||
fg.addEventListener("mouse_up",function(e)begin
|
||
if fdragtext then
|
||
begin
|
||
e.stoppropagation();
|
||
fdragtext := nil;
|
||
end
|
||
end );
|
||
//构造提示标签
|
||
fmovetip := new tg_tips();
|
||
fmovetip.Visible := false;
|
||
fmovetip.clip_state := 0;
|
||
fmovetip.parent := line;
|
||
fmovetip.data_idx := 5;
|
||
fmovetip.fontinfo.size := 12;
|
||
fmovetip.box_mode := true;//false;
|
||
fmovetip.fontinfo.color := 0xff00ff;
|
||
//设置提示数据点
|
||
line.onhit_at := function(o,d)begin
|
||
x := d["cvsx"];
|
||
y := d["cvsy"];
|
||
r := o.ExecuteCommand("hit_point",array(x,y));
|
||
fhitidx := r;
|
||
return r>=0;
|
||
end
|
||
line.addEventListener("mouse_out",function(e)begin
|
||
if e.eventPhase<>2 then return ;
|
||
fmovetip.Visible := false;
|
||
e.stoppropagation();
|
||
end,true);
|
||
line.addEventListener("mouse_move",function(e)
|
||
begin
|
||
if e.eventPhase<>2 then return ;
|
||
e.stoppropagation();
|
||
x := e.cvsx;
|
||
y := e.cvsy;
|
||
if fhitidx>=0 then
|
||
begin
|
||
fmovetip.Visible := true;
|
||
return fmovetip.data_idx := fhitidx;
|
||
end else fmovetip.Visible := false;
|
||
end,true);
|
||
end
|
||
fhitidx;
|
||
fdragtext;
|
||
ftextinitpos;
|
||
fmousedownpos;
|
||
fmovetip;
|
||
fgwnd;
|
||
fg;
|
||
end
|
||
}
|
||
function point_in_rgn(p,rgn_,method); //判断点是否在区域中
|
||
function graph_paint_lines(cvs,linestyle,xys,closed,ifo); //根据给定点绘制线
|
||
function graph_paint_points(mk,cvs,xys); //根据点信息绘制点
|
||
function graph_paint_boolen_value(n,v);
|
||
function graph_paint_rec_to_points(rec);
|
||
function r_2_a(arg);
|
||
function a_2_r(arg);
|
||
function d2angle(v1,v2);
|
||
type tg_picture = class(tcustommemcanvas,tg_figure_container) //绘图对象
|
||
uses utslvclgdi;
|
||
function create(w,h);
|
||
begin
|
||
class(tcustommemcanvas).create(w,h);
|
||
class(tg_figure_container).create();
|
||
frect := array(0,0,w,h);
|
||
ffigure.rec_getter := function()begin
|
||
return frect;
|
||
end
|
||
end
|
||
function save_png(fn);
|
||
begin
|
||
paint();
|
||
savepng(fn);
|
||
end
|
||
private
|
||
frect;
|
||
function paint(); //绘制
|
||
begin
|
||
brush.color := 0xffffff;
|
||
FillRect(frect);
|
||
ffigure.paint_pre(self);
|
||
end
|
||
end
|
||
{
|
||
type tg_metafile = class(tcustommetacanvas,tg_figure_container) //绘图对象
|
||
uses utslvclgdi;
|
||
function create(fn,w,h);
|
||
begin
|
||
class(tcustommetacanvas).create(fn,w,h);
|
||
class(tg_figure_container).create();
|
||
frect := array(0,0,w,h);
|
||
ffigure.rec_getter := function()begin
|
||
return frect;
|
||
end
|
||
end
|
||
function save_wmf(fn);
|
||
begin
|
||
paint();
|
||
//savepng(fn);
|
||
end
|
||
private
|
||
frect;
|
||
function paint(); //绘制
|
||
begin
|
||
brush.color := 0xffffff;
|
||
FillRect(frect);
|
||
ffigure.paint_pre(self);
|
||
end
|
||
end }
|
||
//tcustommetacanvas
|
||
type tg_WinControl = class(tcustomcontrol,tg_figure_container) //绘图窗口
|
||
function create(AOwner);
|
||
begin
|
||
class(tcustomcontrol).create(AOwner);
|
||
width := 300;
|
||
height := 300;
|
||
class(tg_figure_container).create();
|
||
fg_timer := new unit(utslvclstdctl).tcustomtimer(self);
|
||
fg_timer.Interval := 300;
|
||
fg_timer.Ontimer := thisfunction(figure_need_fresh);
|
||
ffigureprepared := false;
|
||
ffigure.rec_getter := function()begin
|
||
return clientrect;
|
||
end
|
||
ffigure.fresh_caller := thisfunction(flushfigure);
|
||
end
|
||
function flushfigure();
|
||
begin
|
||
if not HandleAllocated() then return ;
|
||
if not ffigureprepared then
|
||
begin
|
||
return ;
|
||
end
|
||
if f_validate_doing then
|
||
begin
|
||
return ;
|
||
end
|
||
fg_timer.start();
|
||
end
|
||
function paint();override; //绘制
|
||
begin
|
||
fg_timer.stop();
|
||
cvs := canvas;
|
||
f_validate_doing := true;
|
||
ffigureprepared := false;
|
||
ffigure.paint_pre(cvs);
|
||
ffigureprepared := true;
|
||
f_validate_doing := false;
|
||
end
|
||
function DestroyHandle();override;
|
||
begin
|
||
ffigureprepared := false;
|
||
inherited;
|
||
end
|
||
function MouseUp(o,e);override;
|
||
begin
|
||
if ffigure then
|
||
begin
|
||
d := e_2_array(e,evt_mouse_up);
|
||
if ffigure.executecommand(evt_mouse_up,d)=1 then e.skip := true;
|
||
end
|
||
end
|
||
function MouseDown(o,e);override;
|
||
begin
|
||
if ffigure then
|
||
begin
|
||
d := e_2_array(e,evt_mouse_down);
|
||
if ffigure.executecommand(evt_mouse_down,d)=1 then e.skip := true;
|
||
end
|
||
//echo "\r\n",functionname(),tostn(array(xy,bt,sh));
|
||
end
|
||
function MouseMove(o,e);override;
|
||
begin
|
||
if ffigure then
|
||
begin
|
||
fmovecnt++;
|
||
if fmovecnt>4 then fmovecnt := 0;
|
||
if fmovecnt<>2 then return ;
|
||
d := e_2_array(e,evt_mouse_move);
|
||
if ffigure.executecommand(evt_mouse_move,d)=1 then e.skip := true;
|
||
end
|
||
end
|
||
function DoMouseWheel(o,e);override;
|
||
begin
|
||
if ffigure then
|
||
begin
|
||
p := ScreenToClient(e.xpos,e.ypos);
|
||
st := e.shiftstate();
|
||
sft := 0x0 in st;
|
||
sctl := 0x2 in st;
|
||
d := array("type":evt_mouse_wheel,"cvsx":p[0],"cvsy":p[1],"delta":e.delta,"shift":sft,"ctrl":sctl,);
|
||
ffigure.executecommand(evt_mouse_wheel,d);
|
||
e.skip := true;
|
||
end
|
||
end
|
||
function DoWMSIZE(o,e);override;
|
||
begin
|
||
inherited;
|
||
if ffigure then
|
||
ffigure.executecommand(cmd_figure_changed);
|
||
end
|
||
function Recycling();override;
|
||
begin
|
||
ffigure:=nil;
|
||
inherited;
|
||
end
|
||
private
|
||
function figure_need_fresh(o,e); //定时刷新
|
||
begin
|
||
o.stop();
|
||
if not ffigureprepared then return ; //没有准备好
|
||
if f_validate_doing then return;
|
||
InvalidateRect(nil,false);
|
||
|
||
end
|
||
function e_2_array(e,tp);
|
||
begin
|
||
d := array();
|
||
st := e.shiftstate();
|
||
sft := 0x0 in st;
|
||
sctl := 0x2 in st;
|
||
d := array(
|
||
"type":tp,
|
||
"cvsx":e.xpos,
|
||
"cvsy":e.ypos,
|
||
"shift":sft,
|
||
"ctrl":sctl,
|
||
"button":e.button(),
|
||
);
|
||
return d;
|
||
end
|
||
private
|
||
fmovecnt;
|
||
fg_timer;
|
||
f_validate_doing;
|
||
ffigureprepared;
|
||
end
|
||
type tg_figure_container = class(tg_const) //figure的容器
|
||
function create();
|
||
begin
|
||
ffigure := new tg_figure();
|
||
end
|
||
property figure read ffigure;
|
||
protected
|
||
ffigure;
|
||
end
|
||
type tg_figure = class(tg_evet_conainter) //绘图容器
|
||
function create();
|
||
begin
|
||
inherited;
|
||
faxeses := new tnumindexarray();
|
||
end
|
||
function paint_pre(cvs); //绘制
|
||
begin
|
||
Fpainting := true;
|
||
cvs := new tg_canvas(cvs.Handle,self);
|
||
for i,v in faxeses.data do
|
||
begin
|
||
v.paint_pre(cvs);
|
||
end
|
||
Fpainting := false;
|
||
end
|
||
function executecommand(cmd,p);
|
||
begin
|
||
case cmd of
|
||
"figure_need_fresh":
|
||
begin
|
||
fresh();
|
||
return ;
|
||
end
|
||
evt_mouse_wheel:
|
||
begin
|
||
r := cmd_mouse_event(evt_mouse_wheel,p);
|
||
if not r then
|
||
begin
|
||
r := executecommand(cmd_zoom_inc,p);
|
||
end
|
||
return r;
|
||
end
|
||
cmd_zoom_inc:
|
||
begin
|
||
for i,v in faxeses.data do
|
||
begin
|
||
if 1 = v.executecommand(cmd_zoom_inc,p) then continue;
|
||
else r := true; //经过了默认
|
||
end
|
||
return r;
|
||
end
|
||
evt_mouse_move:
|
||
begin
|
||
return cmd_mouse_event(evt_mouse_move,p);
|
||
end
|
||
evt_mouse_up:
|
||
begin
|
||
return cmd_mouse_event(evt_mouse_up,p);
|
||
end
|
||
evt_mouse_down:
|
||
begin
|
||
return cmd_mouse_event(evt_mouse_down,p);
|
||
end
|
||
cmd_figure_changed:
|
||
begin
|
||
for i,v in faxeses.data do
|
||
begin
|
||
v.executecommand(cmd_figure_changed);
|
||
end
|
||
end
|
||
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 fresh(); ///刷新////////////////////////
|
||
begin
|
||
if Fpainting then return ;
|
||
if ffresh_caller then call(ffresh_caller);
|
||
end
|
||
function rect(); ///获取区域///////////////////////////////
|
||
begin
|
||
r := array(0,0,200,200);
|
||
if frect_getter then r := call(frect_getter);
|
||
return r;
|
||
end
|
||
property rec_getter read frect_getter write frect_getter; //区域获取
|
||
property fresh_caller read ffresh_caller write ffresh_caller; //刷新回调
|
||
public
|
||
function dispatchEvent(evt,nd);
|
||
begin
|
||
bs := evt.bubbles;
|
||
if ifarray(nd) then
|
||
begin
|
||
nds := nd;
|
||
end else
|
||
begin
|
||
nds := array();
|
||
p := nd;
|
||
while p do
|
||
begin
|
||
nds[idx] := p;
|
||
idx++;
|
||
p := p.parent;
|
||
end
|
||
end
|
||
tg := nds[0];
|
||
nds[length(nds)] := self(true);
|
||
for i := length(nds)-1 downto 0 do
|
||
begin
|
||
it := nds[i];
|
||
ph := (i=0)?2:1;
|
||
d := array("eventphase":ph,
|
||
"target":tg,
|
||
"currenttarget":it,
|
||
);
|
||
e := evt.clone(d);
|
||
it.dealevent(e,true);
|
||
if e.stoppropagationed then
|
||
begin
|
||
evt.stoppropagation();
|
||
return true;
|
||
end
|
||
end
|
||
if not bs then return true;
|
||
for i := 0 to length(nds)-1 do
|
||
begin
|
||
it := nds[i];
|
||
ph := (i=0)?2:3;
|
||
d := array("eventphase":ph,
|
||
"target":tg,
|
||
"currenttarget":it,
|
||
);
|
||
e := evt.clone(d);
|
||
it.dealevent(e);
|
||
if e.stoppropagationed then
|
||
begin
|
||
evt.stoppropagation();
|
||
return true;
|
||
end
|
||
end
|
||
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
|
||
function inverse_array(d);
|
||
begin
|
||
r := array();
|
||
len := length(d)-1;
|
||
for i,v in d do
|
||
begin
|
||
r[len-i] := v;
|
||
end
|
||
return r;
|
||
end
|
||
function cmd_mouse_event(evtname,p);
|
||
begin
|
||
d := p;
|
||
for i,v in inverse_array(faxeses.data) do
|
||
begin
|
||
nds := node_hit_list(v,d);
|
||
if nds then
|
||
begin
|
||
break;
|
||
end
|
||
end
|
||
if not ifarray( nds ) then return ;
|
||
d["istrusted"] := true;
|
||
d["bubbles"] := true;
|
||
case evtname of
|
||
evt_mouse_move :
|
||
begin
|
||
ninnode := nds[0];
|
||
if ninnode then
|
||
begin
|
||
if fMouseOnOBJ<> ninnode then //鼠标进入不同的控件
|
||
begin
|
||
if fMouseOnOBJ then //旧控件 处理move out
|
||
begin
|
||
onds := array();
|
||
nnd := fMouseOnOBJ;
|
||
while nnd do
|
||
begin
|
||
onds[length(onds)] := nnd;
|
||
nnd := nnd.parent;
|
||
end
|
||
evt := new tg_evt_mouse(evt_mouse_out,d);
|
||
dispatchEvent(evt,onds);
|
||
end
|
||
fMouseOnOBJ := ninnode;
|
||
evt := new tg_evt_mouse(evt_mouse_in,d); //处理mouse in
|
||
dispatchEvent(evt,nds);
|
||
end
|
||
end else
|
||
begin
|
||
end
|
||
end
|
||
end
|
||
evt := new tg_evt_mouse(evtname,d);
|
||
dispatchEvent(evt,nds);
|
||
return evt.stoppropagationed or evt.defaultPrevented; //是否停止
|
||
end
|
||
private
|
||
[weakref] frect_getter;
|
||
[weakref] ffresh_caller;
|
||
[weakref] fMouseOnOBJ;
|
||
fwilladdaxs;
|
||
fwilldelaxs;
|
||
faxeses;
|
||
end
|
||
type tg_axes = class(tg_base) //坐标系
|
||
private
|
||
[weakref]fFigure;
|
||
///////////////坐标辅助计算/////////////////////////
|
||
p_left;
|
||
p_top;
|
||
p_width;
|
||
p_height;
|
||
f_changed;
|
||
static const c_g_data_changed=1;
|
||
static const c_g_paint_rect=2;
|
||
static const c_g_data_zoombox=4;
|
||
static const c_g_rote_changed=8;
|
||
///////////////////////////////////////////
|
||
public //zoom-xyz
|
||
function executecommand(cmd,pm);override;
|
||
begin
|
||
ochanged := f_changed;
|
||
case cmd of
|
||
"title_rgn": return ftitle.executecommand("label_rgn");
|
||
"x_label_rgn": return (fx_label.visible=tgc_on)?faxes_objects[0].executecommand("label_rgn"):nil; //标签区域
|
||
"y_label_rgn": return (fy_label.visible=tgc_on)?faxes_objects[1].executecommand("label_rgn"):nil;
|
||
"z_label_rgn": return (fz_label.visible=tgc_on)?faxes_objects[2].executecommand("label_rgn"):nil;
|
||
"x_tics_recs": return (fx_label.visible=tgc_on)?faxes_objects[0].executecommand("tics_recs"):nil; //哭的标签区域
|
||
"y_tics_recs": return (fy_label.visible=tgc_on)?faxes_objects[1].executecommand("tics_recs"):nil;
|
||
"z_tics_recs": return (fz_label.visible=tgc_on)?faxes_objects[2].executecommand("tics_recs"):nil;
|
||
cmd_zoom_inc:
|
||
begin
|
||
if not ifarray(pm) then return ;
|
||
p0 := pm["cvsx"];
|
||
p1 := pm["cvsy"];
|
||
for i := 0 to 2 do
|
||
begin
|
||
a0 := fzoom_box[i,0];
|
||
b0 := fzoom_box[i,1];
|
||
if not xy_in_paint_rect(p0,p1) then
|
||
begin
|
||
return true;
|
||
//continue;
|
||
end
|
||
if not xyz_to_zoom(p0,p1,fzoom_box[2,0],x,y,z) then continue ;
|
||
dx := ((pm["delta"]>0)?(1.05):(1/1.05));
|
||
if not zoom_bound_op(a0,b0,dx,array(x,y,z)[i],a,b) then continue ;
|
||
rt := 1.1;
|
||
cg := 0;
|
||
if a<fdata_bounds[i,0]*rt then
|
||
begin
|
||
cg++;
|
||
a := fdata_bounds[i,0]*rt ;
|
||
end
|
||
if b>fdata_bounds[i,1]*rt then
|
||
begin
|
||
cg++;
|
||
b := fdata_bounds[i,1]*rt;
|
||
end
|
||
if cg=2 then continue;
|
||
fzoom_box[i] := array(a,b);
|
||
f_changed .|= c_g_data_zoombox;
|
||
end
|
||
end
|
||
cmd_node_add_in:
|
||
begin
|
||
if pm is class(tg_graph_base) then
|
||
begin
|
||
f_changed .|= c_g_data_changed;
|
||
f_changed .|= c_g_data_zoombox;
|
||
end
|
||
end
|
||
cmd_figure_changed:
|
||
begin
|
||
f_changed .|= c_g_paint_rect;
|
||
f_changed .|= c_g_data_zoombox;
|
||
end
|
||
cmd_data_changed:
|
||
begin
|
||
f_changed .|= c_g_data_changed;
|
||
f_changed .|= c_g_data_zoombox;
|
||
end
|
||
end ;
|
||
if ochanged<>f_changed then prop_changed(cmd_data_changed,f_changed);
|
||
end
|
||
|
||
function axes_mapping(x,y,z,_x,_y);override;//坐标系相对位置到画布
|
||
begin
|
||
if not(fFigure ) then return false;
|
||
_x := p_left+p_width*x ;
|
||
_y := p_top +p_height*y;
|
||
return true;
|
||
end
|
||
function axes_unmapping(x,y,_x,_y,_z);override;//画布位置到坐标系相对位置
|
||
begin
|
||
if not(fFigure ) then return false;
|
||
_x := (x-p_left)/p_width;
|
||
_y := (y-p_top)/p_height;
|
||
return true;
|
||
end
|
||
function zoom_to_xyz(x,y,zi,_x,_y,_z); //视图到xyz
|
||
begin
|
||
if not(fFigure ) then return false;
|
||
/////////////处理z轴的默认值/////nil,-inf 为最小值;inf为最大值;nan为中间值//////////////////////////////
|
||
z := zi;
|
||
if ifnil(zi) then
|
||
begin
|
||
z := fzoom_box[2,0];
|
||
end
|
||
else
|
||
if isinfinite(zi) then
|
||
begin
|
||
if zi>0 then
|
||
z := fzoom_box[2,1];
|
||
else z := fzoom_box[2,0];
|
||
end else
|
||
if isnan(zi) then z := (fzoom_box[2,0]+fzoom_box[2,1])/2;
|
||
/////////////////////////////////////////////////////////////////
|
||
if faxes_reverse[0]=tgc_on then x0 := fcoordinate_sizes[0]/2-(x-fzoom_bounds[0,0])/fzoom_coordinate_rates[0];
|
||
else
|
||
x0 := (x-fzoom_bounds[0,0])/fzoom_coordinate_rates[0] -fcoordinate_sizes[0]/2;
|
||
if faxes_reverse[1]=tgc_on then y0 := fcoordinate_sizes[1]/2-(y-fzoom_bounds[1,0])/fzoom_coordinate_rates[1];
|
||
else y0 := (y-fzoom_bounds[1,0])/fzoom_coordinate_rates[1] -fcoordinate_sizes[1]/2;
|
||
if faxes_reverse[2]=tgc_on then z0 := fcoordinate_sizes[2]/2-(z-fzoom_bounds[2,0])/fzoom_coordinate_rates[2];
|
||
else z0 := (z-fzoom_bounds[2,0])/fzoom_coordinate_rates[2] -fcoordinate_sizes[2]/2;
|
||
transxyz(x0,y0,z0,_x,_y,_z);
|
||
_x +=fbounds_center[0];
|
||
_y +=fbounds_center[1];
|
||
_z +=fbounds_center[2];
|
||
return true;
|
||
end
|
||
function xyz_to_zoom(x,y,z,_x,_y,_z); //xyz到视图
|
||
begin
|
||
if not(fFigure ) then return false;
|
||
x1 := x;y1 := y;z1 := z;
|
||
x1 -=fbounds_center[0];
|
||
y1 -=fbounds_center[1];
|
||
z1 -=fbounds_center[2];
|
||
untransxyz(x1,y1,z1,x0,y0,z0);
|
||
if faxes_reverse[0]=tgc_on then
|
||
begin
|
||
_x := (fcoordinate_sizes[0]/2-x0)*fzoom_coordinate_rates[0]+fzoom_bounds[0,0];
|
||
end
|
||
else
|
||
begin
|
||
_x := (x0+fcoordinate_sizes[0]/2)*fzoom_coordinate_rates[0]+fzoom_bounds[0,0];
|
||
end
|
||
if faxes_reverse[1]=tgc_on then
|
||
begin
|
||
_y := (fcoordinate_sizes[1]/2-y0)*fzoom_coordinate_rates[1]+fzoom_bounds[1,0];
|
||
end
|
||
else
|
||
begin
|
||
_y := (y0+fcoordinate_sizes[1]/2)*fzoom_coordinate_rates[1]+fzoom_bounds[1,0];
|
||
end
|
||
if faxes_reverse[2]=tgc_on then
|
||
begin
|
||
_z := (fcoordinate_sizes[2]/2-z0)*fzoom_coordinate_rates[2]+fzoom_bounds[2,0];
|
||
end
|
||
else
|
||
begin
|
||
_z := (z0+fcoordinate_sizes[2]/2)*fzoom_coordinate_rates[2]+fzoom_bounds[2,0];
|
||
end
|
||
return true;
|
||
end
|
||
function paint_pre(cvs);override;
|
||
begin
|
||
if visible<>tgc_on then return ;
|
||
axes_changed();
|
||
modify_coordinate_position();
|
||
r := array(p_left-1,p_top-1,p_left+p_width+1,p_top+p_height+1);
|
||
cvs.axesrec := r;
|
||
cvs.axesvector := get_top_outer_points();
|
||
//paint(cvs);
|
||
paint_grid(cvs);
|
||
inherited;
|
||
cvs.axesunclip();
|
||
for i,v in faxes_objects do //绘制坐标
|
||
begin
|
||
v.paint_pre(cvs);
|
||
end
|
||
modify_label_position();
|
||
ftitle.paint_pre(cvs);
|
||
if fbox = tgc_on then
|
||
begin
|
||
set_lineinfo_to_canvas(cvs);
|
||
paint_box(cvs);
|
||
end
|
||
cvs.axesunclip();
|
||
end
|
||
function axes_changed();//改变
|
||
begin
|
||
if not fFigure then return ;
|
||
if f_changed then
|
||
begin
|
||
change_locked := true;
|
||
fr := fFigure.rect();
|
||
w := fr[2]-fr[0];
|
||
h := fr[3]-fr[1];
|
||
wa := w*(1-fmargins[0]-fmargins[2]);
|
||
ha := h*(1-fmargins[1]-fmargins[3]);
|
||
p_left := fr[0]+w*fmargins[0]+wa*faxes_bounds[0];
|
||
p_top := fr[1]+h*fmargins[1]+wa*faxes_bounds[1];
|
||
p_width := wa*(faxes_bounds[2]-faxes_bounds[0]);
|
||
p_height := ha*(faxes_bounds[3]-faxes_bounds[1]);
|
||
if fsqured=tgc_on then
|
||
begin
|
||
ts := min(p_width,p_height);
|
||
p_width := ts;
|
||
p_height := ts;
|
||
end
|
||
fcvs_bounds := array(p_left,p_top,p_left+p_width,p_top+p_height);
|
||
if (f_changed .& c_g_data_changed)=c_g_data_changed then
|
||
begin
|
||
tbds := fdata_bounds;
|
||
for i,v in get_node_data_bounds(self(true)) do
|
||
begin
|
||
if not fdata_bounds_locked[i] then
|
||
begin
|
||
new_bounds(v[0],v[1],a_,b_);
|
||
tbds[i] := array(a_,b_);//v*1.05;
|
||
end
|
||
end
|
||
fdata_bounds := tbds;
|
||
fzoom_box := tbds*1.05;
|
||
fzoom_bounds := fzoom_box;
|
||
end
|
||
/////////////计算旋转矩阵//////////////////////////
|
||
if (f_changed .& c_g_rote_changed)=c_g_rote_changed then
|
||
begin
|
||
c := cos(falpha);
|
||
s := sin(falpha);
|
||
c1 := cos(ftheta);
|
||
s1 := sin(ftheta);
|
||
frote_mt := array((0,1,0),(1,0,0),(0,0,1)):*array((c,s,0),(-s,c,0),(0,0,1)):*array((1,0,0),(0,c1,s1),(0,-s1,c1));
|
||
end
|
||
////////////////////////////////////////
|
||
if (f_changed .& c_g_data_zoombox)=c_g_data_zoombox then
|
||
begin
|
||
fzoom_bounds := fzoom_box;
|
||
end
|
||
recalc_size();
|
||
auto_set_axis();
|
||
change_locked := false;
|
||
end
|
||
f_changed := 0;
|
||
end
|
||
private
|
||
//////////长宽高////////////////////
|
||
fbounds_center; //中心
|
||
//////////////////////
|
||
fface_v_indexs; //定点次序
|
||
flines_index;//
|
||
ftheta;
|
||
ftheta_a;
|
||
falpha;
|
||
falpha_a;
|
||
frote_mt;
|
||
fcvs_bounds;
|
||
fzoom_bounds;
|
||
fbox_vertexs;
|
||
fzoom_coordinate_rates;
|
||
fcoordinate_sizes;
|
||
frevers;
|
||
public //create
|
||
function set_trans(t,a); //设置转换角度
|
||
begin
|
||
if (t=ftheta) and (falpha=a) then return ;
|
||
if ifnumber(t) then
|
||
begin
|
||
ftheta_a := (r_2_a(t) mod 360);
|
||
ftheta := a_2_r(ftheta_a);
|
||
end
|
||
if ifnumber(a) then
|
||
begin
|
||
falpha_a := r_2_a(a) mod 360;
|
||
falpha := a_2_r(falpha_a);
|
||
end
|
||
if ifnumber(t) or ifnumber(a) then f_changed .|=8;
|
||
prop_changed();
|
||
return ;
|
||
end
|
||
function create(pms);
|
||
begin
|
||
f_changed := 0;
|
||
fsqured := tgc_off;
|
||
inherited;
|
||
ftheta := 0;
|
||
falpha := 0;
|
||
flines_index := array(
|
||
(0,1),
|
||
(1,2),
|
||
(2,3),
|
||
(3,0),
|
||
(4,5),
|
||
(5,6),
|
||
(6,7),
|
||
(7,4),
|
||
(0,4),
|
||
(1,5),
|
||
(2,6),
|
||
(3,7)
|
||
);
|
||
fface_v_indexs := array(
|
||
(0,1,2,3),
|
||
(0,4,7,3),
|
||
(0,1,5,4),
|
||
(1,5,6,2),
|
||
(2,6,7,3),
|
||
(4,5,6,7)
|
||
);
|
||
fcvs_bounds := array(0,0,200,200);
|
||
fcoordinate_sizes := array(200,200,200);
|
||
frote_mt := array((0,1,0),(1,0,0),(0,0,1));
|
||
fbounds_center := array(100,100,100);
|
||
fzoom_bounds := array((0,200),(0,200),(0,200));
|
||
set_trans(0,pi()*1.5);
|
||
fzoom_coordinate_rates := array(1,1,1);
|
||
fdata_bounds_locked := array(0,0,0);
|
||
fgrid := array();
|
||
for i:= 0 to 1 do
|
||
begin
|
||
gd := new tg_line_info();
|
||
gd.width := 0;
|
||
gd.Style := tgc_PS_DOT;
|
||
fgrid[i] := gd;
|
||
end
|
||
faxes_reverse := array(tgc_off,tgc_off,tgc_off);
|
||
fbox := tgc_off;
|
||
ffilled := tgc_off;
|
||
fx_location := tgc_bottom;
|
||
fz_location := tgc_right;
|
||
fy_location := tgc_left;
|
||
faxes_objects := array();
|
||
for i := 0 to 2 do
|
||
begin
|
||
axi := new tg_axis_main();
|
||
axi.tics_style := tgc_tics_v;//tgc_tics_r;
|
||
lbl := new tg_label_axis();
|
||
case i of
|
||
0:
|
||
begin
|
||
fx_label := lbl;
|
||
axi.tics_direction := tgc_bottom;
|
||
axi.ytics_coord := array("x",0,0);
|
||
axi.tag := "+x+";
|
||
end
|
||
1:
|
||
begin
|
||
fy_label := lbl;
|
||
axi.tics_direction := tgc_left;
|
||
axi.ytics_coord := array(0,"y",0);
|
||
axi.tag := "+y+";
|
||
end
|
||
2:
|
||
begin
|
||
fz_label := lbl;
|
||
//axi.visible := false;
|
||
axi.ytics_coord := array(0,0,"z");
|
||
axi.tag := "+z+";
|
||
end
|
||
end ;
|
||
axi.axis_label := lbl;
|
||
faxes_objects[i] := axi;
|
||
axi.axes := self(true);
|
||
end
|
||
|
||
ftitle := new tg_label_axes();
|
||
ftitle.axes := self(true);
|
||
ftitle.location := tgc_by_axes;
|
||
fauto_ticks := array(tgc_on,tgc_on,tgc_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 := fdata_bounds;
|
||
//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 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 z_location read fz_location write set_z_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 faxes_bounds write set_axes_bounds; //坐标轴边界
|
||
property squred read fsqured write set_squred; //绘制区域是否采用等长宽,默认
|
||
property data_bounds read gs_data_bounds write gs_data_bounds; //数据边界
|
||
property zoom_box read gs_zoom_box write gs_zoom_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 //variable
|
||
Fpainting;
|
||
fgrid;
|
||
faxes_objects;
|
||
fzoom_box;
|
||
fmargins;
|
||
fsqured;
|
||
faxes_bounds ;//= [0,0,1,1]
|
||
fdata_bounds;
|
||
fdata_bounds_locked;
|
||
ffilled;
|
||
fauto_ticks;
|
||
ftitle;
|
||
fx_label;
|
||
fy_label;
|
||
fz_label;
|
||
fx_location;
|
||
fy_location;
|
||
fz_location;
|
||
fbox;
|
||
faxes_reverse;
|
||
private
|
||
fwilldelfigure;
|
||
fwilladdfigure;
|
||
function paint_grid(cvs);//绘制表格
|
||
begin
|
||
xg := fgrid[0];
|
||
if xg.width>0 and ifnumber(xg.color) then
|
||
begin
|
||
set_lineinfo_to_canvas(cvs,xg);
|
||
for i,v in faxes_objects[0].executecommand("get_tics_value") do
|
||
begin
|
||
if v<fzoom_box[0,0] or v>fzoom_box[0,1] then continue;
|
||
if zoom_to_xyz(v,fzoom_box[1,0],0,_x1,_y1) then
|
||
begin
|
||
zoom_to_xyz(v,fzoom_box[1,1],0,_x2,_y2);
|
||
cvs.moveto(array(_x1,_y1));
|
||
cvs.lineto(array(_x2,_y2));
|
||
end
|
||
end
|
||
end
|
||
xg := fgrid[1];
|
||
if xg.width>0 and ifnumber(xg.color) then
|
||
begin
|
||
set_lineinfo_to_canvas(cvs,xg);
|
||
for i,v in faxes_objects[1].executecommand("get_tics_value") do
|
||
begin
|
||
if v<fzoom_box[1,0] or v>fzoom_box[1,1] then continue;
|
||
if zoom_to_xyz(fzoom_box[0,0],v,0,_x1,_y1) then
|
||
begin
|
||
zoom_to_xyz(fzoom_box[0,1],v,0,_x2,_y2);
|
||
cvs.moveto(array(_x1,_y1));
|
||
cvs.lineto(array(_x2,_y2));
|
||
end
|
||
end
|
||
end
|
||
end
|
||
function paint_box(cvs);
|
||
begin
|
||
r := array();
|
||
ls := array();
|
||
ps2 := array();
|
||
inpoints := array();
|
||
tf := get_top_face(); //获得顶部的3个面
|
||
for i,fc in tf do
|
||
begin
|
||
for ii in fbox_vertexs do //判断点是否在面的阴影中
|
||
begin
|
||
if (ii in fc) then continue;
|
||
if point_in_rgn(fbox_vertexs[ii],fbox_vertexs[fc]) then
|
||
begin
|
||
inpoints[length(inpoints)] := ii;
|
||
end
|
||
end
|
||
end
|
||
hd := array();
|
||
for i,v in flines_index do //判断线是否需要隐藏
|
||
begin
|
||
ps := fbox_vertexs[v];
|
||
if (inpoints intersect v) then hd[i] := true;
|
||
for j,vj in ps do
|
||
ls[i,j] := vj[0:1]+fbounds_center;
|
||
end
|
||
for i,v in ls do //绘制线
|
||
begin
|
||
ps1 := v;
|
||
if hd[i] then cvs.pen.style := 1;
|
||
else cvs.pen.style := 0;
|
||
cvs.draw_polyline().points(ps1).draw();
|
||
end
|
||
end
|
||
function auto_set_axis();//自动计算坐标
|
||
begin
|
||
for i:=0 to 2 do
|
||
begin
|
||
axi :=faxes_objects[i];
|
||
axi.executecommand("set_bounds",fzoom_box[i]);
|
||
if axi.visible<>tgc_on then continue;
|
||
fsz := axi.fontinfo.size;
|
||
if fauto_ticks[i] = tgc_on then
|
||
begin
|
||
[arg,ifx,sz] := axi.executecommand("get_angleofhoriz");
|
||
if ifx then
|
||
begin
|
||
n := integer(sz/(fsz*12));
|
||
end else
|
||
begin
|
||
n := integer(sz/(fsz*4));
|
||
end
|
||
xcd := array();
|
||
xcdls := array();
|
||
if n>0 then
|
||
begin
|
||
rt := new_bounds(fzoom_box[i,0],fzoom_box[i,1],a_,b_);
|
||
bs :=ceil((b_-a_)/(rt)/n);
|
||
axi.sub_tics := min(bs,5);
|
||
stp := bs*rt;
|
||
vi := a_;
|
||
ii := 0;
|
||
while vi<=b_ do
|
||
begin
|
||
xcd[ii++] := vi;
|
||
vi+=stp;
|
||
end
|
||
xcd[ii] := vi;
|
||
end
|
||
axi.tics_coord := xcd;
|
||
end
|
||
end
|
||
end
|
||
function xy_in_paint_rect(x,y);//鼠标是否在坐标内
|
||
begin
|
||
if not ifnumber(x) then return false;
|
||
if not ifnumber(y) then return false;
|
||
if x<p_left or x>(p_left+p_width) then return false;
|
||
if y<p_top or y>(p_top+p_height) then return false;
|
||
return true;
|
||
end
|
||
function zoom_bound_op(a,b,dx,x,a1,b1);//缩放
|
||
begin
|
||
if x<a or x>b then return false;
|
||
if not(ifnumber(dx)) then return false ;
|
||
len := (b-a)/dx;
|
||
rt := (x-a)/(b-a);
|
||
a1 := x-len*rt;
|
||
b1 := a1+len;
|
||
return true;
|
||
end
|
||
function modify_label_position(); //修正标签位置
|
||
begin
|
||
if ftitle and (ftitle.visible=tgc_on) and (ftitle.auto_position=tgc_on) then
|
||
begin
|
||
s := ftitle.text;
|
||
if s then
|
||
begin
|
||
ax := faxes_objects[0];
|
||
//y := p_top-20-(ftitle.fontinfo.size*2);
|
||
fr := fFigure.rect();
|
||
y := fr[1]+10;
|
||
{if (ax.visible=tgc_on) and (ax.tics_direction = tgc_top) then
|
||
begin
|
||
y -=(ax.fontinfo.size*2);
|
||
end}
|
||
x := p_left+(p_width-length(s)*10)/2;
|
||
if ftitle.location=tgc_by_coordinates then
|
||
xyz_to_zoom(x,y,0,_x,_y,_z);
|
||
else axes_unmapping(x,y,_x,_y,_z);
|
||
ftitle.executecommand("auto_position_value",array(_x,_y));
|
||
end
|
||
end
|
||
end
|
||
function get_axis_index(p);
|
||
begin
|
||
r := array();
|
||
if not ifarray(p) then return r;
|
||
for i,v in p do
|
||
begin
|
||
zoom_to_xyz(v[0],v[1],v[2],_x0,_y0,_z0);
|
||
r[i] := array(_x0,_y0,_z0);
|
||
end
|
||
return sselect thisrowindex from r order by [1] asc end;
|
||
end
|
||
function get_duan_dian(x0,y0,z0,x1,y1,z1,x2,y2,z2);
|
||
begin
|
||
x0 := fzoom_box[0,0];
|
||
y0 := fzoom_box[1,0];
|
||
z0 := fzoom_box[2,0];
|
||
x1 := fzoom_box[0,1];
|
||
y1 := fzoom_box[1,1];
|
||
z1 := fzoom_box[2,1];
|
||
x2 := (x0+x1)/2;
|
||
y2 := (y0+y1)/2;
|
||
z2 := (z0+z1)/2;
|
||
end
|
||
|
||
function modify_x_position(loc);
|
||
begin
|
||
get_duan_dian(x0,y0,z0,x1,y1,z1,x2,y2,z2);
|
||
//////bottom
|
||
px := array();
|
||
px[0] := array(x2,y0,z0);
|
||
px[1] := array(x2,y0,z1);
|
||
///top
|
||
px[2] := array(x2,y1,z0);
|
||
px[3] := array(x2,y1,z1);
|
||
r := array();
|
||
for i,v in px do
|
||
begin
|
||
zoom_to_xyz(v[0],v[1],v[2],_x0,_y0,_z0);
|
||
r[i] := array(_x0,_y0,_z0);
|
||
end
|
||
axx := faxes_objects[0];
|
||
case loc of
|
||
tgc_bottom:
|
||
begin
|
||
if like_0(ftheta) then
|
||
begin
|
||
if faxes_reverse[1]=tgc_on then idx := 2;
|
||
else
|
||
idx := 0;
|
||
end else
|
||
begin
|
||
idxs := sselect thisrowindex from r order by [1] asc end;
|
||
if faxes_reverse[1]=tgc_on then idx := idxs[3];
|
||
else
|
||
idx := idxs[0];
|
||
end
|
||
idxv := px[idx];
|
||
zoom_to_xyz(x2,y2,z2,_x0,_y0,_z0);//中间点
|
||
zoom_to_xyz(x0,idxv[1],idxv[2],_x00,_y00,_z00);//轴线0点
|
||
v1 := array(_x0-r[idx,0],_y0-r[idx,1]);//射线方向
|
||
v2 := array(r[idx,0]-_x00,r[idx,1]-_y00); //轴方向
|
||
p_trans(v2[0],v2[1],-pi()/2.01,_x,_y);
|
||
jj := r_2_a( d2angle(array(_x,_y),v1));
|
||
axx.ytics_coord := array("x",idxv[1],idxv[2]);
|
||
if jj>90 then axx.tics_direction := tgc_direct_desc ;
|
||
else axx.tics_direction := tgc_direct_asc;
|
||
return ;
|
||
axx.ytics_coord := array("x",fzoom_box[1,(faxes_reverse[1]= tgc_on)],fzoom_box[2,(faxes_reverse[1]= tgc_on)]);
|
||
if faxes_reverse[0]=tgc_on then axx.tics_direction := tgc_direct_asc;
|
||
else
|
||
axx.tics_direction := tgc_direct_desc;
|
||
end
|
||
tgc_top:
|
||
begin
|
||
if like_0(ftheta) then
|
||
begin
|
||
if faxes_reverse[1]=tgc_on then idx := 0;
|
||
else
|
||
idx := 2;
|
||
end else
|
||
begin
|
||
idxs := sselect thisrowindex from r order by [1] desc end;
|
||
if faxes_reverse[1]=tgc_on then idx := idxs[3];
|
||
else
|
||
idx := idxs[0];
|
||
end
|
||
idxv := px[idx];
|
||
zoom_to_xyz(x2,y2,z2,_x0,_y0,_z0);//中间点
|
||
zoom_to_xyz(x0,idxv[1],idxv[2],_x00,_y00,_z00);//轴线0点
|
||
v1 := array(_x0-r[idx,0],_y0-r[idx,1]);//射线方向
|
||
v2 := array(r[idx,0]-_x00,r[idx,1]-_y00); //轴方向
|
||
p_trans(v2[0],v2[1],-pi()/2.01,_x,_y);
|
||
jj := r_2_a( d2angle(array(_x,_y),v1));
|
||
axx.ytics_coord := array("x",idxv[1],idxv[2]);
|
||
if jj>90 then axx.tics_direction := tgc_direct_desc ;
|
||
else axx.tics_direction := tgc_direct_asc;
|
||
return ;
|
||
axx.ytics_coord := array("x",fzoom_box[1,(faxes_reverse[1]<> tgc_on)],fzoom_box[2,(faxes_reverse[1]= tgc_on)]);
|
||
if faxes_reverse[0]=tgc_on then axx.tics_direction := tgc_direct_desc;
|
||
else
|
||
axx.tics_direction := tgc_direct_asc;
|
||
end
|
||
tgc_middle:
|
||
begin
|
||
axx.ytics_coord := array("x",fzoom_box[1,0]+(fzoom_box[1,1]-fzoom_box[1,0])/2,0);
|
||
end
|
||
tgc_origin:
|
||
begin
|
||
if fzoom_box[1,0]<0 and fzoom_box[1,1]>0 then
|
||
axx.ytics_coord := array("x",0,0);
|
||
else
|
||
begin
|
||
return modify_x_position(tgc_bottom);
|
||
//axx.ytics_coord := array("x",fzoom_box[1,(faxes_reverse[1]= tgc_on)],0);
|
||
end
|
||
axx.tics_direction := tgc_direct_desc;
|
||
end
|
||
end ;
|
||
end
|
||
function modify_y_position(loc);
|
||
begin
|
||
get_duan_dian(x0,y0,z0,x1,y1,z1,x2,y2,z2);
|
||
//////left
|
||
py := array();
|
||
py[0] := array(x0,y2,z0);
|
||
py[1] := array(x0,y2,z1);
|
||
///right
|
||
py[2] := array(x1,y2,z0);
|
||
py[3] := array(x1,y2,z1);
|
||
r := array();
|
||
for i,v in py do
|
||
begin
|
||
zoom_to_xyz(v[0],v[1],v[2],_x0,_y0,_z0);
|
||
r[i] := array(_x0,_y0,_z0);
|
||
end
|
||
axy := faxes_objects[1];
|
||
case loc of
|
||
tgc_left:
|
||
begin
|
||
if like_0(ftheta) then
|
||
begin
|
||
if faxes_reverse[0]=tgc_on then idx := 2;
|
||
else
|
||
idx := 0;
|
||
end else
|
||
begin
|
||
idxs := sselect thisrowindex from r order by [1] desc end;
|
||
if faxes_reverse[0]=tgc_on then idx := idxs[3];
|
||
else
|
||
idx := idxs[0];
|
||
end
|
||
idxv := py[idx];
|
||
zoom_to_xyz(x2,y2,z2,_x0,_y0,_z0);//中间点
|
||
zoom_to_xyz(idxv[0],y0,idxv[2],_x00,_y00,_z00);//轴线0点
|
||
v1 := array(_x0-r[idx,0],_y0-r[idx,1]);//射线方向
|
||
v2 := array(r[idx,0]-_x00,r[idx,1]-_y00); //轴方向
|
||
p_trans(v2[0],v2[1],-pi()/2.01,_x,_y);
|
||
jj := r_2_a( d2angle(array(_x,_y),v1));
|
||
axy.ytics_coord := array(py[idx,0],"y",py[idx,2]);
|
||
if jj>90 then axy.tics_direction := tgc_direct_desc ;
|
||
else axy.tics_direction := tgc_direct_asc;
|
||
return ;
|
||
axy.ytics_coord := array(fzoom_box[0,(faxes_reverse[0] = tgc_on)],"y",fzoom_box[2,(faxes_reverse[1]= tgc_on)]);
|
||
if faxes_reverse[1]=tgc_on then axy.tics_direction := tgc_direct_desc ;
|
||
else
|
||
axy.tics_direction := tgc_direct_asc;
|
||
end
|
||
tgc_right:
|
||
begin
|
||
if like_0(ftheta) then
|
||
begin
|
||
if faxes_reverse[0]=tgc_on then idx := 0;
|
||
else
|
||
idx := 2;
|
||
end else
|
||
begin
|
||
idxs := sselect thisrowindex from r order by [1] asc end;
|
||
if faxes_reverse[0]=tgc_on then idx := idxs[3];
|
||
else
|
||
idx := idxs[0];
|
||
end
|
||
idxv := py[idx];
|
||
zoom_to_xyz(x2,y2,z2,_x0,_y0,_z0);//中间点
|
||
zoom_to_xyz(idxv[0],y0,idxv[2],_x00,_y00,_z00);//轴线0点
|
||
v1 := array(_x0-r[idx,0],_y0-r[idx,1]);//射线方向
|
||
v2 := array(r[idx,0]-_x00,r[idx,1]-_y00); //轴方向
|
||
p_trans(v2[0],v2[1],-pi()/2.01,_x,_y);
|
||
jj := r_2_a( d2angle(array(_x,_y),v1));
|
||
axy.ytics_coord := array(py[idx,0],"y",py[idx,2]);
|
||
if jj>90 then axy.tics_direction := tgc_direct_desc ;
|
||
else axy.tics_direction := tgc_direct_asc;
|
||
return ;
|
||
axy.ytics_coord := array(fzoom_box[0,(faxes_reverse[0]<> tgc_on)],"y",fzoom_box[2,(faxes_reverse[1]= tgc_on)]);
|
||
if faxes_reverse[1]=tgc_on then axy.tics_direction := tgc_direct_asc;
|
||
else
|
||
axy.tics_direction := tgc_direct_desc;
|
||
end
|
||
tgc_middle:
|
||
begin
|
||
axy.ytics_coord := array(fzoom_box[0,0]+(fzoom_box[0,1]-fzoom_box[0,0])/2,"y",0);
|
||
end
|
||
tgc_origin:
|
||
begin
|
||
if fzoom_box[0,0]<0 and fzoom_box[0,1]>0 then
|
||
begin
|
||
axy.ytics_coord := array(0,"y",0);
|
||
end
|
||
else
|
||
begin
|
||
return modify_y_position(tgc_left);
|
||
//axy.ytics_coord := array(fzoom_box[0,(faxes_reverse[0] = tgc_on)],"y",0);
|
||
end
|
||
axy.tics_direction := tgc_direct_asc;
|
||
end
|
||
end;
|
||
end
|
||
function modify_z_position(loc);
|
||
begin
|
||
if like_0(ftheta_a) then return ;
|
||
get_duan_dian(x0,y0,z0,x1,y1,z1,x2,y2,z2);
|
||
axz := faxes_objects[2];
|
||
pz := array();
|
||
pz[0] := array(x0,y0,z2);
|
||
pz[1] := array(x1,y0,z2);
|
||
pz[2] := array(x1,y1,z2);
|
||
pz[3] := array(x0,y1,z2);
|
||
r := array();
|
||
for i,v in pz do
|
||
begin
|
||
zoom_to_xyz(v[0],v[1],v[2],_x0,_y0,_z0);
|
||
r[i] := array(_x0,_y0,_z0);
|
||
end
|
||
case loc of
|
||
tgc_right:
|
||
begin
|
||
idxs := sselect thisrowindex from r order by [0] desc end;
|
||
end
|
||
else
|
||
begin
|
||
idxs := sselect thisrowindex from r order by [0] asc end;
|
||
end
|
||
end;
|
||
idx := idxs[0];
|
||
idxv := pz[idx];
|
||
zoom_to_xyz(x2,y2,z2,_x0,_y0,_z0);//中间点
|
||
zoom_to_xyz(idxv[0],idxv[1],z0,_x00,_y00,_z00);//轴线0点
|
||
v1 := array(_x0-r[idx,0],_y0-r[idx,1]);//射线方向
|
||
v2 := array(r[idx,0]-_x00,r[idx,1]-_y00); //轴方向
|
||
p_trans(v2[0],v2[1],-pi()/2.01,_x,_y);
|
||
jj := r_2_a( d2angle(array(_x,_y),v1));
|
||
axz.ytics_coord := array(pz[idx,0],pz[idx,1],"z");
|
||
if jj>90 then axz.tics_direction := tgc_direct_desc ;
|
||
else axz.tics_direction := tgc_direct_asc;
|
||
return ;
|
||
|
||
axz.ytics_coord := array(idxv[0],idxv[1],"z");
|
||
if ftheta_a>180 or ftheta_a<0 then axz.tics_direction :=tgc_direct_asc ;
|
||
else axz.tics_direction := tgc_direct_desc ;
|
||
end
|
||
function modify_coordinate_position();//修正坐标轴位置
|
||
begin
|
||
|
||
////////////////y轴///////////////////////////////////
|
||
modify_y_position(fy_location);
|
||
///////////////x///////////////////////////////
|
||
modify_x_position(fx_location);
|
||
//////z-axis
|
||
modify_z_position(fz_location);
|
||
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));
|
||
f_changed .|= c_g_paint_rect;
|
||
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(tg_figure_container)) then return SetFigure(v.figure);
|
||
if v is class(tg_figure) then //添加
|
||
begin
|
||
fwilladdfigure := v;
|
||
v.add_axes(self(true));
|
||
fwilladdfigure := nil;
|
||
end else
|
||
begin
|
||
fFigure := nil;
|
||
end
|
||
end
|
||
function set_filled(v);
|
||
begin
|
||
if not tg_boolen_value(v,nv) then return ;
|
||
if nv<>fbox then
|
||
begin
|
||
ffilled := nv;
|
||
prop_changed("ffilled",nv);
|
||
end
|
||
end
|
||
function set_box(v);
|
||
begin
|
||
if not tg_boolen_value(v,nv) then
|
||
begin
|
||
nv := v;
|
||
end
|
||
if (nv in array(tgc_box_on,tgc_box_off,tgc_box_half,tgc_box_hidden_axes)) and v<>fbox then
|
||
begin
|
||
fbox := nv;
|
||
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;
|
||
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;
|
||
prop_changed("y_location",v);
|
||
end
|
||
end
|
||
function set_z_location(v);
|
||
begin
|
||
if v<>fz_location and ( v in array(tgc_left,tgc_right)) then
|
||
begin
|
||
fz_location := v;
|
||
prop_changed("z_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(vidx,v);//自动更新坐标标签
|
||
begin
|
||
tg_boolen_value(v,nv);
|
||
idx := tg_get_true_idx(vidx);
|
||
if nv=tgc_on or nv=tgc_off then
|
||
begin
|
||
if idx in array(0,1,2) then
|
||
begin
|
||
if fauto_ticks[idx]<>nv then
|
||
begin
|
||
fauto_ticks[idx] := nv;
|
||
if nv=tgc_on then faxes_objects[i].tics_style := tgc_tics_v;//faxes_objects[i].tics_style := tgc_tics_r;
|
||
//else faxes_objects[i].tics_style := tgc_tics_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(vidx);
|
||
begin
|
||
idx := tg_get_true_idx(vidx);
|
||
if idx in array(0,1,2) then
|
||
begin
|
||
return faxes_objects[idx];
|
||
end
|
||
end
|
||
function set_squred(v);
|
||
begin
|
||
if not tg_boolen_value(v,nv) then return ;
|
||
if nv<>fsqured then
|
||
begin
|
||
fsqured := nv;
|
||
prop_changed("axes_bounds",idx);
|
||
end
|
||
end
|
||
function set_axes_bounds(v);
|
||
begin
|
||
if ifarray(v) and ifnumber(v[0]) and ifnumber(v[1]) and v[2]>v[0] and v[3]>v[1] then
|
||
begin
|
||
if faxes_bounds<>v then
|
||
begin
|
||
faxes_bounds := v;
|
||
f_changed .|=c_g_paint_rect ;
|
||
prop_changed("axes_bounds",idx);
|
||
end
|
||
end
|
||
end
|
||
function gs_data_bounds(vidx,v);
|
||
begin
|
||
idx := tg_get_true_idx(vidx);
|
||
if (v=-1) or (v=tgc_off) then
|
||
begin
|
||
if idx in array(0,1,2) then
|
||
begin
|
||
fdata_bounds_locked[idx] := false;
|
||
end
|
||
end else
|
||
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;
|
||
fdata_bounds_locked[idx] := true;
|
||
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_zoom_box(vidx,v);
|
||
begin
|
||
idx := tg_get_true_idx(vidx);
|
||
if ifarray(v) and ifnumber(v[0]) and ifnumber(v[1]) then
|
||
begin
|
||
if idx in array(0,1,2) then
|
||
begin
|
||
fzoom_box[idx] := v;
|
||
prop_changed("zoom_box",idx);
|
||
end
|
||
end else //get
|
||
begin
|
||
if idx in array(0,1,2) then return fzoom_box[idx];
|
||
return fzoom_box;
|
||
end
|
||
end
|
||
function gs_axes_reverse(vidx,v); //反向
|
||
begin
|
||
if not tg_boolen_value(v,nv) then return ;
|
||
idx := tg_get_true_idx(vidx);
|
||
if nv=tgc_off or nv=tgc_on then
|
||
begin
|
||
if idx in array(0,1) then
|
||
begin
|
||
faxes_reverse[idx] := nv;
|
||
prop_changed("axes_reverse",idx);
|
||
end
|
||
end else //get
|
||
begin
|
||
if idx in array(0,1) then return faxes_reverse[idx];
|
||
return faxes_reverse;
|
||
end
|
||
end
|
||
function gs_margins(v); //空白
|
||
begin
|
||
if ifarray(v) then
|
||
begin
|
||
if v<>fmargins and v[0]>0 and v[1]>0 and v[2]>0 and v[3]>0 and (v[0]+v[2])<1 and (v[1]+v[3])<1 then
|
||
begin
|
||
fmargins := v;
|
||
f_changed .|= c_g_paint_rect;
|
||
prop_changed("margins",idx);
|
||
end
|
||
return ;
|
||
end
|
||
return fmargins;
|
||
end
|
||
function gs_sub_ticks(vidx,v); //小刻度线
|
||
begin
|
||
idx := tg_get_true_idx(vidx);
|
||
if ifnumber(v) and (v>=0) then
|
||
begin
|
||
if idx in array(0,1,2) then
|
||
begin
|
||
faxes_objects[idx].sub_tics := v;
|
||
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
|
||
|
||
////////////////三维转换////////////////////
|
||
function transxyz(x,y,z,_x,_y,_z); //旋转数据
|
||
begin
|
||
r := array((x,y,z)):*frote_mt;
|
||
_x := r[0,0];
|
||
_y := r[0,1];
|
||
_z := r[0,2];
|
||
end
|
||
function untransxyz(x,y,z,_x,_y,_z);
|
||
begin
|
||
r := array((x,y,z)):/frote_mt;
|
||
_x := r[0,0];
|
||
_y := r[0,1];
|
||
_z := r[0,2];
|
||
end
|
||
function get_new_w_h(w1,h1,w,h,z);//获取变换的大小
|
||
begin
|
||
//z1 := (w1+h1)/2;
|
||
z1 := min(w1,h1);
|
||
z := z1;
|
||
w := w1;
|
||
h := h1;
|
||
while true do
|
||
begin
|
||
ps := init_vecs(h,w,z);
|
||
bd := zeros(2,2);
|
||
for i,v in ps do
|
||
begin
|
||
transxyz(v[0],v[1],v[2],_x,_y,_z);
|
||
bd[0,0] := min(_x,bd[0,0]);
|
||
bd[0,1] := max(_x,bd[0,1]);
|
||
bd[1,0] := min(_y,bd[1,0]);
|
||
bd[1,1] := max(_y,bd[1,1]);
|
||
end
|
||
bw := bd[0,1]-bd[0,0];
|
||
bh := bd[1,1]-bd[1,0];
|
||
if bw<w1 and bh<h1 then break;
|
||
w*=0.99;
|
||
h*=0.99;
|
||
z*=0.99;
|
||
end
|
||
mj1 := w*h;
|
||
bk := array(w,h,z);
|
||
z := z1;
|
||
w := h1;
|
||
h := w1;
|
||
while true do
|
||
begin
|
||
ps := init_vecs(h,w,z);
|
||
bd := zeros(2,2);
|
||
for i,v in ps do
|
||
begin
|
||
transxyz(v[0],v[1],v[2],_x,_y,_z);
|
||
bd[0,0] := min(_x,bd[0,0]);
|
||
bd[0,1] := max(_x,bd[0,1]);
|
||
bd[1,0] := min(_y,bd[1,0]);
|
||
bd[1,1] := max(_y,bd[1,1]);
|
||
end
|
||
bw := bd[0,1]-bd[0,0];
|
||
bh := bd[1,1]-bd[1,0];
|
||
if bw<w1 and bh<h1 then break;
|
||
w*=0.99;
|
||
h*=0.99;
|
||
z*=0.99;
|
||
end
|
||
mj2 := w*h;
|
||
if mj2<mj1 then
|
||
begin
|
||
[w,h,z] := bk;
|
||
end
|
||
end
|
||
function recalc_size(); //重算大小
|
||
begin
|
||
w1 := fcvs_bounds[2]-fcvs_bounds[0];
|
||
h1 := fcvs_bounds[3]-fcvs_bounds[1];
|
||
fbounds_center := array(fcvs_bounds[0]+w1/2,fcvs_bounds[1]+h1/2,0);
|
||
get_new_w_h(w1,h1,w,h,z);
|
||
fcoordinate_sizes[0] := h;
|
||
fcoordinate_sizes[1] := w;
|
||
fcoordinate_sizes[2] := z;
|
||
fzoom_coordinate_rates[0] := (fzoom_bounds[0,1]-fzoom_bounds[0,0])/h;
|
||
fzoom_coordinate_rates[1] := (fzoom_bounds[1,1]-fzoom_bounds[1,0])/w;
|
||
fzoom_coordinate_rates[2] := (fzoom_bounds[2,1]-fzoom_bounds[2,0])/z;
|
||
fbox_vertexs := array();
|
||
for i,v in init_vecs(h,w,z) do
|
||
begin
|
||
transxyz(v[0],v[1],v[2],x,y,z);
|
||
fbox_vertexs[i] := array(x,y,z);
|
||
end
|
||
end
|
||
function init_vecs(x,y,z); //初始化顶点
|
||
begin
|
||
r := array();
|
||
r[0]:=array(-x/2, -y/2, -z/2); //0
|
||
r[1]:=array(-x/2, y/2, -z/2); //1
|
||
r[2]:=array(x/2, y/2, -z/2); //2
|
||
r[3]:=array(x/2, -y/2, -z/2); //3
|
||
r[4]:=array(-x/2, -y/2, z/2); //4
|
||
r[5]:=array(-x/2, y/2, z/2); //5
|
||
r[6]:=array(x/2, y/2, z/2); //6
|
||
r[7]:=array(x/2, -y/2, z/2); //7
|
||
return r;
|
||
end
|
||
function get_top_face(); //获取最上面的三个面,便于计算隐藏的线
|
||
begin
|
||
r := array();
|
||
for i , v in fface_v_indexs do
|
||
begin
|
||
zi := 0;
|
||
if ifarray(v) then
|
||
begin
|
||
for j,vj in v do
|
||
begin
|
||
zi += fbox_vertexs[vj][2];
|
||
end
|
||
end
|
||
r[i] := zi;
|
||
end
|
||
r := sselect thisrowindex from r order by thisrow desc end;
|
||
return fface_v_indexs[r[0:2]];
|
||
end
|
||
function get_top_outer_points();
|
||
begin
|
||
//////////////获取顶部三个面的点////////////////////////
|
||
r :=get_top_face();
|
||
pts := array();
|
||
for i,v in r do
|
||
begin
|
||
pts union2= v;
|
||
end
|
||
pts2 := array();
|
||
for i,v in r do
|
||
begin
|
||
if not pts2 then pts2 := v;
|
||
else pts2 intersect= v;
|
||
end
|
||
r := (pts minus pts2);
|
||
///////////计算中心和各个点的角度////////////////////
|
||
rt := array();
|
||
xxyy := zeros(3);
|
||
for i,v in r do
|
||
begin
|
||
vi := fbox_vertexs[v]+fbounds_center;
|
||
rt[i] := vi;
|
||
rt[i,3] := v;
|
||
xxyy+=vi;
|
||
end
|
||
xxyy /= length(rt);
|
||
for i := 0 to length(rt)-1 do
|
||
begin
|
||
rt[i,4] := get_x_arg(rt[i,0:1]-xxyy[0:1]);
|
||
end
|
||
r := select [0],[1] from rt order by [4] end;
|
||
return r;
|
||
end
|
||
function get_x_arg(dxy);
|
||
begin
|
||
a_180 := pi();
|
||
a_90 := a_180/2;
|
||
a_30 := a_180/6;
|
||
a_60 := a_180/3;
|
||
a_45 := a_180/4;
|
||
a_150 := a_180/6*5;
|
||
xarg := d2angle(array(5,0),dxy); //和x夹角
|
||
yarg := d2angle(array(0,5),dxy); //和y夹角
|
||
if isnan(xarg) then
|
||
begin
|
||
if dxy[0]>0 then xarg := 0;
|
||
else xarg := a_180;
|
||
end
|
||
if isnan(yarg) then
|
||
begin
|
||
if dxy[1]>0 then yarg := 0;
|
||
else yarg := a_180;
|
||
end
|
||
if xarg<a_30 or xarg>a_150 then
|
||
begin
|
||
ifh := true;
|
||
end
|
||
if like_0( xarg) then
|
||
begin
|
||
ifh := true;
|
||
end else
|
||
if a_like_b(xarg,a_180) then
|
||
begin
|
||
xarg := -xarg;
|
||
ifh := true;
|
||
end else
|
||
if a_like_b(yarg,a_90) then
|
||
begin
|
||
xarg := 0;
|
||
ifh := true;
|
||
end else
|
||
if yarg = 0 then
|
||
begin
|
||
xarg := a_90;
|
||
end else
|
||
if yarg=a_180 then
|
||
begin
|
||
xarg:=-a_90;
|
||
end else
|
||
if xarg<a_90 and yarg>a_90 then //第1
|
||
begin
|
||
xarg := -xarg;
|
||
end else
|
||
if xarg>a_90 and yarg>a_90 then //第2
|
||
begin
|
||
xarg :=-xarg;
|
||
end else
|
||
if yarg<a_90 and xarg>a_90 then //第3
|
||
begin
|
||
end else
|
||
if yarg<a_90 and xarg<a_90 then //第4
|
||
begin
|
||
end
|
||
return xarg;
|
||
end
|
||
end
|
||
type tg_canvas = class(TcustomCanvas) //画布对象
|
||
uses utslvclgdi;
|
||
function create(h,fg);
|
||
begin
|
||
inherited create();
|
||
ffigure := fg;
|
||
FCvsHandle := h;
|
||
Handle := h;
|
||
faxesrgn := new TRGNPOLY();//new TRGNRECT();
|
||
ffigurergn := new TRGNRECT();//new TRGNRECT();
|
||
ffigurergn.rect := fg.rect();
|
||
faxesrgntemp := new TRGNPOLY();//new TRGNRECT();
|
||
//ffigurergn.
|
||
end
|
||
function axesclip(); //裁剪坐标系范围
|
||
begin
|
||
if faxesrgn then
|
||
begin
|
||
_wapi.SelectClipRgn(FCvsHandle,faxesrgn.Handle); //裁剪区域
|
||
end
|
||
end
|
||
function figureclip(); //裁剪figure区域
|
||
begin
|
||
if ffigurergn then
|
||
begin
|
||
_wapi.SelectClipRgn(FCvsHandle,ffigurergn.Handle); //裁剪figure
|
||
end
|
||
end
|
||
function clip_rgn(pts);//裁剪指定区域
|
||
begin
|
||
faxesrgntemp.points := pts;
|
||
h := faxesrgntemp.Handle;
|
||
if h then _wapi.SelectClipRgn(FCvsHandle,faxesrgntemp.Handle);
|
||
end
|
||
function axesunclip();//取消裁剪
|
||
begin
|
||
_wapi.SelectClipRgn(FCvsHandle,0);
|
||
end
|
||
function destroy();
|
||
begin
|
||
Handle := 0;
|
||
faxesrgn := nil;
|
||
ffigurergn := nil;
|
||
faxesrgntemp :=nil;
|
||
end
|
||
property figure:tg_figure read ffigure; //绘制区域
|
||
property axesvector read faxesvector write set_clip_vector; //坐标系区域
|
||
property axesrec read FaxesRec write set_clip_rect; //坐标系矩形区域
|
||
private
|
||
FaxesRec;
|
||
faxesvector;
|
||
FCvsHandle;
|
||
faxesrgn;
|
||
ffigurergn;
|
||
faxesrgntemp;
|
||
ffigurerect;
|
||
[weakref]ffigure;
|
||
private
|
||
function set_clip_rect(rec);
|
||
begin
|
||
FaxesRec := rec;
|
||
//set_clip_vector( rec_to_points(rec));
|
||
end
|
||
function set_clip_vector(v);
|
||
begin
|
||
faxesvector :=v;
|
||
faxesrgn.points := faxesvector;
|
||
end
|
||
end
|
||
type tg_axis_main = class(tg_axis) //主轴
|
||
public
|
||
function create(pms);
|
||
begin
|
||
inherited;
|
||
end
|
||
protected
|
||
function prop_changed(n,v);override;
|
||
begin
|
||
case n of
|
||
"tics_direction","xtics_coord","ytics_coord":
|
||
begin
|
||
return ;
|
||
end else
|
||
begin
|
||
//echo "\r\n",n;
|
||
end
|
||
end
|
||
inherited;
|
||
end
|
||
function SetParent(V);override;
|
||
begin
|
||
|
||
end
|
||
function get_axes();override;
|
||
begin
|
||
return faxes;
|
||
end
|
||
function set_axes(axs);override;
|
||
begin
|
||
if axs is class(tg_axes) then faxes := axs;
|
||
end
|
||
private
|
||
[weakref] faxes;
|
||
function getfontinfo();override;
|
||
begin
|
||
if faxes and (ParentFont=tgc_on) then
|
||
begin
|
||
r := faxes.fontinfo;
|
||
r.flinker := self(true);
|
||
return r;
|
||
end
|
||
ffontinfo.flinker := self(true);
|
||
return ffontinfo;
|
||
end
|
||
end
|
||
type tg_label_axis = class(tg_base) //坐标轴标签
|
||
public
|
||
function create(pms);
|
||
begin
|
||
inherited;
|
||
ftext := "";
|
||
ffont_angle := 0;
|
||
end
|
||
published
|
||
property font_angle read ffont_angle write set_font_angle;//90
|
||
property text read ftext write set_text;
|
||
protected
|
||
function SetParent(V);override;
|
||
begin
|
||
end
|
||
private
|
||
ffont_angle;
|
||
ftext;
|
||
private
|
||
function set_font_angle(ag);
|
||
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 v<>ftext and ifstring(v) then
|
||
begin
|
||
ftext := v;
|
||
prop_changed("text",v);
|
||
end
|
||
end
|
||
end
|
||
type tg_label_axes = class(tg_label) //坐标系标签
|
||
public
|
||
function create(pms);
|
||
begin
|
||
inherited;
|
||
clip_state := tgc_off;
|
||
auto_position := tgc_on;
|
||
end
|
||
protected
|
||
function SetParent(V);override;
|
||
begin
|
||
end
|
||
function get_axes();override;
|
||
begin
|
||
return faxes;
|
||
end
|
||
function set_axes(axs);override;
|
||
begin
|
||
if axs is class(tg_axes) then faxes := axs;
|
||
end
|
||
private
|
||
[weakref] faxes;
|
||
end
|
||
type tg_axis = class(tg_base) //轴对象
|
||
function create(pms);
|
||
begin
|
||
inherited;
|
||
clip_state := tgc_off;
|
||
fticksize := 12;
|
||
fsubticksize := 6;
|
||
ftics_direction := tgc_direct_asc; //
|
||
fxtics_coord := array(0,1,2,3);
|
||
ftcmin := 0;
|
||
ftcmax := 3;
|
||
ftccount := 3;
|
||
fxtics_coord_v := array(0,1,2,3);
|
||
fytics_coord := array("tics",0,0);
|
||
ftics_labels := array("0","1","2","3");
|
||
ftics_segment := tgc_on;
|
||
ftics_style := tgc_tics_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);override;
|
||
begin
|
||
case cmd of
|
||
"tics_recs" : return (visible=tgc_on)?ftics_recs:nil; //标签区域
|
||
"label_rgn": return (flabel.visible=tgc_on)?flabel_rgn:nil; //标题区域
|
||
"get_tics_value":return fxtics_coord_v;
|
||
"set_bounds": return set_zoom_bounds(pm);
|
||
"get_angleofhoriz" :
|
||
begin
|
||
get_angleofhoriz(xarg,ifh,sz);
|
||
return array(xarg,ifh,sz);
|
||
end
|
||
end;
|
||
end
|
||
function paint(cvs);override;
|
||
begin
|
||
if visible<>tgc_on then return ;
|
||
if clip_state=tgc_on then cvs.axesclip();
|
||
else cvs.axesunclip();
|
||
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
|
||
vi := fxtics_coord_v[i]+dx*j;
|
||
if fzoom_bounds and (vi<fzoom_bounds[0] or vi>fzoom_bounds[1]) then continue;
|
||
subtks[idx++] := vi;
|
||
end
|
||
end
|
||
end
|
||
return draw_axis(cvs,subtks);
|
||
end
|
||
protected
|
||
function draw_tics(cvs,info);virtual;
|
||
begin
|
||
if not ifarray(info) then return ;
|
||
for i,v in info do
|
||
begin
|
||
cvs.drawtext(v[0],v[1]);
|
||
end
|
||
end
|
||
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 tics_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"]
|
||
property axis_label read flabel write flabel; //轴标签
|
||
private
|
||
flabel_rgn;
|
||
ftics_recs;
|
||
fzoom_bounds;
|
||
fticksize;
|
||
fsubticksize;
|
||
fxtics_coord_v;
|
||
ftcmin;
|
||
ftcmax;
|
||
ftccount;
|
||
///////////////////////////////
|
||
ftics_direction;
|
||
fxtics_coord;
|
||
fytics_coord;
|
||
fsub_tics;
|
||
ftics_color;
|
||
ftics_segment;
|
||
ftics_style;
|
||
ftics_labels;
|
||
flabel;
|
||
//format_n ;//= ""
|
||
//fractional_font ;//= "off"
|
||
//clip_state ;//= "off"
|
||
//clip_box ;//= []
|
||
//user_data ;//= []
|
||
//tag ;//= ""
|
||
private
|
||
function v_to_cvs(tpax,v,x,y);
|
||
begin
|
||
case tpax of
|
||
"x":zoom_to_xyz(v,fytics_coord[1],fytics_coord[2],x,y);
|
||
"y":zoom_to_xyz(fytics_coord[0],v,fytics_coord[2],x,y);
|
||
"z":zoom_to_xyz(fytics_coord[0],fytics_coord[1],v,x,y);
|
||
end;
|
||
end
|
||
function get_tic_to(direc,size,arg,_x,_y);
|
||
begin
|
||
pi2 := pi()/2;
|
||
if direc=tgc_direct_desc then
|
||
begin
|
||
p_trans(size,0,-arg-pi2,_x,_y);
|
||
end
|
||
else
|
||
begin
|
||
p_trans(size,0,-arg+pi2,_x,_y);
|
||
end
|
||
return 1;
|
||
end
|
||
function get_angleofhoriz(xarg,ifh,sz); //获取角度以及位置
|
||
begin
|
||
xarg := 0;ifh := false;sz:=0;
|
||
tkxys := array();
|
||
get_axis_type(tpax);
|
||
////////////坐标轴边界///////////////////////////////
|
||
if fzoom_bounds then
|
||
begin
|
||
minv := fzoom_bounds[0];
|
||
manv := fzoom_bounds[1];
|
||
end else
|
||
begin
|
||
minv := minvalue(fxtics_coord_v);
|
||
manv := maxvalue(fxtics_coord_v);
|
||
end
|
||
if not(minv<manv) then return false;
|
||
//////////////////////////////////////////////
|
||
v_to_cvs(tpax,minv,x,y);
|
||
tkxys[0] := array(x,y);
|
||
v_to_cvs(tpax,manv,x2,y2);
|
||
tkxys[1] := array(x2,y2);
|
||
sz := (x2-x)^2+(y2-y)^2;
|
||
if sz>0 then sz := sqrt(sz);
|
||
if length(tkxys)<2 then return false;
|
||
dxy := (tkxys[1]-tkxys[0]);
|
||
if (like_0(dxy[0])) and like_0(dxy[1]) then return false;
|
||
a_180 := pi();
|
||
a_90 := a_180/2;
|
||
a_30 := a_180/6;
|
||
a_60 := a_180/3;
|
||
a_45 := a_180/4;
|
||
a_150 := a_180/6*5;
|
||
xarg := d2angle(array(5,0),dxy); //和x夹角
|
||
yarg := d2angle(array(0,5),dxy); //和y夹角
|
||
if isnan(xarg) then
|
||
begin
|
||
if dxy[0]>0 then xarg := 0;
|
||
else xarg := a_180;
|
||
end
|
||
if isnan(yarg) then
|
||
begin
|
||
if dxy[1]>0 then yarg := 0;
|
||
else yarg := a_180;
|
||
end
|
||
if xarg<a_30 or xarg>a_150 then
|
||
begin
|
||
ifh := true;
|
||
end
|
||
if like_0( xarg) then
|
||
begin
|
||
ifh := true;
|
||
end else
|
||
if a_like_b(xarg,a_180) then
|
||
begin
|
||
xarg := -xarg;
|
||
ifh := true;
|
||
end else
|
||
if a_like_b(yarg,a_90) then
|
||
begin
|
||
xarg := 0;
|
||
ifh := true;
|
||
end else
|
||
if yarg = 0 then
|
||
begin
|
||
xarg := a_90;
|
||
end else
|
||
if yarg=a_180 then
|
||
begin
|
||
xarg:=-a_90;
|
||
end else
|
||
if xarg<a_90 and yarg>a_90 then //第1
|
||
begin
|
||
xarg := -xarg;
|
||
end else
|
||
if xarg>a_90 and yarg>a_90 then //第2
|
||
begin
|
||
xarg :=-xarg;
|
||
end else
|
||
if yarg<a_90 and xarg>a_90 then //第3
|
||
begin
|
||
end else
|
||
if yarg<a_90 and xarg<a_90 then //第4
|
||
begin
|
||
end
|
||
end
|
||
function get_axis_type(tpax);
|
||
begin
|
||
tpax := "x";
|
||
if ifnumber(fytics_coord[1]) and ifnumber(fytics_coord[2]) then tpax := "x";
|
||
else if ifnumber(fytics_coord[2]) and ifnumber(fytics_coord[0]) then tpax := "y";
|
||
else if ifnumber(fytics_coord[0]) and ifnumber(fytics_coord[1]) then tpax := "z";
|
||
return tpax;
|
||
end
|
||
function draw_axis(cvs,subtks);
|
||
begin
|
||
pw := lineinfo.width;
|
||
set_lineinfo_to_canvas(cvs);
|
||
tksize := pw+fticksize;
|
||
tic_space := 3;
|
||
tksizesub := fsubticksize+pw;
|
||
get_axis_type(tpax);
|
||
set_lineinfo_to_canvas(cvs);
|
||
tkxys := array();
|
||
xarg := 0;
|
||
ifvert := false;
|
||
get_angleofhoriz(xarg,ifvert,sz);
|
||
if like_0(sz) then return ;
|
||
for i,v in fxtics_coord_v do
|
||
begin
|
||
v_to_cvs(tpax,v,x,y);
|
||
tkxys[i] := array(x,y);
|
||
end
|
||
///////////////////轴线////////////////////////////////
|
||
|
||
if ftics_segment=tgc_on then
|
||
begin
|
||
if fzoom_bounds then
|
||
begin
|
||
v_to_cvs(tpax,fzoom_bounds[0],x1,y1);
|
||
v_to_cvs(tpax,fzoom_bounds[1],x2,y2);
|
||
cvs.moveto(array(x1,y1));
|
||
cvs.lineto(array(x2,y2));
|
||
x3 := (x1+x2)/2;
|
||
y3 := (y1+y2)/2;
|
||
ax_pos := array(x1,y1,x2,y2,x3,y3);
|
||
end else
|
||
begin
|
||
for i,v in tkxys do
|
||
begin
|
||
if i=0 then
|
||
cvs.moveto(v);
|
||
else
|
||
cvs.lineto(v);
|
||
end
|
||
end
|
||
end
|
||
|
||
/////////////////////////////////////////////////////
|
||
//////////////////刻度线以及刻度值///////////////////////////////////////
|
||
ts_size := array(fontinfo.size+4,fontinfo.size*2+4);
|
||
tcsinfo := array();
|
||
get_tic_to(ftics_direction,tksize,xarg,_xticlen,_yticklen);
|
||
if ifnumber(ftics_color) then cvs.pen.color := ftics_color;
|
||
ftics_recs := array();
|
||
for i,vi in fxtics_coord_v do
|
||
begin
|
||
if fzoom_bounds and (vi<fzoom_bounds[0] or vi>fzoom_bounds[1]) then continue;
|
||
v := tkxys[i];
|
||
lbi := ftics_labels[i];
|
||
x := v[0];
|
||
y := v[1];
|
||
cvs.moveto(array(x,y));
|
||
|
||
x1 :=x+_xticlen;
|
||
y1 := y+_yticklen;
|
||
cvs.lineto(array(x1,y1));
|
||
//continue;
|
||
sz := nil;
|
||
if lbi then
|
||
begin
|
||
sz := array((length(lbi))*fontinfo.size+4,fontinfo.size*2+4) ;//cvs.GetTextExtent(lbi);
|
||
end
|
||
if sz then
|
||
begin
|
||
if ifvert then //x
|
||
begin
|
||
rec := array(x1-sz[0]/2,0,x1+sz[0]/2,0);
|
||
if _yticklen>0 then
|
||
begin
|
||
rec[1] := y1+tic_space;
|
||
rec[3] := y1+sz[1]+tic_space;
|
||
end else
|
||
begin
|
||
rec[1] := y1-sz[1]-tic_space;
|
||
rec[3] := y1-tic_space;
|
||
end
|
||
end else //y
|
||
begin
|
||
ts_size[1] := max(ts_size[1],sz[0]);
|
||
rec := array(0,y1-sz[1]/2,0,y1+sz[1]/2);
|
||
if _xticlen>0 then
|
||
begin
|
||
rec[0] := x1+tic_space;
|
||
rec[2] := x1+sz[0]+tic_space;
|
||
end else
|
||
begin
|
||
rec[0] := x1-sz[0]-tic_space;
|
||
rec[2] := x1-tic_space;
|
||
end
|
||
end
|
||
tcsinfo[length(tcsinfo)] := array(lbi,rec,"h");
|
||
ftics_recs[i] := rec;
|
||
end
|
||
end
|
||
if tcsinfo then
|
||
begin
|
||
set_fontinfo_to_canvas(cvs);
|
||
draw_tics(cvs,tcsinfo);
|
||
end
|
||
/////////////////////////////////////////////////////////////////////////
|
||
////////////////////子刻度线////////////////////////////////////////////////
|
||
get_tic_to(ftics_direction,tksizesub,xarg,_xstic,_ystic);
|
||
for i,v in subtks do
|
||
begin
|
||
v_to_cvs(tpax,v,x,y);
|
||
cvs.moveto(array(x,y));
|
||
//get_tic_to(ftics_direction,tksizesub,xarg,_x,_y);
|
||
cvs.lineto(array(_xstic+x,y+_ystic));
|
||
end
|
||
//if not ax_pos then return ;
|
||
flabel_rgn := array();
|
||
if flabel is class(tg_label_axis) then //绘制标签
|
||
begin
|
||
//tx := ax_pos[2]-ax_pos[1]
|
||
if flabel.visible<>tgc_on then return ;
|
||
t := flabel.text;
|
||
if not t then return ;
|
||
if not fzoom_bounds then return ;
|
||
lbft := flabel.fontinfo;
|
||
sz := lbft.size;
|
||
set_fontinfo_to_canvas(cvs,lbft);
|
||
_x := _xticlen;
|
||
_y := _yticklen;
|
||
bs :=2;//xarg<0?1:2;//(xarg<0?2.2:0.2);
|
||
slen := sz*length(t);
|
||
zlen := max(abs(ax_pos[2]-ax_pos[0]),abs(ax_pos[3]-ax_pos[1]));
|
||
rt := (1-slen/zlen);
|
||
tx := fzoom_bounds[0] + (rt>0? (rt*(fzoom_bounds[1]-fzoom_bounds[0])/2):0);
|
||
v_to_cvs(tpax,tx,x1,y1);
|
||
|
||
nxarg := (r_2_a(xarg) mod 180);//abs()*pi());
|
||
//echo "\r\narg:",r_2_a(xarg),"===",nxarg;
|
||
nxarg := nxarg*pi()/180;
|
||
if _y<0 then _y-=ts_size[0]+tic_space+sz*bs;
|
||
else _y+=ts_size[0]+tic_space+sz*bs;
|
||
if _x<0 then _x -= sz*bs+ts_size[1]+tic_space;
|
||
else _x+=sz*bs+ts_size[1]+tic_space;
|
||
nx := x1+_x;//ax_pos[4]+_x;
|
||
ny := y1+_y;//ax_pos[5]+_y;
|
||
t_rec := array(nx,ny,nx+slen,ny+lbft.size);
|
||
flabel_rgn := rec_to_points(t_rec);
|
||
if like_0(nxarg) then
|
||
begin
|
||
cvs.textout(t,array(nx,ny));
|
||
end else
|
||
begin
|
||
rgn_points_trans(flabel_rgn,-nxarg);
|
||
cvs.SaveDC();
|
||
cvs.trans(-nxarg,nx,ny);
|
||
cvs.textout(t,array(0,0));
|
||
cvs.RestoreDC();
|
||
end
|
||
end
|
||
end
|
||
function set_zoom_bounds(v);
|
||
begin
|
||
if ifarray(v) and v[0]<v[1] then
|
||
begin
|
||
fzoom_bounds := array(v[0],v[1]);
|
||
end else
|
||
begin
|
||
fzoom_bounds := nil;
|
||
end
|
||
end
|
||
function set_tics_direction(v);
|
||
begin
|
||
if v<>ftics_direction and ( v in array(tgc_direct_asc,tgc_direct_desc)) then
|
||
begin
|
||
ftics_direction := v;
|
||
prop_changed("tics_direction",v);
|
||
end
|
||
end
|
||
function tc_to_label(v);
|
||
begin
|
||
return format("%f",v);//tostn(v);
|
||
end
|
||
function set_xtics_coord(v);
|
||
begin
|
||
if v<> fxtics_coord and ifarray(v) then
|
||
begin
|
||
case ftics_style of
|
||
tgc_tics_v:
|
||
begin
|
||
lbs := array();
|
||
for i,vi in v do
|
||
begin
|
||
if not ifnumber(vi) then return ;
|
||
lbs[i] := tc_to_label(vi);
|
||
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_tics_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 ytics_ok(v);
|
||
begin
|
||
if ifarray(v) and length(v)>=3 then
|
||
begin
|
||
nmc := 0;
|
||
for i := 0 to 2 do
|
||
begin
|
||
if ifnumber(v[i]) then nmc++;
|
||
end
|
||
return nmc=2;
|
||
end
|
||
end
|
||
function set_ytics_coord(v);
|
||
begin
|
||
if v<> fytics_coord and ytics_ok(v) then
|
||
begin
|
||
fytics_coord := v;
|
||
prop_changed("ytics_coord",v);
|
||
end
|
||
end
|
||
function set_tics_segment(v);
|
||
begin
|
||
if not tg_boolen_value(n,nv) then return ;
|
||
if ftics_segment<>nv then
|
||
begin
|
||
ftics_segment := nv;
|
||
prop_changed("tics_segment",nv);
|
||
end
|
||
end
|
||
function set_tics_color(v);
|
||
begin
|
||
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_tics_v,tgc_tics_r)) then
|
||
begin
|
||
ftics_style := v;
|
||
case v of
|
||
tgc_tics_v:
|
||
begin
|
||
fxtics_coord := array();
|
||
for i,v in fxtics_coord_v do
|
||
begin
|
||
fxtics_coord[i] := v;
|
||
end
|
||
end
|
||
tgc_tics_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_text = class(tg_base)
|
||
public
|
||
function create(pms);
|
||
begin
|
||
inherited;
|
||
ftextalign := 1;
|
||
clip_state := tgc_off;
|
||
ftext := array();
|
||
fdata := array();
|
||
ffont_angle := 0;
|
||
end
|
||
function paint(cvs);override;
|
||
begin
|
||
if (visible<>tgc_on) then return ;
|
||
if not fdata then return ;
|
||
if not ftext then return ;
|
||
if not zoom_to_xyz(fdata[0],fdata[1],fdata[2],x,y) then return ;
|
||
if clip_state=tgc_on or ((p:=parent) and p.clip_state=tgc_on) then
|
||
begin
|
||
bx := axes.zoom_box;
|
||
vj := fdata;
|
||
if vj[0]<bx[0,0] or vj[1]<bx[1,0] or vj[2]<bx[2,0] or vj[0]>bx[0,1] or vj[1]>bx[1,1] or vj[2]>bx[2,1] then
|
||
begin
|
||
return ;
|
||
end
|
||
cvs.axesclip();
|
||
end
|
||
else cvs.axesunclip();
|
||
get_text_size(w,h,hi);
|
||
modify_text_pos(x,y,w,h,ftextalign);
|
||
FPaintrect := array(x,y,x+w,y+h);
|
||
Frgnpoints := rec_to_points(FPaintrect)[0:3];
|
||
if ffont_angle<>0 then
|
||
begin
|
||
cvs.SaveDC();
|
||
cvs.trans(-ffont_angle,x,y);
|
||
rgn_points_trans(Frgnpoints,-ffont_angle);
|
||
x := 0;
|
||
y := 0;
|
||
end
|
||
if line_mode=tgc_on then
|
||
begin
|
||
set_lineinfo_to_canvas(cvs);
|
||
rc := array(x,y,x+w,y+h);
|
||
cvs.draw_rect().rect(rc).draw();
|
||
end
|
||
set_fontinfo_to_canvas(cvs);
|
||
for i,v in ftext do
|
||
begin
|
||
cvs.textout(v,array(x,y+i*hi));
|
||
end
|
||
if ffont_angle<>0 then
|
||
cvs.RestoreDC();
|
||
end
|
||
function executecommand(cmd,p);override;
|
||
begin
|
||
case cmd of
|
||
"text_rec": return (visible=tgc_on)? FPaintrect:nil;
|
||
"text_rgn": return (visible=tgc_on)? Frgnpoints:nil; //区域
|
||
"point_in_text": return (visible=tgc_on and Frgnpoints)? point_in_rgn(p,Frgnpoints):false; //区域
|
||
end ;
|
||
return inherited;
|
||
end
|
||
published
|
||
property text read ftext write set_text; //一维字符串数组
|
||
property data read fdata write set_data; //位置 x.y
|
||
property font_angle read ffont_angle write set_font_angle; //角度
|
||
property textalign read ftextalign write set_textalign;
|
||
private
|
||
FPaintrect;
|
||
Frgnpoints;
|
||
ftext;
|
||
fdata;
|
||
ffont_angle;
|
||
ftextalign;
|
||
private
|
||
function set_textalign(v);
|
||
begin
|
||
if v<>ftextalign and ( v in (1->9)) then
|
||
begin
|
||
ftextalign := v;
|
||
prop_changed("textalign",v);
|
||
end
|
||
end
|
||
function get_text_size(w,h,hi);
|
||
begin
|
||
fw := fontinfo.size;
|
||
fh := fw*2;
|
||
hi:=fh+2;
|
||
w := 0;
|
||
h := 0;
|
||
for i,v in ftext do
|
||
begin
|
||
si := v;
|
||
w := max(w,length(si)*fw);
|
||
h+=fh;
|
||
end
|
||
h+=2;
|
||
end
|
||
function set_text(v);
|
||
begin
|
||
tx := array();
|
||
if ifstring(v) and v then return set_text(array(v));
|
||
if not ifarray(v) then return ;
|
||
for i,vi in v do
|
||
begin
|
||
if ifstring(vi) then tx[length(tx)] := vi;
|
||
end
|
||
if ftext<>tx then
|
||
begin
|
||
ftext :=tx;
|
||
prop_changed("text",tx);
|
||
end
|
||
end
|
||
function set_data(d);
|
||
begin
|
||
if fdata<>d and ifarray(d) and ifnumber(d[0]) and ifnumber(d[1]) then
|
||
begin
|
||
fdata := d;
|
||
prop_changed("data",d);
|
||
end
|
||
end
|
||
function set_font_angle(arg);
|
||
begin
|
||
if arg<>ffont_angle then
|
||
begin
|
||
ffont_angle := arg;
|
||
prop_changed("font_angle",arg);
|
||
end
|
||
end
|
||
|
||
end
|
||
type tg_label =class(tg_base) //标签对象
|
||
function create(pms);
|
||
begin
|
||
inherited;
|
||
ftextalign := 1;
|
||
clip_state := tgc_off;
|
||
ftext := false;
|
||
flocation := tgc_by_coordinates;
|
||
fposition := array(0,0);
|
||
ffill_mode := false;
|
||
ffont_angle := 0;
|
||
fauto_rotation := false;
|
||
end
|
||
function paint(cvs);override;
|
||
begin
|
||
if tgc_on<>visible then return ;
|
||
if not ftext then return ;
|
||
if clip_state=tgc_on then cvs.axesclip();
|
||
else cvs.axesunclip();
|
||
set_fontinfo_to_canvas(cvs);
|
||
p := fposition;
|
||
|
||
if fauto_position=tgc_on then
|
||
begin
|
||
p := fauto_position_value;
|
||
end else
|
||
begin
|
||
p := fposition;
|
||
end
|
||
case flocation of
|
||
tgc_by_axes:
|
||
begin
|
||
if not axes_mapping(p[0],p[1],0,x_,y_) then return ;
|
||
end else //tgc_by_coordinates:
|
||
begin
|
||
if not zoom_to_xyz(p[0],p[1],0,x_,y_) then return ;
|
||
end
|
||
end
|
||
txtw := length(ftext)*fontinfo.size;
|
||
txth := fontinfo.size;
|
||
modify_text_pos(x_,y_,txtw,txth,ftextalign);//修正位置
|
||
rec := array(x_,y_,x_+txtw,y_+txth);
|
||
flabel_rgn := rec_to_points(rec)[0:3];
|
||
if ffont_angle<>0 then
|
||
begin
|
||
rgn_points_trans(flabel_rgn,-ffont_angle);
|
||
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
|
||
function executecommand(cmd,p);override;
|
||
begin
|
||
case cmd of
|
||
"auto_position_value":
|
||
begin
|
||
fauto_position_value := p;
|
||
return ;
|
||
end
|
||
"label_rgn": return (visible=tgc_on)?flabel_rgn:nil; //标签的区域
|
||
end;
|
||
return inherited;
|
||
end
|
||
protected
|
||
function check_parent(p);override;
|
||
begin
|
||
return (not p) or (p is class(tg_axis));
|
||
end
|
||
published
|
||
property textalign read ftextalign write set_textalign;
|
||
property text read ftext write set_text;//= ""
|
||
property position read fposition write set_position;//[-27.697388,-1.7130177]
|
||
property location read flocation write Set_location;
|
||
property auto_position read fauto_position write set_auto_position;//"on"
|
||
//property auto_position_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
|
||
ftextalign;
|
||
flabel_rgn;
|
||
flocation;
|
||
ftext;
|
||
fposition;
|
||
fauto_position_value;
|
||
ffont_angle;
|
||
fauto_position;
|
||
fauto_rotation;
|
||
private
|
||
function set_textalign(v);
|
||
begin
|
||
if v<>ftextalign and ( v in (1->9)) then
|
||
begin
|
||
ftextalign := v;
|
||
prop_changed("textalign",v);
|
||
end
|
||
end
|
||
function Set_location(v);
|
||
begin
|
||
if flocation<>v and (v in array(tgc_by_axes,tgc_by_coordinates)) then
|
||
begin
|
||
flocation := v;
|
||
end
|
||
end
|
||
function set_auto_position(v);
|
||
begin
|
||
if not tg_boolen_value(v,nv) then return ;
|
||
if nv<>fauto_position then
|
||
begin
|
||
fauto_position := nv;
|
||
prop_changed("auto_position",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_position(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("position",v);
|
||
end
|
||
end
|
||
function set_auto_rotation(v);
|
||
begin
|
||
if not tg_boolen_value(v,nv) then return ;
|
||
if fauto_rotation<>nv then
|
||
begin
|
||
fauto_rotation := nv;
|
||
prop_changed("auto_rotation",nv);
|
||
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_tips = class(tg_base) //提示
|
||
function create(pms);
|
||
begin
|
||
inherited;
|
||
flocation := tgc_by_coordinates;
|
||
fdisplay_components := "xy";
|
||
fbox_mode := tgc_on;
|
||
mark_mode := tgc_on;
|
||
markinfo.Style := tgc_mks_square;
|
||
markinfo.size := 5;
|
||
fline_style := 0;
|
||
fforeground := -1;
|
||
fbackground := -2;
|
||
fmark_style := 11;
|
||
fdata_idx := -1;
|
||
frow_mode := false;
|
||
end
|
||
function executecommand(cmd,pm);override;
|
||
begin
|
||
case cmd of
|
||
"fresh":
|
||
begin
|
||
FData := nil;
|
||
ftext :="";
|
||
f_ps := nil;
|
||
prop_changed("fdata_idx",pm);
|
||
end
|
||
"tips_rec": return (visible=tgc_on )?FPaintrect:nil; //区域
|
||
"hit_tip":
|
||
begin
|
||
if (visible<>tgc_on) then return nil;
|
||
return pointinrect(pm,FPaintrect);
|
||
end
|
||
end
|
||
end
|
||
function paint(cvs);override;
|
||
begin
|
||
FPaintrect := array();
|
||
if tgc_on<>visible then return ;
|
||
p := parent;
|
||
if not p then return ;
|
||
d := get_data();
|
||
if ifnil(d) then return ;
|
||
ss := get_text();
|
||
if not ss then return ;
|
||
if not(f_ps and ifnumber(f_ps[0]) and ifnumber(f_ps[1])) then return ;
|
||
if clip_state=tgc_on then //迂回处理
|
||
begin
|
||
bx := axes.zoom_box;
|
||
vj := d;
|
||
if vj[0]<bx[0,0] or vj[1]<bx[1,0] or vj[2]<bx[2,0] or vj[0]>bx[0,1] or vj[1]>bx[1,1] or vj[2]>bx[2,1] then
|
||
begin
|
||
return ;
|
||
end
|
||
cvs.axesclip();
|
||
end
|
||
else cvs.axesunclip();
|
||
ws := 0;
|
||
hs := array();
|
||
w := fontinfo.size;
|
||
h := w*2;
|
||
for i,v in ss do
|
||
begin
|
||
ws := max(ws,length(v)*w+w);
|
||
hs[i] := h+4;
|
||
end
|
||
zoom_to_xyz(f_ps[0],f_ps[1],z,x_,y_);
|
||
sz := array(ws,sum(hs));
|
||
if mark_mode = tgc_on then
|
||
begin
|
||
mk := markinfo;
|
||
msz := max(ceil(mk.size/2),2);
|
||
paint_marks(mk,cvs,array((x_,y_)));
|
||
end
|
||
case flocation of
|
||
tgc_in_upper_left: lc := 0;
|
||
tgc_in_upper_right: lc := 1;
|
||
tgc_in_lower_right: lc := 2;
|
||
tgc_in_lower_left: lc := 3;
|
||
else
|
||
lc := (fdata_idx+1) mod 3;//randomfrom(array(0,1,2,3));
|
||
end ;
|
||
rec := get_rect_at_corner(x_,y_,sz[0],sz[1],msz,lc);
|
||
FPaintrect := rec;
|
||
if fbox_mode=tgc_on then
|
||
begin
|
||
set_lineinfo_to_canvas(cvs);
|
||
cvs.draw_rect.rect(rec).draw();
|
||
end
|
||
b_x := rec[0];
|
||
b_y := rec[1];
|
||
set_fontinfo_to_canvas(cvs);
|
||
for i,v in ss do
|
||
begin
|
||
rci := array(b_x,b_y,b_x+ws,b_y+hs[i]);
|
||
cvs.drawtext(v,rci);
|
||
b_y+=hs[i];
|
||
end
|
||
end
|
||
published
|
||
//property interp_mode read finterp_mode write finterp_mode; //"on"
|
||
property location read flocation write set_location; //对应位置
|
||
property box_mode read fbox_mode write set_box_mode; //"on"
|
||
property display_components read fdisplay_components write set_display_components; //"xy"
|
||
property data_idx read fdata_idx write set_data_idx; //对应数据序号
|
||
property display_function read fdisplay_function write fdisplay_function;
|
||
property text read get_text write set_text;
|
||
property data read get_data; //数据
|
||
private
|
||
[weakref]fdisplay_function;
|
||
flocation;
|
||
fbox_mode;
|
||
//finterp_mode;
|
||
fdisplay_components;
|
||
fdata_idx;
|
||
ftext;
|
||
fdata;
|
||
FPaintrect;
|
||
//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"]
|
||
//detached_position ;//= []
|
||
protected
|
||
function check_parent(p);override;
|
||
begin
|
||
return ifnil(p) or (p is class(tg_graph));
|
||
end
|
||
private
|
||
f_ps;
|
||
function init_display(tip,ps,txts);
|
||
begin
|
||
d := get_data();
|
||
if ifarray(d) and ifnumber(d[0]) and ifnumber(d[1]) then
|
||
begin
|
||
px := d[0];
|
||
py := d[1];
|
||
ps := array(px,py);
|
||
txts := array();
|
||
for i := 1 to length(fdisplay_components) do
|
||
begin
|
||
vi := fdisplay_components[i];
|
||
case vi of
|
||
"x","X":
|
||
begin
|
||
txts[length(txts)] := vi+format(":%f",px);
|
||
end
|
||
"y","Y":
|
||
begin
|
||
txts[length(txts)] := vi+format(":%f",py);
|
||
end
|
||
end ;
|
||
end
|
||
end
|
||
end
|
||
function set_text(txt);
|
||
begin
|
||
if get_text()<>txt and ifarray(txt) then
|
||
begin
|
||
ftext := array();
|
||
for i,v in txt do
|
||
begin
|
||
if ifstring(v) then
|
||
begin
|
||
ftext[idx++] := v;
|
||
end
|
||
end
|
||
end
|
||
end
|
||
function get_text();
|
||
begin
|
||
if ftext then return ftext;
|
||
if iffuncptr(display_function) then
|
||
begin
|
||
call(display_function,self(true),ps,txt);
|
||
f_ps := ps;
|
||
end else
|
||
begin
|
||
init_display(self(true),ps,txt);
|
||
f_ps := ps;
|
||
end
|
||
ftext := txt;
|
||
return ftext;
|
||
end
|
||
function get_data();
|
||
begin
|
||
if fdata then return FData;
|
||
if not(fdata_idx>=0) then return nil;
|
||
p := parent;
|
||
if p then
|
||
begin
|
||
FData := p.get_graph_data_by_idx(fdata_idx);
|
||
return fdata;
|
||
end
|
||
return nil;
|
||
end
|
||
function set_data_idx(idx);
|
||
begin
|
||
if ifnumber(idx) and idx<>fdata_idx then
|
||
begin
|
||
fdata_idx := idx ;
|
||
executecommand("fresh",pm);
|
||
|
||
end
|
||
end
|
||
function set_location(v);
|
||
begin
|
||
if v<>flocation then
|
||
begin
|
||
flocation := v;
|
||
prop_changed("location",nv);
|
||
end
|
||
end
|
||
function set_display_components(v);
|
||
begin
|
||
if not( v and ifstring(v)) then return ;
|
||
if d_comp_ok(v) and fdisplay_components<>v then
|
||
begin
|
||
fdisplay_components := v;
|
||
executecommand("fresh",pm);
|
||
end
|
||
end
|
||
function set_box_mode(v);
|
||
begin
|
||
if not tg_boolen_value(v,nv) then return ;
|
||
if nv<>fbox_mode then
|
||
begin
|
||
fbox_mode := nv;
|
||
prop_changed("box_mode",nv);
|
||
end
|
||
end
|
||
function d_comp_ok(dcp);
|
||
begin
|
||
t := array("x":1,"y":1,"z":1);
|
||
for i := 1 to length(dcp) do
|
||
begin
|
||
vi := dcp[i];
|
||
if t[vi]<>1 then return false;
|
||
t[vi] := 2;
|
||
end
|
||
return true;
|
||
end
|
||
end
|
||
type tg_legend = class(tg_base) //图例
|
||
function create(pms);
|
||
begin
|
||
inherited;
|
||
clip_state := tgc_off;
|
||
flocation := tgc_in_upper_right;
|
||
flinks := array();
|
||
FText := array();
|
||
fposition := nil;
|
||
end
|
||
function paint(cvs);override;
|
||
begin
|
||
if tgc_on<>visible then return ;
|
||
if clip_state=tgc_on then cvs.axesclip();
|
||
else cvs.axesunclip();
|
||
get_lenged_sizes(lw,lh,ws,hs,objs,ss);
|
||
arec := cvs.axesrec;
|
||
rc := arec;
|
||
dis := 30;
|
||
cvs.axesunclip();
|
||
set_lineinfo_to_canvas(cvs);
|
||
case flocation of
|
||
tgc_upper_caption:
|
||
begin
|
||
x := arec[0];
|
||
y := arec[1];
|
||
mx := ceil((arec[2]-arec[0]-lw)/2)-dis;
|
||
rc := get_rect_at_corner(x,y,lw,lh,dis,2,mx);
|
||
cvs.draw_rect().rect(rc).draw();
|
||
end
|
||
tgc_lower_caption:
|
||
begin
|
||
x := arec[0];
|
||
y := arec[3];
|
||
mx := ceil((arec[2]-arec[0]-lw)/2)-dis;
|
||
rc := get_rect_at_corner(x,y,lw,lh,dis,1,mx);
|
||
cvs.draw_rect().rect(rc).draw();
|
||
end
|
||
tgc_in_upper_right:
|
||
begin
|
||
x := arec[2];
|
||
y := arec[1];
|
||
rc := get_rect_at_corner(x,y,lw,lh,dis,3);
|
||
cvs.draw_rect().rect(rc).draw();
|
||
end
|
||
tgc_in_upper_left:
|
||
begin
|
||
x := arec[0];
|
||
y := arec[1];
|
||
rc := get_rect_at_corner(x,y,lw,lh,dis,2);
|
||
cvs.draw_rect().rect(rc).draw();
|
||
end
|
||
tgc_in_lower_left:
|
||
begin
|
||
x := arec[0];
|
||
y := arec[3];
|
||
rc := get_rect_at_corner(x,y,lw,lh,dis,1);
|
||
cvs.draw_rect().rect(rc).draw();
|
||
end
|
||
|
||
tgc_in_lower_right:
|
||
begin
|
||
x := arec[2];
|
||
y := arec[3];
|
||
rc := get_rect_at_corner(x,y,lw,lh,dis,0);
|
||
cvs.draw_rect().rect(rc).draw();
|
||
end
|
||
tgc_by_coordinates: //根据位置信息设置处理
|
||
begin
|
||
if ifnil(fposition) then
|
||
begin
|
||
x := arec[2];
|
||
y := arec[1];
|
||
rc := get_rect_at_corner(x,y,lw,lh,0,3);
|
||
xyz_to_zoom(rc[0],rc[1],0,_x,_y,_z);
|
||
fposition := array(_x,_y);
|
||
end else
|
||
begin
|
||
zoom_to_xyz(fposition[0],fposition[1],0,_x,_y);
|
||
rc:= array(_x,_y,_x+lw,_y+lh);
|
||
end
|
||
cvs.draw_rect().rect(rc).draw();
|
||
end
|
||
tgc_by_axes:
|
||
begin
|
||
if ifnil(fposition) then
|
||
begin
|
||
x := arec[2];
|
||
y := arec[1];
|
||
rc := get_rect_at_corner(x,y,lw,lh,0,3);
|
||
axes_unmapping(rc[0],rc[1],_x,_y,_z);
|
||
fposition := array(_x,_y);
|
||
end else
|
||
begin
|
||
axes_mapping(fposition[0],fposition[1],0,_x,_y);
|
||
rc:= array(_x,_y,_x+lw,_y+lh);
|
||
end
|
||
cvs.draw_rect().rect(rc).draw();
|
||
end
|
||
end;
|
||
b_x := rc[0];
|
||
b_y := rc[1];
|
||
flegend_rec := rc;
|
||
set_fontinfo_to_canvas(cvs);
|
||
flegend_sub_recs := array();
|
||
for i,v in objs do
|
||
begin
|
||
hi := hs[i];
|
||
if v then
|
||
begin
|
||
rci := array(b_x,b_y,b_x+ws[0],b_y+hi);
|
||
v.paint_legend(cvs,rci);
|
||
end
|
||
flegend_sub_recs[i] := rci;
|
||
si := ss[i];
|
||
if si then
|
||
begin
|
||
rci := array(b_x+ws[0],b_y,b_x+ws[0]+ws[1],b_y+hi);
|
||
cvs.drawtext(si,rci);
|
||
end
|
||
b_y+=hi;
|
||
end
|
||
cvs.axesclip();
|
||
end
|
||
function executecommand(cmd,p);override;
|
||
begin
|
||
case cmd of
|
||
"hit_legend":
|
||
begin
|
||
if (visible<>tgc_on) then return -1;
|
||
x := p[0];y := p[1];
|
||
for i,v in flegend_sub_recs do
|
||
begin
|
||
if pointinrect(p,v) then return i;
|
||
end
|
||
return -1;
|
||
end
|
||
"legend_rec":return (visible=tgc_on)? flegend_rec:nil; //整个图例区域
|
||
"legend_sub_recs":return (visible=tgc_on)? flegend_sub_recs:nil; //各个图像的区域
|
||
end
|
||
return inherited;
|
||
end
|
||
published
|
||
property location read flocation write set_location; //相对位置类型
|
||
property position read fposition write set_position; //位置
|
||
property links read flinks write set_links; //图形
|
||
property text read FText write set_text; //图例字符串
|
||
protected
|
||
function check_parent(p);override;
|
||
begin
|
||
return ifnil(p) or (p is class(tg_axes));
|
||
end
|
||
private
|
||
[weakref] flinks;
|
||
flocation;
|
||
FText;
|
||
fposition;
|
||
flegend_rec;
|
||
flegend_sub_recs;
|
||
//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 ;//= []
|
||
private
|
||
function get_lenged_sizes(lw,lh,ws,hs,objs,ss);
|
||
begin
|
||
ws := array(0,0);
|
||
hs := array();
|
||
w := fontinfo.size;
|
||
h := w*2;
|
||
objs := array();
|
||
ss := array();
|
||
for i:= 0 to max(length(flinks),length(ftext))-1 do
|
||
begin
|
||
vi := flinks[i];
|
||
si := ftext[i];
|
||
if vi is class(tg_graph) then
|
||
begin
|
||
objs[i] := vi;
|
||
vi.get_legend_size(w1,h1);
|
||
ws[0] := max(ws[0],w1);
|
||
end else
|
||
begin
|
||
h1 := 0;
|
||
objs[i] := 0;
|
||
end
|
||
if ifstring(si) then
|
||
begin
|
||
ws[1] := max(w*length(si)+2,ws[1]);
|
||
ss[i] := si;
|
||
end else
|
||
begin
|
||
ss[i] := nil;
|
||
end
|
||
hs[i] := max(h+4,h1);
|
||
end
|
||
lw := ws[0]+ws[1];
|
||
lh := sum(hs);
|
||
end
|
||
function set_position(v); //位置
|
||
begin
|
||
if fposition<>v and ifarray(v) and ifnumber(v[0]) and ifnumber(v[1]) then
|
||
begin
|
||
fposition := array(v[0],v[1]);
|
||
prop_changed("position",v);
|
||
end
|
||
end
|
||
function set_text(s); //图例字符串设置
|
||
begin
|
||
idx := 0;
|
||
flg := false;
|
||
if not ifarray(s) then return ;
|
||
if ftext=s then return ;
|
||
ftext := s;
|
||
prop_changed("text",s);
|
||
end
|
||
function set_links(vs); //关联图
|
||
begin
|
||
if ifarray(vs) and vs<>flinks then
|
||
begin
|
||
flinks := vs;
|
||
prop_changed("links_changed",vs);
|
||
end
|
||
end
|
||
function set_location(v); //位置类型
|
||
begin
|
||
vs := static array(tgc_in_upper_right:true,tgc_in_upper_left:true,tgc_in_lower_right:true,tgc_in_lower_left:true,
|
||
//tgc_out_upper_right,tgc_out_upper_left,tgc_out_lower_right,tgc_out_lower_left,
|
||
tgc_upper_caption:true,tgc_lower_caption:true,
|
||
tgc_by_coordinates:true,tgc_by_axes:true);
|
||
if v<>flocation and (vs[v]) then
|
||
begin
|
||
flocation := v;
|
||
end
|
||
end
|
||
end
|
||
type tg_graph_base = class(tg_base) //兼容绘图和goup两个类型
|
||
function create(pm);
|
||
begin
|
||
inherited;
|
||
end
|
||
function get_data_bounds();virtual; //获取数据边界
|
||
begin
|
||
return get_node_data_bounds(self(true));
|
||
end
|
||
end
|
||
type tg_graph = class(tg_graph_base) //绘图对象,包括数据,提示等内容
|
||
function create(pms);
|
||
begin
|
||
inherited;
|
||
fgraph_data := array();
|
||
end
|
||
function get_data_tips(); //获得数据提示对象
|
||
begin
|
||
r := array();
|
||
for i:= 0 to NodeCount-1 do
|
||
begin
|
||
vi := GetNodeByIndex(i);
|
||
if vi is class(tg_tips) then
|
||
begin
|
||
r[ridx++] := vi;
|
||
end
|
||
end
|
||
return r;
|
||
end
|
||
function get_legend_size(w,h);virtual; //图例大小
|
||
begin
|
||
h := fontinfo.size+4;
|
||
w := 100;
|
||
end
|
||
function paint_legend(cvs,rec);virtual; //绘制图例
|
||
begin
|
||
|
||
end
|
||
function get_graph_data_by_idx(idx); //获取数据点
|
||
begin
|
||
return fgraph_data[idx];
|
||
end
|
||
property graph_data read fgraph_data write set_graph_data; //数据
|
||
protected
|
||
fgraph_data;//数据
|
||
protected
|
||
function prop_changed(n,v);override; //属性改变处理
|
||
begin
|
||
case n of
|
||
"data":
|
||
begin
|
||
for i,v in get_data_tips() do
|
||
begin
|
||
v.executecommand("fresh",nil);
|
||
end
|
||
ax := axes;
|
||
if ax then
|
||
ax.executecommand(cmd_data_changed);
|
||
end else
|
||
begin
|
||
inherited;
|
||
end
|
||
end ;
|
||
end
|
||
function set_graph_data(v);virtual;
|
||
begin
|
||
if v<>fgraph_data then
|
||
begin
|
||
fgraph_data := v;
|
||
prop_changed("data",v);
|
||
end
|
||
end
|
||
end
|
||
type tg_Polyline = class(tg_graph) //线图对象
|
||
function create(pms);
|
||
begin
|
||
inherited;
|
||
clip_state := tgc_on;
|
||
fclosed := tgc_off;
|
||
line_mode := tgc_on;
|
||
mark_mode := tgc_off;
|
||
fpolyline_style := tgc_LS_interpolated;// interpolated,staircase,barplot,arrowed,filled,bar
|
||
fbar_width := 0.3;
|
||
fdata_bounds := array((0,1),(0,1),(0,1));
|
||
end
|
||
function get_data_bounds();override; //数据边界
|
||
begin
|
||
return fdata_bounds;
|
||
end
|
||
function paint(cvs);override; //绘图
|
||
begin
|
||
if tgc_on<> visible then return ;
|
||
bx := axes.zoom_box;
|
||
tempbarw := 0;
|
||
z0 := bx[2,0];
|
||
fface_rgn := array();
|
||
if clip_state=tgc_on then
|
||
begin
|
||
//cvs.axesclip();
|
||
fface_rgn := array();
|
||
for i,v in rec_to_points( array(bx[0,0],bx[1,0],bx[0,1],bx[1,1])) do
|
||
begin
|
||
zoom_to_xyz(v[0],v[1],z0,x,y);
|
||
fface_rgn[i] := array(x,y);
|
||
end
|
||
cvs.clip_rgn(fface_rgn);
|
||
end else
|
||
begin
|
||
cvs.axesunclip();
|
||
end
|
||
xys := array();
|
||
ys := array();
|
||
for i,v in fgraph_data do
|
||
begin
|
||
if not zoom_to_xyz(v[0],v[1],z0,x,y) then return ;
|
||
if not(tempbarw) and fbar_width>0 then ////////处理bar的宽度///////
|
||
begin
|
||
b := get_abs_barwidth();
|
||
zoom_to_xyz((v[0]+b/2),v[1],z0,xtemp,ytemp);
|
||
xtemp-=x;
|
||
ytemp-=y;
|
||
tempbarw := array();
|
||
tempbarw[0] := b*(xtemp)/(abs(xtemp)+abs(ytemp));
|
||
tempbarw[1] := b*(ytemp)/(abs(xtemp)+abs(ytemp));
|
||
end
|
||
xys[i] := array(integer(x),integer(y));
|
||
case fpolyline_style of
|
||
tgc_LS_bar,tgc_ls_Bar2,tgc_LS_barplot,tgc_LS_filled:
|
||
begin
|
||
zoom_to_xyz(v[0],0,0,x,y) ;
|
||
ys[i] := array(x,y);
|
||
end
|
||
end;
|
||
end
|
||
fline_points_in_canvas := xys;
|
||
pinfo := array("line_mode":line_mode,"bar_width":tempbarw,"color":lineinfo.color,"bkcolor":lineinfo.bkcolor,"xy0":ys,"bar_rgns",array());
|
||
set_lineinfo_to_canvas(cvs);
|
||
paint_lines(cvs,fpolyline_style,xys,fclosed,pinfo);
|
||
fline_bar_rgn := pinfo["bar_rgns"];
|
||
mk := markinfo.clone();
|
||
if mark_mode=tgc_on and mk.size>2 then
|
||
begin
|
||
paint_marks(mk,cvs,xys);
|
||
end
|
||
inherited;
|
||
end
|
||
function executecommand(cmd,p);override;
|
||
begin
|
||
case cmd of
|
||
"hit_point":
|
||
begin
|
||
if not(fface_rgn and point_in_rgn(p,fface_rgn)) then return -1;
|
||
case fpolyline_style of
|
||
tgc_LS_bar,tgc_ls_Bar2:
|
||
begin
|
||
for i,v in fline_bar_rgn do
|
||
begin
|
||
if point_in_rgn(p,v) then return i;
|
||
end
|
||
end else
|
||
begin
|
||
sz := markinfo.size+5;
|
||
for i,v in fline_points_in_canvas do
|
||
begin
|
||
if sqrt(sum((p-v)^2))<sz then return i;
|
||
end
|
||
end
|
||
end;
|
||
return -1;
|
||
end
|
||
"points_in_canvas":return (visible=tgc_on)? fline_points_in_canvas:array(); //数据散点
|
||
"points_in_range":return (visible=tgc_on)? point_in_rgn(p,fline_points_in_canvas):false;
|
||
end;
|
||
return inherited;
|
||
end
|
||
function get_legend_size(w,h);virtual; //获取图例大小
|
||
begin
|
||
mk := markinfo;
|
||
h := fontinfo.size+4;
|
||
w := 100;
|
||
if mark_mode=tgc_on then
|
||
begin
|
||
h := max(10,mk.size+4);
|
||
w := 5*h;
|
||
end
|
||
end
|
||
function paint_legend(cvs,rec);override; //绘制图例
|
||
begin
|
||
set_lineinfo_to_canvas(cvs);
|
||
dh := (rec[3]-rec[1]);
|
||
y0 := ceil(rec[1]+dh/2);
|
||
dis := ceil((rec[2]-rec[0])/5);
|
||
case fpolyline_style of
|
||
tgc_LS_bar,tgc_LS_bar2,tgc_LS_barplot,tgc_LS_filled:
|
||
begin
|
||
xys := array((rec[0]+dis,y0-dh/4),(rec[0]+4*dis,y0-dh/4),(rec[0]+4*dis,y0+dh/4),(rec[0]+dis,y0+dh/4));
|
||
paint_lines(cvs,tgc_LS_filled,xys,tgc_on,array("line_mode":line_mode,"bar_width":array(get_abs_barwidth(),0),"color":lineinfo.color,"bkcolor":lineinfo.bkcolor));
|
||
end else
|
||
begin
|
||
xys := array((rec[0]+dis,y0),(rec[0]+4*dis,y0));
|
||
paint_lines(cvs,tgc_LS_interpolated,xys,0,array("line_mode":line_mode,"bar_width":array(get_abs_barwidth(),0),"color":lineinfo.color,"bkcolor":lineinfo.bkcolor));
|
||
end
|
||
end ;
|
||
mk := markinfo.clone();
|
||
if mark_mode=tgc_on and mk.size>2 then
|
||
begin
|
||
xys := array((rec[0]+dis*2,y0),(rec[0]+3*dis,y0));
|
||
paint_marks(mk,cvs,xys);
|
||
end
|
||
end
|
||
property closed read fclosed write set_line_closed;//= "off" 封闭
|
||
property polyline_style read fpolyline_style write set_polyline_style;//= "0" 线型
|
||
property bar_width read fbar_width write set_bar_width;//= "0" 柱状宽度
|
||
private
|
||
fline_points_in_canvas;
|
||
fline_bar_rgn;
|
||
fface_rgn;
|
||
fdata_bounds;
|
||
fclosed;
|
||
fforeground;
|
||
fbackground;
|
||
fpolyline_style;
|
||
fbar_width;
|
||
//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 ;//= []
|
||
protected
|
||
function set_graph_data(d);override; //设置数据
|
||
begin
|
||
if d<>fgraph_data then
|
||
begin
|
||
fx := d[:,0];
|
||
fy := d[:,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);
|
||
inherited;
|
||
end
|
||
end
|
||
private
|
||
function get_abs_barwidth();//获得
|
||
begin
|
||
if fbar_width>0 and fbar_width<=1 then
|
||
begin
|
||
dx := (fdata_bounds[0,1]-fdata_bounds[0,0])/(length(fgraph_data)-1);
|
||
if zoom_to_xyz(0,0,nil,x1,y1) and zoom_to_xyz(dx,0,nil,x2,y2) then
|
||
begin
|
||
return (abs(x1-x2)+abs(y1-y2))*fbar_width;
|
||
end
|
||
end
|
||
return fbar_width;
|
||
end
|
||
function set_bar_width(v);
|
||
begin
|
||
if v<>fbar_width and v>0 then
|
||
begin
|
||
fbar_width := v;
|
||
prop_changed("bar_width",nv);
|
||
end
|
||
end
|
||
function set_line_closed(v);
|
||
begin
|
||
if not tg_boolen_value(v,nv) then return ;
|
||
if nv<>fclosed then
|
||
begin
|
||
fclosed := nv;
|
||
prop_changed("closed",nv);
|
||
end
|
||
end
|
||
function set_polyline_style(v);
|
||
begin
|
||
if v<>fpolyline_style then
|
||
begin
|
||
fpolyline_style := v;
|
||
end
|
||
end
|
||
end
|
||
type tg_gdi = class(tg_const) //gdi对象基类
|
||
function create(awner);
|
||
begin
|
||
fpdata := array();
|
||
FOwner := awner;
|
||
end
|
||
function clone();//克隆信息
|
||
begin
|
||
r := createobject(self(true).Classinfo(1),nil);
|
||
r.fpdata := fpdata;
|
||
return r;
|
||
end
|
||
property info read fpdata write set_pdatas; //数据信息
|
||
[weakref]flinker;
|
||
protected
|
||
function check_prop(idx,v);virtual;//检查数据
|
||
begin
|
||
return true;
|
||
end
|
||
function set_pdatas(d); //设置数据
|
||
begin
|
||
if flinker then
|
||
begin
|
||
flinker.ParentFont := false;
|
||
if flinker<>FOwner then
|
||
begin
|
||
ft := flinker.fontinfo;
|
||
ft.info := d;
|
||
return ;
|
||
end
|
||
end
|
||
{
|
||
if (flinker and flinker<>FOwner) then
|
||
begin
|
||
flinker.ParentFont := false;
|
||
ft := flinker.fontinfo;
|
||
ft.info := d;
|
||
return ;
|
||
end }
|
||
for i,v in d do
|
||
begin
|
||
if fpdata[i]<>v and check_prop(i,v) then
|
||
begin
|
||
cg := true;
|
||
fpdata[i] := v;
|
||
end
|
||
end
|
||
if cg then
|
||
begin
|
||
pdata_changed();
|
||
end
|
||
end
|
||
function pdata_changed();virtual; //数据改变
|
||
begin
|
||
if fonwer then fonwer.invalidate();
|
||
end
|
||
function get_pdata(idx);//获取单个字段
|
||
begin
|
||
return fpdata[idx];
|
||
end
|
||
function set_pdata(idx,v);//设置单个值
|
||
begin
|
||
set_pdatas(array(idx:v));
|
||
end
|
||
fpdata; //数据
|
||
private
|
||
[weakref]FOwner;
|
||
end
|
||
type tg_line_info = class(tg_gdi) //线型信息
|
||
function create(awer);
|
||
begin
|
||
inherited;
|
||
fpdata := array("color":0,"size":1,"style":tgc_PS_SOLID,"bkcolor":nil);
|
||
end
|
||
property style index "style" read get_pdata write set_pdata;
|
||
property width index "size" read get_pdata write set_pdata;
|
||
property size index "size" read get_pdata write set_pdata;
|
||
property color index "color" read get_pdata write set_pdata;
|
||
property bkcolor index "bkcolor" read get_pdata write set_pdata;
|
||
protected
|
||
function check_prop(idx,v);override;//检查数据
|
||
begin
|
||
case idx of
|
||
"size":
|
||
begin
|
||
return ifnumber(v) and v>=0;
|
||
end
|
||
"style","color":
|
||
begin
|
||
return ifnumber(v);
|
||
end
|
||
"bkcolor":
|
||
begin
|
||
return ifnumber(v) or ifnil(v);
|
||
end
|
||
end
|
||
return false;
|
||
end
|
||
end
|
||
type tg_font_info = class(tg_gdi) //字体信息
|
||
function create(awner);
|
||
begin
|
||
inherited;
|
||
fpdata := array("style":nil,"size":7,"color":0,"bkcolor":nil);
|
||
end
|
||
property style index "style" read get_pdata write set_pdata;
|
||
property size index "size" read get_pdata write set_pdata;
|
||
property color index "color" read get_pdata write set_pdata;
|
||
property bkcolor index "bkcolor" read get_pdata write set_pdata;
|
||
protected
|
||
function check_prop(idx,v);override;//检查数据
|
||
begin
|
||
case idx of
|
||
"size":
|
||
begin
|
||
return ifnumber(v) and v>5;
|
||
end
|
||
"style":
|
||
begin
|
||
return ifnumber(v);
|
||
end
|
||
"color":
|
||
begin
|
||
return ifnumber(v) or (v=tgc_complementary_color);
|
||
end
|
||
"bkcolor":
|
||
begin
|
||
return ifnumber(v) or ifnil(v);
|
||
end
|
||
end
|
||
return false;
|
||
end
|
||
end
|
||
type tg_mark_info = class(tg_gdi) //标记信息
|
||
function create(awner);
|
||
begin
|
||
inherited;
|
||
fpdata := array("style":tgc_mks_dot,"size":0,"size_unit":tgc_mk_point,"color":0,"bkcolor":0xffffff);
|
||
end
|
||
property style index "style" read get_pdata write set_pdata;
|
||
property size index "size" read get_pdata write set_pdata;
|
||
property size_unit read get_pdata write set_pdata;
|
||
property color index "color" read get_pdata write set_pdata;
|
||
property bkcolor index "bkcolor" read get_pdata write set_pdata;
|
||
protected
|
||
function check_prop(idx,v);override;//检查数据
|
||
begin
|
||
case idx of
|
||
"size_unit":
|
||
begin
|
||
return (tgc_mk_tabulated=v or tgc_mk_point=v);
|
||
end
|
||
"size":
|
||
begin
|
||
return ifnumber(v) and v>=0;
|
||
end
|
||
"style":
|
||
begin
|
||
return (v and ifstring(v));
|
||
end
|
||
"color":
|
||
begin
|
||
return ifnumber(v);
|
||
end
|
||
"bkcolor":
|
||
begin
|
||
return ifnumber(v) or ifnil(v);
|
||
end
|
||
end
|
||
return false;
|
||
end
|
||
end
|
||
type tg_evet_conainter = class(tg_const) //带消息的绘图基类
|
||
function create();
|
||
begin
|
||
fCapturelist := new tevent_list();
|
||
fbubblelist := new tevent_list();
|
||
end
|
||
function addEventListener(evtype,fn,ifCapture);virtual;
|
||
begin
|
||
if ifCapture then return fCapturelist.add(evtype,fn);
|
||
return fbubblelist.add(evtype,fn);
|
||
end
|
||
function removeEventListener(evtype,fn,ifCapture);
|
||
begin
|
||
if ifCapture then return fCapturelist.remove(evtype,fn);
|
||
return fbubblelist.remove(evtype,fn);
|
||
end
|
||
function dealevent(evt,ifCapture);
|
||
begin
|
||
if ifCapture then return fCapturelist.dispatch(evt);
|
||
return fbubblelist.dispatch(evt);
|
||
end
|
||
private
|
||
fCapturelist;
|
||
fbubblelist;
|
||
end
|
||
type tg_base = class(TNode,tg_evet_conainter) //基类,提供层次关系结构
|
||
public
|
||
function create(pms);
|
||
begin
|
||
class(TNode).create();
|
||
class(tg_evet_conainter).create();
|
||
fchange_locked := false;
|
||
fclip_state := tgc_on;
|
||
fvisibe := tgc_on;
|
||
fenabled := tgc_on;
|
||
fline_mode := tgc_off;
|
||
fmark_mode := tgc_off;
|
||
fParentFont := tgc_on;
|
||
flineinfo := new tg_line_info(self(true));
|
||
fmarkinfo := new tg_mark_info(self(true));
|
||
ffontinfo := new tg_font_info(self(true));
|
||
end
|
||
function axes_mapping(x,y,z,_x,_y);virtual; //
|
||
begin
|
||
p := get_axes();
|
||
if p then return p.axes_mapping(x,y,z,_x,_y);
|
||
return false;
|
||
end
|
||
function axes_unmapping(x,y,z,_x,_y);virtual;
|
||
begin
|
||
p := get_axes();
|
||
if p then return p.axes_unmapping(x,y,z,_x,_y);
|
||
return false;
|
||
end
|
||
function zoom_to_xyz(x,y,z,_x,_y,_z);virtual; //视图坐标到数据坐标
|
||
begin
|
||
p := get_axes();
|
||
if p then return p.zoom_to_xyz(x,y,z,_x,_y,_z);
|
||
return false;
|
||
end
|
||
function xyz_to_zoom(x,y,z,x_,y_,z_);virtual; //数据坐标到视图坐标
|
||
begin
|
||
p := get_axes();
|
||
if p then return p.xyz_to_zoom(x,y,z,x_,y_,z_);
|
||
return false;
|
||
end
|
||
function executecommand(cmd,pm);virtual; //执行操作
|
||
begin
|
||
|
||
end
|
||
function paint(cvs);virtual; //绘制
|
||
begin
|
||
|
||
end
|
||
function paint_pre(cvs);virtual;
|
||
begin
|
||
paint(cvs);
|
||
for i := 0 to NodeCount-1 do
|
||
begin
|
||
vi := GetNodeByIndex(i);
|
||
vi.paint_pre(cvs);
|
||
end
|
||
end
|
||
function hit_at(info):bool; //命中处理,鼠标信息
|
||
begin
|
||
if fonhit_at then return call(fonhit_at,self(true),info) ;
|
||
return false;
|
||
end
|
||
function set_lineinfo_to_canvas(cvs,info); //设置线条信息到画布
|
||
begin
|
||
if info is class(tg_line_info) then li := info;
|
||
else
|
||
li := lineinfo;
|
||
cl := li.color;
|
||
bcl := li.bkcolor;
|
||
cp := cvs.pen;
|
||
cp.style := li.style;
|
||
if ifnumber(cl) then
|
||
begin
|
||
cp.color := cl;
|
||
end else
|
||
begin
|
||
cp.Style := tgc_BS_NULL;
|
||
end
|
||
cp.width := li.width;
|
||
cb := cvs.brush;
|
||
if ifnumber(bcl) then
|
||
begin
|
||
cb.color := bcl;
|
||
cb.Style := tgc_BS_SOLID;
|
||
end
|
||
else
|
||
begin
|
||
cb.Style := tgc_BS_NULL;
|
||
end
|
||
end
|
||
function set_fontinfo_to_canvas(cvs,info); //设置字体信息到画布
|
||
begin
|
||
if info is class(tg_font_info) then fi := info;
|
||
else
|
||
fi := fontinfo;
|
||
cf := cvs.font;
|
||
if ifnil(fi.bkcolor) then cf.bkmode := 1;
|
||
else cf.bkmode := 2;
|
||
bc := fi.bkcolor;
|
||
cf.bkcolor := bc;
|
||
if fi.color =tgc_complementary_color then
|
||
begin
|
||
if ifnil(bc) then cf.color := 0;
|
||
else
|
||
cf.color := calc_complementary_color(bc);
|
||
end else cf.color := fi.color;
|
||
cf.width := fi.size;
|
||
cf.height := fi.size*2;
|
||
end
|
||
function dispatchEvent(evt); //分发
|
||
begin
|
||
if not(evt is class(tg_evt)) then return 1;
|
||
tg := self(true);
|
||
p := tg;
|
||
while p do
|
||
begin
|
||
if p is class(tg_axes) then
|
||
begin
|
||
p := p.figure;
|
||
break;
|
||
end
|
||
p := p.parent;
|
||
end
|
||
if not p then return 0;
|
||
return p.dispatchEvent(evt,tg);
|
||
end
|
||
function invalidate(n); //刷新
|
||
begin
|
||
if (n<>"visible") and (tgc_off=fvisibe) then return ;
|
||
if fchange_locked then return ;
|
||
axs := get_axes();
|
||
if axs then
|
||
begin
|
||
if axs.change_locked then return ;
|
||
fg := axs.figure;
|
||
end
|
||
if fg then
|
||
begin
|
||
fg.executecommand("figure_need_fresh",p);
|
||
end
|
||
end
|
||
published
|
||
property line_mode read fline_mode write set_line_mode;
|
||
property mark_mode read fmark_mode write set_mark_mode;
|
||
property clip_state read fclip_state write set_clip_state;
|
||
property axes read get_axes write set_axes;
|
||
property visible read fvisibe write setvisible;
|
||
property enabled read fenabled write setenabled;
|
||
property lineinfo read flineinfo;
|
||
property markinfo read fmarkinfo;
|
||
property fontinfo read getfontinfo;
|
||
property ParentFont read fParentFont write setParentFont;
|
||
property change_locked read fchange_locked write fchange_locked;
|
||
property onhit_at read fonhit_at write fonhit_at;
|
||
public
|
||
tgtype; //类型名称
|
||
user_data;
|
||
tag;
|
||
protected
|
||
function get_axes();virtual;
|
||
begin
|
||
p := parent;
|
||
if p then return p.axes;
|
||
end
|
||
function set_axes(axs);virtual;
|
||
begin
|
||
end
|
||
function check_parent(p);virtual; //父节点检查
|
||
begin
|
||
return true;
|
||
end
|
||
function prop_changed(n,v);virtual; //改变通知
|
||
begin
|
||
invalidate(n);
|
||
end
|
||
function SetParent(V);virtual;
|
||
begin
|
||
if not check_parent(v) then return ;
|
||
if v then ct := v.NodeCount;
|
||
r := inherited;
|
||
if v then ct2 := v.NodeCount;
|
||
if ct2>ct then
|
||
begin
|
||
ax := axes;
|
||
if ax then ax.executecommand(cmd_node_add_in,self(true));
|
||
end
|
||
return r;
|
||
end
|
||
protected
|
||
ffontinfo;
|
||
private
|
||
[weakref]fonhit_at;
|
||
fclip_state;
|
||
fline_mode;
|
||
fmark_mode;
|
||
fvisibe;
|
||
fenabled;
|
||
flineinfo;
|
||
fmarkinfo;
|
||
|
||
fchange_locked;
|
||
fParentFont;
|
||
function getfontinfo();virtual;
|
||
begin
|
||
p := parent;
|
||
if p and (fParentFont=tgc_on) then
|
||
begin
|
||
r := p.fontinfo;
|
||
r.flinker := self(true);
|
||
return r;
|
||
end
|
||
ffontinfo.flinker := self(true);
|
||
return ffontinfo;
|
||
end
|
||
function setParentFont(v);
|
||
begin
|
||
if tg_boolen_value(v,nv) and nv <>fParentFont then
|
||
begin
|
||
fParentFont := nv;
|
||
prop_changed("parentfont",nv);
|
||
end
|
||
end
|
||
function set_clip_state(v);
|
||
begin
|
||
if tg_boolen_value(v,nv) and (nv<>fclip_state) then
|
||
begin
|
||
fclip_state := nv;
|
||
prop_changed("clip_state",nv);
|
||
end
|
||
end
|
||
function set_line_mode(v);
|
||
begin
|
||
if tg_boolen_value(v,nv) and (nv<>fline_mode) then
|
||
begin
|
||
fline_mode := nv;
|
||
prop_changed("line_mode",nv);
|
||
end
|
||
end
|
||
function set_mark_mode(v);
|
||
begin
|
||
if tg_boolen_value(v,nv) and nv<>fmark_mode then
|
||
begin
|
||
fmark_mode := nv;
|
||
prop_changed("mark_mode",nv);
|
||
end
|
||
end
|
||
function setenabled(v);
|
||
begin
|
||
if tg_boolen_value(v,nv) and (nv<>fenabled) then
|
||
begin
|
||
fenabled := nv;
|
||
//prop_changed("enabled",fvisibe);
|
||
end
|
||
end
|
||
function setvisible(v);//设置可见
|
||
begin
|
||
if tg_boolen_value(v,nv) and (nv<>fvisibe) then
|
||
begin
|
||
fvisibe := nv;
|
||
prop_changed("visible",fvisibe);
|
||
end
|
||
end
|
||
end
|
||
type tg_const = class()
|
||
////////////基础///////////////////
|
||
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_direct_asc = "asc";
|
||
static const tgc_direct_desc = "desc";
|
||
|
||
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_box_hidden_axes = "hidden_axes";
|
||
static const tgc_tics_v = "v";
|
||
static const tgc_tics_r = "r";
|
||
static const tgc_tics_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_DT_always = "always";
|
||
static const tgc_DT_mouseclick = "mouseclick";
|
||
static const tgc_DT_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_BS_NULL=1;
|
||
static const tgc_BS_SOLID=0;
|
||
|
||
///////////////////线型///////////////////////////////
|
||
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";
|
||
static const tgc_LS_bar2="bar2";
|
||
|
||
/////////////////相对位置////////////////////////////
|
||
static const tgc_in_upper_right = "in_upper_right";
|
||
static const tgc_in_upper_left = "in_upper_left";
|
||
static const tgc_in_lower_right = "in_lower_right";
|
||
static const tgc_in_lower_left = "in_lower_left";
|
||
static const tgc_upper_caption = "upper_caption";
|
||
static const tgc_lower_caption = "lower_caption";
|
||
static const tgc_by_coordinates = "by_coordinates";
|
||
static const tgc_by_axes = "by_axes";
|
||
|
||
//static const tgc_out_upper_right = "out_upper_right";
|
||
//static const tgc_out_upper_left = "out_upper_left";
|
||
//static const tgc_out_lower_right = "out_lower_right";
|
||
//static const tgc_out_lower_left = "out_lower_left";
|
||
//////////////
|
||
static evt_mouse_down = "mouse_down";
|
||
static evt_mouse_wheel = "mouse_wheel";
|
||
static evt_mouse_move = "mouse_move";
|
||
static evt_mouse_in = "mouse_in";
|
||
static evt_mouse_out = "mouse_out";
|
||
static evt_mouse_up = "mouse_up";
|
||
static const CAPTURING_PHASE = 1;
|
||
static const AT_TARGET = 2;
|
||
static const BUBBLING_PHASE = 3;
|
||
///////////////////////////
|
||
static const cmd_zoom_inc = "zoom_inc";
|
||
static const cmd_figure_changed = "figure_changed";
|
||
static const cmd_data_changed = "data_changed";
|
||
static const cmd_node_add_in = "node_add_in";
|
||
/////////////////////////////////////////////////////////
|
||
static const tgc_complementary_color = "complementary_color"; //采用补色
|
||
////////////////////////////////
|
||
|
||
end
|
||
type tg_evt =class() //消息
|
||
function create(etype,pms);
|
||
begin
|
||
feventtype := etype;
|
||
ftimeStamp := mtic;
|
||
fisTrusted := false;
|
||
feventPhase := 0;
|
||
freturnValue := true;
|
||
fdefaultPrevented := false;
|
||
fbubbles := true;
|
||
FstopImmediatePropagationed := false;
|
||
if not ifarray(pms) then return ;
|
||
fiparams := pms;
|
||
fisTrusted := pms["istrusted"]?true:false;
|
||
ftarget := pms["target"];
|
||
fcurrentTarget := pms["currenttarget"];
|
||
fbubbles := pms["bubbles"]?true:false;
|
||
feventPhase := (pms["eventphase"]>0)?pms["eventphase"]:0;
|
||
end
|
||
function clone(d); //克隆对象
|
||
begin
|
||
if ifarray(d) then d2 := fiparams union d;
|
||
else d2 := d;
|
||
co := self(true).Classinfo(1);
|
||
return createobject(co,feventtype,d2);
|
||
end
|
||
function preventdefault(); //阻止默认行为
|
||
begin
|
||
fdefaultPrevented := true;
|
||
end
|
||
function stoppropagation(); //停止传播
|
||
begin
|
||
fstoppropagationed := true;
|
||
end
|
||
function stopImmediatePropagation(); //阻止当前类型的消息
|
||
begin
|
||
FstopImmediatePropagationed := true;
|
||
end
|
||
published
|
||
property bubbles read fbubbles; //是否冒泡,只读
|
||
property currentTarget read fcurrentTarget;//当前绑定的对象,只读
|
||
property target read ftarget;//目标对象,只读
|
||
property stoppropagationed read fstoppropagationed;//是否已经调用 stoppropagation,只读
|
||
property stopImmediatePropagationed read FstopImmediatePropagationed;//是否已经调用 stopImmediatePropagation,只读
|
||
property defaultPrevented read fdefaultPrevented;//是否已经调用 preventdefault,只读
|
||
property returnValue read freturnValue write freturnValue;//true表示正常执行,false表示阻止默认行为
|
||
property eventPhase read feventPhase;//只读,0,1,捕获,2到达目标,3,冒泡
|
||
property timeStamp read ftimeStamp;//只读,加载完成到现在的时间
|
||
property eventtype read feventtype;//只读类型
|
||
property isTrusted read fisTrusted;//true表示用户触发,false表示代码触发
|
||
property init_params read fiparams; //初始化参数
|
||
private
|
||
feventtype;
|
||
ftimeStamp;
|
||
fisTrusted;
|
||
feventPhase;
|
||
freturnValue;
|
||
fdefaultPrevented;
|
||
fstoppropagationed;
|
||
ftarget;
|
||
fbubbles;
|
||
fcurrentTarget;
|
||
FstopImmediatePropagationed;
|
||
fiparams;
|
||
end
|
||
type tg_evt_custom = class(tg_evt) //自定义消息
|
||
function create(etyp,pms);
|
||
begin
|
||
inherited;
|
||
fdetail := array();
|
||
if ifarray(pms) then fdetail := pms["detail"];
|
||
end
|
||
property detail read fdetail;
|
||
private
|
||
fdetail;
|
||
end
|
||
type tg_evt_mouse = class(tg_evt_custom) //鼠标消息
|
||
function create(etyp,pms);
|
||
begin
|
||
inherited;
|
||
if ifarray(pms) then
|
||
begin
|
||
fcvsx := pms["cvsx"];
|
||
fcvsy := pms["cvsy"];
|
||
fdouble := pms["double"];
|
||
fbutton := pms["button"];
|
||
fshift := pms["shift"];
|
||
fctl := pms["ctrl"];
|
||
fctl := pms["fdelta"];
|
||
end
|
||
end
|
||
property cvsx read fcvsx;
|
||
property cvsy read fcvsy;
|
||
property shift read fshift;
|
||
property ctrl read fctrl;
|
||
property delta read fdelta;
|
||
|
||
property double read fdouble;
|
||
property button read fbutton;
|
||
private
|
||
fdelta;
|
||
fcvsx;
|
||
fcvsy;
|
||
fshift;
|
||
fdouble;
|
||
fctrl;
|
||
fbutton;
|
||
end
|
||
|
||
implementation
|
||
///////////事件存储对象///////////////////////
|
||
type tevent_item = class()
|
||
function create(n,f);
|
||
begin
|
||
ename := n;
|
||
efunc := f;
|
||
end
|
||
ename;
|
||
[weakref]efunc;
|
||
end
|
||
type tevent_list = class() //消息对象列表
|
||
function create();
|
||
begin
|
||
FItems := array();
|
||
end
|
||
function add(n,f); //添加
|
||
begin
|
||
if not(ifstring(n) and n) then return 0;
|
||
if not ifobj(f) then return 0;
|
||
for i,v in FItems do
|
||
begin
|
||
if (v.ename=n and v.efunc=f) then return ;
|
||
end
|
||
FItems[length(FItems)] := new tevent_item(n,f);
|
||
return true;
|
||
end
|
||
function remove(n,f);//移除
|
||
begin
|
||
idx := -1;
|
||
for i,v in FItems do
|
||
begin
|
||
if (ifnil(f) and v.ename = n) or (ifnil(n) and v.efunc=f) or (v.efunc=f and v.ename = n) then
|
||
begin
|
||
idx := i;
|
||
break;
|
||
end
|
||
end
|
||
if idx>0 then
|
||
begin
|
||
deleteindex(FItems,idx);
|
||
remove(n,f);
|
||
end
|
||
end
|
||
function dispatch(e);//分发
|
||
begin
|
||
for i,it in FItems do
|
||
begin
|
||
if it then
|
||
begin
|
||
if e.stoppropagationed or e.stopImmediatePropagationed then return ;
|
||
f := it.efunc;
|
||
n := it.ename;
|
||
if f and n=e.eventtype then call(f,e);
|
||
end
|
||
end
|
||
end
|
||
FItems;
|
||
end
|
||
function node_hit_list(nd,info); //节点命中
|
||
begin
|
||
nnd := node_hit_at(nd,info);
|
||
r := array();
|
||
if nnd then
|
||
begin
|
||
r[0] := nnd ;
|
||
idx := 1;
|
||
while nnd do
|
||
begin
|
||
nnd := nnd.parent;
|
||
if nnd then r[idx] := nnd;
|
||
idx++;
|
||
end
|
||
end
|
||
return r;
|
||
end
|
||
function node_hit_at(nd,info); //命中处理
|
||
begin
|
||
if (nd.visible=nd.tgc_off) then return 0;
|
||
if (nd.enabled=nd.tgc_off) then return 0;
|
||
nct := nd.NodeCount;
|
||
if nct>0 then
|
||
begin
|
||
for i := nd.NodeCount-1 downto 0 do
|
||
begin
|
||
hnod := node_hit_at(nd.GetNodeByIndex(i),info) ;
|
||
if hnod then return hnod;
|
||
end
|
||
end
|
||
if nd.hit_at(info) then return nd;
|
||
return 0;
|
||
end
|
||
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 graph_paint_lines(cvs,pls,xys,cls,ifo);//绘制线
|
||
begin
|
||
return paint_lines(cvs,pls,xys,cls,ifo);
|
||
end
|
||
function graph_paint_points(mk,dc,xys);//绘制点
|
||
begin
|
||
return paint_marks(mk,dc,xys);
|
||
end
|
||
function graph_paint_boolen_value(n,v);//布尔类型格式化
|
||
begin
|
||
return tg_boolen_value(n,v);
|
||
end
|
||
function graph_paint_rec_to_points(rec);//将rect转换为点数组
|
||
begin
|
||
return rec_to_points(rec);
|
||
end
|
||
function paint_lines(cvs,pls,xys,cls,ifo);//划线
|
||
begin
|
||
o := static new tg_const();
|
||
case pls of
|
||
o.tgc_LS_staircase:
|
||
begin
|
||
if ifo["line_mode"]<>o.tgc_on then return ;
|
||
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
|
||
o.tgc_LS_barplot:
|
||
begin
|
||
for i,v in xys do
|
||
begin
|
||
cvs.moveto(array(v[0],v[1]));
|
||
cvs.lineto(array(ifo["xy0",i,0],ifo["xy0",i,1]));
|
||
end
|
||
paint_lines(cvs,o.tgc_LS_interpolated,xys,cls,ifo);
|
||
end
|
||
o.tgc_LS_bar,o.tgc_ls_bar2:
|
||
begin
|
||
b_w_x := integer(ifo["bar_width"][0]/2);
|
||
b_w_y := integer(ifo["bar_width"][1]/2);
|
||
//cvs.brush.color := ifo["bkcolor"];
|
||
wflg := (abs(b_w_x)+abs(b_w_y))>0.1;
|
||
bar_rgns := array();
|
||
for i,v in xys do
|
||
begin
|
||
if wflg then
|
||
begin
|
||
v1 := array(v[0]-b_w_x,v[1]-b_w_y);
|
||
v2 := array(v[0]+b_w_x,v[1]+b_w_y);
|
||
v3 := array(ifo["xy0",i,0]+b_w_x,ifo["xy0",i,1]+b_w_y);
|
||
v4 := array(ifo["xy0",i,0]-b_w_x,ifo["xy0",i,1]-b_w_y);
|
||
barrec := array(v1,v2,v3,v4);
|
||
bar_rgns[i] := barrec;
|
||
cvs.draw_polygon().points(barrec).draw();
|
||
end else
|
||
begin
|
||
cvs.moveto(array(v[0],v[1]));
|
||
cvs.lineto(array(ifo["xy0",i,0],ifo["xy0",i,1]));
|
||
end
|
||
end
|
||
ifo["bar_rgns"] := bar_rgns;
|
||
if o.tgc_ls_bar=pls then
|
||
paint_lines(cvs,o.tgc_LS_interpolated,xys,cls,ifo);
|
||
end
|
||
o.tgc_LS_arrowed:
|
||
begin
|
||
if ifo["line_mode"]<>o.tgc_on then return ;
|
||
paint_lines(cvs,o.tgc_LS_interpolated,xys,cls,ifo);
|
||
vlast := xys[0];
|
||
for i,v in xys do
|
||
begin
|
||
if i<1 then continue;
|
||
x := v[0];
|
||
y := v[1];
|
||
dx := x-vlast[0];
|
||
dy := y-vlast[1];
|
||
arg := arctan(dy/dx)+pi();
|
||
sz := 15;
|
||
p_trans(sz,0,-(arg-pi()/6),x1,y1);
|
||
cvs.moveto(v);
|
||
cvs.lineto(array(v[0]+x1,v[1]+y1));
|
||
p_trans(sz,0,-(arg+pi()/6),x1,y1);
|
||
cvs.moveto(v);
|
||
cvs.lineto(array(v[0]+x1,v[1]+y1));
|
||
vlast := v;
|
||
end
|
||
end
|
||
o.tgc_LS_filled:
|
||
begin
|
||
if cls=o.tgc_on then
|
||
begin
|
||
//cvs.brush.color := ifo["bkcolor"];
|
||
cvs.draw_polygon().points(xys).draw();
|
||
end else
|
||
begin
|
||
//cvs.brush.color := ifo["color"];
|
||
for i,v in xys do
|
||
begin
|
||
if i=0 then continue;
|
||
v1 := v;
|
||
v4 := xys[i-1];
|
||
v2 := array(ifo["xy0",i,0],ifo["xy0",i,1]);
|
||
v3 := array(ifo["xy0",i-1,0],ifo["xy0",i-1,1]);
|
||
cvs.draw_polygon().points(array(v1,v2,v3,v4)).draw();
|
||
end
|
||
end
|
||
paint_lines(cvs,o.tgc_LS_interpolated,xys,cls,ifo);
|
||
end
|
||
else
|
||
begin
|
||
if ifo["line_mode"]<>o.tgc_on then return ;
|
||
cvs.draw_polyline().points(xys union ((cls=o.tgc_on and length(xys)>2)?array(xys[0]):array())).draw();
|
||
end
|
||
end
|
||
end
|
||
function paint_marks(mk,dc,xys); //绘制marks;
|
||
begin
|
||
o := static new tg_const();
|
||
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.style := 0;
|
||
dc.brush.color := mk.bkcolor;
|
||
case tp of
|
||
o.tgc_mks_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
|
||
o.tgc_mks_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
|
||
o.tgc_mks_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
|
||
o.tgc_mks_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
|
||
o.tgc_mks_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
|
||
o.tgc_mks_diamond_plus:
|
||
begin
|
||
mk.Style := o.tgc_mks_diamond ;
|
||
paint_marks(mk,dc,xys);
|
||
mk.Style := o.tgc_mks_plus;
|
||
paint_marks(mk,dc,xys);
|
||
mk.Style := o.tgc_mks_diamond_plus;
|
||
end
|
||
o.tgc_mks_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
|
||
o.tgc_mks_dot,o.tgc_mks_circle,o.tgc_mks_square:
|
||
begin
|
||
if tp=o.tgc_mks_dot then
|
||
dc.brush.color := mk.color;
|
||
if tp=o.tgc_mks_square 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
|
||
o.tgc_mks_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
|
||
o.tgc_mks_star:
|
||
begin
|
||
mk.Style := o.tgc_mks_circle;
|
||
paint_marks(mk,dc,xys);
|
||
mk.Style := o.tgc_mks_plus;
|
||
paint_marks(mk,dc,xys);
|
||
mk.Style := o.tgc_mks_star;
|
||
end
|
||
o.tgc_mks_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
|
||
o.tgc_mks_asterisk:
|
||
begin
|
||
mk.Style := o.tgc_mks_cross;
|
||
paint_marks(mk,dc,xys);
|
||
mk.Style := o.tgc_mks_plus;
|
||
paint_marks(mk,dc,xys);
|
||
mk.Style := o.tgc_mks_asterisk;
|
||
end
|
||
end ;
|
||
end
|
||
function tg_boolen_value(v,nv); //规则化boolean
|
||
begin
|
||
if v=true or v="on" then
|
||
begin
|
||
nv := "on";
|
||
return true;
|
||
end else
|
||
if v=false or v="off" then
|
||
begin
|
||
nv := "off";
|
||
return true;
|
||
end
|
||
end
|
||
////////////////边界取整////////////////////////////
|
||
function new_bound_factor(a,n);
|
||
begin
|
||
if a>1 and a<=10 then
|
||
begin
|
||
return int(a)*10^n;
|
||
end else
|
||
if a>10 then
|
||
begin
|
||
n++;
|
||
return new_bound_factor(a/10,n);
|
||
end else
|
||
if a<=1 then
|
||
begin
|
||
n--;
|
||
return new_bound_factor(a*10,n);
|
||
end
|
||
end
|
||
function new_bounds(a,b,a_,b_,par);
|
||
begin
|
||
a_ := a;
|
||
b_ := b;
|
||
if not(par>=1) then par:=20;//20;
|
||
r := new_bound_factor((b-a)/par,n);
|
||
if r<>0 then
|
||
begin
|
||
a_:=floor(a/r)*r;
|
||
b_:= ceil(b/r)*r;
|
||
end
|
||
return r;
|
||
end
|
||
function get_node_data_bounds(nd); //获取节点的范围
|
||
begin
|
||
d := zeros(3,2);
|
||
for i := 0 to nd.NodeCount-1 do
|
||
begin
|
||
vi := nd.GetNodeByIndex(i);
|
||
if vi is class(tg_graph_base) then
|
||
begin
|
||
bds := vi.get_data_bounds();
|
||
if i=0 then
|
||
begin
|
||
d := bds;
|
||
end else
|
||
mg_bds(bds,d);
|
||
end
|
||
end
|
||
return d;
|
||
end
|
||
function modify_text_pos(x_,y_,txtw,txth,al);//修正对齐位置
|
||
begin
|
||
case al of
|
||
2:
|
||
begin
|
||
x_ := x_-txtw/2;
|
||
end
|
||
3:
|
||
begin
|
||
x_ := x_-txtw;
|
||
end
|
||
4:
|
||
begin
|
||
y_ := y_-txth/2;
|
||
end
|
||
5:
|
||
begin
|
||
x_ := x_-txtw/2;
|
||
y_ := y_-txth/2;
|
||
end
|
||
6:
|
||
begin
|
||
x_ := x_-txtw;
|
||
y_ := y_-txth/2;
|
||
end
|
||
7:
|
||
begin
|
||
y_ := y_-txth;
|
||
end
|
||
8:
|
||
begin
|
||
x_ := x_-txtw/2;
|
||
y_ := y_-txth;
|
||
end
|
||
9:
|
||
begin
|
||
x_ := x_-txtw;
|
||
y_ := y_-txth;
|
||
end
|
||
end;
|
||
end
|
||
function get_rect_at_corner(x,y,w,h,itv,flg,mvx,mvy); //计算围绕点的区域位置
|
||
begin
|
||
//0左上 ,1右上 2 右下 3 左下
|
||
r := zeros(4);
|
||
case flg of
|
||
0:
|
||
begin
|
||
r[0] :=x-w-itv;
|
||
r[1] :=y-h-itv;
|
||
r[2] :=x-itv;
|
||
r[3] :=y-itv;
|
||
end
|
||
1:
|
||
begin
|
||
r[0] :=x+itv;
|
||
r[1] :=y-h-itv;
|
||
r[2] :=x+w+itv;
|
||
r[3] :=y-itv;
|
||
end
|
||
2:
|
||
begin
|
||
r[0] :=x+itv;
|
||
r[1] :=y+itv;
|
||
r[2] :=x+w+itv;
|
||
r[3] :=y+h+itv;
|
||
end
|
||
3:
|
||
begin
|
||
r[0] :=x-w-itv;
|
||
r[1] :=y+itv;
|
||
r[2] :=x-itv;
|
||
r[3] :=y+h+itv;
|
||
end
|
||
4: //中
|
||
begin
|
||
w2 := ceil(w/2);
|
||
h2 := ceil(h/2);
|
||
r[0] :=x-w2;
|
||
r[1] :=y-h2;
|
||
r[2] :=x+w2;
|
||
r[3] :=y+h2;
|
||
end
|
||
|
||
end;
|
||
if mvx>0 or mvx<0 then
|
||
begin
|
||
r[0]+=mvx;
|
||
r[2]+=mvx;
|
||
end
|
||
if mvy>0 or mvy<0 then
|
||
begin
|
||
r[1]+=mvy;
|
||
r[3]+=mvy;
|
||
end
|
||
return r;
|
||
end
|
||
/////////////辅助//////////////////////////////////////
|
||
function like_0(x,jd);
|
||
begin
|
||
if jd>10 then return (x+jd=jd);
|
||
return (x+1000)=1000;
|
||
end
|
||
function a_like_b(a,b,jd);
|
||
begin
|
||
return like_0(a-b);
|
||
end
|
||
function r_2_a(arg);
|
||
begin
|
||
return arg*180/pi();
|
||
end
|
||
function a_2_r(arg);
|
||
begin
|
||
return arg*pi()/180;
|
||
end
|
||
function d2angle(v1,v2); //角度计算
|
||
begin
|
||
r := arccos(sum(v1*v2)/vectorsize(v1)/vectorsize(v2));
|
||
return r;
|
||
if r>0 or r<0 then return r;
|
||
return 0;
|
||
end
|
||
function vectorsize(v); //向量长度
|
||
begin
|
||
return (v[0]^2+v[1]^2)^0.5;
|
||
end
|
||
function rec_to_points(rec);
|
||
begin
|
||
return array(rec[array(0,1)],rec[array(2,1)],rec[array(2,3)],rec[array(0,3)],rec[array(0,1)]);
|
||
end
|
||
function point_in_rgn(p,rgn_,method); //夹角法
|
||
begin
|
||
if (method = 1) or ifnil(method) then return point_in_polygon(p, rgn_);
|
||
arg := 0;
|
||
rgn := rgn_ union array(rgn_[0]);
|
||
len := length(rgn);
|
||
if len<4 then return 0;
|
||
for i := 1 to len-1 do
|
||
begin
|
||
p1 := rgn[i-1];
|
||
p2 := rgn[i];
|
||
v1 := array(p1[0]-p[0],p1[1]-p[1]);
|
||
v2 := array(p2[0]-p[0],p2[1]-p[1]);
|
||
argi := d2angle(v1,v2);
|
||
if argi>0 or argi<0 then arg+=argi;
|
||
end
|
||
return (abs(arg/2-pi())<0.01);
|
||
end
|
||
function point_in_polygon(point, polygon);//射线法
|
||
begin
|
||
x0 := point[0];
|
||
y0 := point[1];
|
||
ct := 0;
|
||
len := length(polygon)-1;
|
||
if len<3 then return 0;
|
||
for i ,v in polygon do
|
||
begin
|
||
x1 := v[0];
|
||
y1 := v[1];
|
||
if i=len then v2 := polygon[0];
|
||
else v2 := polygon[i+1];
|
||
x2 := v2[0];
|
||
y2 := v2[1];
|
||
if ((y1 > y0) <> (y2 > y0)) and x0 < ((x2 - x1) * (y0 - y1) / (y2 - y1) + x1) then ct += 1;
|
||
end
|
||
return (ct % 2) =1;
|
||
end
|
||
function rgn_points_trans(pts,ag);
|
||
begin
|
||
x := pts[0,0];
|
||
y := pts[0,1];
|
||
for i := 1 to length(pts)-1 do
|
||
begin
|
||
p_trans(pts[i,0]-x,pts[i,1]-y,ag,px,py);
|
||
pts[i] := array(x+px,y+py);
|
||
end
|
||
end
|
||
function tg_get_true_idx(idx);//坐标规范化
|
||
begin
|
||
nidx := idx;
|
||
case idx of
|
||
"x","X": nidx := 0;
|
||
"y","Y": nidx := 1;
|
||
"z","Z": nidx := 2;
|
||
end ;
|
||
return nidx;
|
||
end
|
||
///////////////////////////////////////
|
||
function calc_complementary_color(c);//补色计算
|
||
begin
|
||
return rgb((255-GetRValue(c)),(255-GetgValue(c)),(255-GetbValue(c)));
|
||
end
|
||
////////////////////////////////////////
|
||
initialization
|
||
finalization
|
||
end. |