Rhino C++ API  7.21
Classes | Public Member Functions | Static Public Member Functions | List of all members
ON_ParticleSystem Class Reference

#include <opennurbs_plus_particle.h>

Classes

class  ON_Force
 
class  ON_IntegrateContext
 
class  ON_Particle
 
class  ON_ParticleIterator
 
class  ON_ParticleState
 

Public Member Functions

 ON_ParticleSystem ()
 
bool AccumulateForces ()
 
class ON_ParticleSystem::ON_ParticleAddFixedParticle (double mass, ON_3dPoint initial_position)
 
class ON_ParticleSystem::ON_ForceAddHooksSpringForce (class ON_ParticleSystem::ON_Particle *particle1, class ON_ParticleSystem::ON_Particle *particle2, double rest_length, double spring_constant, double damping_constant)
 
class ON_ParticleSystem::ON_ForceAddInverseDistanceSquaredForce (class ON_ParticleSystem::ON_Particle *particle1, class ON_ParticleSystem::ON_Particle *particle2, double c, double minimum_distance)
 
class ON_ParticleSystem::ON_ForceAddNaryForce (bool(*force_function)(ON__UINT_PTR, class ON_ParticleSystem::ON_Particle **), ON__UINT_PTR context, unsigned int particle_count, class ON_Particle **particles)
 
class ON_ParticleSystem::ON_ParticleAddParticle (double mass, ON_3dPoint initial_position)
 
class ON_ParticleSystem::ON_ParticleAddParticle (double mass, ON_3dPoint initial_position, ON_3dVector initial_velocity)
 
class ON_ParticleSystem::ON_ParticleAddParticle (double mass, ON_3dPoint initial_position, ON_3dVector initial_velocity, ON_3dVector initial_acceleration)
 
class ON_ParticleSystem::ON_ForceAddUnaryForce (bool(*force_function)(ON__UINT_PTR, class ON_ParticleSystem::ON_Particle *), ON__UINT_PTR context)
 
ON_BoundingBox BoundingBox () const
 
double CurrentTime () const
 
double GlobalDragForceCoefficient (int i) const
 
ON_3dVector GlobalGravityForce () const
 
bool IncrementTime (bool(*integrate_func)(class ON_ParticleSystem::ON_IntegrateContext &), ON__UINT_PTR integrate_context, double delta_time)
 
bool IncrementTimeEuler (double delta_time)
 
bool IncrementTimeSemiImplicitEuler (bool(*integrate_func)(class ON_ParticleSystem::ON_IntegrateContext &), ON__UINT_PTR integrate_context, double delta_time)
 
bool IncrementTimeVelocityVeret (bool(*integrate_func)(class ON_ParticleSystem::ON_IntegrateContext &), ON__UINT_PTR integrate_context, double delta_time)
 
bool IncrementTimeVerlet (bool(*integrate_func)(class ON_ParticleSystem::ON_IntegrateContext &), ON__UINT_PTR integrate_context, double delta_time)
 
const class ON_ParticleSystem::ON_ParticleMaximumIncrementalChange () const
 
double PreviousTime () const
 
void SetGlobalDragForce (double drag_coefficient1, double drag_coefficient2, double drag_coefficient3)
 
void SetGlobalGravityForce (ON_3dVector G)
 
bool SetStartTime (double start_time)
 

Static Public Member Functions

static bool IntegrateEuler (class ON_ParticleSystem::ON_IntegrateContext &context)
 
static bool IntegrateSemiImplicitEuler (class ON_ParticleSystem::ON_IntegrateContext &context)
 
static bool IntegrateVelocityVerlet1 (class ON_ParticleSystem::ON_IntegrateContext &context)
 
static bool IntegrateVerlet (class ON_ParticleSystem::ON_IntegrateContext &context)
 

Constructor & Destructor Documentation

◆ ON_ParticleSystem()

ON_ParticleSystem::ON_ParticleSystem ( )

Member Function Documentation

◆ AccumulateForces()

bool ON_ParticleSystem::AccumulateForces ( )

◆ AddFixedParticle()

class ON_ParticleSystem::ON_Particle* ON_ParticleSystem::AddFixedParticle ( double  mass,
ON_3dPoint  initial_position 
)

◆ AddHooksSpringForce()

class ON_ParticleSystem::ON_Force* ON_ParticleSystem::AddHooksSpringForce ( class ON_ParticleSystem::ON_Particle particle1,
class ON_ParticleSystem::ON_Particle particle2,
double  rest_length,
double  spring_constant,
double  damping_constant 
)

Description: Adds a Hook's law spring force bewtween particles that is proportional to (distance - rest_length). Parameters: particle1 - [in] particle2 - [in] rest_length - [in] rest length of the spring. spring_constant - [in] Spring force magnitude = spring_constant*(distance - rest_length). When spring_constant > 0 and distance > rest_length, the force attracts. damping_constant - [in] Damping force magnitude = damping_constant*|(delta velocity) o D|, where D is a unit vector points from one particle to the other. When damping_constant > 0 and the particles are moving towards each other, the damping force repels. When damping_constant > 0 and the particles are moving away from each other, the damping force attracts.

◆ AddInverseDistanceSquaredForce()

class ON_ParticleSystem::ON_Force* ON_ParticleSystem::AddInverseDistanceSquaredForce ( class ON_ParticleSystem::ON_Particle particle1,
class ON_ParticleSystem::ON_Particle particle2,
double  c,
double  minimum_distance 
)

Description: Adds binary force bewtween particles that is proportional to 1/(distance squared). Parameters: particle1 - [in] particle2 - [in] c - [in] force = c/d^2 c > 0 for attractive forces c < 0 for repulsive forces minimum_distance - [in] If the distance between the particles is < minimum_distance, then the force evaluator fails. Example: Gravity: double g = 6.672e-11; ///< N m^2/kg^2 double c = g*mass1*mass2; double min_distance = (radius1+radius2); AddInverseDistanceSquaredForce(p1,p2,c,min_distance); Coulumb's Force double k = 8.9875e9; ///< N m^2/C^2 double c = -k*charge1*charge2; double min_distance = (radius1+radius2); AddInverseDistanceSquaredForce(p1,p2,c,min_distance);

◆ AddNaryForce()

class ON_ParticleSystem::ON_Force* ON_ParticleSystem::AddNaryForce ( bool(*)(ON__UINT_PTR, class ON_ParticleSystem::ON_Particle **)  force_function,
ON__UINT_PTR  context,
unsigned int  particle_count,
class ON_Particle **  particles 
)

Description: A N-ary force acts on a fixed set of particles.

Parameters: force_function - [in] A function that calculates the force on the particles listed in the particles[] array parameter. If force_function() returns false, the solver will stop.

context - [in] First parameter passed to force_function.
If the information in your context consists of up to 4 doubles, then you may use the ON_Force.m_context member as shown in the example.

particle_count - [in] Number of particles in particles[] array.

particles[] - [in] List of particles this force acts on.

Example: / Hook's law spring / This example if for illustration purposes. / In practice it is more efficient to call ON_ParticleSystem::AddHooksSpringForce().

      struct HooksSpringForceContext
      {
        double m_rest_length;
        double m_spring_constant;
        double m_damping_constant;
      };

      static bool HooksSpringForceFunction(
        ON__UINT_PTR context,
        class ON_ParticleSystem::ON_Particle** particles
        )
      {
        const ON_3dVector dx = particles[1]->m_position - particles[0]->m_position;
        const double length = dx.Length();
        if ( length > 0.0 )
        {
          const ON_3dVector dv = particles[1]->m_velocity - particles[0]->m_velocity;
          const struct HooksSpringForceContext* spring_context = (const struct HooksSpringForceContext*)context;
          double f = spring_context->m_spring_constant*(1.0 - spring_context->m_rest_length/length)
                    + spring_context->m_damping_constant*((dv.x*dx.x + dv.y*dx.y + dv.z*dx.z)/(length*length));
          ON_3dVector F = f*dx;
          particles[0]->m_force += F;
          particles[1]->m_force -= F;
        }
        return true;
      }

      class ON_ParticleSystem::ON_Particle* particle1 = ...;
      class ON_ParticleSystem::ON_Particle* particle2 = ...;          double rest_length = ...;
      double spring_constant = ...;
      double damping_constant  = ...;
      ON_ParticleSystem::ON_Particle* particles[2] = {particle1,particle2};
      ON_Force* F = AddNaryForce(HooksSpringForceFunction,0,2,particles);
      if ( 0 != F )
      {
        F->m_context.m_ptr = (ON__UINT_PTR)(&F->m_context.m_x[0]);
        struct HooksSpringForceContext* spring_context = (struct HooksSpringForceContext* )F->m_context.m_ptr;
        spring_context->m_rest_length = rest_length;
        spring_context->m_spring_constant = spring_constant;
        spring_context->m_damping_constant = damping_constant;
      }

Remarks: To add the common damped spring force that is calculated using Hook's law, it is easier to call AddHooksSpringForce().

◆ AddParticle() [1/3]

class ON_ParticleSystem::ON_Particle* ON_ParticleSystem::AddParticle ( double  mass,
ON_3dPoint  initial_position 
)

Description: Add a particle to the system. Parameters: mass - [in] initial_position - [in] initial_velocity - [in] You may pass zero if you are using an integrator that does not need this value. initial_acceleration - [in] You may pass zero if you are using an integrator that does not need this value. Remarks: The constructors that omit initial_velocity or initiali_acceleration assume those values are zero

◆ AddParticle() [2/3]

class ON_ParticleSystem::ON_Particle* ON_ParticleSystem::AddParticle ( double  mass,
ON_3dPoint  initial_position,
ON_3dVector  initial_velocity 
)

◆ AddParticle() [3/3]

class ON_ParticleSystem::ON_Particle* ON_ParticleSystem::AddParticle ( double  mass,
ON_3dPoint  initial_position,
ON_3dVector  initial_velocity,
ON_3dVector  initial_acceleration 
)

◆ AddUnaryForce()

class ON_ParticleSystem::ON_Force* ON_ParticleSystem::AddUnaryForce ( bool(*)(ON__UINT_PTR, class ON_ParticleSystem::ON_Particle *)  force_function,
ON__UINT_PTR  context 
)

Description: A unary force acts on every particle in the system.

Parameters: context - [in] First parameter passed to force_function.

force_function - [in] A function that calculates the force on the particle. If force_function() returns false, the solver will stop.

Example: If you had 8, or perhaps 9, particles representing the planets in our solar system, you were comfortable neglecting the effects the planets' mass have on the sun's position and you chose a coordinate system with the sun at the origin, then you could add a solar gravity force doing something like the following.

bool GetSolarGravity( 
  void*, ///< no context required
  const class ON_ParticleSystem::ON_Particle* planet, 
  ON_3dVector* SolarGravityForce
  )
{

/ masses in kilograms and distances in meters const double solar_mass = 1.9891e30; ///< kilograms const double g = 6.67384e-11; ///< meters^3/(kilogram seconds^2) ON_3dVector V = ON_3dPoint::Origin - planet->m_position; double r = V.Length();
if ( !(r > 6.955e8) ) { / Planet crashed into the sun! / The sun's radius is 6.955e8 meters. This calculation / ignores planets melting as they get too close to the sun. return false; } SolarGravityForce = (g*planet->m_mass*solar_mass/(r*r*r))*V; ///< r^3 because input V is not unitized return true; }

.... AddUnaryForce(0,GetSolarGravity);

Remarks: To add a global "gravity", it is more efficent to use SetGlobalGravityForce(). To add a global "drag" force, it is more efficient to use SetGlobalDragForce().

◆ BoundingBox()

ON_BoundingBox ON_ParticleSystem::BoundingBox ( ) const

◆ CurrentTime()

double ON_ParticleSystem::CurrentTime ( ) const

Returns: Current particle system time.

◆ GlobalDragForceCoefficient()

double ON_ParticleSystem::GlobalDragForceCoefficient ( int  i) const

◆ GlobalGravityForce()

ON_3dVector ON_ParticleSystem::GlobalGravityForce ( ) const

◆ IncrementTime()

bool ON_ParticleSystem::IncrementTime ( bool(*)(class ON_ParticleSystem::ON_IntegrateContext &)  integrate_func,
ON__UINT_PTR  integrate_context,
double  delta_time 
)

Description: Increment the current state of the particle system using a custom integration algorithm. Parameters: integrate_func - [in] An integration function.
You may use one of the canned methods listed below or provide your own. ON_ParticleSystem::IntegrateEuler() ON_ParticleSystem::IntegrateSemiImplicitEuler() ...

integrate_context - [in] value passed as context.m_integration_context. delta_time - [in] value passed as contextm_delta_time.

◆ IncrementTimeEuler()

bool ON_ParticleSystem::IncrementTimeEuler ( double  delta_time)

Description: Increment the current state of the particle system using the Euler integration algorithm. Parameters: delta_time - [in] Remarks: Calls IncrementTime with ON_ParticleSystem::IntegrateEuler as the integration function.

◆ IncrementTimeSemiImplicitEuler()

bool ON_ParticleSystem::IncrementTimeSemiImplicitEuler ( bool(*)(class ON_ParticleSystem::ON_IntegrateContext &)  integrate_func,
ON__UINT_PTR  integrate_context,
double  delta_time 
)

Description: Increment the current state of the particle system using the semi-implicity Euler integration algorithm. Parameters: delta_time - [in] Remarks: Calls IncrementTime with ON_ParticleSystem::IntegrateSemiImplicitEuler as the integration function.

◆ IncrementTimeVelocityVeret()

bool ON_ParticleSystem::IncrementTimeVelocityVeret ( bool(*)(class ON_ParticleSystem::ON_IntegrateContext &)  integrate_func,
ON__UINT_PTR  integrate_context,
double  delta_time 
)

Description: Increment the current state of the particle system using the velocity Verlet integration algorithm. Parameters: delta_time - [in] Remarks: Calls IncrementTime with ON_ParticleSystem::IntegrateVerlet as the integration function. Note that the Verlet algorithm does not calculate velocity values.

◆ IncrementTimeVerlet()

bool ON_ParticleSystem::IncrementTimeVerlet ( bool(*)(class ON_ParticleSystem::ON_IntegrateContext &)  integrate_func,
ON__UINT_PTR  integrate_context,
double  delta_time 
)

Description: Increment the current state of the particle system using the Verlet integration algorithm. Parameters: delta_time - [in] Remarks: Calls IncrementTime with ON_ParticleSystem::IntegrateVerlet as the integration function. Note that the Verlet algorithm does not calculate velocity values.

◆ IntegrateEuler()

static bool ON_ParticleSystem::IntegrateEuler ( class ON_ParticleSystem::ON_IntegrateContext context)
static

Description: Updates context.m_state.m_position and context.m_state.m_velocity using Euler integration.

Parameters: context - [in / out] The returned position and velocity are incremented using the following calculation. x1 = current position v1 = current velocity a1 = (current accumulated force)/(current mass) / incremented position and velocity x = x1 + v1*dt + 0.5*a1*dt*dt; v = v1 + a1*dt;

Remarks: This is the best choice in the rare case when all forces are independent of time. The canonical example when being when the only force is the force of gravity and no collisions occur. Note that forces whose formulae involve position or velocity are almost never indepent of time. In particular, if your system has drag, damping or spring forces, then this is probably the worst choice for an integrator.

◆ IntegrateSemiImplicitEuler()

static bool ON_ParticleSystem::IntegrateSemiImplicitEuler ( class ON_ParticleSystem::ON_IntegrateContext context)
static

Description: Updates context.m_state.m_position and context.m_state.m_velocity using Semi-implicit Euler integration.

Parameters: context - [in / out] The returned position and velocity are incremented using the following calculation. x1 = current position v1 = current velocity a1 = (current accumulated force)/(current mass) / incremented position and velocity v = v1 + a1*dt; x = x1 + v*dt + 0.5*a1*dt*dt;

◆ IntegrateVelocityVerlet1()

static bool ON_ParticleSystem::IntegrateVelocityVerlet1 ( class ON_ParticleSystem::ON_IntegrateContext context)
static

Description: Updates context.m_state.m_position and context.m_state.m_velocity using Stormer-Verlet integration.

Parameters: context - [in / out] The returned position is incremented using the following calculation. x1 = current position v1 = current velocity a1 = (current accumulated force)/(current mass) / incremented position v = v1 + 0.5* a1*dt; x = x1 + v*dt; Remarks: The velocity Verlet algorithm uses IntegrateVelocityVerlet1 as the first stemBecause the calculation requires a valid previous state, the initial iteration must be performed by another integrator. If context.m_particle->m_previous_state.m_time is ON_UNSET_VALUE, then IntegrateEuler is called.

◆ IntegrateVerlet()

static bool ON_ParticleSystem::IntegrateVerlet ( class ON_ParticleSystem::ON_IntegrateContext context)
static

Description: Updates context.m_state.m_position using Verlet integration.

Parameters: context - [in / out] The returned position is incremented using the following calculation. x0 = previous position x1 = current position a1 = (current accumulated force)/(current mass) / incremented position x = 2*x1 - x0 + a1*dt*dt; Remarks:

  • The Verlet algorithm cannot be used when the force accumulation step depends on velocities. If you have damped springs or forces like global drag, you must use some other integration algorithm.
  • Because the calculation requires a valid previous state, the initial iteration must be performed by another integrator. If context.m_particle->m_previous_state.m_time is ON_UNSET_VALUE, then ON_ParticleSystem::IntegrateEuler is called to get the starting values.

◆ MaximumIncrementalChange()

const class ON_ParticleSystem::ON_Particle* ON_ParticleSystem::MaximumIncrementalChange ( ) const

Returns: A pointer to the particle that moved the farthest during the most recent call to IncrementTime(). This information is useful for adjusting time increments.

◆ PreviousTime()

double ON_ParticleSystem::PreviousTime ( ) const

Returns: Particle system time at the previous iteration. ON_UNSET_VALUE is returned if time has never been incremented.

◆ SetGlobalDragForce()

void ON_ParticleSystem::SetGlobalDragForce ( double  drag_coefficient1,
double  drag_coefficient2,
double  drag_coefficient3 
)

Description: Applies a cubic drag force of -(drag_coefficient1 + drag_coefficient2*|v| + drag_coefficient3*|v|^2)*v, where "v" is the particle's velocity. Parameters: drag_coefficient1 - [in] drag_coefficient2 - [in] drag_coefficient3 - [in]

◆ SetGlobalGravityForce()

void ON_ParticleSystem::SetGlobalGravityForce ( ON_3dVector  G)

Description: Applies a force of ON_Particle.m_mass*G to every particle. Parameters: G - [in] Vector acceleration of gravity.

◆ SetStartTime()

bool ON_ParticleSystem::SetStartTime ( double  start_time)

Description: Sets the starting time. Parameters: start_time - [in] Remarks: The default starting time is zero. Once time has been incremented, the starting time cannot be set.