mirror of
https://github.com/gwm17/implot.git
synced 2024-11-13 22:48:50 -05:00
fix up time format demo
This commit is contained in:
parent
d23bd30a44
commit
901f0558b1
62
implot.cpp
62
implot.cpp
|
@ -107,7 +107,6 @@ ImPlotStyle::ImPlotStyle() {
|
||||||
ErrorBarWeight = 1.5f;
|
ErrorBarWeight = 1.5f;
|
||||||
DigitalBitHeight = 8;
|
DigitalBitHeight = 8;
|
||||||
DigitalBitGap = 4;
|
DigitalBitGap = 4;
|
||||||
AntiAliasedLines = false;
|
|
||||||
|
|
||||||
PlotBorderSize = 1;
|
PlotBorderSize = 1;
|
||||||
MinorAlpha = 0.25f;
|
MinorAlpha = 0.25f;
|
||||||
|
@ -124,6 +123,9 @@ ImPlotStyle::ImPlotStyle() {
|
||||||
PlotMinSize = ImVec2(300,225);
|
PlotMinSize = ImVec2(300,225);
|
||||||
|
|
||||||
ImPlot::StyleColorsAuto(this);
|
ImPlot::StyleColorsAuto(this);
|
||||||
|
|
||||||
|
AntiAliasedLines = false;
|
||||||
|
UseLocalTime = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace ImPlot {
|
namespace ImPlot {
|
||||||
|
@ -646,7 +648,7 @@ inline int GetTimeStep(int max_divs, ImPlotTimeUnit unit) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline time_t MakeGmTime(const struct tm *ptm) {
|
ImPlotTime MkGmtTime(struct tm *ptm) {
|
||||||
time_t secs = 0;
|
time_t secs = 0;
|
||||||
int year = ptm->tm_year + 1900;
|
int year = ptm->tm_year + 1900;
|
||||||
for (int y = 1970; y < year; ++y)
|
for (int y = 1970; y < year; ++y)
|
||||||
|
@ -657,21 +659,52 @@ inline time_t MakeGmTime(const struct tm *ptm) {
|
||||||
secs += ptm->tm_hour * 3600;
|
secs += ptm->tm_hour * 3600;
|
||||||
secs += ptm->tm_min * 60;
|
secs += ptm->tm_min * 60;
|
||||||
secs += ptm->tm_sec;
|
secs += ptm->tm_sec;
|
||||||
return secs;
|
return ImPlotTime(secs,0);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline tm* GetGmTime(const time_t* time, tm* tm)
|
tm* GetGmtTime(const ImPlotTime& t, tm* ptm)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
if (gmtime_s(tm, time) == 0)
|
if (gmtime_s(ptm, &t.S) == 0)
|
||||||
return tm;
|
return ptm;
|
||||||
else
|
else
|
||||||
return NULL;
|
return NULL;
|
||||||
#else
|
#else
|
||||||
return gmtime_r(time, tm);
|
return gmtime_r(&t.S, ptm);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImPlotTime MkLocTime(struct tm *ptm) {
|
||||||
|
ImPlotTime t;
|
||||||
|
t.S = mktime(ptm);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
tm* GetLocTime(const ImPlotTime& t, tm* ptm) {
|
||||||
|
#ifdef _WIN32
|
||||||
|
if (localtime_s(ptm, &t.S) == 0)
|
||||||
|
return ptm;
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
#else
|
||||||
|
return localtime_r(&t.S, ptm);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
inline ImPlotTime MkTime(struct tm *ptm) {
|
||||||
|
if (GetStyle().UseLocalTime)
|
||||||
|
return MkLocTime(ptm);
|
||||||
|
else
|
||||||
|
return MkGmtTime(ptm);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline tm* GetTime(const ImPlotTime& t, tm* ptm) {
|
||||||
|
if (GetStyle().UseLocalTime)
|
||||||
|
return GetLocTime(t,ptm);
|
||||||
|
else
|
||||||
|
return GetGmtTime(t,ptm);
|
||||||
|
}
|
||||||
|
|
||||||
ImPlotTime AddTime(const ImPlotTime& t, ImPlotTimeUnit unit, int count) {
|
ImPlotTime AddTime(const ImPlotTime& t, ImPlotTimeUnit unit, int count) {
|
||||||
tm& Tm = GImPlot->Tm;
|
tm& Tm = GImPlot->Tm;
|
||||||
ImPlotTime t_out = t;
|
ImPlotTime t_out = t;
|
||||||
|
@ -683,7 +716,7 @@ ImPlotTime AddTime(const ImPlotTime& t, ImPlotTimeUnit unit, int count) {
|
||||||
case ImPlotTimeUnit_Hr: t_out.S += count * 3600; break;
|
case ImPlotTimeUnit_Hr: t_out.S += count * 3600; break;
|
||||||
case ImPlotTimeUnit_Day: t_out.S += count * 86400; break;
|
case ImPlotTimeUnit_Day: t_out.S += count * 86400; break;
|
||||||
case ImPlotTimeUnit_Mo: for (int i = 0; i < count; ++i) { // this might have a bug
|
case ImPlotTimeUnit_Mo: for (int i = 0; i < count; ++i) { // this might have a bug
|
||||||
GetGmTime(&t.S, &Tm);
|
GetTime(t_out, &Tm);
|
||||||
t_out.S += 86400 * GetDaysInMonth(Tm.tm_year + 1900, Tm.tm_mon);
|
t_out.S += 86400 * GetDaysInMonth(Tm.tm_year + 1900, Tm.tm_mon);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -701,8 +734,7 @@ ImPlotTime AddTime(const ImPlotTime& t, ImPlotTimeUnit unit, int count) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ImPlotTime FloorTime(const ImPlotTime& t, ImPlotTimeUnit unit) {
|
ImPlotTime FloorTime(const ImPlotTime& t, ImPlotTimeUnit unit) {
|
||||||
GetGmTime(&t.S, &GImPlot->Tm);
|
GetTime(t, &GImPlot->Tm);
|
||||||
GImPlot->Tm.tm_isdst = -1;
|
|
||||||
switch (unit) {
|
switch (unit) {
|
||||||
case ImPlotTimeUnit_S: return ImPlotTime(t.S, 0);
|
case ImPlotTimeUnit_S: return ImPlotTime(t.S, 0);
|
||||||
case ImPlotTimeUnit_Ms: return ImPlotTime(t.S, (t.Us / 1000) * 1000);
|
case ImPlotTimeUnit_Ms: return ImPlotTime(t.S, (t.Us / 1000) * 1000);
|
||||||
|
@ -714,7 +746,7 @@ ImPlotTime FloorTime(const ImPlotTime& t, ImPlotTimeUnit unit) {
|
||||||
case ImPlotTimeUnit_Min: GImPlot->Tm.tm_sec = 0; break;
|
case ImPlotTimeUnit_Min: GImPlot->Tm.tm_sec = 0; break;
|
||||||
default: return t;
|
default: return t;
|
||||||
}
|
}
|
||||||
return ImPlotTime(MakeGmTime(&GImPlot->Tm),0);
|
return MkTime(&GImPlot->Tm);
|
||||||
}
|
}
|
||||||
|
|
||||||
ImPlotTime CeilTime(const ImPlotTime& t, ImPlotTimeUnit unit) {
|
ImPlotTime CeilTime(const ImPlotTime& t, ImPlotTimeUnit unit) {
|
||||||
|
@ -731,7 +763,7 @@ ImPlotTime RoundTime(const ImPlotTime& t, ImPlotTimeUnit unit) {
|
||||||
|
|
||||||
int GetYear(const ImPlotTime& t) {
|
int GetYear(const ImPlotTime& t) {
|
||||||
tm& Tm = GImPlot->Tm;
|
tm& Tm = GImPlot->Tm;
|
||||||
GetGmTime(&t.S, &Tm);
|
GetTime(t, &Tm);
|
||||||
return Tm.tm_year + 1900;
|
return Tm.tm_year + 1900;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -747,14 +779,12 @@ ImPlotTime MakeYear(int year) {
|
||||||
Tm.tm_mon = 0;
|
Tm.tm_mon = 0;
|
||||||
Tm.tm_year = yr;
|
Tm.tm_year = yr;
|
||||||
Tm.tm_sec = 0;
|
Tm.tm_sec = 0;
|
||||||
Tm.tm_isdst = -1;
|
return MkTime(&Tm);
|
||||||
time_t s = MakeGmTime(&Tm);
|
|
||||||
return ImPlotTime(s);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int FormatTime(const ImPlotTime& t, char* buffer, int size, ImPlotTimeFmt fmt) {
|
int FormatTime(const ImPlotTime& t, char* buffer, int size, ImPlotTimeFmt fmt) {
|
||||||
tm& Tm = GImPlot->Tm;
|
tm& Tm = GImPlot->Tm;
|
||||||
GetGmTime(&t.S, &Tm);
|
GetTime(t, &Tm);
|
||||||
|
|
||||||
const char* ap = Tm.tm_hour < 12 ? "am" : "pm";
|
const char* ap = Tm.tm_hour < 12 ? "am" : "pm";
|
||||||
const int us = t.Us % 1000;
|
const int us = t.Us % 1000;
|
||||||
|
|
5
implot.h
5
implot.h
|
@ -217,7 +217,6 @@ struct ImPlotStyle {
|
||||||
float DigitalBitHeight; // = 8, digital channels bit height (at y = 1.0f) in pixels
|
float DigitalBitHeight; // = 8, digital channels bit height (at y = 1.0f) in pixels
|
||||||
float DigitalBitGap; // = 4, digital channels bit padding gap in pixels
|
float DigitalBitGap; // = 4, digital channels bit padding gap in pixels
|
||||||
// plot styling variables
|
// plot styling variables
|
||||||
bool AntiAliasedLines; // = false, enable global anti-aliasing on plot lines (overrides ImPlotFlags_AntiAliased)
|
|
||||||
float PlotBorderSize; // = 1, line thickness of border around plot area
|
float PlotBorderSize; // = 1, line thickness of border around plot area
|
||||||
float MinorAlpha; // = 0.25 alpha multiplier applied to minor axis grid lines
|
float MinorAlpha; // = 0.25 alpha multiplier applied to minor axis grid lines
|
||||||
ImVec2 MajorTickLen; // = 10,10 major tick lengths for X and Y axes
|
ImVec2 MajorTickLen; // = 10,10 major tick lengths for X and Y axes
|
||||||
|
@ -231,7 +230,11 @@ struct ImPlotStyle {
|
||||||
ImVec2 LegendPadding; // = 10,10 legend padding from top-left of plot
|
ImVec2 LegendPadding; // = 10,10 legend padding from top-left of plot
|
||||||
ImVec2 InfoPadding; // = 10,10 padding between plot edge and interior info text
|
ImVec2 InfoPadding; // = 10,10 padding between plot edge and interior info text
|
||||||
ImVec2 PlotMinSize; // = 300,225 minimum size plot frame can be when shrunk
|
ImVec2 PlotMinSize; // = 300,225 minimum size plot frame can be when shrunk
|
||||||
|
// colors
|
||||||
ImVec4 Colors[ImPlotCol_COUNT]; // array of plot specific colors
|
ImVec4 Colors[ImPlotCol_COUNT]; // array of plot specific colors
|
||||||
|
// settings/flags
|
||||||
|
bool AntiAliasedLines; // = false, enable global anti-aliasing on plot lines (overrides ImPlotFlags_AntiAliased)
|
||||||
|
bool UseLocalTime; // = false, axis labels will be formatted for your timezone when ImPlotAxisFlag_Time is enabled
|
||||||
ImPlotStyle();
|
ImPlotStyle();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#define sprintf sprintf_s
|
#define sprintf sprintf_s
|
||||||
|
@ -124,6 +125,25 @@ struct RollingBuffer {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Huge data used by Time Formatting example (~500 MB allocation!)
|
||||||
|
struct HugeTimeData {
|
||||||
|
HugeTimeData(double min) {
|
||||||
|
Ts = new double[Size];
|
||||||
|
Ys = new double[Size];
|
||||||
|
for (int i = 0; i < Size; ++i) {
|
||||||
|
Ts[i] = min + i;
|
||||||
|
Ys[i] = GetY(Ts[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
~HugeTimeData() { delete[] Ts; delete[] Ys; }
|
||||||
|
static double GetY(double t) {
|
||||||
|
return 0.5 + 0.25 * sin(t/86400/12) + 0.005 * sin(t/3600);
|
||||||
|
}
|
||||||
|
double* Ts;
|
||||||
|
double* Ys;
|
||||||
|
static const int Size = 60*60*24*366;
|
||||||
|
};
|
||||||
|
|
||||||
void ShowDemoWindow(bool* p_open) {
|
void ShowDemoWindow(bool* p_open) {
|
||||||
t_float DEMO_TIME = (t_float)ImGui::GetTime();
|
t_float DEMO_TIME = (t_float)ImGui::GetTime();
|
||||||
static bool show_imgui_metrics = false;
|
static bool show_imgui_metrics = false;
|
||||||
|
@ -591,11 +611,42 @@ void ShowDemoWindow(bool* p_open) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ImGui::CollapsingHeader("Time Formatted Axes")) {
|
if (ImGui::CollapsingHeader("Time Formatted Axes")) {
|
||||||
static double min = 1577836800; // 01/01/2020 @ 12:00:00am (UTC)
|
|
||||||
static double max = 1609459200; // 01/01/2021 @ 12:00:00am (UTC)
|
|
||||||
ImPlot::SetNextPlotLimits(min,max,0,1);
|
|
||||||
if (ImPlot::BeginPlot("##Time", "UTC Time", "Y-Axis", ImVec2(-1,0), 0, ImPlotAxisFlags_Time)) {
|
|
||||||
|
|
||||||
|
static double t_min = 1577836800; // 01/01/2020 @ 12:00:00am (UTC)
|
||||||
|
static double t_max = 1609459200; // 01/01/2021 @ 12:00:00am (UTC)
|
||||||
|
|
||||||
|
ImGui::BulletText("When ImPlotAxisFlags_Time is enabled on the X-Axis, values are interpreted as\n"
|
||||||
|
"UNIX timestamps in seconds and axis labels are formated as date/time.");
|
||||||
|
ImGui::BulletText("By default, labels are in UTC time but can be set to use local time instead.");
|
||||||
|
|
||||||
|
ImGui::Checkbox("Use Local Time",&ImPlot::GetStyle().UseLocalTime);
|
||||||
|
|
||||||
|
static HugeTimeData* data = NULL;
|
||||||
|
if (data == NULL) {
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (ImGui::Button("Generate Huge Data (~500MB!)")) {
|
||||||
|
static HugeTimeData sdata(t_min);
|
||||||
|
data = &sdata;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImPlot::SetNextPlotLimits(t_min,t_max,0,1);
|
||||||
|
if (ImPlot::BeginPlot("##Time", "Time", "Value", ImVec2(-1,0), 0, ImPlotAxisFlags_Time)) {
|
||||||
|
if (data != NULL) {
|
||||||
|
// downsample our data
|
||||||
|
int downsample = (int)ImPlot::GetPlotLimits().X.Size() / 1000 + 1;
|
||||||
|
int start = (int)(ImPlot::GetPlotLimits().X.Min - t_min);
|
||||||
|
start = start < 0 ? 0 : start > HugeTimeData::Size - 1 ? HugeTimeData::Size - 1 : start;
|
||||||
|
int end = (int)(ImPlot::GetPlotLimits().X.Max - t_min) + 1000;
|
||||||
|
end = end < 0 ? 0 : end > HugeTimeData::Size - 1 ? HugeTimeData::Size - 1 : end;
|
||||||
|
int size = (end - start)/downsample;
|
||||||
|
// plot it
|
||||||
|
ImPlot::PlotLine("Time Series", &data->Ts[start], &data->Ys[start], size, 0, sizeof(double)*downsample);
|
||||||
|
}
|
||||||
|
// plot time now
|
||||||
|
double t_now = (double)time(0);
|
||||||
|
double y_now = HugeTimeData::GetY(t_now);
|
||||||
|
ImPlot::PlotScatter("Now",&t_now,&y_now,1);
|
||||||
ImPlot::EndPlot();
|
ImPlot::EndPlot();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1133,8 +1184,9 @@ void ShowDemoWindow(bool* p_open) {
|
||||||
static ImVec4 bearCol = ImVec4(0.853f, 0.050f, 0.310f, 1.000f);
|
static ImVec4 bearCol = ImVec4(0.853f, 0.050f, 0.310f, 1.000f);
|
||||||
ImGui::SameLine(); ImGui::ColorEdit4("##Bull", &bullCol.x, ImGuiColorEditFlags_NoInputs);
|
ImGui::SameLine(); ImGui::ColorEdit4("##Bull", &bullCol.x, ImGuiColorEditFlags_NoInputs);
|
||||||
ImGui::SameLine(); ImGui::ColorEdit4("##Bear", &bearCol.x, ImGuiColorEditFlags_NoInputs);
|
ImGui::SameLine(); ImGui::ColorEdit4("##Bear", &bearCol.x, ImGuiColorEditFlags_NoInputs);
|
||||||
|
ImPlot::GetStyle().UseLocalTime = false;
|
||||||
ImPlot::SetNextPlotLimits(1546300800, 1571961600, 1250, 1600);
|
ImPlot::SetNextPlotLimits(1546300800, 1571961600, 1250, 1600);
|
||||||
if (ImPlot::BeginPlot("Candlestick Chart","Day","USD",ImVec2(-1,-1),0,ImPlotAxisFlags_Time)) {
|
if (ImPlot::BeginPlot("Candlestick Chart","Day","USD",ImVec2(-1,0),0,ImPlotAxisFlags_Time)) {
|
||||||
MyImPlot::PlotCandlestick("GOOGL",dates, opens, closes, lows, highs, 218, tooltip, 0.25f, bullCol, bearCol);
|
MyImPlot::PlotCandlestick("GOOGL",dates, opens, closes, lows, highs, 218, tooltip, 0.25f, bullCol, bearCol);
|
||||||
ImPlot::EndPlot();
|
ImPlot::EndPlot();
|
||||||
}
|
}
|
||||||
|
|
|
@ -577,7 +577,7 @@ struct ImPlotAxisScale
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Two part time struct.
|
/// Two part timestamp struct.
|
||||||
struct ImPlotTime {
|
struct ImPlotTime {
|
||||||
time_t S; // second part
|
time_t S; // second part
|
||||||
int Us; // microsecond part
|
int Us; // microsecond part
|
||||||
|
@ -777,8 +777,7 @@ inline T OffsetAndStride(const T* data, int idx, int count, int offset, int stri
|
||||||
// Time Utils
|
// Time Utils
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
// NB: These functions only work if there is a current ImPlotContext because the
|
|
||||||
// internal tm struct is owned by the context!
|
|
||||||
|
|
||||||
// Returns true if year is leap year (366 days long)
|
// Returns true if year is leap year (366 days long)
|
||||||
inline bool IsLeapYear(int year) {
|
inline bool IsLeapYear(int year) {
|
||||||
|
@ -793,6 +792,19 @@ inline int GetDaysInMonth(int year, int month) {
|
||||||
return days[month] + (int)(month == 1 && IsLeapYear(year));
|
return days[month] + (int)(month == 1 && IsLeapYear(year));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make a timestamp from a tm struct expressed as a UTC time (i.e. GMT timezone).
|
||||||
|
ImPlotTime MkGmtTime(struct tm *ptm);
|
||||||
|
// Make a tm struct from a timestamp expressed as a UTC time (i.e. GMT timezone).
|
||||||
|
tm* GetGmtTime(const ImPlotTime& t, tm* ptm);
|
||||||
|
|
||||||
|
// Make a timestamp from a tm struct expressed as a local time.
|
||||||
|
ImPlotTime MkLocTime(struct tm *ptm);
|
||||||
|
// Make a tm struct from a timestamp expressed as a local time.
|
||||||
|
tm* GetLocTime(const ImPlotTime& t, tm* ptm);
|
||||||
|
|
||||||
|
// NB: These functions only work if there is a current ImPlotContext because the
|
||||||
|
// internal tm struct is owned by the context!
|
||||||
|
|
||||||
// Adds time to a timestamp. #count must be positive!
|
// Adds time to a timestamp. #count must be positive!
|
||||||
ImPlotTime AddTime(const ImPlotTime& t, ImPlotTimeUnit unit, int count);
|
ImPlotTime AddTime(const ImPlotTime& t, ImPlotTimeUnit unit, int count);
|
||||||
// Rounds a timestamp down to nearest.
|
// Rounds a timestamp down to nearest.
|
||||||
|
|
Loading…
Reference in New Issue
Block a user