1 module plot2d.chart.tre;
2
3 public import plot2d.chart.base;
4
5 ///
6 class TreChart : BaseChart!TreStat
7 {
8 protected:
9 override void expandViewport(ref const Elem val, ref bool[2] inited)
10 {
11 if (val.tm == val.tm)
12 {
13 if (inited[0])
14 {
15 vp.w.min.set!min(val.tm);
16 vp.w.max.set!max(val.tm);
17 }
18 else
19 {
20 vp.w.min = val.tm;
21 vp.w.max = val.tm;
22 inited[0] = true;
23 }
24 }
25 if (val.min == val.min && val.max == val.max)
26 {
27 if (inited[1])
28 {
29 vp.h.min.set!min(val.min);
30 vp.h.max.set!max(val.max);
31 }
32 else
33 {
34 vp.h.min = val.min;
35 vp.h.max = val.max;
36 inited[1] = true;
37 }
38 }
39 }
40
41 public:
42
43 Color fillUp, fillDown, stroke, strokeLimUp, strokeLimDown;
44
45 bool skipNaN = true;
46 bool verticalCap = true;
47
48 double disaster;
49 double disasterCoef = 3; // must be > 1
50
51 this(Color stroke,
52 Color strokeLimUp, Color fillUp,
53 Color strokeLimDown, Color fillDown,
54 BufferFiller fd)
55 {
56 this.stroke = stroke;
57 this.fillUp = fillUp;
58 this.fillDown = fillDown;
59 this.strokeLimUp = strokeLimUp;
60 this.strokeLimDown = strokeLimDown;
61 super(fd);
62 }
63
64 override
65 {
66 void update()
67 {
68 super.update();
69 if (buffer.data.length == 0) return;
70
71 auto avg_diff = 0.0;
72 foreach (a, b; lockstep(buffer.data[0..$-1], buffer.data[1..$]))
73 avg_diff += b.tm - a.tm;
74 avg_diff /= buffer.data.length;
75 disaster = avg_diff * disasterCoef;
76 }
77
78 void draw(Ctx cr, Trtor tr)
79 {
80 auto limlinewidth = style.number.get("limlinewidth", 1);
81 auto linewidth = style.number.get("linewidth", 2);
82
83 auto buf = buffer.data.filter!(a=>skipNaN?a.check:true);
84
85 if (buf.empty) return;
86
87 cr.clipViewport(tr.inPadding);
88
89 auto lst = buf.front;
90 buf.popFront;
91
92 void vcap(typeof(lst) p)
93 {
94 cr.setLineWidth(limlinewidth);
95 cr.setColor(strokeLimUp);
96 cr.lineP2P(tr.toDA(p.valPnt), tr.toDA(p.maxPnt));
97 cr.stroke();
98
99 cr.setColor(strokeLimDown);
100 cr.lineP2P(tr.toDA(p.valPnt), tr.toDA(p.minPnt));
101 cr.stroke();
102
103 cr.setLineWidth(linewidth);
104 cr.setColor(stroke);
105 cr.lineP2P(tr.toDA(p.valPnt)-Point(1,0),
106 tr.toDA(p.valPnt)+Point(1,0));
107 cr.stroke();
108 }
109
110 foreach (val; buf)
111 {
112 if (verticalCap)
113 {
114 if (!lst.check && val.check) vcap(val);
115 else
116 if (lst.check && !val.check) vcap(lst);
117 }
118
119 if (!skipNaN && !(val.check && lst.check))
120 {
121 lst = val;
122 continue;
123 }
124 //if (val.tm - lst.tm > disaster)
125 //{ lst = val; continue; }
126
127 cr.setColor(fillUp);
128 cr.lineP2P(tr.toDA(lst.maxPnt),
129 tr.toDA(lst.valPnt),
130 tr.toDA(val.maxPnt));
131 cr.fill();
132 cr.lineP2P(tr.toDA(lst.valPnt),
133 tr.toDA(val.maxPnt),
134 tr.toDA(val.valPnt));
135 cr.fill();
136
137 cr.setColor(fillDown);
138 cr.lineP2P(tr.toDA(lst.valPnt),
139 tr.toDA(lst.minPnt),
140 tr.toDA(val.valPnt));
141 cr.fill();
142 cr.lineP2P(tr.toDA(lst.minPnt),
143 tr.toDA(val.valPnt),
144 tr.toDA(val.minPnt));
145 cr.fill();
146
147 cr.setLineWidth(limlinewidth);
148
149 cr.setColor(strokeLimUp);
150 cr.lineP2P(tr.toDA(lst.maxPnt), tr.toDA(val.maxPnt));
151 cr.stroke();
152
153 cr.setColor(strokeLimDown);
154 cr.lineP2P(tr.toDA(lst.minPnt), tr.toDA(val.minPnt));
155 cr.stroke();
156
157 cr.setLineWidth(linewidth);
158 cr.setColor(stroke);
159 cr.lineP2P(tr.toDA(lst.valPnt), tr.toDA(val.valPnt));
160 cr.stroke();
161
162 lst = val;
163 }
164 }
165 }
166 }