0.4.1
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
PlotItemStyle.cpp
Go to the documentation of this file.
1// This file is part of INSTINCT, the INS Toolkit for Integrated
2// Navigation Concepts and Training by the Institute of Navigation of
3// the University of Stuttgart, Germany.
4//
5// This Source Code Form is subject to the terms of the Mozilla Public
6// License, v. 2.0. If a copy of the MPL was not distributed with this
7// file, You can obtain one at https://mozilla.org/MPL/2.0/.
8
9#include "PlotItemStyle.hpp"
10
11#include <cstddef>
12#include <functional>
13#include <imgui.h>
14#include <imgui_stdlib.h>
15#include <implot.h>
16#include <implot_internal.h>
17#include <muParser.h>
18#include <string>
19
21#include "util/Logger.hpp"
22
23namespace NAV
24{
25
26/// @brief Write info to a json object
27/// @param[out] j Json output
28/// @param[in] style Object to read info from
29void to_json(json& j, const PlotItemStyle& style)
30{
31 j = json{
32 { "legendName", style.legendName },
33 { "stride", style.stride },
34 { "lineType", style.lineType },
35 { "color", style.color },
36 { "colormapMask", style.colormapMask },
37 { "colormapMaskDataCmpIdx", style.colormapMaskDataCmpIdx },
38 { "thickness", style.thickness },
39 { "markerColormapMask", style.markerColormapMask },
40 { "markerColormapMaskDataCmpIdx", style.markerColormapMaskDataCmpIdx },
41 { "markers", style.markers },
42 { "markerStyle", style.markerStyle },
43 { "markerSize", style.markerSize },
44 { "markerWeight", style.markerWeight },
45 { "markerFillColor", style.markerFillColor },
46 { "markerOutlineColor", style.markerOutlineColor },
47 { "errorBoundsEnabled", style.errorBoundsEnabled },
48 { "errorBoundsDataIdx", style.errorBoundsDataIdx },
49 { "errorBoundsAlpha", style.errorBoundsAlpha },
50 { "errorBoundsModifierExpression", style.errorBoundsModifierExpression },
51 { "eventsEnabled", style.eventsEnabled },
52 { "eventMarkerStyle", style.eventMarkerStyle },
53 { "eventMarkerSize", style.eventMarkerSize },
54 { "eventMarkerWeight", style.eventMarkerWeight },
55 { "eventMarkerFillColor", style.eventMarkerFillColor },
56 { "eventMarkerOutlineColor", style.eventMarkerOutlineColor },
57 { "eventTooltipFilterRegex", style.eventTooltipFilterRegex },
58 };
59 if (style.lineFlags) { j["lineFlags"] = style.lineFlags.value(); }
60}
61/// @brief Read info from a json object
62/// @param[in] j Json variable to read info from
63/// @param[out] style Output object
64void from_json(const json& j, PlotItemStyle& style)
65{
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); }
75 if (j.contains("markerColormapMaskDataCmpIdx")) { j.at("markerColormapMaskDataCmpIdx").get_to(style.markerColormapMaskDataCmpIdx); }
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); }
85 if (j.contains("errorBoundsModifierExpression")) { j.at("errorBoundsModifierExpression").get_to(style.errorBoundsModifierExpression); }
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); }
93}
94
96 const char* displayTitle,
97 int plotDataBufferSize,
98 int plotElementIdx,
99 [[maybe_unused]] const char* nameId,
100 ImPlotLineFlags plotLineFlags,
101 ScrollingBuffer<ImU32>* colormapMaskColors,
102 ScrollingBuffer<ImU32>* markerColormapMaskColors,
103 const std::function<bool(size_t&, const char*)>& ShowDataReferenceChooser,
104 ScrollingBuffer<double>* eventMarker,
105 std::vector<std::tuple<double, double, PlotEventTooltip>>* eventTooltips)
106{
108
109 // Legend item context menu (right click on legend item)
110 if (ImPlot::BeginLegendPopup(id))
111 {
112 if (displayTitle)
113 {
114 ImGui::TextUnformatted(displayTitle);
115 ImGui::Separator();
116 }
117
118 if (legendNameGui.empty())
119 {
121 }
122 ImGui::InputText("Legend name", &legendNameGui);
123 if (legendNameGui != legendName && !ImGui::IsItemActive())
124 {
126 ret.changed = true;
127 LOG_DEBUG("{}: Legend changed to {}", nameId, legendName);
128 }
129
130 if (ImGui::InputInt("Stride", &stride))
131 {
132 stride = std::max(stride, 0);
133 stride = std::min(stride, plotDataBufferSize - 1);
134 ret.changed = true;
135 LOG_DEBUG("{}: Stride changed to {}", nameId, stride);
136 }
137
138 if (auto lt = static_cast<int>(lineType);
139 ImGui::Combo("Style", &lt, "Scatter\0Line\0\0"))
140 {
141 lineType = static_cast<decltype(lineType)>(lt);
142 ret.changed = true;
143 }
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))
148 {
149 lineFlags = lFlags;
150 ret.changed = true;
151 }
152 if (ImGui::IsItemHovered()) { ImGui::SetTooltip("Markers (if displayed) on the edge of a plot will not be clipped"); }
153 ImGui::SameLine();
154 if (ImGui::CheckboxFlags("SkipNaN", &lFlags, ImPlotLineFlags_SkipNaN))
155 {
156 lineFlags = lFlags;
157 ret.changed = true;
158 }
159 if (ImGui::IsItemHovered()) { ImGui::SetTooltip("NaNs values will be skipped instead of rendered as missing data"); }
160 ImGui::SameLine();
161 if (ImGui::CheckboxFlags("Loop", &lFlags, ImPlotLineFlags_Loop))
162 {
163 lineFlags = lFlags;
164 ret.changed = true;
165 }
166 if (ImGui::IsItemHovered()) { ImGui::SetTooltip("The last and first point will be connected to form a closed loop"); }
167 if (lineFlags)
168 {
169 ImGui::SameLine();
170 if (ImGui::Button("Auto##Line Flags"))
171 {
172 lineFlags.reset();
173 }
174 }
175 if (plotItemLineFlagsAuto) { ImGui::PopStyleVar(); }
177 {
178 if (ImGui::DragFloat("Line Thickness", &thickness, 0.1F, 0.0F, 8.0F, "%.2f px"))
179 {
180 ret.changed = true;
181 }
182 if (colormapMaskColors && ShowColormapSelector(colormapMask.first, colormapMask.second))
183 {
184 colormapMaskColors->clear();
185 ret.changed = true;
186 }
187 if (colormapMaskColors && colormapMask.first != ColormapMaskType::None
188 && ShowDataReferenceChooser(colormapMaskDataCmpIdx, "Colormap Ref"))
189 {
190 colormapMaskColors->clear();
191 ret.changed = true;
192 }
194 {
195 bool isColorAuto = ImPlot::IsColorAuto(color);
196 auto col = isColorAuto ? ImPlot::GetColormapColor(plotElementIdx) : color;
197 if (ImGui::ColorEdit4("Line Color", &col.x))
198 {
199 color = col;
200 ret.changed = true;
201 }
202 if (!isColorAuto)
203 {
204 ImGui::SameLine();
205 if (ImGui::Button("Auto##Line Color"))
206 {
207 color = IMPLOT_AUTO_COL;
208 }
209 }
210 }
211 if (ImGui::Checkbox("Markers", &markers))
212 {
213 ret.changed = true;
214 }
215 }
217 {
218 if (ImGui::Combo("Marker Style", &markerStyle,
219 "Circle\0Square\0Diamond\0Up\0Down\0Left\0Right\0Cross\0Plus\0Asterisk\0\0"))
220 {
221 ret.changed = true;
222 }
223 if (ImGui::DragFloat("Marker Size", &markerSize, 0.1F, 1.0F, 10.0F, "%.2f px"))
224 {
225 ret.changed = true;
226 }
227 if (ImGui::DragFloat("Marker Weight", &markerWeight, 0.05F, 0.5F, 3.0F, "%.2f px"))
228 {
229 ret.changed = true;
230 }
231 if (!markers)
232 {
233 if (colormapMaskColors && ShowColormapSelector(colormapMask.first, colormapMask.second))
234 {
235 colormapMaskColors->clear();
236 ret.changed = true;
237 }
238 if (colormapMaskColors && colormapMask.first != ColormapMaskType::None
239 && ShowDataReferenceChooser(colormapMaskDataCmpIdx, "Colormap Ref"))
240 {
241 colormapMaskColors->clear();
242 ret.changed = true;
243 }
244 }
246 {
247 if (colormapMaskColors && ShowColormapSelector(markerColormapMask.first, markerColormapMask.second, "Marker "))
248 {
249 markerColormapMaskColors->clear();
250 ret.changed = true;
251 }
252 if (colormapMaskColors && markerColormapMask.first != ColormapMaskType::None
253 && ShowDataReferenceChooser(markerColormapMaskDataCmpIdx, "Marker Colormap Ref"))
254 {
255 markerColormapMaskColors->clear();
256 ret.changed = true;
257 }
258 }
262 {
263 bool isColorAuto = ImPlot::IsColorAuto(markerFillColor);
264 auto col = isColorAuto ? ImPlot::GetColormapColor(plotElementIdx) : markerFillColor;
265 if (ImGui::ColorEdit4("Marker Fill Color", &col.x))
266 {
267 markerFillColor = col;
268 ret.changed = true;
269 }
270 if (!isColorAuto)
271 {
272 ImGui::SameLine();
273 if (ImGui::Button("Auto##Marker Fill Color"))
274 {
275 markerFillColor = IMPLOT_AUTO_COL;
276 }
277 }
278
279 isColorAuto = ImPlot::IsColorAuto(markerOutlineColor);
280 col = isColorAuto ? ImPlot::GetColormapColor(plotElementIdx) : markerOutlineColor;
281 if (ImGui::ColorEdit4("Marker Outline Color", &col.x))
282 {
283 markerOutlineColor = col;
284 ret.changed = true;
285 }
286 if (!isColorAuto)
287 {
288 ImGui::SameLine();
289 if (ImGui::Button("Auto##Marker Outline Color"))
290 {
291 markerOutlineColor = IMPLOT_AUTO_COL;
292 }
293 }
294 }
295 }
297 {
298 ImGui::Separator();
299 ret.changed |= ImGui::Checkbox("Show Error Bounds", &errorBoundsEnabled);
301 {
302 auto idx = errorBoundsDataIdx;
303 if (ShowDataReferenceChooser(errorBoundsDataIdx, "Error Bounds Ref") && errorBoundsDataIdx != idx)
304 {
305 ret.changed = true;
306 ret.errorBoundsReCalcNeeded = true;
307 }
308 ret.changed |= ImGui::SliderFloat("Error Bounds Alpha", &errorBoundsAlpha, 0.0F, 1.0F, "%.2f");
310 std::string expression = errorBoundsModifierExpressionTemp;
312 {
313 ImGui::PushStyleColor(ImGuiCol_Text, ImColor(220, 20, 60).Value);
314 }
315 ImGui::InputTextWithHint("Error Bounds Modifier", "e.g. '3 * x' or 'sqrt(x)'", &expression);
317 {
318 ImGui::PopStyleColor();
319 if (!errorBoundsModifierExpression.empty() && ImGui::IsItemHovered()) { ImGui::SetTooltip("Currently used expression:\n%s", errorBoundsModifierExpression.c_str()); }
320 }
321 if (expression != errorBoundsModifierExpressionTemp && !ImGui::IsItemActive())
322 {
324 try
325 {
327 {
328 double x = 1.0;
329 mu::Parser p;
330 p.DefineVar("x", &x);
332 x = p.Eval();
333 }
334
337 ret.changed = true;
338 ret.errorBoundsReCalcNeeded = true;
339 }
340 catch (mu::Parser::exception_type& e)
341 {
342 LOG_ERROR("{}: Error bound modifier parse error on '{}': {} in expression: {}", nameId, legendName, e.GetMsg(), errorBoundsModifierExpressionTemp);
343 }
344 }
345 ImGui::SameLine();
346 if (gui::widgets::BeginHelpMarker("(?)", 0.0F))
347 {
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);
356 };
357
358 ImGui::BeginGroup();
359 {
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)))
363 {
364 ImGui::TableSetupColumn("Name");
365 ImGui::TableSetupColumn("Argc.");
366 ImGui::TableSetupColumn("Explanation");
367 ImGui::TableHeadersRow();
368
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");
394
395 ImGui::EndTable();
396 }
397 }
398 ImGui::EndGroup();
399
400 ImGui::SameLine();
401
402 ImGui::BeginGroup();
403 {
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)))
407 {
408 ImGui::TableSetupColumn("Operator");
409 ImGui::TableSetupColumn("Description");
410 ImGui::TableSetupColumn("Priority");
411 ImGui::TableHeadersRow();
412
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");
429
430 ImGui::EndTable();
431 }
432
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)))
436 {
437 ImGui::TableSetupColumn("Operator");
438 ImGui::TableSetupColumn("Description");
439 ImGui::TableSetupColumn("Remarks");
440 ImGui::TableHeadersRow();
441
442 tableEntry("?:", "if then else operator", "C++ style syntax");
443
444 ImGui::EndTable();
445 }
446
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)))
450 {
451 ImGui::TableSetupColumn("Constant");
452 ImGui::TableSetupColumn("Description");
453 ImGui::TableSetupColumn("Remarks");
454 ImGui::TableHeadersRow();
455
456 tableEntry("_pi", "The one and only pi", "3.14159265359");
457 tableEntry("_e", "Euler's number", "2.71828182846");
458
459 ImGui::EndTable();
460 }
461 }
462 ImGui::EndGroup();
463
465 }
466 }
467 }
468 if (eventMarker && eventTooltips)
469 {
470 ImGui::Separator();
471 if (ImGui::Checkbox("Events", &eventsEnabled))
472 {
473 ret.changed = true;
474 }
475 if (eventsEnabled)
476 {
477 if (ImGui::Combo("Event Marker Style", &eventMarkerStyle,
478 "Circle\0Square\0Diamond\0Up\0Down\0Left\0Right\0Cross\0Plus\0Asterisk\0\0"))
479 {
480 ret.changed = true;
481 }
482 if (ImGui::DragFloat("Event Marker Size", &eventMarkerSize, 0.1F, 1.0F, 10.0F, "%.2f px"))
483 {
484 ret.changed = true;
485 }
486 if (ImGui::DragFloat("Event Marker Weight", &eventMarkerWeight, 0.05F, 0.5F, 3.0F, "%.2f px"))
487 {
488 ret.changed = true;
489 }
490 bool isColorAuto = ImPlot::IsColorAuto(eventMarkerFillColor);
491 auto col = isColorAuto ? ImPlot::GetColormapColor(plotElementIdx) : eventMarkerFillColor;
492 if (ImGui::ColorEdit4("Event Marker Fill Color", &col.x))
493 {
495 ret.changed = true;
496 }
497 if (!isColorAuto)
498 {
499 ImGui::SameLine();
500 if (ImGui::Button("Auto##Event Marker Fill Color"))
501 {
502 eventMarkerFillColor = IMPLOT_AUTO_COL;
503 }
504 }
505
506 isColorAuto = ImPlot::IsColorAuto(eventMarkerOutlineColor);
507 col = isColorAuto ? ImPlot::GetColormapColor(plotElementIdx) : eventMarkerOutlineColor;
508 if (ImGui::ColorEdit4("Event Marker Outline Color", &col.x))
509 {
511 ret.changed = true;
512 }
513 if (!isColorAuto)
514 {
515 ImGui::SameLine();
516 if (ImGui::Button("Auto##Event Marker Outline Color"))
517 {
518 eventMarkerOutlineColor = IMPLOT_AUTO_COL;
519 }
520 }
521
522 if (ImGui::InputText("Event Filter Regex", &eventTooltipFilterRegex))
523 {
524 eventMarker->clear();
525 eventTooltips->clear();
526 ret.changed = true;
527 }
528 }
529 }
530
531 ImPlot::EndLegendPopup();
532 }
533 return ret;
534}
535
536void PlotItemStyle::plotData(const char* plotName,
537 const ScrollingBuffer<double>& xData,
538 const ScrollingBuffer<double>& yData,
539 int plotElementIdx,
540 int defaultStride,
541 ImPlotLineFlags plotLineFlags,
542 ScrollingBuffer<ImU32>* colormapMaskColors,
543 ScrollingBuffer<ImU32>* markerColormapMaskColors,
544 const std::array<ScrollingBuffer<double>, 2>* yErrorData) const
545{
546 auto lineColor = ImPlot::IsColorAuto(color) ? ImPlot::GetColormapColor(plotElementIdx) : color;
548 {
549 ImPlot::SetNextLineStyle(lineColor, thickness);
550 }
552 {
553 ImPlot::SetNextMarkerStyle(markerStyle,
555 ImPlot::IsColorAuto(markerFillColor) ? ImPlot::GetColormapColor(plotElementIdx) : markerFillColor,
557 ImPlot::IsColorAuto(markerOutlineColor) ? ImPlot::GetColormapColor(plotElementIdx) : markerOutlineColor);
558 }
559
560 auto stride = this->stride ? this->stride : defaultStride;
561 auto dataPointCount = static_cast<int>(std::ceil(static_cast<double>(yData.size())
562 / static_cast<double>(stride)));
563
564 // Plot the data
566 {
567 if (colormapMaskColors && markerColormapMaskColors && colormapMask.first != ColormapMaskType::None)
568 {
569 ImPlot::SetNextColorsData(ImPlotCol_Line, colormapMaskColors->data(), stride * static_cast<int>(sizeof(ImU32)));
570 if (markers)
571 {
572 ImPlot::SetNextColorsData(ImPlotCol_MarkerFill, markerColormapMask.first != ColormapMaskType::None ? markerColormapMaskColors->data() : colormapMaskColors->data(), stride * static_cast<int>(sizeof(ImU32)));
573 ImPlot::SetNextColorsData(ImPlotCol_MarkerOutline, markerColormapMask.first != ColormapMaskType::None ? markerColormapMaskColors->data() : colormapMaskColors->data(), stride * static_cast<int>(sizeof(ImU32)));
574 }
575 }
576 else if (markerColormapMaskColors && markers && markerColormapMask.first != ColormapMaskType::None)
577 {
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)));
580 }
581 ImPlot::PlotLine(plotName,
582 xData.data(),
583 yData.data(),
584 dataPointCount,
585 lineFlags.value_or(plotLineFlags),
586 static_cast<int>(std::ceil(static_cast<double>(yData.offset()) / static_cast<double>(stride))),
587 stride * static_cast<int>(sizeof(double)));
588
589 if (errorBoundsEnabled && yErrorData && ImPlot::GetCurrentPlot()->Items.GetItemByIndex(plotElementIdx)->Show)
590 {
591 ImPlot::SetNextFillStyle(lineColor, errorBoundsAlpha);
592 ImPlot::PlotShaded("",
593 xData.data(),
594 (*yErrorData)[0].data(),
595 (*yErrorData)[1].data(),
596 dataPointCount,
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)));
600 }
601 }
603 {
604 if (colormapMaskColors && colormapMask.first != ColormapMaskType::None && colormapMaskColors->isInfiniteBuffer())
605 {
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)));
608 }
609 ImPlot::PlotScatter(plotName,
610 xData.data(),
611 yData.data(),
612 dataPointCount,
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)));
616 }
617}
618
619} // namespace NAV
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)
Definition Logger.hpp:67
#define LOG_ERROR
Error occurred, which stops part of the program to work, but not everything.
Definition Logger.hpp:73
Specifying the look of a certain line in the plot.
A buffer which is overwriting itself from the start when full.
bool isInfiniteBuffer() const
Returns whether the buffer is infinite and growing.
const T * data() const
Returns a pointer to the raw data array (not in scrolled order)
int offset() const
Returns the data index of the first element in the buffer.
size_t size() const
Returns the number of elements in the container.
void clear()
Erases all elements from the container. After this call, size() returns zero.
bool BeginHelpMarker(const char *symbol="(?)", float textWrapLength=35.0F)
Begins a Text Help Marker, e.g. '(?)', with custom content.
void EndHelpMarker(bool wrapText=true)
Ends a Text Help Marker with custom content.
void to_json(json &j, const Node &node)
Converts the provided node into a json object.
Definition Node.cpp:990
@ None
Do not use a colormap mask.
Definition Colormap.hpp:119
bool ShowColormapSelector(ColormapMaskType &type, int64_t &id, const char *label)
Shows a combobox to select a colormap.
Definition Colormap.cpp:245
void from_json(const json &j, Node &node)
Converts the provided json object into a node object.
Definition Node.cpp:1007
bool errorBoundsReCalcNeeded
Settings of the error bounds changed and needs to be recalculated.
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.
ImVec4 color
Line Color.
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)