mirror of
https://github.com/gwm17/implot.git
synced 2025-01-30 10:58:51 -05:00
PlotDigital multi level
Plot digital channels as float (only positive values)
This commit is contained in:
parent
1d900f123b
commit
494b9eb61d
34
implot.cpp
34
implot.cpp
|
@ -49,7 +49,8 @@ ImPlotStyle::ImPlotStyle() {
|
|||
MarkerWeight = 1;
|
||||
ErrorBarSize = 5;
|
||||
ErrorBarWeight = 1.5;
|
||||
DigitalBitHeight = 7;
|
||||
DigitalBitHeight = 8;
|
||||
DigitalBitGap = 4;
|
||||
|
||||
Colors[ImPlotCol_Line] = IM_COL_AUTO;
|
||||
Colors[ImPlotCol_Fill] = IM_COL_AUTO;
|
||||
|
@ -330,6 +331,7 @@ struct ImPlotContext {
|
|||
ImNextPlotData NextPlotData;
|
||||
// Digital plot item count
|
||||
int DigitalPlotItemCnt;
|
||||
int DigitalPlotOffset;
|
||||
};
|
||||
|
||||
/// Global plot context
|
||||
|
@ -1056,6 +1058,7 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
|
|||
gp.LegendLabels.Buf.resize(0);
|
||||
// reset digital plot items count
|
||||
gp.DigitalPlotItemCnt = 0;
|
||||
gp.DigitalPlotOffset = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1469,7 +1472,8 @@ static const ImPlotStyleVarInfo GPlotStyleVarInfo[] =
|
|||
{ ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, MarkerWeight) }, // ImPlotStyleVar_MarkerWeight
|
||||
{ ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, ErrorBarSize) }, // ImPlotStyleVar_ErrorBarSize
|
||||
{ ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, ErrorBarWeight) }, // ImPlotStyleVar_ErrorBarWeight
|
||||
{ ImGuiDataType_S32, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, DigitalBitHeight) } // ImPlotStyleVar_DigitalBitHeight
|
||||
{ ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, DigitalBitHeight) }, // ImPlotStyleVar_DigitalBitHeight
|
||||
{ ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, DigitalBitGap) } // ImPlotStyleVar_DigitalBitGap
|
||||
};
|
||||
|
||||
static const ImPlotStyleVarInfo* GetPlotStyleVarInfo(ImPlotStyleVar idx)
|
||||
|
@ -2187,8 +2191,8 @@ void PlotPieChart(const char** label_ids, float* values, int count, const ImVec2
|
|||
ImVec2 size = CalcTextSize(buffer);
|
||||
float angle = a0 + (a1 - a0) * 0.5f;
|
||||
ImVec2 pos = PlotToPixels(center.x + 0.5f * radius * cos(angle), center.y + 0.5f * radius * sin(angle));
|
||||
DrawList.AddText(pos - size * 0.5f + ImVec2(1,1), gp.Col_Bg, buffer);
|
||||
DrawList.AddText(pos - size * 0.5f, GetColorU32(ImGuiCol_Text), buffer);
|
||||
DrawList.AddText(pos - size * 0.5f + ImVec2(1,1), IM_COL32(0,0,0,255), buffer);
|
||||
DrawList.AddText(pos - size * 0.5f, IM_COL32(255,255,255,255), buffer);
|
||||
}
|
||||
}
|
||||
a0 = a1;
|
||||
|
@ -2236,31 +2240,30 @@ inline void PlotDigitalEx(const char* label_id, Getter getter, int count, int of
|
|||
bool cull = HasFlag(gp.CurrentPlot->Flags, ImPlotFlags_CullData);
|
||||
|
||||
const float line_weight = item->Highlight ? gp.Style.LineWeight * 2 : gp.Style.LineWeight;
|
||||
|
||||
// render digital signals as "pixel bases" rectangles
|
||||
if (count > 1 && rend_line) {
|
||||
//
|
||||
const float mx = (gp.PixelRange.Max.x - gp.PixelRange.Min.x) / (gp.CurrentPlot->XAxis.Max - gp.CurrentPlot->XAxis.Min);
|
||||
int pixY_0 = line_weight;
|
||||
int pixY_1 = gp.Style.DigitalBitHeight;
|
||||
int pixY_Offset = 20;//20 pixel from bottom due to mouse cursor label
|
||||
int pixY_chOffset = pixY_1 + 3; //3 pixels between channels
|
||||
ImVec2 pMin, pMax;
|
||||
float y0 = (gp.PixelRange.Min.y) + ((-pixY_chOffset * gp.DigitalPlotItemCnt) - pixY_0 - pixY_Offset);
|
||||
float y1 = (gp.PixelRange.Min.y) + ((-pixY_chOffset * gp.DigitalPlotItemCnt) - pixY_1 - pixY_Offset);
|
||||
const int segments = count - 1;
|
||||
int i1 = offset;
|
||||
int pixYMax = 0;
|
||||
for (int s = 0; s < segments; ++s) {
|
||||
const int i2 = (i1 + 1) % count;
|
||||
ImVec2 itemData1 = getter(i1);
|
||||
ImVec2 itemData2 = getter(i2);
|
||||
i1 = i2;
|
||||
int pixY_0 = line_weight;
|
||||
int pixY_1 = gp.Style.DigitalBitHeight * ImMax(0.0f, itemData1.y); //allow only positive values
|
||||
int pixY_chPosOffset = ImMax((int)gp.Style.DigitalBitHeight, pixY_1) + gp.Style.DigitalBitGap;
|
||||
pixYMax = ImMax(pixYMax, pixY_chPosOffset);
|
||||
ImVec2 pMin, pMax;
|
||||
pMin.x = gp.PixelRange.Min.x + mx * (itemData1.x - gp.CurrentPlot->XAxis.Min);
|
||||
pMin.y = (gp.PixelRange.Min.y) + ((-pixY_chOffset * gp.DigitalPlotItemCnt) - pixY_Offset);
|
||||
pMax.x = gp.PixelRange.Min.x + mx * (itemData2.x - gp.CurrentPlot->XAxis.Min);
|
||||
pMax.y = ((int) itemData1.y == 0) ? y0 : y1;
|
||||
int pixY_Offset = 20;//20 pixel from bottom due to mouse cursor label
|
||||
pMin.y = (gp.PixelRange.Min.y) + ((-gp.DigitalPlotOffset) - pixY_Offset);
|
||||
pMax.y = (gp.PixelRange.Min.y) + ((-gp.DigitalPlotOffset) - pixY_0 - pixY_1 - pixY_Offset);
|
||||
//plot only one rectangle for same digital state
|
||||
while (((s+2) < segments) && ((int) itemData1.y == (int) itemData2.y)) {
|
||||
while (((s+2) < segments) && (itemData1.y == itemData2.y)) {
|
||||
const int i2 = (i1 + 1) % count;
|
||||
itemData2 = getter(i2);
|
||||
pMax.x = gp.PixelRange.Min.x + mx * (itemData2.x - gp.CurrentPlot->XAxis.Min);
|
||||
|
@ -2280,6 +2283,7 @@ inline void PlotDigitalEx(const char* label_id, Getter getter, int count, int of
|
|||
}
|
||||
}
|
||||
gp.DigitalPlotItemCnt++;
|
||||
gp.DigitalPlotOffset += pixYMax;
|
||||
}
|
||||
|
||||
ImGui::PopClipRect();
|
||||
|
|
8
implot.h
8
implot.h
|
@ -88,7 +88,8 @@ enum ImPlotStyleVar_ {
|
|||
ImPlotStyleVar_MarkerWeight, // float, outline weight of markers in pixels
|
||||
ImPlotStyleVar_ErrorBarSize, // float, error bar whisker width in pixels
|
||||
ImPlotStyleVar_ErrorBarWeight, // float, error bar whisker weight in pixels
|
||||
ImPlotStyleVar_DigitalBitHeight, // int, digital channels bit height (at 1)
|
||||
ImPlotStyleVar_DigitalBitHeight, // float, digital channels bit height (at 1) in pixels
|
||||
ImPlotStyleVar_DigitalBitGap, // float, digital channels bit padding gap in pixels
|
||||
ImPlotStyleVar_COUNT
|
||||
};
|
||||
|
||||
|
@ -122,7 +123,8 @@ struct ImPlotStyle {
|
|||
float MarkerWeight; // = 1, outline weight of markers in pixels
|
||||
float ErrorBarSize; // = 5, error bar whisker width in pixels
|
||||
float ErrorBarWeight; // = 1.5, error bar whisker weight in pixels
|
||||
int DigitalBitHeight; // = 7, digital channels bit height (at 1)
|
||||
float DigitalBitHeight; // = 8, digital channels bit height (at y = 1.0f) in pixels
|
||||
float DigitalBitGap; // = 4, digital channels bit padding gap in pixels
|
||||
ImVec4 Colors[ImPlotCol_COUNT]; // array of plot specific colors
|
||||
ImPlotStyle();
|
||||
};
|
||||
|
@ -176,7 +178,7 @@ void PlotPieChart(const char** label_ids, float* values, int count, const ImVec2
|
|||
// Plots a text label at point x,y.
|
||||
void PlotLabel(const char* text, float x, float y, bool vertical = false, const ImVec2& pixel_offset = ImVec2(0,0));
|
||||
// Plots digital channels.
|
||||
void PlotDigital(const char* label_id, const float* xs, const float* ys, int count, int offset = 0, int stride = sizeof(float) + sizeof(bool));
|
||||
void PlotDigital(const char* label_id, const float* xs, const float* ys, int count, int offset = 0, int stride = sizeof(float));
|
||||
void PlotDigital(const char* label_id, ImVec2 (*getter)(void* data, int idx), void* data, int count, int offset = 0);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
@ -48,7 +48,7 @@ struct ScrollingData {
|
|||
}
|
||||
void Erase() {
|
||||
if (Data.size() > 0) {
|
||||
Data.clear();
|
||||
Data.shrink(0);
|
||||
Offset = 0;
|
||||
}
|
||||
}
|
||||
|
@ -520,22 +520,22 @@ void ShowImPlotDemoWindow(bool* p_open) {
|
|||
}
|
||||
}
|
||||
|
||||
if (ImGui::CollapsingHeader("Digital")) {
|
||||
if (ImGui::CollapsingHeader("Digital and Analog Signals")) {
|
||||
|
||||
|
||||
static int bitHeight = 7;
|
||||
ImGui::SetNextItemWidth(100);
|
||||
ImGui::DragInt("Bit Hieght", &bitHeight, 0.2, 5, 50);
|
||||
/// Set the X axis range of the next plot. Call right before BeginPlot(). If ImGuiCond_Always is used, the axis will be locked.
|
||||
//void SetNextPlotRangeX(float x_min, float x_max, ImGuiCond cond = ImGuiCond_Once);
|
||||
static bool paused = false;
|
||||
#define K_PLOT_DIGITAL_CH_COUNT 8
|
||||
#define K_PLOT_ANALOG_CH_COUNT 8
|
||||
#define K_PLOT_DIGITAL_CH_COUNT 4
|
||||
#define K_PLOT_ANALOG_CH_COUNT 4
|
||||
static ScrollingData dataDigital[K_PLOT_DIGITAL_CH_COUNT];
|
||||
static ScrollingData dataAnalog[K_PLOT_ANALOG_CH_COUNT];
|
||||
static bool showDigital[K_PLOT_DIGITAL_CH_COUNT];
|
||||
static bool showAnalog[K_PLOT_ANALOG_CH_COUNT];
|
||||
|
||||
ImGui::BulletText("Drag data items from the left column onto the plot.");
|
||||
ImGui::BulletText("You can plot digital and analog signals on the same plot.");
|
||||
ImGui::BulletText("Digital signals do not respond to Y drag and zoom, so that");
|
||||
ImGui::Indent();
|
||||
ImGui::Text("you can drag analog signals over the rising/falling digital edge.");
|
||||
ImGui::Unindent();
|
||||
ImGui::BeginGroup();
|
||||
if (ImGui::Button("Clear", {100, 0})) {
|
||||
for (int i = 0; i < K_PLOT_DIGITAL_CH_COUNT; ++i)
|
||||
|
@ -545,10 +545,16 @@ void ShowImPlotDemoWindow(bool* p_open) {
|
|||
}
|
||||
if (ImGui::Button(paused ? "Resume" : "Pause", {100,0}))
|
||||
paused = !paused;
|
||||
ImGui::SetNextItemWidth(100);
|
||||
static float bitHeight = 8;
|
||||
ImGui::DragFloat("##Bit Height", &bitHeight, 1, 5, 25, "%.0f px");
|
||||
ImGui::SetNextItemWidth(100);
|
||||
static float bitGap = 4;
|
||||
ImGui::DragFloat("##Bit Gap", &bitGap, 1, 2, 20, "%.0f px");
|
||||
ImGui::Separator();
|
||||
for (int i = 0; i < K_PLOT_DIGITAL_CH_COUNT; ++i) {
|
||||
char label[32];
|
||||
sprintf(label, "digital_data_%d", i);
|
||||
sprintf(label, "digital_%d", i);
|
||||
ImGui::Checkbox(label, &showDigital[i]);
|
||||
if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None)) {
|
||||
ImGui::SetDragDropPayload("DND_DIGITAL_PLOT", &i, sizeof(int));
|
||||
|
@ -558,7 +564,7 @@ void ShowImPlotDemoWindow(bool* p_open) {
|
|||
}
|
||||
for (int i = 0; i < K_PLOT_ANALOG_CH_COUNT; ++i) {
|
||||
char label[32];
|
||||
sprintf(label, "analog_data_%d", i);
|
||||
sprintf(label, "analog_%d", i);
|
||||
ImGui::Checkbox(label, &showAnalog[i]);
|
||||
if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None)) {
|
||||
ImGui::SetDragDropPayload("DND_ANALOG_PLOT", &i, sizeof(int));
|
||||
|
@ -569,78 +575,52 @@ void ShowImPlotDemoWindow(bool* p_open) {
|
|||
ImGui::EndGroup();
|
||||
ImGui::SameLine();
|
||||
static float t = 0;
|
||||
if (true) {
|
||||
if (!paused) {
|
||||
t += ImGui::GetIO().DeltaTime;
|
||||
|
||||
//digital signal values
|
||||
int i = 0;
|
||||
if (showDigital[i])
|
||||
dataDigital[i].AddPoint(t, sin(t) > 0.45);
|
||||
dataDigital[i].AddPoint(t, sin(2*t) > 0.45);
|
||||
i++;
|
||||
if (showDigital[i])
|
||||
dataDigital[i].AddPoint(t, sin(t) < 0.45);
|
||||
dataDigital[i].AddPoint(t, sin(2*t) < 0.45);
|
||||
i++;
|
||||
if (showDigital[i])
|
||||
dataDigital[i].AddPoint(t, sin(t) > 0.83);
|
||||
dataDigital[i].AddPoint(t, (int)t % 5);
|
||||
i++;
|
||||
if (showDigital[i])
|
||||
dataDigital[i].AddPoint(t, sin(t) < 0.17);
|
||||
i++;
|
||||
if (showDigital[i])
|
||||
dataDigital[i].AddPoint(t, cos(t) > 0.45);
|
||||
i++;
|
||||
if (showDigital[i])
|
||||
dataDigital[i].AddPoint(t, cos(t) < 0.45);
|
||||
i++;
|
||||
if (showDigital[i])
|
||||
dataDigital[i].AddPoint(t, cos(t) > 0.83);
|
||||
i++;
|
||||
if (showDigital[i])
|
||||
dataDigital[i].AddPoint(t, cos(t) < 0.17);
|
||||
|
||||
dataDigital[i].AddPoint(t, sin(2*t) < 0.17);
|
||||
//Analog signal values
|
||||
i = 0;
|
||||
if (showAnalog[i])
|
||||
dataAnalog[i].AddPoint(t, sin(t));
|
||||
dataAnalog[i].AddPoint(t, sin(2*t));
|
||||
i++;
|
||||
if (showAnalog[i])
|
||||
dataAnalog[i].AddPoint(t, cos(t));
|
||||
dataAnalog[i].AddPoint(t, cos(2*t));
|
||||
i++;
|
||||
if (showAnalog[i])
|
||||
dataAnalog[i].AddPoint(t, sin(t) * cos(t));
|
||||
dataAnalog[i].AddPoint(t, sin(2*t) * cos(2*t));
|
||||
i++;
|
||||
if (showAnalog[i])
|
||||
dataAnalog[i].AddPoint(t, sin(t) - cos(t));
|
||||
i++;
|
||||
if (showAnalog[i])
|
||||
dataAnalog[i].AddPoint(t, cos(t) - sin(t));
|
||||
i++;
|
||||
if (showAnalog[i])
|
||||
dataAnalog[i].AddPoint(t, sin(t) + cos(t));
|
||||
i++;
|
||||
if (showAnalog[i])
|
||||
dataAnalog[i].AddPoint(t, (sin(t) + cos(t)) / (sin(t) * cos(t)));
|
||||
i++;
|
||||
if (showAnalog[i])
|
||||
dataAnalog[i].AddPoint(t, (cos(t) + cos(t)) / (cos(t) * cos(t)));
|
||||
i++;
|
||||
|
||||
dataAnalog[i].AddPoint(t, sin(2*t) - cos(2*t));
|
||||
}
|
||||
ImGui::SetNextPlotRangeX(t - 60.0f, t, paused ? ImGuiCond_Once : ImGuiCond_Always);
|
||||
if (ImGui::BeginPlot("##DND", NULL, NULL, ImVec2(-1,300), ImPlotFlags_Default)) {
|
||||
ImGui::SetNextPlotRangeY(-1, 1);
|
||||
ImGui::SetNextPlotRangeX(t - 10.0f, t, paused ? ImGuiCond_Once : ImGuiCond_Always);
|
||||
if (ImGui::BeginPlot("##Digital", NULL, NULL, ImVec2(-1,300), ImPlotFlags_Default)) {
|
||||
for (int i = 0; i < K_PLOT_DIGITAL_CH_COUNT; ++i) {
|
||||
if (showDigital[i]) {
|
||||
char label[32];
|
||||
sprintf(label, "digital_data_%d", i);
|
||||
sprintf(label, "digital_%d", i);
|
||||
ImGui::PushPlotStyleVar(ImPlotStyleVar_DigitalBitHeight, bitHeight);
|
||||
ImGui::PushPlotStyleVar(ImPlotStyleVar_DigitalBitGap, bitGap);
|
||||
ImGui::PlotDigital(label, &dataDigital[i].Data[0].x, &dataDigital[i].Data[0].y, dataDigital[i].Data.size(), dataDigital[i].Offset, 2 * sizeof(float));
|
||||
ImGui::PopPlotStyleVar();
|
||||
ImGui::PopPlotStyleVar(2);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < K_PLOT_ANALOG_CH_COUNT; ++i) {
|
||||
if (showAnalog[i]) {
|
||||
char label[32];
|
||||
sprintf(label, "analog_data_%d", i);
|
||||
sprintf(label, "analog_%d", i);
|
||||
if (dataAnalog[i].Data.size() > 0)
|
||||
ImGui::Plot(label, &dataAnalog[i].Data[0].x, &dataAnalog[i].Data[0].y, dataAnalog[i].Data.size(), dataAnalog[i].Offset, 2 * sizeof(float));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user