123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134 |
- #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<Charge>::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<Charge>::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 );
- }
- }
|