2160 lines
77 KiB
Plaintext
2160 lines
77 KiB
Plaintext
unit utvclgraphicsext;
|
||
interface
|
||
uses utslvclauxiliary,utvclgraphics;//,utslvclconstant;
|
||
{
|
||
//玫瑰图
|
||
uses tslvcl,utvclgraphics,utvclgraphicsext;
|
||
app := initializeapplication();
|
||
app.createform(class(tfm),fm);
|
||
fm.show();
|
||
app.run();
|
||
type tfm=class(tvcform)
|
||
function create(aowner);
|
||
begin
|
||
inherited;
|
||
caption := "玫瑰图";
|
||
width := 800;
|
||
Height := 800;
|
||
fg := new tg_WinControl(self);
|
||
fg.parent := self;
|
||
fg.Align := alClient;
|
||
//////////设置坐标轴属性////////////////////////
|
||
axs := new tg_axes();
|
||
axs.figure := fg.figure;
|
||
axs.title.text := "玫瑰图";
|
||
args := array(('name':'a','value':300)
|
||
,('name':'b','value':200)
|
||
,('name':'c','value':500)
|
||
,('name':'d','value':700)
|
||
,('name':'e','value':300)
|
||
,('name':'f','value':200)
|
||
,('name':'g','value':500)
|
||
,('name':'h','value':700)
|
||
,('name':'i','value':300)
|
||
,('name':'j','value':200)
|
||
,('name':'k','value':500)
|
||
,('name':'l','value':700)
|
||
);
|
||
line := new tg_Polypie();
|
||
line.graph_data := args;
|
||
line.pie_type := "rose"; //'ring';
|
||
line.parent := axs;
|
||
//绘制图例
|
||
lg := new tg_legend();
|
||
lg.parent := axs;
|
||
//lg.location := lg.tgc_by_axes;
|
||
lg.postion := array(-0.11,0.7);
|
||
//lg.text := array("aaa","bbb",'ccc','ddd');
|
||
lg.links := array(line);
|
||
//构造提示标签
|
||
fmovetip := new tg_tips();
|
||
fmovetip.parent := line;
|
||
fmovetip.box_mode := true; //false;
|
||
fmovetip.display_function := function(o,ps,d)
|
||
begin
|
||
p := o.parent;
|
||
if not fshowpos then return;
|
||
if p then
|
||
begin
|
||
dd := p.get_graph_data_by_idx(o.data_idx);
|
||
p.xyz_to_zoom(fshowpos[0],fshowpos[1],nil,x1,y1);
|
||
ps := array(x1,y1);
|
||
d := array(dd["name"],tostn(dd["value"]));
|
||
end
|
||
end
|
||
//设置提示数据点
|
||
line.onhit_at := function(o,d)
|
||
begin
|
||
x := d["cvsx"];
|
||
y := d["cvsy"];
|
||
r := o.ExecuteCommand("hit_part",array(x,y));
|
||
r := r >= 0;
|
||
return r;
|
||
end
|
||
line.addEventListener("mouse_in", function(e)
|
||
begin
|
||
if e.eventPhase <> 2 then return;
|
||
e.stoppropagation();
|
||
end
|
||
,true);
|
||
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;
|
||
idx := e.target.ExecuteCommand("hit_part",array(x,y));
|
||
if idx >= 0 then
|
||
begin
|
||
fmovetip.data_idx := idx;
|
||
fshowpos := array(x,y);
|
||
fmovetip.Visible := true;
|
||
end
|
||
end
|
||
,true);
|
||
end
|
||
fmovetip;
|
||
fg;
|
||
fshowpos;
|
||
end
|
||
|
||
//雷达图
|
||
uses tslvcl,utvclgraphics,utvclgraphicsext;
|
||
app := initializeapplication();
|
||
app.createform(class(tfm),fm);
|
||
fm.show();
|
||
app.run();
|
||
type tfm = class(tvcform)
|
||
function create(aowner);
|
||
begin
|
||
inherited;
|
||
caption := "雷达图";
|
||
width := 800;
|
||
Height := 800;
|
||
fg := new tg_WinControl(self);
|
||
fg.parent := self;
|
||
fg.Align := alClient;
|
||
//////////设置坐标轴属性////////////////////////
|
||
axs := new tg_axes();
|
||
axs.box := true;
|
||
axs.figure := fg.figure;
|
||
axs.title.text := "雷达图";
|
||
line := new tg_Polyradar();
|
||
indicator := array(
|
||
('name':'射击','max':300),
|
||
('name':'游泳','max':200),
|
||
('name':'篮球','max':500),
|
||
('name':'足球','max':700),
|
||
('name':'跑步','max':300),
|
||
('name':'举重','max':200)
|
||
);
|
||
indicator := array(
|
||
('name':'射击','max':110),
|
||
('name':'游泳','max':110),
|
||
('name':'篮球','max':110),
|
||
('name':'足球','max':110),
|
||
('name':'跑步','max':110),
|
||
('name':'举重','max':110)
|
||
);
|
||
args := array(
|
||
('name':'一班','value':array(90, 80, 85, 85, 95, 95)),
|
||
('name':'二班','value':array(85, 65, 65, 90, 100, 70)),
|
||
('name':'三班','value':array(70, 60, 99, 50, 90, 80))
|
||
);
|
||
|
||
line.graph_data := args;
|
||
line.indicator := indicator;
|
||
line.parent := axs;
|
||
lg := new tg_legend();
|
||
lg.parent := axs;
|
||
lg.postion := array(-0.11,0.7);
|
||
lg.links := array(line);
|
||
end
|
||
fg;
|
||
end
|
||
//树图
|
||
uses tslvcl,utvclgraphics,utvclgraphicsext;
|
||
app := initializeapplication();
|
||
app.createform(class(tfm),fm);
|
||
fm.show();
|
||
app.run();
|
||
type tfm = class(tvcform)
|
||
function create(aowner);
|
||
begin
|
||
inherited;
|
||
Caption := "树图";
|
||
fg := new tg_WinControl(self);
|
||
fg.Caption := "树图";
|
||
fg.parent := self;
|
||
fg.Align := alClient;
|
||
//////////设置坐标轴属性////////////////////////
|
||
axs := new tg_axes();
|
||
axs.figure := fg.figure;
|
||
axs.title.text := "树图";
|
||
//设置线型属性
|
||
line := new tg_Polytree();
|
||
line.parent := axs;
|
||
line.lineinfo.color := 0x0000ff;
|
||
line.markinfo.bkcolor := 0x00ff00;
|
||
line.markinfo.color := 0x0000ff;
|
||
line.mark_mode := true;
|
||
line.markinfo.size := 5;
|
||
line.show_text := true;//展示节点文本
|
||
d := array();
|
||
idx := 0;
|
||
line.graph_data := array('name':'111','show': true,'children':(
|
||
('name':'222','children':(('name':'333','children':(('name':'111','children':(
|
||
('name':'222','children':(('name':'333','children':(('name':'111','children':(
|
||
('name':'222','children':(('name':'333','children':(('name':'111','children':(
|
||
('name':'222','children':(('name':'333','children':()),('name':'444','children':(('name':'111','children':(
|
||
('name':'222','children':(('name':'333','children':()),('name':'444','children':(('name':'111','children':(
|
||
('name':'222','children':(('name':'333','children':()),('name':'444','children':()))),
|
||
('name':'555','children':(('name':'666','children':()),('name':'777','children':()))),
|
||
('name':'888','children':(('name':'999','children':()),('name':'xxx','children':()),('name':'zzz','children':())))
|
||
)
|
||
))))),
|
||
('name':'555','children':(('name':'666','show': false,'children':()),('name':'777','children':()))),
|
||
('name':'888','children':(('name':'999','children':()),('name':'xxx','children':()),('name':'zzz','children':())))
|
||
)
|
||
))))),
|
||
('name':'555','children':(('name':'666','children':()),('name':'777','children':()))),
|
||
('name':'888','children':(('name':'999','children':()),('name':'xxx','children':()),('name':'zzz','children':(('name':'111','children':(
|
||
('name':'222','children':(('name':'333','children':()),('name':'444','children':()))),
|
||
('name':'555','children':(('name':'666','children':()),('name':'777','children':()))),
|
||
('name':'888','children':(('name':'999','children':()),('name':'xxx','children':()),('name':'zzz','children':())))
|
||
)
|
||
)))))
|
||
)
|
||
))),('name':'444','children':()))),
|
||
('name':'555','children':(('name':'666','children':()),('name':'777','children':()))),
|
||
('name':'888','children':(('name':'999','children':()),('name':'xxx','children':()),('name':'zzz','children':(('name':'111','children':(
|
||
('name':'222','children':(('name':'333','children':()),('name':'444','children':()))),
|
||
('name':'555','children':(('name':'666','children':()),('name':'777','children':(('name':'111','children':(
|
||
('name':'222','children':(('name':'333','children':()),('name':'444','children':()))),
|
||
('name':'555','children':(('name':'666','children':()),('name':'777','children':()))),
|
||
('name':'888','children':(('name':'999','children':()),('name':'xxx','children':()),('name':'zzz','children':())))
|
||
)
|
||
))))),
|
||
('name':'888','children':(('name':'999','children':()),('name':'xxx','children':()),('name':'zzz','children':())))
|
||
)
|
||
)))))
|
||
)
|
||
))),('name':'444','children':()))),
|
||
('name':'555','children':(('name':'666','children':()),('name':'777','children':()))),
|
||
('name':'888','children':(('name':'999','children':()),('name':'xxx','children':()),('name':'zzz','children':())))
|
||
)
|
||
))),('name':'444','children':(('name':'111','children':(
|
||
('name':'222','children':(('name':'333','children':()),('name':'444','children':(('name':'111','children':(
|
||
('name':'222','children':(('name':'333','children':()),('name':'444','children':()))),
|
||
('name':'555','children':(('name':'666','children':()),('name':'777','children':()))),
|
||
('name':'888','children':(('name':'999','children':()),('name':'xxx','children':()),('name':'zzz','children':())))
|
||
)
|
||
))))),
|
||
('name':'555','children':(('name':'666','children':()),('name':'777','children':()))),
|
||
('name':'888','children':(('name':'999','children':()),('name':'xxx','children':()),('name':'zzz','children':())))
|
||
)
|
||
))))),
|
||
('name':'555','children':(('name':'666','children':()),('name':'777','children':(('name':'111','children':(
|
||
('name':'222','children':(('name':'333','children':()),('name':'444','children':()))),
|
||
('name':'555','children':(('name':'666','children':()),('name':'777','children':()))),
|
||
('name':'888','children':(('name':'999','children':()),('name':'xxx','children':()),('name':'zzz','children':())))
|
||
)
|
||
))))),
|
||
('name':'888','children':(('name':'999','children':(('name':'111','children':(
|
||
('name':'222','children':(('name':'333','children':()),('name':'444','children':()))),
|
||
('name':'555','children':(('name':'666','children':(('name':'111','children':(
|
||
('name':'222','children':(('name':'333','children':()),('name':'444','children':()))),
|
||
('name':'555','children':(('name':'666','children':()),('name':'777','children':()))),
|
||
('name':'888','children':(('name':'999','children':()),('name':'xxx','children':()),('name':'zzz','children':(('name':'111','children':(
|
||
('name':'222','children':(('name':'333','children':()),('name':'444','children':()))),
|
||
('name':'555','children':(('name':'666','children':()),('name':'777','children':()))),
|
||
('name':'888','children':(('name':'999','children':()),('name':'xxx','children':()),('name':'zzz','children':(('name':'111','children':(
|
||
('name':'222','children':(('name':'333','children':()),('name':'444','children':()))),
|
||
('name':'555','children':(('name':'666','children':()),('name':'777','children':()))),
|
||
('name':'888','children':(('name':'999','children':()),('name':'xxx','children':()),('name':'zzz','children':())))
|
||
)
|
||
)))))
|
||
)
|
||
)))))
|
||
)
|
||
))),('name':'777','children':()))),
|
||
('name':'888','children':(('name':'999','children':()),('name':'xxx','children':()),('name':'zzz','children':(('name':'111','children':(
|
||
('name':'222','children':(('name':'333','children':()),('name':'444','children':()))),
|
||
('name':'555','children':(('name':'666','children':()),('name':'777','children':()))),
|
||
('name':'888','children':(('name':'999','children':()),('name':'xxx','children':()),('name':'zzz','children':(('name':'111','children':(
|
||
('name':'222','children':(('name':'333','children':()),('name':'444','children':()))),
|
||
('name':'555','children':(('name':'666','children':()),('name':'777','children':()))),
|
||
('name':'888','children':(('name':'999','children':()),('name':'xxx','children':()),('name':'zzz','children':())))
|
||
)
|
||
)))))
|
||
)
|
||
)))))
|
||
)
|
||
))),('name':'xxx','children':(('name':'111','children':(
|
||
('name':'222','children':(('name':'333','children':()),('name':'444','children':()))),
|
||
('name':'555','children':(('name':'666','children':()),('name':'777','children':()))),
|
||
('name':'888','children':(('name':'999','children':()),('name':'xxx','children':()),('name':'zzz','children':(('name':'111','children':(
|
||
('name':'222','children':(('name':'333','children':()),('name':'444','children':()))),
|
||
('name':'555','children':(('name':'666','children':()),('name':'777','children':()))),
|
||
('name':'888','children':(('name':'999','children':()),('name':'xxx','children':()),('name':'zzz','children':(('name':'111','children':(
|
||
('name':'222','children':(('name':'333','children':()),('name':'444','children':()))),
|
||
('name':'555','children':(('name':'666','children':()),('name':'777','children':()))),
|
||
('name':'888','children':(('name':'999','children':()),('name':'xxx','children':()),('name':'zzz','children':(('name':'111','children':(
|
||
('name':'222','children':(('name':'333','children':()),('name':'444','children':()))),
|
||
('name':'555','children':(('name':'666','children':()),('name':'777','children':()))),
|
||
('name':'888','children':(('name':'999','children':()),('name':'xxx','children':()),('name':'zzz','children':())))
|
||
)
|
||
)))))
|
||
)
|
||
)))))
|
||
)
|
||
)))))
|
||
)
|
||
))),('name':'zzz','children':(('name':'777','children':())))))
|
||
)
|
||
);
|
||
|
||
end
|
||
fg;
|
||
end
|
||
//k线图
|
||
uses tslvcl,utvclgraphics,utvclgraphicsext;
|
||
app := initializeapplication();
|
||
app.createform(class(tfm),fm);
|
||
fm.show();
|
||
app.run();
|
||
type tfm = class(tvcform)
|
||
function create(aowner);
|
||
begin
|
||
inherited;
|
||
Caption := "k线图";
|
||
fg := new tg_WinControl(self);
|
||
fg.parent := self;
|
||
fg.Align := alClient;
|
||
//////////设置坐标轴属性////////////////////////
|
||
axs := new tg_axes();
|
||
axs.figure := fg.figure;
|
||
axs.title.text := "k线图 ";
|
||
axs.title.fontinfo.size := 15;
|
||
axs.title.fontinfo.color := 0xff0000;
|
||
axs.x_label.text := "日期";
|
||
axs.grid(0).Width := 2;
|
||
axs.grid(0).color := 0x0ff0f0;
|
||
axs.auto_ticks(0) := false;
|
||
//设置线型属性
|
||
line := new tg_Polycandlestick();
|
||
line.lineinfo.color := 0xff0000;
|
||
line.bullcolor := 0x0000ff;
|
||
line.bearcolor := 0x00ff00;
|
||
line.line_mode := false;
|
||
line.graph_data := array(("2017-10-24",1.1,1,1.3,0.3),("2017-10-25",3,4,4.5,2.5),("2017-10-26",5,8,9,3),("2017-10-27",10,8,9,3),("2017-10-28",5,8,9,8.5),("2017-10-29",5,8,9,3)
|
||
,("2017-10-30",5,8,9,3),("2017-10-31",5,8,9,3),("2017-11-01",5,8,9,3));
|
||
line.parent := axs;
|
||
end
|
||
fg;
|
||
end
|
||
//盒须图
|
||
uses tslvcl,utvclgraphics,utvclgraphicsext;
|
||
app := initializeapplication();
|
||
app.createform(class(tfm),fm);
|
||
fm.show();
|
||
app.run();
|
||
type tfm = class(tvcform)
|
||
function create(aowner);
|
||
begin
|
||
inherited;
|
||
Caption := "盒须图";
|
||
fg := new tg_WinControl(self);
|
||
fg.Caption := "盒须图";
|
||
fg.parent := self;
|
||
fg.Align := alClient;
|
||
//////////设置坐标轴属性////////////////////////
|
||
axs := new tg_axes();
|
||
axs.figure := fg.figure;
|
||
axs.title.text := "盒须图";
|
||
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;
|
||
axs.grid(0).Width := 2;
|
||
axs.grid(0).color := 0x0ff0f0;
|
||
line := new tg_Polyboxplot();
|
||
line.lineinfo.color := 0xff0000;
|
||
line.graph_data := array((850, 740, 900, 1070, 930, 850, 950, 980, 980, 880, 1000, 980, 930, 650, 760, 810, 1000, 1000, 960, 960),
|
||
(960, 940, 960, 940, 880, 800, 850, 880, 900, 840, 830, 790, 810, 880, 880, 830, 800, 790, 760, 800),
|
||
(880, 880, 880, 860, 720, 720, 620, 860, 970, 950, 880, 910, 850, 870, 840, 840, 850, 840, 840, 840),
|
||
(890, 810, 810, 820, 800, 770, 760, 740, 750, 760, 910, 920, 890, 860, 880, 720, 840, 850, 850, 780),
|
||
(890, 840, 780, 810, 760, 810, 790, 810, 820, 850, 870, 870, 810, 740, 810, 940, 950, 800, 810, 870)
|
||
);
|
||
line.parent := axs;
|
||
end
|
||
fg;
|
||
end
|
||
//旭日图
|
||
uses tslvcl,utvclgraphics,utvclgraphicsext;
|
||
app := initializeapplication();
|
||
app.createform(class(tfm),fm);
|
||
fm.show();
|
||
app.run();
|
||
type tfm = class(tvcform)
|
||
function create(aowner);
|
||
begin
|
||
inherited;
|
||
caption := '旭日图';
|
||
width := 800;
|
||
Height := 800;
|
||
fg := new tg_WinControl(self);
|
||
fg.parent := self;
|
||
fg.Align := alClient;
|
||
//////////设置坐标轴属性////////////////////////
|
||
axs := new tg_axes();
|
||
axs.box := true;
|
||
axs.figure := fg.figure;
|
||
axs.title.text :="旭日图";
|
||
args := array(
|
||
'name': '组织',
|
||
'children': (
|
||
(
|
||
'name': '总经理办公室',
|
||
'children': (
|
||
(
|
||
'name': '财务部',
|
||
"itemstyle":("color":0xff00ff),
|
||
'value': 15,
|
||
'children': (
|
||
('name': '会计', 'value': 2),
|
||
(
|
||
'name': '财务主管',
|
||
'value': 5,
|
||
'children': (
|
||
('name': '财务专员', 'value': 2)
|
||
)
|
||
),
|
||
('name': '财务助理', 'value': 4)
|
||
)
|
||
),
|
||
('name': '市场部', 'children': (('name': '市场经理', 'value': 4))),
|
||
(
|
||
'name': '人力资源部',
|
||
'value': 10,
|
||
'children': (
|
||
('name': '人事经理', 'value': 5, 'itemStyle': ('color': 'yellow')),
|
||
('name': '招聘专员', 'value': 1)
|
||
)
|
||
)
|
||
)
|
||
),
|
||
(
|
||
'name': '技术部',
|
||
'children': (
|
||
(
|
||
'name': '研发部',
|
||
'children': (
|
||
('name': '项目经理', 'value': 3),
|
||
(
|
||
'name': '开发工程师',
|
||
'value': 4,
|
||
'children': (('name': '实习生', 'value': 2))
|
||
)
|
||
)
|
||
)
|
||
)
|
||
),
|
||
(
|
||
'name': '销售部',
|
||
'children': (
|
||
(
|
||
'name': '销售经理',
|
||
'children': (
|
||
('name': '销售代表', 'value': 1),
|
||
('name': '销售助理', 'value': 2)
|
||
)
|
||
)
|
||
)
|
||
)
|
||
)
|
||
);
|
||
line := new tg_Polysunburst();
|
||
line.graph_data := args;
|
||
line.parent := axs;
|
||
end
|
||
fg;
|
||
end
|
||
}
|
||
type tg_Polycandlestick = class(tg_graph) //k线图
|
||
function create(pms);
|
||
begin
|
||
inherited;
|
||
fbarrgn := array();
|
||
clip_state := tgc_on;
|
||
line_mode := tgc_on;
|
||
mark_mode := tgc_off;
|
||
fbar_width := 0.3;
|
||
fdata_bounds := array((0,1),(0,1),(0,1));
|
||
end
|
||
function get_data_bounds();override; //边界
|
||
begin
|
||
//fdata_bounds[0,1] := length(fgraph_data);
|
||
return fdata_bounds;
|
||
end
|
||
function paint(cvs);override; //绘制
|
||
begin
|
||
if tgc_on<> visible then return ;
|
||
tempbarw := 0;
|
||
bx := axes.zoom_box;
|
||
if clip_state=tgc_on then
|
||
begin
|
||
pts := array();
|
||
for i,v in graph_paint_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],bx[2,0],x,y);
|
||
pts[i] := array(x,y);
|
||
end
|
||
cvs.clip_rgn(pts);
|
||
end else
|
||
begin
|
||
cvs.axesunclip();
|
||
end
|
||
xys := array();
|
||
wick_y := array();
|
||
set_lineinfo_to_canvas(cvs);
|
||
xlbl := array("0");
|
||
xcd := array(0);
|
||
for i,v in fgraph_data do
|
||
begin
|
||
xlbl[i+1] := v[0];
|
||
xcd[i+1] := i+1;
|
||
end
|
||
axes.axises(0).tics_coord := xcd;
|
||
axes.axises(0).tics_labels := xlbl;
|
||
ys := array();
|
||
for i,v in fgraph_data do
|
||
begin
|
||
if not zoom_to_xyz(i+1,v[1],bx[2,0],x,y) then return ;
|
||
xys[i] := array(integer(x),integer(y));
|
||
if not zoom_to_xyz(i+1,v[3],bx[2,0],x,y) then return ;
|
||
wick_y[i][0] := array(integer(x),integer(y));
|
||
if not zoom_to_xyz(i+1,v[4],bx[2,0],x,y) then return ;
|
||
wick_y[i][1] := array(integer(x),integer(y));
|
||
zoom_to_xyz(i+1,v[2],bx[2,0],x,y) ;
|
||
ys[i] := array(integer(x),integer(y));
|
||
if not zoom_to_xyz(i+1,v[1],bx[2,0],x,y) then return ;
|
||
if not(tempbarw) and fbar_width>0 then ////////计算宽度///////
|
||
begin
|
||
b := get_abs_barwidth();
|
||
zoom_to_xyz((i+1+b/2),v[1],bx[2,0],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
|
||
end
|
||
fline_points_in_canvas := xys;
|
||
fbarrgn := array();
|
||
pinfo := array("line_mode":line_mode,"bar_width":tempbarw,"color":lineinfo.color,"bullcolor":fbullcolor,"bearcolor":fbearcolor,"bkcolor":lineinfo.bkcolor,"xy0":ys,"wick_y": wick_y);
|
||
paint_candlestick(cvs,0,xys,0,fgraph_data,pinfo);
|
||
fbarrgn := pinfo["barrgn"];
|
||
inherited;
|
||
end
|
||
function executecommand(cmd,p);override;
|
||
begin
|
||
case cmd of
|
||
"hit_point":
|
||
begin
|
||
for i,v in fbarrgn do
|
||
begin
|
||
if point_in_rgn(p,v) then return i;
|
||
end
|
||
return -1;
|
||
end
|
||
"points_in_canvas":return (visible=tgc_on)? fline_points_in_canvas:nil; //???????
|
||
end;
|
||
return inherited;
|
||
end
|
||
published
|
||
property bar_width read fbar_width write set_barwidth;//宽度
|
||
property bullcolor read fbullcolor write set_bullcolor;//牛色
|
||
property bearcolor read fbearcolor write set_bearcolor;//熊色
|
||
private
|
||
fline_points_in_canvas;
|
||
fbarrgn;
|
||
fdata_bounds;
|
||
fforeground;
|
||
fbackground;
|
||
fbar_width;
|
||
fbullcolor;
|
||
fbearcolor;
|
||
protected
|
||
function set_graph_data(d);override; //设置数据
|
||
begin
|
||
if d<>fgraph_data then
|
||
begin
|
||
//fx := d[:,0];
|
||
fdata_bounds[0,0] := 0;
|
||
fdata_bounds[0,1] := length(d);
|
||
fdata_bounds[1,0] := minvalue(d[:,4]);
|
||
fdata_bounds[1,1] := maxvalue(d[:,3]);
|
||
inherited;
|
||
end
|
||
end
|
||
private
|
||
function get_abs_barwidth();//获得
|
||
begin
|
||
if fbar_width>0 and fbar_width<=1 then
|
||
begin
|
||
if zoom_to_xyz(0,0,nil,x1,y1) and zoom_to_xyz(1,0,nil,x2,y2) then
|
||
begin
|
||
return (abs(x1-x2)+abs(y1-y2))*fbar_width;
|
||
end
|
||
end
|
||
return fbar_width;
|
||
end
|
||
function set_barwidth(v);//设置宽度
|
||
begin
|
||
if (v<>fbar_width) and (v>0) then
|
||
begin
|
||
fbar_width := v;
|
||
prop_changed("barwidth",v);
|
||
end
|
||
end
|
||
function set_bullcolor(v);//牛色
|
||
begin
|
||
//if not graph_paint_boolen_value(v,nv) then return ;
|
||
if v<>fbullcolor and ifnumber(v) then
|
||
begin
|
||
fbullcolor := v;
|
||
prop_changed("bullcolor",v);
|
||
end
|
||
end
|
||
function set_bearcolor(v);//熊色
|
||
begin
|
||
//if not graph_paint_boolen_value(v,nv) then return ;
|
||
if v<>fbearcolor and ifnumber(v) then
|
||
begin
|
||
fbearcolor := v;
|
||
prop_changed("bearcolor",v);
|
||
end
|
||
end
|
||
end
|
||
type tg_Polyboxplot = class(tg_graph) //盒须图
|
||
function create(pms);
|
||
begin
|
||
inherited;
|
||
fbarrgn := array();
|
||
clip_state := tgc_on;
|
||
line_mode := tgc_on;
|
||
mark_mode := tgc_off;
|
||
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;
|
||
if clip_state=tgc_on then
|
||
begin
|
||
//cvs.axesclip();
|
||
pts := array();
|
||
for i,v in graph_paint_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],bx[2,0],x,y);
|
||
pts[i] := array(x,y);
|
||
end
|
||
cvs.clip_rgn(pts);
|
||
end else
|
||
begin
|
||
cvs.axesunclip();
|
||
end
|
||
xys := array();
|
||
medians := array();
|
||
wick_y := array();
|
||
outliers := array();
|
||
inliers := array(());
|
||
set_lineinfo_to_canvas(cvs);
|
||
ys := array();
|
||
for i,v in fgraph_data do
|
||
begin
|
||
q1 := Quartile(v,1);
|
||
q2 := Quartile(v,2);
|
||
q3 := Quartile(v,3);
|
||
iqr := q3-q1;
|
||
maximum := q3+(1.5*iqr);
|
||
minimum := q1-(1.5*iqr);
|
||
inliers[i] := array();
|
||
for j,w in v do
|
||
begin
|
||
len := length(outliers);
|
||
if w>=minimum and w<=maximum then
|
||
begin
|
||
inlen := length(inliers[i]);
|
||
inliers[i][inlen] := w;
|
||
end
|
||
else if w < minimum then
|
||
begin
|
||
if not zoom_to_xyz(i+1,w,bx[2,0],x,y) then return ;
|
||
outliers[len] := array(integer(x),integer(y));
|
||
|
||
end
|
||
else
|
||
begin
|
||
if not zoom_to_xyz(i+1,w,bx[2,0],x,y) then return ;
|
||
outliers[len] := array(integer(x),integer(y));
|
||
end
|
||
end
|
||
|
||
if not zoom_to_xyz(i+1,q1,bx[2,0],x,y) then return ;
|
||
xys[i] := array(integer(x),integer(y));
|
||
if not zoom_to_xyz(i+1,q2,bx[2,0],x,y) then return ;
|
||
medians[i] := array(integer(x),integer(y));
|
||
if not zoom_to_xyz(i+1,MaxValue(inliers[i]),bx[2,0],x,y) then return ;
|
||
wick_y[i][0] := array(integer(x),integer(y));
|
||
if not zoom_to_xyz(i+1,MinValue(inliers[i]),bx[2,0],x,y) then return ;
|
||
wick_y[i][1] := array(integer(x),integer(y));
|
||
zoom_to_xyz(i+1,q3,bx[2,0],x,y) ;
|
||
ys[i] := array(integer(x),integer(y));
|
||
|
||
if not zoom_to_xyz(i+1,q1,bx[2,0],x,y) then return ;
|
||
if not(tempbarw) and fbar_width>0 then ////////????bar????///////
|
||
begin
|
||
b := get_abs_barwidth();
|
||
zoom_to_xyz((i+1+b/2),q1,bx[2,0],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
|
||
end
|
||
fline_points_in_canvas := xys;
|
||
pinfo := array("line_mode":line_mode,"bar_width":tempbarw,"color":lineinfo.color,"bkcolor":lineinfo.bkcolor,"xy0":ys,"wick_y": wick_y, "medians": medians);
|
||
paint_boxplot(cvs,0,xys,0,pinfo);
|
||
fbarrgn := pinfo["barrgn"];
|
||
mk := markinfo.clone();
|
||
if mark_mode=tgc_on and mk.size>2 then
|
||
begin
|
||
graph_paint_points(mk,cvs,outliers);
|
||
end
|
||
inherited;
|
||
end
|
||
function executecommand(cmd,p);override;
|
||
begin
|
||
case cmd of
|
||
"points_in_canvas":return (visible=tgc_on)? fline_points_in_canvas:nil; //???????
|
||
end;
|
||
return inherited;
|
||
end
|
||
function get_legend_size(w,h);virtual; //??????????
|
||
begin
|
||
mk := markinfo;
|
||
h := fontinfo.size*2+4;
|
||
w := 100;
|
||
if mark_mode=tgc_on then
|
||
begin
|
||
h := max(h,mk.size+4);
|
||
w := 5*h;
|
||
end
|
||
end
|
||
function paint_legend(cvs,rec);override; //???????
|
||
begin
|
||
y0 := ceil(rec[1]+(rec[3]-rec[1])/2);
|
||
dis := ceil((rec[2]-rec[0])/5);
|
||
xys := array((rec[0]+dis,y0),(rec[0]+4*dis,y0));
|
||
set_lineinfo_to_canvas(cvs);
|
||
graph_paint_lines(cvs,tgc_LS_interpolated,xys,0,array("line_mode":line_mode,"bar_width":fbar_width,"color":lineinfo.color,"bkcolor":lineinfo.bkcolor));
|
||
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));
|
||
graph_paint_points(mk,cvs,xys);
|
||
end
|
||
end
|
||
property bar_width read fbar_width write set_bar_width;//= "0" ??????
|
||
private
|
||
fbarrgn;
|
||
fline_points_in_canvas;
|
||
fdata_bounds;
|
||
fforeground;
|
||
fbackground;
|
||
fbar_width;
|
||
protected
|
||
function set_graph_data(d);override; //????????
|
||
begin
|
||
if d<>fgraph_data then
|
||
begin
|
||
fdata_bounds[0,0] := 0;
|
||
fdata_bounds[0,1] := length(d);
|
||
fdata_bounds[1,0] := minvalue(minvalue(d));
|
||
fdata_bounds[1,1] := maxvalue(maxvalue(d));
|
||
inherited;
|
||
end
|
||
end
|
||
private
|
||
function get_abs_barwidth();//获得
|
||
begin
|
||
if fbar_width>0 and fbar_width<=1 then
|
||
begin
|
||
if zoom_to_xyz(0,0,nil,x1,y1) and zoom_to_xyz(1,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
|
||
end
|
||
type tg_Polypie = class(tg_graph) //饼图
|
||
function create(pms);
|
||
begin
|
||
ftexts := array();
|
||
fshow_text := 1;
|
||
pie_radian := array();
|
||
inherited;
|
||
clip_state := tgc_on;
|
||
fcolormap := get_default_color_list();
|
||
line_mode := tgc_on;
|
||
mark_mode := tgc_off;
|
||
fpie_type := 'pie';
|
||
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;
|
||
if clip_state=tgc_on then
|
||
begin
|
||
pts := array();
|
||
for i,v in graph_paint_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],bx[2,0],x,y);
|
||
pts[i] := array(x,y);
|
||
end
|
||
cvs.clip_rgn(pts);
|
||
end else
|
||
begin
|
||
cvs.axesunclip();
|
||
end
|
||
xys := array();
|
||
medians := array();
|
||
wick_y := array();
|
||
outliers := array();
|
||
inliers := array(());
|
||
set_lineinfo_to_canvas(cvs);
|
||
ys := array();
|
||
prominentidx := 1;//
|
||
prominentrate := 0; //
|
||
fpei_parts_data := array();
|
||
for i,v in pie_radian do
|
||
begin
|
||
if fpie_type='pie' then
|
||
begin
|
||
pie_data := 1+get_pie_lines(v[0],v[1],i=prominentidx,prominentrate);
|
||
end
|
||
else if fpie_type='ring' then
|
||
begin
|
||
pie_data := 1+get_pie_ring_lines(v[0],v[1],0.7,0.4,i=prominentidx,prominentrate);
|
||
end
|
||
else if fpie_type='rose' then
|
||
begin
|
||
pie_data := 1+get_rose_lines(v[0],v[1],i=prominentidx,prominentrate, v[3]);
|
||
end
|
||
xys := array();
|
||
for j,v in pie_data do
|
||
begin
|
||
if not zoom_to_xyz(v[0],v[1],bx[2,0],x,y) then return ;
|
||
xys[j] := array(integer(x),integer(y));
|
||
end
|
||
index := i%length(fcolormap);
|
||
item_color := fcolormap[index];
|
||
paint_pie(cvs,xys,array("line_mode":line_mode,"color":item_color,"bkcolor":item_color,"xy0":ys));
|
||
fpei_parts_data[i] := xys;
|
||
end
|
||
end
|
||
function executecommand(cmd,p);override;
|
||
begin
|
||
case cmd of
|
||
"get_texts":
|
||
begin
|
||
return ftexts;
|
||
end
|
||
"hit_part":
|
||
begin
|
||
for i,v in fpei_parts_data do
|
||
begin
|
||
if point_in_rgn(p,v,true) then return i;
|
||
end
|
||
return -1;
|
||
end
|
||
end;
|
||
return inherited;
|
||
end
|
||
function get_legend_size(w,h);override; //获取图例大小
|
||
begin
|
||
if not pie_radian then return inherited;
|
||
sz := fontinfo.size;
|
||
h := (sz*2+6)*max(1,length(pie_radian))+5;
|
||
w := 0;
|
||
ws := 5;
|
||
for i,v in pie_radian do
|
||
begin
|
||
si :=v[2];
|
||
if ifstring(si) then ws := max((length(si))*sz,ws);
|
||
end
|
||
w +=ws;
|
||
w +=35;
|
||
end
|
||
function paint_legend(cvs,rec);override; //绘制图例
|
||
begin
|
||
set_lineinfo_to_canvas(cvs);
|
||
set_fontinfo_to_canvas(cvs);
|
||
h := fontinfo.size*2+6;// + ((h-fontinfo.size)/2);
|
||
y0 := rec[1]+h;
|
||
for i,v in pie_radian do
|
||
begin
|
||
index := i%length(fcolormap);
|
||
item_color := fcolormap[index];
|
||
xys := array((rec[0]+2,y0+i*h-3),(rec[0]+25,y0+i*h-3),(rec[0]+25,y0-h+6+i*h),(rec[0]+2,y0-h+6+i*h));
|
||
paint_pie(cvs,xys,array("line_mode":line_mode,"bar_width":fbar_width,"color":item_color,"bkcolor":item_color));
|
||
cvs.textout(v[2],array(rec[0]+30,y0+(i-1)*h+3));
|
||
end
|
||
end
|
||
property color_map read fcolormap write set_colormap;//颜色地图
|
||
property pie_type read fpie_type write set_pie_type;//类型
|
||
property show_text read fshow_text write set_show_text;
|
||
private
|
||
ftexts;
|
||
fshow_text;
|
||
pie_radian;
|
||
fpei_parts_data;
|
||
fdata_bounds;
|
||
fpie_type;
|
||
fforeground;
|
||
fbackground;
|
||
fcolormap;
|
||
protected
|
||
function set_graph_data(d);override; //设置数据
|
||
begin
|
||
if d<>fgraph_data then
|
||
begin
|
||
fdata_bounds[0,0] := 0;
|
||
fdata_bounds[1,0] := 0;
|
||
fdata_bounds[0,1] := 2;
|
||
fdata_bounds[1,1] := 2;
|
||
inherited;
|
||
data_process();
|
||
end
|
||
end
|
||
private
|
||
function set_pie_type(v);
|
||
begin
|
||
if v<>fpie_type and ( v in array("pie","rose","ring")) then
|
||
begin
|
||
fpie_type := v;
|
||
data_process();
|
||
end
|
||
end
|
||
function set_show_text(v);
|
||
begin
|
||
if v<>fshow_text and (v in array(0,1,2,3)) then
|
||
begin
|
||
fshow_text := v;
|
||
data_process();
|
||
end
|
||
end
|
||
function set_colormap(v);
|
||
begin
|
||
if ifarray(v) and v<>fcolormap then
|
||
begin
|
||
fcolormap := v;
|
||
end
|
||
end
|
||
function data_process(); //
|
||
begin
|
||
total := 0;
|
||
total_value_list := array();
|
||
for i,v in fgraph_data do
|
||
begin
|
||
total := total + v['value'];
|
||
total_value_list[i] := v['value'];
|
||
end
|
||
maxt := maxvalue(total_value_list);
|
||
currentAngle := 0;
|
||
pie_radian := array();
|
||
for i,v in ftexts do //清空
|
||
begin
|
||
v.parent := false;
|
||
end
|
||
ftexts := array();
|
||
for i,v in fgraph_data do
|
||
begin
|
||
pie_radian[i][0] := currentAngle;
|
||
rs := v['value'] / total;
|
||
pie_radian[i][1] := currentAngle + (rs) * 2 * pi();
|
||
sri := format("%3f",rs*100)+"%";
|
||
pie_radian[i][2] := mult_str(" ",7-length(sri))$sri$" "$v["name"];
|
||
pie_radian[i][3] := v['value']/maxt;
|
||
pie_radian[i][4] := currentAngle + rs * pi();
|
||
pie_radian[i][5] := (rs) * 2 * pi();
|
||
carg := currentAngle + rs * pi();
|
||
currentAngle := pie_radian[i][1];
|
||
gtx := new tg_text();
|
||
gtx.parent := self;
|
||
gtx.clip_state :=false;
|
||
case pie_type of
|
||
"rose":
|
||
begin
|
||
gtx.data := 1+array(sin(pie_radian[i][4])*pie_radian[i][3],cos(pie_radian[i][4])*pie_radian[i][3]);
|
||
end
|
||
"ring":
|
||
begin
|
||
gtx.data := 1+array(sin(pie_radian[i][4])*0.7,cos(pie_radian[i][4])*0.7);
|
||
end else
|
||
begin
|
||
gtx.data := 1+array(sin(pie_radian[i][4]),cos(pie_radian[i][4]))*0.8;
|
||
end
|
||
end ;
|
||
if carg<(pi()/4) then
|
||
begin
|
||
gtx.textalign := 8;
|
||
end else
|
||
if carg<(pi()*3/4) then
|
||
begin
|
||
gtx.textalign := 4;
|
||
end else
|
||
if carg<(pi()*5/4) then
|
||
begin
|
||
gtx.textalign := 2;
|
||
end else
|
||
if carg<(pi()*7/4) then
|
||
begin
|
||
gtx.textalign := 6;
|
||
end else gtx.textalign := 8;
|
||
case fshow_text of
|
||
1:
|
||
begin
|
||
gtx.text := array(sri);
|
||
end
|
||
2:
|
||
begin
|
||
gtx.text := array(v["name"]);
|
||
end
|
||
3:
|
||
begin
|
||
gtx.text := array(pie_radian[i][2]);
|
||
end
|
||
else
|
||
begin
|
||
gtx.text := array();
|
||
end
|
||
end;
|
||
ftexts[i] := gtx;
|
||
end
|
||
|
||
end
|
||
function get_pie_lines(arg1,arg2,prominent,prominentrate); //?????????????
|
||
begin
|
||
stp := pi()/360;
|
||
d := 1;
|
||
r := array();
|
||
r[0] := array(0,0);
|
||
idx := 1;
|
||
for i:= arg1 to arg2 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*0.8;
|
||
end
|
||
function get_rose_lines(arg1,arg2,prominent,prominentrate,proportion); //???????????????
|
||
begin
|
||
stp := pi()/360;
|
||
d := 1;
|
||
r := array();
|
||
r[0] := array(0,0);
|
||
idx := 1;
|
||
for i:= arg1 to arg2 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*proportion;
|
||
end
|
||
end
|
||
type tg_Polyradar = class(tg_graph) //雷达图
|
||
function create(pms);
|
||
begin
|
||
findicator_texts := array();
|
||
inherited;
|
||
clip_state := tgc_on;
|
||
fcolormap := get_default_color_list();
|
||
line_mode := tgc_on;
|
||
mark_mode := tgc_off;
|
||
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;
|
||
if clip_state=tgc_on then
|
||
begin
|
||
//cvs.axesclip();
|
||
pts := array();
|
||
for i,v in graph_paint_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],bx[2,0],x,y);
|
||
pts[i] := array(x,y);
|
||
end
|
||
cvs.clip_rgn(pts);
|
||
end else
|
||
begin
|
||
cvs.axesunclip();
|
||
end
|
||
xys := array();
|
||
medians := array();
|
||
wick_y := array();
|
||
outliers := array();
|
||
inliers := array(());
|
||
set_lineinfo_to_canvas(cvs);
|
||
ys := array();
|
||
radar_indicator_radian := data_indicator_process(findicator);
|
||
draw_radar_grid(cvs,radar_indicator_radian);
|
||
|
||
for j,w in fgraph_data do
|
||
begin
|
||
vl := array();
|
||
for jj,vj in w['value'] do
|
||
begin
|
||
vl[jj] := vj/findicator[jj]['max'];
|
||
end
|
||
cl := fcolormap[j%length(fcolormap)];
|
||
cvs.pen.color := cl;
|
||
for i,v in 1+get_radar_cyclings(radar_indicator_radian,vl) do
|
||
begin
|
||
zoom_to_xyz(v[0],v[1],z,x,y) ;
|
||
xys[i] := array(x,y);
|
||
end
|
||
cvs.brush.color := cl;
|
||
cvs.brush.style := BS_SOLID;
|
||
cvs.alpha := 60+j*10;
|
||
cvs.draw_polygon().points(xys).draw();
|
||
cvs.alpha := 255;
|
||
cvs.draw_polyline().points(xys).draw();
|
||
end
|
||
end
|
||
function executecommand(cmd,p);override;
|
||
begin
|
||
case cmd of
|
||
"points_in_canvas":return (visible=tgc_on)? fline_points_in_canvas:nil; //???????
|
||
end;
|
||
return inherited;
|
||
end
|
||
|
||
function get_legend_size(w,h);override; //图例大小
|
||
begin
|
||
sz := fontinfo.size;
|
||
h := (sz*2+6)*max(1,length(fgraph_data))+5;
|
||
w := 0;
|
||
ws := 5;
|
||
for i,v in fgraph_data do
|
||
begin
|
||
si :=v["name"];
|
||
if ifstring(si) then ws := max((length(si))*sz,ws);
|
||
end
|
||
w +=ws;
|
||
w +=35;
|
||
end
|
||
function paint_legend(cvs,rec);override; //图例绘制
|
||
begin
|
||
set_lineinfo_to_canvas(cvs);
|
||
set_fontinfo_to_canvas(cvs);
|
||
h := fontinfo.size*2+6;// + ((h-fontinfo.size)/2);
|
||
y0 := rec[1]+h;
|
||
for i,v in fgraph_data do
|
||
begin
|
||
index := i%length(fcolormap);
|
||
item_color := fcolormap[index];
|
||
xys := array((rec[0]+2,y0+i*h),(rec[0]+25,y0+i*h),(rec[0]+25,y0-fontinfo.size+i*h),(rec[0]+2,y0-fontinfo.size+i*h));
|
||
paint_pie(cvs,xys,array("line_mode":line_mode,"bar_width":fbar_width,"color":item_color,"bkcolor":item_color));
|
||
cvs.textout(v["name"],array(rec[0]+30,y0+(i-1)*h));
|
||
end
|
||
end
|
||
property color_map read fcolormap write fcolormap;
|
||
property indicator read findicator write set_indicator;// 指标轴
|
||
private
|
||
fline_points_in_canvas;
|
||
fdata_bounds;
|
||
fcolormap;
|
||
fforeground;
|
||
fbackground;
|
||
findicator;
|
||
findicator_texts;
|
||
protected
|
||
function set_graph_data(d);override; //????????
|
||
begin
|
||
if d<>fgraph_data then
|
||
begin
|
||
fdata_bounds[0,0] := -0.1;
|
||
fdata_bounds[0,1] := 2.1;
|
||
fdata_bounds[1,0] := -0.2;
|
||
fdata_bounds[1,1] := 2.1;
|
||
inherited;
|
||
end
|
||
end
|
||
private
|
||
function set_indicator(v);
|
||
begin
|
||
if ifarray(v) and v<>findicator then
|
||
begin
|
||
findicator := v;
|
||
draw_indicator_text(v);
|
||
end
|
||
end
|
||
function data_indicator_process(data); //计算数据
|
||
begin
|
||
borders := Length(data);
|
||
angleStep := 2 * pi() / borders;
|
||
currentAngle := 0;
|
||
segments := array(0);
|
||
for i,v in data do
|
||
begin
|
||
if i=0 then continue;
|
||
currentAngle += angleStep;
|
||
segments[i] := currentAngle;
|
||
end
|
||
return segments;
|
||
end
|
||
function draw_indicator_text(data);
|
||
begin
|
||
borders := Length(data);
|
||
angleStep := 2 * pi() / borders;
|
||
currentAngle := 0;
|
||
rightVertices := array();
|
||
for i,v in findicator_texts do
|
||
begin
|
||
v.parent := nil;
|
||
end
|
||
findicator_texts := array();
|
||
for i := 0 to borders - 1 do
|
||
begin
|
||
text_indicator := 1+array(sin(currentAngle)*1,cos(currentAngle)*1);
|
||
gtx := new tg_text();
|
||
gtx.clip_state := tgc_off;
|
||
gtx.line_mode := false;
|
||
gtx.parent := self;
|
||
gtx.text := array(data[i]['name']);
|
||
gtx.data := text_indicator;
|
||
if currentAngle<(pi()/4) then
|
||
begin
|
||
gtx.textalign := 8;
|
||
end else
|
||
if currentAngle<(pi()*3/4) then
|
||
begin
|
||
gtx.textalign := 4;
|
||
end else
|
||
if currentAngle<(pi()*5/4) then
|
||
begin
|
||
gtx.textalign := 2;
|
||
end else
|
||
if currentAngle<(pi()*7/4) then
|
||
begin
|
||
gtx.textalign := 6;
|
||
end else gtx.textalign := 8;
|
||
//gtx.font_angle := currentAngle-pi()*3/4;
|
||
currentAngle := currentAngle + angleStep;
|
||
findicator_texts[i] := gtx;
|
||
end
|
||
end
|
||
function get_radar_cyclings(iradar,r1);
|
||
begin
|
||
vis := array();
|
||
r := array();
|
||
for i,vi in iradar do
|
||
begin
|
||
if ifarray(r1) then rx := r1[i];
|
||
else rx := r1;
|
||
x0 := sin(vi)*rx;
|
||
y0 := cos(vi)*rx;
|
||
r[i] := array(x0,y0);
|
||
end
|
||
r[length(r)] := r[0];
|
||
return r;
|
||
end
|
||
function draw_radar_grid(cvs,iradar);
|
||
begin
|
||
bx := axes.zoom_box;
|
||
z := bx[2,0];
|
||
vis := array();
|
||
set_lineinfo_to_canvas(cvs);
|
||
for i,vi in iradar do
|
||
begin
|
||
x0 := sin(vi);
|
||
y0 := cos(vi);
|
||
if not zoom_to_xyz(x0+1,y0+1,z,x,y) then return ;
|
||
zoom_to_xyz(1,1,z,x1,y1);
|
||
cvs.moveto(array(x1,y1));
|
||
cvs.lineto(array(x,y));
|
||
end
|
||
n := 4;
|
||
st := 1/n;
|
||
for i := 1 to n do
|
||
begin
|
||
for i,v in 1+get_radar_cyclings(iradar,i*st) do
|
||
begin
|
||
zoom_to_xyz(v[0],v[1],z,x,y) ;
|
||
if i=0 then cvs.moveto(x,y);
|
||
else cvs.lineto(x,y);
|
||
end
|
||
end
|
||
end
|
||
end
|
||
type tg_Polytree = class(tg_graph) //树图对象
|
||
function create(pms);
|
||
begin
|
||
inherited;
|
||
clip_state := tgc_on;
|
||
line_mode := tgc_on;
|
||
mark_mode := tgc_off;
|
||
fshow_text := tgc_on;
|
||
fdata_bounds := array((0,50),(0,50),(0,50));
|
||
fnode_space_x := 50;
|
||
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;
|
||
if clip_state=tgc_on then
|
||
begin
|
||
pts := array();
|
||
for i,v in graph_paint_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],bx[2,0],x,y);
|
||
pts[i] := array(x,y);
|
||
end
|
||
cvs.clip_rgn(pts);
|
||
end else
|
||
begin
|
||
cvs.axesunclip();
|
||
end
|
||
xys := array();
|
||
set_lineinfo_to_canvas(cvs);
|
||
ys := array();
|
||
fline_points_in_canvas := xys;
|
||
render_tree(fstructure_tree, cvs, bx);
|
||
end
|
||
function executecommand(cmd,p);override;
|
||
begin
|
||
case cmd of
|
||
"points_in_canvas":return (visible=tgc_on)? fline_points_in_canvas:nil; //数据散点
|
||
end;
|
||
return inherited;
|
||
end
|
||
function firstwalk(V,Distance);override; // 第一次递归
|
||
begin
|
||
if V.NodeCount = 0 then
|
||
begin
|
||
if V.leftmost_sibling <> nil then
|
||
begin
|
||
if V.left_brother() = nil then
|
||
V.X := 0 + Distance;
|
||
else
|
||
V.X := V.left_brother().X + Distance;
|
||
end
|
||
else
|
||
V.X := 0;
|
||
end
|
||
else
|
||
begin
|
||
DefaultAncestor := V.GetNodeByIndex(0);
|
||
for i := 0 to V.NodeCount-1 do
|
||
begin
|
||
firstwalk(V.GetNodeByIndex(i), Distance);
|
||
DefaultAncestor := apportion(V.GetNodeByIndex(i), DefaultAncestor, Distance);
|
||
end;
|
||
ExecuteShifts(V);
|
||
Midpoint := (V.GetNodeByIndex(0).X + V.LastChild.X) / 2;
|
||
W := V.left_brother();
|
||
if W <> nil then
|
||
begin
|
||
V.X := W.X + Distance;
|
||
V.ModVal := V.X - Midpoint;
|
||
end
|
||
else
|
||
V.X := Midpoint;
|
||
end;
|
||
return V;
|
||
end;
|
||
function apportion(V,DefaultAncestor, Distance);override; //修正子孙节点定位
|
||
begin
|
||
LeftBrother := V.left_brother();
|
||
if LeftBrother <> nil then
|
||
begin
|
||
VInnerRight := V;
|
||
VOuterRight := V;
|
||
VInnerLeft := LeftBrother;
|
||
VOuterLeft := V.leftmost_sibling;
|
||
if VOuterLeft = nil then VOuterLeft := V;
|
||
|
||
SInnerRight := V.ModVal;
|
||
SOuterRight := V.ModVal;
|
||
SInnerLeft := VInnerLeft.ModVal;
|
||
SOuterLeft := VOuterLeft.ModVal;
|
||
|
||
while (VInnerLeft.right() <> nil) and (VInnerRight.left() <> nil) do
|
||
begin
|
||
VInnerLeft := VInnerLeft.right();
|
||
VInnerRight := VInnerRight.left();
|
||
VOuterLeft := VOuterLeft.left();
|
||
VOuterRight := VOuterRight.right();
|
||
if VInnerLeft = 0 then
|
||
begin
|
||
end
|
||
if VOuterRight = 0 then
|
||
begin
|
||
end
|
||
VOuterRight.Ancestor := V;
|
||
|
||
Shift := (VInnerLeft.X + SInnerLeft) - (VInnerRight.X + SInnerRight) + Distance;
|
||
if Shift > 0 then
|
||
begin
|
||
Anc := get_ancestor(VInnerLeft, V, DefaultAncestor);
|
||
move_subtree(Anc, V, Shift);
|
||
SInnerRight := SInnerRight + Shift;
|
||
SOuterRight := SOuterRight + Shift;
|
||
end;
|
||
SInnerLeft := SInnerLeft + VInnerLeft.ModVal;
|
||
SInnerRight := SInnerRight + VInnerRight.ModVal;
|
||
SOuterLeft := SOuterLeft + VOuterLeft.ModVal;
|
||
SOuterRight := SOuterRight + VOuterRight.ModVal;
|
||
end;
|
||
|
||
if (VInnerLeft.right() <> nil) and (VOuterRight.right() = nil) then
|
||
begin
|
||
VOuterRight.Thread := VInnerLeft.right();
|
||
VOuterRight.ModVal := VOuterRight.ModVal + (SInnerLeft - SOuterRight);
|
||
end
|
||
else if (VInnerRight.left() <> nil) and (VOuterLeft.left() = nil) then
|
||
begin
|
||
VOuterLeft.Thread := VInnerRight.left();
|
||
VOuterLeft.ModVal := VOuterLeft.ModVal + (SInnerRight - SOuterLeft);
|
||
end;
|
||
DefaultAncestor := V;
|
||
end;
|
||
return DefaultAncestor;
|
||
end;
|
||
function move_subtree(WL,WR, Shift);override; //移动子树
|
||
begin
|
||
Subtrees := WR.TNumber - WL.TNumber;
|
||
_WRChange := WR.Change - (Shift / Subtrees);
|
||
WR.Change := _WRChange;
|
||
_WRShift := WR.Shift + Shift;
|
||
WR.Shift := _WRShift;
|
||
_WLChange := WL.Change + (Shift / Subtrees);
|
||
WL.Change :=_WLChange;
|
||
_WRX := WR.X + Shift;
|
||
WR.X := _WRX;
|
||
_WRModVal := WR.ModVal + Shift;
|
||
WR.ModVal := _WRModVal;
|
||
end;
|
||
function ExecuteShifts(V);override;
|
||
begin
|
||
Shift := 0;
|
||
Change := 0;
|
||
for i := V.NodeCount-1 downto 0 do
|
||
begin
|
||
W := V.GetNodeByIndex(i);
|
||
W.X := W.X + Shift;
|
||
W.ModVal := W.ModVal + Shift;
|
||
Change := Change + W.Change;
|
||
Shift := Shift + W.Shift + Change;
|
||
if Change = NAN then
|
||
if Change = -INF then
|
||
end;
|
||
end;
|
||
function get_ancestor(VIL, V, DefaultAncestor);override; //如果vil节点的祖先节点在v节点的兄弟节点中,那么返回vil的祖先节点,否则返回default_ancestor
|
||
begin
|
||
if (VIL.Ancestor <> nil) and (V.Parent <> nil) and (VIL.Ancestor.Parent = V.Parent) then
|
||
return VIL.Ancestor;
|
||
else
|
||
return DefaultAncestor;
|
||
end;
|
||
function second_walk(V, M, Depth, Min);override; //第二次遍历
|
||
begin
|
||
V.X := V.X + M;
|
||
V.Y := Depth;
|
||
if Min = -1 then
|
||
Min := V.X
|
||
else if V.X < Min then
|
||
Min := V.X;
|
||
|
||
for i := 0 to V.NodeCount-1 do
|
||
Min := second_walk(V.GetNodeByIndex(i), M + V.ModVal, Depth + 1, Min);
|
||
|
||
return Min;
|
||
end;
|
||
function third_walk(V, N);override; // 第三次遍历
|
||
begin
|
||
V.X := V.X + N;
|
||
for i := 0 to V.NodeCount-1 do
|
||
third_walk(V.GetNodeByIndex(i), N);
|
||
end;
|
||
function Buchheim(Tree);override;
|
||
begin
|
||
DT := firstwalk(Tree, 1);
|
||
Min := second_walk(DT, 0, 0, -1);
|
||
if Min < 0 then third_walk(DT, -Min);
|
||
return DT;
|
||
end;
|
||
function handle_tree(V);override;
|
||
begin
|
||
V.X := V.X * fnode_space_x;
|
||
V.X := V.X + fnode_space_x;
|
||
V.Y := V.Y * fnode_space_x;
|
||
V.Y := V.Y + fnode_space_x;
|
||
for i := 0 to V.NodeCount-1 do handle_tree(V.GetNodeByIndex(i));
|
||
end;
|
||
function render_tree(Tree,cvs, bx);override; //绘制树
|
||
begin
|
||
if Tree.ShowNode then
|
||
begin
|
||
for j := 0 to Tree.NodeCount-1 do
|
||
begin
|
||
if Tree.GetNodeByIndex(j).ShowNode then
|
||
begin
|
||
xys := array();
|
||
set_lineinfo_to_canvas(cvs);
|
||
ys := array();
|
||
//_data := array((Tree.X,Tree.Y),(Tree.X,(Tree.Y + Tree.GetNodeByIndex(j).Y) / 2),(Tree.GetNodeByIndex(j).X,(Tree.Y + Tree.GetNodeByIndex(j).Y) / 2),(Tree.GetNodeByIndex(j).X,Tree.GetNodeByIndex(j).Y));
|
||
TreeY := Tree.Y;
|
||
TreeX := Tree.X;
|
||
tndj := Tree.GetNodeByIndex(j);
|
||
Treejy := tndj.Y;
|
||
Treejx := tndj.x;
|
||
try2 := (TreeY + Treejy) / 2;
|
||
_data := array(
|
||
(TreeY, TreeX),
|
||
(try2, TreeX),
|
||
(try2, Treejx),
|
||
(Treejy, Treejx)
|
||
);
|
||
{_data := array(
|
||
(Tree.Y, Tree.X),
|
||
((Tree.Y + Tree.GetNodeByIndex(j).Y) / 2, Tree.X),
|
||
((Tree.Y + Tree.GetNodeByIndex(j).Y) / 2, Tree.GetNodeByIndex(j).X),
|
||
(Tree.GetNodeByIndex(j).Y, Tree.GetNodeByIndex(j).X)
|
||
);}
|
||
|
||
for i,v in _data do
|
||
begin
|
||
if not zoom_to_xyz(v[0],v[1],bx[2,0],x,y) then return ;
|
||
xys[i] := array(integer(x),integer(y));
|
||
end
|
||
fline_points_in_canvas := xys;
|
||
set_lineinfo_to_canvas(cvs);
|
||
paint_tree(cvs,xys,array("line_mode":line_mode,"bar_width":0,"color":lineinfo.color,"bkcolor":lineinfo.bkcolor,"xy0":ys));
|
||
mk := markinfo.clone();
|
||
if mark_mode=tgc_on and mk.size>2 then
|
||
begin
|
||
graph_paint_points(mk,cvs,array(xys[0], xys[3]));
|
||
end
|
||
if (Tree.GetNodeByIndex(j).NodeCount) then render_tree(Tree.GetNodeByIndex(j),cvs, bx);
|
||
end
|
||
end
|
||
end
|
||
end;
|
||
property node_space_x read fnode_space_x write set_node_space_x;//= "0" 柱状宽度
|
||
property show_text read fshow_text write set_show_text;//= "0" 柱状宽度
|
||
private
|
||
fline_points_in_canvas;
|
||
fdata_bounds;
|
||
fforeground;
|
||
fbackground;
|
||
fnode_space_x;
|
||
fshow_text;
|
||
fstructure_tree;
|
||
protected
|
||
function set_graph_data(d);override; //设置数据
|
||
begin
|
||
if d<>fgraph_data then
|
||
begin
|
||
test_tree := new tg_tree_node(d,nil,0,1);
|
||
Buchheim_tree := Buchheim(test_tree);
|
||
handle_tree(Buchheim_tree);
|
||
fstructure_tree := Buchheim_tree;
|
||
find_data_bounds(fstructure_tree);
|
||
//fdata_bounds[0,1] := fdata_bounds[0,1] +fnode_space_x;
|
||
//fdata_bounds[1,1] := fdata_bounds[1,1] +fnode_space_x;
|
||
inherited;
|
||
end
|
||
end
|
||
private
|
||
function set_node_space_x(v);
|
||
begin
|
||
if v >=0 and v<>fnode_space_x then
|
||
begin
|
||
fnode_space_x := v;
|
||
prop_changed("node_space_x",v);
|
||
end
|
||
end
|
||
function set_show_text(v);
|
||
begin
|
||
if not graph_paint_boolen_value(v,nv) then return ;
|
||
if nv<>fshow_text then
|
||
begin
|
||
fshow_text := nv;
|
||
find_data_bounds(fstructure_tree);
|
||
prop_changed("show_text",nv);
|
||
end
|
||
end
|
||
function find_data_bounds(Tree); //设置数据
|
||
begin
|
||
if not fstructure_tree then return ;
|
||
if Tree.ShowNode then
|
||
begin
|
||
if fshow_text = tgc_on then
|
||
begin
|
||
n := Tree.TName;
|
||
if n and ifstring(n) then
|
||
begin
|
||
if tree.ftextobj then
|
||
begin
|
||
gtx.data := array(Tree.Y, Tree.X);
|
||
end else
|
||
begin
|
||
gtx := new tg_text();
|
||
gtx.clip_state := tgc_off;
|
||
gtx.parent := self;
|
||
gtx.text := array(n);
|
||
gtx.data := array(Tree.Y, Tree.X);
|
||
tree.ftextobj := gtx;
|
||
end
|
||
end else
|
||
begin
|
||
if tree.ftextobj then
|
||
begin
|
||
tree.ftextobj.visible := false;
|
||
end
|
||
end
|
||
end
|
||
|
||
if Tree.NodeCount >0 then
|
||
begin
|
||
for j := 0 to Tree.NodeCount-1 do
|
||
begin
|
||
ndj := Tree.GetNodeByIndex(j);
|
||
//fdata_bounds[0,0] := 0;
|
||
//fdata_bounds[1,0] := 0;
|
||
fdata_bounds[0,1] := Max(fdata_bounds[0,1],ndj.Y);
|
||
fdata_bounds[1,1] := Max(fdata_bounds[1,1],ndj.X);
|
||
find_data_bounds(ndj);
|
||
end
|
||
end
|
||
end
|
||
end
|
||
end
|
||
type tg_Polysunburst = class(tg_graph) //旭日图
|
||
function create(pms);
|
||
begin
|
||
inherited;
|
||
ftext_container := array();
|
||
clip_state := tgc_on;
|
||
fcolormap := get_default_color_list();
|
||
line_mode := tgc_on;
|
||
mark_mode := tgc_off;
|
||
fbar_width := 0;
|
||
fdata_bounds := array((0,1),(0,1),(0,1));
|
||
fshow_text := tgc_on;
|
||
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;
|
||
if clip_state=tgc_on then
|
||
begin
|
||
pts := array();
|
||
for i,v in graph_paint_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],bx[2,0],x,y);
|
||
pts[i] := array(x,y);
|
||
end
|
||
cvs.clip_rgn(pts);
|
||
end else
|
||
begin
|
||
cvs.axesunclip();
|
||
end
|
||
xys := array();
|
||
medians := array();
|
||
wick_y := array();
|
||
outliers := array();
|
||
inliers := array(());
|
||
set_lineinfo_to_canvas(cvs);
|
||
ys := array();
|
||
CalculateCoordinates(1.0, 10.0, 0.4, 0.7, 0, 360, fgraph_data, cvs, bx);
|
||
inherited;
|
||
end
|
||
function executecommand(cmd,p);override;
|
||
begin
|
||
case cmd of
|
||
"points_in_canvas":return (visible=tgc_on)? fline_points_in_canvas:nil; //???????
|
||
end;
|
||
return inherited;
|
||
end
|
||
function CalculateCoordinates(x1, y1, r1, r2, startAngle, endAngle, node, cvs, bx);
|
||
begin
|
||
totalValue := CalculateTotalValue(node);
|
||
angle := startAngle;
|
||
_r3 := r1 + (r2 - r1);
|
||
_r4 := r2 + (r2 - r1);
|
||
ndc := node['children'];
|
||
if ndc and ifarray(ndc) then
|
||
begin
|
||
for i := 0 to length(ndc)-1 do
|
||
begin
|
||
childStartAngle := angle;
|
||
xys := array();
|
||
_portion := CalculateTotalValue(ndc[i]) / totalValue;
|
||
childEndAngle := angle +_portion * 2 * pi() * x1;
|
||
pie_data := fcenter+get_pie_ring_lines(childStartAngle,childEndAngle,r2,r1,0,0);
|
||
for j,v in pie_data do
|
||
begin
|
||
if not zoom_to_xyz(v[0],v[1],bx[2,0],x,y) then return ;
|
||
xys[j] := array(integer(x),integer(y));
|
||
zoom_to_xyz(v[0],0,0,x,y) ;
|
||
end
|
||
fline_points_in_canvas := xys;
|
||
its := ndc[i]['itemstyle']['color'];
|
||
item_color := ifnumber(its)?its: fcolormap[1];
|
||
paint_sunburst(cvs,xys,array("line_mode":line_mode,"bar_width":0,"color":0xffffff,"bkcolor":item_color,"xy0":ys));
|
||
CalculateCoordinates(_portion * x1, y1, _r3, _r4, childStartAngle, childEndAngle, ndc[i], cvs, bx);
|
||
angle := childEndAngle;
|
||
end;
|
||
end
|
||
end;
|
||
function CalculateTotalValue(node); //设置数据
|
||
begin
|
||
if node = nil then return 0;
|
||
pv := 0;
|
||
if node['value'] <> nil then pv := node['value'];
|
||
//return node['value'];
|
||
totalValue := 0;
|
||
ndc := node['children'];
|
||
if ifarray(ndc) and ndc then
|
||
begin
|
||
for i := 0 to length(ndc)-1 do
|
||
begin
|
||
totalValue := totalValue + CalculateTotalValue(ndc[i]);
|
||
end;
|
||
end
|
||
return max(pv,totalValue);
|
||
end;
|
||
function getTreeDepth(node); //获取深度
|
||
begin
|
||
ndc := node['children'];
|
||
if not(ifarray(ndc) and ndc) then
|
||
begin
|
||
return 0;
|
||
end
|
||
_deep := 0;
|
||
for i := 0 to length(ndc)-1 do
|
||
begin
|
||
_deep := Max(_deep, getTreeDepth(ndc[i]));
|
||
end
|
||
return _deep + 1;
|
||
end
|
||
function get_pie_ring_center(arg1_,arg2_,r1,r2,prominent,prominentrate); //???????????????
|
||
begin
|
||
arg := arg1_+(arg2_-arg1_)/2;
|
||
d1 := r1;
|
||
return array(sin(arg)*d1,cos(arg)*d1);
|
||
end
|
||
function get_legend_size(w,h);override;
|
||
begin
|
||
inherited ;
|
||
end
|
||
function paint_legend(cvs,rec);override;
|
||
begin
|
||
inherited;
|
||
end
|
||
property color_map read fcolormap write fcolormap;//
|
||
property show_text read fshow_text write set_show_text;//
|
||
private
|
||
ftext_container;
|
||
fline_points_in_canvas;
|
||
fdata_bounds;
|
||
fcolormap;
|
||
fshow_text;
|
||
fforeground;
|
||
fbackground;
|
||
fcenter;
|
||
protected
|
||
function set_graph_data(d);override; //设置数据
|
||
begin
|
||
if d<>fgraph_data then
|
||
begin
|
||
clear_text();
|
||
deep := getTreeDepth(d);
|
||
fcenter := deep*(0.7-0.4)+0.4;
|
||
fdata_bounds[0,0] := 0;
|
||
fdata_bounds[1,0] := 0;
|
||
fdata_bounds[0,1] := fcenter * 2;
|
||
fdata_bounds[1,1] := fcenter * 2;
|
||
inherited;
|
||
draw_text();
|
||
end
|
||
end
|
||
private
|
||
function set_show_text(v);
|
||
begin
|
||
if not graph_paint_boolen_value(v,nv) then return ;
|
||
if nv<>fshow_text then
|
||
begin
|
||
fshow_text := nv;
|
||
draw_text();
|
||
end
|
||
end
|
||
function clear_text();
|
||
begin
|
||
for i,v in ftext_container do
|
||
begin
|
||
v.parent := nil;
|
||
end
|
||
ftext_container := array();
|
||
end
|
||
function draw_text();
|
||
begin
|
||
if fshow_text = tgc_on then
|
||
begin
|
||
CalculateTextCoordinates(1.0, 10.0, 0.1, 0.4, 0, 360, fgraph_data);
|
||
end else
|
||
begin
|
||
clear_text();
|
||
end
|
||
end
|
||
function CalculateTextCoordinates(x1, y1, r1, r2, startAngle, endAngle, node);
|
||
begin
|
||
totalValue := CalculateTotalValue(node);
|
||
angle := startAngle;
|
||
_r3 := r1 + (r2 - r1);
|
||
_r4 := r2 + (r2 - r1);
|
||
textct := length(ftext_container)>0;
|
||
if ifarray(node) and node["name"] and ifstring(node["name"]) then
|
||
begin
|
||
|
||
gtx := new tg_text();
|
||
gtx.clip_state := tgc_on;
|
||
gtx.line_mode := 0;
|
||
if textct then
|
||
begin
|
||
gtx.font_angle := ((startAngle + endAngle) / 2) - pi()/2;
|
||
text_data := fcenter+get_pie_ring_center(startAngle,endAngle,r1,r2,0,0);
|
||
end else
|
||
begin
|
||
gtx.textalign := 5;
|
||
text_data := fcenter+get_pie_ring_center(startAngle,endAngle,r1/2,r2,0,0);
|
||
end
|
||
gtx.data := text_data;
|
||
gtx.parent := self;
|
||
gtx.text := array(node['name']);
|
||
ftext_container[length(ftext_container)] := gtx;
|
||
end
|
||
ndc := node['children'];
|
||
if ifarray(ndc) and ndc then
|
||
begin
|
||
for i := 0 to length(ndc)-1 do
|
||
begin
|
||
childStartAngle := angle;
|
||
_portion := CalculateTotalValue(ndc[i]) / totalValue;
|
||
childEndAngle := angle +_portion * 2 * pi() * x1;
|
||
CalculateTextCoordinates(_portion * x1, y1, _r3, _r4, childStartAngle, childEndAngle, ndc[i]);
|
||
angle := childEndAngle;
|
||
end;
|
||
end
|
||
end;
|
||
end
|
||
implementation
|
||
type tg_tree_node = class(TNode)
|
||
private
|
||
public
|
||
ftextobj;
|
||
fName;
|
||
X; // x坐标
|
||
Y; // y坐标
|
||
//fChildren;
|
||
Thread; // 线程节点,也就是指向下一个轮廓节点
|
||
ModVal; // 根据左兄弟定位的x与根据子节点中间定位的x之差
|
||
Ancestor; // 要么指向自身,要么指向所属树的根
|
||
Change;
|
||
Shift;
|
||
TNumber; // 这是它在兄弟节点中的位置索引 1...n
|
||
LmostSibling; // 最左侧的兄弟节点
|
||
ShowNode;
|
||
function Create(tree,p,depth,number);virtual;
|
||
begin
|
||
class(TNode).create();
|
||
fName := tree['name'];
|
||
ndc := tree['children'];
|
||
if ifarray(ndc) and ndc then
|
||
begin
|
||
for i,v in ndc do
|
||
begin
|
||
it := new tg_tree_node(v,self,depth+1, i+1) ;
|
||
it.parent := self;
|
||
AppendNode(it);
|
||
//self(true).fChildren := it;
|
||
end
|
||
end
|
||
X := -1;
|
||
Y := Depth;
|
||
Thread := nil;
|
||
ModVal := 0;
|
||
Ancestor := self(true);
|
||
Change := 0;
|
||
Shift := 0;
|
||
TNumber := number;
|
||
LmostSibling := nil;
|
||
ShowNode := tree['show'] = nil ? true : tree['show'];
|
||
end
|
||
function right(); // 有线程返回线程节点,否则返回最右侧的子节点,也就是树的右轮廓
|
||
begin
|
||
if self.Thread <> nil then
|
||
Result := self.Thread;
|
||
else if self.NodeCount > 0 then
|
||
Result := self.LastChild;
|
||
else
|
||
Result := nil;
|
||
return Result;
|
||
end
|
||
|
||
function left();virtual; // 有线程返回线程节点,否则返回最左侧的子节点,也就是树的左轮廓
|
||
begin
|
||
if self.Thread <> nil then
|
||
result := self.Thread;
|
||
else if self.NodeCount > 0 then
|
||
Result := self.GetNodeByIndex(0);
|
||
else
|
||
Result := nil;
|
||
return Result;
|
||
end
|
||
|
||
function left_brother(); // 获取前一个兄弟节点
|
||
begin
|
||
Result := nil;
|
||
if self.Parent = nil then
|
||
return Result;
|
||
for i := 0 to self.parent.NodeCount-1 do
|
||
begin
|
||
if self.parent.GetNodeByIndex(i) = self then
|
||
return Result;
|
||
else
|
||
Result := self.parent.GetNodeByIndex(i);
|
||
end;
|
||
return Result;
|
||
end
|
||
|
||
function get_lmost_sibling(); // 获取同一层级第一个兄弟节点,如果第一个是自身,那么返回null
|
||
begin
|
||
if (self.LmostSibling = nil) and (self.Parent <> nil) and (self <> self.Parent.GetNodeByIndex(0)) then
|
||
self.LmostSibling := self.Parent.GetNodeByIndex(0);
|
||
Result := self.LmostSibling;
|
||
return Result;
|
||
end
|
||
|
||
function destroy();override;
|
||
begin
|
||
inherited;
|
||
if ftextobj then ftextobj.parent := nil;
|
||
ftextobj := nil;
|
||
end
|
||
property TName read fName;
|
||
property leftmost_sibling read get_lmost_sibling;
|
||
end
|
||
function get_pie_ring_lines(arg1,arg2,r1,r2,prominent,prominentrate); //???????????????
|
||
begin
|
||
stp := pi()/360;
|
||
d1 := r1;
|
||
d2 := r2;
|
||
r := array();
|
||
s := array();
|
||
s_reverse := array();
|
||
//r[0] := array(0,0);
|
||
idx := 0;
|
||
for i:= arg1+(prominent?stp:0) to arg2-(prominent?stp:0) step stp do
|
||
begin
|
||
s[idx] := array(sin(i)*d2,cos(i)*d2);
|
||
r[idx++] := array(sin(i)*d1,cos(i)*d1);
|
||
end
|
||
ls :=length(s);
|
||
for j,v in s do
|
||
begin
|
||
s_reverse[j] := s[ls-j-1];
|
||
end
|
||
r &= s_reverse;
|
||
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
|
||
function paint_candlestick(cvs,pls,xys,cls,fdata,ifo);
|
||
begin
|
||
o := static new tg_const();
|
||
b_w_x := integer(ifo["bar_width"][0]/2);
|
||
b_w_y := integer(ifo["bar_width"][1]/2);
|
||
//cvs.brush.color := ifo["bullcolor"];
|
||
wflg := (abs(b_w_x)+abs(b_w_y))>1;
|
||
barrgn := 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);
|
||
cvs.brush.style := tgc_BS_SOLID;
|
||
upper_wick_start := fdata[i][2]>= fdata[i][1]?ifo["xy0",i]:v;
|
||
lower_wick_start := fdata[i][2]>= fdata[i][1]?v:ifo["xy0",i];
|
||
cvs.brush.color := fdata[i][2]>= fdata[i][1]?ifo["bullcolor"]:ifo["bearcolor"];
|
||
cvs.pen.color := cvs.brush.color;
|
||
v1234 := array(v1,v2,v3,v4);
|
||
barrgn[i] := v1234;
|
||
cvs.draw_polygon().points(v1234).draw();
|
||
cvs.moveto(upper_wick_start);
|
||
cvs.lineto(ifo["wick_y",i,0]); //
|
||
cvs.moveto(lower_wick_start);
|
||
cvs.lineto(ifo["wick_y",i,1]); //
|
||
end else
|
||
begin
|
||
cvs.moveto(array(ifo["xy0",i,0],ifo["xy0",i,1]));
|
||
cvs.lineto(array(ifo["xy0",i,0],ifo["xy0",i,1]));
|
||
end
|
||
end
|
||
ifo["barrgn"] := barrgn;
|
||
end
|
||
function paint_boxplot(cvs,pls,xys,cls,ifo); //
|
||
begin
|
||
o := static new tg_const();
|
||
b_w_x := integer(ifo["bar_width"][0]/2);
|
||
b_w_y := integer(ifo["bar_width"][1]/2);
|
||
barrgn := array();
|
||
wflg := (abs(b_w_x)+abs(b_w_y))>1;
|
||
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);
|
||
v1234 := array(v1,v2,v3,v4);
|
||
barrgn[i] := v1234;
|
||
upper_wick_start := ifo["xy0",i];
|
||
lower_wick_start := v;
|
||
cvs.pen.color := cvs.brush.color; // ???????????
|
||
cvs.draw_polygon().points(v1234).draw();
|
||
cvs.moveto(upper_wick_start);
|
||
cvs.lineto(ifo["wick_y",i,0]); // ?????10???????????????????????????wick_y
|
||
|
||
cvs.moveto(lower_wick_start);
|
||
cvs.lineto(ifo["wick_y",i,1]);
|
||
upper_bound_start := array(ifo["wick_y",i,0,0]-b_w_x,ifo["wick_y",i,0,1]-b_w_y);
|
||
upper_bound_end := array(ifo["wick_y",i,0,0]+b_w_x,ifo["wick_y",i,0,1]+b_w_y);
|
||
cvs.moveto(upper_bound_start);
|
||
cvs.lineto(upper_bound_end);
|
||
|
||
lower_bound_start := array(ifo["wick_y",i,1,0]-b_w_x,ifo["wick_y",i,1,1]-b_w_y);
|
||
lower_bound_end := array(ifo["wick_y",i,1,0]+b_w_x,ifo["wick_y",i,1,1]+b_w_y);
|
||
cvs.moveto(lower_bound_start);
|
||
cvs.lineto(lower_bound_end);
|
||
|
||
medians_start := array(ifo["medians",i,0]-b_w_x,ifo["medians",i,1]-b_w_y);
|
||
medians_end := array(ifo["medians",i,0]+b_w_x,ifo["medians",i,1]+b_w_y);
|
||
cvs.moveto(medians_start);
|
||
cvs.lineto(medians_end);
|
||
end else
|
||
begin
|
||
cvs.moveto(array(ifo["xy0",i,0],ifo["xy0",i,1]));
|
||
cvs.lineto(array(ifo["xy0",i,0],ifo["xy0",i,1]));
|
||
end
|
||
end
|
||
ifo["barrgn"] := barrgn;
|
||
end
|
||
|
||
function paint_pie(cvs,xys,ifo); //画饼
|
||
begin
|
||
cvs.brush.color := ifo["bkcolor"];
|
||
cvs.brush.style := tgc_BS_SOLID;
|
||
cvs.pen.style := 0;
|
||
cvs.pen.color := ifo["color"];
|
||
cvs.draw_polygon().points(xys).draw();
|
||
end
|
||
function paint_sunburst(cvs,xys,ifo);//画饼
|
||
begin
|
||
return paint_pie(cvs,xys,ifo);
|
||
end
|
||
function paint_tree(cvs,xys,ifo); //画树
|
||
begin
|
||
//cvs.brush.color := ifo["bkcolor"];
|
||
//cvs.pen.style := 0;
|
||
//cvs.pen.color := ifo["color"];
|
||
//cvs.pen.color := 0x0000ff;
|
||
tree := cvs.draw_bezier();
|
||
//tree.startpoint(xys[0]);
|
||
tree.addpoints(xys);
|
||
//tree.addpoints(array(xys[1]));
|
||
//tree.addpoints(array(xys[2]));
|
||
//tree.addpoints(array(xys[3]));
|
||
tree.draw();
|
||
end
|
||
function mult_str(s,n);
|
||
begin
|
||
r := s;
|
||
for i := 2 to n do //exp
|
||
begin
|
||
r+=s;
|
||
end
|
||
return r;
|
||
end
|
||
function get_default_color_list(); //获取默认的颜色列表
|
||
begin
|
||
//return array(0xc67054, 0x75cc91, 0x58c8fa, 0x6666ee, 0xdec073, 0x72a23b, 0x5284fc, 0xb4609a, 0xcc7cea);
|
||
return array(0x00CED1,0xFA8072,0x00BFFF,0xFFFFE0,0xF0FFFF,0xFDF5E6,0xFAF0E6,0xFF8C00,0xC0C0C0,0x008B8B,0xE6E6FA,0xF5DEB3,0xE9967A,0xFF00FF,0x9400D3,0x00FF00,0xDC143C,0xFF4500,0xD8BFD8,0x6B8E23,0x1E90FF,0x708090,0x00FA9A,0xFAEBD7,0xADD8E6,0x8B4513,0xFFFAFA,0x8A2BE2,0x4169E1,0x000080,0xF0FFF0,0x191970,0xF4A460,0xFFDEAD,0x0000CD,0xF5FFFA,0x8B0000,0xFF7F50,0xBA55D3,0x7CFC00,0xFFE4C4,0xDCDCDC,0x87CEEB,0x696969,0x808080,0xFF1493,0x48D1CC,0xFFF0F5,0x00008B,0xDDA0DD,0xFFA07A,0x4682B4,0xFFDAB9,0x6495ED,0xFFC0CB,0x008000,0xADFF2F,0xBDB76B,0x66CDAA,0xEE82EE,0xFFFF00,0x556B2F,0xFFB6C1,0x20B2AA,0xDB7093,0xFFFAF0,0xB22222,0x6A5ACD,0xFF6347,0x778899,0xFAFAD2,0x800080,0x00FFFF,0x006400,0x8FBC8F,0xFFFFFF,0x40E0D0,0xFFD700,0x00FF7F,0xF8F8FF,0xA0522D,0x87CEFA,0xDEB887,0x000000,0x0000FF,0xD2691E,0xFF00FF,0xF5F5F5,0xFFF5EE,0x98FB98,0xFFF8DC,0xF0F8FF,0x800000,0xBC8F8F,0x8B008B,0xD3D3D3,0x9ACD32,0xA9A9A9,0xFF69B4,0xAFEEEE,0xB8860B,0xD2B48C,0xF5F5DC,0x5F9EA0,0x228B22,0x2F4F4F,0xA52A2A,0x7FFFD4,0x90EE90,0x7B68EE,0xB0C4DE,0xF08080,0x32CD32,0x483D8B,0x9370DB,0xCD5C5C,0xDA70D6,0x808000,0x008080,0xFFE4B5,0xC71585,0x9932CC,0xFFEBCD,0xE0FFFF,0x00FFFF,0x4B0082,0xEEE8AA,0xFFE4E1,0xFFEFD5,0xDAA520,0x2E8B57,0xF0E68C,0x7FFF00,0xB0E0E6,0xFFFFF0,0xFFA500,0xFF0000,0xCD853F,0x3CB371,0xFFFACD);
|
||
end
|
||
initialization
|
||
finalization
|
||
end.
|