Public Member Functions | Private Member Functions | Private Attributes | Static Private Attributes

Particle Class Reference

The Particle encapsulates both particle physical properties and visual properties needed for rendering during animation. More...

Collaboration diagram for Particle:
Collaboration graph
[legend]

List of all members.

Public Member Functions

 Particle (WorldOfParticles parent, double M, double Q, double X, double Y, double R, double T)
 Creates a new instance of Particle.
double getX ()
 Gets the x-component of particle position.
double getY ()
 Gets the y-component of particle position.
double getKineticEnergy ()
 Gets the kinetic energy for the particle.
void dump ()
 Dumps x/y-components of position, velocity and acceleration to System.out.
void resetVelocity ()
 Resets velocity and acceleration for particle to 0.
void makeCentripetalVelocity ()
 Makes velocity centripetal to acceleration.
void resetForce ()
 Resets total force to 0 ( so it could be summed up again).
void addForceFromParticle (Particle p)
 Calculates particular force that acts on this particle when interacting with some other remote particle p.
void applyForce ()
 Applies accumulated (summed up) total force on the particle.
void moveParticle (double dx, double dy)
 Moves the particle (overriding forces) and resets its velocity.
void forceBarrier (WorldOfParticles.Barrier barrier)
 Keeps the particle inside infinite potential barrier.
void paint (Graphics gr, boolean annotate)
 Renders the particle in Graphics context.
void kill ()
 Kills the particle by setting particle's life time to 0.
void interruptibleSleep (long millis)
 Thread.sleep wrapper.
void run ()
 Main thread that solves Newton's laws of motion, effectively moving the particle in the parent WorldOfParticles (unless the world is paused i.e.

Private Member Functions

void initBlurTrail (int size)
 Creates blur trail context (faded ghost images for particle)
void integrateNewtonLaws (double dT)
 Moves the particle using numerical integration of differential equations of the motion by Euler's method.
void drawGradCircle (Graphics2D g2d, float x, float y, float radius, Color color)
 Draws the circle with radial gradient from the center.
void createParticleImage ()
 Creates the image of the particle that will be animated.

Private Attributes

WorldOfParticles world
 Particle always belong to some world of particles.
double mass = 1
double charge = 1
double radius = 1
double xPos = 0
double yPos = 0
double vx = 0
double vy = 0
double vsq = 0
double ax = 0
double ay = 0
double asq = 0
double Fx = 0
double Fy = 0
double lifeTime = Double.POSITIVE_INFINITY
 Particle's life time.
Thread mainThread
 Each object (i.e.
BufferedImage image = null
 Image of the particle that is rendered during animation.
Color color = Color.BLUE
 Particle color.
int aliasedEdges = 10
 Depth (levels) of anti-aliased edges (anti-aliasing disabled if 0).
boolean showTrail = false
int trailSize = 0
int trailRatioC = 0
int trailRatio = 0
int[] trailX = null
int[] trailY = null
float[] trailFade = null

Static Private Attributes

static final double k_e = 5e6
static final double k_G = 1e-5
static final double k_x = 1e-4
static final double minRsq = 91
static final double maxVsq = 4e4

Detailed Description

The Particle encapsulates both particle physical properties and visual properties needed for rendering during animation.

Physical behavior of the particle is governed by gravitational and electrical forces conducted by Newton's law of motion in form of differential equations (applied to particle's mass, charge, position, velocity and acceleration) and solved (integrated) using numerical Euler's method. Each particle has separate thread integrating equations thus effectively "moving" particle.

Forces acting on the particle are set by particle's WorldOfParticle that overviews interactions between all particles and calculates summary forces for each single particles.

The resulting 'motion' of the particle is then rendered to WorldOfParticle's Graphics context. Particle image is generated once and kept in image internal object. Charged particles are either rendered in Red (positive) or Green (negative). Neutral particles are rendered in Blue.

Author:
Mikica B Kocic

Definition at line 37 of file Particle.java.


Constructor & Destructor Documentation

Particle.Particle ( WorldOfParticles  parent,
double  M,
double  Q,
double  X,
double  Y,
double  R,
double  T 
)

Creates a new instance of Particle.

Parameters:
parentthe world to which Particle belongs to
Mmass of the Particle
Qelectrical charge of the Particle
Xinitial position, x-component
Yinitial position, y-component
Rradius range (0 for random radius)
Tlife time in seconds

Definition at line 123 of file Particle.java.

References asq, ax, ay, charge, color, initBlurTrail(), lifeTime, mainThread, mass, radius, vsq, vx, vy, world, xPos, and yPos.

    {
        world    = parent;
        mass     = M;
        charge   = Q;
        lifeTime = T;
        
        /* Initial position
         */
        xPos = X;
        yPos = Y;

        /* Random initial velocity
         */
        vx   = -100 + 200 * Math.random ();
        vy   = -100 + 200 * Math.random ();
        vsq  = Math.pow( vx, 2 ) + Math.pow( vy, 2 );

        /* No initial acceleration
         */
        ax   = 0;
        ay   = 0;
        asq  = 0;

        /* If the radius is not specified (<=0) then randomize radius
         */
        radius = R > 0 ? R : 10.0 + ( 10.0 - R ) * Math.random ();
        
        /* Set color depending on charge: Blue (0), Green (+) Red (-)
         */
        if ( charge == 0 ) {
            color = new Color( 0, 0, 1f );
        } else if ( charge > 0 ) {
            color = new Color( (float)charge, 0, 0 );
        } else {
            color = new Color( 0, -(float)charge, 0 );
        }

        /* Setup ghost trail
         */
        initBlurTrail( 10 );
        
        /* Start moving (solving differential equations for) the particle...
         */
        mainThread = new Thread( this );
        mainThread.start ();
    }

Member Function Documentation

void Particle.addForceFromParticle ( Particle  p )

Calculates particular force that acts on this particle when interacting with some other remote particle p.

Parameters:
premote particle

Definition at line 273 of file Particle.java.

References charge, Fx, Fy, k_e, k_G, mass, minRsq, xPos, and yPos.

    {
        if ( p == this ) {
            return;
        }

        /* Rsq = squared distance R between particles
         */
        double Rsq = Math.pow( p.xPos - xPos, 2 ) 
                   + Math.pow( p.yPos - yPos, 2 );

        /* Quantum-mechanics allows distances between particles above some limit 
         * (like Pauli's Exclusion Principle and nuclear forces)
         * This suppresses that we have infinite interaction forces between particles.
         */
        if ( Rsq < minRsq ) {
            Rsq = minRsq;
        }

        /* Radius vector Cartesian coordinate components
         */
        double cos = ( p.xPos - xPos ) / Math.sqrt( Rsq );
        double sin = ( p.yPos - yPos ) / Math.sqrt( Rsq );
        
        /* Coulomb's force between electrical charges
         */
        double e_force = -k_e * charge * p.charge / Rsq;
        Fx += e_force * cos;
        Fy += e_force * sin;

        /* Gravitational force between particle masses
         */
        double g_force = k_G * mass * p.mass / Rsq;
        Fx += g_force * cos;
        Fy += g_force * sin;
    }
void Particle.applyForce (  )

Applies accumulated (summed up) total force on the particle.

Definition at line 313 of file Particle.java.

References asq, ax, ay, Fx, Fy, k_x, mass, maxVsq, vsq, vx, and vy.

    {
        ax = Fx / mass;
        ay = Fy / mass;
        
        /* Introduce additional drag-force for velocities > sqrt(maxVsq)
         * to slow-down very fast particles.
         */
        if ( vsq > maxVsq ) {
            ax += -k_x * vsq * vx / Math.sqrt( vsq );
            ay += -k_x * vsq * vy / Math.sqrt( vsq );
        }
        
        asq = Math.pow( ax, 2 ) + Math.pow( ay, 2 );
    }
void Particle.createParticleImage (  ) [private]

Creates the image of the particle that will be animated.

Definition at line 419 of file Particle.java.

References aliasedEdges, color, drawGradCircle(), WorldOfParticles.getGraphicsConfiguration(), image, radius, and world.

Referenced by paint().

    {
        GraphicsConfiguration gc = world.getGraphicsConfiguration ();
        if ( gc == null ) {
            return;
        }

        int diameter = (int)( radius * 2 );
        
        image = gc.createCompatibleImage( diameter, diameter, Transparency.TRANSLUCENT );

        Graphics2D gImg = image.createGraphics ();
        if ( aliasedEdges > 0 )
        {
            drawGradCircle(gImg, (int)radius, (int)radius, (int)radius, color ); 
        }
        else
        {
            gImg.setColor( color );
            gImg.fillOval( 0, 0, diameter, diameter );
        }

        gImg.dispose ();
    }
void Particle.drawGradCircle ( Graphics2D  g2d,
float  x,
float  y,
float  radius,
Color  color 
) [private]

Draws the circle with radial gradient from the center.

Definition at line 393 of file Particle.java.

Referenced by createParticleImage().

    {
        Point2D center = new Point2D.Float( x, y );
        
        float[] dist = { 0.0f, 1.0f };
        
        float[] c = { color.getRed()/255f, color.getGreen()/255f, color.getBlue()/255f };
        Color[] colors = {
                new Color( c[0] * 1.0f, c[1] * 1.0f, c[2] * 1.0f, 1.0f ), // base color
                new Color( c[0] * 0.8f, c[1] * 0.8f, c[2] * 0.8f, 0.0f )  // fade out
                };
        
        g2d.setPaint( 
                new RadialGradientPaint( 
                        center, radius, dist, colors, CycleMethod.NO_CYCLE
                        )
                );
        
        g2d.fill( new Ellipse2D.Float( x - radius, y - radius, 2*radius, 2*radius ) );
    }
void Particle.dump (  )

Dumps x/y-components of position, velocity and acceleration to System.out.

Definition at line 236 of file Particle.java.

References ax, ay, lifeTime, vx, vy, xPos, and yPos.

    {
        System.out.printf( "%8.1f %8.1f %8.1f %8.1f %8.1f %8.1f %8.1f\n", 
                           lifeTime, xPos, yPos, vx, vy, ax, ay );
    }
void Particle.forceBarrier ( WorldOfParticles.Barrier  barrier )

Keeps the particle inside infinite potential barrier.

Parameters:
barrierboundaries of infinite potential barrier given as array {x1,y1,x2,y2} of coordinates

Definition at line 347 of file Particle.java.

References vx, vy, xPos, and yPos.

Referenced by integrateNewtonLaws().

    {
        final double k = 0.5; // in-elastic collision coefficient 
        
        if ( xPos < barrier.xBeg ) {
            xPos = barrier.xBeg; 
            vx = -k * vx;
        } else if ( xPos > barrier.xEnd ) {
            xPos = barrier.xEnd; 
            vx = -k * vx ;
        }

        if ( yPos < barrier.yBeg ) {
            yPos = barrier.yBeg; 
            vy = -k * vy;
        } else if ( yPos > barrier.yEnd ) {
            yPos = barrier.yEnd; 
            vy = -k * vy;
        }
    }
double Particle.getKineticEnergy (  )

Gets the kinetic energy for the particle.

Returns:
the kinetic energy for the particle

Definition at line 191 of file Particle.java.

References mass, and vsq.

    {
        return mass * vsq / 2;
    }
double Particle.getX (  )

Gets the x-component of particle position.

Returns:
the x-component of particle position

Definition at line 179 of file Particle.java.

References xPos.

{ return xPos; }
double Particle.getY (  )

Gets the y-component of particle position.

Returns:
the y-component of particle position

Definition at line 185 of file Particle.java.

References yPos.

{ return yPos; }
void Particle.initBlurTrail ( int  size ) [private]

Creates blur trail context (faded ghost images for particle)

Parameters:
sizetrail depth (number of ghost images to show)

Definition at line 203 of file Particle.java.

References showTrail, trailFade, trailRatio, trailRatioC, trailSize, trailX, and trailY.

Referenced by Particle().

    {
        showTrail   = true;
        trailSize   = size;
        trailRatioC = 3;
        trailRatio  = 0;
        
        /* Create blur arrays with x,y positions and fading for ghost images
         */
        trailX    = new int  [ trailSize ];
        trailY    = new int  [ trailSize ];
        trailFade = new float[ trailSize ];
        
        float incrementalFactor = .2f / ( trailSize + 1 );
        
        for( int i = 0; i < trailSize; ++i ) 
        {
            /* Default values for positions -1 indicates 
             * not to render these until with real values
             */
            trailX[ i ] = -1;
            trailY[ i ] = -1;
            
            /* The ghost is more faded as it is further away from the particle
             */
            trailFade[i] = ( .2f - incrementalFactor ) - i * incrementalFactor;
        }
    }
void Particle.integrateNewtonLaws ( double  dT ) [private]

Moves the particle using numerical integration of differential equations of the motion by Euler's method.

Parameters:
dTintegration interval in seconds

Definition at line 374 of file Particle.java.

References ax, ay, forceBarrier(), WorldOfParticles.getBarrier(), vsq, vx, vy, world, xPos, and yPos.

Referenced by run().

    {
        synchronized( world )
        {
            xPos += vx * dT;
            yPos += vy * dT;

            vx   += ax * dT;
            vy   += ay * dT;

            vsq = Math.pow( vx, 2 ) + Math.pow( vy, 2 );
            
            forceBarrier( world.getBarrier () );
        }
    }
void Particle.interruptibleSleep ( long  millis )

Thread.sleep wrapper.

Definition at line 565 of file Particle.java.

References lifeTime.

Referenced by run().

    {
        synchronized( this )
        {
            try {
                Thread.sleep( 10 );
            }
            catch( InterruptedException ie ) {
                lifeTime = 0; // kill thread
            }
        }
    }
void Particle.kill (  )

Kills the particle by setting particle's life time to 0.

Particle is dead (moving thread exits) if its life time < 0.

Definition at line 554 of file Particle.java.

References lifeTime, and mainThread.

    {
        lifeTime = 0.0;
        if ( mainThread != null ) {
            mainThread.interrupt ();
        }
    }
void Particle.makeCentripetalVelocity (  )

Makes velocity centripetal to acceleration.

Definition at line 253 of file Particle.java.

References ax, ay, vx, and vy.

    {
        vx = -ay;
        vy = ax;
    }
void Particle.moveParticle ( double  dx,
double  dy 
)

Moves the particle (overriding forces) and resets its velocity.

Parameters:
dxdelta x-position
dydelta y-position

Definition at line 335 of file Particle.java.

References resetVelocity(), xPos, and yPos.

Referenced by JPWorld.keyPressed().

    {
        xPos += dx; yPos += dy;
        resetVelocity ();
    }
void Particle.paint ( Graphics  gr,
boolean  annotate 
)

Renders the particle in Graphics context.

Parameters:
grthe Graphics context in which particle is rendered
annotateindicator whether additional info about particle's acceleration is displayed or not

Definition at line 451 of file Particle.java.

References asq, ax, ay, charge, color, createParticleImage(), image, lifeTime, radius, showTrail, trailFade, trailRatio, trailRatioC, trailSize, trailX, trailY, xPos, and yPos.

    {
        if ( image == null ) {
            createParticleImage();
            if ( image == null ) {
                return;
            }
        }

        Graphics2D g = (Graphics2D)gr.create ();

        /* Convert (px,py) at the center of the particle to (x,y) as base of the image
         */
        int px = (int)xPos;
        int py = (int)yPos;
        int x = (int)( xPos - radius );
        int y = (int)( yPos - radius );

        /* Base fade for the particle is derived its life time (fades out at the end).
         */
        float baseFade = (float)( lifeTime < 0 ? 0 : lifeTime > 1 ? 1 : lifeTime );
        
        if ( showTrail ) {

            /* Draw previous locations of the particle as a trail of ghost images
             */
            for( int i = 0; i < trailSize; ++i ) {
                if( trailX[i] >= 0 ) {
                    /* Render each particle ghost with fading */
                    g.setComposite( 
                            AlphaComposite.SrcOver.derive( baseFade * trailFade[i] )
                            );
                    g.drawImage( image, trailX[i], trailY[i], null );
                }
            }

            --trailRatio;

            if ( trailRatio <= 0 ) {
                
                trailRatio = trailRatioC;

                /* Shift the ghost trail positions in array (from newest to eldest)
                 */
                for( int i = trailSize - 1; i > 0; --i ) {
                    trailX[ i ] = trailX[ i - 1 ];
                    trailY[ i ] = trailY[ i - 1 ];
                }
                trailX[ 0 ] = x;
                trailY[ 0 ] = y;
            }
        }

        g.setComposite( AlphaComposite.SrcOver.derive( baseFade ) );
        
        if ( annotate && asq > 0.0 )
        {
            /* Vector pointing in force direction with length proportional to 
             * the logarithm of acceleration (with small linear fix for dramatic purpose)
             */
            int dx = asq < 1e-9 ? 0 
                : (int)( 1e-3 * ax + 3 * ax * Math.log( 1 + asq ) / Math.sqrt( asq ) );
            int dy = asq < 1e-9 ? 0 
                : (int)( 1e-3 * ay + 3 * ay * Math.log( 1 + asq ) / Math.sqrt( asq ) );
            
            Color cText = new Color( color.getRGB () ).darker ();
            
            /* Draw acceleration vector
             */
            g.setColor( cText.darker () );
            g.drawLine( px, py, px + dx, py + dy );
            g.drawArc( px + dx - 4, py + dy - 4, 8, 8, 0, 360 );
            
            /* Show acceleration values
             */
            g.setColor( cText );
            Font f = new Font( Font.MONOSPACED, Font.PLAIN, 14 ); // TODO: static?
            g.setFont( f );
            g.drawString( String.format( "%+7.1f", ax ), px + dx - 4, py + dy - 4 - 14 );
            g.drawString( String.format( "%+7.1f", ay ), px + dx - 4, py + dy - 4 );
        }
        
        g.drawImage( image, x, y, null );
        
        if ( annotate && true )
        {
            g.setColor( Color.BLACK );
            int R = (int)( radius / 3 );
            if ( charge != 0 ) {
                g.drawLine( px - R, py, px + R, py );
            }
            if ( charge > 0 ) {
                g.drawLine( px, py - R, px, py + R );
            }
        }

        g.dispose ();
    }
void Particle.resetForce (  )

Resets total force to 0 ( so it could be summed up again).

Definition at line 262 of file Particle.java.

References Fx, and Fy.

    {
        Fx = 0; Fy = 0.0;
    }
void Particle.resetVelocity (  )

Resets velocity and acceleration for particle to 0.

Definition at line 245 of file Particle.java.

References vsq, vx, and vy.

Referenced by moveParticle().

    {
        vx = vy = vsq = 0;
    }
void Particle.run (  )

Main thread that solves Newton's laws of motion, effectively moving the particle in the parent WorldOfParticles (unless the world is paused i.e.

freezed). Thread also keeps particle's life time and after it expires, particle is removed from the belonging world.

Definition at line 585 of file Particle.java.

References WorldOfParticles.getTimeScale(), integrateNewtonLaws(), interruptibleSleep(), WorldOfParticles.isPaused(), lifeTime, WorldOfParticles.removeParticle(), and world.

    {
        final int sleepMillis = 5; // ~200 Hz
        
        long oldTime = System.nanoTime ();
            
        while( lifeTime >= 0 ) // particle is dead when its life time becomes lt. 0
        {
            interruptibleSleep( sleepMillis );
            long currentTime = System.nanoTime ();
            
            /* Calculates sleep time dT in seconds. dT is not necessarily the same as
             * the intentioned sleep time. It can be scaled further to speed up or 
             * slow-down particle's motion.
             */
            double dT = world.getTimeScale () * (double)( currentTime - oldTime ) / 1e9;

            if ( ! world.isPaused () ) {
                integrateNewtonLaws( dT );
            }

            lifeTime -= dT;
            oldTime = currentTime;
        }
        
        /* Cleans-up dead particle
         */
        world.removeParticle( this );
    }

Member Data Documentation

int Particle.aliasedEdges = 10 [private]

Depth (levels) of anti-aliased edges (anti-aliasing disabled if 0).

Definition at line 97 of file Particle.java.

Referenced by createParticleImage().

double Particle.asq = 0 [private]

Definition at line 66 of file Particle.java.

Referenced by applyForce(), paint(), and Particle().

double Particle.ax = 0 [private]
double Particle.ay = 0 [private]
double Particle.charge = 1 [private]

Definition at line 54 of file Particle.java.

Referenced by addForceFromParticle(), paint(), and Particle().

Color Particle.color = Color.BLUE [private]

Particle color.

Definition at line 92 of file Particle.java.

Referenced by createParticleImage(), paint(), and Particle().

double Particle.Fx = 0 [private]

Definition at line 67 of file Particle.java.

Referenced by addForceFromParticle(), applyForce(), and resetForce().

double Particle.Fy = 0 [private]

Definition at line 68 of file Particle.java.

Referenced by addForceFromParticle(), applyForce(), and resetForce().

BufferedImage Particle.image = null [private]

Image of the particle that is rendered during animation.

Definition at line 87 of file Particle.java.

Referenced by createParticleImage(), and paint().

final double Particle.k_e = 5e6 [static, private]

Definition at line 39 of file Particle.java.

Referenced by addForceFromParticle().

final double Particle.k_G = 1e-5 [static, private]

Definition at line 40 of file Particle.java.

Referenced by addForceFromParticle().

final double Particle.k_x = 1e-4 [static, private]

Definition at line 41 of file Particle.java.

Referenced by applyForce().

double Particle.lifeTime = Double.POSITIVE_INFINITY [private]

Particle's life time.

Must be positive number or positive infinity. Negative values indicates dead particle.

Definition at line 74 of file Particle.java.

Referenced by dump(), interruptibleSleep(), kill(), paint(), Particle(), and run().

Thread Particle.mainThread [private]

Each object (i.e.

particle) follows the Newton's laws of motion (differential equations) that are solved (integrated) in object's (particle's) main thread.

Definition at line 80 of file Particle.java.

Referenced by kill(), and Particle().

double Particle.mass = 1 [private]

Definition at line 53 of file Particle.java.

Referenced by addForceFromParticle(), applyForce(), getKineticEnergy(), and Particle().

final double Particle.maxVsq = 4e4 [static, private]

Definition at line 43 of file Particle.java.

Referenced by applyForce().

final double Particle.minRsq = 91 [static, private]

Definition at line 42 of file Particle.java.

Referenced by addForceFromParticle().

double Particle.radius = 1 [private]

Definition at line 55 of file Particle.java.

Referenced by createParticleImage(), paint(), and Particle().

boolean Particle.showTrail = false [private]

Definition at line 102 of file Particle.java.

Referenced by initBlurTrail(), and paint().

float [] Particle.trailFade = null [private]

Definition at line 108 of file Particle.java.

Referenced by initBlurTrail(), and paint().

int Particle.trailRatio = 0 [private]

Definition at line 105 of file Particle.java.

Referenced by initBlurTrail(), and paint().

int Particle.trailRatioC = 0 [private]

Definition at line 104 of file Particle.java.

Referenced by initBlurTrail(), and paint().

int Particle.trailSize = 0 [private]

Definition at line 103 of file Particle.java.

Referenced by initBlurTrail(), and paint().

int [] Particle.trailX = null [private]

Definition at line 106 of file Particle.java.

Referenced by initBlurTrail(), and paint().

int [] Particle.trailY = null [private]

Definition at line 107 of file Particle.java.

Referenced by initBlurTrail(), and paint().

double Particle.vsq = 0 [private]
double Particle.vx = 0 [private]
double Particle.vy = 0 [private]

Particle always belong to some world of particles.

This is our world.

Definition at line 48 of file Particle.java.

Referenced by createParticleImage(), integrateNewtonLaws(), Particle(), and run().

double Particle.xPos = 0 [private]
double Particle.yPos = 0 [private]

The documentation for this class was generated from the following file: