#include "ElecField.h" #define WHILE_LIMIT 10000 struct Charge { bool sign ; // true si positive Sint16 value ; Uint16 nbOut ; double x ; // entre 0.0 et 1.0 double y ; }; ElecField::ElecField() : m_graph( 0x0 ) { //ctor } ElecField::~ElecField() { if ( !m_graph ) SDL_FreeSurface( m_graph ) ; } void ElecField::renderGraph( int w, int h ) { // Détruit vieille surface si existante if ( !m_graph ) SDL_FreeSurface( m_graph ) ; // Créé nouvelle surface m_graph = SDL_CreateRGBSurface( SDL_HWSURFACE, w, h, 32, 0, 0, 0, 0 ); // Variables double pas( 0.01 ) ; double x, y, angle ; // Affichage for ( std::vector::iterator it( m_chList.begin() ); it != m_chList.end(); it ++ ) { // Cercle qui localise la charge if ( it->sign ) circleRGBA( m_graph, Sint16( it->x * w ), Sint16( it->y * h ), it->value, 255, 255, 0, 255 ); else circleRGBA( m_graph, Sint16( it->x * w ), Sint16( it->y * h ), -it->value, 0, 128, 255, 255 ); // Ligne de champ qui partent d'une charge + if ( it->sign ) { for ( int s(0); s < it->nbOut; s ++ ) { angle = s * 2 * M_PI / it->nbOut ; x = it->x + it->value * std::cos( s ) / w ; y = it->y + it->value * std::sin( s ) / h ; drawLineFrom( x, y ); } } } } SDL_Surface* ElecField::getGraph() const { return m_graph ; } void ElecField::addCharge(int value, double x, double y, Uint16 nbOut) { m_chList.push_back( { value > 0, value, nbOut, x, y } ); } void ElecField::drawLineFrom( double x, double y ) { double pas( 0.001 ); double xp, yp ; int w( m_graph->w ); int h( m_graph->h ); Uint32 incr(0) ; while ( x > 0.0 && x < 1.0 && y > 0.0 && y < 1.0 && incr < WHILE_LIMIT ) { // Incrémentation incr ++ ; // Mémoriser l'endroit actuel xp = x ; yp = y ; // Calculer la composante de la force double fx( 0.0 ); double fy( 0.0 ); double r; for ( std::vector::iterator it( m_chList.begin() ); it != m_chList.end(); it ++ ) { // Calcul de la distance r = std::sqrt( ( it->x - x )*( it->x - x ) + ( it->y - y )*( it->y - y ) ); // Il faut sortir de la boucle si la ligne se termine sur une charge - if ( !it->sign && std::abs( r ) < -it->value / ( std::sqrt( h*h + w*w ) ) ) break ; // Calcul des forces fx += ( x - it->x ) * it->value / r / r / r ; fy += ( y - it->y ) * it->value / r / r / r ; } // Normaliser r = std::sqrt( fx * fx + fy * fy ); fx /= r ; fy /= r ; // Il faut sortir de la boucle si la force est trop faible if ( r < 0.5 ) break ; // Discrétiser fx *= pas ; fy *= pas ; // Bouger x += fx ; y += fy ; // Dessiner //lineRGBA( m_graph, xp * m_graph->w, yp * m_graph->h, x * m_graph->w, y * m_graph->h, 255, 255, 255, 255 ); pixelRGBA( m_graph, x * m_graph->w, y * m_graph->h, 255, 255, 128, 255 ); } }