- Industrial design and construction

Newton's law of motion

Simulation of particles based on action and reaction

Simulation of particles according to the law of momentum P


m= mass
v= speed
P= m * v

 

Learn more about particle acceleration here: https://www.xtream.sk/zakony-vesmiru

 

If there are several particles of different sizes in space, their momentums will equalize. The heat in the fabric is equalized. Thus, larger particles will move slower and smaller particles faster.

The sample is constructed in such a way that large particles have the greatest speed at the beginning. However, very quickly after the collisions, you can see how the smaller particles accelerate from the larger ones and take some of their momentum. The speed of the particles is thus arranged according to their sizes. Thus, large particles fly slower on average than smaller particles. The number of particles is not as large as in reality, so there is also a considerable random factor, so sometimes it can happen that a particle flies outside the average of its size. However, the more particles you put into the simulation, the more stable the results would be.

Please refresh the page to better see the acceleration of small particles at the beginning.

 

In addition to the acceleration of particles, the attraction caused by the shielding of larger particles can also be observed in the simulations. It is not so noticeable, because there are few particles and it is only in 2 dimensions, so there is a higher probability of particles colliding than in 3D space, but you can still notice that larger particles bump into each other and try to be as close to each other as possible . Of course, the factor of chance sometimes caused them to move away, but it is more likely that the larger particles will come closer to each other. In fact, gravity is created by much smaller particles, which are much more numerous and have higher speeds, so there is not as much turbulence and the larger particles are more stable. A certain frequency of their touch then arises there. Because the more we push larger particles together, the stronger they will also repel each other. So everything is a matter of a certain frequency and force of impact. At the same time, the walls act as a shade, so flying particles often tend to hit the walls.

 

The simulation was programmed by Josh Bradley, edited by Ladislav Ides

https://joshbradley.me/object-collisions-with-canvas/

 

The simulation may be inaccurate and particles may speed up or slow down over time. This is due to the fact that everything is based on calculations that are carried out with perfect accuracy.

Gravity can be simulated in a similar way, but it is necessary to simulate many more particles to reduce the random impact factor of larger particles.

 

When observing the movement of particles, it looks like cellular activity. This suggests that with such a large number of combinations in infinite time, the emergence of cells and therefore life is inevitable.

 

HTML code for display:

<script type="text/javascript">sem vložíte zdrojový kód</script>
  <body onload="draw();">
  <canvas id="canvas" width="600" height="600"></canvas>
  </body>


 

Simulation source code:

//pohyb castic simulacia graviacie 600x600
class State {
  constructor(display, actors) {
    this.display = display;
    this.actors = actors;
  }

  update(time) {

    /**
     * provide an update ID to let actors update other actors only once
     * used with collision detection
     */
    const updateId = Math.floor(Math.random() * 1000000);
    const actors = this.actors.map(actor => {
      return actor.update(this, time, updateId);
    });
    return new State(this.display, actors);
  }
}


class Vector {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }

  add(vector) {
    return new Vector(this.x + vector.x, this.y + vector.y);
  }

  subtract(vector) {
    return new Vector(this.x - vector.x, this.y - vector.y);
  }

  multiply(scalar) {
    return new Vector(this.x * scalar, this.y * scalar);
  }

  dotProduct(vector) {
    return this.x * vector.x + this.y * vector.y;
  }

  get magnitude() {
    return Math.sqrt(this.x ** 2 + this.y ** 2);
  }

  get direction() {
    return Math.atan2(this.x, this.y);
  }
}

 //ctx = document.getElementById('canvas').getContext('2d');

class Canvas {
  constructor(parent = document.body, width = 10, height = 10) {
    this.canvas = document.createElement('canvas');
    this.canvas.width = width;
    this.canvas.height = height;
    parent.appendChild(this.canvas);
    this.ctx =document.getElementById('canvas').getContext('2d');
  }

  sync(state) {
    this.clearDisplay();
    this.drawActors(state.actors);
  }

  clearDisplay() {

    // opacity controls the trail effect set to 1 to remove
    this.ctx.fillStyle = 'rgba(255, 255, 255, .4)';
    this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
    this.ctx.strokeStyle = 'black';
    this.ctx.strokeRect(0, 0, this.canvas.width, this.canvas.height);
  }

  drawActors(actors) {
    for (let actor of actors) {
      if (actor.type === 'circle') {
        this.drawCircle(actor);
      }
    }
  }

  drawCircle(actor) {
    this.ctx.beginPath();
    this.ctx.arc(actor.position.x, actor.position.y, actor.radius, 0, Math.PI * 2);
    this.ctx.closePath();
    this.ctx.fillStyle = actor.color;
    this.ctx.fill();
  }
}

class Ball {
  constructor(config) {
    Object.assign(this,
      {
        id: Math.floor(Math.random() * 1000000),
        type: 'circle',
        position: new Vector(100, 100),
        velocity: new Vector(3, 3),
        radius: 25,
        color: 'blue',
        collisions: [],
      },
      config
    );
  }

  update(state, time, updateId) {

    /**
     * if slice occurs on too many elements, it starts to lag
     * collisions is an array to allow multiple collisions at once
     */
    if (this.collisions.length > 10) {
      this.collisions = this.collisions.slice(this.collisions.length - 3);
    }

    /**
     * this is the most stable solution to avoid overlap
     * but it is slightly inaccurate
     */
    for (let actor of state.actors) {
      if (this === actor || this.collisions.includes(actor.id + updateId)) {
        continue;
      }

      /**
       * check if actors collide in the next frame and update now if they do
       * innaccurate, but it is the easiest solution to the sticky collision bug
       */
      const distance = this.position.add(this.velocity).subtract(actor.position.add(actor.velocity)).magnitude;

      if (distance <= this.radius + actor.radius) {
        const v1 = collisionVector(this, actor);
        const v2 = collisionVector(actor, this);
        this.velocity = v1;
        actor.velocity = v2;
        this.collisions.push(actor.id + updateId);
        actor.collisions.push(this.id + updateId);
      }
    }

    // setting bounds on the canvas prevents balls from overlapping on update
    const upperLimit = new Vector(state.display.canvas.width - this.radius, state.display.canvas.height - this.radius);
    const lowerLimit = new Vector(0 + this.radius, 0 + this.radius);

    //check if hitting left or right of container
    if (this.position.x >= upperLimit.x || this.position.x <= lowerLimit.x) {
     this.velocity = new Vector(-this.velocity.x, this.velocity.y);
    }

    //if (this.position.x >= upperLimit.x) {//moje
    // this.position.x=lowerLimit.x+1;
    //}

    //if (this.position.x <= lowerLimit.x) {//moje
    // this.position.x=upperLimit.x;
    //}

    // check if hitting top or bottom of container
    if (this.position.y >= upperLimit.y || this.position.y <= lowerLimit.y) {
      this.velocity = new Vector(this.velocity.x, -this.velocity.y);
    }


    //if (this.position.y >= upperLimit.y) {//moje
    // this.position.y=lowerLimit.y+1;
    //}

    //if (this.position.y <= lowerLimit.y) {//moje
    // this.position.y=upperLimit.y;
    //}



 

const newX = Math.max(Math.min(this.position.x + this.velocity.x, upperLimit.x), lowerLimit.x);
const newY = Math.max(Math.min(this.position.y + this.velocity.y, upperLimit.y), lowerLimit.y);

return new Ball({
...this,
position: new Vector(newX, newY),
});
}

get area() {
return Math.PI * this.radius ** 2;
}

get sphereArea() {
return 4 * Math.PI * this.radius ** 2;
}
}

// see elastic collision: https://en.wikipedia.org/wiki/Elastic_collision
const collisionVector = (particle1, particle2) => {
return particle1.velocity
.subtract(particle1.position
.subtract(particle2.position)
.multiply(particle1.velocity
.subtract(particle2.velocity)
.dotProduct(particle1.position.subtract(particle2.position))
/ particle1.position.subtract(particle2.position).magnitude ** 2/1.002 // lomeno 1.002 je spomalenie na vyrovnanie chyby výpočtu
)

// add mass to the system
.multiply((2 * particle2.sphereArea) / (particle1.sphereArea + particle2.sphereArea))
);
};

const isMovingTowards = (particle1, particle2) => {
return particle2.position.subtract(particle1.position).dotProduct(particle1.velocity) > 0;
};

const runAnimation = animation => {
let lastTime = null;
const frame = time => {
if (lastTime !== null) {
const timeStep = Math.min(100, time - lastTime) / 1000;

// return false from animation to stop
if (animation(timeStep) === false) {
return;
}
}
lastTime = time;
requestAnimationFrame(frame);
};
requestAnimationFrame(frame);
};

const random = (max = 9, min = 0) => {
return Math.floor(Math.random() * (max - min + 1) + min);
};

const colors = ['red', 'green', 'blue', 'purple', 'orange'];

const collidingBalls = ({ width = 600, height = 600, parent = document.body, count = 10 } = {}) => {
const display = new Canvas(parent, width, height);
const balls = [];
for (let i = 0; i < 10; i++) {
balls.push(new Ball({
radius: 7,
color: colors[1],
position: new Vector(random(width - 10, 10), random(height - 10, 10)),
velocity: new Vector(random(3, -3), random(3, -3)),
}));
}

//velke
for (let i = 0; i < 2; i++) {
balls.push(new Ball({
radius: 30,
color: colors[2],
position: new Vector(random(width - 10, 10), random(height - 10, 10)),
velocity: new Vector(5, 0),
}));
}

for (let i = 0; i < 2; i++) {
balls.push(new Ball({
radius: 30,
color: colors[2],
position: new Vector(random(width - 10, 10), random(height - 10, 10)),
velocity: new Vector(0,5),
}));
}
for (let i = 0; i < 2; i++) {
balls.push(new Ball({
radius: 30,
color: colors[2],
position: new Vector(random(width - 10, 10), random(height - 10, 10)),
velocity: new Vector(0, -5),
}));
}
for (let i = 0; i < 2; i++) {
balls.push(new Ball({
radius: 30,
color: colors[2],
position: new Vector(random(width - 10, 10), random(height - 10, 10)),
velocity: new Vector(-5, 0),
}));
}
//kioniec velke
for (let i = 0; i < 500; i++) {
balls.push(new Ball({
radius: 3,
color: colors[0],
position: new Vector(random(width - 10, 10), random(height - 10, 10)),
velocity: new Vector(random(3, -3), random(3, -3)),
}));
}

let state = new State(display, balls);
runAnimation(time => {
state = state.update(time);
display.sync(state);
});
};

function draw() {
collidingBalls();
}


    


All rights reserved. Copying text and images is only allowed with XTREAM a.s. and link to the source www.xtream.sk