34 #ifndef IMGUI_DEFINE_MATH_OPERATORS
35 #define IMGUI_DEFINE_MATH_OPERATORS
39 #include "imgui_internal.h"
41 #ifndef IMPLOT_VERSION
42 #error Must include implot.h before implot_internal.h
47 #if (IMGUI_VERSION_NUM < 18303)
48 #define GetBufSize GetSize
59 #define IMPLOT_MIN_TIME 0
61 #define IMPLOT_MAX_TIME 32503680000
63 #define IMPLOT_LABEL_FORMAT "%g"
65 #define IMPLOT_LABEL_MAX_SIZE 32
71 #define IMPLOT_NUM_X_AXES ImAxis_Y1
72 #define IMPLOT_NUM_Y_AXES (ImAxis_COUNT - IMPLOT_NUM_X_AXES)
75 #define IM_COL32_SPLIT_RGB(col,r,g,b) \
76 ImU32 r = ((col >> IM_COL32_R_SHIFT) & 0xFF); \
77 ImU32 g = ((col >> IM_COL32_G_SHIFT) & 0xFF); \
78 ImU32 b = ((col >> IM_COL32_B_SHIFT) & 0xFF);
86 struct ImPlotAxisColor;
106 static inline float ImLog10(
float x) {
return log10f(x); }
107 static inline double ImLog10(
double x) {
return log10(x); }
108 static inline float ImSinh(
float x) {
return sinhf(x); }
109 static inline double ImSinh(
double x) {
return sinh(x); }
110 static inline float ImAsinh(
float x) {
return asinhf(x); }
111 static inline double ImAsinh(
double x) {
return asinh(x); }
113 template <
typename TSet,
typename TFlag>
114 static inline bool ImHasFlag(TSet set, TFlag flag) {
return (set & flag) == flag; }
116 template <
typename TSet,
typename TFlag>
117 static inline void ImFlipFlag(TSet& set, TFlag flag) { ImHasFlag(set, flag) ? set &= ~flag : set |= flag; }
119 template <
typename T>
120 static inline T ImRemap(T x, T x0, T x1, T y0, T y1) {
return y0 + (x - x0) * (y1 - y0) / (x1 - x0); }
122 template <
typename T>
123 static inline T ImRemap01(T x, T x0, T x1) {
return (x - x0) / (x1 - x0); }
125 static inline int ImPosMod(
int l,
int r) {
return (l % r + r) % r; }
127 static inline bool ImNan(
double val) {
return isnan(val); }
129 static inline bool ImNanOrInf(
double val) {
return !(val >= -DBL_MAX && val <= DBL_MAX) || ImNan(val); }
131 static inline double ImConstrainNan(
double val) {
return ImNan(val) ? 0 : val; }
133 static inline double ImConstrainInf(
double val) {
return val >= DBL_MAX ? DBL_MAX : val <= -DBL_MAX ? - DBL_MAX : val; }
135 static inline double ImConstrainLog(
double val) {
return val <= 0 ? 0.001f : val; }
137 static inline double ImConstrainTime(
double val) {
return val < IMPLOT_MIN_TIME ? IMPLOT_MIN_TIME : (val > IMPLOT_MAX_TIME ? IMPLOT_MAX_TIME : val); }
139 static inline bool ImAlmostEqual(
double v1,
double v2,
int ulp = 2) {
return ImAbs(v1-v2) < DBL_EPSILON * ImAbs(v1+v2) * ulp || ImAbs(v1-v2) < DBL_MIN; }
141 template <
typename T>
142 static inline T ImMinArray(
const T* values,
int count) { T m = values[0];
for (
int i = 1; i < count; ++i) {
if (values[i] < m) { m = values[i]; } }
return m; }
144 template <
typename T>
145 static inline T ImMaxArray(
const T* values,
int count) { T m = values[0];
for (
int i = 1; i < count; ++i) {
if (values[i] > m) { m = values[i]; } }
return m; }
147 template <
typename T>
148 static inline void ImMinMaxArray(
const T* values,
int count, T* min_out, T* max_out) {
149 T Min = values[0]; T Max = values[0];
150 for (
int i = 1; i < count; ++i) {
151 if (values[i] < Min) { Min = values[i]; }
152 if (values[i] > Max) { Max = values[i]; }
154 *min_out = Min; *max_out = Max;
157 template <
typename T>
158 static inline T ImSum(
const T* values,
int count) {
160 for (
int i = 0; i < count; ++i)
165 template <
typename T>
166 static inline double ImMean(
const T* values,
int count) {
167 double den = 1.0 / count;
169 for (
int i = 0; i < count; ++i)
170 mu += (
double)values[i] * den;
174 template <
typename T>
175 static inline double ImStdDev(
const T* values,
int count) {
176 double den = 1.0 / (count - 1.0);
177 double mu = ImMean(values, count);
179 for (
int i = 0; i < count; ++i)
180 x += ((
double)values[i] - mu) * ((double)values[i] - mu) * den;
184 static inline ImU32 ImMixU32(ImU32 a, ImU32 b, ImU32 s) {
186 const ImU32 af = 256-s;
188 const ImU64 al = (a & 0x00ff00ff) | (((ImU64)(a & 0xff00ff00)) << 24);
189 const ImU64 bl = (b & 0x00ff00ff) | (((ImU64)(b & 0xff00ff00)) << 24);
190 const ImU64 mix = (al * af + bl * bf);
191 return ((mix >> 32) & 0xff00ff00) | ((mix & 0xff00ff00) >> 8);
193 const ImU32 af = 256-s;
195 const ImU32 al = (a & 0x00ff00ff);
196 const ImU32 ah = (a & 0xff00ff00) >> 8;
197 const ImU32 bl = (b & 0x00ff00ff);
198 const ImU32 bh = (b & 0xff00ff00) >> 8;
199 const ImU32 ml = (al * af + bl * bf);
200 const ImU32 mh = (ah * af + bh * bf);
201 return (mh & 0xff00ff00) | ((ml & 0xff00ff00) >> 8);
206 static inline ImU32 ImLerpU32(
const ImU32* colors,
int size,
float t) {
207 int i1 = (int)((size - 1 ) * t);
209 if (i2 == size || size == 1)
211 float den = 1.0f / (size - 1);
214 float tr = ImRemap01(t, t1, t2);
215 return ImMixU32(colors[i1], colors[i2], (ImU32)(tr*256));
219 static inline ImU32 ImAlphaU32(ImU32 col,
float alpha) {
220 return col & ~((ImU32)((1.0f-alpha)*255)<<IM_COL32_A_SHIFT);
224 template <
typename T>
225 static inline bool ImOverlaps(T min_a, T max_a, T min_b, T max_b) {
226 return min_a <= max_b && min_b <= max_a;
233 typedef int ImPlotTimeUnit;
234 typedef int ImPlotDateFmt;
235 typedef int ImPlotTimeFmt;
237 enum ImPlotTimeUnit_ {
249 enum ImPlotDateFmt_ {
250 ImPlotDateFmt_None = 0,
252 ImPlotDateFmt_DayMoYr,
258 enum ImPlotTimeFmt_ {
259 ImPlotTimeFmt_None = 0,
264 ImPlotTimeFmt_MinSMs,
265 ImPlotTimeFmt_HrMinSMs,
266 ImPlotTimeFmt_HrMinS,
275 typedef void (*ImPlotLocator)(
ImPlotTicker& ticker,
const ImPlotRange& range,
float pixels,
bool vertical, ImPlotFormatter formatter,
void* formatter_data);
284 ImPlotDateTimeSpec(ImPlotDateFmt date_fmt, ImPlotTimeFmt time_fmt,
bool use_24_hr_clk =
false,
bool use_iso_8601 =
false) {
287 UseISO8601 = use_iso_8601;
288 Use24HourClock = use_24_hr_clk;
301 ImPlotTime(time_t s,
int us = 0) { S = s + us / 1000000; Us = us % 1000000; }
302 void RollOver() { S = S + Us / 1000000; Us = Us % 1000000; }
303 double ToDouble()
const {
return (
double)S + (double)Us / 1000000.0; }
304 static ImPlotTime FromDouble(
double t) {
return ImPlotTime((time_t)t, (
int)(t * 1000000 - floor(t) * 1000000)); }
308 {
return ImPlotTime(lhs.S + rhs.S, lhs.Us + rhs.Us); }
310 {
return ImPlotTime(lhs.S - rhs.S, lhs.Us - rhs.Us); }
312 {
return lhs.S == rhs.S && lhs.Us == rhs.Us; }
314 {
return lhs.S == rhs.S ? lhs.Us < rhs.Us : lhs.S < rhs.S; }
316 {
return rhs < lhs; }
318 {
return lhs < rhs || lhs == rhs; }
320 {
return lhs > rhs || lhs == rhs; }
338 int Append(
const char* name,
const ImU32* keys,
int count,
bool qual) {
339 if (GetIndex(name) != -1)
341 KeyOffsets.push_back(Keys.size());
342 KeyCounts.push_back(count);
343 Keys.reserve(Keys.size()+count);
344 for (
int i = 0; i < count; ++i)
345 Keys.push_back(keys[i]);
346 TextOffsets.push_back(Text.size());
347 Text.append(name, name + strlen(name) + 1);
348 Quals.push_back(qual);
349 ImGuiID
id = ImHashStr(name);
356 void _AppendTable(ImPlotColormap cmap) {
357 int key_count = GetKeyCount(cmap);
358 const ImU32* keys = GetKeys(cmap);
359 int off = Tables.size();
360 TableOffsets.push_back(off);
362 Tables.reserve(key_count);
363 for (
int i = 0; i < key_count; ++i)
364 Tables.push_back(keys[i]);
365 TableSizes.push_back(key_count);
368 int max_size = 255 * (key_count-1) + 1;
369 Tables.reserve(off + max_size);
373 for (
int i = 0; i < key_count-1; ++i) {
374 for (
int s = 0; s < 255; ++s) {
377 ImU32 c = ImMixU32(a,b,s);
385 ImU32 c = keys[key_count-1];
391 TableSizes.push_back(max_size);
395 void RebuildTables() {
397 TableSizes.resize(0);
398 TableOffsets.resize(0);
399 for (
int i = 0; i < Count; ++i)
403 inline bool IsQual(ImPlotColormap cmap)
const {
return Quals[cmap]; }
404 inline const char* GetName(ImPlotColormap cmap)
const {
return cmap < Count ? Text.Buf.Data + TextOffsets[cmap] : NULL; }
405 inline ImPlotColormap GetIndex(
const char* name)
const { ImGuiID key = ImHashStr(name);
return Map.GetInt(key,-1); }
407 inline const ImU32* GetKeys(ImPlotColormap cmap)
const {
return &Keys[KeyOffsets[cmap]]; }
408 inline int GetKeyCount(ImPlotColormap cmap)
const {
return KeyCounts[cmap]; }
409 inline ImU32 GetKeyColor(ImPlotColormap cmap,
int idx)
const {
return Keys[KeyOffsets[cmap]+idx]; }
410 inline void SetKeyColor(ImPlotColormap cmap,
int idx, ImU32 value) { Keys[KeyOffsets[cmap]+idx] = value; RebuildTables(); }
412 inline const ImU32* GetTable(ImPlotColormap cmap)
const {
return &Tables[TableOffsets[cmap]]; }
413 inline int GetTableSize(ImPlotColormap cmap)
const {
return TableSizes[cmap]; }
414 inline ImU32 GetTableColor(ImPlotColormap cmap,
int idx)
const {
return Tables[TableOffsets[cmap]+idx]; }
416 inline ImU32 LerpTable(ImPlotColormap cmap,
float t)
const {
417 int off = TableOffsets[cmap];
418 int siz = TableSizes[cmap];
419 int idx = Quals[cmap] ? ImClamp((
int)(siz*t),0,siz-1) : (int)((siz - 1) * t + 0.5f);
420 return Tables[off + idx];
426 double X, Y, Neg, Pos;
428 X = x; Y = y; Neg = neg; Pos = pos;
441 ColorBg = ColorFg = 0;
456 void AppendV(
const ImVec2& pos,
const ImVec2& off, ImU32 bg, ImU32 fg,
bool clamp,
const char* fmt, va_list args) IM_FMTLIST(7) {
458 an.Pos = pos; an.Offset = off;
459 an.ColorBg = bg; an.ColorFg = fg;
460 an.TextOffset = TextBuffer.size();
462 Annotations.push_back(an);
463 TextBuffer.appendfv(fmt, args);
464 const char nul[] =
"";
465 TextBuffer.append(nul,nul+1);
469 void Append(
const ImVec2& pos,
const ImVec2& off, ImU32 bg, ImU32 fg,
bool clamp,
const char* fmt, ...) IM_FMTARGS(7) {
472 AppendV(pos, off, bg, fg, clamp, fmt, args);
476 const char* GetText(
int idx) {
477 return TextBuffer.Buf.Data + Annotations[idx].TextOffset;
481 Annotations.shrink(0);
482 TextBuffer.Buf.shrink(0);
503 void AppendV(ImAxis axis,
double value, ImU32 bg, ImU32 fg,
const char* fmt, va_list args) IM_FMTLIST(6) {
509 tag.TextOffset = TextBuffer.size();
511 TextBuffer.appendfv(fmt, args);
512 const char nul[] =
"";
513 TextBuffer.append(nul,nul+1);
517 void Append(ImAxis axis,
double value, ImU32 bg, ImU32 fg,
const char* fmt, ...) IM_FMTARGS(6) {
520 AppendV(axis, value, bg, fg, fmt, args);
524 const char* GetText(
int idx) {
525 return TextBuffer.Buf.Data + Tags[idx].TextOffset;
530 TextBuffer.Buf.shrink(0);
547 ImPlotTick(
double value,
bool major,
int level,
bool show_label) {
551 ShowLabel = show_label;
569 ImPlotTick& AddTick(
double value,
bool major,
int level,
bool show_label,
const char* label) {
570 ImPlotTick tick(value, major, level, show_label);
571 if (show_label && label != NULL) {
572 tick.TextOffset = TextBuffer.size();
573 TextBuffer.append(label, label + strlen(label) + 1);
574 tick.LabelSize = ImGui::CalcTextSize(TextBuffer.Buf.Data + tick.TextOffset);
576 return AddTick(tick);
579 ImPlotTick& AddTick(
double value,
bool major,
int level,
bool show_label, ImPlotFormatter formatter,
void* data) {
580 ImPlotTick tick(value, major, level, show_label);
581 if (show_label && formatter != NULL) {
582 char buff[IMPLOT_LABEL_MAX_SIZE];
583 tick.TextOffset = TextBuffer.size();
584 formatter(tick.PlotPos, buff,
sizeof(buff), data);
585 TextBuffer.append(buff, buff + strlen(buff) + 1);
586 tick.LabelSize = ImGui::CalcTextSize(TextBuffer.Buf.Data + tick.TextOffset);
588 return AddTick(tick);
592 if (tick.ShowLabel) {
593 MaxSize.x = tick.LabelSize.x > MaxSize.x ? tick.LabelSize.x : MaxSize.x;
594 MaxSize.y = tick.LabelSize.y > MaxSize.y ? tick.LabelSize.y : MaxSize.y;
596 tick.Idx = Ticks.size();
597 Ticks.push_back(tick);
601 const char* GetText(
int idx)
const {
602 return TextBuffer.Buf.Data + Ticks[idx].TextOffset;
606 return GetText(tick.Idx);
609 void OverrideSizeLate(
const ImVec2& size) {
610 LateSize.x = size.x > LateSize.x ? size.x : LateSize.x;
611 LateSize.y = size.y > LateSize.y ? size.y : LateSize.y;
616 TextBuffer.Buf.shrink(0);
622 int TickCount()
const {
631 ImPlotAxisFlags Flags;
632 ImPlotAxisFlags PreviousFlags;
634 ImPlotCond RangeCond;
642 ImPlotFormatter Formatter;
645 ImPlotLocator Locator;
653 ImPlotTransform TransformForward;
654 ImPlotTransform TransformInverse;
656 float PixelMin, PixelMax;
657 double ScaleMin, ScaleMax;
659 float Datum1, Datum2;
663 ImU32 ColorMaj, ColorMin, ColorTick, ColorTxt, ColorBg, ColorHov, ColorAct, ColorHiLi;
670 bool ShowDefaultTicks;
676 Flags = PreviousFlags = ImPlotAxisFlags_None;
679 Scale = ImPlotScale_Linear;
680 TransformForward = TransformInverse = NULL;
681 TransformData = NULL;
682 FitExtents.Min = HUGE_VAL;
683 FitExtents.Max = -HUGE_VAL;
687 LinkedMin = LinkedMax = NULL;
690 PixelMin = PixelMax = 0;
692 ColorMaj = ColorMin = ColorTick = ColorTxt = ColorBg = ColorHov = ColorAct = 0;
693 ColorHiLi = IM_COL32_BLACK_TRANS;
695 FormatterData = NULL;
697 Enabled = Hovered = Held = FitThisFrame = HasRange = HasFormatSpec =
false;
698 ShowDefaultTicks =
true;
701 inline void Reset() {
703 Scale = ImPlotScale_Linear;
704 TransformForward = TransformInverse = NULL;
705 TransformData = NULL;
707 HasFormatSpec =
false;
709 FormatterData = NULL;
711 ShowDefaultTicks =
true;
712 FitThisFrame =
false;
713 FitExtents.Min = HUGE_VAL;
714 FitExtents.Max = -HUGE_VAL;
721 inline bool SetMin(
double _min,
bool force=
false) {
722 if (!force && IsLockedMin())
724 _min = ImConstrainNan(ImConstrainInf(_min));
725 if (_min < ConstraintRange.Min)
726 _min = ConstraintRange.Min;
727 double z = Range.Max - _min;
728 if (z < ConstraintZoom.Min)
729 _min = Range.Max - ConstraintZoom.Min;
730 if (z > ConstraintZoom.Max)
731 _min = Range.Max - ConstraintZoom.Max;
732 if (_min >= Range.Max)
735 PickerTimeMin = ImPlotTime::FromDouble(Range.Min);
736 UpdateTransformCache();
740 inline bool SetMax(
double _max,
bool force=
false) {
741 if (!force && IsLockedMax())
743 _max = ImConstrainNan(ImConstrainInf(_max));
744 if (_max > ConstraintRange.Max)
745 _max = ConstraintRange.Max;
746 double z = _max - Range.Min;
747 if (z < ConstraintZoom.Min)
748 _max = Range.Min + ConstraintZoom.Min;
749 if (z > ConstraintZoom.Max)
750 _max = Range.Min + ConstraintZoom.Max;
751 if (_max <= Range.Min)
754 PickerTimeMax = ImPlotTime::FromDouble(Range.Max);
755 UpdateTransformCache();
759 inline void SetRange(
double v1,
double v2) {
760 Range.Min = ImMin(v1,v2);
761 Range.Max = ImMax(v1,v2);
763 PickerTimeMin = ImPlotTime::FromDouble(Range.Min);
764 PickerTimeMax = ImPlotTime::FromDouble(Range.Max);
765 UpdateTransformCache();
769 SetRange(range.Min, range.Max);
772 inline void SetAspect(
double unit_per_pix) {
773 double new_size = unit_per_pix * PixelSize();
774 double delta = (new_size - Range.Size()) * 0.5;
777 else if (IsLockedMin() && !IsLockedMax())
778 SetRange(Range.Min, Range.Max + 2*delta);
779 else if (!IsLockedMin() && IsLockedMax())
780 SetRange(Range.Min - 2*delta, Range.Max);
782 SetRange(Range.Min - delta, Range.Max + delta);
785 inline float PixelSize()
const {
return ImAbs(PixelMax - PixelMin); }
787 inline double GetAspect()
const {
return Range.Size() / PixelSize(); }
789 inline void Constrain() {
790 Range.Min = ImConstrainNan(ImConstrainInf(Range.Min));
791 Range.Max = ImConstrainNan(ImConstrainInf(Range.Max));
792 if (Range.Min < ConstraintRange.Min)
793 Range.Min = ConstraintRange.Min;
794 if (Range.Max > ConstraintRange.Max)
795 Range.Max = ConstraintRange.Max;
796 double z = Range.Size();
797 if (z < ConstraintZoom.Min) {
798 double delta = (ConstraintZoom.Min - z) * 0.5;
802 if (z > ConstraintZoom.Max) {
803 double delta = (z - ConstraintZoom.Max) * 0.5;
807 if (Range.Max <= Range.Min)
808 Range.Max = Range.Min + DBL_EPSILON;
811 inline void UpdateTransformCache() {
812 ScaleToPixel = (PixelMax - PixelMin) / Range.Size();
813 if (TransformForward != NULL) {
814 ScaleMin = TransformForward(Range.Min, TransformData);
815 ScaleMax = TransformForward(Range.Max, TransformData);
818 ScaleMin = Range.Min;
819 ScaleMax = Range.Max;
823 inline float PlotToPixels(
double plt)
const {
824 if (TransformForward != NULL) {
825 double s = TransformForward(plt, TransformData);
826 double t = (s - ScaleMin) / (ScaleMax - ScaleMin);
827 plt = Range.Min + Range.Size() * t;
829 return (
float)(PixelMin + ScaleToPixel * (plt - Range.Min));
833 inline double PixelsToPlot(
float pix)
const {
834 double plt = (pix - PixelMin) / ScaleToPixel + Range.Min;
835 if (TransformInverse != NULL) {
836 double t = (plt - Range.Min) / Range.Size();
837 double s = t * (ScaleMax - ScaleMin) + ScaleMin;
838 plt = TransformInverse(s, TransformData);
843 inline void ExtendFit(
double v) {
844 if (!ImNanOrInf(v) && v >= ConstraintRange.Min && v <= ConstraintRange.Max) {
845 FitExtents.Min = v < FitExtents.Min ? v : FitExtents.Min;
846 FitExtents.Max = v > FitExtents.Max ? v : FitExtents.Max;
850 inline void ExtendFitWith(
ImPlotAxis& alt,
double v,
double v_alt) {
851 if (ImHasFlag(Flags, ImPlotAxisFlags_RangeFit) && !alt.Range.Contains(v_alt))
853 if (!ImNanOrInf(v) && v >= ConstraintRange.Min && v <= ConstraintRange.Max) {
854 FitExtents.Min = v < FitExtents.Min ? v : FitExtents.Min;
855 FitExtents.Max = v > FitExtents.Max ? v : FitExtents.Max;
859 inline void ApplyFit(
float padding) {
860 const double ext_size = FitExtents.Size() * 0.5;
861 FitExtents.Min -= ext_size * padding;
862 FitExtents.Max += ext_size * padding;
863 if (!IsLockedMin() && !ImNanOrInf(FitExtents.Min))
864 Range.Min = FitExtents.Min;
865 if (!IsLockedMax() && !ImNanOrInf(FitExtents.Max))
866 Range.Max = FitExtents.Max;
867 if (ImAlmostEqual(Range.Min, Range.Max)) {
872 UpdateTransformCache();
875 inline bool HasLabel()
const {
return LabelOffset != -1 && !ImHasFlag(Flags, ImPlotAxisFlags_NoLabel); }
876 inline bool HasGridLines()
const {
return !ImHasFlag(Flags, ImPlotAxisFlags_NoGridLines); }
877 inline bool HasTickLabels()
const {
return !ImHasFlag(Flags, ImPlotAxisFlags_NoTickLabels); }
878 inline bool HasTickMarks()
const {
return !ImHasFlag(Flags, ImPlotAxisFlags_NoTickMarks); }
879 inline bool WillRender()
const {
return Enabled && (HasGridLines() || HasTickLabels() || HasTickMarks()); }
880 inline bool IsOpposite()
const {
return ImHasFlag(Flags, ImPlotAxisFlags_Opposite); }
881 inline bool IsInverted()
const {
return ImHasFlag(Flags, ImPlotAxisFlags_Invert); }
882 inline bool IsForeground()
const {
return ImHasFlag(Flags, ImPlotAxisFlags_Foreground); }
883 inline bool IsAutoFitting()
const {
return ImHasFlag(Flags, ImPlotAxisFlags_AutoFit); }
884 inline bool CanInitFit()
const {
return !ImHasFlag(Flags, ImPlotAxisFlags_NoInitialFit) && !HasRange && !LinkedMin && !LinkedMax; }
885 inline bool IsRangeLocked()
const {
return HasRange && RangeCond == ImPlotCond_Always; }
886 inline bool IsLockedMin()
const {
return !Enabled || IsRangeLocked() || ImHasFlag(Flags, ImPlotAxisFlags_LockMin); }
887 inline bool IsLockedMax()
const {
return !Enabled || IsRangeLocked() || ImHasFlag(Flags, ImPlotAxisFlags_LockMax); }
888 inline bool IsLocked()
const {
return IsLockedMin() && IsLockedMax(); }
889 inline bool IsInputLockedMin()
const {
return IsLockedMin() || IsAutoFitting(); }
890 inline bool IsInputLockedMax()
const {
return IsLockedMax() || IsAutoFitting(); }
891 inline bool IsInputLocked()
const {
return IsLocked() || IsAutoFitting(); }
892 inline bool HasMenus()
const {
return !ImHasFlag(Flags, ImPlotAxisFlags_NoMenus); }
894 inline bool IsPanLocked(
bool increasing) {
895 if (ImHasFlag(Flags, ImPlotAxisFlags_PanStretch)) {
896 return IsInputLocked();
899 if (IsLockedMin() || IsLockedMax() || IsAutoFitting())
902 return Range.Max == ConstraintRange.Max;
904 return Range.Min == ConstraintRange.Min;
909 if (LinkedMin) { *LinkedMin = Range.Min; }
910 if (LinkedMax) { *LinkedMax = Range.Max; }
914 if (LinkedMin) { SetMin(*LinkedMin,
true); }
915 if (LinkedMax) { SetMax(*LinkedMax,
true); }
928 PadA = PadB = PadAMax = PadBMax = 0;
930 void Begin() { PadAMax = PadBMax = 0; }
931 void Update(
float& pad_a,
float& pad_b,
float& delta_a,
float& delta_b) {
932 float bak_a = pad_a;
float bak_b = pad_b;
933 if (PadAMax < pad_a) { PadAMax = pad_a; }
934 if (PadBMax < pad_b) { PadBMax = pad_b; }
935 if (pad_a < PadA) { pad_a = PadA; delta_a = pad_a - bak_a; }
else { delta_a = 0; }
936 if (pad_b < PadB) { pad_b = PadB; delta_b = pad_b - bak_b; }
else { delta_b = 0; }
938 void End() { PadA = PadAMax; PadB = PadBMax; }
939 void Reset() { PadA = PadB = PadAMax = PadBMax = 0; }
955 Color = IM_COL32_WHITE;
958 SeenThisFrame =
false;
959 LegendHovered =
false;
968 ImPlotLegendFlags Flags;
969 ImPlotLegendFlags PreviousFlags;
970 ImPlotLocation Location;
971 ImPlotLocation PreviousLocation;
980 Flags = PreviousFlags = ImPlotLegendFlags_None;
982 Hovered = Held =
false;
983 Location = PreviousLocation = ImPlotLocation_NorthWest;
986 void Reset() { Indices.shrink(0); Labels.Buf.shrink(0); }
999 int GetItemCount()
const {
return ItemPool.GetBufSize(); }
1000 ImGuiID GetItemID(
const char* label_id) {
return ImGui::GetID(label_id); }
1001 ImPlotItem* GetItem(ImGuiID
id) {
return ItemPool.GetByKey(
id); }
1002 ImPlotItem* GetItem(
const char* label_id) {
return GetItem(GetItemID(label_id)); }
1003 ImPlotItem* GetOrAddItem(ImGuiID
id) {
return ItemPool.GetOrAddByKey(
id); }
1004 ImPlotItem* GetItemByIndex(
int i) {
return ItemPool.GetByIndex(i); }
1005 int GetItemIndex(
ImPlotItem* item) {
return ItemPool.GetIndex(item); }
1006 int GetLegendCount()
const {
return Legend.Indices.size(); }
1007 ImPlotItem* GetLegendItem(
int i) {
return ItemPool.GetByIndex(Legend.Indices[i]); }
1008 const char* GetLegendLabel(
int i) {
return Legend.Labels.Buf.Data + GetLegendItem(i)->NameOffset; }
1009 void Reset() { ItemPool.Clear(); Legend.Reset(); ColormapIdx = 0; }
1017 ImPlotFlags PreviousFlags;
1018 ImPlotLocation MouseTextLocation;
1019 ImPlotMouseTextFlags MouseTextFlags;
1043 Flags = PreviousFlags = ImPlotFlags_None;
1044 for (
int i = 0; i < IMPLOT_NUM_X_AXES; ++i)
1045 XAxis(i).Vertical =
false;
1046 for (
int i = 0; i < IMPLOT_NUM_Y_AXES; ++i)
1047 YAxis(i).Vertical =
true;
1048 SelectStart =
ImVec2(0,0);
1049 CurrentX = ImAxis_X1;
1050 CurrentY = ImAxis_Y1;
1051 MouseTextLocation = ImPlotLocation_South | ImPlotLocation_East;
1052 MouseTextFlags = ImPlotMouseTextFlags_None;
1055 Initialized = SetupLocked = FitThisFrame =
false;
1056 Hovered = Held = Selected = Selecting = ContextLocked =
false;
1059 inline bool IsInputLocked()
const {
1060 for (
int i = 0; i < IMPLOT_NUM_X_AXES; ++i) {
1061 if (!XAxis(i).IsInputLocked())
1064 for (
int i = 0; i < IMPLOT_NUM_Y_AXES; ++i) {
1065 if (!YAxis(i).IsInputLocked())
1071 inline void ClearTextBuffer() { TextBuffer.Buf.shrink(0); }
1073 inline void SetTitle(
const char* title) {
1074 if (title && ImGui::FindRenderedTextEnd(title, NULL) != title) {
1075 TitleOffset = TextBuffer.size();
1076 TextBuffer.append(title, title + strlen(title) + 1);
1082 inline bool HasTitle()
const {
return TitleOffset != -1 && !ImHasFlag(Flags, ImPlotFlags_NoTitle); }
1083 inline const char* GetTitle()
const {
return TextBuffer.Buf.Data + TitleOffset; }
1085 inline ImPlotAxis& XAxis(
int i) {
return Axes[ImAxis_X1 + i]; }
1086 inline const ImPlotAxis& XAxis(
int i)
const {
return Axes[ImAxis_X1 + i]; }
1087 inline ImPlotAxis& YAxis(
int i) {
return Axes[ImAxis_Y1 + i]; }
1088 inline const ImPlotAxis& YAxis(
int i)
const {
return Axes[ImAxis_Y1 + i]; }
1090 inline int EnabledAxesX() {
1092 for (
int i = 0; i < IMPLOT_NUM_X_AXES; ++i)
1093 cnt += XAxis(i).Enabled;
1097 inline int EnabledAxesY() {
1099 for (
int i = 0; i < IMPLOT_NUM_Y_AXES; ++i)
1100 cnt += YAxis(i).Enabled;
1104 inline void SetAxisLabel(
ImPlotAxis& axis,
const char* label) {
1105 if (label && ImGui::FindRenderedTextEnd(label, NULL) != label) {
1106 axis.LabelOffset = TextBuffer.size();
1107 TextBuffer.append(label, label + strlen(label) + 1);
1110 axis.LabelOffset = -1;
1114 inline const char* GetAxisLabel(
const ImPlotAxis& axis)
const {
return TextBuffer.Buf.Data + axis.LabelOffset; }
1120 ImPlotSubplotFlags Flags;
1121 ImPlotSubplotFlags PreviousFlags;
1141 Flags = PreviousFlags = ImPlotSubplotFlags_None;
1142 Rows = Cols = CurrentIdx = 0;
1143 FrameHovered =
false;
1144 Items.Legend.Location = ImPlotLocation_North;
1145 Items.Legend.Flags = ImPlotLegendFlags_Horizontal|ImPlotLegendFlags_Outside;
1146 Items.Legend.CanGoInside =
false;
1147 TempSizes[0] = TempSizes[1] = 0;
1148 FrameHovered =
false;
1156 ImPlotCond RangeCond[ImAxis_COUNT];
1158 bool HasRange[ImAxis_COUNT];
1159 bool Fit[ImAxis_COUNT];
1160 double* LinkedMin[ImAxis_COUNT];
1161 double* LinkedMax[ImAxis_COUNT];
1166 for (
int i = 0; i < ImAxis_COUNT; ++i) {
1167 HasRange[i] =
false;
1169 LinkedMin[i] = LinkedMax[i] = NULL;
1179 ImPlotMarker Marker;
1184 float ErrorBarWeight;
1185 float DigitalBitHeight;
1186 float DigitalBitGap;
1189 bool RenderMarkerLine;
1190 bool RenderMarkerFill;
1193 ImPlotCond HiddenCond;
1196 for (
int i = 0; i < 5; ++i)
1197 Colors[i] = IMPLOT_AUTO_COL;
1198 LineWeight = MarkerSize = MarkerWeight = FillAlpha = ErrorBarSize = ErrorBarWeight = DigitalBitHeight = DigitalBitGap = IMPLOT_AUTO;
1199 Marker = IMPLOT_AUTO;
1200 HasHidden = Hidden =
false;
1223 bool ChildWindowMade;
1240 int DigitalPlotItemCnt;
1241 int DigitalPlotOffset;
1245 bool OpenContextThisFrame;
1271 IMPLOT_API
void ResetCtxForNextAlignedPlots(
ImPlotContext* ctx);
1280 IMPLOT_API
ImPlotPlot* GetPlot(
const char* title);
1284 IMPLOT_API
void BustPlotCache();
1287 IMPLOT_API
void ShowPlotContextMenu(
ImPlotPlot& plot);
1294 static inline void SetupLock() {
1295 if (!GImPlot->CurrentPlot->SetupLocked)
1297 GImPlot->CurrentPlot->SetupLocked =
true;
1305 IMPLOT_API
void SubplotNextCell();
1308 IMPLOT_API
void ShowSubplotsContextMenu(
ImPlotSubplot& subplot);
1315 IMPLOT_API
bool BeginItem(
const char* label_id, ImPlotItemFlags flags=0, ImPlotCol recolor_from=IMPLOT_AUTO);
1318 template <
typename _Fitter>
1319 bool BeginItemEx(
const char* label_id,
const _Fitter& fitter, ImPlotItemFlags flags=0, ImPlotCol recolor_from=IMPLOT_AUTO) {
1320 if (BeginItem(label_id, flags, recolor_from)) {
1322 if (plot.FitThisFrame && !ImHasFlag(flags, ImPlotItemFlags_NoFit))
1323 fitter.Fit(plot.Axes[plot.CurrentX], plot.Axes[plot.CurrentY]);
1330 IMPLOT_API
void EndItem();
1333 IMPLOT_API
ImPlotItem* RegisterOrGetItem(
const char* label_id, ImPlotItemFlags flags,
bool* just_created = NULL);
1335 IMPLOT_API
ImPlotItem* GetItem(
const char* label_id);
1339 IMPLOT_API
void BustItemCache();
1346 static inline bool AnyAxesInputLocked(
ImPlotAxis* axes,
int count) {
1347 for (
int i = 0; i < count; ++i) {
1348 if (axes[i].Enabled && axes[i].IsInputLocked())
1355 static inline bool AllAxesInputLocked(
ImPlotAxis* axes,
int count) {
1356 for (
int i = 0; i < count; ++i) {
1357 if (axes[i].Enabled && !axes[i].IsInputLocked())
1363 static inline bool AnyAxesHeld(
ImPlotAxis* axes,
int count) {
1364 for (
int i = 0; i < count; ++i) {
1365 if (axes[i].Enabled && axes[i].Held)
1371 static inline bool AnyAxesHovered(
ImPlotAxis* axes,
int count) {
1372 for (
int i = 0; i < count; ++i) {
1373 if (axes[i].Enabled && axes[i].Hovered)
1380 static inline bool FitThisFrame() {
1381 return GImPlot->CurrentPlot->FitThisFrame;
1385 static inline void FitPointX(
double x) {
1387 ImPlotAxis& x_axis = plot.Axes[plot.CurrentX];
1388 x_axis.ExtendFit(x);
1392 static inline void FitPointY(
double y) {
1394 ImPlotAxis& y_axis = plot.Axes[plot.CurrentY];
1395 y_axis.ExtendFit(y);
1399 static inline void FitPoint(
const ImPlotPoint& p) {
1401 ImPlotAxis& x_axis = plot.Axes[plot.CurrentX];
1402 ImPlotAxis& y_axis = plot.Axes[plot.CurrentY];
1403 x_axis.ExtendFitWith(y_axis, p.x, p.y);
1404 y_axis.ExtendFitWith(x_axis, p.y, p.x);
1409 {
return r1.Min <= r2.Max && r2.Min <= r1.Max; }
1412 IMPLOT_API
void ShowAxisContextMenu(
ImPlotAxis& axis,
ImPlotAxis* equal_axis,
bool time_allowed =
false);
1425 IMPLOT_API
void ShowAltLegend(
const char* title_id,
bool vertical =
true,
const ImVec2 size =
ImVec2(0,0),
bool interactable =
true);
1427 IMPLOT_API
bool ShowLegendContextMenu(
ImPlotLegend& legend,
bool visible);
1434 IMPLOT_API
void LabelAxisValue(
const ImPlotAxis& axis,
double value,
char* buff,
int size,
bool round =
false);
1441 static inline const ImPlotNextItemData& GetItemData() {
return GImPlot->NextItemData; }
1444 static inline bool IsColorAuto(
const ImVec4& col) {
return col.w == -1; }
1446 static inline bool IsColorAuto(ImPlotCol idx) {
return IsColorAuto(GImPlot->Style.Colors[idx]); }
1448 IMPLOT_API
ImVec4 GetAutoColor(ImPlotCol idx);
1451 static inline ImVec4 GetStyleColorVec4(ImPlotCol idx) {
return IsColorAuto(idx) ? GetAutoColor(idx) : GImPlot->Style.Colors[idx]; }
1452 static inline ImU32 GetStyleColorU32(ImPlotCol idx) {
return ImGui::ColorConvertFloat4ToU32(GetStyleColorVec4(idx)); }
1455 IMPLOT_API
void AddTextVertical(
ImDrawList *DrawList,
ImVec2 pos, ImU32 col,
const char* text_begin,
const char* text_end = NULL);
1457 IMPLOT_API
void AddTextCentered(
ImDrawList* DrawList,
ImVec2 top_center, ImU32 col,
const char* text_begin,
const char* text_end = NULL);
1459 static inline ImVec2 CalcTextSizeVertical(
const char *text) {
1460 ImVec2 sz = ImGui::CalcTextSize(text);
1461 return ImVec2(sz.y, sz.x);
1464 static inline ImU32 CalcTextColor(
const ImVec4& bg) {
return (bg.x * 0.299f + bg.y * 0.587f + bg.z * 0.114f) > 0.5f ? IM_COL32_BLACK : IM_COL32_WHITE; }
1465 static inline ImU32 CalcTextColor(ImU32 bg) {
return CalcTextColor(ImGui::ColorConvertU32ToFloat4(bg)); }
1467 static inline ImU32 CalcHoverColor(ImU32 col) {
return ImMixU32(col, CalcTextColor(col), 32); }
1471 if (pos.x < Min.x) pos.x = Min.x;
1472 if (pos.y < Min.y) pos.y = Min.y;
1473 if ((pos.x + size.x) > Max.x) pos.x = Max.x - size.x;
1474 if ((pos.y + size.y) > Max.y) pos.y = Max.y - size.y;
1479 IMPLOT_API ImU32 GetColormapColorU32(
int idx, ImPlotColormap cmap);
1481 IMPLOT_API ImU32 NextColormapColorU32();
1483 IMPLOT_API ImU32 SampleColormapU32(
float t, ImPlotColormap cmap);
1486 IMPLOT_API
void RenderColorBar(
const ImU32* colors,
int size,
ImDrawList& DrawList,
const ImRect& bounds,
bool vert,
bool reversed,
bool continuous);
1493 IMPLOT_API
double NiceNum(
double x,
bool round);
1495 static inline int OrderOfMagnitude(
double val) {
return val == 0 ? 0 : (int)(floor(log10(fabs(val)))); }
1497 static inline int OrderToPrecision(
int order) {
return order > 0 ? 0 : 1 - order; }
1499 static inline int Precision(
double val) {
return OrderToPrecision(OrderOfMagnitude(val)); }
1501 static inline double RoundTo(
double val,
int prec) {
double p = pow(10,(
double)prec);
return floor(val*p+0.5)/p; }
1505 float v1 = (a1.x * a2.y - a1.y * a2.x);
float v2 = (b1.x * b2.y - b1.y * b2.x);
1506 float v3 = ((a1.x - a2.x) * (b1.y - b2.y) - (a1.y - a2.y) * (b1.x - b2.x));
1507 return ImVec2((v1 * (b1.x - b2.x) - v2 * (a1.x - a2.x)) / v3, (v1 * (b1.y - b2.y) - v2 * (a1.y - a2.y)) / v3);
1511 template <
typename T>
1512 void FillRange(
ImVector<T>& buffer,
int n, T vmin, T vmax) {
1514 T step = (vmax - vmin) / (n - 1);
1515 for (
int i = 0; i < n; ++i) {
1516 buffer[i] = vmin + i * step;
1521 template <
typename T>
1522 static inline void CalculateBins(
const T* values,
int count, ImPlotBin meth,
const ImPlotRange& range,
int& bins_out,
double& width_out) {
1524 case ImPlotBin_Sqrt:
1525 bins_out = (int)ceil(sqrt(count));
1527 case ImPlotBin_Sturges:
1528 bins_out = (int)ceil(1.0 + log2(count));
1530 case ImPlotBin_Rice:
1531 bins_out = (int)ceil(2 * cbrt(count));
1533 case ImPlotBin_Scott:
1534 width_out = 3.49 * ImStdDev(values, count) / cbrt(count);
1535 bins_out = (int)round(range.Size() / width_out);
1538 width_out = range.Size() / bins_out;
1546 static inline bool IsLeapYear(
int year) {
1547 return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
1550 static inline int GetDaysInMonth(
int year,
int month) {
1551 static const int days[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
1552 return days[month] + (int)(month == 1 && IsLeapYear(year));
1556 IMPLOT_API
ImPlotTime MkGmtTime(
struct tm *ptm);
1558 IMPLOT_API tm* GetGmtTime(
const ImPlotTime& t, tm* ptm);
1561 IMPLOT_API
ImPlotTime MkLocTime(
struct tm *ptm);
1563 IMPLOT_API tm* GetLocTime(
const ImPlotTime& t, tm* ptm);
1570 IMPLOT_API
ImPlotTime MakeTime(
int year,
int month = 0,
int day = 1,
int hour = 0,
int min = 0,
int sec = 0,
int us = 0);
1586 IMPLOT_API
int FormatTime(
const ImPlotTime& t,
char* buffer,
int size, ImPlotTimeFmt fmt,
bool use_24_hr_clk);
1588 IMPLOT_API
int FormatDate(
const ImPlotTime& t,
char* buffer,
int size, ImPlotDateFmt fmt,
bool use_iso_8601);
1599 IMPLOT_API
bool ShowTimePicker(
const char*
id,
ImPlotTime* t);
1605 static inline double TransformForward_Log10(
double v,
void*) {
1606 v = v <= 0.0 ? DBL_MIN : v;
1610 static inline double TransformInverse_Log10(
double v,
void*) {
1611 return ImPow(10, v);
1614 static inline double TransformForward_SymLog(
double v,
void*) {
1615 return 2.0 * ImAsinh(v / 2.0);
1618 static inline double TransformInverse_SymLog(
double v,
void*) {
1619 return 2.0 * ImSinh(v / 2.0);
1622 static inline double TransformForward_Logit(
double v,
void*) {
1623 v = ImClamp(v, DBL_MIN, 1.0 - DBL_EPSILON);
1624 return ImLog10(v / (1 - v));
1627 static inline double TransformInverse_Logit(
double v,
void*) {
1628 return 1.0 / (1.0 + ImPow(10,-v));
1635 static inline int Formatter_Default(
double value,
char* buff,
int size,
void* data) {
1636 char* fmt = (
char*)data;
1637 return ImFormatString(buff, size, fmt, value);
1640 static inline int Formatter_Logit(
double value,
char* buff,
int size,
void*) {
1642 return ImFormatString(buff,size,
"1/2");
1643 else if (value < 0.5)
1644 return ImFormatString(buff,size,
"%g", value);
1646 return ImFormatString(buff,size,
"1 - %g", 1 - value);
1652 ImPlotFormatter UserFormatter;
1653 void* UserFormatterData;
1656 static inline int Formatter_Time(
double,
char* buff,
int size,
void* data) {
1658 return FormatDateTime(ftd->Time, buff, size, ftd->Spec);
1665 void Locator_Default(
ImPlotTicker& ticker,
const ImPlotRange& range,
float pixels,
bool vertical, ImPlotFormatter formatter,
void* formatter_data);
1666 void Locator_Time(
ImPlotTicker& ticker,
const ImPlotRange& range,
float pixels,
bool vertical, ImPlotFormatter formatter,
void* formatter_data);
1667 void Locator_Log10(
ImPlotTicker& ticker,
const ImPlotRange& range,
float pixels,
bool vertical, ImPlotFormatter formatter,
void* formatter_data);
1668 void Locator_SymLog(
ImPlotTicker& ticker,
const ImPlotRange& range,
float pixels,
bool vertical, ImPlotFormatter formatter,
void* formatter_data);
Definition: implot_internal.h:920
Definition: implot_internal.h:448
Definition: implot_internal.h:433
Definition: implot_internal.h:629
Definition: implot_internal.h:323
Definition: implot_internal.h:1205
Definition: implot_internal.h:282
Definition: implot_internal.h:991
Definition: implot_internal.h:944
Definition: implot_internal.h:967
Definition: implot_internal.h:1176
Definition: implot_internal.h:1155
Definition: implot_internal.h:1014
Definition: implot_internal.h:425
Definition: implot_internal.h:1118
Definition: implot_internal.h:495
Definition: implot_internal.h:487
Definition: implot_internal.h:537
Definition: implot_internal.h:558
Definition: implot_internal.h:297
Definition: imgui_internal.h:517