Skip to content

Commit a1a2359

Browse files
committed
core: add palette, bands/hist/heatmap, legend/tick/object API, text mode, and manifest support
1 parent ed3f32f commit a1a2359

6 files changed

Lines changed: 479 additions & 41 deletions

File tree

include/gnuplotpp/plot.hpp

Lines changed: 116 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@ namespace gnuplotpp {
1717
/** @brief Output file formats supported by the renderer. */
1818
enum class OutputFormat { Pdf, Svg, Eps, Png };
1919

20+
/** @brief Figure-wide palette selection for automatic series colors. */
21+
enum class ColorPalette { Default, Tab10, Viridis, Grayscale };
22+
23+
/** @brief Text rendering mode used by terminal setup. */
24+
enum class TextMode { Enhanced, Plain, LaTeX };
25+
2026
/** @brief Built-in publication presets for size and style defaults. */
2127
enum class Preset {
2228
IEEE_SingleColumn,
@@ -46,10 +52,64 @@ struct FigureSpec {
4652
Preset preset = Preset::IEEE_SingleColumn;
4753
FigureSizeInches size{};
4854
Style style{};
55+
ColorPalette palette = ColorPalette::Default;
56+
TextMode text_mode = TextMode::Enhanced;
4957
int rows = 1;
5058
int cols = 1;
5159
std::vector<OutputFormat> formats{OutputFormat::Pdf};
5260
std::string title;
61+
bool write_manifest = false;
62+
};
63+
64+
/** @brief Legend placement presets. */
65+
enum class LegendPosition {
66+
TopRight,
67+
TopLeft,
68+
BottomRight,
69+
BottomLeft,
70+
OutsideRight,
71+
OutsideBottom
72+
};
73+
74+
/** @brief Legend configuration for one axes. */
75+
struct LegendSpec {
76+
bool enabled = true;
77+
LegendPosition position = LegendPosition::TopRight;
78+
int columns = 1;
79+
bool boxed = false;
80+
bool opaque = false;
81+
bool has_font_pt = false;
82+
double font_pt = 8.0;
83+
};
84+
85+
/** @brief Typed label annotation. */
86+
struct LabelAnnotation {
87+
std::string text;
88+
std::string at = "graph 0.05,0.95";
89+
std::string font;
90+
bool front = true;
91+
};
92+
93+
/** @brief Typed arrow annotation. */
94+
struct ArrowAnnotation {
95+
std::string from = "graph 0.1,0.9";
96+
std::string to = "graph 0.2,0.8";
97+
bool heads = true;
98+
double line_width_pt = 1.0;
99+
std::string color = "#000000";
100+
bool front = true;
101+
};
102+
103+
/** @brief Typed rectangle object for highlights/masks. */
104+
struct RectObject {
105+
std::string from = "graph 0.1,0.1";
106+
std::string to = "graph 0.2,0.2";
107+
bool has_fill_opacity = false;
108+
double fill_opacity = 0.15;
109+
std::string fill_color = "#000000";
110+
bool border = false;
111+
std::string border_color = "#000000";
112+
bool front = false;
53113
};
54114

55115
/** @brief Axes-level labels, limits, and grid/log controls. */
@@ -59,6 +119,7 @@ struct AxesSpec {
59119
std::string ylabel;
60120
bool grid = false;
61121
bool legend = true;
122+
LegendSpec legend_spec{};
62123

63124
bool has_xlim = false;
64125
double xmin = 0.0;
@@ -71,12 +132,27 @@ struct AxesSpec {
71132
bool xlog = false;
72133
bool ylog = false;
73134

135+
bool has_xtick_step = false;
136+
double xtick_step = 1.0;
137+
bool has_ytick_step = false;
138+
double ytick_step = 1.0;
139+
bool has_xminor_count = false;
140+
int xminor_count = 2;
141+
bool has_yminor_count = false;
142+
int yminor_count = 2;
143+
std::string xformat;
144+
std::string yformat;
145+
146+
std::vector<LabelAnnotation> labels;
147+
std::vector<ArrowAnnotation> arrows;
148+
std::vector<RectObject> rectangles;
149+
74150
// Optional raw gnuplot commands for advanced annotations (arrows/labels/etc).
75151
std::vector<std::string> gnuplot_commands;
76152
};
77153

78154
/** @brief Supported series drawing types. */
79-
enum class SeriesType { Line, Scatter, ErrorBars, Band };
155+
enum class SeriesType { Line, Scatter, ErrorBars, Band, Histogram, Heatmap };
80156

81157
/** @brief Series metadata and optional per-series style override. */
82158
struct SeriesSpec {
@@ -100,6 +176,8 @@ struct SeriesData {
100176
SeriesSpec spec;
101177
std::vector<double> x;
102178
std::vector<double> y;
179+
std::vector<double> y2;
180+
std::vector<double> z;
103181
};
104182

105183
/**
@@ -124,6 +202,43 @@ class Axes {
124202
std::span<const double> x,
125203
std::span<const double> y);
126204

205+
/**
206+
* @brief Add a confidence band from lower/upper curves.
207+
* @param spec Series style metadata.
208+
* @param x X samples.
209+
* @param y_low Lower bound values.
210+
* @param y_high Upper bound values.
211+
* @throws std::invalid_argument if lengths differ.
212+
*/
213+
void add_band(const SeriesSpec& spec,
214+
std::span<const double> x,
215+
std::span<const double> y_low,
216+
std::span<const double> y_high);
217+
218+
/**
219+
* @brief Add a histogram-style series from bin centers and counts.
220+
* @param spec Series metadata.
221+
* @param bin_centers Histogram bin centers.
222+
* @param counts Histogram values.
223+
* @throws std::invalid_argument if lengths differ.
224+
*/
225+
void add_histogram(const SeriesSpec& spec,
226+
std::span<const double> bin_centers,
227+
std::span<const double> counts);
228+
229+
/**
230+
* @brief Add heatmap samples as x/y/z triplets.
231+
* @param spec Series metadata.
232+
* @param x X coordinates.
233+
* @param y Y coordinates.
234+
* @param z Intensity values.
235+
* @throws std::invalid_argument if lengths differ.
236+
*/
237+
void add_heatmap(const SeriesSpec& spec,
238+
std::span<const double> x,
239+
std::span<const double> y,
240+
std::span<const double> z);
241+
127242
/** @return Current axes configuration. */
128243
const AxesSpec& spec() const { return spec_; }
129244

include/gnuplotpp/presets.hpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44

55
namespace gnuplotpp {
66

7+
/** @brief High-level style bundles for common publication/presentation looks. */
8+
enum class StyleProfile { Science, IEEE_Strict, AIAA_Strict, Presentation, DarkPrintSafe };
9+
710
/** @brief Resolved size/style defaults for one preset. */
811
struct PresetDefaults {
912
FigureSizeInches size;
@@ -27,4 +30,11 @@ void apply_preset_defaults(FigureSpec& spec,
2730
bool overwrite_size = true,
2831
bool overwrite_style = true);
2932

33+
/**
34+
* @brief Apply a style profile on top of current figure style/palette settings.
35+
* @param spec Figure spec to update.
36+
* @param profile Style profile selector.
37+
*/
38+
void apply_style_profile(FigureSpec& spec, StyleProfile profile);
39+
3040
} // namespace gnuplotpp

src/figure.cpp

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,64 @@ void Axes::add_series(const SeriesSpec& spec,
2323
series_.push_back(std::move(data));
2424
}
2525

26+
void Axes::add_band(const SeriesSpec& spec,
27+
std::span<const double> x,
28+
std::span<const double> y_low,
29+
std::span<const double> y_high) {
30+
if (x.size() != y_low.size() || x.size() != y_high.size()) {
31+
throw std::invalid_argument("x, y_low, and y_high must have the same length");
32+
}
33+
SeriesSpec band_spec = spec;
34+
band_spec.type = SeriesType::Band;
35+
if (band_spec.has_opacity && (band_spec.opacity < 0.0 || band_spec.opacity > 1.0)) {
36+
throw std::invalid_argument("series opacity must be in [0, 1]");
37+
}
38+
SeriesData data;
39+
data.spec = band_spec;
40+
data.x.assign(x.begin(), x.end());
41+
data.y.assign(y_low.begin(), y_low.end());
42+
data.y2.assign(y_high.begin(), y_high.end());
43+
series_.push_back(std::move(data));
44+
}
45+
46+
void Axes::add_histogram(const SeriesSpec& spec,
47+
std::span<const double> bin_centers,
48+
std::span<const double> counts) {
49+
if (bin_centers.size() != counts.size()) {
50+
throw std::invalid_argument("bin_centers and counts must have the same length");
51+
}
52+
SeriesSpec hist_spec = spec;
53+
hist_spec.type = SeriesType::Histogram;
54+
if (hist_spec.has_opacity && (hist_spec.opacity < 0.0 || hist_spec.opacity > 1.0)) {
55+
throw std::invalid_argument("series opacity must be in [0, 1]");
56+
}
57+
SeriesData data;
58+
data.spec = hist_spec;
59+
data.x.assign(bin_centers.begin(), bin_centers.end());
60+
data.y.assign(counts.begin(), counts.end());
61+
series_.push_back(std::move(data));
62+
}
63+
64+
void Axes::add_heatmap(const SeriesSpec& spec,
65+
std::span<const double> x,
66+
std::span<const double> y,
67+
std::span<const double> z) {
68+
if (x.size() != y.size() || x.size() != z.size()) {
69+
throw std::invalid_argument("x, y, and z must have the same length");
70+
}
71+
SeriesSpec hm_spec = spec;
72+
hm_spec.type = SeriesType::Heatmap;
73+
if (hm_spec.has_opacity && (hm_spec.opacity < 0.0 || hm_spec.opacity > 1.0)) {
74+
throw std::invalid_argument("series opacity must be in [0, 1]");
75+
}
76+
SeriesData data;
77+
data.spec = hm_spec;
78+
data.x.assign(x.begin(), x.end());
79+
data.y.assign(y.begin(), y.end());
80+
data.z.assign(z.begin(), z.end());
81+
series_.push_back(std::move(data));
82+
}
83+
2684
Figure::Figure(FigureSpec spec) : spec_(std::move(spec)) {
2785
if (spec_.rows <= 0 || spec_.cols <= 0) {
2886
throw std::invalid_argument("rows and cols must be positive");

0 commit comments

Comments
 (0)