Skip to content

Instantly share code, notes, and snippets.

@JamesBremner
Created September 24, 2017 20:08
Show Gist options
  • Save JamesBremner/d7d2f19a1ac73ffa34e1acd44cfae878 to your computer and use it in GitHub Desktop.
Save JamesBremner/d7d2f19a1ac73ffa34e1acd44cfae878 to your computer and use it in GitHub Desktop.
#include <nana/gui.hpp>
namespace nana
{
namespace plot
{
class plot;
class trace
{
public:
/// set data
void add( const std::vector< double >& y )
{
myY = y;
}
/// set color
void color( const colors & clr )
{
myColor = clr;
}
int size()
{
return (int) myY.size();
}
void bounds( int& min, int& max )
{
min = myY[0];
max = min;
for( auto y : myY )
{
if( y < min )
min = y;
if( y > max )
max = y;
}
}
/// draw
void update( window wd, plot* p );
private:
std::vector< double > myY;
colors myColor;
};
/** 2D plotting */
class plot
{
public:
/** CTOR
@param[in parent window where plot will be drawn
*/
plot( window parent )
: myParent( parent )
{
}
/** Add a data trace
@param[in] t the data trace to be added
*/
void add( trace& t )
{
myTrace.push_back( t );
}
int xinc()
{
return myXinc;
}
int minY()
{
return myMinY;
}
int ymax()
{
return myMaxY;
}
double Scale()
{
return myScale;
}
int YOffset()
{
return myYOffset;
}
/** Draw the plot */
void Update()
{
CalcScale();
for( auto& t : myTrace )
t.update( myParent, this );
}
private:
///window where plot will be drawn
window myParent;
/// plot traces
std::vector< trace > myTrace;
int myXinc;
int myMinY, myMaxY;
double myScale;
int myYOffset;
void CalcScale()
{
int maxCount = 0;
myTrace[0].bounds( myMinY, myMaxY );
for( auto& t : myTrace ) {
if( t.size() > maxCount )
maxCount = t.size();
int min, max;
t.bounds( min, max );
if( min < myMinY )
myMinY = min;
if( max > myMaxY )
myMaxY = max;
}
myXinc = 300 / maxCount;
myScale = 200 / ( myMaxY - myMinY );
myYOffset = 200 + myScale * myMinY;
}
};
void trace::update( window wd, plot * p )
{
drawing drw( wd );
drw.draw([this,p](paint::graphics& graph)
{
bool first = true;
int x = 0;
int xinc = p->xinc();
double s = p->Scale();
int yOffset = p->YOffset();
int prev;
for( auto y : myY )
{
if( first )
{
first = false;
prev = y;
continue;
}
graph.line(
point(x, yOffset - prev * s),
point(x+xinc, yOffset - y * s),
myColor);
x += xinc;
prev = y;
}
});
drw.update();
}
}
}
int main()
{
using namespace nana;
try
{
form fm;
// construct plot to be drawn on form
plot::plot thePlot( fm );
// construct first plot trace
plot::trace t1;
// provide some data to trace
std::vector< double > d1 { 10, 15, 20, 25, 30, 25, 20, 15, 10 };
t1.add( d1 );
// plot in blue
t1.color( colors::blue );
// add to plot
thePlot.add( t1 );
// construct second trace
plot::trace t2;
// provide data
std::vector< double > d2 { 20, 30, 40, 50, 60, 50, 40, 30, 20 };
t2.add( d2 );
// plot in red
t2.color( colors::red );
// add to plot
thePlot.add( t2 );
// update the plot
thePlot.Update();
fm.show();
exec();
}
catch( std::runtime_error& e )
{
msgbox mb( e.what() );
mb();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment