implot_internal.h 67 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689
  1. // MIT License
  2. // Copyright (c) 2023 Evan Pezent
  3. // Permission is hereby granted, free of charge, to any person obtaining a copy
  4. // of this software and associated documentation files (the "Software"), to deal
  5. // in the Software without restriction, including without limitation the rights
  6. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7. // copies of the Software, and to permit persons to whom the Software is
  8. // furnished to do so, subject to the following conditions:
  9. // The above copyright notice and this permission notice shall be included in all
  10. // copies or substantial portions of the Software.
  11. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  12. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  13. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  14. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  15. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  16. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  17. // SOFTWARE.
  18. // ImPlot v0.17
  19. // You may use this file to debug, understand or extend ImPlot features but we
  20. // don't provide any guarantee of forward compatibility!
  21. //-----------------------------------------------------------------------------
  22. // [SECTION] Header Mess
  23. //-----------------------------------------------------------------------------
  24. #pragma once
  25. #ifndef IMPLOT_VERSION
  26. #error Must include implot.h before implot_internal.h
  27. #endif
  28. #ifndef IMGUI_DISABLE
  29. #include <time.h>
  30. #include "imgui_internal.h"
  31. // Support for pre-1.84 versions. ImPool's GetSize() -> GetBufSize()
  32. #if (IMGUI_VERSION_NUM < 18303)
  33. #define GetBufSize GetSize
  34. #endif
  35. //-----------------------------------------------------------------------------
  36. // [SECTION] Constants
  37. //-----------------------------------------------------------------------------
  38. // Constants can be changed unless stated otherwise. We may move some of these
  39. // to ImPlotStyleVar_ over time.
  40. // Mimimum allowable timestamp value 01/01/1970 @ 12:00am (UTC) (DO NOT DECREASE THIS)
  41. #define IMPLOT_MIN_TIME 0
  42. // Maximum allowable timestamp value 01/01/3000 @ 12:00am (UTC) (DO NOT INCREASE THIS)
  43. #define IMPLOT_MAX_TIME 32503680000
  44. // Default label format for axis labels
  45. #define IMPLOT_LABEL_FORMAT "%g"
  46. // Max character size for tick labels
  47. #define IMPLOT_LABEL_MAX_SIZE 32
  48. //-----------------------------------------------------------------------------
  49. // [SECTION] Macros
  50. //-----------------------------------------------------------------------------
  51. #define IMPLOT_NUM_X_AXES ImAxis_Y1
  52. #define IMPLOT_NUM_Y_AXES (ImAxis_COUNT - IMPLOT_NUM_X_AXES)
  53. // Split ImU32 color into RGB components [0 255]
  54. #define IM_COL32_SPLIT_RGB(col,r,g,b) \
  55. ImU32 r = ((col >> IM_COL32_R_SHIFT) & 0xFF); \
  56. ImU32 g = ((col >> IM_COL32_G_SHIFT) & 0xFF); \
  57. ImU32 b = ((col >> IM_COL32_B_SHIFT) & 0xFF);
  58. //-----------------------------------------------------------------------------
  59. // [SECTION] Forward Declarations
  60. //-----------------------------------------------------------------------------
  61. struct ImPlotTick;
  62. struct ImPlotAxis;
  63. struct ImPlotAxisColor;
  64. struct ImPlotItem;
  65. struct ImPlotLegend;
  66. struct ImPlotPlot;
  67. struct ImPlotNextPlotData;
  68. struct ImPlotTicker;
  69. //-----------------------------------------------------------------------------
  70. // [SECTION] Context Pointer
  71. //-----------------------------------------------------------------------------
  72. #ifndef GImPlot
  73. extern IMPLOT_API ImPlotContext* GImPlot; // Current implicit context pointer
  74. #endif
  75. //-----------------------------------------------------------------------------
  76. // [SECTION] Generic Helpers
  77. //-----------------------------------------------------------------------------
  78. // Computes the common (base-10) logarithm
  79. static inline float ImLog10(float x) { return log10f(x); }
  80. static inline double ImLog10(double x) { return log10(x); }
  81. static inline float ImSinh(float x) { return sinhf(x); }
  82. static inline double ImSinh(double x) { return sinh(x); }
  83. static inline float ImAsinh(float x) { return asinhf(x); }
  84. static inline double ImAsinh(double x) { return asinh(x); }
  85. // Returns true if a flag is set
  86. template <typename TSet, typename TFlag>
  87. static inline bool ImHasFlag(TSet set, TFlag flag) { return (set & flag) == flag; }
  88. // Flips a flag in a flagset
  89. template <typename TSet, typename TFlag>
  90. static inline void ImFlipFlag(TSet& set, TFlag flag) { ImHasFlag(set, flag) ? set &= ~flag : set |= flag; }
  91. // Linearly remaps x from [x0 x1] to [y0 y1].
  92. template <typename T>
  93. static inline T ImRemap(T x, T x0, T x1, T y0, T y1) { return y0 + (x - x0) * (y1 - y0) / (x1 - x0); }
  94. // Linear rempas x from [x0 x1] to [0 1]
  95. template <typename T>
  96. static inline T ImRemap01(T x, T x0, T x1) { return (x - x0) / (x1 - x0); }
  97. // Returns always positive modulo (assumes r != 0)
  98. static inline int ImPosMod(int l, int r) { return (l % r + r) % r; }
  99. // Returns true if val is NAN
  100. static inline bool ImNan(double val) { return isnan(val); }
  101. // Returns true if val is NAN or INFINITY
  102. static inline bool ImNanOrInf(double val) { return !(val >= -DBL_MAX && val <= DBL_MAX) || ImNan(val); }
  103. // Turns NANs to 0s
  104. static inline double ImConstrainNan(double val) { return ImNan(val) ? 0 : val; }
  105. // Turns infinity to floating point maximums
  106. static inline double ImConstrainInf(double val) { return val >= DBL_MAX ? DBL_MAX : val <= -DBL_MAX ? - DBL_MAX : val; }
  107. // Turns numbers less than or equal to 0 to 0.001 (sort of arbitrary, is there a better way?)
  108. static inline double ImConstrainLog(double val) { return val <= 0 ? 0.001f : val; }
  109. // Turns numbers less than 0 to zero
  110. static inline double ImConstrainTime(double val) { return val < IMPLOT_MIN_TIME ? IMPLOT_MIN_TIME : (val > IMPLOT_MAX_TIME ? IMPLOT_MAX_TIME : val); }
  111. // True if two numbers are approximately equal using units in the last place.
  112. static inline bool ImAlmostEqual(double v1, double v2, int ulp = 2) { return ImAbs(v1-v2) < DBL_EPSILON * ImAbs(v1+v2) * ulp || ImAbs(v1-v2) < DBL_MIN; }
  113. // Finds min value in an unsorted array
  114. template <typename T>
  115. static inline T ImMinArray(const T* values, int count) { T m = values[0]; for (int i = 1; i < count; ++i) { if (values[i] < m) { m = values[i]; } } return m; }
  116. // Finds the max value in an unsorted array
  117. template <typename T>
  118. static inline T ImMaxArray(const T* values, int count) { T m = values[0]; for (int i = 1; i < count; ++i) { if (values[i] > m) { m = values[i]; } } return m; }
  119. // Finds the min and max value in an unsorted array
  120. template <typename T>
  121. static inline void ImMinMaxArray(const T* values, int count, T* min_out, T* max_out) {
  122. T Min = values[0]; T Max = values[0];
  123. for (int i = 1; i < count; ++i) {
  124. if (values[i] < Min) { Min = values[i]; }
  125. if (values[i] > Max) { Max = values[i]; }
  126. }
  127. *min_out = Min; *max_out = Max;
  128. }
  129. // Finds the sim of an array
  130. template <typename T>
  131. static inline T ImSum(const T* values, int count) {
  132. T sum = 0;
  133. for (int i = 0; i < count; ++i)
  134. sum += values[i];
  135. return sum;
  136. }
  137. // Finds the mean of an array
  138. template <typename T>
  139. static inline double ImMean(const T* values, int count) {
  140. double den = 1.0 / count;
  141. double mu = 0;
  142. for (int i = 0; i < count; ++i)
  143. mu += (double)values[i] * den;
  144. return mu;
  145. }
  146. // Finds the sample standard deviation of an array
  147. template <typename T>
  148. static inline double ImStdDev(const T* values, int count) {
  149. double den = 1.0 / (count - 1.0);
  150. double mu = ImMean(values, count);
  151. double x = 0;
  152. for (int i = 0; i < count; ++i)
  153. x += ((double)values[i] - mu) * ((double)values[i] - mu) * den;
  154. return sqrt(x);
  155. }
  156. // Mix color a and b by factor s in [0 256]
  157. static inline ImU32 ImMixU32(ImU32 a, ImU32 b, ImU32 s) {
  158. #ifdef IMPLOT_MIX64
  159. const ImU32 af = 256-s;
  160. const ImU32 bf = s;
  161. const ImU64 al = (a & 0x00ff00ff) | (((ImU64)(a & 0xff00ff00)) << 24);
  162. const ImU64 bl = (b & 0x00ff00ff) | (((ImU64)(b & 0xff00ff00)) << 24);
  163. const ImU64 mix = (al * af + bl * bf);
  164. return ((mix >> 32) & 0xff00ff00) | ((mix & 0xff00ff00) >> 8);
  165. #else
  166. const ImU32 af = 256-s;
  167. const ImU32 bf = s;
  168. const ImU32 al = (a & 0x00ff00ff);
  169. const ImU32 ah = (a & 0xff00ff00) >> 8;
  170. const ImU32 bl = (b & 0x00ff00ff);
  171. const ImU32 bh = (b & 0xff00ff00) >> 8;
  172. const ImU32 ml = (al * af + bl * bf);
  173. const ImU32 mh = (ah * af + bh * bf);
  174. return (mh & 0xff00ff00) | ((ml & 0xff00ff00) >> 8);
  175. #endif
  176. }
  177. // Lerp across an array of 32-bit collors given t in [0.0 1.0]
  178. static inline ImU32 ImLerpU32(const ImU32* colors, int size, float t) {
  179. int i1 = (int)((size - 1 ) * t);
  180. int i2 = i1 + 1;
  181. if (i2 == size || size == 1)
  182. return colors[i1];
  183. float den = 1.0f / (size - 1);
  184. float t1 = i1 * den;
  185. float t2 = i2 * den;
  186. float tr = ImRemap01(t, t1, t2);
  187. return ImMixU32(colors[i1], colors[i2], (ImU32)(tr*256));
  188. }
  189. // Set alpha channel of 32-bit color from float in range [0.0 1.0]
  190. static inline ImU32 ImAlphaU32(ImU32 col, float alpha) {
  191. return col & ~((ImU32)((1.0f-alpha)*255)<<IM_COL32_A_SHIFT);
  192. }
  193. // Returns true of two ranges overlap
  194. template <typename T>
  195. static inline bool ImOverlaps(T min_a, T max_a, T min_b, T max_b) {
  196. return min_a <= max_b && min_b <= max_a;
  197. }
  198. //-----------------------------------------------------------------------------
  199. // [SECTION] ImPlot Enums
  200. //-----------------------------------------------------------------------------
  201. typedef int ImPlotTimeUnit; // -> enum ImPlotTimeUnit_
  202. typedef int ImPlotDateFmt; // -> enum ImPlotDateFmt_
  203. typedef int ImPlotTimeFmt; // -> enum ImPlotTimeFmt_
  204. enum ImPlotTimeUnit_ {
  205. ImPlotTimeUnit_Us, // microsecond
  206. ImPlotTimeUnit_Ms, // millisecond
  207. ImPlotTimeUnit_S, // second
  208. ImPlotTimeUnit_Min, // minute
  209. ImPlotTimeUnit_Hr, // hour
  210. ImPlotTimeUnit_Day, // day
  211. ImPlotTimeUnit_Mo, // month
  212. ImPlotTimeUnit_Yr, // year
  213. ImPlotTimeUnit_COUNT
  214. };
  215. enum ImPlotDateFmt_ { // default [ ISO 8601 ]
  216. ImPlotDateFmt_None = 0,
  217. ImPlotDateFmt_DayMo, // 10/3 [ --10-03 ]
  218. ImPlotDateFmt_DayMoYr, // 10/3/91 [ 1991-10-03 ]
  219. ImPlotDateFmt_MoYr, // Oct 1991 [ 1991-10 ]
  220. ImPlotDateFmt_Mo, // Oct [ --10 ]
  221. ImPlotDateFmt_Yr // 1991 [ 1991 ]
  222. };
  223. enum ImPlotTimeFmt_ { // default [ 24 Hour Clock ]
  224. ImPlotTimeFmt_None = 0,
  225. ImPlotTimeFmt_Us, // .428 552 [ .428 552 ]
  226. ImPlotTimeFmt_SUs, // :29.428 552 [ :29.428 552 ]
  227. ImPlotTimeFmt_SMs, // :29.428 [ :29.428 ]
  228. ImPlotTimeFmt_S, // :29 [ :29 ]
  229. ImPlotTimeFmt_MinSMs, // 21:29.428 [ 21:29.428 ]
  230. ImPlotTimeFmt_HrMinSMs, // 7:21:29.428pm [ 19:21:29.428 ]
  231. ImPlotTimeFmt_HrMinS, // 7:21:29pm [ 19:21:29 ]
  232. ImPlotTimeFmt_HrMin, // 7:21pm [ 19:21 ]
  233. ImPlotTimeFmt_Hr // 7pm [ 19:00 ]
  234. };
  235. //-----------------------------------------------------------------------------
  236. // [SECTION] Callbacks
  237. //-----------------------------------------------------------------------------
  238. typedef void (*ImPlotLocator)(ImPlotTicker& ticker, const ImPlotRange& range, float pixels, bool vertical, ImPlotFormatter formatter, void* formatter_data);
  239. //-----------------------------------------------------------------------------
  240. // [SECTION] Structs
  241. //-----------------------------------------------------------------------------
  242. // Combined date/time format spec
  243. struct ImPlotDateTimeSpec {
  244. ImPlotDateTimeSpec() {}
  245. ImPlotDateTimeSpec(ImPlotDateFmt date_fmt, ImPlotTimeFmt time_fmt, bool use_24_hr_clk = false, bool use_iso_8601 = false) {
  246. Date = date_fmt;
  247. Time = time_fmt;
  248. UseISO8601 = use_iso_8601;
  249. Use24HourClock = use_24_hr_clk;
  250. }
  251. ImPlotDateFmt Date;
  252. ImPlotTimeFmt Time;
  253. bool UseISO8601;
  254. bool Use24HourClock;
  255. };
  256. // Two part timestamp struct.
  257. struct ImPlotTime {
  258. time_t S; // second part
  259. int Us; // microsecond part
  260. ImPlotTime() { S = 0; Us = 0; }
  261. ImPlotTime(time_t s, int us = 0) { S = s + us / 1000000; Us = us % 1000000; }
  262. void RollOver() { S = S + Us / 1000000; Us = Us % 1000000; }
  263. double ToDouble() const { return (double)S + (double)Us / 1000000.0; }
  264. static ImPlotTime FromDouble(double t) { return ImPlotTime((time_t)t, (int)(t * 1000000 - floor(t) * 1000000)); }
  265. };
  266. static inline ImPlotTime operator+(const ImPlotTime& lhs, const ImPlotTime& rhs)
  267. { return ImPlotTime(lhs.S + rhs.S, lhs.Us + rhs.Us); }
  268. static inline ImPlotTime operator-(const ImPlotTime& lhs, const ImPlotTime& rhs)
  269. { return ImPlotTime(lhs.S - rhs.S, lhs.Us - rhs.Us); }
  270. static inline bool operator==(const ImPlotTime& lhs, const ImPlotTime& rhs)
  271. { return lhs.S == rhs.S && lhs.Us == rhs.Us; }
  272. static inline bool operator<(const ImPlotTime& lhs, const ImPlotTime& rhs)
  273. { return lhs.S == rhs.S ? lhs.Us < rhs.Us : lhs.S < rhs.S; }
  274. static inline bool operator>(const ImPlotTime& lhs, const ImPlotTime& rhs)
  275. { return rhs < lhs; }
  276. static inline bool operator<=(const ImPlotTime& lhs, const ImPlotTime& rhs)
  277. { return lhs < rhs || lhs == rhs; }
  278. static inline bool operator>=(const ImPlotTime& lhs, const ImPlotTime& rhs)
  279. { return lhs > rhs || lhs == rhs; }
  280. // Colormap data storage
  281. struct ImPlotColormapData {
  282. ImVector<ImU32> Keys;
  283. ImVector<int> KeyCounts;
  284. ImVector<int> KeyOffsets;
  285. ImVector<ImU32> Tables;
  286. ImVector<int> TableSizes;
  287. ImVector<int> TableOffsets;
  288. ImGuiTextBuffer Text;
  289. ImVector<int> TextOffsets;
  290. ImVector<bool> Quals;
  291. ImGuiStorage Map;
  292. int Count;
  293. ImPlotColormapData() { Count = 0; }
  294. int Append(const char* name, const ImU32* keys, int count, bool qual) {
  295. if (GetIndex(name) != -1)
  296. return -1;
  297. KeyOffsets.push_back(Keys.size());
  298. KeyCounts.push_back(count);
  299. Keys.reserve(Keys.size()+count);
  300. for (int i = 0; i < count; ++i)
  301. Keys.push_back(keys[i]);
  302. TextOffsets.push_back(Text.size());
  303. Text.append(name, name + strlen(name) + 1);
  304. Quals.push_back(qual);
  305. ImGuiID id = ImHashStr(name);
  306. int idx = Count++;
  307. Map.SetInt(id,idx);
  308. _AppendTable(idx);
  309. return idx;
  310. }
  311. void _AppendTable(ImPlotColormap cmap) {
  312. int key_count = GetKeyCount(cmap);
  313. const ImU32* keys = GetKeys(cmap);
  314. int off = Tables.size();
  315. TableOffsets.push_back(off);
  316. if (IsQual(cmap)) {
  317. Tables.reserve(key_count);
  318. for (int i = 0; i < key_count; ++i)
  319. Tables.push_back(keys[i]);
  320. TableSizes.push_back(key_count);
  321. }
  322. else {
  323. int max_size = 255 * (key_count-1) + 1;
  324. Tables.reserve(off + max_size);
  325. // ImU32 last = keys[0];
  326. // Tables.push_back(last);
  327. // int n = 1;
  328. for (int i = 0; i < key_count-1; ++i) {
  329. for (int s = 0; s < 255; ++s) {
  330. ImU32 a = keys[i];
  331. ImU32 b = keys[i+1];
  332. ImU32 c = ImMixU32(a,b,s);
  333. // if (c != last) {
  334. Tables.push_back(c);
  335. // last = c;
  336. // n++;
  337. // }
  338. }
  339. }
  340. ImU32 c = keys[key_count-1];
  341. // if (c != last) {
  342. Tables.push_back(c);
  343. // n++;
  344. // }
  345. // TableSizes.push_back(n);
  346. TableSizes.push_back(max_size);
  347. }
  348. }
  349. void RebuildTables() {
  350. Tables.resize(0);
  351. TableSizes.resize(0);
  352. TableOffsets.resize(0);
  353. for (int i = 0; i < Count; ++i)
  354. _AppendTable(i);
  355. }
  356. inline bool IsQual(ImPlotColormap cmap) const { return Quals[cmap]; }
  357. inline const char* GetName(ImPlotColormap cmap) const { return cmap < Count ? Text.Buf.Data + TextOffsets[cmap] : nullptr; }
  358. inline ImPlotColormap GetIndex(const char* name) const { ImGuiID key = ImHashStr(name); return Map.GetInt(key,-1); }
  359. inline const ImU32* GetKeys(ImPlotColormap cmap) const { return &Keys[KeyOffsets[cmap]]; }
  360. inline int GetKeyCount(ImPlotColormap cmap) const { return KeyCounts[cmap]; }
  361. inline ImU32 GetKeyColor(ImPlotColormap cmap, int idx) const { return Keys[KeyOffsets[cmap]+idx]; }
  362. inline void SetKeyColor(ImPlotColormap cmap, int idx, ImU32 value) { Keys[KeyOffsets[cmap]+idx] = value; RebuildTables(); }
  363. inline const ImU32* GetTable(ImPlotColormap cmap) const { return &Tables[TableOffsets[cmap]]; }
  364. inline int GetTableSize(ImPlotColormap cmap) const { return TableSizes[cmap]; }
  365. inline ImU32 GetTableColor(ImPlotColormap cmap, int idx) const { return Tables[TableOffsets[cmap]+idx]; }
  366. inline ImU32 LerpTable(ImPlotColormap cmap, float t) const {
  367. int off = TableOffsets[cmap];
  368. int siz = TableSizes[cmap];
  369. int idx = Quals[cmap] ? ImClamp((int)(siz*t),0,siz-1) : (int)((siz - 1) * t + 0.5f);
  370. return Tables[off + idx];
  371. }
  372. };
  373. // ImPlotPoint with positive/negative error values
  374. struct ImPlotPointError {
  375. double X, Y, Neg, Pos;
  376. ImPlotPointError(double x, double y, double neg, double pos) {
  377. X = x; Y = y; Neg = neg; Pos = pos;
  378. }
  379. };
  380. // Interior plot label/annotation
  381. struct ImPlotAnnotation {
  382. ImVec2 Pos;
  383. ImVec2 Offset;
  384. ImU32 ColorBg;
  385. ImU32 ColorFg;
  386. int TextOffset;
  387. bool Clamp;
  388. ImPlotAnnotation() {
  389. ColorBg = ColorFg = 0;
  390. TextOffset = 0;
  391. Clamp = false;
  392. }
  393. };
  394. // Collection of plot labels
  395. struct ImPlotAnnotationCollection {
  396. ImVector<ImPlotAnnotation> Annotations;
  397. ImGuiTextBuffer TextBuffer;
  398. int Size;
  399. ImPlotAnnotationCollection() { Reset(); }
  400. void AppendV(const ImVec2& pos, const ImVec2& off, ImU32 bg, ImU32 fg, bool clamp, const char* fmt, va_list args) IM_FMTLIST(7) {
  401. ImPlotAnnotation an;
  402. an.Pos = pos; an.Offset = off;
  403. an.ColorBg = bg; an.ColorFg = fg;
  404. an.TextOffset = TextBuffer.size();
  405. an.Clamp = clamp;
  406. Annotations.push_back(an);
  407. TextBuffer.appendfv(fmt, args);
  408. const char nul[] = "";
  409. TextBuffer.append(nul,nul+1);
  410. Size++;
  411. }
  412. void Append(const ImVec2& pos, const ImVec2& off, ImU32 bg, ImU32 fg, bool clamp, const char* fmt, ...) IM_FMTARGS(7) {
  413. va_list args;
  414. va_start(args, fmt);
  415. AppendV(pos, off, bg, fg, clamp, fmt, args);
  416. va_end(args);
  417. }
  418. const char* GetText(int idx) {
  419. return TextBuffer.Buf.Data + Annotations[idx].TextOffset;
  420. }
  421. void Reset() {
  422. Annotations.shrink(0);
  423. TextBuffer.Buf.shrink(0);
  424. Size = 0;
  425. }
  426. };
  427. struct ImPlotTag {
  428. ImAxis Axis;
  429. double Value;
  430. ImU32 ColorBg;
  431. ImU32 ColorFg;
  432. int TextOffset;
  433. };
  434. struct ImPlotTagCollection {
  435. ImVector<ImPlotTag> Tags;
  436. ImGuiTextBuffer TextBuffer;
  437. int Size;
  438. ImPlotTagCollection() { Reset(); }
  439. void AppendV(ImAxis axis, double value, ImU32 bg, ImU32 fg, const char* fmt, va_list args) IM_FMTLIST(6) {
  440. ImPlotTag tag;
  441. tag.Axis = axis;
  442. tag.Value = value;
  443. tag.ColorBg = bg;
  444. tag.ColorFg = fg;
  445. tag.TextOffset = TextBuffer.size();
  446. Tags.push_back(tag);
  447. TextBuffer.appendfv(fmt, args);
  448. const char nul[] = "";
  449. TextBuffer.append(nul,nul+1);
  450. Size++;
  451. }
  452. void Append(ImAxis axis, double value, ImU32 bg, ImU32 fg, const char* fmt, ...) IM_FMTARGS(6) {
  453. va_list args;
  454. va_start(args, fmt);
  455. AppendV(axis, value, bg, fg, fmt, args);
  456. va_end(args);
  457. }
  458. const char* GetText(int idx) {
  459. return TextBuffer.Buf.Data + Tags[idx].TextOffset;
  460. }
  461. void Reset() {
  462. Tags.shrink(0);
  463. TextBuffer.Buf.shrink(0);
  464. Size = 0;
  465. }
  466. };
  467. // Tick mark info
  468. struct ImPlotTick
  469. {
  470. double PlotPos;
  471. float PixelPos;
  472. ImVec2 LabelSize;
  473. int TextOffset;
  474. bool Major;
  475. bool ShowLabel;
  476. int Level;
  477. int Idx;
  478. ImPlotTick(double value, bool major, int level, bool show_label) {
  479. PixelPos = 0;
  480. PlotPos = value;
  481. Major = major;
  482. ShowLabel = show_label;
  483. Level = level;
  484. TextOffset = -1;
  485. }
  486. };
  487. // Collection of ticks
  488. struct ImPlotTicker {
  489. ImVector<ImPlotTick> Ticks;
  490. ImGuiTextBuffer TextBuffer;
  491. ImVec2 MaxSize;
  492. ImVec2 LateSize;
  493. int Levels;
  494. ImPlotTicker() {
  495. Reset();
  496. }
  497. ImPlotTick& AddTick(double value, bool major, int level, bool show_label, const char* label) {
  498. ImPlotTick tick(value, major, level, show_label);
  499. if (show_label && label != nullptr) {
  500. tick.TextOffset = TextBuffer.size();
  501. TextBuffer.append(label, label + strlen(label) + 1);
  502. tick.LabelSize = ImGui::CalcTextSize(TextBuffer.Buf.Data + tick.TextOffset);
  503. }
  504. return AddTick(tick);
  505. }
  506. ImPlotTick& AddTick(double value, bool major, int level, bool show_label, ImPlotFormatter formatter, void* data) {
  507. ImPlotTick tick(value, major, level, show_label);
  508. if (show_label && formatter != nullptr) {
  509. char buff[IMPLOT_LABEL_MAX_SIZE];
  510. tick.TextOffset = TextBuffer.size();
  511. formatter(tick.PlotPos, buff, sizeof(buff), data);
  512. TextBuffer.append(buff, buff + strlen(buff) + 1);
  513. tick.LabelSize = ImGui::CalcTextSize(TextBuffer.Buf.Data + tick.TextOffset);
  514. }
  515. return AddTick(tick);
  516. }
  517. inline ImPlotTick& AddTick(ImPlotTick tick) {
  518. if (tick.ShowLabel) {
  519. MaxSize.x = tick.LabelSize.x > MaxSize.x ? tick.LabelSize.x : MaxSize.x;
  520. MaxSize.y = tick.LabelSize.y > MaxSize.y ? tick.LabelSize.y : MaxSize.y;
  521. }
  522. tick.Idx = Ticks.size();
  523. Ticks.push_back(tick);
  524. return Ticks.back();
  525. }
  526. const char* GetText(int idx) const {
  527. return TextBuffer.Buf.Data + Ticks[idx].TextOffset;
  528. }
  529. const char* GetText(const ImPlotTick& tick) {
  530. return GetText(tick.Idx);
  531. }
  532. void OverrideSizeLate(const ImVec2& size) {
  533. LateSize.x = size.x > LateSize.x ? size.x : LateSize.x;
  534. LateSize.y = size.y > LateSize.y ? size.y : LateSize.y;
  535. }
  536. void Reset() {
  537. Ticks.shrink(0);
  538. TextBuffer.Buf.shrink(0);
  539. MaxSize = LateSize;
  540. LateSize = ImVec2(0,0);
  541. Levels = 1;
  542. }
  543. int TickCount() const {
  544. return Ticks.Size;
  545. }
  546. };
  547. // Axis state information that must persist after EndPlot
  548. struct ImPlotAxis
  549. {
  550. ImGuiID ID;
  551. ImPlotAxisFlags Flags;
  552. ImPlotAxisFlags PreviousFlags;
  553. ImPlotRange Range;
  554. ImPlotCond RangeCond;
  555. ImPlotScale Scale;
  556. ImPlotRange FitExtents;
  557. ImPlotAxis* OrthoAxis;
  558. ImPlotRange ConstraintRange;
  559. ImPlotRange ConstraintZoom;
  560. ImPlotTicker Ticker;
  561. ImPlotFormatter Formatter;
  562. void* FormatterData;
  563. char FormatSpec[16];
  564. ImPlotLocator Locator;
  565. double* LinkedMin;
  566. double* LinkedMax;
  567. int PickerLevel;
  568. ImPlotTime PickerTimeMin, PickerTimeMax;
  569. ImPlotTransform TransformForward;
  570. ImPlotTransform TransformInverse;
  571. void* TransformData;
  572. float PixelMin, PixelMax;
  573. double ScaleMin, ScaleMax;
  574. double ScaleToPixel;
  575. float Datum1, Datum2;
  576. ImRect HoverRect;
  577. int LabelOffset;
  578. ImU32 ColorMaj, ColorMin, ColorTick, ColorTxt, ColorBg, ColorHov, ColorAct, ColorHiLi;
  579. bool Enabled;
  580. bool Vertical;
  581. bool FitThisFrame;
  582. bool HasRange;
  583. bool HasFormatSpec;
  584. bool ShowDefaultTicks;
  585. bool Hovered;
  586. bool Held;
  587. ImPlotAxis() {
  588. ID = 0;
  589. Flags = PreviousFlags = ImPlotAxisFlags_None;
  590. Range.Min = 0;
  591. Range.Max = 1;
  592. Scale = ImPlotScale_Linear;
  593. TransformForward = TransformInverse = nullptr;
  594. TransformData = nullptr;
  595. FitExtents.Min = HUGE_VAL;
  596. FitExtents.Max = -HUGE_VAL;
  597. OrthoAxis = nullptr;
  598. ConstraintRange = ImPlotRange(-INFINITY,INFINITY);
  599. ConstraintZoom = ImPlotRange(DBL_MIN,INFINITY);
  600. LinkedMin = LinkedMax = nullptr;
  601. PickerLevel = 0;
  602. Datum1 = Datum2 = 0;
  603. PixelMin = PixelMax = 0;
  604. LabelOffset = -1;
  605. ColorMaj = ColorMin = ColorTick = ColorTxt = ColorBg = ColorHov = ColorAct = 0;
  606. ColorHiLi = IM_COL32_BLACK_TRANS;
  607. Formatter = nullptr;
  608. FormatterData = nullptr;
  609. Locator = nullptr;
  610. Enabled = Hovered = Held = FitThisFrame = HasRange = HasFormatSpec = false;
  611. ShowDefaultTicks = true;
  612. }
  613. inline void Reset() {
  614. Enabled = false;
  615. Scale = ImPlotScale_Linear;
  616. TransformForward = TransformInverse = nullptr;
  617. TransformData = nullptr;
  618. LabelOffset = -1;
  619. HasFormatSpec = false;
  620. Formatter = nullptr;
  621. FormatterData = nullptr;
  622. Locator = nullptr;
  623. ShowDefaultTicks = true;
  624. FitThisFrame = false;
  625. FitExtents.Min = HUGE_VAL;
  626. FitExtents.Max = -HUGE_VAL;
  627. OrthoAxis = nullptr;
  628. ConstraintRange = ImPlotRange(-INFINITY,INFINITY);
  629. ConstraintZoom = ImPlotRange(DBL_MIN,INFINITY);
  630. Ticker.Reset();
  631. }
  632. inline bool SetMin(double _min, bool force=false) {
  633. if (!force && IsLockedMin())
  634. return false;
  635. _min = ImConstrainNan(ImConstrainInf(_min));
  636. if (_min < ConstraintRange.Min)
  637. _min = ConstraintRange.Min;
  638. double z = Range.Max - _min;
  639. if (z < ConstraintZoom.Min)
  640. _min = Range.Max - ConstraintZoom.Min;
  641. if (z > ConstraintZoom.Max)
  642. _min = Range.Max - ConstraintZoom.Max;
  643. if (_min >= Range.Max)
  644. return false;
  645. Range.Min = _min;
  646. PickerTimeMin = ImPlotTime::FromDouble(Range.Min);
  647. UpdateTransformCache();
  648. return true;
  649. };
  650. inline bool SetMax(double _max, bool force=false) {
  651. if (!force && IsLockedMax())
  652. return false;
  653. _max = ImConstrainNan(ImConstrainInf(_max));
  654. if (_max > ConstraintRange.Max)
  655. _max = ConstraintRange.Max;
  656. double z = _max - Range.Min;
  657. if (z < ConstraintZoom.Min)
  658. _max = Range.Min + ConstraintZoom.Min;
  659. if (z > ConstraintZoom.Max)
  660. _max = Range.Min + ConstraintZoom.Max;
  661. if (_max <= Range.Min)
  662. return false;
  663. Range.Max = _max;
  664. PickerTimeMax = ImPlotTime::FromDouble(Range.Max);
  665. UpdateTransformCache();
  666. return true;
  667. };
  668. inline void SetRange(double v1, double v2) {
  669. Range.Min = ImMin(v1,v2);
  670. Range.Max = ImMax(v1,v2);
  671. Constrain();
  672. PickerTimeMin = ImPlotTime::FromDouble(Range.Min);
  673. PickerTimeMax = ImPlotTime::FromDouble(Range.Max);
  674. UpdateTransformCache();
  675. }
  676. inline void SetRange(const ImPlotRange& range) {
  677. SetRange(range.Min, range.Max);
  678. }
  679. inline void SetAspect(double unit_per_pix) {
  680. double new_size = unit_per_pix * PixelSize();
  681. double delta = (new_size - Range.Size()) * 0.5;
  682. if (IsLocked())
  683. return;
  684. else if (IsLockedMin() && !IsLockedMax())
  685. SetRange(Range.Min, Range.Max + 2*delta);
  686. else if (!IsLockedMin() && IsLockedMax())
  687. SetRange(Range.Min - 2*delta, Range.Max);
  688. else
  689. SetRange(Range.Min - delta, Range.Max + delta);
  690. }
  691. inline float PixelSize() const { return ImAbs(PixelMax - PixelMin); }
  692. inline double GetAspect() const { return Range.Size() / PixelSize(); }
  693. inline void Constrain() {
  694. Range.Min = ImConstrainNan(ImConstrainInf(Range.Min));
  695. Range.Max = ImConstrainNan(ImConstrainInf(Range.Max));
  696. if (Range.Min < ConstraintRange.Min)
  697. Range.Min = ConstraintRange.Min;
  698. if (Range.Max > ConstraintRange.Max)
  699. Range.Max = ConstraintRange.Max;
  700. double z = Range.Size();
  701. if (z < ConstraintZoom.Min) {
  702. double delta = (ConstraintZoom.Min - z) * 0.5;
  703. Range.Min -= delta;
  704. Range.Max += delta;
  705. }
  706. if (z > ConstraintZoom.Max) {
  707. double delta = (z - ConstraintZoom.Max) * 0.5;
  708. Range.Min += delta;
  709. Range.Max -= delta;
  710. }
  711. if (Range.Max <= Range.Min)
  712. Range.Max = Range.Min + DBL_EPSILON;
  713. }
  714. inline void UpdateTransformCache() {
  715. ScaleToPixel = (PixelMax - PixelMin) / Range.Size();
  716. if (TransformForward != nullptr) {
  717. ScaleMin = TransformForward(Range.Min, TransformData);
  718. ScaleMax = TransformForward(Range.Max, TransformData);
  719. }
  720. else {
  721. ScaleMin = Range.Min;
  722. ScaleMax = Range.Max;
  723. }
  724. }
  725. inline float PlotToPixels(double plt) const {
  726. if (TransformForward != nullptr) {
  727. double s = TransformForward(plt, TransformData);
  728. double t = (s - ScaleMin) / (ScaleMax - ScaleMin);
  729. plt = Range.Min + Range.Size() * t;
  730. }
  731. return (float)(PixelMin + ScaleToPixel * (plt - Range.Min));
  732. }
  733. inline double PixelsToPlot(float pix) const {
  734. double plt = (pix - PixelMin) / ScaleToPixel + Range.Min;
  735. if (TransformInverse != nullptr) {
  736. double t = (plt - Range.Min) / Range.Size();
  737. double s = t * (ScaleMax - ScaleMin) + ScaleMin;
  738. plt = TransformInverse(s, TransformData);
  739. }
  740. return plt;
  741. }
  742. inline void ExtendFit(double v) {
  743. if (!ImNanOrInf(v) && v >= ConstraintRange.Min && v <= ConstraintRange.Max) {
  744. FitExtents.Min = v < FitExtents.Min ? v : FitExtents.Min;
  745. FitExtents.Max = v > FitExtents.Max ? v : FitExtents.Max;
  746. }
  747. }
  748. inline void ExtendFitWith(ImPlotAxis& alt, double v, double v_alt) {
  749. if (ImHasFlag(Flags, ImPlotAxisFlags_RangeFit) && !alt.Range.Contains(v_alt))
  750. return;
  751. if (!ImNanOrInf(v) && v >= ConstraintRange.Min && v <= ConstraintRange.Max) {
  752. FitExtents.Min = v < FitExtents.Min ? v : FitExtents.Min;
  753. FitExtents.Max = v > FitExtents.Max ? v : FitExtents.Max;
  754. }
  755. }
  756. inline void ApplyFit(float padding) {
  757. const double ext_size = FitExtents.Size() * 0.5;
  758. FitExtents.Min -= ext_size * padding;
  759. FitExtents.Max += ext_size * padding;
  760. if (!IsLockedMin() && !ImNanOrInf(FitExtents.Min))
  761. Range.Min = FitExtents.Min;
  762. if (!IsLockedMax() && !ImNanOrInf(FitExtents.Max))
  763. Range.Max = FitExtents.Max;
  764. if (ImAlmostEqual(Range.Min, Range.Max)) {
  765. Range.Max += 0.5;
  766. Range.Min -= 0.5;
  767. }
  768. Constrain();
  769. UpdateTransformCache();
  770. }
  771. inline bool HasLabel() const { return LabelOffset != -1 && !ImHasFlag(Flags, ImPlotAxisFlags_NoLabel); }
  772. inline bool HasGridLines() const { return !ImHasFlag(Flags, ImPlotAxisFlags_NoGridLines); }
  773. inline bool HasTickLabels() const { return !ImHasFlag(Flags, ImPlotAxisFlags_NoTickLabels); }
  774. inline bool HasTickMarks() const { return !ImHasFlag(Flags, ImPlotAxisFlags_NoTickMarks); }
  775. inline bool WillRender() const { return Enabled && (HasGridLines() || HasTickLabels() || HasTickMarks()); }
  776. inline bool IsOpposite() const { return ImHasFlag(Flags, ImPlotAxisFlags_Opposite); }
  777. inline bool IsInverted() const { return ImHasFlag(Flags, ImPlotAxisFlags_Invert); }
  778. inline bool IsForeground() const { return ImHasFlag(Flags, ImPlotAxisFlags_Foreground); }
  779. inline bool IsAutoFitting() const { return ImHasFlag(Flags, ImPlotAxisFlags_AutoFit); }
  780. inline bool CanInitFit() const { return !ImHasFlag(Flags, ImPlotAxisFlags_NoInitialFit) && !HasRange && !LinkedMin && !LinkedMax; }
  781. inline bool IsRangeLocked() const { return HasRange && RangeCond == ImPlotCond_Always; }
  782. inline bool IsLockedMin() const { return !Enabled || IsRangeLocked() || ImHasFlag(Flags, ImPlotAxisFlags_LockMin); }
  783. inline bool IsLockedMax() const { return !Enabled || IsRangeLocked() || ImHasFlag(Flags, ImPlotAxisFlags_LockMax); }
  784. inline bool IsLocked() const { return IsLockedMin() && IsLockedMax(); }
  785. inline bool IsInputLockedMin() const { return IsLockedMin() || IsAutoFitting(); }
  786. inline bool IsInputLockedMax() const { return IsLockedMax() || IsAutoFitting(); }
  787. inline bool IsInputLocked() const { return IsLocked() || IsAutoFitting(); }
  788. inline bool HasMenus() const { return !ImHasFlag(Flags, ImPlotAxisFlags_NoMenus); }
  789. inline bool IsPanLocked(bool increasing) {
  790. if (ImHasFlag(Flags, ImPlotAxisFlags_PanStretch)) {
  791. return IsInputLocked();
  792. }
  793. else {
  794. if (IsLockedMin() || IsLockedMax() || IsAutoFitting())
  795. return false;
  796. if (increasing)
  797. return Range.Max == ConstraintRange.Max;
  798. else
  799. return Range.Min == ConstraintRange.Min;
  800. }
  801. }
  802. void PushLinks() {
  803. if (LinkedMin) { *LinkedMin = Range.Min; }
  804. if (LinkedMax) { *LinkedMax = Range.Max; }
  805. }
  806. void PullLinks() {
  807. if (LinkedMin && LinkedMax) { SetRange(*LinkedMin, *LinkedMax); }
  808. else if (LinkedMin) { SetMin(*LinkedMin,true); }
  809. else if (LinkedMax) { SetMax(*LinkedMax,true); }
  810. }
  811. };
  812. // Align plots group data
  813. struct ImPlotAlignmentData {
  814. bool Vertical;
  815. float PadA;
  816. float PadB;
  817. float PadAMax;
  818. float PadBMax;
  819. ImPlotAlignmentData() {
  820. Vertical = true;
  821. PadA = PadB = PadAMax = PadBMax = 0;
  822. }
  823. void Begin() { PadAMax = PadBMax = 0; }
  824. void Update(float& pad_a, float& pad_b, float& delta_a, float& delta_b) {
  825. float bak_a = pad_a; float bak_b = pad_b;
  826. if (PadAMax < pad_a) { PadAMax = pad_a; }
  827. if (PadBMax < pad_b) { PadBMax = pad_b; }
  828. if (pad_a < PadA) { pad_a = PadA; delta_a = pad_a - bak_a; } else { delta_a = 0; }
  829. if (pad_b < PadB) { pad_b = PadB; delta_b = pad_b - bak_b; } else { delta_b = 0; }
  830. }
  831. void End() { PadA = PadAMax; PadB = PadBMax; }
  832. void Reset() { PadA = PadB = PadAMax = PadBMax = 0; }
  833. };
  834. // State information for Plot items
  835. struct ImPlotItem
  836. {
  837. ImGuiID ID;
  838. ImU32 Color;
  839. ImRect LegendHoverRect;
  840. int NameOffset;
  841. bool Show;
  842. bool LegendHovered;
  843. bool SeenThisFrame;
  844. ImPlotItem() {
  845. ID = 0;
  846. Color = IM_COL32_WHITE;
  847. NameOffset = -1;
  848. Show = true;
  849. SeenThisFrame = false;
  850. LegendHovered = false;
  851. }
  852. ~ImPlotItem() { ID = 0; }
  853. };
  854. // Holds Legend state
  855. struct ImPlotLegend
  856. {
  857. ImPlotLegendFlags Flags;
  858. ImPlotLegendFlags PreviousFlags;
  859. ImPlotLocation Location;
  860. ImPlotLocation PreviousLocation;
  861. ImVec2 Scroll;
  862. ImVector<int> Indices;
  863. ImGuiTextBuffer Labels;
  864. ImRect Rect;
  865. ImRect RectClamped;
  866. bool Hovered;
  867. bool Held;
  868. bool CanGoInside;
  869. ImPlotLegend() {
  870. Flags = PreviousFlags = ImPlotLegendFlags_None;
  871. CanGoInside = true;
  872. Hovered = Held = false;
  873. Location = PreviousLocation = ImPlotLocation_NorthWest;
  874. Scroll = ImVec2(0,0);
  875. }
  876. void Reset() { Indices.shrink(0); Labels.Buf.shrink(0); }
  877. };
  878. // Holds Items and Legend data
  879. struct ImPlotItemGroup
  880. {
  881. ImGuiID ID;
  882. ImPlotLegend Legend;
  883. ImPool<ImPlotItem> ItemPool;
  884. int ColormapIdx;
  885. ImPlotItemGroup() { ID = 0; ColormapIdx = 0; }
  886. int GetItemCount() const { return ItemPool.GetBufSize(); }
  887. ImGuiID GetItemID(const char* label_id) { return ImGui::GetID(label_id); /* GetIDWithSeed */ }
  888. ImPlotItem* GetItem(ImGuiID id) { return ItemPool.GetByKey(id); }
  889. ImPlotItem* GetItem(const char* label_id) { return GetItem(GetItemID(label_id)); }
  890. ImPlotItem* GetOrAddItem(ImGuiID id) { return ItemPool.GetOrAddByKey(id); }
  891. ImPlotItem* GetItemByIndex(int i) { return ItemPool.GetByIndex(i); }
  892. int GetItemIndex(ImPlotItem* item) { return ItemPool.GetIndex(item); }
  893. int GetLegendCount() const { return Legend.Indices.size(); }
  894. ImPlotItem* GetLegendItem(int i) { return ItemPool.GetByIndex(Legend.Indices[i]); }
  895. const char* GetLegendLabel(int i) { return Legend.Labels.Buf.Data + GetLegendItem(i)->NameOffset; }
  896. void Reset() { ItemPool.Clear(); Legend.Reset(); ColormapIdx = 0; }
  897. };
  898. // Holds Plot state information that must persist after EndPlot
  899. struct ImPlotPlot
  900. {
  901. ImGuiID ID;
  902. ImPlotFlags Flags;
  903. ImPlotFlags PreviousFlags;
  904. ImPlotLocation MouseTextLocation;
  905. ImPlotMouseTextFlags MouseTextFlags;
  906. ImPlotAxis Axes[ImAxis_COUNT];
  907. ImGuiTextBuffer TextBuffer;
  908. ImPlotItemGroup Items;
  909. ImAxis CurrentX;
  910. ImAxis CurrentY;
  911. ImRect FrameRect;
  912. ImRect CanvasRect;
  913. ImRect PlotRect;
  914. ImRect AxesRect;
  915. ImRect SelectRect;
  916. ImVec2 SelectStart;
  917. int TitleOffset;
  918. bool JustCreated;
  919. bool Initialized;
  920. bool SetupLocked;
  921. bool FitThisFrame;
  922. bool Hovered;
  923. bool Held;
  924. bool Selecting;
  925. bool Selected;
  926. bool ContextLocked;
  927. ImPlotPlot() {
  928. Flags = PreviousFlags = ImPlotFlags_None;
  929. for (int i = 0; i < IMPLOT_NUM_X_AXES; ++i)
  930. XAxis(i).Vertical = false;
  931. for (int i = 0; i < IMPLOT_NUM_Y_AXES; ++i)
  932. YAxis(i).Vertical = true;
  933. SelectStart = ImVec2(0,0);
  934. CurrentX = ImAxis_X1;
  935. CurrentY = ImAxis_Y1;
  936. MouseTextLocation = ImPlotLocation_South | ImPlotLocation_East;
  937. MouseTextFlags = ImPlotMouseTextFlags_None;
  938. TitleOffset = -1;
  939. JustCreated = true;
  940. Initialized = SetupLocked = FitThisFrame = false;
  941. Hovered = Held = Selected = Selecting = ContextLocked = false;
  942. }
  943. inline bool IsInputLocked() const {
  944. for (int i = 0; i < IMPLOT_NUM_X_AXES; ++i) {
  945. if (!XAxis(i).IsInputLocked())
  946. return false;
  947. }
  948. for (int i = 0; i < IMPLOT_NUM_Y_AXES; ++i) {
  949. if (!YAxis(i).IsInputLocked())
  950. return false;
  951. }
  952. return true;
  953. }
  954. inline void ClearTextBuffer() { TextBuffer.Buf.shrink(0); }
  955. inline void SetTitle(const char* title) {
  956. if (title && ImGui::FindRenderedTextEnd(title, nullptr) != title) {
  957. TitleOffset = TextBuffer.size();
  958. TextBuffer.append(title, title + strlen(title) + 1);
  959. }
  960. else {
  961. TitleOffset = -1;
  962. }
  963. }
  964. inline bool HasTitle() const { return TitleOffset != -1 && !ImHasFlag(Flags, ImPlotFlags_NoTitle); }
  965. inline const char* GetTitle() const { return TextBuffer.Buf.Data + TitleOffset; }
  966. inline ImPlotAxis& XAxis(int i) { return Axes[ImAxis_X1 + i]; }
  967. inline const ImPlotAxis& XAxis(int i) const { return Axes[ImAxis_X1 + i]; }
  968. inline ImPlotAxis& YAxis(int i) { return Axes[ImAxis_Y1 + i]; }
  969. inline const ImPlotAxis& YAxis(int i) const { return Axes[ImAxis_Y1 + i]; }
  970. inline int EnabledAxesX() {
  971. int cnt = 0;
  972. for (int i = 0; i < IMPLOT_NUM_X_AXES; ++i)
  973. cnt += XAxis(i).Enabled;
  974. return cnt;
  975. }
  976. inline int EnabledAxesY() {
  977. int cnt = 0;
  978. for (int i = 0; i < IMPLOT_NUM_Y_AXES; ++i)
  979. cnt += YAxis(i).Enabled;
  980. return cnt;
  981. }
  982. inline void SetAxisLabel(ImPlotAxis& axis, const char* label) {
  983. if (label && ImGui::FindRenderedTextEnd(label, nullptr) != label) {
  984. axis.LabelOffset = TextBuffer.size();
  985. TextBuffer.append(label, label + strlen(label) + 1);
  986. }
  987. else {
  988. axis.LabelOffset = -1;
  989. }
  990. }
  991. inline const char* GetAxisLabel(const ImPlotAxis& axis) const { return TextBuffer.Buf.Data + axis.LabelOffset; }
  992. };
  993. // Holds subplot data that must persist after EndSubplot
  994. struct ImPlotSubplot {
  995. ImGuiID ID;
  996. ImPlotSubplotFlags Flags;
  997. ImPlotSubplotFlags PreviousFlags;
  998. ImPlotItemGroup Items;
  999. int Rows;
  1000. int Cols;
  1001. int CurrentIdx;
  1002. ImRect FrameRect;
  1003. ImRect GridRect;
  1004. ImVec2 CellSize;
  1005. ImVector<ImPlotAlignmentData> RowAlignmentData;
  1006. ImVector<ImPlotAlignmentData> ColAlignmentData;
  1007. ImVector<float> RowRatios;
  1008. ImVector<float> ColRatios;
  1009. ImVector<ImPlotRange> RowLinkData;
  1010. ImVector<ImPlotRange> ColLinkData;
  1011. float TempSizes[2];
  1012. bool FrameHovered;
  1013. bool HasTitle;
  1014. ImPlotSubplot() {
  1015. ID = 0;
  1016. Flags = PreviousFlags = ImPlotSubplotFlags_None;
  1017. Rows = Cols = CurrentIdx = 0;
  1018. Items.Legend.Location = ImPlotLocation_North;
  1019. Items.Legend.Flags = ImPlotLegendFlags_Horizontal|ImPlotLegendFlags_Outside;
  1020. Items.Legend.CanGoInside = false;
  1021. TempSizes[0] = TempSizes[1] = 0;
  1022. FrameHovered = false;
  1023. HasTitle = false;
  1024. }
  1025. };
  1026. // Temporary data storage for upcoming plot
  1027. struct ImPlotNextPlotData
  1028. {
  1029. ImPlotCond RangeCond[ImAxis_COUNT];
  1030. ImPlotRange Range[ImAxis_COUNT];
  1031. bool HasRange[ImAxis_COUNT];
  1032. bool Fit[ImAxis_COUNT];
  1033. double* LinkedMin[ImAxis_COUNT];
  1034. double* LinkedMax[ImAxis_COUNT];
  1035. ImPlotNextPlotData() { Reset(); }
  1036. void Reset() {
  1037. for (int i = 0; i < ImAxis_COUNT; ++i) {
  1038. HasRange[i] = false;
  1039. Fit[i] = false;
  1040. LinkedMin[i] = LinkedMax[i] = nullptr;
  1041. }
  1042. }
  1043. };
  1044. // Temporary data storage for upcoming item
  1045. struct ImPlotNextItemData {
  1046. ImVec4 Colors[5]; // ImPlotCol_Line, ImPlotCol_Fill, ImPlotCol_MarkerOutline, ImPlotCol_MarkerFill, ImPlotCol_ErrorBar
  1047. float LineWeight;
  1048. ImPlotMarker Marker;
  1049. float MarkerSize;
  1050. float MarkerWeight;
  1051. float FillAlpha;
  1052. float ErrorBarSize;
  1053. float ErrorBarWeight;
  1054. float DigitalBitHeight;
  1055. float DigitalBitGap;
  1056. bool RenderLine;
  1057. bool RenderFill;
  1058. bool RenderMarkerLine;
  1059. bool RenderMarkerFill;
  1060. bool HasHidden;
  1061. bool Hidden;
  1062. ImPlotCond HiddenCond;
  1063. ImPlotNextItemData() { Reset(); }
  1064. void Reset() {
  1065. for (int i = 0; i < 5; ++i)
  1066. Colors[i] = IMPLOT_AUTO_COL;
  1067. LineWeight = MarkerSize = MarkerWeight = FillAlpha = ErrorBarSize = ErrorBarWeight = DigitalBitHeight = DigitalBitGap = IMPLOT_AUTO;
  1068. Marker = IMPLOT_AUTO;
  1069. HasHidden = Hidden = false;
  1070. }
  1071. };
  1072. // Holds state information that must persist between calls to BeginPlot()/EndPlot()
  1073. struct ImPlotContext {
  1074. // Plot States
  1075. ImPool<ImPlotPlot> Plots;
  1076. ImPool<ImPlotSubplot> Subplots;
  1077. ImPlotPlot* CurrentPlot;
  1078. ImPlotSubplot* CurrentSubplot;
  1079. ImPlotItemGroup* CurrentItems;
  1080. ImPlotItem* CurrentItem;
  1081. ImPlotItem* PreviousItem;
  1082. // Tick Marks and Labels
  1083. ImPlotTicker CTicker;
  1084. // Annotation and Tabs
  1085. ImPlotAnnotationCollection Annotations;
  1086. ImPlotTagCollection Tags;
  1087. // Style and Colormaps
  1088. ImPlotStyle Style;
  1089. ImVector<ImGuiColorMod> ColorModifiers;
  1090. ImVector<ImGuiStyleMod> StyleModifiers;
  1091. ImPlotColormapData ColormapData;
  1092. ImVector<ImPlotColormap> ColormapModifiers;
  1093. // Time
  1094. tm Tm;
  1095. // Temp data for general use
  1096. ImVector<double> TempDouble1, TempDouble2;
  1097. ImVector<int> TempInt1;
  1098. // Misc
  1099. int DigitalPlotItemCnt;
  1100. int DigitalPlotOffset;
  1101. ImPlotNextPlotData NextPlotData;
  1102. ImPlotNextItemData NextItemData;
  1103. ImPlotInputMap InputMap;
  1104. bool OpenContextThisFrame;
  1105. ImGuiTextBuffer MousePosStringBuilder;
  1106. ImPlotItemGroup* SortItems;
  1107. // Align plots
  1108. ImPool<ImPlotAlignmentData> AlignmentData;
  1109. ImPlotAlignmentData* CurrentAlignmentH;
  1110. ImPlotAlignmentData* CurrentAlignmentV;
  1111. };
  1112. //-----------------------------------------------------------------------------
  1113. // [SECTION] Internal API
  1114. // No guarantee of forward compatibility here!
  1115. //-----------------------------------------------------------------------------
  1116. namespace ImPlot {
  1117. //-----------------------------------------------------------------------------
  1118. // [SECTION] Context Utils
  1119. //-----------------------------------------------------------------------------
  1120. // Initializes an ImPlotContext
  1121. IMPLOT_API void Initialize(ImPlotContext* ctx);
  1122. // Resets an ImPlot context for the next call to BeginPlot
  1123. IMPLOT_API void ResetCtxForNextPlot(ImPlotContext* ctx);
  1124. // Resets an ImPlot context for the next call to BeginAlignedPlots
  1125. IMPLOT_API void ResetCtxForNextAlignedPlots(ImPlotContext* ctx);
  1126. // Resets an ImPlot context for the next call to BeginSubplot
  1127. IMPLOT_API void ResetCtxForNextSubplot(ImPlotContext* ctx);
  1128. //-----------------------------------------------------------------------------
  1129. // [SECTION] Plot Utils
  1130. //-----------------------------------------------------------------------------
  1131. // Gets a plot from the current ImPlotContext
  1132. IMPLOT_API ImPlotPlot* GetPlot(const char* title);
  1133. // Gets the current plot from the current ImPlotContext
  1134. IMPLOT_API ImPlotPlot* GetCurrentPlot();
  1135. // Busts the cache for every plot in the current context
  1136. IMPLOT_API void BustPlotCache();
  1137. // Shows a plot's context menu.
  1138. IMPLOT_API void ShowPlotContextMenu(ImPlotPlot& plot);
  1139. //-----------------------------------------------------------------------------
  1140. // [SECTION] Setup Utils
  1141. //-----------------------------------------------------------------------------
  1142. // Lock Setup and call SetupFinish if necessary.
  1143. static inline void SetupLock() {
  1144. ImPlotContext& gp = *GImPlot;
  1145. if (!gp.CurrentPlot->SetupLocked)
  1146. SetupFinish();
  1147. gp.CurrentPlot->SetupLocked = true;
  1148. }
  1149. //-----------------------------------------------------------------------------
  1150. // [SECTION] Subplot Utils
  1151. //-----------------------------------------------------------------------------
  1152. // Advances to next subplot
  1153. IMPLOT_API void SubplotNextCell();
  1154. // Shows a subplot's context menu.
  1155. IMPLOT_API void ShowSubplotsContextMenu(ImPlotSubplot& subplot);
  1156. //-----------------------------------------------------------------------------
  1157. // [SECTION] Item Utils
  1158. //-----------------------------------------------------------------------------
  1159. // Begins a new item. Returns false if the item should not be plotted. Pushes PlotClipRect.
  1160. IMPLOT_API bool BeginItem(const char* label_id, ImPlotItemFlags flags=0, ImPlotCol recolor_from=IMPLOT_AUTO);
  1161. // Same as above but with fitting functionality.
  1162. template <typename _Fitter>
  1163. bool BeginItemEx(const char* label_id, const _Fitter& fitter, ImPlotItemFlags flags=0, ImPlotCol recolor_from=IMPLOT_AUTO) {
  1164. if (BeginItem(label_id, flags, recolor_from)) {
  1165. ImPlotPlot& plot = *GetCurrentPlot();
  1166. if (plot.FitThisFrame && !ImHasFlag(flags, ImPlotItemFlags_NoFit))
  1167. fitter.Fit(plot.Axes[plot.CurrentX], plot.Axes[plot.CurrentY]);
  1168. return true;
  1169. }
  1170. return false;
  1171. }
  1172. // Ends an item (call only if BeginItem returns true). Pops PlotClipRect.
  1173. IMPLOT_API void EndItem();
  1174. // Register or get an existing item from the current plot.
  1175. IMPLOT_API ImPlotItem* RegisterOrGetItem(const char* label_id, ImPlotItemFlags flags, bool* just_created = nullptr);
  1176. // Get a plot item from the current plot.
  1177. IMPLOT_API ImPlotItem* GetItem(const char* label_id);
  1178. // Gets the current item.
  1179. IMPLOT_API ImPlotItem* GetCurrentItem();
  1180. // Busts the cache for every item for every plot in the current context.
  1181. IMPLOT_API void BustItemCache();
  1182. //-----------------------------------------------------------------------------
  1183. // [SECTION] Axis Utils
  1184. //-----------------------------------------------------------------------------
  1185. // Returns true if any enabled axis is locked from user input.
  1186. static inline bool AnyAxesInputLocked(ImPlotAxis* axes, int count) {
  1187. for (int i = 0; i < count; ++i) {
  1188. if (axes[i].Enabled && axes[i].IsInputLocked())
  1189. return true;
  1190. }
  1191. return false;
  1192. }
  1193. // Returns true if all enabled axes are locked from user input.
  1194. static inline bool AllAxesInputLocked(ImPlotAxis* axes, int count) {
  1195. for (int i = 0; i < count; ++i) {
  1196. if (axes[i].Enabled && !axes[i].IsInputLocked())
  1197. return false;
  1198. }
  1199. return true;
  1200. }
  1201. static inline bool AnyAxesHeld(ImPlotAxis* axes, int count) {
  1202. for (int i = 0; i < count; ++i) {
  1203. if (axes[i].Enabled && axes[i].Held)
  1204. return true;
  1205. }
  1206. return false;
  1207. }
  1208. static inline bool AnyAxesHovered(ImPlotAxis* axes, int count) {
  1209. for (int i = 0; i < count; ++i) {
  1210. if (axes[i].Enabled && axes[i].Hovered)
  1211. return true;
  1212. }
  1213. return false;
  1214. }
  1215. // Returns true if the user has requested data to be fit.
  1216. static inline bool FitThisFrame() {
  1217. return GImPlot->CurrentPlot->FitThisFrame;
  1218. }
  1219. // Extends the current plot's axes so that it encompasses a vertical line at x
  1220. static inline void FitPointX(double x) {
  1221. ImPlotPlot& plot = *GetCurrentPlot();
  1222. ImPlotAxis& x_axis = plot.Axes[plot.CurrentX];
  1223. x_axis.ExtendFit(x);
  1224. }
  1225. // Extends the current plot's axes so that it encompasses a horizontal line at y
  1226. static inline void FitPointY(double y) {
  1227. ImPlotPlot& plot = *GetCurrentPlot();
  1228. ImPlotAxis& y_axis = plot.Axes[plot.CurrentY];
  1229. y_axis.ExtendFit(y);
  1230. }
  1231. // Extends the current plot's axes so that it encompasses point p
  1232. static inline void FitPoint(const ImPlotPoint& p) {
  1233. ImPlotPlot& plot = *GetCurrentPlot();
  1234. ImPlotAxis& x_axis = plot.Axes[plot.CurrentX];
  1235. ImPlotAxis& y_axis = plot.Axes[plot.CurrentY];
  1236. x_axis.ExtendFitWith(y_axis, p.x, p.y);
  1237. y_axis.ExtendFitWith(x_axis, p.y, p.x);
  1238. }
  1239. // Returns true if two ranges overlap
  1240. static inline bool RangesOverlap(const ImPlotRange& r1, const ImPlotRange& r2)
  1241. { return r1.Min <= r2.Max && r2.Min <= r1.Max; }
  1242. // Shows an axis's context menu.
  1243. IMPLOT_API void ShowAxisContextMenu(ImPlotAxis& axis, ImPlotAxis* equal_axis, bool time_allowed = false);
  1244. //-----------------------------------------------------------------------------
  1245. // [SECTION] Legend Utils
  1246. //-----------------------------------------------------------------------------
  1247. // Gets the position of an inner rect that is located inside of an outer rect according to an ImPlotLocation and padding amount.
  1248. IMPLOT_API ImVec2 GetLocationPos(const ImRect& outer_rect, const ImVec2& inner_size, ImPlotLocation location, const ImVec2& pad = ImVec2(0,0));
  1249. // Calculates the bounding box size of a legend _before_ clipping.
  1250. IMPLOT_API ImVec2 CalcLegendSize(ImPlotItemGroup& items, const ImVec2& pad, const ImVec2& spacing, bool vertical);
  1251. // Clips calculated legend size
  1252. IMPLOT_API bool ClampLegendRect(ImRect& legend_rect, const ImRect& outer_rect, const ImVec2& pad);
  1253. // Renders legend entries into a bounding box
  1254. IMPLOT_API bool ShowLegendEntries(ImPlotItemGroup& items, const ImRect& legend_bb, bool interactable, const ImVec2& pad, const ImVec2& spacing, bool vertical, ImDrawList& DrawList);
  1255. // Shows an alternate legend for the plot identified by #title_id, outside of the plot frame (can be called before or after of Begin/EndPlot but must occur in the same ImGui window! This is not thoroughly tested nor scrollable!).
  1256. IMPLOT_API void ShowAltLegend(const char* title_id, bool vertical = true, const ImVec2 size = ImVec2(0,0), bool interactable = true);
  1257. // Shows a legend's context menu.
  1258. IMPLOT_API bool ShowLegendContextMenu(ImPlotLegend& legend, bool visible);
  1259. //-----------------------------------------------------------------------------
  1260. // [SECTION] Label Utils
  1261. //-----------------------------------------------------------------------------
  1262. // Create a a string label for a an axis value
  1263. IMPLOT_API void LabelAxisValue(const ImPlotAxis& axis, double value, char* buff, int size, bool round = false);
  1264. //-----------------------------------------------------------------------------
  1265. // [SECTION] Styling Utils
  1266. //-----------------------------------------------------------------------------
  1267. // Get styling data for next item (call between Begin/EndItem)
  1268. static inline const ImPlotNextItemData& GetItemData() { return GImPlot->NextItemData; }
  1269. // Returns true if a color is set to be automatically determined
  1270. static inline bool IsColorAuto(const ImVec4& col) { return col.w == -1; }
  1271. // Returns true if a style color is set to be automatically determined
  1272. static inline bool IsColorAuto(ImPlotCol idx) { return IsColorAuto(GImPlot->Style.Colors[idx]); }
  1273. // Returns the automatically deduced style color
  1274. IMPLOT_API ImVec4 GetAutoColor(ImPlotCol idx);
  1275. // Returns the style color whether it is automatic or custom set
  1276. static inline ImVec4 GetStyleColorVec4(ImPlotCol idx) { return IsColorAuto(idx) ? GetAutoColor(idx) : GImPlot->Style.Colors[idx]; }
  1277. static inline ImU32 GetStyleColorU32(ImPlotCol idx) { return ImGui::ColorConvertFloat4ToU32(GetStyleColorVec4(idx)); }
  1278. // Draws vertical text. The position is the bottom left of the text rect.
  1279. IMPLOT_API void AddTextVertical(ImDrawList *DrawList, ImVec2 pos, ImU32 col, const char* text_begin, const char* text_end = nullptr);
  1280. // Draws multiline horizontal text centered.
  1281. IMPLOT_API void AddTextCentered(ImDrawList* DrawList, ImVec2 top_center, ImU32 col, const char* text_begin, const char* text_end = nullptr);
  1282. // Calculates the size of vertical text
  1283. static inline ImVec2 CalcTextSizeVertical(const char *text) {
  1284. ImVec2 sz = ImGui::CalcTextSize(text);
  1285. return ImVec2(sz.y, sz.x);
  1286. }
  1287. // Returns white or black text given background color
  1288. static inline ImU32 CalcTextColor(const ImVec4& bg) { return (bg.x * 0.299f + bg.y * 0.587f + bg.z * 0.114f) > 0.5f ? IM_COL32_BLACK : IM_COL32_WHITE; }
  1289. static inline ImU32 CalcTextColor(ImU32 bg) { return CalcTextColor(ImGui::ColorConvertU32ToFloat4(bg)); }
  1290. // Lightens or darkens a color for hover
  1291. static inline ImU32 CalcHoverColor(ImU32 col) { return ImMixU32(col, CalcTextColor(col), 32); }
  1292. // Clamps a label position so that it fits a rect defined by Min/Max
  1293. static inline ImVec2 ClampLabelPos(ImVec2 pos, const ImVec2& size, const ImVec2& Min, const ImVec2& Max) {
  1294. if (pos.x < Min.x) pos.x = Min.x;
  1295. if (pos.y < Min.y) pos.y = Min.y;
  1296. if ((pos.x + size.x) > Max.x) pos.x = Max.x - size.x;
  1297. if ((pos.y + size.y) > Max.y) pos.y = Max.y - size.y;
  1298. return pos;
  1299. }
  1300. // Returns a color from the Color map given an index >= 0 (modulo will be performed).
  1301. IMPLOT_API ImU32 GetColormapColorU32(int idx, ImPlotColormap cmap);
  1302. // Returns the next unused colormap color and advances the colormap. Can be used to skip colors if desired.
  1303. IMPLOT_API ImU32 NextColormapColorU32();
  1304. // Linearly interpolates a color from the current colormap given t between 0 and 1.
  1305. IMPLOT_API ImU32 SampleColormapU32(float t, ImPlotColormap cmap);
  1306. // Render a colormap bar
  1307. IMPLOT_API void RenderColorBar(const ImU32* colors, int size, ImDrawList& DrawList, const ImRect& bounds, bool vert, bool reversed, bool continuous);
  1308. //-----------------------------------------------------------------------------
  1309. // [SECTION] Math and Misc Utils
  1310. //-----------------------------------------------------------------------------
  1311. // Rounds x to powers of 2,5 and 10 for generating axis labels (from Graphics Gems 1 Chapter 11.2)
  1312. IMPLOT_API double NiceNum(double x, bool round);
  1313. // Computes order of magnitude of double.
  1314. static inline int OrderOfMagnitude(double val) { return val == 0 ? 0 : (int)(floor(log10(fabs(val)))); }
  1315. // Returns the precision required for a order of magnitude.
  1316. static inline int OrderToPrecision(int order) { return order > 0 ? 0 : 1 - order; }
  1317. // Returns a floating point precision to use given a value
  1318. static inline int Precision(double val) { return OrderToPrecision(OrderOfMagnitude(val)); }
  1319. // Round a value to a given precision
  1320. static inline double RoundTo(double val, int prec) { double p = pow(10,(double)prec); return floor(val*p+0.5)/p; }
  1321. // Returns the intersection point of two lines A and B (assumes they are not parallel!)
  1322. static inline ImVec2 Intersection(const ImVec2& a1, const ImVec2& a2, const ImVec2& b1, const ImVec2& b2) {
  1323. float v1 = (a1.x * a2.y - a1.y * a2.x); float v2 = (b1.x * b2.y - b1.y * b2.x);
  1324. float v3 = ((a1.x - a2.x) * (b1.y - b2.y) - (a1.y - a2.y) * (b1.x - b2.x));
  1325. return ImVec2((v1 * (b1.x - b2.x) - v2 * (a1.x - a2.x)) / v3, (v1 * (b1.y - b2.y) - v2 * (a1.y - a2.y)) / v3);
  1326. }
  1327. // Fills a buffer with n samples linear interpolated from vmin to vmax
  1328. template <typename T>
  1329. void FillRange(ImVector<T>& buffer, int n, T vmin, T vmax) {
  1330. buffer.resize(n);
  1331. T step = (vmax - vmin) / (n - 1);
  1332. for (int i = 0; i < n; ++i) {
  1333. buffer[i] = vmin + i * step;
  1334. }
  1335. }
  1336. // Calculate histogram bin counts and widths
  1337. template <typename T>
  1338. static inline void CalculateBins(const T* values, int count, ImPlotBin meth, const ImPlotRange& range, int& bins_out, double& width_out) {
  1339. switch (meth) {
  1340. case ImPlotBin_Sqrt:
  1341. bins_out = (int)ceil(sqrt(count));
  1342. break;
  1343. case ImPlotBin_Sturges:
  1344. bins_out = (int)ceil(1.0 + log2(count));
  1345. break;
  1346. case ImPlotBin_Rice:
  1347. bins_out = (int)ceil(2 * cbrt(count));
  1348. break;
  1349. case ImPlotBin_Scott:
  1350. width_out = 3.49 * ImStdDev(values, count) / cbrt(count);
  1351. bins_out = (int)round(range.Size() / width_out);
  1352. break;
  1353. }
  1354. width_out = range.Size() / bins_out;
  1355. }
  1356. //-----------------------------------------------------------------------------
  1357. // Time Utils
  1358. //-----------------------------------------------------------------------------
  1359. // Returns true if year is leap year (366 days long)
  1360. static inline bool IsLeapYear(int year) {
  1361. return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
  1362. }
  1363. // Returns the number of days in a month, accounting for Feb. leap years. #month is zero indexed.
  1364. static inline int GetDaysInMonth(int year, int month) {
  1365. static const int days[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
  1366. return days[month] + (int)(month == 1 && IsLeapYear(year));
  1367. }
  1368. // Make a UNIX timestamp from a tm struct expressed in UTC time (i.e. GMT timezone).
  1369. IMPLOT_API ImPlotTime MkGmtTime(struct tm *ptm);
  1370. // Make a tm struct expressed in UTC time (i.e. GMT timezone) from a UNIX timestamp.
  1371. IMPLOT_API tm* GetGmtTime(const ImPlotTime& t, tm* ptm);
  1372. // Make a UNIX timestamp from a tm struct expressed in local time.
  1373. IMPLOT_API ImPlotTime MkLocTime(struct tm *ptm);
  1374. // Make a tm struct expressed in local time from a UNIX timestamp.
  1375. IMPLOT_API tm* GetLocTime(const ImPlotTime& t, tm* ptm);
  1376. // NB: The following functions only work if there is a current ImPlotContext because the
  1377. // internal tm struct is owned by the context! They are aware of ImPlotStyle.UseLocalTime.
  1378. // // Make a UNIX timestamp from a tm struct according to the current ImPlotStyle.UseLocalTime setting.
  1379. static inline ImPlotTime MkTime(struct tm *ptm) {
  1380. if (GetStyle().UseLocalTime) return MkLocTime(ptm);
  1381. else return MkGmtTime(ptm);
  1382. }
  1383. // Get a tm struct from a UNIX timestamp according to the current ImPlotStyle.UseLocalTime setting.
  1384. static inline tm* GetTime(const ImPlotTime& t, tm* ptm) {
  1385. if (GetStyle().UseLocalTime) return GetLocTime(t,ptm);
  1386. else return GetGmtTime(t,ptm);
  1387. }
  1388. // Make a timestamp from time components.
  1389. // year[1970-3000], month[0-11], day[1-31], hour[0-23], min[0-59], sec[0-59], us[0,999999]
  1390. IMPLOT_API ImPlotTime MakeTime(int year, int month = 0, int day = 1, int hour = 0, int min = 0, int sec = 0, int us = 0);
  1391. // Get year component from timestamp [1970-3000]
  1392. IMPLOT_API int GetYear(const ImPlotTime& t);
  1393. // Get month component from timestamp [0-11]
  1394. IMPLOT_API int GetMonth(const ImPlotTime& t);
  1395. // Adds or subtracts time from a timestamp. #count > 0 to add, < 0 to subtract.
  1396. IMPLOT_API ImPlotTime AddTime(const ImPlotTime& t, ImPlotTimeUnit unit, int count);
  1397. // Rounds a timestamp down to nearest unit.
  1398. IMPLOT_API ImPlotTime FloorTime(const ImPlotTime& t, ImPlotTimeUnit unit);
  1399. // Rounds a timestamp up to the nearest unit.
  1400. IMPLOT_API ImPlotTime CeilTime(const ImPlotTime& t, ImPlotTimeUnit unit);
  1401. // Rounds a timestamp up or down to the nearest unit.
  1402. IMPLOT_API ImPlotTime RoundTime(const ImPlotTime& t, ImPlotTimeUnit unit);
  1403. // Combines the date of one timestamp with the time-of-day of another timestamp.
  1404. IMPLOT_API ImPlotTime CombineDateTime(const ImPlotTime& date_part, const ImPlotTime& time_part);
  1405. // Get the current time as a timestamp.
  1406. static inline ImPlotTime Now() { return ImPlotTime::FromDouble((double)time(nullptr)); }
  1407. // Get the current date as a timestamp.
  1408. static inline ImPlotTime Today() { return ImPlot::FloorTime(Now(), ImPlotTimeUnit_Day); }
  1409. // Formats the time part of timestamp t into a buffer according to #fmt
  1410. IMPLOT_API int FormatTime(const ImPlotTime& t, char* buffer, int size, ImPlotTimeFmt fmt, bool use_24_hr_clk);
  1411. // Formats the date part of timestamp t into a buffer according to #fmt
  1412. IMPLOT_API int FormatDate(const ImPlotTime& t, char* buffer, int size, ImPlotDateFmt fmt, bool use_iso_8601);
  1413. // Formats the time and/or date parts of a timestamp t into a buffer according to #fmt
  1414. IMPLOT_API int FormatDateTime(const ImPlotTime& t, char* buffer, int size, ImPlotDateTimeSpec fmt);
  1415. // Shows a date picker widget block (year/month/day).
  1416. // #level = 0 for day, 1 for month, 2 for year. Modified by user interaction.
  1417. // #t will be set when a day is clicked and the function will return true.
  1418. // #t1 and #t2 are optional dates to highlight.
  1419. IMPLOT_API bool ShowDatePicker(const char* id, int* level, ImPlotTime* t, const ImPlotTime* t1 = nullptr, const ImPlotTime* t2 = nullptr);
  1420. // Shows a time picker widget block (hour/min/sec).
  1421. // #t will be set when a new hour, minute, or sec is selected or am/pm is toggled, and the function will return true.
  1422. IMPLOT_API bool ShowTimePicker(const char* id, ImPlotTime* t);
  1423. //-----------------------------------------------------------------------------
  1424. // [SECTION] Transforms
  1425. //-----------------------------------------------------------------------------
  1426. static inline double TransformForward_Log10(double v, void*) {
  1427. v = v <= 0.0 ? DBL_MIN : v;
  1428. return ImLog10(v);
  1429. }
  1430. static inline double TransformInverse_Log10(double v, void*) {
  1431. return ImPow(10, v);
  1432. }
  1433. static inline double TransformForward_SymLog(double v, void*) {
  1434. return 2.0 * ImAsinh(v / 2.0);
  1435. }
  1436. static inline double TransformInverse_SymLog(double v, void*) {
  1437. return 2.0 * ImSinh(v / 2.0);
  1438. }
  1439. static inline double TransformForward_Logit(double v, void*) {
  1440. v = ImClamp(v, DBL_MIN, 1.0 - DBL_EPSILON);
  1441. return ImLog10(v / (1 - v));
  1442. }
  1443. static inline double TransformInverse_Logit(double v, void*) {
  1444. return 1.0 / (1.0 + ImPow(10,-v));
  1445. }
  1446. //-----------------------------------------------------------------------------
  1447. // [SECTION] Formatters
  1448. //-----------------------------------------------------------------------------
  1449. static inline int Formatter_Default(double value, char* buff, int size, void* data) {
  1450. char* fmt = (char*)data;
  1451. return ImFormatString(buff, size, fmt, value);
  1452. }
  1453. static inline int Formatter_Logit(double value, char* buff, int size, void*) {
  1454. if (value == 0.5)
  1455. return ImFormatString(buff,size,"1/2");
  1456. else if (value < 0.5)
  1457. return ImFormatString(buff,size,"%g", value);
  1458. else
  1459. return ImFormatString(buff,size,"1 - %g", 1 - value);
  1460. }
  1461. struct Formatter_Time_Data {
  1462. ImPlotTime Time;
  1463. ImPlotDateTimeSpec Spec;
  1464. ImPlotFormatter UserFormatter;
  1465. void* UserFormatterData;
  1466. };
  1467. static inline int Formatter_Time(double, char* buff, int size, void* data) {
  1468. Formatter_Time_Data* ftd = (Formatter_Time_Data*)data;
  1469. return FormatDateTime(ftd->Time, buff, size, ftd->Spec);
  1470. }
  1471. //------------------------------------------------------------------------------
  1472. // [SECTION] Locator
  1473. //------------------------------------------------------------------------------
  1474. void Locator_Default(ImPlotTicker& ticker, const ImPlotRange& range, float pixels, bool vertical, ImPlotFormatter formatter, void* formatter_data);
  1475. void Locator_Time(ImPlotTicker& ticker, const ImPlotRange& range, float pixels, bool vertical, ImPlotFormatter formatter, void* formatter_data);
  1476. void Locator_Log10(ImPlotTicker& ticker, const ImPlotRange& range, float pixels, bool vertical, ImPlotFormatter formatter, void* formatter_data);
  1477. void Locator_SymLog(ImPlotTicker& ticker, const ImPlotRange& range, float pixels, bool vertical, ImPlotFormatter formatter, void* formatter_data);
  1478. } // namespace ImPlot
  1479. #endif // #ifndef IMGUI_DISABLE