Skip to content

Signalsmith-Audio/plot

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

97 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Basic C++ plots

This is a minimal header-only and dependency-free C++ plotting library.

It's maintained mostly for internal Signalsmith Audio use, so I'm adding features as I need them.

example plot

Design choices

  • SVG output only
  • auto-styled lines and fills
    • simultaneous colour/dash/hatch/marker sequences for accessibility
    • styling done via (customisable) CSS where possible
    • custom JS (included as source or URL)
  • explicit labelling on lines, or legends
  • values labelled with three levels: major/minor/tick
    • no explicit axis-lines, use major gridlines instead
  • simplifies paths
    • attempts not to draw out-of-view data
    • drops points along almost-straight lines
  • each plot's edge can have multiple partial axes
  • basic grid (each row/column stretches to contain its contents)
  • animated graphs with <animate> (SMIL)

Limitations

  • only 2D plots supported
  • no automatic label placement or de-collision
  • text lengths are heuristically estimated

How to use

All you need is the header file:

#include "plot.h";

View the API docs for complete info.

Basic example: drawing lines

Here's a minimal example, which sets up a 2D plot, adds some grid-lines/ticks:

// Set up a plot
signalsmith::plot::Plot2D plot;

// Place the grid/ticks
plot.x.majors(0, 10).tick(5).minor(3.5);
ploy.y.major(0);

// If you don't set the scale, it will guess from data/ticks
plot.x.linear(0, 15);
// You can use custom scales, using any function
// (or lambda) which accepts/returns `double`
plot.y.range(std::log, 1, 1000);

// Set up a line
auto &line = plot.line();
for (auto &p : points) {
	// Add points as x/y pairs
	line.add(p.x, p.y);
}
// or from array (using `.size()` if not specified)
line.addArray(xArr, yArr);

plot.write("example.svg");

More examples

See examples.cpp for code examples. Here are the images generated by that code:

Default plot styleCustom plot styleStyle sequenceLine with cutsIntersecting circlesMultiple axesLegendGridAnimationScatterScatter animated

API principles

You create a top-level object, which could be a Figure or a Plot2D:

signalsmith::plot::Plot2D plot;

When you create a sub-object (line, sub-plot, etc.), you are returned a reference. These elements are deliberately not copyable, so if you use auto instead of auto & it will complain.

auto &line = plot.line();

Many methods return a reference to the object, allowing you to chain them together, e.g.:

plot.x.major(0, 10).minor(5);

Heat maps

There's an additional module in heatmap.h for pixel-based heat-maps:

Heat-mapHeat-map with scale

This uses the PlotStyle's cmap to generate 256 RGB(A) colour-map values, then outputs an indexed PNG.

Custom style

You can customise the styles using PlotStyle objects. For individual Figures you can use the .style field, or for all plots you can alter PlotStyle::defaultStyle().

Additionally, if there is a "signalsmith-plot-style.h" in the include path, this is automatically #included by plot.h. You can use this to define a custom style per-project or system-wide. Since the library is header-only, the best way to customise is the constructor of a static global variable:

static struct MyCustomStyle {
	MyCustomStyle() {
		auto &style = signalsmith::plot::PlotStyle::defaultStyle();
		// ... get funky
	}
} myCustomStyle;

Development

Testing

There aren't any unit tests, just a visual check of the example plots.

License

Released as 0BSD. If you need anything else, get in touch. 🙂

About

GitHub mirror of our basic C++ plotting library

Resources

License

Stars

Watchers

Forks

Contributors 3

  •  
  •  
  •  

Languages