ElecField.cpp 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. #include "ElecField.h"
  2. #define WHILE_LIMIT 10000
  3. struct Charge
  4. {
  5. bool sign ; // true si positive
  6. Sint16 value ;
  7. Uint16 nbOut ;
  8. double x ; // entre 0.0 et 1.0
  9. double y ;
  10. };
  11. ElecField::ElecField() : m_graph( 0x0 )
  12. {
  13. //ctor
  14. }
  15. ElecField::~ElecField()
  16. {
  17. if ( !m_graph ) SDL_FreeSurface( m_graph ) ;
  18. }
  19. void ElecField::renderGraph( int w, int h )
  20. {
  21. // Détruit vieille surface si existante
  22. if ( !m_graph ) SDL_FreeSurface( m_graph ) ;
  23. // Créé nouvelle surface
  24. m_graph = SDL_CreateRGBSurface( SDL_HWSURFACE, w, h, 32, 0, 0, 0, 0 );
  25. // Variables
  26. double pas( 0.01 ) ;
  27. double x, y, angle ;
  28. // Affichage
  29. for ( std::vector<Charge>::iterator it( m_chList.begin() ); it != m_chList.end(); it ++ )
  30. {
  31. // Cercle qui localise la charge
  32. if ( it->sign )
  33. circleRGBA( m_graph, Sint16( it->x * w ), Sint16( it->y * h ), it->value, 255, 255, 0, 255 );
  34. else
  35. circleRGBA( m_graph, Sint16( it->x * w ), Sint16( it->y * h ), -it->value, 0, 128, 255, 255 );
  36. // Ligne de champ qui partent d'une charge +
  37. if ( it->sign )
  38. {
  39. for ( int s(0); s < it->nbOut; s ++ )
  40. {
  41. angle = s * 2 * M_PI / it->nbOut ;
  42. x = it->x + it->value * std::cos( s ) / w ;
  43. y = it->y + it->value * std::sin( s ) / h ;
  44. drawLineFrom( x, y );
  45. }
  46. }
  47. }
  48. }
  49. SDL_Surface* ElecField::getGraph() const
  50. {
  51. return m_graph ;
  52. }
  53. void ElecField::addCharge(int value, double x, double y, Uint16 nbOut)
  54. {
  55. m_chList.push_back( { value > 0, value, nbOut, x, y } );
  56. }
  57. void ElecField::drawLineFrom( double x, double y )
  58. {
  59. double pas( 0.001 );
  60. double xp, yp ;
  61. int w( m_graph->w );
  62. int h( m_graph->h );
  63. Uint32 incr(0) ;
  64. while ( x > 0.0 && x < 1.0 && y > 0.0 && y < 1.0 && incr < WHILE_LIMIT )
  65. {
  66. // Incrémentation
  67. incr ++ ;
  68. // Mémoriser l'endroit actuel
  69. xp = x ;
  70. yp = y ;
  71. // Calculer la composante de la force
  72. double fx( 0.0 );
  73. double fy( 0.0 );
  74. double r;
  75. for ( std::vector<Charge>::iterator it( m_chList.begin() ); it != m_chList.end(); it ++ )
  76. {
  77. // Calcul de la distance
  78. r = std::sqrt( ( it->x - x )*( it->x - x ) + ( it->y - y )*( it->y - y ) );
  79. // Il faut sortir de la boucle si la ligne se termine sur une charge -
  80. if ( !it->sign && std::abs( r ) < -it->value / ( std::sqrt( h*h + w*w ) ) )
  81. break ;
  82. // Calcul des forces
  83. fx += ( x - it->x ) * it->value / r / r / r ;
  84. fy += ( y - it->y ) * it->value / r / r / r ;
  85. }
  86. // Normaliser
  87. r = std::sqrt( fx * fx + fy * fy );
  88. fx /= r ;
  89. fy /= r ;
  90. // Il faut sortir de la boucle si la force est trop faible
  91. if ( r < 0.5 )
  92. break ;
  93. // Discrétiser
  94. fx *= pas ;
  95. fy *= pas ;
  96. // Bouger
  97. x += fx ;
  98. y += fy ;
  99. // Dessiner
  100. //lineRGBA( m_graph, xp * m_graph->w, yp * m_graph->h, x * m_graph->w, y * m_graph->h, 255, 255, 255, 255 );
  101. pixelRGBA( m_graph, x * m_graph->w, y * m_graph->h, 255, 255, 128, 255 );
  102. }
  103. }