1 #ifndef _ScatterDraw_ScatterDraw_h
2 #define _ScatterDraw_ScatterDraw_h
3
4 #include <Draw/Draw.h>
5 #include <Painter/Painter.h>
6 #include "DataSource.h"
7 #include "Equation.h"
8 #include "DrawingFunctions.h"
9 #include "SeriesPlot.h"
10 #include "MarkPlot.h"
11
12 namespace Upp {
13
14 Color GetOpaqueColor(const Color &color, const Color &background, double opacity);
15
16 void debug_h(); // Dummy function used to debug .h files
17
18 class DashStyle {
19 public:
Register(const String & name,const String & style)20 static int Register(const String& name, const String& style) {
21 return map().FindAdd(name, style);
22 return map().FindAdd(name, style);
23 }
Unregister(const String & name)24 static void Unregister(const String& name) {
25 int id = TypeIndex(name);
26 ASSERT(id >= 0);
27 map().Remove(id);
28 }
UnregisterFrom(int id)29 static void UnregisterFrom(int id) {
30 for (int i = GetCount() - 1; i >= id; --i)
31 map().Remove(i);
32 }
TypeName(int i)33 static String TypeName(int i) {return map().GetKey(i);}
Style(int i)34 static String Style(int i) {return map()[i];}
TypeIndex(const String & name)35 static int TypeIndex(const String& name) {return map().Find(name);}
StyleIndex(const String & style)36 static int StyleIndex(const String& style) {
37 for (int i = 0; i < GetCount(); ++i) {
38 if (map()[i] == style)
39 return i;
40 }
41 return -1;
42 }
GetCount()43 static int GetCount() {return map().GetCount();}
44
45 protected:
map()46 static VectorMap<String, String>& map() {static VectorMap<String, String> map; return map;}
47 };
48
49 enum RAINBOW {BLUE_YELLOW_RED, RED_YELLOW_BLUE, GREEN_YELLOW_RED, RED_YELLOW_GREEN,
50 BLUE_WHITE_RED, RED_WHITE_BLUE, WHITE_BLACK, BLACK_WHITE};
51
52 Color GetRainbowColor(double frac, RAINBOW rainbow, int numScales);
53 Color GetRainbowColor(double frac, const Color &from, const Color &to, int numScales);
54 Color GetRainbowColor(double frac, const Color &col0, const Color &col1, const Color &col2, int numScales);
55
56 class ScatterDraw {
57 public:
58 ScatterDraw();
~ScatterDraw()59 virtual ~ScatterDraw() noexcept {}
60
61 enum Formats {
62 EXP,
63 MON,
64 DY,
65 CUSTOM
66 };
67 enum {
68 MD_DRAW = -1,
69 MD_ANTIALIASED = MODE_ANTIALIASED,
70 MD_NOAA = MODE_NOAA,
71 MD_SUBPIXEL = MODE_SUBPIXEL
72 };
73
74 #define LINE_SOLID ""
75 #define LINE_DOTTED_FINER "2 10"
76 #define LINE_DOTTED_FINE "2 6"
77 #define LINE_DOTTED "4 10"
78 #define LINE_DOTTED_SEP "4 20"
79 #define LINE_DASHED "12 12"
80 #define LINE_DASH_DOT "12 8 3 8" // Reduced. Previous was too long
81 #define LINE_BEGIN_END "-"
82
83 protected:
84 class ScatterBasicSeries {
85 public:
86 ScatterBasicSeries();
87 void Init(int index);
88
89 bool primaryY;
90 bool sequential;
91
92 One<SeriesPlot> seriesPlot;
93 double thickness;
94 Color color;
95 String dash;
96
97 One<MarkPlot> markPlot;
98 double markWidth;
99 Color markColor;
100 double markBorderWidth;
101 Color markBorderColor;
102
103 Color fillColor;
104
105 String legend;
106 String unitsX, unitsY;
107
108 double opacity;
109
110 double barWidth;
111 bool isClosed;
112
113 Vector<String> *labels;
114 Font labelsFont;
115 Color labelsColor;
116 int labelsDx, labelsDy;
117 Alignment labelsAlign;
118
119 bool showLegend;
120 bool legendLine; // show line in legend even if series is NoPlot
121
122 int id;
123
124 private:
125 template <class T>
Ize(T & io)126 void Ize(T& io) {
127 int seriesP = Null;
128 int markP = Null;
129 if (io.IsStoring()) {
130 if (markPlot)
131 markP = markPlot->GetType();
132 if (seriesPlot)
133 seriesP = seriesPlot->GetType();
134 }
135 io
136 ("primaryY", primaryY)
137 ("sequential", sequential)
138 ("thickness", thickness)
139 ("color", color)
140 ("dash", dash)
141 ("markWidth", markWidth)
142 ("markColor", markColor)
143 ("markBorderWidth", markBorderWidth)
144 ("markBorderColor", markBorderColor)
145 ("fillColor", fillColor)
146 ("markBorderColor", markBorderColor)
147 ("legend", legend)
148 ("unitsX", unitsX)
149 ("unitsY", unitsY)
150 ("opacity", opacity)
151 ("id", id)
152 ("seriesP", seriesP)
153 ("markPlot", markP)
154 ("seriesPlot", seriesP)
155 ("barWidth", barWidth)
156 ("isClosed", isClosed)
157 ("showLegend", showLegend)
158 ("legendLine", legendLine)
159 ;
160 if (io.IsLoading()) {
161 if (!IsNull(markP))
162 markPlot = MarkPlot::Create(markP);
163 else
164 markPlot = 0;
165 if (!IsNull(seriesP))
166 seriesPlot = SeriesPlot::Create(seriesP);
167 else
168 seriesPlot = 0;
169 }
170 }
171
172 public:
Xmlize(XmlIO & xml)173 void Xmlize(XmlIO& xml) {Ize(xml);}
Jsonize(JsonIO & json)174 void Jsonize(JsonIO& json) {Ize(json);}
175
Serialize(Stream & s)176 void Serialize(Stream& s) {
177 int seriesP = Null;
178 int markP = Null;
179 if (s.IsStoring()) {
180 if (markPlot)
181 markP = markPlot->GetType();
182 if (seriesPlot)
183 seriesP = seriesPlot->GetType();
184 }
185 s % primaryY
186 % sequential
187 % thickness
188 % color
189 % dash
190 % markWidth
191 % markColor
192 % markBorderWidth
193 % markBorderColor
194 % fillColor
195 % markBorderColor
196 % legend
197 % unitsX
198 % unitsY
199 % opacity
200 % id
201 % seriesP
202 % markP
203 % seriesP
204 % barWidth
205 % isClosed
206 % showLegend
207 % legendLine
208 ;
209 if (s.IsLoading()) {
210 if (!IsNull(markP))
211 markPlot = MarkPlot::Create(markP);
212 else
213 markPlot = 0;
214 if (!IsNull(seriesP))
215 seriesPlot = SeriesPlot::Create(seriesP);
216 else
217 seriesPlot = 0;
218 }
219 }
220 };
221
222 class ScatterSeries : public Moveable<ScatterSeries>, public ScatterBasicSeries {
223 public:
ScatterSeries()224 ScatterSeries() : owns(false), serializeData(false) {dataS.Init(&data);}
225 void SetDataSource(DataSource *pointsData, bool ownsData = true) {
226 DeletePD();
227 pD = pointsData;
228 owns = ownsData;
229 }
SetDataSourceInternal()230 void SetDataSourceInternal() {
231 CopyInternal();
232 DeletePD();
233 pD = &dataS;
234 serializeData = true;
235 owns = false;
236 }
Data()237 DataSource &Data() {return *(~pD);}
Data()238 const DataSource &Data() const {return *(~pD);}
IsDeleted()239 bool IsDeleted() const {
240 if (~pD == nullptr)
241 return true;
242 bool ismagic = (~pD)->IsMagic();
243 ASSERT(ismagic);
244 return !ismagic;
245 }
~ScatterSeries()246 virtual ~ScatterSeries() noexcept {DeletePD();}
247 void SerializeData(bool ser = true) {serializeData = ser;}
248 void SerializeFormat(bool ser = false) {serializeFormat = ser;}
Xmlize(XmlIO & xio)249 void Xmlize(XmlIO& xio) {XmlizeByJsonize(xio, *this);}
Jsonize(JsonIO & json)250 void Jsonize(JsonIO& json) {
251 ScatterBasicSeries::Jsonize(json);
252 if (json.IsStoring() && pD)
253 CopyInternal();
254 json("data", data);
255 if (json.IsLoading()) {
256 if (!data.IsEmpty()) {
257 pD = &dataS;
258 serializeData = true;
259 }
260 }
261 }
Serialize(Stream & s)262 void Serialize(Stream& s) {
263 ScatterBasicSeries::Serialize(s);
264 if (s.IsStoring() && pD)
265 CopyInternal();
266 s % data;
267 if (s.IsLoading()) {
268 if (!data.IsEmpty()) {
269 pD = &dataS;
270 serializeData = true;
271 }
272 }
273 }
274
275 private:
276 Ptr<DataSource> pD;
277 bool owns;
278 Vector<Pointf> data;
279 VectorPointf dataS;
280 bool serializeData, serializeFormat;
281
CopyInternal()282 void CopyInternal() {
283 int64 sz = pD->GetCount();
284 if (IsNull(sz) || sz == 0)
285 return;
286 data.SetCount(int(sz));
287 for (int64 i = 0; i < sz; ++i) {
288 data[int(i)].x = pD->x(i);
289 data[int(i)].y = pD->y(i);
290 }
291 }
DeletePD()292 void DeletePD() {
293 if(pD && owns) {
294 delete pD;
295 pD = 0;
296 }
297 }
298 };
299
300 static Color GetNewColor(int index, int version = 1);
301 static String GetNewDash(int index);
302 static MarkPlot *GetNewMarkPlot(int index);
303
WhenPaint(Painter & w)304 void WhenPaint(Painter &w) {WhenPainter(w);}
WhenPaint(Draw & w)305 void WhenPaint(Draw &w) {WhenDraw(w);}
306
307 public:
308 template<class T>
309 void SetDrawing(T& w, bool ctrl = false);
310
311 Function<void(String&, int, double)> cbModifFormatX;
312 Function<void(String&, int, double)> cbModifFormatXGridUnits;
313 Function<void(String&, int, double)> cbModifFormatDeltaX;
314 Function<void(String&, int, double)> cbModifFormatY;
315 Function<void(String&, int, double)> cbModifFormatYGridUnits;
316 Function<void(String&, int, double)> cbModifFormatDeltaY;
317 Function<void(String&, int, double)> cbModifFormatY2;
318 Function<void(String&, int, double)> cbModifFormatY2GridUnits;
319 Function<void(String&, int, double)> cbModifFormatDeltaY2;
320
321 Function<void(Vector<double>&)> SetGridLinesX;
322 Function<void(Vector<double>&)> SetGridLinesY;
323
324 Function<void()> WhenZoomScroll;
325 Function<void()> WhenSetRange;
326 Function<void()> WhenSetXYMin;
327 Function<void(Painter&)> WhenPainter;
328 Function<void(Draw&)> WhenDraw;
329 Function<void()> WhenZoomToFit;
330
331 Function <bool(int)> WhenRemoveSeries;
332 Function <bool(int, int)> WhenSwapSeries;
333
SetSize(const Size & sz)334 ScatterDraw& SetSize(const Size &sz) {
335 size = sz;
336 plotScaleX = responsive ? responsivenessFactor*size.cx/600. : 1;
337 plotScaleY = responsive ? responsivenessFactor*size.cy/400. : 1;
338 plotScaleAvg = responsive ? (plotScaleX + plotScaleY)/2. : 1;
339 return *this;
340 };
GetSize()341 Size GetSize() const {return size;};
342 ScatterDraw& Responsive(bool _responsive = true, double factor = 1) {
343 this->responsive = _responsive;
344 responsivenessFactor = factor;
345 plotScaleX = _responsive ? responsivenessFactor*size.cx/600. : 1;
346 plotScaleY = _responsive ? responsivenessFactor*size.cy/400. : 1;
347 plotScaleAvg = _responsive ? (plotScaleX + plotScaleY)/2. : 1;
348 return *this;
349 }
IsResponsive()350 bool IsResponsive() {return responsive;}
GetResponsivenessFactor()351 double GetResponsivenessFactor() {return responsivenessFactor;}
GetPlotScaleX()352 double GetPlotScaleX() {return plotScaleX;}
GetPlotScaleY()353 double GetPlotScaleY() {return plotScaleY;}
GetPlotScaleAvg()354 double GetPlotScaleAvg(){return plotScaleAvg;}
355
356 ScatterDraw& SetColor(const Color& _color);
357 ScatterDraw& SetTitle(const String& _title);
358 const String& GetTitle();
359 ScatterDraw& SetTitleFont(const Upp::Font& fontTitle);
GetTitleFont()360 Upp::Font& GetTitleFont() {return titleFont;};
361 ScatterDraw& SetTitleColor(const Color& colorTitle);
GetTitleColor()362 Upp::Color& GetTitleColor() {return titleColor;};
363
364 ScatterDraw& SetLabels(const String& _xLabel, const String& _yLabel, const String& _yLabel2 = "");
365 ScatterDraw& SetLabelX(const String& _xLabel);
GetLabelX()366 const String &GetLabelX() {return xLabel_base;}
367 ScatterDraw& SetLabelY(const String& _yLabel);
GetLabelY()368 const String &GetLabelY() {return yLabel_base;}
369 ScatterDraw& SetLabelY2(const String& _yLabel);
GetLabelY2()370 const String &GetLabelY2() {return yLabel2_base;}
371 ScatterDraw& SetLabelsFont(const Upp::Font& fontLabels);
GetLabelsFont()372 Upp::Font GetLabelsFont() {return labelsFont;};
373 ScatterDraw& SetLabelsColor(const Color& colorLabels);
GetLabelsColor()374 Upp::Color GetLabelsColor() {return labelsColor;};
375
376 ScatterDraw& SetPlotAreaMargin(int hLeft, int hRight, int vTop, int vBottom);
377 ScatterDraw& SetPlotAreaLeftMargin(int margin);
GetPlotAreaLeftMargin()378 int GetPlotAreaLeftMargin() {return hPlotLeft;}
379 ScatterDraw& SetPlotAreaRightMargin(int margin);
GetPlotAreaRightMargin()380 int GetPlotAreaRightMargin() {return hPlotRight;}
381 ScatterDraw& SetPlotAreaTopMargin(int margin);
GetPlotAreaTopMargin()382 int GetPlotAreaTopMargin() {return vPlotTop;}
383 ScatterDraw& SetPlotAreaBottomMargin(int margin);
GetPlotAreaBottomMargin()384 int GetPlotAreaBottomMargin() {return vPlotBottom;}
385
386 ScatterDraw& SetPlotAreaColor(const Color& p_a_color);
GetPlotAreaColor()387 Color& GetPlotAreaColor() {return plotAreaColor;}
388
389 ScatterDraw& SetAxisColor(const Color& axis_color);
390 ScatterDraw& SetAxisWidth(double axis_width);
GetAxisWidth()391 double GetAxisWidth() {return axisWidth;}
392
SetGridColor(const Color & grid_color)393 ScatterDraw& SetGridColor(const Color& grid_color){gridColor = grid_color; return *this;}
GetGridColor()394 Color &GetGridColor() {return gridColor;}
SetGridWidth(double grid_width)395 ScatterDraw& SetGridWidth(double grid_width) {gridWidth = grid_width; return *this;}
GetGridWidth()396 double GetGridWidth() {return gridWidth;}
SetGridDash(const char * dash)397 ScatterDraw& SetGridDash(const char *dash) {gridDash = dash; return *this;}
GetGridDash()398 const char *GetGridDash() {return gridDash;}
399
400 ScatterDraw& ShowVGrid(bool show);
401 ScatterDraw& ShowHGrid(bool show);
402
403 ScatterDraw& ShowLegend(bool show = true) {showLegend = show; return *this;}
GetShowLegend()404 bool GetShowLegend() {return showLegend;}
SetLegendPos(const Point & pos)405 ScatterDraw& SetLegendPos(const Point &pos) {legendPos = pos; return *this;}
SetLegendPosX(int x)406 ScatterDraw& SetLegendPosX(int x) {legendPos.x = x; return *this;}
SetLegendPosY(int y)407 ScatterDraw& SetLegendPosY(int y) {legendPos.y = y; return *this;}
GetLegendPos()408 Point& GetLegendPos() {return legendPos;}
SetLegendFont(const Font & fnt)409 ScatterDraw& SetLegendFont(const Font &fnt) {legendFont = fnt; return *this;}
GetLegendFont()410 Font &GetLegendFont() {return legendFont;}
SetLegendNumCols(int num)411 ScatterDraw& SetLegendNumCols(int num) {legendNumCols = num; return *this;}
GetLegendNumCols()412 int GetLegendNumCols() {return legendNumCols;}
SetLegendRowSpacing(int num)413 ScatterDraw& SetLegendRowSpacing(int num) {legendRowSpacing = num;return *this;}
GetLegendRowSpacing()414 int GetLegendRowSpacing() {return legendRowSpacing;}
415 enum LEGEND_POS {
416 TOP,
417 LEFT_TOP,
418 RIGHT_TOP,
419 LEFT_BOTTOM,
420 RIGHT_BOTTOM
421 };
SetLegendAnchor(LEGEND_POS anchor)422 ScatterDraw& SetLegendAnchor(LEGEND_POS anchor) {legendAnchor = anchor; return *this;}
GetLegendAnchor()423 LEGEND_POS GetLegendAnchor() {return legendAnchor;}
SetLegendFillColor(const Color & color)424 ScatterDraw& SetLegendFillColor(const Color &color) {legendFillColor = color; return *this;}
SetLegendBorderColor(const Color & color)425 ScatterDraw& SetLegendBorderColor(const Color &color) {legendBorderColor = color; return *this;}
GetLegendFillColor()426 Color& GetLegendFillColor() {return legendFillColor;}
GetLegendBorderColor()427 Color& GetLegendBorderColor() {return legendBorderColor;}
428
429 ScatterDraw& SetMode(int _mode = MD_ANTIALIASED) {this->mode = _mode; Refresh(); return *this;};
GetMode()430 int GetMode() {return mode;};
431
432 ScatterDraw &ZoomToFit(bool horizontal = true, bool vertical = false, double factor = 0);
433 //ScatterDraw &ZoomToFit(bool horizontal, double minx, double maxx, bool vertical, double minxy, double maxy,
434 // bool vertical2, double miny2, double maxy2, double factor);
435 //ScatterDraw &ZoomToFitSmart(bool horizontal, double minx, double maxx, bool vertical, double minxy, double maxy,
436 // bool vertical2, double miny2, double maxy2, double factor);
437 void Zoom(double scale, bool hor = true, bool ver = true);
438 void Scroll(double factorX, double factorY);
439
440 enum ZoomStyle {TO_CENTER, FROM_BASE};
441 ScatterDraw &SetZoomStyleX(ZoomStyle style = TO_CENTER) {zoomStyleX = style; return *this;}
442 ScatterDraw &SetZoomStyleY(ZoomStyle style = TO_CENTER) {zoomStyleY = style; return *this;}
443
444 ScatterDraw& SetRange(double rx, double ry = Null, double ry2 = Null);
445 ScatterDraw& SetRangeLinked(double rx, double ry, double ry2 = 100);
GetXRange()446 double GetXRange()const {return xRange;}
GetYRange()447 double GetYRange()const {return yRange;}
GetY2Range()448 double GetY2Range()const {return yRange2;}
449 ScatterDraw &SetMajorUnits(double ux, double uy = Null);
450 ScatterDraw &SetMajorUnitsNum(int nx, int ny = Null);
GetMajorUnitsX()451 double GetMajorUnitsX() {return xMajorUnit;}
GetMajorUnitsY()452 double GetMajorUnitsY() {return yMajorUnit;}
GetMajorUnitsY2()453 double GetMajorUnitsY2() {return yMajorUnit2;}
454 ScatterDraw& SetMinUnits(double ux, double uy = Null);
GetXMinUnit()455 double GetXMinUnit() const {return xMinUnit;}
GetYMinUnit()456 double GetYMinUnit() const {return yMinUnit;}
GetYMinUnit2()457 double GetYMinUnit2() const {return yMinUnit2;}
458
459 ScatterDraw& SetXYMin(double xmin, double ymin = Null, double ymin2 = Null);
460 ScatterDraw& SetXYMinLinked(double xmin, double ymin = Null, double ymin2 = Null);
GetXMin()461 double GetXMin() const {return xMin;}
GetYMin()462 double GetYMin() const {return yMin;}
GetYMin2()463 double GetYMin2() const {return yMin2;}
GetY2Min()464 double GetY2Min() const {return yMin2;}
GetXMax()465 double GetXMax() const {return xMin + xRange;}
GetYMax()466 double GetYMax() const {return yMin + yRange;}
GetY2Max()467 double GetY2Max() const {return yMin2 + yRange2;}
468
469 ScatterDraw &Graduation_FormatX(Formats fi);
470 ScatterDraw &Graduation_FormatY(Formats fi);
471 ScatterDraw &Graduation_FormatY2(Formats fi);
472
473 //ScatterDraw &SetPolar(bool polar = true) {isPolar = polar; return *this;};
474
AddSeries(double * yData,int numData,double x0,double deltaX)475 ScatterDraw &AddSeries(double *yData, int numData, double x0, double deltaX)
476 {return AddSeries<CArray>(yData, numData, x0, deltaX);}
AddSeries(double * xData,double * yData,int numData)477 ScatterDraw &AddSeries(double *xData, double *yData, int numData)
478 {return AddSeries<CArray>(yData, xData, numData);}
AddSeries(Eigen::VectorXd & yData,double x0,double deltaX)479 ScatterDraw &AddSeries(Eigen::VectorXd &yData, double x0, double deltaX)
480 {return AddSeries<EigenVector>(yData, x0, deltaX);}
AddSeries(Eigen::VectorXd & xData,Eigen::VectorXd & yData)481 ScatterDraw &AddSeries(Eigen::VectorXd &xData, Eigen::VectorXd &yData)
482 {return AddSeries<EigenVector>(xData, yData);}
AddSeries(Vector<double> & xData,Vector<double> & yData)483 ScatterDraw &AddSeries(Vector<double> &xData, Vector<double> &yData)
484 {return AddSeries<VectorXY>(xData, yData);}
AddSeries(Upp::Array<double> & xData,Upp::Array<double> & yData)485 ScatterDraw &AddSeries(Upp::Array<double> &xData, Upp::Array<double> &yData)
486 {return AddSeries<ArrayXY>(xData, yData);}
AddSeries(Vector<Pointf> & points)487 ScatterDraw &AddSeries(Vector<Pointf> &points) {return AddSeries<VectorPointf>(points);}
AddSeries(Upp::Array<Pointf> & points)488 ScatterDraw &AddSeries(Upp::Array<Pointf> &points) {return AddSeries<ArrayPointf>(points);}
489 template <class Y>
490 ScatterDraw &AddSeries(Vector<Vector <Y> > &data, int idx, int idy,
491 Vector<int> &idsx, Vector<int> &idsy, Vector<int> &idsFixed, bool useCols = true, int beginData = 0, int numData = Null) {
492 return AddSeries<VectorVectorY<Y> >(data, idx, idy, idsx, idsy, idsFixed, useCols, beginData, numData);
493 }
AddSeries(Function<double (double)> function)494 ScatterDraw &AddSeries(Function <double(double)> function) {return AddSeries<FuncSource>(function);}
AddSeries(double (* function)(double))495 ScatterDraw &AddSeries(double (*function)(double)) {return AddSeries<FuncSource>(function);}
AddSeries(void (* function)(double &,double))496 ScatterDraw &AddSeries(void (*function)(double&, double))
497 {return AddSeries<FuncSourceV>(function);}
498 ScatterDraw &AddSeries(Pointf (*function)(double), int np, double from = 0, double to = 1)
499 {return AddSeries<FuncSourcePara>(function, np, from, to);}
AddSeries(PlotExplicFunc function)500 ScatterDraw &AddSeries(PlotExplicFunc function) {return AddSeries<PlotExplicFuncSource>(function);}
501 ScatterDraw &AddSeries(PlotParamFunc function, int np, double from = 0, double to = 1)
502 {return AddSeries<PlotParamFuncSource>(function, np, from, to);}
503
504 ScatterDraw &AddSeries(DataSource &data);
505
506 template <class C>
AddSeries()507 ScatterDraw &AddSeries() {return _AddSeries(new C());}
508 template <class C, class T1>
AddSeries(T1 & arg1)509 ScatterDraw &AddSeries(T1 &arg1)
510 {return _AddSeries(new C(arg1));}
511 template <class C, class T1, class T2>
AddSeries(T1 & arg1,T2 & arg2)512 ScatterDraw &AddSeries(T1 &arg1, T2 &arg2)
513 {return _AddSeries(new C(arg1, arg2));}
514 template <class C, class T1, class T2, class T3>
AddSeries(T1 & arg1,T2 & arg2,T3 & arg3)515 ScatterDraw &AddSeries(T1 &arg1, T2 &arg2, T3 &arg3)
516 {return _AddSeries(new C(arg1, arg2, arg3));}
517 template <class C, class T1, class T2, class T3, class T4>
AddSeries(T1 & arg1,T2 & arg2,T3 & arg3,T4 & arg4)518 ScatterDraw &AddSeries(T1 &arg1, T2 &arg2, T3 &arg3, T4 &arg4)
519 {return _AddSeries(new C(arg1, arg2, arg3, arg4));}
520 template <class C, class T1, class T2, class T3, class T4, class T5>
AddSeries(T1 & arg1,T2 & arg2,T3 & arg3,T4 & arg4,T5 & arg5)521 ScatterDraw &AddSeries(T1 &arg1, T2 &arg2, T3 &arg3, T4 &arg4, T5 &arg5)
522 {return _AddSeries(new C(arg1, arg2, arg3, arg4, arg5));}
523 template <class C, class T1, class T2, class T3, class T4, class T5, class T6>
AddSeries(T1 & arg1,T2 & arg2,T3 & arg3,T4 & arg4,T5 & arg5,T6 & arg6)524 ScatterDraw &AddSeries(T1 &arg1, T2 &arg2, T3 &arg3, T4 &arg4, T5 &arg5, T6 &arg6)
525 {return _AddSeries(new C(arg1, arg2, arg3, arg4, arg5, arg6));}
526 template <class C, class T1, class T2, class T3, class T4, class T5, class T6, class T7>
AddSeries(T1 & arg1,T2 & arg2,T3 & arg3,T4 & arg4,T5 & arg5,T6 & arg6,T7 & arg7)527 ScatterDraw &AddSeries(T1 &arg1, T2 &arg2, T3 &arg3, T4 &arg4, T5 &arg5, T6 &arg6, T7 &arg7)
528 {return _AddSeries(new C(arg1, arg2, arg3, arg4, arg5, arg6, arg7));}
529 template <class C, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8>
AddSeries(T1 & arg1,T2 & arg2,T3 & arg3,T4 & arg4,T5 & arg5,T6 & arg6,T7 & arg7,T8 & arg8)530 ScatterDraw &AddSeries(T1 &arg1, T2 &arg2, T3 &arg3, T4 &arg4, T5 &arg5, T6 &arg6, T7 &arg7, T8 &arg8)
531 {return _AddSeries(new C(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8));}
532 template <class C, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9>
AddSeries(T1 & arg1,T2 & arg2,T3 & arg3,T4 & arg4,T5 & arg5,T6 & arg6,T7 & arg7,T8 & arg8,T9 & arg9)533 ScatterDraw &AddSeries(T1 &arg1, T2 &arg2, T3 &arg3, T4 &arg4, T5 &arg5, T6 &arg6, T7 &arg7, T8 &arg8, T9 &arg9)
534 {return _AddSeries(new C(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9));}
535
536 template <class Y>
AddSeries(Vector<Y> & yData,double x0,double deltaX)537 ScatterDraw &AddSeries(Vector<Y> &yData, double x0, double deltaX) {return _AddSeries(new VectorY<Y>(yData, x0, deltaX));}
538 template <class Y>
AddSeries(Upp::Array<Y> & yData,double x0,double deltaX)539 ScatterDraw &AddSeries(Upp::Array<Y> &yData, double x0, double deltaX) {return _AddSeries(new ArrayY<Y>(yData, x0, deltaX));}
540 template <class X, class Y>
AddSeries(VectorMap<X,Y> & data)541 ScatterDraw &AddSeries(VectorMap<X, Y> &data) {return _AddSeries(new VectorMapXY<X, Y>(data));}
542 template <class X, class Y>
AddSeries(ArrayMap<X,Y> & data)543 ScatterDraw &AddSeries(ArrayMap<X, Y> &data) {return _AddSeries(new ArrayMapXY<X, Y>(data));}
544
GetDataSource(int index)545 DataSource &GetDataSource(int index) {ASSERT(IsValid(index));ASSERT(!series[index].IsDeleted()); return series[index].Data();}
IsDeletedDataSource(int index)546 bool IsDeletedDataSource(int index) {return series[index].IsDeleted();}
547
548 ScatterDraw &InsertSeries(int index, double *yData, int numData, double x0 = 0, double deltaX = 1);
549 ScatterDraw &InsertSeries(int index, double *xData, double *yData, int numData);
550 ScatterDraw &InsertSeries(int index, Vector<double> &xData, Vector<double> &yData);
551 ScatterDraw &InsertSeries(int index, Upp::Array<double> &xData, Upp::Array<double> &yData);
552 ScatterDraw &InsertSeries(int index, Vector<Pointf> &points);
553 ScatterDraw &InsertSeries(int index, Upp::Array<Pointf> &points);
554 ScatterDraw &InsertSeries(int index, double (*function)(double));
555 ScatterDraw &InsertSeries(int index, Pointf (*function)(double), int np, double from = 0, double to = 1);
556 ScatterDraw &InsertSeries(int index, PlotExplicFunc &function);
557 ScatterDraw &InsertSeries(int index, PlotParamFunc function, int np, double from = 0, double to = 1);
558 ScatterDraw &_InsertSeries(int index, DataSource *data);
559
560 template <class C>
InsertSeries(int index)561 ScatterDraw &InsertSeries(int index) {return _InsertSeries(index, new C());}
562 template <class C, class T1>
InsertSeries(int index,T1 & arg1)563 ScatterDraw &InsertSeries(int index, T1 &arg1)
564 {return _InsertSeries(index, new C(arg1));}
565 template <class C, class T1, class T2>
InsertSeries(int index,T1 & arg1,T2 & arg2)566 ScatterDraw &InsertSeries(int index, T1 &arg1, T2 &arg2)
567 {return _InsertSeries(index, new C(arg1, arg2));}
568 template <class C, class T1, class T2, class T3>
InsertSeries(int index,T1 & arg1,T2 & arg2,T3 & arg3)569 ScatterDraw &InsertSeries(int index, T1 &arg1, T2 &arg2, T3 &arg3)
570 {return _InsertSeries(index, new C(arg1, arg2, arg3));}
571 template <class C, class T1, class T2, class T3, class T4>
InsertSeries(int index,T1 & arg1,T2 & arg2,T3 & arg3,T4 & arg4)572 ScatterDraw &InsertSeries(int index, T1 &arg1, T2 &arg2, T3 &arg3, T4 &arg4)
573 {return _InsertSeries(index, new C(arg1, arg2, arg3, arg4));}
574 template <class C, class T1, class T2, class T3, class T4, class T5>
InsertSeries(int index,T1 & arg1,T2 & arg2,T3 & arg3,T4 & arg4,T5 & arg5)575 ScatterDraw &InsertSeries(int index, T1 &arg1, T2 &arg2, T3 &arg3, T4 &arg4, T5 &arg5)
576 {return _InsertSeries(index, new C(arg1, arg2, arg3, arg4, arg5));}
577 template <class C, class T1, class T2, class T3, class T4, class T5, class T6>
InsertSeries(int index,T1 & arg1,T2 & arg2,T3 & arg3,T4 & arg4,T5 & arg5,T6 & arg6)578 ScatterDraw &InsertSeries(int index, T1 &arg1, T2 &arg2, T3 &arg3, T4 &arg4, T5 &arg5, T6 &arg6)
579 {return _InsertSeries(index, new C(arg1, arg2, arg3, arg4, arg5, arg6));}
580
581 template <class Y>
InsertSeries(int index,Vector<Y> & yData,double x0,double deltaX)582 ScatterDraw &InsertSeries(int index, Vector<Y> &yData, double x0, double deltaX) {return _InsertSeries(index, new VectorY<Y>(yData, x0, deltaX));}
583 template <class Y>
InsertSeries(int index,Upp::Array<Y> & yData,double x0,double deltaX)584 ScatterDraw &InsertSeries(int index, Upp::Array<Y> &yData, double x0, double deltaX) {return _InsertSeries(index, new ArrayY<Y>(yData, x0, deltaX));}
585 template <class X, class Y>
InsertSeries(int index,VectorMap<X,Y> & data)586 ScatterDraw &InsertSeries(int index, VectorMap<X, Y> &data) {return _InsertSeries(index, new VectorMapXY<X, Y>(data));}
587 template <class X, class Y>
InsertSeries(int index,ArrayMap<X,Y> & data)588 ScatterDraw &InsertSeries(int index, ArrayMap<X, Y> &data) {return _InsertSeries(index, new ArrayMapXY<X, Y>(data));}
589
590 int64 GetCount(int index);
591 void GetValues(int index, int64 idata, double &x, double &y);
592 double GetValueX(int index, int64 idata);
593 Value GetStringX(int index, int64 idata);
594 double GetValueY(int index, int64 idata);
595 Value GetStringY(int index, int64 idata);
596
597 ScatterDraw &SetNoPlot(int index);
598
PlotStyle()599 ScatterDraw &PlotStyle() {return PlotStyle(0);};
600 template <class C>
PlotStyle()601 ScatterDraw &PlotStyle() {return PlotStyle(new C());}
602 template <class C, class T1>
PlotStyle(T1 arg1)603 ScatterDraw &PlotStyle(T1 arg1) {return PlotStyle(new C(arg1));}
604 template <class C, class T1, class T2>
PlotStyle(T1 arg1,T2 arg2)605 ScatterDraw &PlotStyle(T1 arg1, T2 arg2) {return PlotStyle(new C(arg1, arg2));}
606 template <class C, class T1, class T2, class T3>
PlotStyle(T1 arg1,T2 arg2,T3 arg3)607 ScatterDraw &PlotStyle(T1 arg1, T2 arg2, T3 arg3) {return PlotStyle(new C(arg1, arg2, arg3));}
608
609 ScatterDraw &PlotStyle(int index, SeriesPlot *data);
PlotStyle(SeriesPlot * data)610 ScatterDraw &PlotStyle(SeriesPlot *data) {return PlotStyle(series.GetCount() - 1, data);}
611 ScatterDraw &PlotStyle(int index, const String name);
PlotStyle(const String name)612 ScatterDraw &PlotStyle(const String name) {return PlotStyle(series.GetCount() - 1, name);}
613 const String GetPlotStyleName(int index);
614
NoPlot()615 ScatterDraw &NoPlot() {return PlotStyle();};
616
617 ScatterDraw &Stacked(bool _stacked = true) {stacked = _stacked; return *this;}
618
MarkStyle()619 ScatterDraw &MarkStyle() {return MarkStyle(0);}
620 template <class C>
MarkStyle()621 ScatterDraw &MarkStyle() {return MarkStyle(new C());}
622 template <class C, class T1>
MarkStyle(T1 arg1)623 ScatterDraw &MarkStyle(T1 arg1) {return MarkStyle(new C(arg1));}
624 template <class C, class T1, class T2>
MarkStyle(T1 arg1,T2 arg2)625 ScatterDraw &MarkStyle(T1 arg1, T2 arg2) {return MarkStyle(new C(arg1, arg2));}
626 template <class C, class T1, class T2, class T3>
MarkStyle(T1 arg1,T2 arg2,T3 arg3)627 ScatterDraw &MarkStyle(T1 arg1, T2 arg2, T3 arg3) {return MarkStyle(new C(arg1, arg2, arg3));}
628
629 ScatterDraw &MarkStyle(int index, MarkPlot *data);
MarkStyle(MarkPlot * data)630 ScatterDraw &MarkStyle(MarkPlot *data) {return MarkStyle(series.GetCount() - 1, data);}
631 ScatterDraw &MarkStyle(int index, const String name);
632 ScatterDraw &MarkStyle(int index, int typeidx);
MarkStyle(const String name)633 ScatterDraw &MarkStyle(const String name) {return MarkStyle(series.GetCount() - 1, name);}
634 const String GetMarkStyleName(int index);
635 ScatterDraw &SetMarkStyleType(int index, int type);
SetMarkStyleType(int type)636 ScatterDraw &SetMarkStyleType(int type) {return SetMarkStyleType(series.GetCount() - 1, type);}
637 int GetMarkStyleType(int index);
638
NoMark()639 ScatterDraw &NoMark() {return MarkStyle();};
640
641 ScatterDraw &Stroke(int index, double thickness, Color color);
642 ScatterDraw &Stroke(double thickness, Color color = Null) {return Stroke(series.GetCount() - 1, thickness, color);}
643 ScatterDraw &SetLineColor(int index, Color color);
644 void GetStroke(int index, double &thickness, Color &color);
645 ScatterDraw &Closed(int index, bool closed);
Closed(bool closed)646 ScatterDraw &Closed(bool closed) {return Closed(series.GetCount() - 1, closed);}
647 bool IsClosed(int index);
648 ScatterDraw &BarWidth(int index, double width);
BarWidth(double width)649 ScatterDraw &BarWidth(double width) {return BarWidth(series.GetCount() - 1, width);}
650 double GetBarWidth(int index);
651 ScatterDraw &Dash(const char *dash);
652 ScatterDraw &Dash(int index, const char *dash);
653 ScatterDraw &NoDash();
654 ScatterDraw &NoDash(int index);
655 const String GetDash(int index);
656 ScatterDraw &Fill(Color color = Null);
657 ScatterDraw &MarkColor(Color color = Null);
658 ScatterDraw &MarkBorderColor(Color color = Null);
659 ScatterDraw &MarkWidth(double markWidth = 8);
660 ScatterDraw &MarkBorderWidth(double markWidth = 1);
Hide()661 ScatterDraw &Hide() {series[series.GetCount() - 1].opacity = 0; return *this;}
662
663 ScatterDraw &ShowSeriesLegend(int index, bool show = false);
664 ScatterDraw &ShowSeriesLegend(bool show = false) {return ShowSeriesLegend(series.GetCount() - 1, show);}
GetShowSeriesLegend(int index)665 bool GetShowSeriesLegend(int index) {ASSERT(IsValid(index));ASSERT(!series[index].IsDeleted());return series[index].showLegend;}
NoSeriesLegend(int index)666 ScatterDraw &NoSeriesLegend(int index) {return ShowSeriesLegend(index, false);}
NoSeriesLegend()667 ScatterDraw &NoSeriesLegend() {return ShowSeriesLegend(false);}
668
669 ScatterDraw &Opacity(double opacity = 1) {series[series.GetCount() - 1].opacity = opacity; return *this;}
670 ScatterDraw &Legend(const String legend);
671 ScatterDraw &Legend(int index, const String legend);
672 const String &GetLegend(int index);
673 ScatterDraw &Units(const String unitsY, const String unitsX = "");
674 ScatterDraw &Units(int index, const String unitsY, const String unitsX = "");
675 const String GetUnitsX(int index);
676 const String GetUnitsY(int index);
677
678 ScatterDraw &LegendLine(bool b = true) { series.Top().legendLine = b; return *this; }
679
IsValid(int index)680 inline bool IsValid(int index) const {return (index >= 0 && index < series.GetCount());}
681
682 ScatterDraw &SetDrawXReticle(bool set = true) {drawXReticle = set; return *this;}
683 ScatterDraw &SetDrawYReticle(bool set = true) {drawYReticle = set; return *this;}
684 ScatterDraw &SetDrawY2Reticle(bool set = true) {drawY2Reticle = set; return *this;}
GetDrawXReticle()685 bool GetDrawXReticle() {return drawXReticle;}
GetDrawYReticle()686 bool GetDrawYReticle() {return drawYReticle;}
GetDrawY2Reticle()687 bool GetDrawY2Reticle() {return drawY2Reticle;}
688 ScatterDraw &SetDrawXReticleNumbers(bool set = true) {drawXReticleNumbers = set; return *this;}
689 ScatterDraw &SetDrawYReticleNumbers(bool set = true) {drawYReticleNumbers = set; return *this;}
690 ScatterDraw &SetDrawY2ReticleNumbers(bool set = true){drawY2ReticleNumbers = set; return *this;}
GetDrawXReticleNumbers()691 bool GetDrawXReticleNumbers() {return drawXReticleNumbers;}
GetDrawYReticleNumbers()692 bool GetDrawYReticleNumbers() {return drawYReticleNumbers;}
GetDrawY2ReticleNumbers()693 bool GetDrawY2ReticleNumbers() {return drawY2ReticleNumbers;}
SetReticleFont(const Font & fnt)694 ScatterDraw &SetReticleFont(const Font &fnt) {reticleFont = fnt; return *this;}
GetReticleFont()695 Font &GetReticleFont() {return reticleFont;}
SetReticleColor(const Color & col)696 ScatterDraw &SetReticleColor(const Color &col) {reticleColor = col; return *this;}
GetReticleColor()697 Color &GetReticleColor() {return reticleColor;}
698
699 ScatterDraw &SetFillColor(int index, const Color& color);
SetFillColor(const Color & color)700 ScatterDraw &SetFillColor(const Color& color) {return SetFillColor(series.GetCount() - 1, color);}
701 Color GetFillColor(int index) const;
702
703 ScatterDraw &SetMarkWidth(int index, double width);
SetMarkWidth(double width)704 ScatterDraw &SetMarkWidth(double width) {return SetMarkWidth(series.GetCount() - 1, width);}
705 double GetMarkWidth(int index);
706 ScatterDraw &SetMarkColor(int index, const Color& pcolor);
SetMarkColor(const Color & pcolor)707 ScatterDraw &SetMarkColor(const Color& pcolor) {return SetMarkColor(series.GetCount() - 1, pcolor);}
708 Color GetMarkColor(int index) const;
709 ScatterDraw &SetMarkBorderWidth(int index, double width);
710 double GetMarkBorderWidth(int index);
711 ScatterDraw &SetMarkBorderColor(int index, const Color& pcolor);
712 Color GetMarkBorderColor(int index) const;
713 void NoMark(int index);
714 bool IsShowMark(int index);
715
716 void SetDataPrimaryY(int index, bool primary = true);
717 ScatterDraw &SetDataPrimaryY(bool primary = true);
718 void SetDataSecondaryY(int index, bool secondary = true);
719 ScatterDraw &SetDataSecondaryY(bool secondary = true);
SetRightY(int index)720 void SetRightY(int index) {SetDataSecondaryY(index);}
SetRightY()721 ScatterDraw &SetRightY() {return SetDataSecondaryY();}
722 bool IsDataPrimaryY(int index);
723 bool ThereAreSecondaryY();
724
725 void SetSequentialX(int index, bool sequential);
726 ScatterDraw &SetSequentialX(bool sequential = true);
727 ScatterDraw &SetSequentialXAll(bool sequential = true);
728 bool GetSequentialX(int index);
729 bool GetSequentialX();
730
731 void Show(int index, bool show = true);
732 bool IsVisible(int index);
733 ScatterDraw &ShowAll(bool show = true);
734
735 bool RemoveSeries(int index);
736 void RemoveAllSeries();
737
738 bool SwapSeries(int i1, int i2);
739
740 ScatterDraw& Id(int id);
741 ScatterDraw& Id(int index, int id);
742 int GetId(int index);
743
744 Drawing GetDrawing();
745 Image GetImage();
746
747 #ifdef PLATFORM_WIN32
748 void SaveAsMetafile(const char* file) const;
749 #endif
750
751 ScatterDraw& SetMinZoom(double x, double y = -1) {return SetMinRange(x, y);}
752 ScatterDraw& SetMaxZoom(double x, double y = -1) {return SetMaxRange(x, y);}
753 ScatterDraw& SetMinRange(double x, double y = -1) {minXRange = x; minYRange = y; return *this;}
754 ScatterDraw& SetMaxRange(double x, double y = -1) {maxXRange = x; maxYRange = y; return *this;}
SetMinXmin(double val)755 ScatterDraw& SetMinXmin(double val) {minXmin = val; return *this;}
SetMinYmin(double val)756 ScatterDraw& SetMinYmin(double val) {minYmin = val; return *this;}
SetMaxXmax(double val)757 ScatterDraw& SetMaxXmax(double val) {maxXmax = val; return *this;}
SetMaxYmax(double val)758 ScatterDraw& SetMaxYmax(double val) {maxYmax = val; return *this;}
759
760 ScatterDraw& SetFastViewX(bool set = true) {fastViewX = set; return *this;}
GetFastViewX()761 bool GetFastViewX() {return fastViewX;}
762
763 double GetXByPoint(double x);
764 double GetYByPoint(double y);
765 double GetY2ByPoint(double y);
766 double GetXPointByValue(double x);
767 double GetYPointByValue(double y);
768
GetCount()769 int GetCount() {return series.GetCount();}
IsEmpty()770 bool IsEmpty() {return series.IsEmpty();}
771
772 ScatterDraw& LinkedWith(ScatterDraw& ctrl);
773 void Unlinked();
774
GetMinX()775 double GetMinX() {return xMin;}
GetPlotWidth()776 int GetPlotWidth() {return plotW;}
GetPlotHeight()777 int GetPlotHeight() {return plotH;}
GetPosX(double x)778 double GetPosX(double x) {return plotW*(x - xMin)/xRange;}
GetSizeX(double cx)779 double GetSizeX(double cx) {return plotW*cx/xRange;}
GetPosY(double y)780 double GetPosY(double y) {return plotH - plotH*(y - yMin)/yRange;}
GetSizeY(double cy)781 double GetSizeY(double cy) {return plotH*cy/yRange;}
GetPosY2(double y)782 double GetPosY2(double y) {return plotH - plotH*(y - yMin2)/yRange2;}
GetSizeY2(double cy)783 double GetSizeY2(double cy) {return plotH*cy/yRange2;}
784
GetRealPosX(double x)785 double GetRealPosX(double x) {return xMin + (x - hPlotLeft*plotScaleX)*xRange/plotW;}
GetRealPosY(double y)786 double GetRealPosY(double y) {return yMin + yRange - (y - plotScaleY*vPlotTop - titleHeight)*yRange/plotH;}
GetRealPosY2(double y)787 double GetRealPosY2(double y) {return yMin2 + yRange2 - (y - plotScaleY*vPlotTop - titleHeight)*yRange2/plotH;}
788
GetScatterPosX(double x)789 double GetScatterPosX(double x) {return (x - xMin)*plotW/xRange + hPlotLeft*plotScaleX;}
GetScatterPosY(double y)790 double GetScatterPosY(double y) {return (yMin + yRange - y)*plotH/yRange + plotScaleY*vPlotTop + titleHeight;}
GetScatterPosY2(double y)791 double GetScatterPosY2(double y){return (yMin2 + yRange2 - y)*plotH/yRange2 + plotScaleY*vPlotTop + titleHeight;}
GetScatterDistance(double dx,double dy)792 double GetScatterDistance(double dx, double dy) {return sqrt(sqr(GetScatterPosX(dx)) + sqr(GetScatterPosY(dy)));}
GetScatterDistance2(double dx,double dy)793 double GetScatterDistance2(double dx, double dy) {return sqrt(sqr(GetScatterPosX(dx)) + sqr(GetScatterPosY2(dy)));}
794
GetPixelThickX()795 double GetPixelThickX() {return xRange/plotW;}
GetPixelThickY()796 double GetPixelThickY() {return yRange/plotH;}
797
798 ScatterDraw& SetMouseHandling(bool valx = true, bool valy = false);
799 ScatterDraw& SetMouseHandlingLinked(bool valx = true, bool valy = false);
GetMouseHandlingX()800 bool GetMouseHandlingX() {return mouseHandlingX;}
GetMouseHandlingY()801 bool GetMouseHandlingY() {return mouseHandlingY;}
802
803 ScatterDraw& AddSurf(DataSourceSurf &surf);
RemoveSurf()804 ScatterDraw& RemoveSurf() {surf = nullptr; return *this;}
SetSurfMinZ(double val)805 ScatterDraw& SetSurfMinZ(double val) {surfMinZ = val; return *this;}
GetSurfMinZ()806 double GetSurfMinZ() const {return surfMinZ;}
SetSurfMaxZ(double val)807 ScatterDraw& SetSurfMaxZ(double val) {surfMaxZ = val; return *this;}
GetSurfMaxZ()808 double GetSurfMaxZ() const {return surfMaxZ;}
ZoomToFitZ()809 ScatterDraw& ZoomToFitZ() {surfMinZ = surf->MinZ(); surfMaxZ = surf->MaxZ(); return *this;}
810
SurfNumColor(int num,bool cont)811 ScatterDraw& SurfNumColor(int num, bool cont){surfNumColor = num; continuousColor = cont; return *this;}
SurfRainbow(RAINBOW val)812 ScatterDraw& SurfRainbow(RAINBOW val) {surfRainbow = val; return *this;}
SurfRainbow()813 RAINBOW SurfRainbow() {return surfRainbow;}
814
SurfUnits(const String & units)815 ScatterDraw& SurfUnits(const String &units) {surfUnits = units; return *this;}
816 enum SURF_UNITS_POS {
817 UNITS_TOP,
818 UNITS_BOTTOM,
819 UNITS_LEFT,
820 UNITS_RIGHT
821 };
SurfUnitsPos(SURF_UNITS_POS pos)822 ScatterDraw& SurfUnitsPos(SURF_UNITS_POS pos) {surfUnitsPos = pos; return *this;}
823 enum SURF_LEGEND_POS {
824 LEGEND_LEFT,
825 LEGEND_RIGHT
826 };
SurfLegendPos(SURF_LEGEND_POS pos)827 ScatterDraw& SurfLegendPos(SURF_LEGEND_POS pos) {surfLegendPos = pos; return *this;}
828
829 ScatterDraw& ShowRainbowPalette(bool show = true) {showRainbow = show; return *this;}
GetShowRainbowPalette()830 bool GetShowRainbowPalette() {return showRainbow;}
SetRainbowPalettePos(const Point & p)831 ScatterDraw& SetRainbowPalettePos(const Point &p) {rainbowPos = p; return *this;}
GetRainbowPalettePos()832 Point& GetRainbowPalettePos() {return rainbowPos;}
SetRainbowPaletteSize(const Size & sz)833 ScatterDraw& SetRainbowPaletteSize(const Size &sz) {rainbowSize = sz; return *this;}
GetRainbowPaletteSize()834 Size& GetRainbowPaletteSize() {return rainbowSize;}
SetRainbowPaletteAnchor(LEGEND_POS anchor)835 ScatterDraw& SetRainbowPaletteAnchor(LEGEND_POS anchor) {rainbowAnchor = anchor;return *this;}
GetRainbowPaletteAnchor()836 LEGEND_POS GetRainbowPaletteAnchor() {return rainbowAnchor;}
SetRainbowPaletteBorderColor(const Color & color)837 ScatterDraw& SetRainbowPaletteBorderColor(const Color &color) {rainbowBorderColor = color;return *this;}
GetRainbowPaletteBorderColor()838 Color& GetRainbowPaletteBorderColor() {return rainbowBorderColor;}
SetRainbowPaletteFont(const Font & fnt)839 ScatterDraw& SetRainbowPaletteFont(const Font &fnt) {rainbowPaletteFont = fnt;return *this;}
GetRainbowPaletteFont()840 Font& GetRainbowPaletteFont() {return rainbowPaletteFont;}
SetRainbowPaletteTextColor(const Color & color)841 ScatterDraw& SetRainbowPaletteTextColor(const Color &color) {rainbowPaletteTextColor = color;return *this;}
GetRainbowPaletteTextColor()842 Color& GetRainbowPaletteTextColor() {return rainbowPaletteTextColor;}
843
844 ScatterDraw &AddLabelSeries(Vector<String> &labels, int dx = 0, int dy = 0, Font font = StdFont(),
845 Alignment align = ALIGN_CENTER, Color color = Black()) {
846 int index = series.GetCount() - 1;
847
848 return AddLabelSeries(index, labels, dx, dy, font, align, color);
849 }
850 ScatterDraw& AddLabelSeries(int index, Vector<String> &labels, int dx = 0, int dy = 0, Font font = StdFont(),
851 Alignment align = ALIGN_CENTER, Color color = Black()) {
852 ASSERT(IsValid(index));
853 ASSERT(!series[index].IsDeleted());
854
855 series[index].labels = &labels;
856 series[index].labelsDx = dx;
857 series[index].labelsDy = dy;
858 series[index].labelsFont = font;
859 series[index].labelsAlign = align;
860 series[index].labelsColor = color;
861 return *this;
862 }
863
SetDataSourceInternal()864 ScatterDraw& SetDataSourceInternal() {
865 for (int i = 0; i < series.GetCount(); ++i) {
866 ScatterSeries &serie = series[i];
867 if (serie.IsDeleted())
868 continue;
869 serie.SetDataSourceInternal();
870 }
871 return *this;
872 }
873 ScatterDraw& SerializeData(bool ser = true) {
874 for (int i = 0; i < series.GetCount(); ++i) {
875 ScatterSeries &serie = series[i];
876 if (serie.IsDeleted())
877 continue;
878 serie.SerializeData(ser);
879 }
880 return *this;
881 }
882 ScatterDraw& SerializeFormat(bool ser = true) {
883 for (int i = 0; i < series.GetCount(); ++i) {
884 ScatterSeries &serie = series[i];
885 if (serie.IsDeleted())
886 continue;
887 serie.SerializeFormat(ser);
888 }
889 serializeFormat = ser;
890 return *this;
891 }
892
893 template <class T>
Ize(T & io)894 void Ize(T& io) {
895 if (serializeFormat) {
896 int intlegendAnchor = 0, intrainbowAnchor = 0, intsurfRainbow = 0, intsurfUnitsPos = 0, intsurfLegendPos = 0;
897 if (io.IsStoring()) {
898 intlegendAnchor = legendAnchor;
899 intrainbowAnchor = rainbowAnchor;
900 intsurfRainbow = surfRainbow;
901 intsurfUnitsPos = surfUnitsPos;
902 intsurfLegendPos = surfLegendPos;
903 }
904 io
905 ("title", title)
906 ("titleFont", titleFont)
907 ("titleColor", titleColor)
908 ("titleHeight", titleHeight)
909 ("xLabel_base", xLabel_base)
910 ("yLabel_base", yLabel_base)
911 ("yLabel2_base", yLabel2_base)
912 ("labelsFont", labelsFont)
913 ("labelsColor", labelsColor)
914 ("xRange", xRange)
915 ("yRange", yRange)
916 ("yRange2", yRange2)
917 ("xMin", xMin)
918 ("yMin", yMin)
919 ("yMin2", yMin2)
920 ("xMajorUnit", xMajorUnit)
921 ("yMajorUnit", yMajorUnit)
922 ("yMajorUnit2", yMajorUnit2)
923 ("xMinUnit", xMinUnit)
924 ("yMinUnit", yMinUnit)
925 ("yMinUnit2", yMinUnit2)
926 ("minXRange", minXRange)
927 ("maxXRange", maxXRange)
928 ("minYRange", minYRange)
929 ("maxYRange", maxYRange)
930 ("minXmin", minXmin)
931 ("minYmin", minYmin)
932 ("maxXmax", maxXmax)
933 ("maxYmax", maxYmax)
934 ("hPlotLeft", hPlotLeft)
935 ("hPlotRight", hPlotRight)
936 ("vPlotTop", vPlotTop)
937 ("vPlotBottom", vPlotBottom)
938 ("size", size)
939 ("responsive", responsive)
940 ("legendAnchor", intlegendAnchor)
941 ("legendPos", legendPos)
942 ("legendFillColor", legendFillColor)
943 ("legendBorderColor", legendBorderColor)
944 ("legendFont", legendFont)
945 ("legendNumCols", legendNumCols)
946 ("legendRowSpacing", legendRowSpacing)
947 ("series", series)
948 ("mouseHandlingX", mouseHandlingX)
949 ("mouseHandlingY", mouseHandlingY)
950 ("plotAreaColor", plotAreaColor)
951 ("drawXReticle", drawXReticle)
952 ("drawYReticle", drawYReticle)
953 ("drawY2Reticle", drawY2Reticle)
954 ("drawXReticleNumbers", drawXReticleNumbers)
955 ("drawYReticleNumbers", drawYReticleNumbers)
956 ("drawY2ReticleNumbers", drawY2ReticleNumbers)
957 ("axisWidth", axisWidth)
958 ("reticleFont", reticleFont)
959 ("reticleColor", reticleColor)
960 ("gridColor", gridColor)
961 ("gridWidth", gridWidth)
962 ("gridDash", gridDash)
963 ("drawVGrid", drawVGrid)
964 //("drawVGrid2", drawVGrid2)
965 ("drawHGrid", drawHGrid)
966 //("drawHGrid2", drawHGrid2)
967 //("freqGrid2", freqGrid2)
968 ("showRainbow", showRainbow)
969 ("rainbowPos", rainbowPos)
970 ("rainbowSize", rainbowSize)
971 ("rainbowAnchor", intrainbowAnchor)
972 ("rainbowBorderColor", rainbowBorderColor)
973 ("rainbowPaletteFont", rainbowPaletteFont)
974 ("rainbowPaletteTextColor", rainbowPaletteTextColor)
975 ("surfRainbow", intsurfRainbow)
976 ("surfNumColor", surfNumColor)
977 ("continuousColor", continuousColor)
978 ("surfMinZ", surfMinZ)
979 ("surfMaxZ", surfMaxZ)
980 ("surfUnits", surfUnits)
981 ("surfUnitsPos", intsurfUnitsPos)
982 ("surfLegendPos", intsurfLegendPos)
983 ;
984 if (io.IsLoading()) {
985 labelsChanged = true;
986 legendAnchor = static_cast<LEGEND_POS>(intlegendAnchor);
987 rainbowAnchor = static_cast<LEGEND_POS>(intrainbowAnchor);
988 surfRainbow = static_cast<RAINBOW>(intsurfRainbow);
989 surfUnitsPos = static_cast<SURF_UNITS_POS>(intsurfUnitsPos);
990 surfLegendPos = static_cast<SURF_LEGEND_POS>(intsurfLegendPos);
991 }
992 } else
993 io("series", series);
994 }
995
Xmlize(XmlIO & xml)996 void Xmlize(XmlIO& xml) {Ize(xml);}
Jsonize(JsonIO & json)997 void Jsonize(JsonIO& json) {Ize(json);}
998
Serialize(Stream & s)999 void Serialize(Stream& s) {
1000 if (serializeFormat) {
1001 int intlegendAnchor = 0, intrainbowAnchor = 0, intsurfRainbow = 0, intsurfUnitsPos = 0, intsurfLegendPos = 0;
1002 if (s.IsStoring()) {
1003 intlegendAnchor = legendAnchor;
1004 intrainbowAnchor = rainbowAnchor;
1005 intsurfRainbow = surfRainbow;
1006 intsurfUnitsPos = surfUnitsPos;
1007 intsurfLegendPos = surfLegendPos;
1008 }
1009 s % title
1010 % titleFont
1011 % titleColor
1012 % titleHeight
1013 % xLabel_base
1014 % yLabel_base
1015 % yLabel2_base
1016 % labelsFont
1017 % labelsColor
1018 % xRange
1019 % yRange
1020 % yRange2
1021 % xMin
1022 % yMin
1023 % yMin2
1024 % xMajorUnit
1025 % yMajorUnit
1026 % yMajorUnit2
1027 % xMinUnit
1028 % yMinUnit
1029 % yMinUnit2
1030 % minXRange
1031 % maxXRange
1032 % minYRange
1033 % maxYRange
1034 % minXmin
1035 % minYmin
1036 % maxXmax
1037 % maxYmax
1038 % hPlotLeft
1039 % hPlotRight
1040 % vPlotTop
1041 % vPlotBottom
1042 % size
1043 % intlegendAnchor
1044 % legendPos
1045 % legendFillColor
1046 % legendBorderColor
1047 % legendFont
1048 % series
1049 % mouseHandlingX
1050 % mouseHandlingY
1051 % plotAreaColor
1052 % drawXReticle
1053 % drawYReticle
1054 % drawY2Reticle
1055 % reticleFont
1056 % reticleColor
1057 % responsive
1058 % showRainbow
1059 % rainbowPos
1060 % rainbowSize
1061 % intrainbowAnchor
1062 % rainbowBorderColor
1063 % rainbowPaletteFont
1064 % rainbowPaletteTextColor
1065 % intsurfRainbow
1066 % surfNumColor
1067 % continuousColor
1068 % surfMinZ
1069 % surfMaxZ
1070 % surfUnits
1071 % intsurfUnitsPos
1072 % intsurfLegendPos
1073 % drawXReticleNumbers
1074 % drawYReticleNumbers
1075 % drawY2ReticleNumbers
1076 % axisWidth
1077 ;
1078 if (s.IsLoading()) {
1079 labelsChanged = true;
1080 legendAnchor = static_cast<LEGEND_POS>(intlegendAnchor);
1081 rainbowAnchor = static_cast<LEGEND_POS>(intrainbowAnchor);
1082 surfRainbow = static_cast<RAINBOW>(intsurfRainbow);
1083 surfUnitsPos = static_cast<SURF_UNITS_POS>(intsurfUnitsPos);
1084 surfLegendPos = static_cast<SURF_LEGEND_POS>(intsurfLegendPos);
1085 }
1086 } else
1087 s % series;
1088 }
1089
VariableFormatX(double d)1090 String VariableFormatX(double d) const {return VariableFormat(xRange, d);}
VariableFormatY(double d)1091 String VariableFormatY(double d) const {return VariableFormat(yRange, d);}
VariableFormatY2(double d)1092 String VariableFormatY2(double d) const {return VariableFormat(yRange2, d);}
VariableFormatZ(double d)1093 String VariableFormatZ(double d) const {return VariableFormat(GetSurfMaxZ()-GetSurfMinZ(), d);}
1094
1095 protected:
1096 ScatterDraw &_AddSeries(DataSource *data);
Refresh()1097 virtual void Refresh() {};
1098
1099 int mode{MD_ANTIALIASED};
1100 Color graphColor = White();
1101 String title;
1102 Upp::Font titleFont = Arial(20);
1103 Color titleColor = SColorText();
1104 int titleHeight;
1105
1106 String xLabel, yLabel, yLabel2;
1107 String xLabel_base, yLabel_base, yLabel2_base;
1108 Upp::Font labelsFont = GetStdFont();
1109 Color labelsColor = SColorText();
1110
1111 int hPlotLeft = 30, hPlotRight = 30,
1112 vPlotTop = 30, vPlotBottom = 30;
1113 Color plotAreaColor = White();
1114
1115 bool fastViewX = false, sequentialXAll = false;
1116
1117 Color axisColor = SColorText();
1118 double axisWidth = 0.5;
1119
1120 double xRange = 100., yRange = 100., yRange2 = 100.;
1121 double xMin = 0, yMin = 0, yMin2 = 0;
1122 double xMajorUnit = 10, yMajorUnit = 10, yMajorUnit2 = 10;
1123 double xMajorUnitNum = 5, yMajorUnitNum = 5;
1124 double xMinUnit = 0, yMinUnit = 0, yMinUnit2 = 0;
1125 double xMinUnit0 = 0, yMinUnit0 = 0, yMinUnit20 = 0;
1126 double minXRange = -1, maxXRange = -1, minYRange = -1, maxYRange = -1;
1127 double minXmin = Null, minYmin = Null, maxXmax = Null, maxYmax = Null;
1128 double lastxRange, lastyRange;
1129 bool drawXReticle = true, drawYReticle = true, drawY2Reticle = false;
1130 bool drawXReticleNumbers = true, drawYReticleNumbers = true, drawY2ReticleNumbers = false;
1131 Font reticleFont = GetStdFont();
1132 Color reticleColor = Black;
1133
1134 Color gridColor = SColorDkShadow();
1135 double gridWidth = 0.5;
1136 String gridDash = LINE_DOTTED_FINE;
1137 bool drawVGrid = true, drawHGrid = true;
1138
1139 bool drawVGrid2, drawHGrid2;
1140
1141 int butDownX, butDownY;
1142 bool isScrolling, isLabelPopUp;
1143 ZoomStyle zoomStyleX = TO_CENTER,
1144 zoomStyleY = TO_CENTER;
1145
1146 Upp::Array<ScatterSeries> series;
1147
1148 bool showLegend = true;
1149
1150 bool isPolar = false;
1151
1152 int lastRefresh_sign;
1153 int highlight_0 = Null;
1154
1155 Point legendPos = Point(5, 5);
1156 int legendNumCols = 1;
1157 LEGEND_POS legendAnchor = RIGHT_TOP;
1158 int legendRowSpacing = 5;
1159 Color legendFillColor = White();
1160 Color legendBorderColor = Black();
1161 Font legendFont = GetStdFont();
1162
1163 void DrawLegend(Draw& w) const;
1164
1165 void Scrolling(bool down, Point &pt, bool isOut = false);
1166
ExpFormat(String & s,int,double d)1167 static void ExpFormat(String& s, int , double d) {s = FormatDoubleExp(d, 1);}
MonFormat(String & s,int,double d)1168 static void MonFormat(String& s, int , double d) {s = Format("%Mon", int(d));}
DyFormat(String & s,int,double d)1169 static void DyFormat(String& s, int , double d) {s = Format("%Dy", int(d));}
1170
1171 static String VariableFormat(double range, double d);
1172
1173 template<class T>
1174 void Plot(T& w);
1175 template<class T>
1176 bool PlotTexts(T& w, bool boldX = false, bool boldY = false);
1177
1178 void AdjustMinUnitX();
1179 void AdjustMinUnitY();
1180 void AdjustMinUnitY2();
1181
1182 void AdjustMajorUnitX();
1183 void AdjustMajorUnitY();
1184 void AdjustMajorUnitY2();
1185
1186 bool PointInPlot(Point &pt);
1187 bool PointInBorder(Point &pt);
1188 bool PointInLegend(Point &pt);
1189
1190 Upp::Index<ScatterDraw *> linkedCtrls;
1191 ScatterDraw *linkedMaster = nullptr;
1192
ChangeMouseHandlingX()1193 void ChangeMouseHandlingX() {mouseHandlingX = !mouseHandlingX;}
ChangeMouseHandlingY()1194 void ChangeMouseHandlingY() {mouseHandlingY = !mouseHandlingY;}
1195
1196 bool mouseHandlingX = true, mouseHandlingY = true;
1197
1198 DataSourceSurf *surf = nullptr;
1199 RAINBOW surfRainbow = BLUE_YELLOW_RED;
1200 int surfNumColor = 4;
1201 bool continuousColor = true;
1202 double surfMinZ = Null, surfMaxZ = Null;
1203 String surfUnits;
1204 SURF_UNITS_POS surfUnitsPos = UNITS_TOP;
1205 SURF_LEGEND_POS surfLegendPos = LEGEND_RIGHT;
1206 //Vector<Pointf> isolines;
1207 //int isolinesId;
1208
1209 bool showRainbow = true;
1210 Point rainbowPos = Point(5, 5);
1211 Size rainbowSize = Size(10, 50);
1212 LEGEND_POS rainbowAnchor = RIGHT_BOTTOM;
1213 Color rainbowBorderColor = Black;
1214 Font rainbowPaletteFont = StdFont();
1215 Color rainbowPaletteTextColor = Black;
1216
1217 void DrawRainbowPalette(Draw& w) const;
1218
1219 private:
1220 Size size{Size(800, 400)}; // Size to be used for all but screen painting
1221 double plotScaleX = 1, plotScaleY = 1, plotScaleAvg = 1;
1222 bool responsive = false;
1223 double responsivenessFactor = 1;
1224
1225 static void ParseTextMultiline(const String &text, Upp::Font &fnt,
1226 Upp::Vector <String> &texts, Upp::Vector <Size> &sizes);
1227
1228 ScatterDraw &DoFitToData(bool horizontal, bool vertical, double factor);
1229 //ScatterDraw &DoFitToData(bool horizontal, double minx, double maxx, bool vertical, double minxy, double maxy,
1230 // bool vertical2, double miny2, double maxy2, double factor = 0);
1231 //ScatterDraw &DoFitToDataSmart(bool horizontal, double minx, double maxx, bool vertical, double minxy, double maxy,
1232 // bool vertical2, double miny2, double maxy2, double factor = 0);
1233 void DoZoom(double scale, bool hor, bool ver);
1234 void DoScroll(double factorX, double factorY);
1235
1236 void SetXYMinLinkedEach(double xmin, double xmin0, double ymin, double ymin0, double ymin2, double ymin20);
1237 void SetRangeLinkedEach(double rx, double rx0, double ry, double ry0, double ry2, double ry20);
1238
1239 int NumSeriesLegend() const;
1240
1241 int plotW = Null, plotH = Null;
1242 bool labelsChanged = false;
1243 bool stacked = false;
1244 bool serializeFormat = true;
1245 };
1246
1247 template <class T>
SetDrawing(T & w,bool ctrl)1248 void ScatterDraw::SetDrawing(T& w, bool ctrl) {
1249 w.DrawRect(size, graphColor);
1250
1251 titleHeight = !title.IsEmpty() ? fround(min(plotScaleX, plotScaleY)*(titleFont.GetHeight()+titleFont.GetDescent())) : 0;
1252
1253 plotW = size.cx - fround((hPlotLeft + hPlotRight)*plotScaleX);
1254 plotH = size.cy - fround((vPlotTop + vPlotBottom)*plotScaleY) - titleHeight;
1255
1256 Plot(w);
1257
1258 if (!ctrl) {
1259 if (!PlotTexts(w))
1260 return;
1261 }
1262 }
1263
1264 template <class T>
PlotTexts(T & w,const bool boldX,bool boldY)1265 bool ScatterDraw::PlotTexts(T& w, const bool boldX, bool boldY) {
1266 if(titleHeight > 0) {
1267 Upp::Font fontTitle6;
1268 fontTitle6 = titleFont;
1269 fontTitle6.Height(titleHeight);
1270 Size sz = GetTextSizeSpace(title, fontTitle6);
1271 if (sz.cx > size.cx*0.95) {
1272 fontTitle6.Height(fround((fontTitle6.GetHeight()+fontTitle6.GetDescent())*size.cx*(0.95/sz.cx)));
1273 sz = GetTextSizeSpace(title, fontTitle6);
1274 }
1275 DrawText(w, fround((size.cx - sz.cx)/2.), plotScaleY*2, 0, title, fontTitle6, titleColor);
1276 }
1277 if(showLegend)
1278 DrawLegend(w);
1279
1280 if (surf && showRainbow)
1281 DrawRainbowPalette(w);
1282
1283 if (plotW < 0 || plotH < 0)
1284 return false;
1285
1286 w.Offset(Point(fround(plotScaleX*hPlotLeft), fround(plotScaleY*vPlotTop + titleHeight)));
1287
1288 Upp::Font fontLabel = labelsFont;
1289 fontLabel.Height(fround(min(plotScaleX, plotScaleY)*(labelsFont.GetHeight()+labelsFont.GetDescent())));
1290 Upp::Font fontX = fontLabel;
1291 if (boldX)
1292 fontX.Bold();
1293 Upp::Font fontY = fontLabel;
1294 if (boldY)
1295 fontY.Bold();
1296 Upp::Font fontY2 = fontY;
1297 fontY2.Italic();
1298
1299 if (labelsChanged) {
1300 xLabel = xLabel_base;
1301 yLabel = yLabel_base;
1302 yLabel2 = yLabel2_base;
1303 String yLabelLegends, yLabelLegends2;
1304 Upp::Index<String> xUnits, yUnits, yUnits2;
1305 for (int i = 0; i < series.GetCount(); ++i) {
1306 const ScatterSeries &serie = series[i];
1307 if (serie.IsDeleted() || serie.opacity == 0)
1308 continue;
1309 if (serie.primaryY) {
1310 if (yLabel.IsEmpty()) {
1311 if (!yLabelLegends.IsEmpty())
1312 yLabelLegends << ";";
1313 yLabelLegends << serie.legend;
1314 }
1315 } else {
1316 if (yLabel2.IsEmpty()) {
1317 if (!yLabelLegends2.IsEmpty())
1318 yLabelLegends2 << ";";
1319 yLabelLegends2 << serie.legend;
1320 }
1321 }
1322 if (!serie.unitsX.IsEmpty())
1323 xUnits.FindAdd(serie.unitsX);
1324 if (!serie.unitsY.IsEmpty()) {
1325 if (serie.primaryY)
1326 yUnits.FindAdd(serie.unitsY);
1327 else
1328 yUnits2.FindAdd(serie.unitsY);
1329 }
1330 }
1331 yLabel << yLabelLegends;
1332 yLabel2 << yLabelLegends2;
1333 if (xLabel.Find('[') < 0 && !xUnits.IsEmpty()) {
1334 xLabel += " ";
1335 for (int i = 0; i < xUnits.GetCount(); ++i)
1336 xLabel += "[" + xUnits[i] + "]";
1337 }
1338 if (yLabel.Find('[') < 0 && !yUnits.IsEmpty()) {
1339 yLabel += " ";
1340 for (int i = 0; i < yUnits.GetCount(); ++i)
1341 yLabel += "[" + yUnits[i] + "]";
1342 }
1343 if (yLabel2.Find('[') < 0 && !yUnits2.IsEmpty()) {
1344 yLabel2 += " ";
1345 for (int i = 0; i < yUnits2.GetCount(); ++i)
1346 yLabel2 += "[" + yUnits2[i] + "]";
1347 }
1348 labelsChanged = false;
1349 }
1350 Size lx = GetTextSizeSpace(xLabel, fontX);
1351 Size ly = GetTextSizeSpace(yLabel, fontY);
1352 Size ly2 = GetTextSizeSpace(yLabel2, fontY2);
1353 DrawText(w, (plotW - lx.cx)/2., plotH + plotScaleY*(vPlotBottom - 2) - lx.cy, 0, xLabel, fontX, labelsColor);
1354 DrawText(w, plotScaleX*(2 - hPlotLeft), (plotH + ly.cx)/2., 900, yLabel, fontY, labelsColor);
1355 DrawText(w, size.cx - plotScaleX*(2 + hPlotLeft) - ly2.cy, (plotH + ly2.cx)/2., 900, yLabel2, fontY2, labelsColor);
1356
1357 drawXReticle &= (xRange != 0 && xMajorUnit != 0);
1358 drawYReticle &= (yRange != 0 && yMajorUnit != 0);
1359 drawY2Reticle &= (yRange2 != 0 && yMajorUnit != 0);
1360 drawXReticleNumbers &= (xRange != 0 && xMajorUnit != 0);
1361 drawYReticleNumbers &= (yRange != 0 && yMajorUnit != 0);
1362 drawY2ReticleNumbers &= (yRange2 != 0 && yMajorUnit != 0);
1363
1364 Upp::Font standard6 = reticleFont;
1365 standard6.Height(fround(min(plotScaleX, plotScaleY)*(standard6.GetHeight()+standard6.GetDescent())));
1366 Upp::Font fontXNum = standard6;
1367 if (boldX)
1368 fontXNum.Bold();
1369 Upp::Font fontYNum = standard6;
1370 if (boldY)
1371 fontYNum.Bold();
1372 Upp::Font fontY2Num = fontYNum;
1373 fontY2Num.Italic();
1374
1375 if (drawXReticle || drawXReticleNumbers) {
1376 Vector<double> unitsX;
1377 if (SetGridLinesX)
1378 SetGridLinesX(unitsX);
1379 else {
1380 for(int i = 0; xMinUnit + i*xMajorUnit <= xRange; i++)
1381 unitsX << xMinUnit + i*xMajorUnit;
1382 }
1383 double factorX = plotW/xRange;
1384 for(int i = 0; i < unitsX.GetCount(); ++i) {
1385 double reticleX = factorX*unitsX[i];
1386 if (reticleX >=0 && reticleX <= plotW+0.001) {
1387 double gridX = xMin + unitsX[i];
1388 String gridLabelX;
1389 if (cbModifFormatXGridUnits)
1390 cbModifFormatXGridUnits(gridLabelX, i, gridX);
1391 else if (cbModifFormatX)
1392 cbModifFormatX(gridLabelX, i, gridX);
1393 else
1394 gridLabelX = VariableFormatX(gridX);
1395
1396 if (!gridLabelX.IsEmpty()) {
1397 if (drawXReticleNumbers) {
1398 Upp::Vector <String> texts;
1399 Upp::Vector <Size> sizes;
1400 ParseTextMultiline(gridLabelX, fontXNum, texts, sizes);
1401 for (int ii = 0; ii < texts.GetCount(); ++ii) {
1402 int cy = ii == 0 ? 0 : sizes[ii - 1].cy;
1403 DrawText(w, reticleX - sizes[ii].cx/2.,
1404 plotH + (4 + ii*cy), 0, texts[ii], fontXNum, reticleColor);
1405 }
1406 }
1407 if (drawXReticle)
1408 DrawLineOpa(w, reticleX, plotH, reticleX, plotH + plotScaleY*4, plotScaleAvg, 1, axisWidth, axisColor, LINE_SOLID);
1409 }
1410 }
1411 }
1412 }
1413 if (drawYReticle || drawYReticleNumbers || drawY2ReticleNumbers) {
1414 Vector<double> unitsY;
1415 if (SetGridLinesY)
1416 SetGridLinesY(unitsY);
1417 else {
1418 for(int i = 0; yMinUnit + i*yMajorUnit <= yRange; i++)
1419 unitsY << yMinUnit + i*yMajorUnit;
1420 }
1421 double factorY = plotH/yRange;
1422 for(int i = 0; i < unitsY.GetCount(); ++i) {
1423 double reticleY = plotH - factorY*unitsY[i];
1424 if (drawYReticle)
1425 DrawLineOpa(w, -plotScaleX*4, reticleY, 0, reticleY, plotScaleAvg, 1, axisWidth, axisColor, LINE_SOLID);
1426 if (drawY2Reticle)
1427 DrawLineOpa(w, plotW+plotScaleX*4, reticleY, plotW, reticleY, plotScaleAvg, 1, axisWidth, axisColor, LINE_SOLID);
1428 double gridY = yMin + unitsY[i];
1429 if (drawYReticleNumbers) {
1430 String gridLabelY;
1431 if (cbModifFormatYGridUnits)
1432 cbModifFormatYGridUnits(gridLabelY, i, gridY);
1433 else if (cbModifFormatY)
1434 cbModifFormatY(gridLabelY, i, gridY);
1435 else
1436 gridLabelY = VariableFormatY(gridY);
1437 Size sz = GetTextSizeSpace(gridLabelY, fontYNum);
1438 DrawText(w, -sz.cx - plotScaleX*6, reticleY - sz.cy/2, 0, gridLabelY, fontYNum, axisColor);
1439 }
1440 if (drawY2ReticleNumbers) {
1441 double gridY2 = (gridY - yMin)/yRange*yRange2 + yMin2;
1442 String gridLabelY2;
1443 if (cbModifFormatY2GridUnits)
1444 cbModifFormatY2GridUnits(gridLabelY2, i, gridY2);
1445 else if (cbModifFormatY2)
1446 cbModifFormatY2(gridLabelY2, i, gridY2);
1447 else
1448 gridLabelY2 = VariableFormatY2(gridY2);
1449 Size sz = GetTextSizeSpace(gridLabelY2, fontY2Num);
1450 DrawText(w, plotW + plotScaleX*10, reticleY - sz.cy/2, 0, gridLabelY2, fontY2Num, axisColor);
1451 }
1452 }
1453 }
1454 int borderWidth = fround(gridWidth*plotScaleAvg);
1455 #ifdef flagGUI // Control highlight
1456 if (!IsNull(highlight_0)) {
1457 double delayFactor = 4*(1000. - (GetTickCount() - highlight_0))/1000.;
1458 if (delayFactor < 1) {
1459 delayFactor = 1;
1460 highlight_0 = Null;
1461 }
1462 borderWidth = fround(delayFactor*borderWidth);
1463 }
1464 #endif
1465 DrawRectangle(w, 0, 0, plotW, plotH, 1, borderWidth, Black);
1466
1467 w.End();
1468
1469 return true;
1470 }
1471
1472 template <class T>
Plot(T & w)1473 void ScatterDraw::Plot(T& w) {
1474 if (plotW < 0 || plotH < 0)
1475 return;
1476
1477 w.Offset(Point(fround(plotScaleX*hPlotLeft), fround(plotScaleY*vPlotTop + titleHeight)));
1478 Clip(w, 0, 0, plotW, plotH);
1479
1480 double factorX = plotW/xRange;
1481 double factorY = plotH/yRange;
1482
1483 double left, top, d = min(plotW, plotH);//, r = d/2.;
1484 if (!isPolar) {
1485 if (!surf)
1486 w.DrawRect(0, 0, plotW, plotH, plotAreaColor);
1487 else {
1488 ImageBuffer out_image(plotW, plotH);
1489 Upp::Fill(~out_image, plotAreaColor, out_image.GetLength());
1490
1491 double deltaz = surfMaxZ - surfMinZ;
1492 if (deltaz == 0)
1493 Upp::Fill(~out_image, GetRainbowColor(0, surfRainbow, 0), out_image.GetLength());
1494 else {
1495 CoWork co;
1496 for (int ix = 0; ix < plotW; ++ix) {
1497 co & [=, &out_image] {
1498 for (int iy = 0; iy < plotH; ++iy) {
1499 double x = xMin + (ix + 0.5)/factorX;
1500 double y = yMin + (iy + 0.5)/factorY;
1501 double z = surf->z(x, y);
1502 if (!IsNull(z))
1503 out_image[plotH - iy - 1][ix] = GetRainbowColor((z - surfMinZ)/deltaz,
1504 surfRainbow, continuousColor ? 0 : surfNumColor);
1505 }
1506 };
1507 }
1508 }
1509 w.DrawImage(0, 0, out_image);
1510 }
1511 } else {
1512 if (plotW > plotH) {
1513 left = (plotW - d)/2.;
1514 top = 0;
1515 } else {
1516 left = 0;
1517 top = (plotH - d)/2.;
1518 }
1519 w.DrawEllipse(fround(left), fround(top), fround(d), fround(d), plotAreaColor);
1520 }
1521
1522 if (drawVGrid) {
1523 if (!isPolar) {
1524 Vector<double> unitsX;
1525 if (SetGridLinesX)
1526 SetGridLinesX(unitsX);
1527 else {
1528 if (xMajorUnit > 0) {
1529 for(int i = 0; xMinUnit + i*xMajorUnit <= xRange; i++)
1530 unitsX << xMinUnit + i*xMajorUnit;
1531 }
1532 }
1533 if (unitsX.GetCount() > 0) {
1534 for(int i = 0; i < unitsX.GetCount(); i++) {
1535 double reticleX = factorX*unitsX[i];
1536 if (reticleX >=0 && reticleX <= plotW) {
1537 if (gridDash.GetCount() == 1 && gridDash[0] == '-') {
1538 DrawLineOpa(w, reticleX, 0, reticleX, 8*plotScaleAvg, plotScaleAvg, 1, gridWidth, gridColor, LINE_SOLID);
1539 DrawLineOpa(w, reticleX, plotH-8*plotScaleAvg, reticleX, plotH, plotScaleAvg, 1, gridWidth, gridColor, LINE_SOLID);
1540 } else
1541 DrawLineOpa(w, reticleX, 0, reticleX, plotH, plotScaleAvg, 1, gridWidth, gridColor, gridDash);
1542 }
1543 }
1544 }
1545 } /*else {
1546 double ang0 = 2*M_PI*xMinUnit/xRange;
1547 for(double i = 0; xMinUnit + i*xMajorUnit < xRange; i++) {
1548 double ang = ang0 + i*2*M_PI*xMajorUnit/xRange;
1549 DrawLineOpa(w, x_c, y_c, x_c + r*cos(ang), y_c + r*sin(ang), plotScaleAvg, 1, gridWidth*plotScaleAvg, gridColor, gridDash);
1550 }
1551 }*/
1552 }
1553 if (drawHGrid) {
1554 if (!isPolar) {
1555 Vector<double> unitsY;
1556 if (SetGridLinesY)
1557 SetGridLinesY(unitsY);
1558 else {
1559 if (yMajorUnit > 0) {
1560 for(int i = 0; yMinUnit + i*yMajorUnit <= yRange; i++)
1561 unitsY << yMinUnit + i*yMajorUnit;
1562 }
1563 }
1564 if (unitsY.GetCount() > 0) {
1565 for(int i = 0; i < unitsY.GetCount(); i++) {
1566 double reticleY = plotH - factorY*unitsY[i];
1567 if (reticleY > 2*gridWidth*plotScaleAvg && reticleY < plotH - 2*gridWidth*plotScaleAvg) {
1568 if (gridDash.GetCount() == 1 && gridDash[0] == '-') {
1569 DrawLineOpa(w, 0, reticleY, 8*plotScaleAvg, reticleY, plotScaleAvg, 1, gridWidth, gridColor, LINE_SOLID);
1570 DrawLineOpa(w, plotW-8*plotScaleAvg, reticleY, plotW, reticleY, plotScaleAvg, 1, gridWidth, gridColor, LINE_SOLID);
1571 } else
1572 DrawLineOpa(w, 0, reticleY, plotW, reticleY, plotScaleAvg, 1, gridWidth, gridColor, gridDash);
1573 }
1574 }
1575 }
1576 } /*else {
1577 double y0 = -plotH*yMinUnit/r + plotH;
1578 for(double i = 0; yMinUnit + i*yMajorUnit < yRange; i++) {
1579 double reticleY = y0 + i*r*yRange/yMajorUnit;
1580 DrawCircleOpa(w, plotW/2, plotH/2, reticleY, 1, 1, gridWidth, gridColor, gridDash);
1581 }
1582 }*/
1583 }
1584
1585 try {
1586 for (int j = 0; j < series.GetCount(); j++) {
1587 ScatterSeries &serie = series[j];
1588 if (serie.IsDeleted())
1589 continue;
1590 DataSource &data = serie.Data();
1591 if (serie.opacity == 0 || (!serie.seriesPlot && !serie.markPlot))
1592 continue;
1593 if (!data.IsExplicit() && data.GetCount() == 0)
1594 continue;
1595 if (data.IsExplicit() && IsNull(data.GetCount()))
1596 continue;
1597 Vector<Pointf> points;
1598 if (data.IsParam()) {
1599 double xmin = 0;
1600 double xmax = double(data.GetCount());
1601 for (double x = xmin; x <= xmax; x++) {
1602 double xx = data.x(x);
1603 double yy = data.y(x);
1604 if (IsNull(xx) || IsNull(yy))
1605 points << Null;
1606 else {
1607 int ix = fround(plotW*(xx - xMin)/xRange);
1608 int iy;
1609 if (serie.primaryY)
1610 iy = fround(plotH*(yy - yMin)/yRange);
1611 else
1612 iy = fround(plotH*(yy - yMin2)/yRange2);
1613 points << Point(ix, plotH - iy);
1614 }
1615 }
1616 } else if (data.IsExplicit()) {
1617 double xmin = xMin - 1;
1618 double xmax = xMin + xRange + 1;
1619 double dx = double(xmax - xmin)/plotW;
1620 for (double xx = xmin; xx < xmax; xx += dx) {
1621 double yy = data.f(xx);
1622 if (IsNull(yy))
1623 points << Null;
1624 else {
1625 int ix = fround(plotW*(xx - xMin)/xRange);
1626 int iy;
1627 if (serie.primaryY)
1628 iy = fround(plotH*(yy - yMin)/yRange);
1629 else
1630 iy = fround(plotH*(yy - yMin2)/yRange2);
1631 points << Point(ix, plotH - iy);
1632 }
1633 }
1634 } else {
1635 int64 imin, imax;
1636 if (serie.sequential) {
1637 imin = imax = Null;
1638 for (int64 i = 0; i < data.GetCount(); ++i) {
1639 double xx = data.x(i);
1640 if (!IsNull(xx)) {
1641 if (IsNull(imin)) {
1642 if (xx >= xMin)
1643 imin = i;
1644 }
1645 if (IsNull(imax)) {
1646 if (xx >= xMin + xRange)
1647 imax = i;
1648 }
1649 }
1650 }
1651 if (IsNull(imin))
1652 imin = 0;
1653 if (IsNull(imax))
1654 imax = data.GetCount() - 1;
1655 } else {
1656 imin = 0;
1657 imax = data.GetCount() - 1;
1658 }
1659 if (fastViewX) {
1660 double dxpix = (data.x(imax) - data.x(imin))/plotW;
1661 int npix = 1;
1662 for (int64 i = imin; i <= imax; ) {
1663 double yy = data.y(i);
1664 if (IsNull(yy)) {
1665 ++i;
1666 continue;
1667 }
1668 int64 ii;
1669 double maxv = data.x(imin) + dxpix*npix;
1670 double maxY = yy, minY = yy;
1671 for (ii = 1; i + ii < imax && data.x(i + ii) < maxv; ++ii) {
1672 double dd = data.y(i + ii);
1673 if (IsNull(dd))
1674 continue;
1675 maxY = max(maxY, dd);
1676 minY = min(minY, dd);
1677 }
1678 double xx = data.x(i);
1679 if (IsNull(xx)) {
1680 ++i;
1681 continue;
1682 }
1683 i += ii;
1684 npix++;
1685 int ix = fround(plotW*(xx - xMin)/xRange);
1686 int iMax, iMin;
1687 if (serie.primaryY) {
1688 iMax = fround(plotH*(maxY - yMin)/yRange);
1689 iMin = fround(plotH*(minY - yMin)/yRange);
1690 } else {
1691 iMax = fround(plotH*(maxY - yMin2)/yRange2);
1692 iMin = fround(plotH*(minY - yMin2)/yRange2);
1693 }
1694 points << Point(ix, plotH - iMax);
1695 if (iMax != iMin)
1696 points << Point(ix, plotH - iMin);
1697 }
1698 } else {
1699 for (int64 i = imin; i <= imax; ) {
1700 double xx = data.x(i);
1701 double yy = data.y(i);
1702 ++i;
1703 if (IsNull(xx) || IsNull(yy))
1704 points << Null;
1705 else {
1706 int ix = fround(plotW*(xx - xMin)/xRange);
1707 int iy;
1708 if (serie.primaryY)
1709 iy = fround(plotH*(yy - yMin)/yRange);
1710 else
1711 iy = fround(plotH*(yy - yMin2)/yRange2);
1712 points << Point(ix, plotH - iy);
1713 }
1714 }
1715 }
1716 }
1717 if (!points.IsEmpty() && serie.seriesPlot && serie.thickness > 0)
1718 serie.seriesPlot->Paint(w, points, plotScaleAvg, serie.opacity,
1719 serie.thickness, serie.color,
1720 serie.dash, plotAreaColor, serie.fillColor, plotW/xRange, plotH/yRange,
1721 plotH*(1 + yMin/yRange), serie.barWidth,
1722 serie.isClosed);
1723
1724 if (serie.markWidth >= 1 && serie.markPlot) {
1725 if (!serie.markPlot->IsMultiPlot()) {
1726 for (int i = 0; i < points.GetCount(); i++)
1727 serie.markPlot->Paint(w, plotScaleAvg, points[i],
1728 serie.markWidth, serie.markColor,
1729 serie.markBorderWidth, serie.markBorderColor);
1730 } else {
1731 for (int64 i = 0; i < data.GetCount(); ++i) {
1732 int ix = fround(plotW*(data.x(i) - xMin)/xRange);
1733 int iy;
1734 if (serie.primaryY)
1735 iy = plotH - fround(plotH*(data.y(i) - yMin)/yRange);
1736 else
1737 iy = plotH - fround(plotH*(data.y(i) - yMin2)/yRange2);
1738 Vector<int> dataX, dataY;
1739 Vector<double> dataFixed;
1740 for (int ii = 0; ii < data.GetznxCount(i); ++ii)
1741 dataX << fround(plotW*(data.znx(ii, i) - xMin)/xRange);
1742 if (serie.primaryY) {
1743 for (int ii = 0; ii < data.GetznyCount(i); ++ii)
1744 dataY << (plotH - fround(plotH*(data.zny(ii, i) - yMin)/yRange));
1745 } else {
1746 for (int ii = 0; ii < data.GetznyCount(i); ++ii)
1747 dataY << (plotH - fround(plotH*(data.zny(ii, i) - yMin2)/yRange2));
1748 }
1749 for (int ii = 0; ii < data.GetznFixedCount(); ++ii)
1750 dataFixed << data.znFixed(ii, i);
1751 serie.markPlot->Paint(w, plotScaleAvg, ix, iy, dataX, dataY, dataFixed,
1752 serie.markWidth, serie.markColor,
1753 serie.markBorderWidth, serie.markBorderColor);
1754 }
1755 }
1756 }
1757 if (serie.labels) {
1758 int dx = int(serie.labelsDx*plotScaleX);
1759 int dy = int(serie.labelsDy*plotScaleY);
1760 Font fnt = serie.labelsFont;
1761 fnt.Height(int((fnt.GetHeight() + fnt.GetDescent())*min(plotScaleX, plotScaleY)));
1762 for (int i = 0; i < points.GetCount() && i < serie.labels->GetCount(); i++) {
1763 String txt = (*(serie.labels))[i];
1764 Size sz = GetTextSizeSpace(txt, fnt);
1765 int ddy = static_cast<int>(-sz.cy/2.);
1766 int ddx = 0;
1767 switch (serie.labelsAlign) {
1768 case ALIGN_LEFT: ddx = 0; break;
1769 case ALIGN_CENTER: ddx = -sz.cx/2; break;
1770 case ALIGN_RIGHT: ddx = -sz.cx; break;
1771 default: NEVER();
1772 }
1773 double x = points[i].x + dx + ddx;
1774 double y = points[i].y + dy + ddy;
1775 DrawText(w, x, y, 0, txt, fnt, serie.labelsColor);
1776 }
1777 }
1778 }
1779 } catch(ValueTypeError error) {
1780 ASSERT_(true, error);
1781 }
1782
1783 WhenPaint(w);
1784 ClipEnd(w);
1785 w.End();
1786 }
1787
1788 }
1789
1790 #endif
1791
1792