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 }