implot_items.cpp 127 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264
  1. // MIT License
  2. // Copyright (c) 2020 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.11 WIP
  19. #include "implot.h"
  20. #include "implot_internal.h"
  21. #ifdef _MSC_VER
  22. #define sprintf sprintf_s
  23. #endif
  24. #define SQRT_1_2 0.70710678118f
  25. #define SQRT_3_2 0.86602540378f
  26. #define IMPLOT_NORMALIZE2F_OVER_ZERO(VX, VY) \
  27. { \
  28. float d2 = VX * VX + VY * VY; \
  29. if (d2 > 0.0f) { \
  30. float inv_len = 1.0f / ImSqrt(d2); \
  31. VX *= inv_len; \
  32. VY *= inv_len; \
  33. } \
  34. }
  35. // Support for pre-1.82 versions. Users on 1.82+ can use 0 (default) flags to mean "all corners" but in order to support older versions we are more explicit.
  36. #if (IMGUI_VERSION_NUM < 18102) && !defined(ImDrawFlags_RoundCornersAll)
  37. #define ImDrawFlags_RoundCornersAll ImDrawCornerFlags_All
  38. #endif
  39. namespace ImPlot {
  40. //-----------------------------------------------------------------------------
  41. // Item Utils
  42. //-----------------------------------------------------------------------------
  43. ImPlotItem* RegisterOrGetItem(const char* label_id, bool* just_created) {
  44. ImPlotContext& gp = *GImPlot;
  45. ImPlotItemGroup& Items = *gp.CurrentItems;
  46. ImGuiID id = Items.GetItemID(label_id);
  47. if (just_created != NULL)
  48. *just_created = Items.GetItem(id) == NULL;
  49. ImPlotItem* item = Items.GetOrAddItem(id);
  50. if (item->SeenThisFrame)
  51. return item;
  52. item->SeenThisFrame = true;
  53. int idx = Items.GetItemIndex(item);
  54. item->ID = id;
  55. if (ImGui::FindRenderedTextEnd(label_id, NULL) != label_id) {
  56. Items.Legend.Indices.push_back(idx);
  57. item->NameOffset = Items.Legend.Labels.size();
  58. Items.Legend.Labels.append(label_id, label_id + strlen(label_id) + 1);
  59. }
  60. else {
  61. item->Show = true;
  62. }
  63. return item;
  64. }
  65. ImPlotItem* GetItem(const char* label_id) {
  66. ImPlotContext& gp = *GImPlot;
  67. return gp.CurrentItems->GetItem(label_id);
  68. }
  69. ImPlotItem* GetCurrentItem() {
  70. ImPlotContext& gp = *GImPlot;
  71. return gp.CurrentItem;
  72. }
  73. void SetNextLineStyle(const ImVec4& col, float weight) {
  74. ImPlotContext& gp = *GImPlot;
  75. gp.NextItemData.Colors[ImPlotCol_Line] = col;
  76. gp.NextItemData.LineWeight = weight;
  77. }
  78. void SetNextFillStyle(const ImVec4& col, float alpha) {
  79. ImPlotContext& gp = *GImPlot;
  80. gp.NextItemData.Colors[ImPlotCol_Fill] = col;
  81. gp.NextItemData.FillAlpha = alpha;
  82. }
  83. void SetNextMarkerStyle(ImPlotMarker marker, float size, const ImVec4& fill, float weight, const ImVec4& outline) {
  84. ImPlotContext& gp = *GImPlot;
  85. gp.NextItemData.Marker = marker;
  86. gp.NextItemData.Colors[ImPlotCol_MarkerFill] = fill;
  87. gp.NextItemData.MarkerSize = size;
  88. gp.NextItemData.Colors[ImPlotCol_MarkerOutline] = outline;
  89. gp.NextItemData.MarkerWeight = weight;
  90. }
  91. void SetNextErrorBarStyle(const ImVec4& col, float size, float weight) {
  92. ImPlotContext& gp = *GImPlot;
  93. gp.NextItemData.Colors[ImPlotCol_ErrorBar] = col;
  94. gp.NextItemData.ErrorBarSize = size;
  95. gp.NextItemData.ErrorBarWeight = weight;
  96. }
  97. ImVec4 GetLastItemColor() {
  98. ImPlotContext& gp = *GImPlot;
  99. if (gp.PreviousItem)
  100. return ImGui::ColorConvertU32ToFloat4(gp.PreviousItem->Color);
  101. return ImVec4();
  102. }
  103. void HideNextItem(bool hidden, ImGuiCond cond) {
  104. ImPlotContext& gp = *GImPlot;
  105. gp.NextItemData.HasHidden = true;
  106. gp.NextItemData.Hidden = hidden;
  107. gp.NextItemData.HiddenCond = cond;
  108. }
  109. void BustItemCache() {
  110. ImPlotContext& gp = *GImPlot;
  111. for (int p = 0; p < gp.Plots.GetBufSize(); ++p) {
  112. ImPlotPlot& plot = *gp.Plots.GetByIndex(p);
  113. plot.Items.Reset();
  114. }
  115. for (int p = 0; p < gp.Subplots.GetBufSize(); ++p) {
  116. ImPlotSubplot& subplot = *gp.Subplots.GetByIndex(p);
  117. subplot.Items.Reset();
  118. }
  119. }
  120. void BustColorCache(const char* plot_title_id) {
  121. ImPlotContext& gp = *GImPlot;
  122. if (plot_title_id == NULL) {
  123. BustItemCache();
  124. }
  125. else {
  126. ImGuiID id = ImGui::GetCurrentWindow()->GetID(plot_title_id);
  127. ImPlotPlot* plot = gp.Plots.GetByKey(id);
  128. if (plot != NULL)
  129. plot->Items.Reset();
  130. else {
  131. ImPlotSubplot* subplot = gp.Subplots.GetByKey(id);
  132. if (subplot != NULL)
  133. subplot->Items.Reset();
  134. }
  135. }
  136. }
  137. //-----------------------------------------------------------------------------
  138. // Begin/EndItem
  139. //-----------------------------------------------------------------------------
  140. // Begins a new item. Returns false if the item should not be plotted.
  141. bool BeginItem(const char* label_id, ImPlotCol recolor_from) {
  142. ImPlotContext& gp = *GImPlot;
  143. IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PlotX() needs to be called between BeginPlot() and EndPlot()!");
  144. bool just_created;
  145. ImPlotItem* item = RegisterOrGetItem(label_id, &just_created);
  146. // set current item
  147. gp.CurrentItem = item;
  148. ImPlotNextItemData& s = gp.NextItemData;
  149. // set/override item color
  150. if (recolor_from != -1) {
  151. if (!IsColorAuto(s.Colors[recolor_from]))
  152. item->Color = ImGui::ColorConvertFloat4ToU32(s.Colors[recolor_from]);
  153. else if (!IsColorAuto(gp.Style.Colors[recolor_from]))
  154. item->Color = ImGui::ColorConvertFloat4ToU32(gp.Style.Colors[recolor_from]);
  155. else if (just_created)
  156. item->Color = NextColormapColorU32();
  157. }
  158. else if (just_created) {
  159. item->Color = NextColormapColorU32();
  160. }
  161. // hide/show item
  162. if (gp.NextItemData.HasHidden) {
  163. if (just_created || gp.NextItemData.HiddenCond == ImGuiCond_Always)
  164. item->Show = !gp.NextItemData.Hidden;
  165. }
  166. if (!item->Show) {
  167. // reset next item data
  168. gp.NextItemData.Reset();
  169. gp.PreviousItem = item;
  170. gp.CurrentItem = NULL;
  171. return false;
  172. }
  173. else {
  174. ImVec4 item_color = ImGui::ColorConvertU32ToFloat4(item->Color);
  175. // stage next item colors
  176. s.Colors[ImPlotCol_Line] = IsColorAuto(s.Colors[ImPlotCol_Line]) ? ( IsColorAuto(ImPlotCol_Line) ? item_color : gp.Style.Colors[ImPlotCol_Line] ) : s.Colors[ImPlotCol_Line];
  177. s.Colors[ImPlotCol_Fill] = IsColorAuto(s.Colors[ImPlotCol_Fill]) ? ( IsColorAuto(ImPlotCol_Fill) ? item_color : gp.Style.Colors[ImPlotCol_Fill] ) : s.Colors[ImPlotCol_Fill];
  178. s.Colors[ImPlotCol_MarkerOutline] = IsColorAuto(s.Colors[ImPlotCol_MarkerOutline]) ? ( IsColorAuto(ImPlotCol_MarkerOutline) ? s.Colors[ImPlotCol_Line] : gp.Style.Colors[ImPlotCol_MarkerOutline] ) : s.Colors[ImPlotCol_MarkerOutline];
  179. s.Colors[ImPlotCol_MarkerFill] = IsColorAuto(s.Colors[ImPlotCol_MarkerFill]) ? ( IsColorAuto(ImPlotCol_MarkerFill) ? s.Colors[ImPlotCol_Line] : gp.Style.Colors[ImPlotCol_MarkerFill] ) : s.Colors[ImPlotCol_MarkerFill];
  180. s.Colors[ImPlotCol_ErrorBar] = IsColorAuto(s.Colors[ImPlotCol_ErrorBar]) ? ( GetStyleColorVec4(ImPlotCol_ErrorBar) ) : s.Colors[ImPlotCol_ErrorBar];
  181. // stage next item style vars
  182. s.LineWeight = s.LineWeight < 0 ? gp.Style.LineWeight : s.LineWeight;
  183. s.Marker = s.Marker < 0 ? gp.Style.Marker : s.Marker;
  184. s.MarkerSize = s.MarkerSize < 0 ? gp.Style.MarkerSize : s.MarkerSize;
  185. s.MarkerWeight = s.MarkerWeight < 0 ? gp.Style.MarkerWeight : s.MarkerWeight;
  186. s.FillAlpha = s.FillAlpha < 0 ? gp.Style.FillAlpha : s.FillAlpha;
  187. s.ErrorBarSize = s.ErrorBarSize < 0 ? gp.Style.ErrorBarSize : s.ErrorBarSize;
  188. s.ErrorBarWeight = s.ErrorBarWeight < 0 ? gp.Style.ErrorBarWeight : s.ErrorBarWeight;
  189. s.DigitalBitHeight = s.DigitalBitHeight < 0 ? gp.Style.DigitalBitHeight : s.DigitalBitHeight;
  190. s.DigitalBitGap = s.DigitalBitGap < 0 ? gp.Style.DigitalBitGap : s.DigitalBitGap;
  191. // apply alpha modifier(s)
  192. s.Colors[ImPlotCol_Fill].w *= s.FillAlpha;
  193. // s.Colors[ImPlotCol_MarkerFill].w *= s.FillAlpha; // TODO: this should be separate, if it at all
  194. // apply highlight mods
  195. if (item->LegendHovered && !ImHasFlag(gp.CurrentPlot->Flags, ImPlotFlags_NoHighlight)) {
  196. s.LineWeight *= 2;
  197. s.MarkerWeight *= 2;
  198. // TODO: highlight fills?
  199. }
  200. // set render flags
  201. s.RenderLine = s.Colors[ImPlotCol_Line].w > 0 && s.LineWeight > 0;
  202. s.RenderFill = s.Colors[ImPlotCol_Fill].w > 0;
  203. s.RenderMarkerLine = s.Colors[ImPlotCol_MarkerOutline].w > 0 && s.MarkerWeight > 0;
  204. s.RenderMarkerFill = s.Colors[ImPlotCol_MarkerFill].w > 0;
  205. // push rendering clip rect
  206. PushPlotClipRect();
  207. return true;
  208. }
  209. }
  210. // Ends an item (call only if BeginItem returns true)
  211. void EndItem() {
  212. ImPlotContext& gp = *GImPlot;
  213. // pop rendering clip rect
  214. PopPlotClipRect();
  215. // reset next item data
  216. gp.NextItemData.Reset();
  217. // set current item
  218. gp.PreviousItem = gp.CurrentItem;
  219. gp.CurrentItem = NULL;
  220. }
  221. //-----------------------------------------------------------------------------
  222. // GETTERS
  223. //-----------------------------------------------------------------------------
  224. // Getters can be thought of as iterators that convert user data (e.g. raw arrays)
  225. // to ImPlotPoints
  226. // Interprets an array of Y points as ImPlotPoints where the X value is the index
  227. template <typename T>
  228. struct GetterYs {
  229. GetterYs(const T* ys, int count, double xscale, double x0, int offset, int stride) :
  230. Ys(ys),
  231. Count(count),
  232. XScale(xscale),
  233. X0(x0),
  234. Offset(count ? ImPosMod(offset, count) : 0),
  235. Stride(stride)
  236. { }
  237. inline ImPlotPoint operator()(int idx) const {
  238. return ImPlotPoint(X0 + XScale * idx, (double)OffsetAndStride(Ys, idx, Count, Offset, Stride));
  239. }
  240. const T* const Ys;
  241. const int Count;
  242. const double XScale;
  243. const double X0;
  244. const int Offset;
  245. const int Stride;
  246. };
  247. // Interprets separate arrays for X and Y points as ImPlotPoints
  248. template <typename T>
  249. struct GetterXsYs {
  250. GetterXsYs(const T* xs, const T* ys, int count, int offset, int stride) :
  251. Xs(xs),
  252. Ys(ys),
  253. Count(count),
  254. Offset(count ? ImPosMod(offset, count) : 0),
  255. Stride(stride)
  256. { }
  257. inline ImPlotPoint operator()(int idx) const {
  258. return ImPlotPoint((double)OffsetAndStride(Xs, idx, Count, Offset, Stride), (double)OffsetAndStride(Ys, idx, Count, Offset, Stride));
  259. }
  260. const T* const Xs;
  261. const T* const Ys;
  262. const int Count;
  263. const int Offset;
  264. const int Stride;
  265. };
  266. // Always returns a constant Y reference value where the X value is the index
  267. struct GetterYRef {
  268. GetterYRef(double y_ref, int count, double xscale, double x0) :
  269. YRef(y_ref),
  270. Count(count),
  271. XScale(xscale),
  272. X0(x0)
  273. { }
  274. inline ImPlotPoint operator()(int idx) const {
  275. return ImPlotPoint(X0 + XScale*idx, YRef);
  276. }
  277. const double YRef;
  278. const int Count;
  279. const double XScale;
  280. const double X0;
  281. };
  282. // Interprets an array of X points as ImPlotPoints where the Y value is a constant reference value
  283. template <typename T>
  284. struct GetterXsYRef {
  285. GetterXsYRef(const T* xs, double y_ref, int count, int offset, int stride) :
  286. Xs(xs),
  287. YRef(y_ref),
  288. Count(count),
  289. Offset(count ? ImPosMod(offset, count) : 0),
  290. Stride(stride)
  291. { }
  292. inline ImPlotPoint operator()(int idx) const {
  293. return ImPlotPoint((double)OffsetAndStride(Xs, idx, Count, Offset, Stride), YRef);
  294. }
  295. const T* const Xs;
  296. const double YRef;
  297. const int Count;
  298. const int Offset;
  299. const int Stride;
  300. };
  301. // Interprets an array of Y points as ImPlotPoints where the X value is a constant reference value
  302. template <typename T>
  303. struct GetterXRefYs {
  304. GetterXRefYs(double x_ref, const T* ys, int count, int offset, int stride) :
  305. XRef(x_ref),
  306. Ys(ys),
  307. Count(count),
  308. Offset(count ? ImPosMod(offset, count) : 0),
  309. Stride(stride)
  310. { }
  311. inline ImPlotPoint operator()(int idx) const {
  312. return ImPlotPoint(XRef, (double)OffsetAndStride(Ys, idx, Count, Offset, Stride));
  313. }
  314. const double XRef;
  315. const T* const Ys;
  316. const int Count;
  317. const int Offset;
  318. const int Stride;
  319. };
  320. /// Interprets a user's function pointer as ImPlotPoints
  321. struct GetterFuncPtr {
  322. GetterFuncPtr(ImPlotPoint (*getter)(void* data, int idx), void* data, int count, int offset) :
  323. Getter(getter),
  324. Data(data),
  325. Count(count),
  326. Offset(count ? ImPosMod(offset, count) : 0)
  327. { }
  328. inline ImPlotPoint operator()(int idx) const {
  329. idx = ImPosMod(Offset + idx, Count);
  330. return Getter(Data, idx);
  331. }
  332. ImPlotPoint (* const Getter)(void* data, int idx);
  333. void* const Data;
  334. const int Count;
  335. const int Offset;
  336. };
  337. template <typename T>
  338. struct GetterBarV {
  339. const T* Ys; double XShift; int Count; int Offset; int Stride;
  340. GetterBarV(const T* ys, double xshift, int count, int offset, int stride) { Ys = ys; XShift = xshift; Count = count; Offset = offset; Stride = stride; }
  341. inline ImPlotPoint operator()(int idx) const { return ImPlotPoint((double)idx + (double)XShift, (double)OffsetAndStride(Ys, idx, Count, Offset, Stride)); }
  342. };
  343. template <typename T>
  344. struct GetterBarH {
  345. const T* Xs; double YShift; int Count; int Offset; int Stride;
  346. GetterBarH(const T* xs, double yshift, int count, int offset, int stride) { Xs = xs; YShift = yshift; Count = count; Offset = offset; Stride = stride; }
  347. inline ImPlotPoint operator()(int idx) const { return ImPlotPoint((double)OffsetAndStride(Xs, idx, Count, Offset, Stride), (double)idx + (double)YShift); }
  348. };
  349. template <typename T>
  350. struct GetterError {
  351. GetterError(const T* xs, const T* ys, const T* neg, const T* pos, int count, int offset, int stride) :
  352. Xs(xs),
  353. Ys(ys),
  354. Neg(neg),
  355. Pos(pos),
  356. Count(count),
  357. Offset(count ? ImPosMod(offset, count) : 0),
  358. Stride(stride)
  359. { }
  360. inline ImPlotPointError operator()(int idx) const {
  361. return ImPlotPointError((double)OffsetAndStride(Xs, idx, Count, Offset, Stride),
  362. (double)OffsetAndStride(Ys, idx, Count, Offset, Stride),
  363. (double)OffsetAndStride(Neg, idx, Count, Offset, Stride),
  364. (double)OffsetAndStride(Pos, idx, Count, Offset, Stride));
  365. }
  366. const T* const Xs;
  367. const T* const Ys;
  368. const T* const Neg;
  369. const T* const Pos;
  370. const int Count;
  371. const int Offset;
  372. const int Stride;
  373. };
  374. //-----------------------------------------------------------------------------
  375. // TRANSFORMERS
  376. //-----------------------------------------------------------------------------
  377. // Transforms convert points in plot space (i.e. ImPlotPoint) to pixel space (i.e. ImVec2)
  378. // Transforms points for linear x and linear y space
  379. struct TransformerLinLin {
  380. TransformerLinLin() : YAxis(GetCurrentYAxis()) {}
  381. // inline ImVec2 operator()(const ImPlotPoint& plt) const { return (*this)(plt.x, plt.y); }
  382. inline ImVec2 operator()(const ImPlotPoint& plt) const {
  383. ImPlotContext& gp = *GImPlot;
  384. return ImVec2( (float)(gp.PixelRange[YAxis].Min.x + gp.Mx * (plt.x - gp.CurrentPlot->XAxis.Range.Min)),
  385. (float)(gp.PixelRange[YAxis].Min.y + gp.My[YAxis] * (plt.y - gp.CurrentPlot->YAxis[YAxis].Range.Min)) );
  386. }
  387. const int YAxis;
  388. };
  389. // Transforms points for log x and linear y space
  390. struct TransformerLogLin {
  391. TransformerLogLin() : YAxis(GetCurrentYAxis()) {}
  392. inline ImVec2 operator()(const ImPlotPoint& plt) const {
  393. ImPlotContext& gp = *GImPlot;
  394. double x = plt.x <= 0.0 ? IMPLOT_LOG_ZERO : plt.x;
  395. double t = ImLog10(x / gp.CurrentPlot->XAxis.Range.Min) / gp.LogDenX;
  396. x = ImLerp(gp.CurrentPlot->XAxis.Range.Min, gp.CurrentPlot->XAxis.Range.Max, (float)t);
  397. return ImVec2( (float)(gp.PixelRange[YAxis].Min.x + gp.Mx * (x - gp.CurrentPlot->XAxis.Range.Min)),
  398. (float)(gp.PixelRange[YAxis].Min.y + gp.My[YAxis] * (plt.y - gp.CurrentPlot->YAxis[YAxis].Range.Min)) );
  399. }
  400. const int YAxis;
  401. };
  402. // Transforms points for linear x and log y space
  403. struct TransformerLinLog {
  404. TransformerLinLog() : YAxis(GetCurrentYAxis()) {}
  405. inline ImVec2 operator()(const ImPlotPoint& plt) const {
  406. ImPlotContext& gp = *GImPlot;
  407. double y = plt.y <= 0.0 ? IMPLOT_LOG_ZERO : plt.y;
  408. double t = ImLog10(y / gp.CurrentPlot->YAxis[YAxis].Range.Min) / gp.LogDenY[YAxis];
  409. y = ImLerp(gp.CurrentPlot->YAxis[YAxis].Range.Min, gp.CurrentPlot->YAxis[YAxis].Range.Max, (float)t);
  410. return ImVec2( (float)(gp.PixelRange[YAxis].Min.x + gp.Mx * (plt.x - gp.CurrentPlot->XAxis.Range.Min)),
  411. (float)(gp.PixelRange[YAxis].Min.y + gp.My[YAxis] * (y - gp.CurrentPlot->YAxis[YAxis].Range.Min)) );
  412. }
  413. const int YAxis;
  414. };
  415. // Transforms points for log x and log y space
  416. struct TransformerLogLog {
  417. TransformerLogLog() : YAxis(GetCurrentYAxis()) {}
  418. inline ImVec2 operator()(const ImPlotPoint& plt) const {
  419. ImPlotContext& gp = *GImPlot;
  420. double x = plt.x <= 0.0 ? IMPLOT_LOG_ZERO : plt.x;
  421. double y = plt.y <= 0.0 ? IMPLOT_LOG_ZERO : plt.y;
  422. double t = ImLog10(x / gp.CurrentPlot->XAxis.Range.Min) / gp.LogDenX;
  423. x = ImLerp(gp.CurrentPlot->XAxis.Range.Min, gp.CurrentPlot->XAxis.Range.Max, (float)t);
  424. t = ImLog10(y / gp.CurrentPlot->YAxis[YAxis].Range.Min) / gp.LogDenY[YAxis];
  425. y = ImLerp(gp.CurrentPlot->YAxis[YAxis].Range.Min, gp.CurrentPlot->YAxis[YAxis].Range.Max, (float)t);
  426. return ImVec2( (float)(gp.PixelRange[YAxis].Min.x + gp.Mx * (x - gp.CurrentPlot->XAxis.Range.Min)),
  427. (float)(gp.PixelRange[YAxis].Min.y + gp.My[YAxis] * (y - gp.CurrentPlot->YAxis[YAxis].Range.Min)) );
  428. }
  429. const int YAxis;
  430. };
  431. //-----------------------------------------------------------------------------
  432. // PRIMITIVE RENDERERS
  433. //-----------------------------------------------------------------------------
  434. inline void AddLine(const ImVec2& P1, const ImVec2& P2, float weight, ImU32 col, ImDrawList& DrawList, ImVec2 uv) {
  435. float dx = P2.x - P1.x;
  436. float dy = P2.y - P1.y;
  437. IMPLOT_NORMALIZE2F_OVER_ZERO(dx, dy);
  438. dx *= (weight * 0.5f);
  439. dy *= (weight * 0.5f);
  440. DrawList._VtxWritePtr[0].pos.x = P1.x + dy;
  441. DrawList._VtxWritePtr[0].pos.y = P1.y - dx;
  442. DrawList._VtxWritePtr[0].uv = uv;
  443. DrawList._VtxWritePtr[0].col = col;
  444. DrawList._VtxWritePtr[1].pos.x = P2.x + dy;
  445. DrawList._VtxWritePtr[1].pos.y = P2.y - dx;
  446. DrawList._VtxWritePtr[1].uv = uv;
  447. DrawList._VtxWritePtr[1].col = col;
  448. DrawList._VtxWritePtr[2].pos.x = P2.x - dy;
  449. DrawList._VtxWritePtr[2].pos.y = P2.y + dx;
  450. DrawList._VtxWritePtr[2].uv = uv;
  451. DrawList._VtxWritePtr[2].col = col;
  452. DrawList._VtxWritePtr[3].pos.x = P1.x - dy;
  453. DrawList._VtxWritePtr[3].pos.y = P1.y + dx;
  454. DrawList._VtxWritePtr[3].uv = uv;
  455. DrawList._VtxWritePtr[3].col = col;
  456. DrawList._VtxWritePtr += 4;
  457. DrawList._IdxWritePtr[0] = (ImDrawIdx)(DrawList._VtxCurrentIdx);
  458. DrawList._IdxWritePtr[1] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 1);
  459. DrawList._IdxWritePtr[2] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 2);
  460. DrawList._IdxWritePtr[3] = (ImDrawIdx)(DrawList._VtxCurrentIdx);
  461. DrawList._IdxWritePtr[4] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 2);
  462. DrawList._IdxWritePtr[5] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 3);
  463. DrawList._IdxWritePtr += 6;
  464. DrawList._VtxCurrentIdx += 4;
  465. }
  466. inline void AddRectFilled(const ImVec2& Pmin, const ImVec2& Pmax, ImU32 col, ImDrawList& DrawList, ImVec2 uv) {
  467. DrawList._VtxWritePtr[0].pos = Pmin;
  468. DrawList._VtxWritePtr[0].uv = uv;
  469. DrawList._VtxWritePtr[0].col = col;
  470. DrawList._VtxWritePtr[1].pos = Pmax;
  471. DrawList._VtxWritePtr[1].uv = uv;
  472. DrawList._VtxWritePtr[1].col = col;
  473. DrawList._VtxWritePtr[2].pos.x = Pmin.x;
  474. DrawList._VtxWritePtr[2].pos.y = Pmax.y;
  475. DrawList._VtxWritePtr[2].uv = uv;
  476. DrawList._VtxWritePtr[2].col = col;
  477. DrawList._VtxWritePtr[3].pos.x = Pmax.x;
  478. DrawList._VtxWritePtr[3].pos.y = Pmin.y;
  479. DrawList._VtxWritePtr[3].uv = uv;
  480. DrawList._VtxWritePtr[3].col = col;
  481. DrawList._VtxWritePtr += 4;
  482. DrawList._IdxWritePtr[0] = (ImDrawIdx)(DrawList._VtxCurrentIdx);
  483. DrawList._IdxWritePtr[1] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 1);
  484. DrawList._IdxWritePtr[2] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 2);
  485. DrawList._IdxWritePtr[3] = (ImDrawIdx)(DrawList._VtxCurrentIdx);
  486. DrawList._IdxWritePtr[4] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 1);
  487. DrawList._IdxWritePtr[5] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 3);
  488. DrawList._IdxWritePtr += 6;
  489. DrawList._VtxCurrentIdx += 4;
  490. }
  491. template <typename TGetter, typename TTransformer>
  492. struct LineStripRenderer {
  493. inline LineStripRenderer(const TGetter& getter, const TTransformer& transformer, ImU32 col, float weight) :
  494. Getter(getter),
  495. Transformer(transformer),
  496. Prims(Getter.Count - 1),
  497. Col(col),
  498. Weight(weight)
  499. {
  500. P1 = Transformer(Getter(0));
  501. }
  502. inline bool operator()(ImDrawList& DrawList, const ImRect& cull_rect, const ImVec2& uv, int prim) const {
  503. ImVec2 P2 = Transformer(Getter(prim + 1));
  504. if (!cull_rect.Overlaps(ImRect(ImMin(P1, P2), ImMax(P1, P2)))) {
  505. P1 = P2;
  506. return false;
  507. }
  508. AddLine(P1,P2,Weight,Col,DrawList,uv);
  509. P1 = P2;
  510. return true;
  511. }
  512. const TGetter& Getter;
  513. const TTransformer& Transformer;
  514. const int Prims;
  515. const ImU32 Col;
  516. const float Weight;
  517. mutable ImVec2 P1;
  518. static const int IdxConsumed = 6;
  519. static const int VtxConsumed = 4;
  520. };
  521. template <typename TGetter, typename TTransformer>
  522. struct StairsRenderer {
  523. inline StairsRenderer(const TGetter& getter, const TTransformer& transformer, ImU32 col, float weight) :
  524. Getter(getter),
  525. Transformer(transformer),
  526. Prims(Getter.Count - 1),
  527. Col(col),
  528. HalfWeight(weight * 0.5f)
  529. {
  530. P1 = Transformer(Getter(0));
  531. }
  532. inline bool operator()(ImDrawList& DrawList, const ImRect& cull_rect, const ImVec2& uv, int prim) const {
  533. ImVec2 P2 = Transformer(Getter(prim + 1));
  534. if (!cull_rect.Overlaps(ImRect(ImMin(P1, P2), ImMax(P1, P2)))) {
  535. P1 = P2;
  536. return false;
  537. }
  538. AddRectFilled(ImVec2(P1.x, P1.y + HalfWeight), ImVec2(P2.x, P1.y - HalfWeight), Col, DrawList, uv);
  539. AddRectFilled(ImVec2(P2.x - HalfWeight, P2.y), ImVec2(P2.x + HalfWeight, P1.y), Col, DrawList, uv);
  540. // AddLine(P1, P12, Weight, Col, DrawList, uv);
  541. // AddLine(P12, P2, Weight, Col, DrawList, uv);
  542. P1 = P2;
  543. return true;
  544. }
  545. const TGetter& Getter;
  546. const TTransformer& Transformer;
  547. const int Prims;
  548. const ImU32 Col;
  549. const float HalfWeight;
  550. mutable ImVec2 P1;
  551. static const int IdxConsumed = 12;
  552. static const int VtxConsumed = 8;
  553. };
  554. template <typename TGetter1, typename TGetter2, typename TTransformer>
  555. struct LineSegmentsRenderer {
  556. inline LineSegmentsRenderer(const TGetter1& getter1, const TGetter2& getter2, const TTransformer& transformer, ImU32 col, float weight) :
  557. Getter1(getter1),
  558. Getter2(getter2),
  559. Transformer(transformer),
  560. Prims(ImMin(Getter1.Count, Getter2.Count)),
  561. Col(col),
  562. Weight(weight)
  563. {}
  564. inline bool operator()(ImDrawList& DrawList, const ImRect& cull_rect, const ImVec2& uv, int prim) const {
  565. ImVec2 P1 = Transformer(Getter1(prim));
  566. ImVec2 P2 = Transformer(Getter2(prim));
  567. if (!cull_rect.Overlaps(ImRect(ImMin(P1, P2), ImMax(P1, P2))))
  568. return false;
  569. AddLine(P1,P2,Weight,Col,DrawList,uv);
  570. return true;
  571. }
  572. const TGetter1& Getter1;
  573. const TGetter2& Getter2;
  574. const TTransformer& Transformer;
  575. const int Prims;
  576. const ImU32 Col;
  577. const float Weight;
  578. static const int IdxConsumed = 6;
  579. static const int VtxConsumed = 4;
  580. };
  581. template <typename TGetter1, typename TGetter2, typename TTransformer>
  582. struct ShadedRenderer {
  583. ShadedRenderer(const TGetter1& getter1, const TGetter2& getter2, const TTransformer& transformer, ImU32 col) :
  584. Getter1(getter1),
  585. Getter2(getter2),
  586. Transformer(transformer),
  587. Prims(ImMin(Getter1.Count, Getter2.Count) - 1),
  588. Col(col)
  589. {
  590. P11 = Transformer(Getter1(0));
  591. P12 = Transformer(Getter2(0));
  592. }
  593. inline bool operator()(ImDrawList& DrawList, const ImRect& cull_rect, const ImVec2& uv, int prim) const {
  594. ImVec2 P21 = Transformer(Getter1(prim+1));
  595. ImVec2 P22 = Transformer(Getter2(prim+1));
  596. ImRect rect(ImMin(ImMin(ImMin(P11,P12),P21),P22), ImMax(ImMax(ImMax(P11,P12),P21),P22));
  597. if (!cull_rect.Overlaps(rect)) {
  598. P11 = P21;
  599. P12 = P22;
  600. return false;
  601. }
  602. const int intersect = (P11.y > P12.y && P22.y > P21.y) || (P12.y > P11.y && P21.y > P22.y);
  603. ImVec2 intersection = Intersection(P11,P21,P12,P22);
  604. DrawList._VtxWritePtr[0].pos = P11;
  605. DrawList._VtxWritePtr[0].uv = uv;
  606. DrawList._VtxWritePtr[0].col = Col;
  607. DrawList._VtxWritePtr[1].pos = P21;
  608. DrawList._VtxWritePtr[1].uv = uv;
  609. DrawList._VtxWritePtr[1].col = Col;
  610. DrawList._VtxWritePtr[2].pos = intersection;
  611. DrawList._VtxWritePtr[2].uv = uv;
  612. DrawList._VtxWritePtr[2].col = Col;
  613. DrawList._VtxWritePtr[3].pos = P12;
  614. DrawList._VtxWritePtr[3].uv = uv;
  615. DrawList._VtxWritePtr[3].col = Col;
  616. DrawList._VtxWritePtr[4].pos = P22;
  617. DrawList._VtxWritePtr[4].uv = uv;
  618. DrawList._VtxWritePtr[4].col = Col;
  619. DrawList._VtxWritePtr += 5;
  620. DrawList._IdxWritePtr[0] = (ImDrawIdx)(DrawList._VtxCurrentIdx);
  621. DrawList._IdxWritePtr[1] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 1 + intersect);
  622. DrawList._IdxWritePtr[2] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 3);
  623. DrawList._IdxWritePtr[3] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 1);
  624. DrawList._IdxWritePtr[4] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 3 - intersect);
  625. DrawList._IdxWritePtr[5] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 4);
  626. DrawList._IdxWritePtr += 6;
  627. DrawList._VtxCurrentIdx += 5;
  628. P11 = P21;
  629. P12 = P22;
  630. return true;
  631. }
  632. const TGetter1& Getter1;
  633. const TGetter2& Getter2;
  634. const TTransformer& Transformer;
  635. const int Prims;
  636. const ImU32 Col;
  637. mutable ImVec2 P11;
  638. mutable ImVec2 P12;
  639. static const int IdxConsumed = 6;
  640. static const int VtxConsumed = 5;
  641. };
  642. // Stupid way of calculating maximum index size of ImDrawIdx without integer overflow issues
  643. template <typename T>
  644. struct MaxIdx { static const unsigned int Value; };
  645. template <> const unsigned int MaxIdx<unsigned short>::Value = 65535;
  646. template <> const unsigned int MaxIdx<unsigned int>::Value = 4294967295;
  647. /// Renders primitive shapes in bulk as efficiently as possible.
  648. template <typename Renderer>
  649. inline void RenderPrimitives(const Renderer& renderer, ImDrawList& DrawList, const ImRect& cull_rect) {
  650. unsigned int prims = renderer.Prims;
  651. unsigned int prims_culled = 0;
  652. unsigned int idx = 0;
  653. const ImVec2 uv = DrawList._Data->TexUvWhitePixel;
  654. while (prims) {
  655. // find how many can be reserved up to end of current draw command's limit
  656. unsigned int cnt = ImMin(prims, (MaxIdx<ImDrawIdx>::Value - DrawList._VtxCurrentIdx) / Renderer::VtxConsumed);
  657. // make sure at least this many elements can be rendered to avoid situations where at the end of buffer this slow path is not taken all the time
  658. if (cnt >= ImMin(64u, prims)) {
  659. if (prims_culled >= cnt)
  660. prims_culled -= cnt; // reuse previous reservation
  661. else {
  662. DrawList.PrimReserve((cnt - prims_culled) * Renderer::IdxConsumed, (cnt - prims_culled) * Renderer::VtxConsumed); // add more elements to previous reservation
  663. prims_culled = 0;
  664. }
  665. }
  666. else
  667. {
  668. if (prims_culled > 0) {
  669. DrawList.PrimUnreserve(prims_culled * Renderer::IdxConsumed, prims_culled * Renderer::VtxConsumed);
  670. prims_culled = 0;
  671. }
  672. cnt = ImMin(prims, (MaxIdx<ImDrawIdx>::Value - 0/*DrawList._VtxCurrentIdx*/) / Renderer::VtxConsumed);
  673. DrawList.PrimReserve(cnt * Renderer::IdxConsumed, cnt * Renderer::VtxConsumed); // reserve new draw command
  674. }
  675. prims -= cnt;
  676. for (unsigned int ie = idx + cnt; idx != ie; ++idx) {
  677. if (!renderer(DrawList, cull_rect, uv, idx))
  678. prims_culled++;
  679. }
  680. }
  681. if (prims_culled > 0)
  682. DrawList.PrimUnreserve(prims_culled * Renderer::IdxConsumed, prims_culled * Renderer::VtxConsumed);
  683. }
  684. template <typename Getter, typename Transformer>
  685. inline void RenderLineStrip(const Getter& getter, const Transformer& transformer, ImDrawList& DrawList, float line_weight, ImU32 col) {
  686. ImPlotContext& gp = *GImPlot;
  687. if (ImHasFlag(gp.CurrentPlot->Flags, ImPlotFlags_AntiAliased) || gp.Style.AntiAliasedLines) {
  688. ImVec2 p1 = transformer(getter(0));
  689. for (int i = 1; i < getter.Count; ++i) {
  690. ImVec2 p2 = transformer(getter(i));
  691. if (gp.CurrentPlot->PlotRect.Overlaps(ImRect(ImMin(p1, p2), ImMax(p1, p2))))
  692. DrawList.AddLine(p1, p2, col, line_weight);
  693. p1 = p2;
  694. }
  695. }
  696. else {
  697. RenderPrimitives(LineStripRenderer<Getter,Transformer>(getter, transformer, col, line_weight), DrawList, gp.CurrentPlot->PlotRect);
  698. }
  699. }
  700. template <typename Getter1, typename Getter2, typename Transformer>
  701. inline void RenderLineSegments(const Getter1& getter1, const Getter2& getter2, const Transformer& transformer, ImDrawList& DrawList, float line_weight, ImU32 col) {
  702. ImPlotContext& gp = *GImPlot;
  703. if (ImHasFlag(gp.CurrentPlot->Flags, ImPlotFlags_AntiAliased) || gp.Style.AntiAliasedLines) {
  704. int I = ImMin(getter1.Count, getter2.Count);
  705. for (int i = 0; i < I; ++i) {
  706. ImVec2 p1 = transformer(getter1(i));
  707. ImVec2 p2 = transformer(getter2(i));
  708. if (gp.CurrentPlot->PlotRect.Overlaps(ImRect(ImMin(p1, p2), ImMax(p1, p2))))
  709. DrawList.AddLine(p1, p2, col, line_weight);
  710. }
  711. }
  712. else {
  713. RenderPrimitives(LineSegmentsRenderer<Getter1,Getter2,Transformer>(getter1, getter2, transformer, col, line_weight), DrawList, gp.CurrentPlot->PlotRect);
  714. }
  715. }
  716. template <typename Getter, typename Transformer>
  717. inline void RenderStairs(const Getter& getter, const Transformer& transformer, ImDrawList& DrawList, float line_weight, ImU32 col) {
  718. ImPlotContext& gp = *GImPlot;
  719. if (ImHasFlag(gp.CurrentPlot->Flags, ImPlotFlags_AntiAliased) || gp.Style.AntiAliasedLines) {
  720. ImVec2 p1 = transformer(getter(0));
  721. for (int i = 1; i < getter.Count; ++i) {
  722. ImVec2 p2 = transformer(getter(i));
  723. if (gp.CurrentPlot->PlotRect.Overlaps(ImRect(ImMin(p1, p2), ImMax(p1, p2)))) {
  724. ImVec2 p12(p2.x, p1.y);
  725. DrawList.AddLine(p1, p12, col, line_weight);
  726. DrawList.AddLine(p12, p2, col, line_weight);
  727. }
  728. p1 = p2;
  729. }
  730. }
  731. else {
  732. RenderPrimitives(StairsRenderer<Getter,Transformer>(getter, transformer, col, line_weight), DrawList, gp.CurrentPlot->PlotRect);
  733. }
  734. }
  735. //-----------------------------------------------------------------------------
  736. // MARKER RENDERERS
  737. //-----------------------------------------------------------------------------
  738. inline void TransformMarker(ImVec2* points, int n, const ImVec2& c, float s) {
  739. for (int i = 0; i < n; ++i) {
  740. points[i].x = c.x + points[i].x * s;
  741. points[i].y = c.y + points[i].y * s;
  742. }
  743. }
  744. inline void RenderMarkerGeneral(ImDrawList& DrawList, ImVec2* points, int n, const ImVec2& c, float s, bool outline, ImU32 col_outline, bool fill, ImU32 col_fill, float weight) {
  745. TransformMarker(points, n, c, s);
  746. if (fill)
  747. DrawList.AddConvexPolyFilled(points, n, col_fill);
  748. if (outline && !(fill && col_outline == col_fill)) {
  749. for (int i = 0; i < n; ++i)
  750. DrawList.AddLine(points[i], points[(i+1)%n], col_outline, weight);
  751. }
  752. }
  753. inline void RenderMarkerCircle(ImDrawList& DrawList, const ImVec2& c, float s, bool outline, ImU32 col_outline, bool fill, ImU32 col_fill, float weight) {
  754. ImVec2 marker[10] = {ImVec2(1.0f, 0.0f),
  755. ImVec2(0.809017f, 0.58778524f),
  756. ImVec2(0.30901697f, 0.95105654f),
  757. ImVec2(-0.30901703f, 0.9510565f),
  758. ImVec2(-0.80901706f, 0.5877852f),
  759. ImVec2(-1.0f, 0.0f),
  760. ImVec2(-0.80901694f, -0.58778536f),
  761. ImVec2(-0.3090171f, -0.9510565f),
  762. ImVec2(0.30901712f, -0.9510565f),
  763. ImVec2(0.80901694f, -0.5877853f)};
  764. RenderMarkerGeneral(DrawList, marker, 10, c, s, outline, col_outline, fill, col_fill, weight);
  765. }
  766. inline void RenderMarkerDiamond(ImDrawList& DrawList, const ImVec2& c, float s, bool outline, ImU32 col_outline, bool fill, ImU32 col_fill, float weight) {
  767. ImVec2 marker[4] = {ImVec2(1, 0), ImVec2(0, -1), ImVec2(-1, 0), ImVec2(0, 1)};
  768. RenderMarkerGeneral(DrawList, marker, 4, c, s, outline, col_outline, fill, col_fill, weight);
  769. }
  770. inline void RenderMarkerSquare(ImDrawList& DrawList, const ImVec2& c, float s, bool outline, ImU32 col_outline, bool fill, ImU32 col_fill, float weight) {
  771. ImVec2 marker[4] = {ImVec2(SQRT_1_2,SQRT_1_2),ImVec2(SQRT_1_2,-SQRT_1_2),ImVec2(-SQRT_1_2,-SQRT_1_2),ImVec2(-SQRT_1_2,SQRT_1_2)};
  772. RenderMarkerGeneral(DrawList, marker, 4, c, s, outline, col_outline, fill, col_fill, weight);
  773. }
  774. inline void RenderMarkerUp(ImDrawList& DrawList, const ImVec2& c, float s, bool outline, ImU32 col_outline, bool fill, ImU32 col_fill, float weight) {
  775. ImVec2 marker[3] = {ImVec2(SQRT_3_2,0.5f),ImVec2(0,-1),ImVec2(-SQRT_3_2,0.5f)};
  776. RenderMarkerGeneral(DrawList, marker, 3, c, s, outline, col_outline, fill, col_fill, weight);
  777. }
  778. inline void RenderMarkerDown(ImDrawList& DrawList, const ImVec2& c, float s, bool outline, ImU32 col_outline, bool fill, ImU32 col_fill, float weight) {
  779. ImVec2 marker[3] = {ImVec2(SQRT_3_2,-0.5f),ImVec2(0,1),ImVec2(-SQRT_3_2,-0.5f)};
  780. RenderMarkerGeneral(DrawList, marker, 3, c, s, outline, col_outline, fill, col_fill, weight);
  781. }
  782. inline void RenderMarkerLeft(ImDrawList& DrawList, const ImVec2& c, float s, bool outline, ImU32 col_outline, bool fill, ImU32 col_fill, float weight) {
  783. ImVec2 marker[3] = {ImVec2(-1,0), ImVec2(0.5, SQRT_3_2), ImVec2(0.5, -SQRT_3_2)};
  784. RenderMarkerGeneral(DrawList, marker, 3, c, s, outline, col_outline, fill, col_fill, weight);
  785. }
  786. inline void RenderMarkerRight(ImDrawList& DrawList, const ImVec2& c, float s, bool outline, ImU32 col_outline, bool fill, ImU32 col_fill, float weight) {
  787. ImVec2 marker[3] = {ImVec2(1,0), ImVec2(-0.5, SQRT_3_2), ImVec2(-0.5, -SQRT_3_2)};
  788. RenderMarkerGeneral(DrawList, marker, 3, c, s, outline, col_outline, fill, col_fill, weight);
  789. }
  790. inline void RenderMarkerAsterisk(ImDrawList& DrawList, const ImVec2& c, float s, bool /*outline*/, ImU32 col_outline, bool /*fill*/, ImU32 /*col_fill*/, float weight) {
  791. ImVec2 marker[6] = {ImVec2(SQRT_3_2, 0.5f), ImVec2(0, -1), ImVec2(-SQRT_3_2, 0.5f), ImVec2(SQRT_3_2, -0.5f), ImVec2(0, 1), ImVec2(-SQRT_3_2, -0.5f)};
  792. TransformMarker(marker, 6, c, s);
  793. DrawList.AddLine(marker[0], marker[5], col_outline, weight);
  794. DrawList.AddLine(marker[1], marker[4], col_outline, weight);
  795. DrawList.AddLine(marker[2], marker[3], col_outline, weight);
  796. }
  797. inline void RenderMarkerPlus(ImDrawList& DrawList, const ImVec2& c, float s, bool /*outline*/, ImU32 col_outline, bool /*fill*/, ImU32 /*col_fill*/, float weight) {
  798. ImVec2 marker[4] = {ImVec2(1, 0), ImVec2(0, -1), ImVec2(-1, 0), ImVec2(0, 1)};
  799. TransformMarker(marker, 4, c, s);
  800. DrawList.AddLine(marker[0], marker[2], col_outline, weight);
  801. DrawList.AddLine(marker[1], marker[3], col_outline, weight);
  802. }
  803. inline void RenderMarkerCross(ImDrawList& DrawList, const ImVec2& c, float s, bool /*outline*/, ImU32 col_outline, bool /*fill*/, ImU32 /*col_fill*/, float weight) {
  804. ImVec2 marker[4] = {ImVec2(SQRT_1_2,SQRT_1_2),ImVec2(SQRT_1_2,-SQRT_1_2),ImVec2(-SQRT_1_2,-SQRT_1_2),ImVec2(-SQRT_1_2,SQRT_1_2)};
  805. TransformMarker(marker, 4, c, s);
  806. DrawList.AddLine(marker[0], marker[2], col_outline, weight);
  807. DrawList.AddLine(marker[1], marker[3], col_outline, weight);
  808. }
  809. template <typename Transformer, typename Getter>
  810. inline void RenderMarkers(Getter getter, Transformer transformer, ImDrawList& DrawList, ImPlotMarker marker, float size, bool rend_mk_line, ImU32 col_mk_line, float weight, bool rend_mk_fill, ImU32 col_mk_fill) {
  811. static void (*marker_table[ImPlotMarker_COUNT])(ImDrawList&, const ImVec2&, float s, bool, ImU32, bool, ImU32, float) = {
  812. RenderMarkerCircle,
  813. RenderMarkerSquare,
  814. RenderMarkerDiamond ,
  815. RenderMarkerUp ,
  816. RenderMarkerDown ,
  817. RenderMarkerLeft,
  818. RenderMarkerRight,
  819. RenderMarkerCross,
  820. RenderMarkerPlus,
  821. RenderMarkerAsterisk
  822. };
  823. ImPlotContext& gp = *GImPlot;
  824. const ImRect& rect = gp.CurrentPlot->PlotRect;
  825. for (int i = 0; i < getter.Count; ++i) {
  826. ImVec2 c = transformer(getter(i));
  827. if (c.x >= rect.Min.x && c.y >= rect.Min.y && c.x <= rect.Max.x && c.y <= rect.Max.y)
  828. marker_table[marker](DrawList, c, size, rend_mk_line, col_mk_line, rend_mk_fill, col_mk_fill, weight);
  829. }
  830. }
  831. //-----------------------------------------------------------------------------
  832. // PLOT LINE
  833. //-----------------------------------------------------------------------------
  834. template <typename Getter>
  835. inline void PlotLineEx(const char* label_id, const Getter& getter) {
  836. if (BeginItem(label_id, ImPlotCol_Line)) {
  837. if (FitThisFrame()) {
  838. for (int i = 0; i < getter.Count; ++i) {
  839. ImPlotPoint p = getter(i);
  840. FitPoint(p);
  841. }
  842. }
  843. const ImPlotNextItemData& s = GetItemData();
  844. ImDrawList& DrawList = *GetPlotDrawList();
  845. if (getter.Count > 1 && s.RenderLine) {
  846. const ImU32 col_line = ImGui::GetColorU32(s.Colors[ImPlotCol_Line]);
  847. switch (GetCurrentScale()) {
  848. case ImPlotScale_LinLin: RenderLineStrip(getter, TransformerLinLin(), DrawList, s.LineWeight, col_line); break;
  849. case ImPlotScale_LogLin: RenderLineStrip(getter, TransformerLogLin(), DrawList, s.LineWeight, col_line); break;
  850. case ImPlotScale_LinLog: RenderLineStrip(getter, TransformerLinLog(), DrawList, s.LineWeight, col_line); break;
  851. case ImPlotScale_LogLog: RenderLineStrip(getter, TransformerLogLog(), DrawList, s.LineWeight, col_line); break;
  852. }
  853. }
  854. // render markers
  855. if (s.Marker != ImPlotMarker_None) {
  856. PopPlotClipRect();
  857. PushPlotClipRect(s.MarkerSize);
  858. const ImU32 col_line = ImGui::GetColorU32(s.Colors[ImPlotCol_MarkerOutline]);
  859. const ImU32 col_fill = ImGui::GetColorU32(s.Colors[ImPlotCol_MarkerFill]);
  860. switch (GetCurrentScale()) {
  861. case ImPlotScale_LinLin: RenderMarkers(getter, TransformerLinLin(), DrawList, s.Marker, s.MarkerSize, s.RenderMarkerLine, col_line, s.MarkerWeight, s.RenderMarkerFill, col_fill); break;
  862. case ImPlotScale_LogLin: RenderMarkers(getter, TransformerLogLin(), DrawList, s.Marker, s.MarkerSize, s.RenderMarkerLine, col_line, s.MarkerWeight, s.RenderMarkerFill, col_fill); break;
  863. case ImPlotScale_LinLog: RenderMarkers(getter, TransformerLinLog(), DrawList, s.Marker, s.MarkerSize, s.RenderMarkerLine, col_line, s.MarkerWeight, s.RenderMarkerFill, col_fill); break;
  864. case ImPlotScale_LogLog: RenderMarkers(getter, TransformerLogLog(), DrawList, s.Marker, s.MarkerSize, s.RenderMarkerLine, col_line, s.MarkerWeight, s.RenderMarkerFill, col_fill); break;
  865. }
  866. }
  867. EndItem();
  868. }
  869. }
  870. template <typename T>
  871. void PlotLine(const char* label_id, const T* values, int count, double xscale, double x0, int offset, int stride) {
  872. GetterYs<T> getter(values,count,xscale,x0,offset,stride);
  873. PlotLineEx(label_id, getter);
  874. }
  875. template IMPLOT_API void PlotLine<ImS8> (const char* label_id, const ImS8* values, int count, double xscale, double x0, int offset, int stride);
  876. template IMPLOT_API void PlotLine<ImU8> (const char* label_id, const ImU8* values, int count, double xscale, double x0, int offset, int stride);
  877. template IMPLOT_API void PlotLine<ImS16>(const char* label_id, const ImS16* values, int count, double xscale, double x0, int offset, int stride);
  878. template IMPLOT_API void PlotLine<ImU16>(const char* label_id, const ImU16* values, int count, double xscale, double x0, int offset, int stride);
  879. template IMPLOT_API void PlotLine<ImS32>(const char* label_id, const ImS32* values, int count, double xscale, double x0, int offset, int stride);
  880. template IMPLOT_API void PlotLine<ImU32>(const char* label_id, const ImU32* values, int count, double xscale, double x0, int offset, int stride);
  881. template IMPLOT_API void PlotLine<ImS64>(const char* label_id, const ImS64* values, int count, double xscale, double x0, int offset, int stride);
  882. template IMPLOT_API void PlotLine<ImU64>(const char* label_id, const ImU64* values, int count, double xscale, double x0, int offset, int stride);
  883. template IMPLOT_API void PlotLine<float>(const char* label_id, const float* values, int count, double xscale, double x0, int offset, int stride);
  884. template IMPLOT_API void PlotLine<double>(const char* label_id, const double* values, int count, double xscale, double x0, int offset, int stride);
  885. template <typename T>
  886. void PlotLine(const char* label_id, const T* xs, const T* ys, int count, int offset, int stride) {
  887. GetterXsYs<T> getter(xs,ys,count,offset,stride);
  888. return PlotLineEx(label_id, getter);
  889. }
  890. template IMPLOT_API void PlotLine<ImS8>(const char* label_id, const ImS8* xs, const ImS8* ys, int count, int offset, int stride);
  891. template IMPLOT_API void PlotLine<ImU8>(const char* label_id, const ImU8* xs, const ImU8* ys, int count, int offset, int stride);
  892. template IMPLOT_API void PlotLine<ImS16>(const char* label_id, const ImS16* xs, const ImS16* ys, int count, int offset, int stride);
  893. template IMPLOT_API void PlotLine<ImU16>(const char* label_id, const ImU16* xs, const ImU16* ys, int count, int offset, int stride);
  894. template IMPLOT_API void PlotLine<ImS32>(const char* label_id, const ImS32* xs, const ImS32* ys, int count, int offset, int stride);
  895. template IMPLOT_API void PlotLine<ImU32>(const char* label_id, const ImU32* xs, const ImU32* ys, int count, int offset, int stride);
  896. template IMPLOT_API void PlotLine<ImS64>(const char* label_id, const ImS64* xs, const ImS64* ys, int count, int offset, int stride);
  897. template IMPLOT_API void PlotLine<ImU64>(const char* label_id, const ImU64* xs, const ImU64* ys, int count, int offset, int stride);
  898. template IMPLOT_API void PlotLine<float>(const char* label_id, const float* xs, const float* ys, int count, int offset, int stride);
  899. template IMPLOT_API void PlotLine<double>(const char* label_id, const double* xs, const double* ys, int count, int offset, int stride);
  900. // custom
  901. void PlotLineG(const char* label_id, ImPlotPoint (*getter_func)(void* data, int idx), void* data, int count, int offset) {
  902. GetterFuncPtr getter(getter_func,data, count, offset);
  903. return PlotLineEx(label_id, getter);
  904. }
  905. //-----------------------------------------------------------------------------
  906. // PLOT SCATTER
  907. //-----------------------------------------------------------------------------
  908. template <typename Getter>
  909. inline void PlotScatterEx(const char* label_id, const Getter& getter) {
  910. if (BeginItem(label_id, ImPlotCol_MarkerOutline)) {
  911. if (FitThisFrame()) {
  912. for (int i = 0; i < getter.Count; ++i) {
  913. ImPlotPoint p = getter(i);
  914. FitPoint(p);
  915. }
  916. }
  917. const ImPlotNextItemData& s = GetItemData();
  918. ImDrawList& DrawList = *GetPlotDrawList();
  919. // render markers
  920. ImPlotMarker marker = s.Marker == ImPlotMarker_None ? ImPlotMarker_Circle : s.Marker;
  921. if (marker != ImPlotMarker_None) {
  922. PopPlotClipRect();
  923. PushPlotClipRect(s.MarkerSize);
  924. const ImU32 col_line = ImGui::GetColorU32(s.Colors[ImPlotCol_MarkerOutline]);
  925. const ImU32 col_fill = ImGui::GetColorU32(s.Colors[ImPlotCol_MarkerFill]);
  926. switch (GetCurrentScale()) {
  927. case ImPlotScale_LinLin: RenderMarkers(getter, TransformerLinLin(), DrawList, marker, s.MarkerSize, s.RenderMarkerLine, col_line, s.MarkerWeight, s.RenderMarkerFill, col_fill); break;
  928. case ImPlotScale_LogLin: RenderMarkers(getter, TransformerLogLin(), DrawList, marker, s.MarkerSize, s.RenderMarkerLine, col_line, s.MarkerWeight, s.RenderMarkerFill, col_fill); break;
  929. case ImPlotScale_LinLog: RenderMarkers(getter, TransformerLinLog(), DrawList, marker, s.MarkerSize, s.RenderMarkerLine, col_line, s.MarkerWeight, s.RenderMarkerFill, col_fill); break;
  930. case ImPlotScale_LogLog: RenderMarkers(getter, TransformerLogLog(), DrawList, marker, s.MarkerSize, s.RenderMarkerLine, col_line, s.MarkerWeight, s.RenderMarkerFill, col_fill); break;
  931. }
  932. }
  933. EndItem();
  934. }
  935. }
  936. template <typename T>
  937. void PlotScatter(const char* label_id, const T* values, int count, double xscale, double x0, int offset, int stride) {
  938. GetterYs<T> getter(values,count,xscale,x0,offset,stride);
  939. PlotScatterEx(label_id, getter);
  940. }
  941. template IMPLOT_API void PlotScatter<ImS8>(const char* label_id, const ImS8* values, int count, double xscale, double x0, int offset, int stride);
  942. template IMPLOT_API void PlotScatter<ImU8>(const char* label_id, const ImU8* values, int count, double xscale, double x0, int offset, int stride);
  943. template IMPLOT_API void PlotScatter<ImS16>(const char* label_id, const ImS16* values, int count, double xscale, double x0, int offset, int stride);
  944. template IMPLOT_API void PlotScatter<ImU16>(const char* label_id, const ImU16* values, int count, double xscale, double x0, int offset, int stride);
  945. template IMPLOT_API void PlotScatter<ImS32>(const char* label_id, const ImS32* values, int count, double xscale, double x0, int offset, int stride);
  946. template IMPLOT_API void PlotScatter<ImU32>(const char* label_id, const ImU32* values, int count, double xscale, double x0, int offset, int stride);
  947. template IMPLOT_API void PlotScatter<ImS64>(const char* label_id, const ImS64* values, int count, double xscale, double x0, int offset, int stride);
  948. template IMPLOT_API void PlotScatter<ImU64>(const char* label_id, const ImU64* values, int count, double xscale, double x0, int offset, int stride);
  949. template IMPLOT_API void PlotScatter<float>(const char* label_id, const float* values, int count, double xscale, double x0, int offset, int stride);
  950. template IMPLOT_API void PlotScatter<double>(const char* label_id, const double* values, int count, double xscale, double x0, int offset, int stride);
  951. template <typename T>
  952. void PlotScatter(const char* label_id, const T* xs, const T* ys, int count, int offset, int stride) {
  953. GetterXsYs<T> getter(xs,ys,count,offset,stride);
  954. return PlotScatterEx(label_id, getter);
  955. }
  956. template IMPLOT_API void PlotScatter<ImS8>(const char* label_id, const ImS8* xs, const ImS8* ys, int count, int offset, int stride);
  957. template IMPLOT_API void PlotScatter<ImU8>(const char* label_id, const ImU8* xs, const ImU8* ys, int count, int offset, int stride);
  958. template IMPLOT_API void PlotScatter<ImS16>(const char* label_id, const ImS16* xs, const ImS16* ys, int count, int offset, int stride);
  959. template IMPLOT_API void PlotScatter<ImU16>(const char* label_id, const ImU16* xs, const ImU16* ys, int count, int offset, int stride);
  960. template IMPLOT_API void PlotScatter<ImS32>(const char* label_id, const ImS32* xs, const ImS32* ys, int count, int offset, int stride);
  961. template IMPLOT_API void PlotScatter<ImU32>(const char* label_id, const ImU32* xs, const ImU32* ys, int count, int offset, int stride);
  962. template IMPLOT_API void PlotScatter<ImS64>(const char* label_id, const ImS64* xs, const ImS64* ys, int count, int offset, int stride);
  963. template IMPLOT_API void PlotScatter<ImU64>(const char* label_id, const ImU64* xs, const ImU64* ys, int count, int offset, int stride);
  964. template IMPLOT_API void PlotScatter<float>(const char* label_id, const float* xs, const float* ys, int count, int offset, int stride);
  965. template IMPLOT_API void PlotScatter<double>(const char* label_id, const double* xs, const double* ys, int count, int offset, int stride);
  966. // custom
  967. void PlotScatterG(const char* label_id, ImPlotPoint (*getter_func)(void* data, int idx), void* data, int count, int offset) {
  968. GetterFuncPtr getter(getter_func,data, count, offset);
  969. return PlotScatterEx(label_id, getter);
  970. }
  971. //-----------------------------------------------------------------------------
  972. // PLOT STAIRS
  973. //-----------------------------------------------------------------------------
  974. template <typename Getter>
  975. inline void PlotStairsEx(const char* label_id, const Getter& getter) {
  976. if (BeginItem(label_id, ImPlotCol_Line)) {
  977. if (FitThisFrame()) {
  978. for (int i = 0; i < getter.Count; ++i) {
  979. ImPlotPoint p = getter(i);
  980. FitPoint(p);
  981. }
  982. }
  983. const ImPlotNextItemData& s = GetItemData();
  984. ImDrawList& DrawList = *GetPlotDrawList();
  985. if (getter.Count > 1 && s.RenderLine) {
  986. const ImU32 col_line = ImGui::GetColorU32(s.Colors[ImPlotCol_Line]);
  987. switch (GetCurrentScale()) {
  988. case ImPlotScale_LinLin: RenderStairs(getter, TransformerLinLin(), DrawList, s.LineWeight, col_line); break;
  989. case ImPlotScale_LogLin: RenderStairs(getter, TransformerLogLin(), DrawList, s.LineWeight, col_line); break;
  990. case ImPlotScale_LinLog: RenderStairs(getter, TransformerLinLog(), DrawList, s.LineWeight, col_line); break;
  991. case ImPlotScale_LogLog: RenderStairs(getter, TransformerLogLog(), DrawList, s.LineWeight, col_line); break;
  992. }
  993. }
  994. // render markers
  995. if (s.Marker != ImPlotMarker_None) {
  996. PopPlotClipRect();
  997. PushPlotClipRect(s.MarkerSize);
  998. const ImU32 col_line = ImGui::GetColorU32(s.Colors[ImPlotCol_MarkerOutline]);
  999. const ImU32 col_fill = ImGui::GetColorU32(s.Colors[ImPlotCol_MarkerFill]);
  1000. switch (GetCurrentScale()) {
  1001. case ImPlotScale_LinLin: RenderMarkers(getter, TransformerLinLin(), DrawList, s.Marker, s.MarkerSize, s.RenderMarkerLine, col_line, s.MarkerWeight, s.RenderMarkerFill, col_fill); break;
  1002. case ImPlotScale_LogLin: RenderMarkers(getter, TransformerLogLin(), DrawList, s.Marker, s.MarkerSize, s.RenderMarkerLine, col_line, s.MarkerWeight, s.RenderMarkerFill, col_fill); break;
  1003. case ImPlotScale_LinLog: RenderMarkers(getter, TransformerLinLog(), DrawList, s.Marker, s.MarkerSize, s.RenderMarkerLine, col_line, s.MarkerWeight, s.RenderMarkerFill, col_fill); break;
  1004. case ImPlotScale_LogLog: RenderMarkers(getter, TransformerLogLog(), DrawList, s.Marker, s.MarkerSize, s.RenderMarkerLine, col_line, s.MarkerWeight, s.RenderMarkerFill, col_fill); break;
  1005. }
  1006. }
  1007. EndItem();
  1008. }
  1009. }
  1010. template <typename T>
  1011. void PlotStairs(const char* label_id, const T* values, int count, double xscale, double x0, int offset, int stride) {
  1012. GetterYs<T> getter(values,count,xscale,x0,offset,stride);
  1013. PlotStairsEx(label_id, getter);
  1014. }
  1015. template IMPLOT_API void PlotStairs<ImS8> (const char* label_id, const ImS8* values, int count, double xscale, double x0, int offset, int stride);
  1016. template IMPLOT_API void PlotStairs<ImU8> (const char* label_id, const ImU8* values, int count, double xscale, double x0, int offset, int stride);
  1017. template IMPLOT_API void PlotStairs<ImS16>(const char* label_id, const ImS16* values, int count, double xscale, double x0, int offset, int stride);
  1018. template IMPLOT_API void PlotStairs<ImU16>(const char* label_id, const ImU16* values, int count, double xscale, double x0, int offset, int stride);
  1019. template IMPLOT_API void PlotStairs<ImS32>(const char* label_id, const ImS32* values, int count, double xscale, double x0, int offset, int stride);
  1020. template IMPLOT_API void PlotStairs<ImU32>(const char* label_id, const ImU32* values, int count, double xscale, double x0, int offset, int stride);
  1021. template IMPLOT_API void PlotStairs<ImS64>(const char* label_id, const ImS64* values, int count, double xscale, double x0, int offset, int stride);
  1022. template IMPLOT_API void PlotStairs<ImU64>(const char* label_id, const ImU64* values, int count, double xscale, double x0, int offset, int stride);
  1023. template IMPLOT_API void PlotStairs<float>(const char* label_id, const float* values, int count, double xscale, double x0, int offset, int stride);
  1024. template IMPLOT_API void PlotStairs<double>(const char* label_id, const double* values, int count, double xscale, double x0, int offset, int stride);
  1025. template <typename T>
  1026. void PlotStairs(const char* label_id, const T* xs, const T* ys, int count, int offset, int stride) {
  1027. GetterXsYs<T> getter(xs,ys,count,offset,stride);
  1028. return PlotStairsEx(label_id, getter);
  1029. }
  1030. template IMPLOT_API void PlotStairs<ImS8>(const char* label_id, const ImS8* xs, const ImS8* ys, int count, int offset, int stride);
  1031. template IMPLOT_API void PlotStairs<ImU8>(const char* label_id, const ImU8* xs, const ImU8* ys, int count, int offset, int stride);
  1032. template IMPLOT_API void PlotStairs<ImS16>(const char* label_id, const ImS16* xs, const ImS16* ys, int count, int offset, int stride);
  1033. template IMPLOT_API void PlotStairs<ImU16>(const char* label_id, const ImU16* xs, const ImU16* ys, int count, int offset, int stride);
  1034. template IMPLOT_API void PlotStairs<ImS32>(const char* label_id, const ImS32* xs, const ImS32* ys, int count, int offset, int stride);
  1035. template IMPLOT_API void PlotStairs<ImU32>(const char* label_id, const ImU32* xs, const ImU32* ys, int count, int offset, int stride);
  1036. template IMPLOT_API void PlotStairs<ImS64>(const char* label_id, const ImS64* xs, const ImS64* ys, int count, int offset, int stride);
  1037. template IMPLOT_API void PlotStairs<ImU64>(const char* label_id, const ImU64* xs, const ImU64* ys, int count, int offset, int stride);
  1038. template IMPLOT_API void PlotStairs<float>(const char* label_id, const float* xs, const float* ys, int count, int offset, int stride);
  1039. template IMPLOT_API void PlotStairs<double>(const char* label_id, const double* xs, const double* ys, int count, int offset, int stride);
  1040. // custom
  1041. void PlotStairsG(const char* label_id, ImPlotPoint (*getter_func)(void* data, int idx), void* data, int count, int offset) {
  1042. GetterFuncPtr getter(getter_func,data, count, offset);
  1043. return PlotStairsEx(label_id, getter);
  1044. }
  1045. //-----------------------------------------------------------------------------
  1046. // PLOT SHADED
  1047. //-----------------------------------------------------------------------------
  1048. template <typename Getter1, typename Getter2>
  1049. inline void PlotShadedEx(const char* label_id, const Getter1& getter1, const Getter2& getter2, bool fit2) {
  1050. if (BeginItem(label_id, ImPlotCol_Fill)) {
  1051. if (FitThisFrame()) {
  1052. for (int i = 0; i < getter1.Count; ++i)
  1053. FitPoint(getter1(i));
  1054. if (fit2) {
  1055. for (int i = 0; i < getter2.Count; ++i)
  1056. FitPoint(getter2(i));
  1057. }
  1058. }
  1059. const ImPlotNextItemData& s = GetItemData();
  1060. ImDrawList & DrawList = *GetPlotDrawList();
  1061. if (s.RenderFill) {
  1062. ImU32 col = ImGui::GetColorU32(s.Colors[ImPlotCol_Fill]);
  1063. switch (GetCurrentScale()) {
  1064. case ImPlotScale_LinLin: RenderPrimitives(ShadedRenderer<Getter1,Getter2,TransformerLinLin>(getter1,getter2,TransformerLinLin(), col), DrawList, GImPlot->CurrentPlot->PlotRect); break;
  1065. case ImPlotScale_LogLin: RenderPrimitives(ShadedRenderer<Getter1,Getter2,TransformerLogLin>(getter1,getter2,TransformerLogLin(), col), DrawList, GImPlot->CurrentPlot->PlotRect); break;
  1066. case ImPlotScale_LinLog: RenderPrimitives(ShadedRenderer<Getter1,Getter2,TransformerLinLog>(getter1,getter2,TransformerLinLog(), col), DrawList, GImPlot->CurrentPlot->PlotRect); break;
  1067. case ImPlotScale_LogLog: RenderPrimitives(ShadedRenderer<Getter1,Getter2,TransformerLogLog>(getter1,getter2,TransformerLogLog(), col), DrawList, GImPlot->CurrentPlot->PlotRect); break;
  1068. }
  1069. }
  1070. EndItem();
  1071. }
  1072. }
  1073. template <typename T>
  1074. void PlotShaded(const char* label_id, const T* values, int count, double y_ref, double xscale, double x0, int offset, int stride) {
  1075. bool fit2 = true;
  1076. if (y_ref == -HUGE_VAL) {
  1077. fit2 = false;
  1078. y_ref = GetPlotLimits().Y.Min;
  1079. }
  1080. if (y_ref == HUGE_VAL) {
  1081. fit2 = false;
  1082. y_ref = GetPlotLimits().Y.Max;
  1083. }
  1084. GetterYs<T> getter1(values,count,xscale,x0,offset,stride);
  1085. GetterYRef getter2(y_ref,count,xscale,x0);
  1086. PlotShadedEx(label_id, getter1, getter2, fit2);
  1087. }
  1088. template IMPLOT_API void PlotShaded<ImS8>(const char* label_id, const ImS8* values, int count, double y_ref, double xscale, double x0, int offset, int stride);
  1089. template IMPLOT_API void PlotShaded<ImU8>(const char* label_id, const ImU8* values, int count, double y_ref, double xscale, double x0, int offset, int stride);
  1090. template IMPLOT_API void PlotShaded<ImS16>(const char* label_id, const ImS16* values, int count, double y_ref, double xscale, double x0, int offset, int stride);
  1091. template IMPLOT_API void PlotShaded<ImU16>(const char* label_id, const ImU16* values, int count, double y_ref, double xscale, double x0, int offset, int stride);
  1092. template IMPLOT_API void PlotShaded<ImS32>(const char* label_id, const ImS32* values, int count, double y_ref, double xscale, double x0, int offset, int stride);
  1093. template IMPLOT_API void PlotShaded<ImU32>(const char* label_id, const ImU32* values, int count, double y_ref, double xscale, double x0, int offset, int stride);
  1094. template IMPLOT_API void PlotShaded<ImS64>(const char* label_id, const ImS64* values, int count, double y_ref, double xscale, double x0, int offset, int stride);
  1095. template IMPLOT_API void PlotShaded<ImU64>(const char* label_id, const ImU64* values, int count, double y_ref, double xscale, double x0, int offset, int stride);
  1096. template IMPLOT_API void PlotShaded<float>(const char* label_id, const float* values, int count, double y_ref, double xscale, double x0, int offset, int stride);
  1097. template IMPLOT_API void PlotShaded<double>(const char* label_id, const double* values, int count, double y_ref, double xscale, double x0, int offset, int stride);
  1098. template <typename T>
  1099. void PlotShaded(const char* label_id, const T* xs, const T* ys, int count, double y_ref, int offset, int stride) {
  1100. bool fit2 = true;
  1101. if (y_ref == -HUGE_VAL) {
  1102. fit2 = false;
  1103. y_ref = GetPlotLimits().Y.Min;
  1104. }
  1105. if (y_ref == HUGE_VAL) {
  1106. fit2 = false;
  1107. y_ref = GetPlotLimits().Y.Max;
  1108. }
  1109. GetterXsYs<T> getter1(xs, ys, count, offset, stride);
  1110. GetterXsYRef<T> getter2(xs, y_ref, count, offset, stride);
  1111. PlotShadedEx(label_id, getter1, getter2, fit2);
  1112. }
  1113. template IMPLOT_API void PlotShaded<ImS8>(const char* label_id, const ImS8* xs, const ImS8* ys, int count, double y_ref, int offset, int stride);
  1114. template IMPLOT_API void PlotShaded<ImU8>(const char* label_id, const ImU8* xs, const ImU8* ys, int count, double y_ref, int offset, int stride);
  1115. template IMPLOT_API void PlotShaded<ImS16>(const char* label_id, const ImS16* xs, const ImS16* ys, int count, double y_ref, int offset, int stride);
  1116. template IMPLOT_API void PlotShaded<ImU16>(const char* label_id, const ImU16* xs, const ImU16* ys, int count, double y_ref, int offset, int stride);
  1117. template IMPLOT_API void PlotShaded<ImS32>(const char* label_id, const ImS32* xs, const ImS32* ys, int count, double y_ref, int offset, int stride);
  1118. template IMPLOT_API void PlotShaded<ImU32>(const char* label_id, const ImU32* xs, const ImU32* ys, int count, double y_ref, int offset, int stride);
  1119. template IMPLOT_API void PlotShaded<ImS64>(const char* label_id, const ImS64* xs, const ImS64* ys, int count, double y_ref, int offset, int stride);
  1120. template IMPLOT_API void PlotShaded<ImU64>(const char* label_id, const ImU64* xs, const ImU64* ys, int count, double y_ref, int offset, int stride);
  1121. template IMPLOT_API void PlotShaded<float>(const char* label_id, const float* xs, const float* ys, int count, double y_ref, int offset, int stride);
  1122. template IMPLOT_API void PlotShaded<double>(const char* label_id, const double* xs, const double* ys, int count, double y_ref, int offset, int stride);
  1123. template <typename T>
  1124. void PlotShaded(const char* label_id, const T* xs, const T* ys1, const T* ys2, int count, int offset, int stride) {
  1125. GetterXsYs<T> getter1(xs, ys1, count, offset, stride);
  1126. GetterXsYs<T> getter2(xs, ys2, count, offset, stride);
  1127. PlotShadedEx(label_id, getter1, getter2, true);
  1128. }
  1129. template IMPLOT_API void PlotShaded<ImS8>(const char* label_id, const ImS8* xs, const ImS8* ys1, const ImS8* ys2, int count, int offset, int stride);
  1130. template IMPLOT_API void PlotShaded<ImU8>(const char* label_id, const ImU8* xs, const ImU8* ys1, const ImU8* ys2, int count, int offset, int stride);
  1131. template IMPLOT_API void PlotShaded<ImS16>(const char* label_id, const ImS16* xs, const ImS16* ys1, const ImS16* ys2, int count, int offset, int stride);
  1132. template IMPLOT_API void PlotShaded<ImU16>(const char* label_id, const ImU16* xs, const ImU16* ys1, const ImU16* ys2, int count, int offset, int stride);
  1133. template IMPLOT_API void PlotShaded<ImS32>(const char* label_id, const ImS32* xs, const ImS32* ys1, const ImS32* ys2, int count, int offset, int stride);
  1134. template IMPLOT_API void PlotShaded<ImU32>(const char* label_id, const ImU32* xs, const ImU32* ys1, const ImU32* ys2, int count, int offset, int stride);
  1135. template IMPLOT_API void PlotShaded<ImS64>(const char* label_id, const ImS64* xs, const ImS64* ys1, const ImS64* ys2, int count, int offset, int stride);
  1136. template IMPLOT_API void PlotShaded<ImU64>(const char* label_id, const ImU64* xs, const ImU64* ys1, const ImU64* ys2, int count, int offset, int stride);
  1137. template IMPLOT_API void PlotShaded<float>(const char* label_id, const float* xs, const float* ys1, const float* ys2, int count, int offset, int stride);
  1138. template IMPLOT_API void PlotShaded<double>(const char* label_id, const double* xs, const double* ys1, const double* ys2, int count, int offset, int stride);
  1139. // custom
  1140. void PlotShadedG(const char* label_id, ImPlotPoint (*g1)(void* data, int idx), void* data1, ImPlotPoint (*g2)(void* data, int idx), void* data2, int count, int offset) {
  1141. GetterFuncPtr getter1(g1, data1, count, offset);
  1142. GetterFuncPtr getter2(g2, data2, count, offset);
  1143. PlotShadedEx(label_id, getter1, getter2, true);
  1144. }
  1145. //-----------------------------------------------------------------------------
  1146. // PLOT BAR
  1147. //-----------------------------------------------------------------------------
  1148. // TODO: Migrate to RenderPrimitives
  1149. template <typename Getter>
  1150. void PlotBarsEx(const char* label_id, const Getter& getter, double width) {
  1151. if (BeginItem(label_id, ImPlotCol_Fill)) {
  1152. const double half_width = width / 2;
  1153. if (FitThisFrame()) {
  1154. for (int i = 0; i < getter.Count; ++i) {
  1155. ImPlotPoint p = getter(i);
  1156. FitPoint(ImPlotPoint(p.x - half_width, p.y));
  1157. FitPoint(ImPlotPoint(p.x + half_width, 0));
  1158. }
  1159. }
  1160. const ImPlotNextItemData& s = GetItemData();
  1161. ImDrawList& DrawList = *GetPlotDrawList();
  1162. ImU32 col_line = ImGui::GetColorU32(s.Colors[ImPlotCol_Line]);
  1163. ImU32 col_fill = ImGui::GetColorU32(s.Colors[ImPlotCol_Fill]);
  1164. bool rend_line = s.RenderLine;
  1165. if (s.RenderFill && col_line == col_fill)
  1166. rend_line = false;
  1167. for (int i = 0; i < getter.Count; ++i) {
  1168. ImPlotPoint p = getter(i);
  1169. if (p.y == 0)
  1170. continue;
  1171. ImVec2 a = PlotToPixels(p.x - half_width, p.y);
  1172. ImVec2 b = PlotToPixels(p.x + half_width, 0);
  1173. if (s.RenderFill)
  1174. DrawList.AddRectFilled(a, b, col_fill);
  1175. if (rend_line)
  1176. DrawList.AddRect(a, b, col_line, 0, ImDrawFlags_RoundCornersAll, s.LineWeight);
  1177. }
  1178. EndItem();
  1179. }
  1180. }
  1181. template <typename T>
  1182. void PlotBars(const char* label_id, const T* values, int count, double width, double shift, int offset, int stride) {
  1183. GetterBarV<T> getter(values,shift,count,offset,stride);
  1184. PlotBarsEx(label_id, getter, width);
  1185. }
  1186. template IMPLOT_API void PlotBars<ImS8>(const char* label_id, const ImS8* values, int count, double width, double shift, int offset, int stride);
  1187. template IMPLOT_API void PlotBars<ImU8>(const char* label_id, const ImU8* values, int count, double width, double shift, int offset, int stride);
  1188. template IMPLOT_API void PlotBars<ImS16>(const char* label_id, const ImS16* values, int count, double width, double shift, int offset, int stride);
  1189. template IMPLOT_API void PlotBars<ImU16>(const char* label_id, const ImU16* values, int count, double width, double shift, int offset, int stride);
  1190. template IMPLOT_API void PlotBars<ImS32>(const char* label_id, const ImS32* values, int count, double width, double shift, int offset, int stride);
  1191. template IMPLOT_API void PlotBars<ImU32>(const char* label_id, const ImU32* values, int count, double width, double shift, int offset, int stride);
  1192. template IMPLOT_API void PlotBars<ImS64>(const char* label_id, const ImS64* values, int count, double width, double shift, int offset, int stride);
  1193. template IMPLOT_API void PlotBars<ImU64>(const char* label_id, const ImU64* values, int count, double width, double shift, int offset, int stride);
  1194. template IMPLOT_API void PlotBars<float>(const char* label_id, const float* values, int count, double width, double shift, int offset, int stride);
  1195. template IMPLOT_API void PlotBars<double>(const char* label_id, const double* values, int count, double width, double shift, int offset, int stride);
  1196. template <typename T>
  1197. void PlotBars(const char* label_id, const T* xs, const T* ys, int count, double width, int offset, int stride) {
  1198. GetterXsYs<T> getter(xs,ys,count,offset,stride);
  1199. PlotBarsEx(label_id, getter, width);
  1200. }
  1201. template IMPLOT_API void PlotBars<ImS8>(const char* label_id, const ImS8* xs, const ImS8* ys, int count, double width, int offset, int stride);
  1202. template IMPLOT_API void PlotBars<ImU8>(const char* label_id, const ImU8* xs, const ImU8* ys, int count, double width, int offset, int stride);
  1203. template IMPLOT_API void PlotBars<ImS16>(const char* label_id, const ImS16* xs, const ImS16* ys, int count, double width, int offset, int stride);
  1204. template IMPLOT_API void PlotBars<ImU16>(const char* label_id, const ImU16* xs, const ImU16* ys, int count, double width, int offset, int stride);
  1205. template IMPLOT_API void PlotBars<ImS32>(const char* label_id, const ImS32* xs, const ImS32* ys, int count, double width, int offset, int stride);
  1206. template IMPLOT_API void PlotBars<ImU32>(const char* label_id, const ImU32* xs, const ImU32* ys, int count, double width, int offset, int stride);
  1207. template IMPLOT_API void PlotBars<ImS64>(const char* label_id, const ImS64* xs, const ImS64* ys, int count, double width, int offset, int stride);
  1208. template IMPLOT_API void PlotBars<ImU64>(const char* label_id, const ImU64* xs, const ImU64* ys, int count, double width, int offset, int stride);
  1209. template IMPLOT_API void PlotBars<float>(const char* label_id, const float* xs, const float* ys, int count, double width, int offset, int stride);
  1210. template IMPLOT_API void PlotBars<double>(const char* label_id, const double* xs, const double* ys, int count, double width, int offset, int stride);
  1211. // custom
  1212. void PlotBarsG(const char* label_id, ImPlotPoint (*getter_func)(void* data, int idx), void* data, int count, double width, int offset) {
  1213. GetterFuncPtr getter(getter_func, data, count, offset);
  1214. PlotBarsEx(label_id, getter, width);
  1215. }
  1216. //-----------------------------------------------------------------------------
  1217. // PLOT BAR H
  1218. //-----------------------------------------------------------------------------
  1219. // TODO: Migrate to RenderPrimitives
  1220. template <typename Getter, typename THeight>
  1221. void PlotBarsHEx(const char* label_id, const Getter& getter, THeight height) {
  1222. if (BeginItem(label_id, ImPlotCol_Fill)) {
  1223. const THeight half_height = height / 2;
  1224. if (FitThisFrame()) {
  1225. for (int i = 0; i < getter.Count; ++i) {
  1226. ImPlotPoint p = getter(i);
  1227. FitPoint(ImPlotPoint(0, p.y - half_height));
  1228. FitPoint(ImPlotPoint(p.x, p.y + half_height));
  1229. }
  1230. }
  1231. const ImPlotNextItemData& s = GetItemData();
  1232. ImDrawList& DrawList = *GetPlotDrawList();
  1233. ImU32 col_line = ImGui::GetColorU32(s.Colors[ImPlotCol_Line]);
  1234. ImU32 col_fill = ImGui::GetColorU32(s.Colors[ImPlotCol_Fill]);
  1235. bool rend_line = s.RenderLine;
  1236. if (s.RenderFill && col_line == col_fill)
  1237. rend_line = false;
  1238. for (int i = 0; i < getter.Count; ++i) {
  1239. ImPlotPoint p = getter(i);
  1240. if (p.x == 0)
  1241. continue;
  1242. ImVec2 a = PlotToPixels(0, p.y - half_height);
  1243. ImVec2 b = PlotToPixels(p.x, p.y + half_height);
  1244. if (s.RenderFill)
  1245. DrawList.AddRectFilled(a, b, col_fill);
  1246. if (rend_line)
  1247. DrawList.AddRect(a, b, col_line, 0, ImDrawFlags_RoundCornersAll, s.LineWeight);
  1248. }
  1249. EndItem();
  1250. }
  1251. }
  1252. template <typename T>
  1253. void PlotBarsH(const char* label_id, const T* values, int count, double height, double shift, int offset, int stride) {
  1254. GetterBarH<T> getter(values,shift,count,offset,stride);
  1255. PlotBarsHEx(label_id, getter, height);
  1256. }
  1257. template IMPLOT_API void PlotBarsH<ImS8>(const char* label_id, const ImS8* values, int count, double height, double shift, int offset, int stride);
  1258. template IMPLOT_API void PlotBarsH<ImU8>(const char* label_id, const ImU8* values, int count, double height, double shift, int offset, int stride);
  1259. template IMPLOT_API void PlotBarsH<ImS16>(const char* label_id, const ImS16* values, int count, double height, double shift, int offset, int stride);
  1260. template IMPLOT_API void PlotBarsH<ImU16>(const char* label_id, const ImU16* values, int count, double height, double shift, int offset, int stride);
  1261. template IMPLOT_API void PlotBarsH<ImS32>(const char* label_id, const ImS32* values, int count, double height, double shift, int offset, int stride);
  1262. template IMPLOT_API void PlotBarsH<ImU32>(const char* label_id, const ImU32* values, int count, double height, double shift, int offset, int stride);
  1263. template IMPLOT_API void PlotBarsH<ImS64>(const char* label_id, const ImS64* values, int count, double height, double shift, int offset, int stride);
  1264. template IMPLOT_API void PlotBarsH<ImU64>(const char* label_id, const ImU64* values, int count, double height, double shift, int offset, int stride);
  1265. template IMPLOT_API void PlotBarsH<float>(const char* label_id, const float* values, int count, double height, double shift, int offset, int stride);
  1266. template IMPLOT_API void PlotBarsH<double>(const char* label_id, const double* values, int count, double height, double shift, int offset, int stride);
  1267. template <typename T>
  1268. void PlotBarsH(const char* label_id, const T* xs, const T* ys, int count, double height, int offset, int stride) {
  1269. GetterXsYs<T> getter(xs,ys,count,offset,stride);
  1270. PlotBarsHEx(label_id, getter, height);
  1271. }
  1272. template IMPLOT_API void PlotBarsH<ImS8>(const char* label_id, const ImS8* xs, const ImS8* ys, int count, double height, int offset, int stride);
  1273. template IMPLOT_API void PlotBarsH<ImU8>(const char* label_id, const ImU8* xs, const ImU8* ys, int count, double height, int offset, int stride);
  1274. template IMPLOT_API void PlotBarsH<ImS16>(const char* label_id, const ImS16* xs, const ImS16* ys, int count, double height, int offset, int stride);
  1275. template IMPLOT_API void PlotBarsH<ImU16>(const char* label_id, const ImU16* xs, const ImU16* ys, int count, double height, int offset, int stride);
  1276. template IMPLOT_API void PlotBarsH<ImS32>(const char* label_id, const ImS32* xs, const ImS32* ys, int count, double height, int offset, int stride);
  1277. template IMPLOT_API void PlotBarsH<ImU32>(const char* label_id, const ImU32* xs, const ImU32* ys, int count, double height, int offset, int stride);
  1278. template IMPLOT_API void PlotBarsH<ImS64>(const char* label_id, const ImS64* xs, const ImS64* ys, int count, double height, int offset, int stride);
  1279. template IMPLOT_API void PlotBarsH<ImU64>(const char* label_id, const ImU64* xs, const ImU64* ys, int count, double height, int offset, int stride);
  1280. template IMPLOT_API void PlotBarsH<float>(const char* label_id, const float* xs, const float* ys, int count, double height, int offset, int stride);
  1281. template IMPLOT_API void PlotBarsH<double>(const char* label_id, const double* xs, const double* ys, int count, double height, int offset, int stride);
  1282. // custom
  1283. void PlotBarsHG(const char* label_id, ImPlotPoint (*getter_func)(void* data, int idx), void* data, int count, double height, int offset) {
  1284. GetterFuncPtr getter(getter_func, data, count, offset);
  1285. PlotBarsHEx(label_id, getter, height);
  1286. }
  1287. //-----------------------------------------------------------------------------
  1288. // PLOT ERROR BARS
  1289. //-----------------------------------------------------------------------------
  1290. template <typename Getter>
  1291. void PlotErrorBarsEx(const char* label_id, const Getter& getter) {
  1292. if (BeginItem(label_id)) {
  1293. if (FitThisFrame()) {
  1294. for (int i = 0; i < getter.Count; ++i) {
  1295. ImPlotPointError e = getter(i);
  1296. FitPoint(ImPlotPoint(e.X , e.Y - e.Neg));
  1297. FitPoint(ImPlotPoint(e.X , e.Y + e.Pos ));
  1298. }
  1299. }
  1300. const ImPlotNextItemData& s = GetItemData();
  1301. ImDrawList& DrawList = *GetPlotDrawList();
  1302. const ImU32 col = ImGui::GetColorU32(s.Colors[ImPlotCol_ErrorBar]);
  1303. const bool rend_whisker = s.ErrorBarSize > 0;
  1304. const float half_whisker = s.ErrorBarSize * 0.5f;
  1305. for (int i = 0; i < getter.Count; ++i) {
  1306. ImPlotPointError e = getter(i);
  1307. ImVec2 p1 = PlotToPixels(e.X, e.Y - e.Neg);
  1308. ImVec2 p2 = PlotToPixels(e.X, e.Y + e.Pos);
  1309. DrawList.AddLine(p1,p2,col, s.ErrorBarWeight);
  1310. if (rend_whisker) {
  1311. DrawList.AddLine(p1 - ImVec2(half_whisker, 0), p1 + ImVec2(half_whisker, 0), col, s.ErrorBarWeight);
  1312. DrawList.AddLine(p2 - ImVec2(half_whisker, 0), p2 + ImVec2(half_whisker, 0), col, s.ErrorBarWeight);
  1313. }
  1314. }
  1315. EndItem();
  1316. }
  1317. }
  1318. template <typename T>
  1319. void PlotErrorBars(const char* label_id, const T* xs, const T* ys, const T* err, int count, int offset, int stride) {
  1320. GetterError<T> getter(xs, ys, err, err, count, offset, stride);
  1321. PlotErrorBarsEx(label_id, getter);
  1322. }
  1323. template IMPLOT_API void PlotErrorBars<ImS8>(const char* label_id, const ImS8* xs, const ImS8* ys, const ImS8* err, int count, int offset, int stride);
  1324. template IMPLOT_API void PlotErrorBars<ImU8>(const char* label_id, const ImU8* xs, const ImU8* ys, const ImU8* err, int count, int offset, int stride);
  1325. template IMPLOT_API void PlotErrorBars<ImS16>(const char* label_id, const ImS16* xs, const ImS16* ys, const ImS16* err, int count, int offset, int stride);
  1326. template IMPLOT_API void PlotErrorBars<ImU16>(const char* label_id, const ImU16* xs, const ImU16* ys, const ImU16* err, int count, int offset, int stride);
  1327. template IMPLOT_API void PlotErrorBars<ImS32>(const char* label_id, const ImS32* xs, const ImS32* ys, const ImS32* err, int count, int offset, int stride);
  1328. template IMPLOT_API void PlotErrorBars<ImU32>(const char* label_id, const ImU32* xs, const ImU32* ys, const ImU32* err, int count, int offset, int stride);
  1329. template IMPLOT_API void PlotErrorBars<ImS64>(const char* label_id, const ImS64* xs, const ImS64* ys, const ImS64* err, int count, int offset, int stride);
  1330. template IMPLOT_API void PlotErrorBars<ImU64>(const char* label_id, const ImU64* xs, const ImU64* ys, const ImU64* err, int count, int offset, int stride);
  1331. template IMPLOT_API void PlotErrorBars<float>(const char* label_id, const float* xs, const float* ys, const float* err, int count, int offset, int stride);
  1332. template IMPLOT_API void PlotErrorBars<double>(const char* label_id, const double* xs, const double* ys, const double* err, int count, int offset, int stride);
  1333. template <typename T>
  1334. void PlotErrorBars(const char* label_id, const T* xs, const T* ys, const T* neg, const T* pos, int count, int offset, int stride) {
  1335. GetterError<T> getter(xs, ys, neg, pos, count, offset, stride);
  1336. PlotErrorBarsEx(label_id, getter);
  1337. }
  1338. template IMPLOT_API void PlotErrorBars<ImS8>(const char* label_id, const ImS8* xs, const ImS8* ys, const ImS8* neg, const ImS8* pos, int count, int offset, int stride);
  1339. template IMPLOT_API void PlotErrorBars<ImU8>(const char* label_id, const ImU8* xs, const ImU8* ys, const ImU8* neg, const ImU8* pos, int count, int offset, int stride);
  1340. template IMPLOT_API void PlotErrorBars<ImS16>(const char* label_id, const ImS16* xs, const ImS16* ys, const ImS16* neg, const ImS16* pos, int count, int offset, int stride);
  1341. template IMPLOT_API void PlotErrorBars<ImU16>(const char* label_id, const ImU16* xs, const ImU16* ys, const ImU16* neg, const ImU16* pos, int count, int offset, int stride);
  1342. template IMPLOT_API void PlotErrorBars<ImS32>(const char* label_id, const ImS32* xs, const ImS32* ys, const ImS32* neg, const ImS32* pos, int count, int offset, int stride);
  1343. template IMPLOT_API void PlotErrorBars<ImU32>(const char* label_id, const ImU32* xs, const ImU32* ys, const ImU32* neg, const ImU32* pos, int count, int offset, int stride);
  1344. template IMPLOT_API void PlotErrorBars<ImS64>(const char* label_id, const ImS64* xs, const ImS64* ys, const ImS64* neg, const ImS64* pos, int count, int offset, int stride);
  1345. template IMPLOT_API void PlotErrorBars<ImU64>(const char* label_id, const ImU64* xs, const ImU64* ys, const ImU64* neg, const ImU64* pos, int count, int offset, int stride);
  1346. template IMPLOT_API void PlotErrorBars<float>(const char* label_id, const float* xs, const float* ys, const float* neg, const float* pos, int count, int offset, int stride);
  1347. template IMPLOT_API void PlotErrorBars<double>(const char* label_id, const double* xs, const double* ys, const double* neg, const double* pos, int count, int offset, int stride);
  1348. //-----------------------------------------------------------------------------
  1349. // PLOT ERROR BARS H
  1350. //-----------------------------------------------------------------------------
  1351. template <typename Getter>
  1352. void PlotErrorBarsHEx(const char* label_id, const Getter& getter) {
  1353. if (BeginItem(label_id)) {
  1354. if (FitThisFrame()) {
  1355. for (int i = 0; i < getter.Count; ++i) {
  1356. ImPlotPointError e = getter(i);
  1357. FitPoint(ImPlotPoint(e.X - e.Neg, e.Y));
  1358. FitPoint(ImPlotPoint(e.X + e.Pos, e.Y));
  1359. }
  1360. }
  1361. const ImPlotNextItemData& s = GetItemData();
  1362. ImDrawList& DrawList = *GetPlotDrawList();
  1363. const ImU32 col = ImGui::GetColorU32(s.Colors[ImPlotCol_ErrorBar]);
  1364. const bool rend_whisker = s.ErrorBarSize > 0;
  1365. const float half_whisker = s.ErrorBarSize * 0.5f;
  1366. for (int i = 0; i < getter.Count; ++i) {
  1367. ImPlotPointError e = getter(i);
  1368. ImVec2 p1 = PlotToPixels(e.X - e.Neg, e.Y);
  1369. ImVec2 p2 = PlotToPixels(e.X + e.Pos, e.Y);
  1370. DrawList.AddLine(p1, p2, col, s.ErrorBarWeight);
  1371. if (rend_whisker) {
  1372. DrawList.AddLine(p1 - ImVec2(0, half_whisker), p1 + ImVec2(0, half_whisker), col, s.ErrorBarWeight);
  1373. DrawList.AddLine(p2 - ImVec2(0, half_whisker), p2 + ImVec2(0, half_whisker), col, s.ErrorBarWeight);
  1374. }
  1375. }
  1376. EndItem();
  1377. }
  1378. }
  1379. template <typename T>
  1380. void PlotErrorBarsH(const char* label_id, const T* xs, const T* ys, const T* err, int count, int offset, int stride) {
  1381. GetterError<T> getter(xs, ys, err, err, count, offset, stride);
  1382. PlotErrorBarsHEx(label_id, getter);
  1383. }
  1384. template IMPLOT_API void PlotErrorBarsH<ImS8>(const char* label_id, const ImS8* xs, const ImS8* ys, const ImS8* err, int count, int offset, int stride);
  1385. template IMPLOT_API void PlotErrorBarsH<ImU8>(const char* label_id, const ImU8* xs, const ImU8* ys, const ImU8* err, int count, int offset, int stride);
  1386. template IMPLOT_API void PlotErrorBarsH<ImS16>(const char* label_id, const ImS16* xs, const ImS16* ys, const ImS16* err, int count, int offset, int stride);
  1387. template IMPLOT_API void PlotErrorBarsH<ImU16>(const char* label_id, const ImU16* xs, const ImU16* ys, const ImU16* err, int count, int offset, int stride);
  1388. template IMPLOT_API void PlotErrorBarsH<ImS32>(const char* label_id, const ImS32* xs, const ImS32* ys, const ImS32* err, int count, int offset, int stride);
  1389. template IMPLOT_API void PlotErrorBarsH<ImU32>(const char* label_id, const ImU32* xs, const ImU32* ys, const ImU32* err, int count, int offset, int stride);
  1390. template IMPLOT_API void PlotErrorBarsH<ImS64>(const char* label_id, const ImS64* xs, const ImS64* ys, const ImS64* err, int count, int offset, int stride);
  1391. template IMPLOT_API void PlotErrorBarsH<ImU64>(const char* label_id, const ImU64* xs, const ImU64* ys, const ImU64* err, int count, int offset, int stride);
  1392. template IMPLOT_API void PlotErrorBarsH<float>(const char* label_id, const float* xs, const float* ys, const float* err, int count, int offset, int stride);
  1393. template IMPLOT_API void PlotErrorBarsH<double>(const char* label_id, const double* xs, const double* ys, const double* err, int count, int offset, int stride);
  1394. template <typename T>
  1395. void PlotErrorBarsH(const char* label_id, const T* xs, const T* ys, const T* neg, const T* pos, int count, int offset, int stride) {
  1396. GetterError<T> getter(xs, ys, neg, pos, count, offset, stride);
  1397. PlotErrorBarsHEx(label_id, getter);
  1398. }
  1399. template IMPLOT_API void PlotErrorBarsH<ImS8>(const char* label_id, const ImS8* xs, const ImS8* ys, const ImS8* neg, const ImS8* pos, int count, int offset, int stride);
  1400. template IMPLOT_API void PlotErrorBarsH<ImU8>(const char* label_id, const ImU8* xs, const ImU8* ys, const ImU8* neg, const ImU8* pos, int count, int offset, int stride);
  1401. template IMPLOT_API void PlotErrorBarsH<ImS16>(const char* label_id, const ImS16* xs, const ImS16* ys, const ImS16* neg, const ImS16* pos, int count, int offset, int stride);
  1402. template IMPLOT_API void PlotErrorBarsH<ImU16>(const char* label_id, const ImU16* xs, const ImU16* ys, const ImU16* neg, const ImU16* pos, int count, int offset, int stride);
  1403. template IMPLOT_API void PlotErrorBarsH<ImS32>(const char* label_id, const ImS32* xs, const ImS32* ys, const ImS32* neg, const ImS32* pos, int count, int offset, int stride);
  1404. template IMPLOT_API void PlotErrorBarsH<ImU32>(const char* label_id, const ImU32* xs, const ImU32* ys, const ImU32* neg, const ImU32* pos, int count, int offset, int stride);
  1405. template IMPLOT_API void PlotErrorBarsH<ImS64>(const char* label_id, const ImS64* xs, const ImS64* ys, const ImS64* neg, const ImS64* pos, int count, int offset, int stride);
  1406. template IMPLOT_API void PlotErrorBarsH<ImU64>(const char* label_id, const ImU64* xs, const ImU64* ys, const ImU64* neg, const ImU64* pos, int count, int offset, int stride);
  1407. template IMPLOT_API void PlotErrorBarsH<float>(const char* label_id, const float* xs, const float* ys, const float* neg, const float* pos, int count, int offset, int stride);
  1408. template IMPLOT_API void PlotErrorBarsH<double>(const char* label_id, const double* xs, const double* ys, const double* neg, const double* pos, int count, int offset, int stride);
  1409. //-----------------------------------------------------------------------------
  1410. // PLOT STEMS
  1411. //-----------------------------------------------------------------------------
  1412. template <typename GetterM, typename GetterB>
  1413. inline void PlotStemsEx(const char* label_id, const GetterM& get_mark, const GetterB& get_base) {
  1414. if (BeginItem(label_id, ImPlotCol_Line)) {
  1415. if (FitThisFrame()) {
  1416. for (int i = 0; i < get_base.Count; ++i) {
  1417. FitPoint(get_mark(i));
  1418. FitPoint(get_base(i));
  1419. }
  1420. }
  1421. const ImPlotNextItemData& s = GetItemData();
  1422. ImDrawList& DrawList = *GetPlotDrawList();
  1423. // render stems
  1424. if (s.RenderLine) {
  1425. const ImU32 col_line = ImGui::GetColorU32(s.Colors[ImPlotCol_Line]);
  1426. switch (GetCurrentScale()) {
  1427. case ImPlotScale_LinLin: RenderLineSegments(get_mark, get_base, TransformerLinLin(), DrawList, s.LineWeight, col_line); break;
  1428. case ImPlotScale_LogLin: RenderLineSegments(get_mark, get_base, TransformerLogLin(), DrawList, s.LineWeight, col_line); break;
  1429. case ImPlotScale_LinLog: RenderLineSegments(get_mark, get_base, TransformerLinLog(), DrawList, s.LineWeight, col_line); break;
  1430. case ImPlotScale_LogLog: RenderLineSegments(get_mark, get_base, TransformerLogLog(), DrawList, s.LineWeight, col_line); break;
  1431. }
  1432. }
  1433. // render markers
  1434. ImPlotMarker marker = s.Marker == ImPlotMarker_None ? ImPlotMarker_Circle : s.Marker;
  1435. if (marker != ImPlotMarker_None) {
  1436. PopPlotClipRect();
  1437. PushPlotClipRect(s.MarkerSize);
  1438. const ImU32 col_line = ImGui::GetColorU32(s.Colors[ImPlotCol_MarkerOutline]);
  1439. const ImU32 col_fill = ImGui::GetColorU32(s.Colors[ImPlotCol_MarkerFill]);
  1440. switch (GetCurrentScale()) {
  1441. case ImPlotScale_LinLin: RenderMarkers(get_mark, TransformerLinLin(), DrawList, marker, s.MarkerSize, s.RenderMarkerLine, col_line, s.MarkerWeight, s.RenderMarkerFill, col_fill); break;
  1442. case ImPlotScale_LogLin: RenderMarkers(get_mark, TransformerLogLin(), DrawList, marker, s.MarkerSize, s.RenderMarkerLine, col_line, s.MarkerWeight, s.RenderMarkerFill, col_fill); break;
  1443. case ImPlotScale_LinLog: RenderMarkers(get_mark, TransformerLinLog(), DrawList, marker, s.MarkerSize, s.RenderMarkerLine, col_line, s.MarkerWeight, s.RenderMarkerFill, col_fill); break;
  1444. case ImPlotScale_LogLog: RenderMarkers(get_mark, TransformerLogLog(), DrawList, marker, s.MarkerSize, s.RenderMarkerLine, col_line, s.MarkerWeight, s.RenderMarkerFill, col_fill); break;
  1445. }
  1446. }
  1447. EndItem();
  1448. }
  1449. }
  1450. template <typename T>
  1451. void PlotStems(const char* label_id, const T* values, int count, double y_ref, double xscale, double x0, int offset, int stride) {
  1452. GetterYs<T> get_mark(values,count,xscale,x0,offset,stride);
  1453. GetterYRef get_base(y_ref,count,xscale,x0);
  1454. PlotStemsEx(label_id, get_mark, get_base);
  1455. }
  1456. template IMPLOT_API void PlotStems<ImS8>(const char* label_id, const ImS8* values, int count, double y_ref, double xscale, double x0, int offset, int stride);
  1457. template IMPLOT_API void PlotStems<ImU8>(const char* label_id, const ImU8* values, int count, double y_ref, double xscale, double x0, int offset, int stride);
  1458. template IMPLOT_API void PlotStems<ImS16>(const char* label_id, const ImS16* values, int count, double y_ref, double xscale, double x0, int offset, int stride);
  1459. template IMPLOT_API void PlotStems<ImU16>(const char* label_id, const ImU16* values, int count, double y_ref, double xscale, double x0, int offset, int stride);
  1460. template IMPLOT_API void PlotStems<ImS32>(const char* label_id, const ImS32* values, int count, double y_ref, double xscale, double x0, int offset, int stride);
  1461. template IMPLOT_API void PlotStems<ImU32>(const char* label_id, const ImU32* values, int count, double y_ref, double xscale, double x0, int offset, int stride);
  1462. template IMPLOT_API void PlotStems<ImS64>(const char* label_id, const ImS64* values, int count, double y_ref, double xscale, double x0, int offset, int stride);
  1463. template IMPLOT_API void PlotStems<ImU64>(const char* label_id, const ImU64* values, int count, double y_ref, double xscale, double x0, int offset, int stride);
  1464. template IMPLOT_API void PlotStems<float>(const char* label_id, const float* values, int count, double y_ref, double xscale, double x0, int offset, int stride);
  1465. template IMPLOT_API void PlotStems<double>(const char* label_id, const double* values, int count, double y_ref, double xscale, double x0, int offset, int stride);
  1466. template <typename T>
  1467. void PlotStems(const char* label_id, const T* xs, const T* ys, int count, double y_ref, int offset, int stride) {
  1468. GetterXsYs<T> get_mark(xs,ys,count,offset,stride);
  1469. GetterXsYRef<T> get_base(xs,y_ref,count,offset,stride);
  1470. PlotStemsEx(label_id, get_mark, get_base);
  1471. }
  1472. template IMPLOT_API void PlotStems<ImS8>(const char* label_id, const ImS8* xs, const ImS8* ys, int count, double y_ref, int offset, int stride);
  1473. template IMPLOT_API void PlotStems<ImU8>(const char* label_id, const ImU8* xs, const ImU8* ys, int count, double y_ref, int offset, int stride);
  1474. template IMPLOT_API void PlotStems<ImS16>(const char* label_id, const ImS16* xs, const ImS16* ys, int count, double y_ref, int offset, int stride);
  1475. template IMPLOT_API void PlotStems<ImU16>(const char* label_id, const ImU16* xs, const ImU16* ys, int count, double y_ref, int offset, int stride);
  1476. template IMPLOT_API void PlotStems<ImS32>(const char* label_id, const ImS32* xs, const ImS32* ys, int count, double y_ref, int offset, int stride);
  1477. template IMPLOT_API void PlotStems<ImU32>(const char* label_id, const ImU32* xs, const ImU32* ys, int count, double y_ref, int offset, int stride);
  1478. template IMPLOT_API void PlotStems<ImS64>(const char* label_id, const ImS64* xs, const ImS64* ys, int count, double y_ref, int offset, int stride);
  1479. template IMPLOT_API void PlotStems<ImU64>(const char* label_id, const ImU64* xs, const ImU64* ys, int count, double y_ref, int offset, int stride);
  1480. template IMPLOT_API void PlotStems<float>(const char* label_id, const float* xs, const float* ys, int count, double y_ref, int offset, int stride);
  1481. template IMPLOT_API void PlotStems<double>(const char* label_id, const double* xs, const double* ys, int count, double y_ref, int offset, int stride);
  1482. //-----------------------------------------------------------------------------
  1483. // INFINITE LINES
  1484. //-----------------------------------------------------------------------------
  1485. template <typename T>
  1486. void PlotVLines(const char* label_id, const T* xs, int count, int offset, int stride) {
  1487. if (BeginItem(label_id, ImPlotCol_Line)) {
  1488. const ImPlotLimits lims = GetPlotLimits();
  1489. GetterXsYRef<T> get_min(xs,lims.Y.Min,count,offset,stride);
  1490. GetterXsYRef<T> get_max(xs,lims.Y.Max,count,offset,stride);
  1491. if (FitThisFrame()) {
  1492. for (int i = 0; i < get_min.Count; ++i)
  1493. FitPointX(get_min(i).x);
  1494. }
  1495. const ImPlotNextItemData& s = GetItemData();
  1496. ImDrawList& DrawList = *GetPlotDrawList();
  1497. // render stems
  1498. if (s.RenderLine) {
  1499. const ImU32 col_line = ImGui::GetColorU32(s.Colors[ImPlotCol_Line]);
  1500. switch (GetCurrentScale()) {
  1501. case ImPlotScale_LinLin: RenderLineSegments(get_min, get_max, TransformerLinLin(), DrawList, s.LineWeight, col_line); break;
  1502. case ImPlotScale_LogLin: RenderLineSegments(get_min, get_max, TransformerLogLin(), DrawList, s.LineWeight, col_line); break;
  1503. case ImPlotScale_LinLog: RenderLineSegments(get_min, get_max, TransformerLinLog(), DrawList, s.LineWeight, col_line); break;
  1504. case ImPlotScale_LogLog: RenderLineSegments(get_min, get_max, TransformerLogLog(), DrawList, s.LineWeight, col_line); break;
  1505. }
  1506. }
  1507. EndItem();
  1508. }
  1509. }
  1510. template IMPLOT_API void PlotVLines<ImS8>(const char* label_id, const ImS8* xs, int count, int offset, int stride);
  1511. template IMPLOT_API void PlotVLines<ImU8>(const char* label_id, const ImU8* xs, int count, int offset, int stride);
  1512. template IMPLOT_API void PlotVLines<ImS16>(const char* label_id, const ImS16* xs, int count, int offset, int stride);
  1513. template IMPLOT_API void PlotVLines<ImU16>(const char* label_id, const ImU16* xs, int count, int offset, int stride);
  1514. template IMPLOT_API void PlotVLines<ImS32>(const char* label_id, const ImS32* xs, int count, int offset, int stride);
  1515. template IMPLOT_API void PlotVLines<ImU32>(const char* label_id, const ImU32* xs, int count, int offset, int stride);
  1516. template IMPLOT_API void PlotVLines<ImS64>(const char* label_id, const ImS64* xs, int count, int offset, int stride);
  1517. template IMPLOT_API void PlotVLines<ImU64>(const char* label_id, const ImU64* xs, int count, int offset, int stride);
  1518. template IMPLOT_API void PlotVLines<float>(const char* label_id, const float* xs, int count, int offset, int stride);
  1519. template IMPLOT_API void PlotVLines<double>(const char* label_id, const double* xs, int count, int offset, int stride);
  1520. template <typename T>
  1521. void PlotHLines(const char* label_id, const T* ys, int count, int offset, int stride) {
  1522. if (BeginItem(label_id, ImPlotCol_Line)) {
  1523. const ImPlotLimits lims = GetPlotLimits();
  1524. GetterXRefYs<T> get_min(lims.X.Min,ys,count,offset,stride);
  1525. GetterXRefYs<T> get_max(lims.X.Max,ys,count,offset,stride);
  1526. if (FitThisFrame()) {
  1527. for (int i = 0; i < get_min.Count; ++i)
  1528. FitPointY(get_min(i).y);
  1529. }
  1530. const ImPlotNextItemData& s = GetItemData();
  1531. ImDrawList& DrawList = *GetPlotDrawList();
  1532. // render stems
  1533. if (s.RenderLine) {
  1534. const ImU32 col_line = ImGui::GetColorU32(s.Colors[ImPlotCol_Line]);
  1535. switch (GetCurrentScale()) {
  1536. case ImPlotScale_LinLin: RenderLineSegments(get_min, get_max, TransformerLinLin(), DrawList, s.LineWeight, col_line); break;
  1537. case ImPlotScale_LogLin: RenderLineSegments(get_min, get_max, TransformerLogLin(), DrawList, s.LineWeight, col_line); break;
  1538. case ImPlotScale_LinLog: RenderLineSegments(get_min, get_max, TransformerLinLog(), DrawList, s.LineWeight, col_line); break;
  1539. case ImPlotScale_LogLog: RenderLineSegments(get_min, get_max, TransformerLogLog(), DrawList, s.LineWeight, col_line); break;
  1540. }
  1541. }
  1542. EndItem();
  1543. }
  1544. }
  1545. template IMPLOT_API void PlotHLines<ImS8>(const char* label_id, const ImS8* ys, int count, int offset, int stride);
  1546. template IMPLOT_API void PlotHLines<ImU8>(const char* label_id, const ImU8* ys, int count, int offset, int stride);
  1547. template IMPLOT_API void PlotHLines<ImS16>(const char* label_id, const ImS16* ys, int count, int offset, int stride);
  1548. template IMPLOT_API void PlotHLines<ImU16>(const char* label_id, const ImU16* ys, int count, int offset, int stride);
  1549. template IMPLOT_API void PlotHLines<ImS32>(const char* label_id, const ImS32* ys, int count, int offset, int stride);
  1550. template IMPLOT_API void PlotHLines<ImU32>(const char* label_id, const ImU32* ys, int count, int offset, int stride);
  1551. template IMPLOT_API void PlotHLines<ImS64>(const char* label_id, const ImS64* ys, int count, int offset, int stride);
  1552. template IMPLOT_API void PlotHLines<ImU64>(const char* label_id, const ImU64* ys, int count, int offset, int stride);
  1553. template IMPLOT_API void PlotHLines<float>(const char* label_id, const float* ys, int count, int offset, int stride);
  1554. template IMPLOT_API void PlotHLines<double>(const char* label_id, const double* ys, int count, int offset, int stride);
  1555. //-----------------------------------------------------------------------------
  1556. // PLOT PIE CHART
  1557. //-----------------------------------------------------------------------------
  1558. inline void RenderPieSlice(ImDrawList& DrawList, const ImPlotPoint& center, double radius, double a0, double a1, ImU32 col) {
  1559. static const float resolution = 50 / (2 * IM_PI);
  1560. static ImVec2 buffer[50];
  1561. buffer[0] = PlotToPixels(center);
  1562. int n = ImMax(3, (int)((a1 - a0) * resolution));
  1563. double da = (a1 - a0) / (n - 1);
  1564. for (int i = 0; i < n; ++i) {
  1565. double a = a0 + i * da;
  1566. buffer[i + 1] = PlotToPixels(center.x + radius * cos(a), center.y + radius * sin(a));
  1567. }
  1568. DrawList.AddConvexPolyFilled(buffer, n + 1, col);
  1569. }
  1570. template <typename T>
  1571. void PlotPieChart(const char* const label_ids[], const T* values, int count, double x, double y, double radius, bool normalize, const char* fmt, double angle0) {
  1572. IM_ASSERT_USER_ERROR(GImPlot->CurrentPlot != NULL, "PlotPieChart() needs to be called between BeginPlot() and EndPlot()!");
  1573. ImDrawList & DrawList = *GetPlotDrawList();
  1574. double sum = 0;
  1575. for (int i = 0; i < count; ++i)
  1576. sum += (double)values[i];
  1577. normalize = normalize || sum > 1.0;
  1578. ImPlotPoint center(x,y);
  1579. PushPlotClipRect();
  1580. double a0 = angle0 * 2 * IM_PI / 360.0;
  1581. double a1 = angle0 * 2 * IM_PI / 360.0;
  1582. for (int i = 0; i < count; ++i) {
  1583. double percent = normalize ? (double)values[i] / sum : (double)values[i];
  1584. a1 = a0 + 2 * IM_PI * percent;
  1585. if (BeginItem(label_ids[i])) {
  1586. if (FitThisFrame()) {
  1587. FitPoint(ImPlotPoint(x-radius,y-radius));
  1588. FitPoint(ImPlotPoint(x+radius,y+radius));
  1589. }
  1590. ImU32 col = GetCurrentItem()->Color;
  1591. if (percent < 0.5) {
  1592. RenderPieSlice(DrawList, center, radius, a0, a1, col);
  1593. }
  1594. else {
  1595. RenderPieSlice(DrawList, center, radius, a0, a0 + (a1 - a0) * 0.5, col);
  1596. RenderPieSlice(DrawList, center, radius, a0 + (a1 - a0) * 0.5, a1, col);
  1597. }
  1598. EndItem();
  1599. }
  1600. a0 = a1;
  1601. }
  1602. if (fmt != NULL) {
  1603. a0 = angle0 * 2 * IM_PI / 360.0;
  1604. a1 = angle0 * 2 * IM_PI / 360.0;
  1605. char buffer[32];
  1606. for (int i = 0; i < count; ++i) {
  1607. ImPlotItem* item = GetItem(label_ids[i]);
  1608. double percent = normalize ? (double)values[i] / sum : (double)values[i];
  1609. a1 = a0 + 2 * IM_PI * percent;
  1610. if (item->Show) {
  1611. sprintf(buffer, fmt, (double)values[i]);
  1612. ImVec2 size = ImGui::CalcTextSize(buffer);
  1613. double angle = a0 + (a1 - a0) * 0.5;
  1614. ImVec2 pos = PlotToPixels(center.x + 0.5 * radius * cos(angle), center.y + 0.5 * radius * sin(angle));
  1615. ImU32 col = CalcTextColor(ImGui::ColorConvertU32ToFloat4(item->Color));
  1616. DrawList.AddText(pos - size * 0.5f, col, buffer);
  1617. }
  1618. a0 = a1;
  1619. }
  1620. }
  1621. PopPlotClipRect();
  1622. }
  1623. template IMPLOT_API void PlotPieChart<ImS8>(const char* const label_ids[], const ImS8* values, int count, double x, double y, double radius, bool normalize, const char* fmt, double angle0);
  1624. template IMPLOT_API void PlotPieChart<ImU8>(const char* const label_ids[], const ImU8* values, int count, double x, double y, double radius, bool normalize, const char* fmt, double angle0);
  1625. template IMPLOT_API void PlotPieChart<ImS16>(const char* const label_ids[], const ImS16* values, int count, double x, double y, double radius, bool normalize, const char* fmt, double angle0);
  1626. template IMPLOT_API void PlotPieChart<ImU16>(const char* const label_ids[], const ImU16* values, int count, double x, double y, double radius, bool normalize, const char* fmt, double angle0);
  1627. template IMPLOT_API void PlotPieChart<ImS32>(const char* const label_ids[], const ImS32* values, int count, double x, double y, double radius, bool normalize, const char* fmt, double angle0);
  1628. template IMPLOT_API void PlotPieChart<ImU32>(const char* const label_ids[], const ImU32* values, int count, double x, double y, double radius, bool normalize, const char* fmt, double angle0);
  1629. template IMPLOT_API void PlotPieChart<ImS64>(const char* const label_ids[], const ImS64* values, int count, double x, double y, double radius, bool normalize, const char* fmt, double angle0);
  1630. template IMPLOT_API void PlotPieChart<ImU64>(const char* const label_ids[], const ImU64* values, int count, double x, double y, double radius, bool normalize, const char* fmt, double angle0);
  1631. template IMPLOT_API void PlotPieChart<float>(const char* const label_ids[], const float* values, int count, double x, double y, double radius, bool normalize, const char* fmt, double angle0);
  1632. template IMPLOT_API void PlotPieChart<double>(const char* const label_ids[], const double* values, int count, double x, double y, double radius, bool normalize, const char* fmt, double angle0);
  1633. //-----------------------------------------------------------------------------
  1634. // PLOT HEATMAP
  1635. //-----------------------------------------------------------------------------
  1636. struct RectInfo {
  1637. ImPlotPoint Min, Max;
  1638. ImU32 Color;
  1639. };
  1640. template <typename TGetter, typename TTransformer>
  1641. struct RectRenderer {
  1642. inline RectRenderer(const TGetter& getter, const TTransformer& transformer) :
  1643. Getter(getter),
  1644. Transformer(transformer),
  1645. Prims(Getter.Count)
  1646. {}
  1647. inline bool operator()(ImDrawList& DrawList, const ImRect& cull_rect, const ImVec2& uv, int prim) const {
  1648. RectInfo rect = Getter(prim);
  1649. ImVec2 P1 = Transformer(rect.Min);
  1650. ImVec2 P2 = Transformer(rect.Max);
  1651. if ((rect.Color & IM_COL32_A_MASK) == 0 || !cull_rect.Overlaps(ImRect(ImMin(P1, P2), ImMax(P1, P2))))
  1652. return false;
  1653. DrawList._VtxWritePtr[0].pos = P1;
  1654. DrawList._VtxWritePtr[0].uv = uv;
  1655. DrawList._VtxWritePtr[0].col = rect.Color;
  1656. DrawList._VtxWritePtr[1].pos.x = P1.x;
  1657. DrawList._VtxWritePtr[1].pos.y = P2.y;
  1658. DrawList._VtxWritePtr[1].uv = uv;
  1659. DrawList._VtxWritePtr[1].col = rect.Color;
  1660. DrawList._VtxWritePtr[2].pos = P2;
  1661. DrawList._VtxWritePtr[2].uv = uv;
  1662. DrawList._VtxWritePtr[2].col = rect.Color;
  1663. DrawList._VtxWritePtr[3].pos.x = P2.x;
  1664. DrawList._VtxWritePtr[3].pos.y = P1.y;
  1665. DrawList._VtxWritePtr[3].uv = uv;
  1666. DrawList._VtxWritePtr[3].col = rect.Color;
  1667. DrawList._VtxWritePtr += 4;
  1668. DrawList._IdxWritePtr[0] = (ImDrawIdx)(DrawList._VtxCurrentIdx);
  1669. DrawList._IdxWritePtr[1] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 1);
  1670. DrawList._IdxWritePtr[2] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 3);
  1671. DrawList._IdxWritePtr[3] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 1);
  1672. DrawList._IdxWritePtr[4] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 2);
  1673. DrawList._IdxWritePtr[5] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 3);
  1674. DrawList._IdxWritePtr += 6;
  1675. DrawList._VtxCurrentIdx += 4;
  1676. return true;
  1677. }
  1678. const TGetter& Getter;
  1679. const TTransformer& Transformer;
  1680. const int Prims;
  1681. static const int IdxConsumed = 6;
  1682. static const int VtxConsumed = 4;
  1683. };
  1684. template <typename T>
  1685. struct GetterHeatmap {
  1686. GetterHeatmap(const T* values, int rows, int cols, double scale_min, double scale_max, double width, double height, double xref, double yref, double ydir) :
  1687. Values(values),
  1688. Count(rows*cols),
  1689. Rows(rows),
  1690. Cols(cols),
  1691. ScaleMin(scale_min),
  1692. ScaleMax(scale_max),
  1693. Width(width),
  1694. Height(height),
  1695. XRef(xref),
  1696. YRef(yref),
  1697. YDir(ydir),
  1698. HalfSize(Width*0.5, Height*0.5)
  1699. { }
  1700. inline RectInfo operator()(int idx) const {
  1701. double val = (double)Values[idx];
  1702. const int r = idx / Cols;
  1703. const int c = idx % Cols;
  1704. const ImPlotPoint p(XRef + HalfSize.x + c*Width, YRef + YDir * (HalfSize.y + r*Height));
  1705. RectInfo rect;
  1706. rect.Min.x = p.x - HalfSize.x;
  1707. rect.Min.y = p.y - HalfSize.y;
  1708. rect.Max.x = p.x + HalfSize.x;
  1709. rect.Max.y = p.y + HalfSize.y;
  1710. const float t = ImClamp((float)ImRemap01(val, ScaleMin, ScaleMax),0.0f,1.0f);
  1711. rect.Color = GImPlot->ColormapData.LerpTable(GImPlot->Style.Colormap, t);
  1712. return rect;
  1713. }
  1714. const T* const Values;
  1715. const int Count, Rows, Cols;
  1716. const double ScaleMin, ScaleMax, Width, Height, XRef, YRef, YDir;
  1717. const ImPlotPoint HalfSize;
  1718. };
  1719. template <typename T, typename Transformer>
  1720. void RenderHeatmap(Transformer transformer, ImDrawList& DrawList, const T* values, int rows, int cols, double scale_min, double scale_max, const char* fmt, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max, bool reverse_y) {
  1721. ImPlotContext& gp = *GImPlot;
  1722. if (scale_min == 0 && scale_max == 0) {
  1723. T temp_min, temp_max;
  1724. ImMinMaxArray(values,rows*cols,&temp_min,&temp_max);
  1725. scale_min = (double)temp_min;
  1726. scale_max = (double)temp_max;
  1727. }
  1728. if (scale_min == scale_max) {
  1729. ImVec2 a = transformer(bounds_min);
  1730. ImVec2 b = transformer(bounds_max);
  1731. ImU32 col = GetColormapColorU32(0,gp.Style.Colormap);
  1732. DrawList.AddRectFilled(a, b, col);
  1733. return;
  1734. }
  1735. const double yref = reverse_y ? bounds_max.y : bounds_min.y;
  1736. const double ydir = reverse_y ? -1 : 1;
  1737. GetterHeatmap<T> getter(values, rows, cols, scale_min, scale_max, (bounds_max.x - bounds_min.x) / cols, (bounds_max.y - bounds_min.y) / rows, bounds_min.x, yref, ydir);
  1738. switch (GetCurrentScale()) {
  1739. case ImPlotScale_LinLin: RenderPrimitives(RectRenderer<GetterHeatmap<T>, TransformerLinLin>(getter, TransformerLinLin()), DrawList, gp.CurrentPlot->PlotRect); break;
  1740. case ImPlotScale_LogLin: RenderPrimitives(RectRenderer<GetterHeatmap<T>, TransformerLogLin>(getter, TransformerLogLin()), DrawList, gp.CurrentPlot->PlotRect); break;;
  1741. case ImPlotScale_LinLog: RenderPrimitives(RectRenderer<GetterHeatmap<T>, TransformerLinLog>(getter, TransformerLinLog()), DrawList, gp.CurrentPlot->PlotRect); break;;
  1742. case ImPlotScale_LogLog: RenderPrimitives(RectRenderer<GetterHeatmap<T>, TransformerLogLog>(getter, TransformerLogLog()), DrawList, gp.CurrentPlot->PlotRect); break;;
  1743. }
  1744. if (fmt != NULL) {
  1745. const double w = (bounds_max.x - bounds_min.x) / cols;
  1746. const double h = (bounds_max.y - bounds_min.y) / rows;
  1747. const ImPlotPoint half_size(w*0.5,h*0.5);
  1748. int i = 0;
  1749. for (int r = 0; r < rows; ++r) {
  1750. for (int c = 0; c < cols; ++c) {
  1751. ImPlotPoint p;
  1752. p.x = bounds_min.x + 0.5*w + c*w;
  1753. p.y = yref + ydir * (0.5*h + r*h);
  1754. ImVec2 px = transformer(p);
  1755. char buff[32];
  1756. sprintf(buff, fmt, values[i]);
  1757. ImVec2 size = ImGui::CalcTextSize(buff);
  1758. double t = ImClamp(ImRemap01((double)values[i], scale_min, scale_max),0.0,1.0);
  1759. ImVec4 color = SampleColormap((float)t);
  1760. ImU32 col = CalcTextColor(color);
  1761. DrawList.AddText(px - size * 0.5f, col, buff);
  1762. i++;
  1763. }
  1764. }
  1765. }
  1766. }
  1767. template <typename T>
  1768. void PlotHeatmap(const char* label_id, const T* values, int rows, int cols, double scale_min, double scale_max, const char* fmt, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max) {
  1769. if (BeginItem(label_id)) {
  1770. if (FitThisFrame()) {
  1771. FitPoint(bounds_min);
  1772. FitPoint(bounds_max);
  1773. }
  1774. ImDrawList& DrawList = *GetPlotDrawList();
  1775. switch (GetCurrentScale()) {
  1776. case ImPlotScale_LinLin: RenderHeatmap(TransformerLinLin(), DrawList, values, rows, cols, scale_min, scale_max, fmt, bounds_min, bounds_max, true); break;
  1777. case ImPlotScale_LogLin: RenderHeatmap(TransformerLogLin(), DrawList, values, rows, cols, scale_min, scale_max, fmt, bounds_min, bounds_max, true); break;
  1778. case ImPlotScale_LinLog: RenderHeatmap(TransformerLinLog(), DrawList, values, rows, cols, scale_min, scale_max, fmt, bounds_min, bounds_max, true); break;
  1779. case ImPlotScale_LogLog: RenderHeatmap(TransformerLogLog(), DrawList, values, rows, cols, scale_min, scale_max, fmt, bounds_min, bounds_max, true); break;
  1780. }
  1781. EndItem();
  1782. }
  1783. }
  1784. template IMPLOT_API void PlotHeatmap<ImS8>(const char* label_id, const ImS8* values, int rows, int cols, double scale_min, double scale_max, const char* fmt, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max);
  1785. template IMPLOT_API void PlotHeatmap<ImU8>(const char* label_id, const ImU8* values, int rows, int cols, double scale_min, double scale_max, const char* fmt, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max);
  1786. template IMPLOT_API void PlotHeatmap<ImS16>(const char* label_id, const ImS16* values, int rows, int cols, double scale_min, double scale_max, const char* fmt, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max);
  1787. template IMPLOT_API void PlotHeatmap<ImU16>(const char* label_id, const ImU16* values, int rows, int cols, double scale_min, double scale_max, const char* fmt, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max);
  1788. template IMPLOT_API void PlotHeatmap<ImS32>(const char* label_id, const ImS32* values, int rows, int cols, double scale_min, double scale_max, const char* fmt, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max);
  1789. template IMPLOT_API void PlotHeatmap<ImU32>(const char* label_id, const ImU32* values, int rows, int cols, double scale_min, double scale_max, const char* fmt, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max);
  1790. template IMPLOT_API void PlotHeatmap<ImS64>(const char* label_id, const ImS64* values, int rows, int cols, double scale_min, double scale_max, const char* fmt, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max);
  1791. template IMPLOT_API void PlotHeatmap<ImU64>(const char* label_id, const ImU64* values, int rows, int cols, double scale_min, double scale_max, const char* fmt, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max);
  1792. template IMPLOT_API void PlotHeatmap<float>(const char* label_id, const float* values, int rows, int cols, double scale_min, double scale_max, const char* fmt, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max);
  1793. template IMPLOT_API void PlotHeatmap<double>(const char* label_id, const double* values, int rows, int cols, double scale_min, double scale_max, const char* fmt, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max);
  1794. //-----------------------------------------------------------------------------
  1795. // PLOT HISTOGRAM
  1796. //-----------------------------------------------------------------------------
  1797. template <typename T>
  1798. double PlotHistogram(const char* label_id, const T* values, int count, int bins, bool cumulative, bool density, ImPlotRange range, bool outliers, double bar_scale) {
  1799. if (count <= 0 || bins == 0)
  1800. return 0;
  1801. if (range.Min == 0 && range.Max == 0) {
  1802. T Min, Max;
  1803. ImMinMaxArray(values, count, &Min, &Max);
  1804. range.Min = (double)Min;
  1805. range.Max = (double)Max;
  1806. }
  1807. double width;
  1808. if (bins < 0)
  1809. CalculateBins(values, count, bins, range, bins, width);
  1810. else
  1811. width = range.Size() / bins;
  1812. ImVector<double>& bin_centers = GImPlot->Temp1;
  1813. ImVector<double>& bin_counts = GImPlot->Temp2;
  1814. bin_centers.resize(bins);
  1815. bin_counts.resize(bins);
  1816. int below = 0;
  1817. for (int b = 0; b < bins; ++b) {
  1818. bin_centers[b] = range.Min + b * width + width * 0.5;
  1819. bin_counts[b] = 0;
  1820. }
  1821. int counted = 0;
  1822. double max_count = 0;
  1823. for (int i = 0; i < count; ++i) {
  1824. double val = (double)values[i];
  1825. if (range.Contains(val)) {
  1826. const int b = ImClamp((int)((val - range.Min) / width), 0, bins - 1);
  1827. bin_counts[b] += 1.0;
  1828. if (bin_counts[b] > max_count)
  1829. max_count = bin_counts[b];
  1830. counted++;
  1831. }
  1832. else if (val < range.Min) {
  1833. below++;
  1834. }
  1835. }
  1836. if (cumulative && density) {
  1837. if (outliers)
  1838. bin_counts[0] += below;
  1839. for (int b = 1; b < bins; ++b)
  1840. bin_counts[b] += bin_counts[b-1];
  1841. double scale = 1.0 / (outliers ? count : counted);
  1842. for (int b = 0; b < bins; ++b)
  1843. bin_counts[b] *= scale;
  1844. max_count = bin_counts[bins-1];
  1845. }
  1846. else if (cumulative) {
  1847. if (outliers)
  1848. bin_counts[0] += below;
  1849. for (int b = 1; b < bins; ++b)
  1850. bin_counts[b] += bin_counts[b-1];
  1851. max_count = bin_counts[bins-1];
  1852. }
  1853. else if (density) {
  1854. double scale = 1.0 / ((outliers ? count : counted) * width);
  1855. for (int b = 0; b < bins; ++b)
  1856. bin_counts[b] *= scale;
  1857. max_count *= scale;
  1858. }
  1859. PlotBars(label_id, &bin_centers.Data[0], &bin_counts.Data[0], bins, bar_scale*width);
  1860. return max_count;
  1861. }
  1862. template IMPLOT_API double PlotHistogram<ImS8>(const char* label_id, const ImS8* values, int count, int bins, bool cumulative, bool density, ImPlotRange range, bool outliers, double bar_scale);
  1863. template IMPLOT_API double PlotHistogram<ImU8>(const char* label_id, const ImU8* values, int count, int bins, bool cumulative, bool density, ImPlotRange range, bool outliers, double bar_scale);
  1864. template IMPLOT_API double PlotHistogram<ImS16>(const char* label_id, const ImS16* values, int count, int bins, bool cumulative, bool density, ImPlotRange range, bool outliers, double bar_scale);
  1865. template IMPLOT_API double PlotHistogram<ImU16>(const char* label_id, const ImU16* values, int count, int bins, bool cumulative, bool density, ImPlotRange range, bool outliers, double bar_scale);
  1866. template IMPLOT_API double PlotHistogram<ImS32>(const char* label_id, const ImS32* values, int count, int bins, bool cumulative, bool density, ImPlotRange range, bool outliers, double bar_scale);
  1867. template IMPLOT_API double PlotHistogram<ImU32>(const char* label_id, const ImU32* values, int count, int bins, bool cumulative, bool density, ImPlotRange range, bool outliers, double bar_scale);
  1868. template IMPLOT_API double PlotHistogram<ImS64>(const char* label_id, const ImS64* values, int count, int bins, bool cumulative, bool density, ImPlotRange range, bool outliers, double bar_scale);
  1869. template IMPLOT_API double PlotHistogram<ImU64>(const char* label_id, const ImU64* values, int count, int bins, bool cumulative, bool density, ImPlotRange range, bool outliers, double bar_scale);
  1870. template IMPLOT_API double PlotHistogram<float>(const char* label_id, const float* values, int count, int bins, bool cumulative, bool density, ImPlotRange range, bool outliers, double bar_scale);
  1871. template IMPLOT_API double PlotHistogram<double>(const char* label_id, const double* values, int count, int bins, bool cumulative, bool density, ImPlotRange range, bool outliers, double bar_scale);
  1872. //-----------------------------------------------------------------------------
  1873. // PLOT HISTOGRAM 2D
  1874. //-----------------------------------------------------------------------------
  1875. template <typename T>
  1876. double PlotHistogram2D(const char* label_id, const T* xs, const T* ys, int count, int x_bins, int y_bins, bool density, ImPlotLimits range, bool outliers) {
  1877. if (count <= 0 || x_bins == 0 || y_bins == 0)
  1878. return 0;
  1879. if (range.X.Min == 0 && range.X.Max == 0) {
  1880. T Min, Max;
  1881. ImMinMaxArray(xs, count, &Min, &Max);
  1882. range.X.Min = (double)Min;
  1883. range.X.Max = (double)Max;
  1884. }
  1885. if (range.Y.Min == 0 && range.Y.Max == 0) {
  1886. T Min, Max;
  1887. ImMinMaxArray(ys, count, &Min, &Max);
  1888. range.Y.Min = (double)Min;
  1889. range.Y.Max = (double)Max;
  1890. }
  1891. double width, height;
  1892. if (x_bins < 0)
  1893. CalculateBins(xs, count, x_bins, range.X, x_bins, width);
  1894. else
  1895. width = range.X.Size() / x_bins;
  1896. if (y_bins < 0)
  1897. CalculateBins(ys, count, y_bins, range.Y, y_bins, height);
  1898. else
  1899. height = range.Y.Size() / y_bins;
  1900. const int bins = x_bins * y_bins;
  1901. ImVector<double>& bin_counts = GImPlot->Temp1;
  1902. bin_counts.resize(bins);
  1903. for (int b = 0; b < bins; ++b)
  1904. bin_counts[b] = 0;
  1905. int counted = 0;
  1906. double max_count = 0;
  1907. for (int i = 0; i < count; ++i) {
  1908. if (range.Contains((double)xs[i], (double)ys[i])) {
  1909. const int xb = ImClamp( (int)((double)(xs[i] - range.X.Min) / width) , 0, x_bins - 1);
  1910. const int yb = ImClamp( (int)((double)(ys[i] - range.Y.Min) / height) , 0, y_bins - 1);
  1911. const int b = yb * x_bins + xb;
  1912. bin_counts[b] += 1.0;
  1913. if (bin_counts[b] > max_count)
  1914. max_count = bin_counts[b];
  1915. counted++;
  1916. }
  1917. }
  1918. if (density) {
  1919. double scale = 1.0 / ((outliers ? count : counted) * width * height);
  1920. for (int b = 0; b < bins; ++b)
  1921. bin_counts[b] *= scale;
  1922. max_count *= scale;
  1923. }
  1924. if (BeginItem(label_id)) {
  1925. if (FitThisFrame()) {
  1926. FitPoint(range.Min());
  1927. FitPoint(range.Max());
  1928. }
  1929. ImDrawList& DrawList = *GetPlotDrawList();
  1930. switch (GetCurrentScale()) {
  1931. case ImPlotScale_LinLin: RenderHeatmap(TransformerLinLin(), DrawList, &bin_counts.Data[0], y_bins, x_bins, 0, max_count, NULL, range.Min(), range.Max(), false); break;
  1932. case ImPlotScale_LogLin: RenderHeatmap(TransformerLogLin(), DrawList, &bin_counts.Data[0], y_bins, x_bins, 0, max_count, NULL, range.Min(), range.Max(), false); break;
  1933. case ImPlotScale_LinLog: RenderHeatmap(TransformerLinLog(), DrawList, &bin_counts.Data[0], y_bins, x_bins, 0, max_count, NULL, range.Min(), range.Max(), false); break;
  1934. case ImPlotScale_LogLog: RenderHeatmap(TransformerLogLog(), DrawList, &bin_counts.Data[0], y_bins, x_bins, 0, max_count, NULL, range.Min(), range.Max(), false); break;
  1935. }
  1936. EndItem();
  1937. }
  1938. return max_count;
  1939. }
  1940. template IMPLOT_API double PlotHistogram2D<ImS8>(const char* label_id, const ImS8* xs, const ImS8* ys, int count, int x_bins, int y_bins, bool density, ImPlotLimits range, bool outliers);
  1941. template IMPLOT_API double PlotHistogram2D<ImU8>(const char* label_id, const ImU8* xs, const ImU8* ys, int count, int x_bins, int y_bins, bool density, ImPlotLimits range, bool outliers);
  1942. template IMPLOT_API double PlotHistogram2D<ImS16>(const char* label_id, const ImS16* xs, const ImS16* ys, int count, int x_bins, int y_bins, bool density, ImPlotLimits range, bool outliers);
  1943. template IMPLOT_API double PlotHistogram2D<ImU16>(const char* label_id, const ImU16* xs, const ImU16* ys, int count, int x_bins, int y_bins, bool density, ImPlotLimits range, bool outliers);
  1944. template IMPLOT_API double PlotHistogram2D<ImS32>(const char* label_id, const ImS32* xs, const ImS32* ys, int count, int x_bins, int y_bins, bool density, ImPlotLimits range, bool outliers);
  1945. template IMPLOT_API double PlotHistogram2D<ImU32>(const char* label_id, const ImU32* xs, const ImU32* ys, int count, int x_bins, int y_bins, bool density, ImPlotLimits range, bool outliers);
  1946. template IMPLOT_API double PlotHistogram2D<ImS64>(const char* label_id, const ImS64* xs, const ImS64* ys, int count, int x_bins, int y_bins, bool density, ImPlotLimits range, bool outliers);
  1947. template IMPLOT_API double PlotHistogram2D<ImU64>(const char* label_id, const ImU64* xs, const ImU64* ys, int count, int x_bins, int y_bins, bool density, ImPlotLimits range, bool outliers);
  1948. template IMPLOT_API double PlotHistogram2D<float>(const char* label_id, const float* xs, const float* ys, int count, int x_bins, int y_bins, bool density, ImPlotLimits range, bool outliers);
  1949. template IMPLOT_API double PlotHistogram2D<double>(const char* label_id, const double* xs, const double* ys, int count, int x_bins, int y_bins, bool density, ImPlotLimits range, bool outliers);
  1950. //-----------------------------------------------------------------------------
  1951. // PLOT DIGITAL
  1952. //-----------------------------------------------------------------------------
  1953. // TODO: Make this behave like all the other plot types (.e. not fixed in y axis)
  1954. template <typename Getter>
  1955. inline void PlotDigitalEx(const char* label_id, Getter getter) {
  1956. if (BeginItem(label_id, ImPlotCol_Fill)) {
  1957. ImPlotContext& gp = *GImPlot;
  1958. ImDrawList& DrawList = *GetPlotDrawList();
  1959. const ImPlotNextItemData& s = GetItemData();
  1960. if (getter.Count > 1 && s.RenderFill) {
  1961. const int y_axis = GetCurrentYAxis();
  1962. int pixYMax = 0;
  1963. ImPlotPoint itemData1 = getter(0);
  1964. for (int i = 0; i < getter.Count; ++i) {
  1965. ImPlotPoint itemData2 = getter(i);
  1966. if (ImNanOrInf(itemData1.y)) {
  1967. itemData1 = itemData2;
  1968. continue;
  1969. }
  1970. if (ImNanOrInf(itemData2.y)) itemData2.y = ImConstrainNan(ImConstrainInf(itemData2.y));
  1971. int pixY_0 = (int)(s.LineWeight);
  1972. itemData1.y = ImMax(0.0, itemData1.y);
  1973. float pixY_1_float = s.DigitalBitHeight * (float)itemData1.y;
  1974. int pixY_1 = (int)(pixY_1_float); //allow only positive values
  1975. int pixY_chPosOffset = (int)(ImMax(s.DigitalBitHeight, pixY_1_float) + s.DigitalBitGap);
  1976. pixYMax = ImMax(pixYMax, pixY_chPosOffset);
  1977. ImVec2 pMin = PlotToPixels(itemData1);
  1978. ImVec2 pMax = PlotToPixels(itemData2);
  1979. int pixY_Offset = 20; //20 pixel from bottom due to mouse cursor label
  1980. pMin.y = (gp.PixelRange[y_axis].Min.y) + ((-gp.DigitalPlotOffset) - pixY_Offset);
  1981. pMax.y = (gp.PixelRange[y_axis].Min.y) + ((-gp.DigitalPlotOffset) - pixY_0 - pixY_1 - pixY_Offset);
  1982. //plot only one rectangle for same digital state
  1983. while (((i+2) < getter.Count) && (itemData1.y == itemData2.y)) {
  1984. const int in = (i + 1);
  1985. itemData2 = getter(in);
  1986. if (ImNanOrInf(itemData2.y)) break;
  1987. pMax.x = PlotToPixels(itemData2).x;
  1988. i++;
  1989. }
  1990. //do not extend plot outside plot range
  1991. if (pMin.x < gp.PixelRange[y_axis].Min.x) pMin.x = gp.PixelRange[y_axis].Min.x;
  1992. if (pMax.x < gp.PixelRange[y_axis].Min.x) pMax.x = gp.PixelRange[y_axis].Min.x;
  1993. if (pMin.x > gp.PixelRange[y_axis].Max.x) pMin.x = gp.PixelRange[y_axis].Max.x;
  1994. if (pMax.x > gp.PixelRange[y_axis].Max.x) pMax.x = gp.PixelRange[y_axis].Max.x;
  1995. //plot a rectangle that extends up to x2 with y1 height
  1996. if ((pMax.x > pMin.x) && (gp.CurrentPlot->PlotRect.Contains(pMin) || gp.CurrentPlot->PlotRect.Contains(pMax))) {
  1997. // ImVec4 colAlpha = item->Color;
  1998. // colAlpha.w = item->Highlight ? 1.0f : 0.9f;
  1999. DrawList.AddRectFilled(pMin, pMax, ImGui::GetColorU32(s.Colors[ImPlotCol_Fill]));
  2000. }
  2001. itemData1 = itemData2;
  2002. }
  2003. gp.DigitalPlotItemCnt++;
  2004. gp.DigitalPlotOffset += pixYMax;
  2005. }
  2006. EndItem();
  2007. }
  2008. }
  2009. template <typename T>
  2010. void PlotDigital(const char* label_id, const T* xs, const T* ys, int count, int offset, int stride) {
  2011. GetterXsYs<T> getter(xs,ys,count,offset,stride);
  2012. return PlotDigitalEx(label_id, getter);
  2013. }
  2014. template IMPLOT_API void PlotDigital<ImS8>(const char* label_id, const ImS8* xs, const ImS8* ys, int count, int offset, int stride);
  2015. template IMPLOT_API void PlotDigital<ImU8>(const char* label_id, const ImU8* xs, const ImU8* ys, int count, int offset, int stride);
  2016. template IMPLOT_API void PlotDigital<ImS16>(const char* label_id, const ImS16* xs, const ImS16* ys, int count, int offset, int stride);
  2017. template IMPLOT_API void PlotDigital<ImU16>(const char* label_id, const ImU16* xs, const ImU16* ys, int count, int offset, int stride);
  2018. template IMPLOT_API void PlotDigital<ImS32>(const char* label_id, const ImS32* xs, const ImS32* ys, int count, int offset, int stride);
  2019. template IMPLOT_API void PlotDigital<ImU32>(const char* label_id, const ImU32* xs, const ImU32* ys, int count, int offset, int stride);
  2020. template IMPLOT_API void PlotDigital<ImS64>(const char* label_id, const ImS64* xs, const ImS64* ys, int count, int offset, int stride);
  2021. template IMPLOT_API void PlotDigital<ImU64>(const char* label_id, const ImU64* xs, const ImU64* ys, int count, int offset, int stride);
  2022. template IMPLOT_API void PlotDigital<float>(const char* label_id, const float* xs, const float* ys, int count, int offset, int stride);
  2023. template IMPLOT_API void PlotDigital<double>(const char* label_id, const double* xs, const double* ys, int count, int offset, int stride);
  2024. // custom
  2025. void PlotDigitalG(const char* label_id, ImPlotPoint (*getter_func)(void* data, int idx), void* data, int count, int offset) {
  2026. GetterFuncPtr getter(getter_func,data,count,offset);
  2027. return PlotDigitalEx(label_id, getter);
  2028. }
  2029. //-----------------------------------------------------------------------------
  2030. // PLOT IMAGE
  2031. //-----------------------------------------------------------------------------
  2032. void PlotImage(const char* label_id, ImTextureID user_texture_id, const ImPlotPoint& bmin, const ImPlotPoint& bmax, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& tint_col) {
  2033. if (BeginItem(label_id)) {
  2034. if (FitThisFrame()) {
  2035. FitPoint(bmin);
  2036. FitPoint(bmax);
  2037. }
  2038. ImU32 tint_col32 = ImGui::ColorConvertFloat4ToU32(tint_col);
  2039. GetCurrentItem()->Color = tint_col32;
  2040. ImDrawList& DrawList = *GetPlotDrawList();
  2041. ImVec2 p1 = PlotToPixels(bmin.x, bmax.y);
  2042. ImVec2 p2 = PlotToPixels(bmax.x, bmin.y);
  2043. PushPlotClipRect();
  2044. DrawList.AddImage(user_texture_id, p1, p2, uv0, uv1, tint_col32);
  2045. PopPlotClipRect();
  2046. EndItem();
  2047. }
  2048. }
  2049. //-----------------------------------------------------------------------------
  2050. // PLOT TEXT
  2051. //-----------------------------------------------------------------------------
  2052. // double
  2053. void PlotText(const char* text, double x, double y, bool vertical, const ImVec2& pixel_offset) {
  2054. IM_ASSERT_USER_ERROR(GImPlot->CurrentPlot != NULL, "PlotText() needs to be called between BeginPlot() and EndPlot()!");
  2055. ImDrawList & DrawList = *GetPlotDrawList();
  2056. PushPlotClipRect();
  2057. ImU32 colTxt = GetStyleColorU32(ImPlotCol_InlayText);
  2058. if (vertical) {
  2059. ImVec2 ctr = CalcTextSizeVertical(text) * 0.5f;
  2060. ImVec2 pos = PlotToPixels(ImPlotPoint(x,y)) + ImVec2(-ctr.x, ctr.y) + pixel_offset;
  2061. AddTextVertical(&DrawList, pos, colTxt, text);
  2062. }
  2063. else {
  2064. ImVec2 pos = PlotToPixels(ImPlotPoint(x,y)) - ImGui::CalcTextSize(text) * 0.5f + pixel_offset;
  2065. DrawList.AddText(pos, colTxt, text);
  2066. }
  2067. PopPlotClipRect();
  2068. }
  2069. //-----------------------------------------------------------------------------
  2070. // PLOT DUMMY
  2071. //-----------------------------------------------------------------------------
  2072. void PlotDummy(const char* label_id) {
  2073. if (BeginItem(label_id, ImPlotCol_Line))
  2074. EndItem();
  2075. }
  2076. } // namespace ImPlot