14#include <imgui_stdlib.h>
16#include <implot_internal.h>
33 {
"stride", style.
stride },
35 {
"color", style.
color },
66 if (j.contains(
"legendName")) { j.at(
"legendName").get_to(style.
legendName); }
67 if (j.contains(
"stride")) { j.at(
"stride").get_to(style.
stride); }
68 if (j.contains(
"lineType")) { j.at(
"lineType").get_to(style.
lineType); }
69 if (j.contains(
"color")) { j.at(
"color").get_to(style.
color); }
70 if (j.contains(
"colormapMask")) { j.at(
"colormapMask").get_to(style.
colormapMask); }
71 if (j.contains(
"colormapMaskDataCmpIdx")) { j.at(
"colormapMaskDataCmpIdx").get_to(style.
colormapMaskDataCmpIdx); }
72 if (j.contains(
"thickness")) { j.at(
"thickness").get_to(style.
thickness); }
73 if (j.contains(
"lineFlags")) { style.
lineFlags.emplace(j.at(
"lineFlags").get<uint32_t>()); }
74 if (j.contains(
"markerColormapMask")) { j.at(
"markerColormapMask").get_to(style.
markerColormapMask); }
76 if (j.contains(
"markers")) { j.at(
"markers").get_to(style.
markers); }
77 if (j.contains(
"markerStyle")) { j.at(
"markerStyle").get_to(style.
markerStyle); }
78 if (j.contains(
"markerSize")) { j.at(
"markerSize").get_to(style.
markerSize); }
79 if (j.contains(
"markerWeight")) { j.at(
"markerWeight").get_to(style.
markerWeight); }
80 if (j.contains(
"markerFillColor")) { j.at(
"markerFillColor").get_to(style.
markerFillColor); }
81 if (j.contains(
"markerOutlineColor")) { j.at(
"markerOutlineColor").get_to(style.
markerOutlineColor); }
82 if (j.contains(
"errorBoundsEnabled")) { j.at(
"errorBoundsEnabled").get_to(style.
errorBoundsEnabled); }
83 if (j.contains(
"errorBoundsDataIdx")) { j.at(
"errorBoundsDataIdx").get_to(style.
errorBoundsDataIdx); }
84 if (j.contains(
"errorBoundsAlpha")) { j.at(
"errorBoundsAlpha").get_to(style.
errorBoundsAlpha); }
86 if (j.contains(
"eventsEnabled")) { j.at(
"eventsEnabled").get_to(style.
eventsEnabled); }
87 if (j.contains(
"eventMarkerStyle")) { j.at(
"eventMarkerStyle").get_to(style.
eventMarkerStyle); }
88 if (j.contains(
"eventMarkerSize")) { j.at(
"eventMarkerSize").get_to(style.
eventMarkerSize); }
89 if (j.contains(
"eventMarkerWeight")) { j.at(
"eventMarkerWeight").get_to(style.
eventMarkerWeight); }
90 if (j.contains(
"eventMarkerFillColor")) { j.at(
"eventMarkerFillColor").get_to(style.
eventMarkerFillColor); }
91 if (j.contains(
"eventMarkerOutlineColor")) { j.at(
"eventMarkerOutlineColor").get_to(style.
eventMarkerOutlineColor); }
92 if (j.contains(
"eventTooltipFilterRegex")) { j.at(
"eventTooltipFilterRegex").get_to(style.
eventTooltipFilterRegex); }
96 const char* displayTitle,
97 int plotDataBufferSize,
99 [[maybe_unused]]
const char* nameId,
100 ImPlotLineFlags plotLineFlags,
103 const std::function<
bool(
size_t&,
const char*)>& ShowDataReferenceChooser,
105 std::vector<std::tuple<double, double, PlotEventTooltip>>* eventTooltips)
110 if (ImPlot::BeginLegendPopup(
id))
114 ImGui::TextUnformatted(displayTitle);
130 if (ImGui::InputInt(
"Stride", &
stride))
138 if (
auto lt =
static_cast<int>(
lineType);
139 ImGui::Combo(
"Style", <,
"Scatter\0Line\0\0"))
144 ImPlotLineFlags lFlags =
lineFlags.value_or(plotLineFlags);
145 bool plotItemLineFlagsAuto = !
lineFlags.has_value();
146 if (plotItemLineFlagsAuto) { ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.8F); }
147 if (ImGui::CheckboxFlags(
"NoClip", &lFlags, ImPlotLineFlags_NoClip))
152 if (ImGui::IsItemHovered()) { ImGui::SetTooltip(
"Markers (if displayed) on the edge of a plot will not be clipped"); }
154 if (ImGui::CheckboxFlags(
"SkipNaN", &lFlags, ImPlotLineFlags_SkipNaN))
159 if (ImGui::IsItemHovered()) { ImGui::SetTooltip(
"NaNs values will be skipped instead of rendered as missing data"); }
161 if (ImGui::CheckboxFlags(
"Loop", &lFlags, ImPlotLineFlags_Loop))
166 if (ImGui::IsItemHovered()) { ImGui::SetTooltip(
"The last and first point will be connected to form a closed loop"); }
170 if (ImGui::Button(
"Auto##Line Flags"))
175 if (plotItemLineFlagsAuto) { ImGui::PopStyleVar(); }
178 if (ImGui::DragFloat(
"Line Thickness", &
thickness, 0.1F, 0.0F, 8.0F,
"%.2f px"))
184 colormapMaskColors->
clear();
190 colormapMaskColors->
clear();
195 bool isColorAuto = ImPlot::IsColorAuto(
color);
196 auto col = isColorAuto ? ImPlot::GetColormapColor(plotElementIdx) :
color;
197 if (ImGui::ColorEdit4(
"Line Color", &col.x))
205 if (ImGui::Button(
"Auto##Line Color"))
207 color = IMPLOT_AUTO_COL;
211 if (ImGui::Checkbox(
"Markers", &
markers))
219 "Circle\0Square\0Diamond\0Up\0Down\0Left\0Right\0Cross\0Plus\0Asterisk\0\0"))
223 if (ImGui::DragFloat(
"Marker Size", &
markerSize, 0.1F, 1.0F, 10.0F,
"%.2f px"))
227 if (ImGui::DragFloat(
"Marker Weight", &
markerWeight, 0.05F, 0.5F, 3.0F,
"%.2f px"))
235 colormapMaskColors->
clear();
241 colormapMaskColors->
clear();
249 markerColormapMaskColors->
clear();
255 markerColormapMaskColors->
clear();
264 auto col = isColorAuto ? ImPlot::GetColormapColor(plotElementIdx) :
markerFillColor;
265 if (ImGui::ColorEdit4(
"Marker Fill Color", &col.x))
273 if (ImGui::Button(
"Auto##Marker Fill Color"))
281 if (ImGui::ColorEdit4(
"Marker Outline Color", &col.x))
289 if (ImGui::Button(
"Auto##Marker Outline Color"))
313 ImGui::PushStyleColor(ImGuiCol_Text, ImColor(220, 20, 60).Value);
315 ImGui::InputTextWithHint(
"Error Bounds Modifier",
"e.g. '3 * x' or 'sqrt(x)'", &expression);
318 ImGui::PopStyleColor();
330 p.DefineVar(
"x", &x);
340 catch (mu::Parser::exception_type& e)
348 auto tableEntry = [](
const char* first,
const char* second,
const char* third) {
349 ImGui::TableNextRow();
350 ImGui::TableNextColumn();
351 ImGui::TextUnformatted(first);
352 ImGui::TableNextColumn();
353 ImGui::TextUnformatted(second);
354 ImGui::TableNextColumn();
355 ImGui::TextUnformatted(third);
360 ImGui::TextUnformatted(
"Functions");
361 if (ImGui::BeginTable(fmt::format(
"Functions##{}",
id).c_str(), 3,
362 ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_NoHostExtendX, ImVec2(0.0F, 0.0F)))
364 ImGui::TableSetupColumn(
"Name");
365 ImGui::TableSetupColumn(
"Argc.");
366 ImGui::TableSetupColumn(
"Explanation");
367 ImGui::TableHeadersRow();
369 tableEntry(
"sin",
"1",
"sine function");
370 tableEntry(
"cos",
"1",
"cosine function");
371 tableEntry(
"tan",
"1",
"tangens function");
372 tableEntry(
"asin",
"1",
"arcus sine function");
373 tableEntry(
"acos",
"1",
"arcus cosine function");
374 tableEntry(
"atan",
"1",
"arcus tangens function");
375 tableEntry(
"sinh",
"1",
"hyperbolic sine function");
376 tableEntry(
"cosh",
"1",
"hyperbolic cosine");
377 tableEntry(
"tanh",
"1",
"hyperbolic tangens function");
378 tableEntry(
"asinh",
"1",
"hyperbolic arcus sine function");
379 tableEntry(
"acosh",
"1",
"hyperbolic arcus tangens function");
380 tableEntry(
"atanh",
"1",
"hyperbolic arcur tangens function");
381 tableEntry(
"log2",
"1",
"logarithm to the base 2");
382 tableEntry(
"log10",
"1",
"logarithm to the base 10");
383 tableEntry(
"log",
"1",
"logarithm to base e (2.71828...)");
384 tableEntry(
"ln",
"1",
"logarithm to base e (2.71828...)");
385 tableEntry(
"exp",
"1",
"e raised to the power of x");
386 tableEntry(
"sqrt",
"1",
"square root of a value");
387 tableEntry(
"sign",
"1",
"sign function -1 if x<0; 1 if x>0");
388 tableEntry(
"rint",
"1",
"round to nearest integer");
389 tableEntry(
"abs",
"1",
"absolute value");
390 tableEntry(
"min",
"var.",
"min of all arguments");
391 tableEntry(
"max",
"var.",
"max of all arguments");
392 tableEntry(
"sum",
"var.",
"sum of all arguments");
393 tableEntry(
"avg",
"var.",
"mean value of all arguments");
404 ImGui::TextUnformatted(
"Binary operators");
405 if (ImGui::BeginTable(fmt::format(
"Binary operators##{}",
id).c_str(), 3,
406 ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_NoHostExtendX, ImVec2(0.0F, 0.0F)))
408 ImGui::TableSetupColumn(
"Operator");
409 ImGui::TableSetupColumn(
"Description");
410 ImGui::TableSetupColumn(
"Priority");
411 ImGui::TableHeadersRow();
413 tableEntry(
"=",
"assignement *",
"0");
414 tableEntry(
"||",
"logical or",
"1");
415 tableEntry(
"&&",
"logical and",
"2");
416 tableEntry(
"|",
"bitwise or",
"3");
417 tableEntry(
"&",
"bitwise and",
"4");
418 tableEntry(
"<=",
"less or equal",
"5");
419 tableEntry(
">=",
"greater or equal",
"5");
420 tableEntry(
"!=",
"not equal",
"5");
421 tableEntry(
"==",
"equal",
"5");
422 tableEntry(
">",
"greater than",
"5");
423 tableEntry(
"<",
"less than",
"5");
424 tableEntry(
"+",
"addition",
"6");
425 tableEntry(
"-",
"subtraction",
"6");
426 tableEntry(
"*",
"multiplication",
"7");
427 tableEntry(
"/",
"division",
"7");
428 tableEntry(
"^",
"raise x to the power of y",
"8");
433 ImGui::TextUnformatted(
"Ternary Operators");
434 if (ImGui::BeginTable(fmt::format(
"Ternary Operators##{}",
id).c_str(), 3,
435 ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_NoHostExtendX, ImVec2(0.0F, 0.0F)))
437 ImGui::TableSetupColumn(
"Operator");
438 ImGui::TableSetupColumn(
"Description");
439 ImGui::TableSetupColumn(
"Remarks");
440 ImGui::TableHeadersRow();
442 tableEntry(
"?:",
"if then else operator",
"C++ style syntax");
447 ImGui::TextUnformatted(
"Constants");
448 if (ImGui::BeginTable(fmt::format(
"Constant##{}",
id).c_str(), 3,
449 ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_NoHostExtendX, ImVec2(0.0F, 0.0F)))
451 ImGui::TableSetupColumn(
"Constant");
452 ImGui::TableSetupColumn(
"Description");
453 ImGui::TableSetupColumn(
"Remarks");
454 ImGui::TableHeadersRow();
456 tableEntry(
"_pi",
"The one and only pi",
"3.14159265359");
457 tableEntry(
"_e",
"Euler's number",
"2.71828182846");
468 if (eventMarker && eventTooltips)
478 "Circle\0Square\0Diamond\0Up\0Down\0Left\0Right\0Cross\0Plus\0Asterisk\0\0"))
482 if (ImGui::DragFloat(
"Event Marker Size", &
eventMarkerSize, 0.1F, 1.0F, 10.0F,
"%.2f px"))
486 if (ImGui::DragFloat(
"Event Marker Weight", &
eventMarkerWeight, 0.05F, 0.5F, 3.0F,
"%.2f px"))
492 if (ImGui::ColorEdit4(
"Event Marker Fill Color", &col.x))
500 if (ImGui::Button(
"Auto##Event Marker Fill Color"))
508 if (ImGui::ColorEdit4(
"Event Marker Outline Color", &col.x))
516 if (ImGui::Button(
"Auto##Event Marker Outline Color"))
524 eventMarker->
clear();
525 eventTooltips->clear();
531 ImPlot::EndLegendPopup();
541 ImPlotLineFlags plotLineFlags,
546 auto lineColor = ImPlot::IsColorAuto(
color) ? ImPlot::GetColormapColor(plotElementIdx) :
color;
549 ImPlot::SetNextLineStyle(lineColor,
thickness);
561 auto dataPointCount =
static_cast<int>(std::ceil(
static_cast<double>(yData.
size())
562 /
static_cast<double>(
stride)));
569 ImPlot::SetNextColorsData(ImPlotCol_Line, colormapMaskColors->
data(),
stride *
static_cast<int>(
sizeof(ImU32)));
578 ImPlot::SetNextColorsData(ImPlotCol_MarkerFill, markerColormapMaskColors->
data(),
stride *
static_cast<int>(
sizeof(ImU32)));
579 ImPlot::SetNextColorsData(ImPlotCol_MarkerOutline, markerColormapMaskColors->
data(),
stride *
static_cast<int>(
sizeof(ImU32)));
581 ImPlot::PlotLine(plotName,
586 static_cast<int>(std::ceil(
static_cast<double>(yData.
offset()) /
static_cast<double>(
stride))),
587 stride *
static_cast<int>(
sizeof(
double)));
589 if (
errorBoundsEnabled && yErrorData && ImPlot::GetCurrentPlot()->Items.GetItemByIndex(plotElementIdx)->Show)
592 ImPlot::PlotShaded(
"",
594 (*yErrorData)[0].data(),
595 (*yErrorData)[1].data(),
597 ImPlotShadedFlags_None,
598 static_cast<int>(std::ceil(
static_cast<double>(yData.
offset()) /
static_cast<double>(
stride))),
599 stride *
static_cast<int>(
sizeof(
double)));
606 ImPlot::SetNextColorsData(ImPlotCol_MarkerFill, colormapMaskColors->
data(),
stride *
static_cast<int>(
sizeof(ImU32)));
607 ImPlot::SetNextColorsData(ImPlotCol_MarkerOutline, colormapMaskColors->
data(),
stride *
static_cast<int>(
sizeof(ImU32)));
609 ImPlot::PlotScatter(plotName,
613 lineFlags.value_or(plotLineFlags) & ImPlotLineFlags_NoClip ? ImPlotScatterFlags_NoClip : ImPlotScatterFlags_None,
614 static_cast<int>(std::ceil(
static_cast<double>(yData.
offset()) /
static_cast<double>(
stride))),
615 stride *
static_cast<int>(
sizeof(
double)));
nlohmann::json json
json namespace
Text Help Marker (?) with Tooltip.
Utility class for logging to console and file.
#define LOG_DEBUG
Debug information. Should not be called on functions which receive observations (spamming)
#define LOG_ERROR
Error occurred, which stops part of the program to work, but not everything.
Specifying the look of a certain line in the plot.
void to_json(json &j, const Node &node)
Converts the provided node into a json object.
@ None
Do not use a colormap mask.
bool ShowColormapSelector(ColormapMaskType &type, int64_t &id, const char *label)
Shows a combobox to select a colormap.
void from_json(const json &j, Node &node)
Converts the provided json object into a node object.
Specifying the look of a certain line in the plot.
float eventMarkerSize
Size of the markers (makes the marker smaller/bigger)
float errorBoundsAlpha
Alpha value for the error bounds.
std::string legendNameGui
Legend name which gets changed in the gui.
float thickness
Line thickness.
ImVec4 eventMarkerFillColor
Fill color for markers.
bool eventsEnabled
Show events on this data.
void plotData(const char *plotName, const ScrollingBuffer< double > &xData, const ScrollingBuffer< double > &yData, int plotElementIdx, int defaultStride=1, ImPlotLineFlags plotLineFlags=ImPlotLineFlags_NoClip|ImPlotLineFlags_SkipNaN, ScrollingBuffer< ImU32 > *colormapMaskColors=nullptr, ScrollingBuffer< ImU32 > *markerColormapMaskColors=nullptr, const std::array< ScrollingBuffer< double >, 2 > *yErrorData=nullptr) const
Plots the data with the style.
std::string eventTooltipFilterRegex
Tooltip search regex.
ImPlotMarker markerStyle
Style of the marker to display.
float markerWeight
Weight of the markers (increases thickness of marker lines)
int stride
Amount of points to skip for plotting.
std::optional< ImPlotLineFlags > lineFlags
Line Flags (overrides the plot selection)
float markerSize
Size of the markers (makes the marker smaller/bigger)
LegendPopupReturn showLegendPopup(const char *id, const char *displayTitle, int plotDataBufferSize, int plotElementIdx, const char *nameId, ImPlotLineFlags plotLineFlags=ImPlotLineFlags_NoClip|ImPlotLineFlags_SkipNaN, ScrollingBuffer< ImU32 > *colormapMaskColors=nullptr, ScrollingBuffer< ImU32 > *markerColormapMaskColors=nullptr, const std::function< bool(size_t &, const char *)> &ShowDataReferenceChooser=nullptr, ScrollingBuffer< double > *eventMarker=nullptr, std::vector< std::tuple< double, double, PlotEventTooltip > > *eventTooltips=nullptr)
Shows a legend popup for plot items.
size_t markerColormapMaskDataCmpIdx
Index of the plot data to compare for the color.
std::string errorBoundsModifierExpression
Expression to modify the error bounds with.
ImVec4 eventMarkerOutlineColor
Outline/Border color for markers.
@ Scatter
Scatter plot (only markers)
ImVec4 markerFillColor
Fill color for markers.
std::string errorBoundsModifierExpressionTemp
Expression to modify the error bounds with (temporary GUI variable, till it is a valid expression)
size_t errorBoundsDataIdx
Index of the plot data to use for error bounds.
float eventMarkerWeight
Weight of the markers (increases thickness of marker lines)
ImPlotMarker eventMarkerStyle
Style of the marker to display.
ImVec4 markerOutlineColor
Outline/Border color for markers.
bool errorBoundsEnabled
Wether to plot the error bounds.
size_t colormapMaskDataCmpIdx
Index of the plot data to compare for the color.
LineType lineType
Line type.
std::pair< ColormapMaskType, int64_t > markerColormapMask
Colormap mask (pair: type and id)
bool markers
Display markers for the line plot (no effect for scatter type)
std::string legendName
Display name in the legend (if not set falls back to PlotData::displayName)
std::pair< ColormapMaskType, int64_t > colormapMask
Colormap mask (pair: type and id)