Object-oriented?

ball4

Here is a toy program, in which some balls are bouncing in a box and repulsing each other with the electrostatic force, or by the Coulomb potential.

I do not know if the program is reasonably well written or very bad, but surely the line 10 in MyArea.cpp is ugly.

/* main.cpp */
#include <gtkmm/application.h>
#include <gtkmm/window.h>
#include "MyArea.h"
#include "MyBall.h"

int main(int argc, char** argv)
{
   Glib::RefPtr<Gtk::Application> app = Gtk::Application::create(argc, argv, "org.gtkmm.example");
   Gtk::Window window;
   window.set_title("Animation Test");
   window.set_default_size(400, 400);
   MyArea area;
   window.add(area);
   area.show();
   return app->run(window);
}
/* MyArea.h */
#ifndef MYAREA_H_
#define MYAREA_H_
#include <gtkmm/drawingarea.h>

class MyArea : public  Gtk::DrawingArea {
public:
	MyArea();
	virtual ~MyArea();
protected:
	virtual bool on_draw(const Cairo::RefPtr<Cairo::Context>& cr);
	bool on_timeout();
};

#endif /* MYAREA_H_ */
/* MyArea.cpp */
#include <vector>
#include <cmath>
#include <cairomm/context.h>
#include <glibmm/main.h>
#include "MyArea.h"
#include "MyBall.h"
using namespace std;

vector<MyBall> particle(4);

MyArea::MyArea() {
	Glib::signal_timeout().connect( sigc::mem_fun(*this, &MyArea::on_timeout), 10 );

	for(unsigned int i=0;i<particle.size();i++) {
		double center = (0 + particle.size() - 1) / 2.0;
		double f = (i-center) / particle.size();
		particle[i].Set(0.04, 1.0, f+0.5, 0.8*f, -0.4, 0.0, 0.001*f);
	}
}

MyArea::~MyArea() {
}

void Force(MyBall& b1, MyBall& b2) {
	double x1 = b1.Getx();
	double y1 = b1.Gety();
	double x2 = b2.Getx();
	double y2 = b2.Gety();
	double dist_sq = (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);
	double dist    = sqrt(dist_sq);
	double force   = 0.000001 / dist_sq;
	double force_x = -force * (x2 - x1) / dist;
	double force_y = -force * (y2 - y1) / dist;
	b1.Changevx( force_x);
	b2.Changevx(-force_x);
	b1.Changevy( force_y);
	b2.Changevy(-force_y);
}

bool MyArea::on_timeout() {
	static int count = 0;
	if(count++ % 5 == 0) {	get_window()->invalidate(true); }

	for(unsigned int i=0;i<particle.size();i++) {
		for(unsigned int j=0;j<particle.size();j++) {
			if(i != j) Force(particle[i], particle[j]);
		}
	}

	for(unsigned int i=0;i<particle.size();i++) {
		particle[i].Move();
	}

    return true;
}

bool MyArea::on_draw(const Cairo::RefPtr<Cairo::Context>& cr) {

	Gtk::Allocation allocation = get_allocation();
	const int width  = allocation.get_width();
	const int height = allocation.get_height();

	cr->scale(width, height);
	cr->translate(0.5, 0.5);
	cr->set_source_rgba(0.9, 0.9, 0.8, 1.0);
	cr->paint();

	for(unsigned int i=0;i<particle.size();i++) {
		particle[i].Display(cr);
	}

	return true;
}
/* MyBall.h */
#ifndef MYBALL_H_
#define MYBALL_H_
#include <cairomm/context.h>
class MyBall {
public:
			 MyBall ();
	         MyBall (double, double, double, double, double, double);
	virtual ~MyBall ();
	void     Set    (double, double, double, double, double, double);
	void     Display(const Cairo::RefPtr<Cairo::Context>&);
	double   Getx() const;
	double   Gety() const;
	double   Getw() const;
	void     Changevx(double);
	void     Changevy(double);
	void     Move();
private:
	double m_r;
	double m_c;
	double m_x;
	double m_y;
	double m_vx;
	double m_vy;
};

#endif /* MYBALL_H_ */
/* MyBall.cpp */
#include <cairomm/context.h>
#include "MyBall.h"

MyBall::MyBall() : m_r {0.1}, m_c {0.5}, m_x {0.0}, m_y {0.0}, m_vx {0.0}, m_vy {0.0} {
}

MyBall::~MyBall() {
}

double MyBall::Getx() const {
	return m_x;
}

double MyBall::Gety() const {
	return m_y;
}

void MyBall::Changevx(double v) {
	m_vx += v;
}

void MyBall::Changevy(double v) {
	m_vy += v;
}

void MyBall::Display(const Cairo::RefPtr<Cairo::Context>& cr) {
	cr->arc(m_x, m_y, m_r, 0.0, 2.0*M_PI);
	cr->set_source_rgba(0.0, m_c, 1.0-m_c, 1.0);
	cr->fill_preserve();
	cr->set_source_rgba(0.0, 0.0, 0.0, 1.0);
	cr->set_line_width(0.01);
	cr->stroke();
}

void MyBall::Move() {
	if(m_x>0.5 || m_x<-0.5) { m_vx = -m_vx; }
	if(m_y>0.5 || m_y<-0.5) { m_vy = -m_vy; }
	m_x += m_vx;
	m_y += m_vy;
}

void MyBall::Set(double r, double c, double x, double y, double vx, double vy) {
	m_r = r;
	m_c = c;
	m_x = x;
	m_y = y;
	m_vx = vx;
	m_vy = vy;
}

Leave a Reply

Your email address will not be published. Required fields are marked *