1
0
Fork 0
mirror of https://github.com/gwm17/implot.git synced 2024-11-26 12:18:52 -05:00

add stems and fix bug with marker size

This commit is contained in:
epezent 2020-09-02 09:17:18 -05:00
parent 624fedabe4
commit c8b21a6d36
5 changed files with 205 additions and 65 deletions

View File

@ -20,7 +20,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// ImPlot v0.5 WIP
// ImPlot v0.6 WIP
/*

View File

@ -20,7 +20,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// ImPlot v0.5 WIP
// ImPlot v0.6 WIP
#pragma once
#include "imgui.h"
@ -30,7 +30,7 @@
//-----------------------------------------------------------------------------
// ImPlot version string
#define IMPLOT_VERSION "0.5 WIP"
#define IMPLOT_VERSION "0.6 WIP"
// Indicates variable should deduced automatically.
#define IMPLOT_AUTO -1
// Special color used to indicate that a color should be deduced automatically.
@ -348,6 +348,12 @@ void PlotErrorBarsH(const char* label_id, const double* xs, const double* ys, co
void PlotErrorBarsH(const char* label_id, const float* xs, const float* ys, const float* neg, const float* pos, int count, int offset = 0, int stride = sizeof(float));
void PlotErrorBarsH(const char* label_id, const double* xs, const double* ys, const double* neg, const double* pos, int count, int offset = 0, int stride = sizeof(double));
/// Plots vertical stems.
void PlotStems(const char* label_id, const float* values, int count, float y_ref = 0, int offset = 0, int stride = sizeof(float));
void PlotStems(const char* label_id, const double* values, int count, double y_ref = 0, int offset = 0, int stride = sizeof(double));
void PlotStems(const char* label_id, const float* xs, const float* ys, int count, float y_ref = 0, int offset = 0, int stride = sizeof(float));
void PlotStems(const char* label_id, const double* xs, const double* ys, int count, double y_ref = 0, int offset = 0, int stride = sizeof(double));
// Plots a pie chart. If the sum of values > 1 or normalize is true, each value will be normalized. Center and radius are in plot units. #label_fmt can be set to NULL for no labels.
void PlotPieChart(const char** label_ids, const float* values, int count, float x, float y, float radius, bool normalize = false, const char* label_fmt = "%.1f", float angle0 = 90);
void PlotPieChart(const char** label_ids, const double* values, int count, double x, double y, double radius, bool normalize = false, const char* label_fmt = "%.1f", double angle0 = 90);

View File

@ -20,7 +20,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// ImPlot v0.5 WIP
// ImPlot v0.6 WIP
#include "implot.h"
#include <math.h>
@ -394,6 +394,25 @@ void ShowDemoWindow(bool* p_open) {
ImPlot::EndPlot();
}
}
if (ImGui::CollapsingHeader("Stem Plots")) {
static t_float xs[51], ys1[51], ys2[51];
for (int i = 0; i < 51; ++i) {
xs[i] = i * 0.02f;
ys1[i] = 1.0f + 0.5f * Sin(25*xs[i])*Cos(2*xs[i]);
ys2[i] = 0.5f + 0.25f * Sin(10*xs[i]) * Sin(xs[i]);
}
ImPlot::SetNextPlotLimits(0,1,0,1.6);
if (ImPlot::BeginPlot("Stem Plots")) {
ImPlot::PlotStems("Stems 1",xs,ys1,51);
ImPlot::SetNextLineStyle(ImVec4(1,0.5f,0,0.75f));
ImPlot::SetNextMarkerStyle(ImPlotMarker_Square,5,ImVec4(1,0.5f,0,0.25f));
ImPlot::PlotStems("Stems 2", xs, ys2,51);
ImPlot::EndPlot();
}
}
//-------------------------------------------------------------------------
if (ImGui::CollapsingHeader("Pie Charts")) {
static const char* labels1[] = {"Frogs","Hogs","Dogs","Logs"};
@ -1301,10 +1320,10 @@ namespace ImPlot {
struct BenchmarkItem {
BenchmarkItem() {
float y = RandomRange(0,1);
float y = (float)RandomRange(0,1);
Data = new float[1000];
for (int i = 0; i < 1000; ++i) {
Data[i] = y + RandomRange(-0.01f,0.01f);
Data[i] = y + (float)RandomRange(-0.01f,0.01f);
}
Col = ImVec4((float)RandomRange(0,1),(float)RandomRange(0,1),(float)RandomRange(0,1),1);
}

View File

@ -20,7 +20,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// ImPlot v0.5 WIP
// ImPlot v0.6 WIP
// You may use this file to debug, understand or extend ImPlot features but we
// don't provide any guarantee of forward compatibility!
@ -134,12 +134,12 @@ struct ImBufferWriter
}
};
// Fixed size array
template <typename T, int N>
struct ImArray {
inline T& operator[](int i) { return Data[i]; }
inline const T& operator[](int i) const { return Data[i]; }
T Data[N];
// Fixed size point array
template <int N>
struct ImPlotPointArray {
inline ImPlotPoint& operator[](int i) { return Data[i]; }
inline const ImPlotPoint& operator[](int i) const { return Data[i]; }
ImPlotPoint Data[N];
const int Size = N;
};
@ -388,7 +388,7 @@ struct ImPlotItemStyle {
ImPlotItemStyle() {
for (int i = 0; i < 5; ++i)
Colors[i] = IMPLOT_AUTO_COL;
LineWeight = MarkerWeight = FillAlpha = ErrorBarSize =
LineWeight = MarkerSize = MarkerWeight = FillAlpha = ErrorBarSize =
ErrorBarSize = ErrorBarWeight = DigitalBitHeight = DigitalBitGap = IMPLOT_AUTO;
Marker = IMPLOT_AUTO;
}

View File

@ -20,7 +20,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// ImPlot v0.5 WIP
// ImPlot v0.6 WIP
#include "implot.h"
#include "implot_internal.h"
@ -428,45 +428,28 @@ struct TransformerLogLog {
// PRIMITIVE RENDERERS
//-----------------------------------------------------------------------------
template <typename TGetter, typename TTransformer>
struct LineRenderer {
inline LineRenderer(TGetter getter, TTransformer transformer, ImU32 col, float weight) :
Getter(getter),
Transformer(transformer)
{
Prims = Getter.Count - 1;
Col = col;
Weight = weight;
P1 = Transformer(Getter(0));
}
inline bool operator()(ImDrawList& DrawList, ImVec2 uv, int prim) {
ImPlotContext& gp = *GImPlot;
ImVec2 P2 = Transformer(Getter(prim + 1));
if (!gp.BB_Plot.Overlaps(ImRect(ImMin(P1, P2), ImMax(P1, P2)))) {
P1 = P2;
return false;
}
inline void AddLine(const ImVec2& P1, const ImVec2& P2, float weight, ImU32 col, ImDrawList& DrawList, ImVec2 uv) {
float dx = P2.x - P1.x;
float dy = P2.y - P1.y;
IM_NORMALIZE2F_OVER_ZERO(dx, dy);
dx *= (Weight * 0.5f);
dy *= (Weight * 0.5f);
dx *= (weight * 0.5f);
dy *= (weight * 0.5f);
DrawList._VtxWritePtr[0].pos.x = P1.x + dy;
DrawList._VtxWritePtr[0].pos.y = P1.y - dx;
DrawList._VtxWritePtr[0].uv = uv;
DrawList._VtxWritePtr[0].col = Col;
DrawList._VtxWritePtr[0].col = col;
DrawList._VtxWritePtr[1].pos.x = P2.x + dy;
DrawList._VtxWritePtr[1].pos.y = P2.y - dx;
DrawList._VtxWritePtr[1].uv = uv;
DrawList._VtxWritePtr[1].col = Col;
DrawList._VtxWritePtr[1].col = col;
DrawList._VtxWritePtr[2].pos.x = P2.x - dy;
DrawList._VtxWritePtr[2].pos.y = P2.y + dx;
DrawList._VtxWritePtr[2].uv = uv;
DrawList._VtxWritePtr[2].col = Col;
DrawList._VtxWritePtr[2].col = col;
DrawList._VtxWritePtr[3].pos.x = P1.x - dy;
DrawList._VtxWritePtr[3].pos.y = P1.y + dx;
DrawList._VtxWritePtr[3].uv = uv;
DrawList._VtxWritePtr[3].col = Col;
DrawList._VtxWritePtr[3].col = col;
DrawList._VtxWritePtr += 4;
DrawList._IdxWritePtr[0] = (ImDrawIdx)(DrawList._VtxCurrentIdx);
DrawList._IdxWritePtr[1] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 1);
@ -476,6 +459,26 @@ struct LineRenderer {
DrawList._IdxWritePtr[5] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 3);
DrawList._IdxWritePtr += 6;
DrawList._VtxCurrentIdx += 4;
}
template <typename TGetter, typename TTransformer>
struct LineStripRenderer {
inline LineStripRenderer(TGetter getter, TTransformer transformer, ImU32 col, float weight) :
Getter(getter),
Transformer(transformer)
{
Prims = Getter.Count - 1;
Col = col;
Weight = weight;
P1 = Transformer(Getter(0));
}
inline bool operator()(ImDrawList& DrawList, const ImRect& cull_rect, const ImVec2& uv, int prim) {
ImVec2 P2 = Transformer(Getter(prim + 1));
if (!cull_rect.Overlaps(ImRect(ImMin(P1, P2), ImMax(P1, P2)))) {
P1 = P2;
return false;
}
AddLine(P1,P2,Weight,Col,DrawList,uv);
P1 = P2;
return true;
}
@ -489,6 +492,36 @@ struct LineRenderer {
static const int VtxConsumed = 4;
};
template <typename TGetter1, typename TGetter2, typename TTransformer>
struct LineSegmentsRenderer {
inline LineSegmentsRenderer(TGetter1 getter1, TGetter2 getter2, TTransformer transformer, ImU32 col, float weight) :
Getter1(getter1),
Getter2(getter2),
Transformer(transformer)
{
Prims = ImMin(Getter1.Count, Getter2.Count);
Col = col;
Weight = weight;
}
inline bool operator()(ImDrawList& DrawList, const ImRect& cull_rect, const ImVec2& uv, int prim) {
ImVec2 P1 = Transformer(Getter1(prim));
ImVec2 P2 = Transformer(Getter2(prim));
if (!cull_rect.Overlaps(ImRect(ImMin(P1, P2), ImMax(P1, P2))))
return false;
AddLine(P1,P2,Weight,Col,DrawList,uv);
return true;
}
TGetter1 Getter1;
TGetter2 Getter2;
TTransformer Transformer;
int Prims;
ImU32 Col;
float Weight;
static const int IdxConsumed = 6;
static const int VtxConsumed = 4;
};
template <typename TGetter1, typename TGetter2, typename TTransformer>
struct ShadedRenderer {
ShadedRenderer(TGetter1 getter1, TGetter2 getter2, TTransformer transformer, ImU32 col) :
@ -502,7 +535,7 @@ struct ShadedRenderer {
P12 = Transformer(Getter2(0));
}
inline bool operator()(ImDrawList& DrawList, ImVec2 uv, int prim) {
inline bool operator()(ImDrawList& DrawList, const ImRect& /*cull_rect*/, const ImVec2& uv, int prim) {
// TODO: Culling
ImVec2 P21 = Transformer(Getter1(prim+1));
ImVec2 P22 = Transformer(Getter2(prim+1));
@ -555,7 +588,7 @@ struct RectRenderer {
Prims = Getter.Count / 2;
Col = col;
}
inline bool operator()(ImDrawList& DrawList, ImVec2 uv, int prim) {
inline bool operator()(ImDrawList& DrawList, const ImRect& /*cull_rect*/, const ImVec2& uv, int prim) {
// TODO: Culling
ImVec2 P1 = Transformer(Getter(2*prim));
ImVec2 P2 = Transformer(Getter(2*prim+1));
@ -600,7 +633,7 @@ template <> const unsigned int MaxIdx<unsigned int>::Value = 4294967295;
/// Renders primitive shapes in bulk as efficiently as possible.
template <typename Renderer>
inline void RenderPrimitives(Renderer renderer, ImDrawList& DrawList) {
inline void RenderPrimitives(Renderer renderer, ImDrawList& DrawList, const ImRect& cull_rect) {
unsigned int prims = renderer.Prims;
unsigned int prims_culled = 0;
unsigned int idx = 0;
@ -628,7 +661,7 @@ inline void RenderPrimitives(Renderer renderer, ImDrawList& DrawList) {
}
prims -= cnt;
for (unsigned int ie = idx + cnt; idx != ie; ++idx) {
if (!renderer(DrawList, uv, idx))
if (!renderer(DrawList, cull_rect, uv, idx))
prims_culled++;
}
}
@ -641,7 +674,7 @@ inline void RenderLineStrip(Getter getter, Transformer transformer, ImDrawList&
ImPlotContext& gp = *GImPlot;
if (ImHasFlag(gp.CurrentPlot->Flags, ImPlotFlags_AntiAliased) || gp.Style.AntiAliasedLines) {
ImVec2 p1 = transformer(getter(0));
for (int i = 0; i < getter.Count; ++i) {
for (int i = 1; i < getter.Count; ++i) {
ImVec2 p2 = transformer(getter(i));
if (gp.BB_Plot.Overlaps(ImRect(ImMin(p1, p2), ImMax(p1, p2))))
DrawList.AddLine(p1, p2, col, line_weight);
@ -649,7 +682,24 @@ inline void RenderLineStrip(Getter getter, Transformer transformer, ImDrawList&
}
}
else {
RenderPrimitives(LineRenderer<Getter,Transformer>(getter, transformer, col, line_weight), DrawList);
RenderPrimitives(LineStripRenderer<Getter,Transformer>(getter, transformer, col, line_weight), DrawList, gp.BB_Plot);
}
}
template <typename Getter1, typename Getter2, typename Transformer>
inline void RenderLineSegments(Getter1 getter1, Getter2 getter2, Transformer transformer, ImDrawList& DrawList, float line_weight, ImU32 col) {
ImPlotContext& gp = *GImPlot;
if (ImHasFlag(gp.CurrentPlot->Flags, ImPlotFlags_AntiAliased) || gp.Style.AntiAliasedLines) {
int I = ImMin(getter1.Count, getter2.Count);
for (int i = 0; i < I; ++i) {
ImVec2 p1 = transformer(getter1(i));
ImVec2 p2 = transformer(getter2(i));
if (gp.BB_Plot.Overlaps(ImRect(ImMin(p1, p2), ImMax(p1, p2))))
DrawList.AddLine(p1, p2, col, line_weight);
}
}
else {
RenderPrimitives(LineSegmentsRenderer<Getter1,Getter2,Transformer>(getter1, getter2, transformer, col, line_weight), DrawList, gp.BB_Plot);
}
}
@ -742,7 +792,7 @@ inline void RenderMarkerCross(ImDrawList& DrawList, const ImVec2& c, float s, bo
template <typename Transformer, typename Getter>
inline void RenderMarkers(Getter getter, Transformer transformer, ImDrawList& DrawList, ImPlotMarker marker, float size, bool rend_mk_line, ImU32 col_mk_line, float weight, bool rend_mk_fill, ImU32 col_mk_fill) {
static void (*marker_table[])(ImDrawList&, const ImVec2&, float s, bool, ImU32, bool, ImU32, float) = {
static void (*marker_table[ImPlotMarker_COUNT])(ImDrawList&, const ImVec2&, float s, bool, ImU32, bool, ImU32, float) = {
RenderMarkerCircle,
RenderMarkerSquare,
RenderMarkerDiamond ,
@ -928,10 +978,10 @@ inline void PlotShadedEx(const char* label_id, Getter1 getter1, Getter2 getter2)
if (s.RenderFill) {
ImU32 col = ImGui::GetColorU32(s.Colors[ImPlotCol_Fill]);
switch (GetCurrentScale()) {
case ImPlotScale_LinLin: RenderPrimitives(ShadedRenderer<Getter1,Getter2,TransformerLinLin>(getter1,getter2,TransformerLinLin(), col), DrawList); break;
case ImPlotScale_LogLin: RenderPrimitives(ShadedRenderer<Getter1,Getter2,TransformerLogLin>(getter1,getter2,TransformerLogLin(), col), DrawList); break;
case ImPlotScale_LinLog: RenderPrimitives(ShadedRenderer<Getter1,Getter2,TransformerLinLog>(getter1,getter2,TransformerLinLog(), col), DrawList); break;
case ImPlotScale_LogLog: RenderPrimitives(ShadedRenderer<Getter1,Getter2,TransformerLogLog>(getter1,getter2,TransformerLogLog(), col), DrawList); break;
case ImPlotScale_LinLin: RenderPrimitives(ShadedRenderer<Getter1,Getter2,TransformerLinLin>(getter1,getter2,TransformerLinLin(), col), DrawList, GImPlot->BB_Plot); break;
case ImPlotScale_LogLin: RenderPrimitives(ShadedRenderer<Getter1,Getter2,TransformerLogLin>(getter1,getter2,TransformerLogLin(), col), DrawList, GImPlot->BB_Plot); break;
case ImPlotScale_LinLog: RenderPrimitives(ShadedRenderer<Getter1,Getter2,TransformerLinLog>(getter1,getter2,TransformerLinLog(), col), DrawList, GImPlot->BB_Plot); break;
case ImPlotScale_LogLog: RenderPrimitives(ShadedRenderer<Getter1,Getter2,TransformerLogLog>(getter1,getter2,TransformerLogLog(), col), DrawList, GImPlot->BB_Plot); break;
}
}
EndItem();
@ -1226,6 +1276,71 @@ void PlotErrorBarsH(const char* label_id, const double* xs, const double* ys, co
PlotErrorBarsHEx(label_id, getter);
}
//-----------------------------------------------------------------------------
// PLOT STEMS
//-----------------------------------------------------------------------------
template <typename GetterM, typename GetterB>
inline void PlotStemsEx(const char* label_id, GetterM get_mark, GetterB get_base) {
if (BeginItem(label_id, ImPlotCol_Line)) {
if (FitThisFrame()) {
for (int i = 0; i < get_base.Count; ++i) {
FitPoint(get_mark(i));
FitPoint(get_base(i));
}
}
const ImPlotItemStyle& s = GetItemStyle();
ImDrawList& DrawList = *GetPlotDrawList();
// render stems
if (s.RenderLine) {
const ImU32 col_line = ImGui::GetColorU32(s.Colors[ImPlotCol_Line]);
switch (GetCurrentScale()) {
case ImPlotScale_LinLin: RenderLineSegments(get_mark, get_base, TransformerLinLin(), DrawList, s.LineWeight, col_line); break;
case ImPlotScale_LogLin: RenderLineSegments(get_mark, get_base, TransformerLogLin(), DrawList, s.LineWeight, col_line); break;
case ImPlotScale_LinLog: RenderLineSegments(get_mark, get_base, TransformerLinLog(), DrawList, s.LineWeight, col_line); break;
case ImPlotScale_LogLog: RenderLineSegments(get_mark, get_base, TransformerLogLog(), DrawList, s.LineWeight, col_line); break;
}
}
// render markers
ImPlotMarker marker = s.Marker == ImPlotMarker_None ? ImPlotMarker_Circle : s.Marker;
if (marker != ImPlotMarker_None) {
const ImU32 col_line = ImGui::GetColorU32(s.Colors[ImPlotCol_MarkerOutline]);
const ImU32 col_fill = ImGui::GetColorU32(s.Colors[ImPlotCol_MarkerFill]);
switch (GetCurrentScale()) {
case ImPlotScale_LinLin: RenderMarkers(get_mark, TransformerLinLin(), DrawList, marker, s.MarkerSize, s.RenderMarkerLine, col_line, s.MarkerWeight, s.RenderMarkerFill, col_fill); break;
case ImPlotScale_LogLin: RenderMarkers(get_mark, TransformerLogLin(), DrawList, marker, s.MarkerSize, s.RenderMarkerLine, col_line, s.MarkerWeight, s.RenderMarkerFill, col_fill); break;
case ImPlotScale_LinLog: RenderMarkers(get_mark, TransformerLinLog(), DrawList, marker, s.MarkerSize, s.RenderMarkerLine, col_line, s.MarkerWeight, s.RenderMarkerFill, col_fill); break;
case ImPlotScale_LogLog: RenderMarkers(get_mark, TransformerLogLog(), DrawList, marker, s.MarkerSize, s.RenderMarkerLine, col_line, s.MarkerWeight, s.RenderMarkerFill, col_fill); break;
}
}
EndItem();
}
}
void PlotStems(const char* label_id, const float* values, int count, float y_ref, int offset, int stride) {
GetterYs<float> get_mark(values,count,offset,stride);
GetterYRef<float> get_base(y_ref,count);
PlotStemsEx(label_id, get_mark, get_base);
}
void PlotStems(const char* label_id, const double* values, int count, double y_ref, int offset, int stride) {
GetterYs<double> get_mark(values,count,offset,stride);
GetterYRef<double> get_base(y_ref,count);
PlotStemsEx(label_id, get_mark, get_base);
}
void PlotStems(const char* label_id, const float* xs, const float* ys, int count, float y_ref, int offset, int stride) {
GetterXsYs<float> get_mark(xs,ys,count,offset,stride);
GetterXsYRef<float> get_base(xs,y_ref,count,offset,stride);
PlotStemsEx(label_id, get_mark, get_base);
}
void PlotStems(const char* label_id, const double* xs, const double* ys, int count, double y_ref, int offset, int stride) {
GetterXsYs<double> get_mark(xs,ys,count,offset,stride);
GetterXsYRef<double> get_base(xs,y_ref,count,offset,stride);
PlotStemsEx(label_id, get_mark, get_base);
}
//-----------------------------------------------------------------------------
// PLOT PIE CHART
//-----------------------------------------------------------------------------
@ -1476,10 +1591,10 @@ void PlotRectsEx(const char* label_id, Getter getter) {
ImDrawList& DrawList = *GetPlotDrawList();
ImU32 col = ImGui::GetColorU32(s.Colors[ImPlotCol_Fill]);
switch (GetCurrentScale()) {
case ImPlotScale_LinLin: RenderPrimitives(RectRenderer<Getter,TransformerLinLin>(getter, TransformerLinLin(), col), DrawList); break;
case ImPlotScale_LogLin: RenderPrimitives(RectRenderer<Getter,TransformerLogLin>(getter, TransformerLogLin(), col), DrawList); break;
case ImPlotScale_LinLog: RenderPrimitives(RectRenderer<Getter,TransformerLinLog>(getter, TransformerLinLog(), col), DrawList); break;
case ImPlotScale_LogLog: RenderPrimitives(RectRenderer<Getter,TransformerLogLog>(getter, TransformerLogLog(), col), DrawList); break;
case ImPlotScale_LinLin: RenderPrimitives(RectRenderer<Getter,TransformerLinLin>(getter, TransformerLinLin(), col), DrawList, GImPlot->BB_Plot); break;
case ImPlotScale_LogLin: RenderPrimitives(RectRenderer<Getter,TransformerLogLin>(getter, TransformerLogLin(), col), DrawList, GImPlot->BB_Plot); break;
case ImPlotScale_LinLog: RenderPrimitives(RectRenderer<Getter,TransformerLinLog>(getter, TransformerLinLog(), col), DrawList, GImPlot->BB_Plot); break;
case ImPlotScale_LogLog: RenderPrimitives(RectRenderer<Getter,TransformerLogLog>(getter, TransformerLogLog(), col), DrawList, GImPlot->BB_Plot); break;
}
}
EndItem();