Skip to content

Instantly share code, notes, and snippets.

@milasudril
Created July 31, 2022 19:04
Show Gist options
  • Save milasudril/6c8de615120f1788f0eadc15de279610 to your computer and use it in GitHub Desktop.
Save milasudril/6c8de615120f1788f0eadc15de279610 to your computer and use it in GitHub Desktop.
Simple gnuplot interface
#include <span>
#include <memory>
#include <stdexcept>
#include <algorithm>
using vec2_t [[gnu::vector_size(8)]] = float;
struct pipe_closer
{
void operator()(FILE* f) const
{
if(f != nullptr)
{ pclose(f); }
}
};
using pipe = std::unique_ptr<FILE, pipe_closer>;
template<class ... T>
auto make_pipe(T&& ... args)
{
auto ret = pipe{popen(std::forward<T>(args)...)};
if(ret == nullptr)
{ throw std::runtime_error{"Failed to start gnuplot"};}
return ret;
}
struct axis_range
{
double min;
double max;
};
class plot
{
public:
plot():m_handle{make_pipe("gnuplot -p", "w")}{}
plot& x_range(axis_range range)
{
fprintf(m_handle.get(), "set xrange [%.17e:%.17e]\n", range.min, range.max);
return *this;
}
plot& y_range(axis_range range)
{
fprintf(m_handle.get(), "set yrange [%.17e:%.17e]\n", range.min, range.max);
return *this;
}
plot& axis_equal()
{
fprintf(m_handle.get(), "set size ratio -1\n");
return *this;
}
plot& add_data_series(std::span<vec2_t const> points)
{
fprintf(m_handle.get(), "plot '-' with lines\n");
std::ranges::for_each(points, [handle = m_handle.get()](auto point){
fprintf(handle, "%.17e %.17e\n", point[0], point[1]);
});
fprintf(m_handle.get(), "e\n");
return *this;
}
private:
pipe m_handle;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment