Images are overlapping/crossing each other when I am Calling an image on every moving/bouncing ball

Hi All, I went through the Bouncing ball overlap issue and used xdir = -abs(xdir) on each collision. However, the moment I load images on these balls(which in this case are molecules) , they start overlapping again. Please help me with this.

var Engine = Matter.Engine;
var Render = Matter.Render;
var World = Matter.World;
var Bodies = Matter.Bodies;
var Composite = Matter.Composite;
var Composites = Matter.Composites;
var Mouse = Matter.Mouse;
var MouseConstraint = Matter.MouseConstraint;
var engine;
var world;
var bodies;

var canvas;

//body global variables 
var bodynumber = [];
var bodyPositionX = [];
var bodyPositionY = [];
var input;

var mouseConstraint;
var img;
var systemtemp;

//#IMAGE
function preload(){
img = loadImage('Water.png');
}


function setup() {
  cnv = createCanvas(600, 600);
  cnv.position(width/2,0);

  //create an engine
  engine = Engine.create();
  world = engine.world;
  world.gravity.y = 0;

  var gravityX = world.gravity.x;
var gravityY = world.gravity.y;


  //add rectangles/floors
  var params = {
    isStatic: true
    }
     var ground = Bodies.rectangle(width / 2, height, width, 30, params);
     var wall1 = Bodies.rectangle(0, height / 2, 30, height, params);
     var wall2 = Bodies.rectangle(width, height / 2, 30, height, params);
     var top = Bodies.rectangle(width / 2, 0, width, 30, params);
     World.add(world, [ground,wall1,wall2,top]);

  //add circle stack
  function makeCircle(x, y) {
      var params = {
      restitution: 1.0,
      friction: 0,
      offset : 0,
      mass : 18
      }
    return Bodies.circle(x, y,22, params);
    this.x = x;
    this.y = y;

  }

  // x, y, columns, rows, column gap, row gap
  var stack = Composites.stack(200,30, 5, 4, 0, 0, makeCircle);
  bodies = stack.bodies;

  for (var i = 0; i < bodies.length; i++){
  bodynumber[i] = stack.bodies[i];
  bodyPositionX[i] = stack.bodies[i].position.x;
  bodyPositionY[i] = stack.bodies[i].position.y;
  console.log(bodynumber[i]);
  }

//adding heat slider
 Heatslider = createSlider(-5,5,0);
 Heatslider.position(30,300);

 var val = Heatslider.value();
 console.log(val);

 //value for heatslider
 input = createInput(val);
 input.position(40,500);
 //adding reset button
 ResetButton = createButton("Reset");
 ResetButton.position(50,260);
 //ResetButton.mousePressed(resetSketch);

  // add all of the bodies to the world
  World.add(world, stack);

  //run the engine
 Engine.run(engine);
}



//DRAW
function draw() {
  background(51);
  drawcircle();
  CalculateKE();

  for (var i =0;i< bodies.length;i++){ 
   for (var j =0;j< bodies.length;j++){
   if(i != j){
   var test = intersects(bodynumber[i],bodynumber[j]);
  }
  }
  }
//setgravity();

//try block
/*for ( var i = 0; i < bodies.length ; i++)
{
for( var j = 0; j < bodies.length ; j++){
var pvector = createVector((bodynumber[i].position.x),(bodynumber[i].position.y));
var p2vector = createVector((bodynumber[j].position.x),(bodynumber[j].position.y));
var diffvector = p5.Vector.sub(pvector,p2vector);
diffvector.normalize();
diffvector.mult(0.001);
//line(diffvector);
Matter.Body.applyForce(bodynumber[j],p2vector,diffvector);
//bodynumber[0].force = 2*diffvector;
console.log(pvector,p2vector,diffvector,bodynumber[0]);

}
}  */

  //text
  input.html(Heatslider.value());
  text(Heatslider.value(),40,500);

  //draw floor
  stroke(0);
  strokeWeight(1);
  fill(255,50);
  rect((width/2) -300, height -15, width, 15);


  //move bubbles 
 for (var i = 0; i < bodies.length; i++) {
 bodynumber[i].position.x = bodynumber[i].position.x  + 0.2*random(-1,1);
 bodynumber[i].position.y = bodynumber[i].position.y  + 0.2*random(-1,1);
                                         }

  //Gravity Adjustments
function setgravity(){
if (systemtemp >= 100)  { // Gas case
                        world.gravity.y = 0;
                        world.gravity.x = 0;
                         } 
else if (systemtemp <= 0) { // Solid case
                        world.gravity.y = (100 - systemtemp) / (100 - 0);
                        world.gravity.x = world.gravity.y * 0.02;
                          } 
else                    { // Liquid case
                        world.gravity.y = (100 - systemtemp) / (100 - 0);
                        world.gravity.x = world.gravity.y * 0.6;
                         }

console.log("gravity",systemtemp);
}


 //check circle collision
function intersects(first,other){
    var d = dist(first.position.x, first.position.y ,other.position.x, other.position.y);
    if( d < 44) {
    first.velocity.x = -abs(first.velocity.x);
    first.velocity.y = -abs(first.velocity.y);
    other.velocity.x = -abs(other.velocity.x);
    other.velocity.y = -abs(other.velocity.y);
    var test = 1;
    console.log(test);
    }
    }
}

//draw function inside DRAW
 function drawcircle(){
  stroke(255);
  strokeWeight(1);
  fill(255, 50);
  for (var i = 0; i < bodies.length; i++) {
    var circle = bodies[i];
    var pos = circle.position;
    var r = 22;
    var angle = circle.angle;
    push();
    translate(pos.x, pos.y);
    rotate(angle);
    image(img,0,0);
    //ellipse(0, 0, 20, 20);
    //line(0, 0, r, 0);
    pop();  
    }

//Attractive forces between all molecules
function attractiveForce(first,other){
var distance = dist(first.position.x, first.position.y ,other.position.x, other.position.y);
var dxx = first.position.x - other.position.x;
var dyy = first.position.y - other.position.y;
var nx = dxx/distance;
var ny = dyy/distance;
}


//instantaneous push to each molecule
function move(){
 for (var i = 0; i < bodies.length; i++) {
 bodynumber[i].position.x = bodynumber[i].position.x  + random(-1,1);
 bodynumber[i].position.y = bodynumber[i].position.y  + random(-1,1);
 }
}

//increasing offset value on each draw() call
 for (var i = 0; i < bodies.length; i++) {
 bodynumber[i].offset = bodynumber[i].offset + 5;
 } 

}
Tagged:

Answers

  • First thing first...

    Please format your code. Edit your post (gear on top right side of any of your posts), select your code and hit ctrl+o. Leave an empty line above and below your block of code. Details here: https://forum.processing.org/two/discussion/15473/readme-how-to-format-code-and-text

    Kf

  • @kfrajer : Sorry about that. I have formatted the code. Please look into the issue.

  • Answer ✓

    Notice CalculateKE(); is missing. However I managed...

    Two points:
    Add this to setup: imageMode(CENTER);
    https://p5js.org/reference/#/p5/imageMode

    Second, when drawing your image, follow this next:

        image(img, 0, 0,40,40);
        //ellipse(0, 0, 40, 40);
    

    Notice you should use the alternative version of image when drawing your objects. Also notice I double your size used in ellipse, as you initial example clearly shows that your boundary checking was using the diameter and not the radius of your object.

    Kf

  • edited November 2017

    Hi @kfrajer, Thank you for your immediate response. I am trying to create water molecules that change their state from gas to solid to liquid according to the values of the slider ( liquid at val = 0, gas at val > 0, solid at val <0). For this I have applied continuous forces to keep the molecules together that change value acc to stste. While changing the radius, has now solved the issue of molecules overlap to a great extent, they still overlap after sometime of start of simulation. To solve this I tried adding a condition that applies force only when the molecules are not touching.However, this is not working correctly. Please look into the issue. Thanks!

    var Engine = Matter.Engine;
    var Render = Matter.Render;
    var World = Matter.World;
    var Bodies = Matter.Bodies;
    var Composite = Matter.Composite;
    var Composites = Matter.Composites;
    var Mouse = Matter.Mouse;
    var MouseConstraint = Matter.MouseConstraint;
    var engine;
    var world;
    var bodies;
    var gcoll = 0;
    var canvas;
    
    //body global variables 
    var bodynumber = [];
    var bodyPositionX = [];
    var bodyPositionY = [];
    var input;
    var mouseConstraint;
    var img;
    var systemtemp;
    var val;
    
    function setup() {
       frameRate(10);
      cnv = createCanvas(600, 600);
      cnv.position(width/2,0);
    
      //create an engine
      engine = Engine.create();
      world = engine.world;
      world.gravity.y = 0.2;
    
      var gravityX = world.gravity.x;
    var gravityY = world.gravity.y;
    
    
      //add rectangles/floors
      var params1 = {
        isStatic: true,
        restitution : 1.0
        }
    
      var params = {
        isStatic: true
        }
         var ground = Bodies.rectangle(width / 2, height, width, 30, params1);
         var wall1 = Bodies.rectangle(0, height / 2, 30, height, params);
         var wall2 = Bodies.rectangle(width, height / 2, 30, height, params);
         var top = Bodies.rectangle(width / 2, 0, width, 30, params);
         World.add(world, [ground,wall1,wall2,top]);
    
      //add circle stack
      function makeCircle(x, y) {
          var params = {
          restitution: 1.0,
          friction: 0,
          offset : 0,
          mass : 18
          }
        return Bodies.circle(x, y, 20, params);
        this.x = x;
        this.y = y;
    
      }
    
      // x, y, columns, rows, column gap, row gap
      var stack = Composites.stack(200,30, 5, 4, 0, 0, makeCircle);
      bodies = stack.bodies;
    
      for (var i = 0; i < bodies.length; i++){
      bodynumber[i] = stack.bodies[i];
      bodyPositionX[i] = stack.bodies[i].position.x;
      bodyPositionY[i] = stack.bodies[i].position.y;
      console.log(bodynumber[i]);
      }
    
    
    
     //adding heat slider
     Heatslider = createSlider(-5,5,0);
     Heatslider.position(30,300);
    
    
    
    
     //value for heatslider
     input = createInput(val);
     input.position(40,500);
    
    
     //adding reset button
     ResetButton = createButton("Reset");
     ResetButton.position(50,260);
     //ResetButton.mousePressed(resetSketch);
    
     // add all of the bodies to the world
      World.add(world, stack);
    
     //run the engine
     //Engine.run(engine);
    }
    
    
    
    //DRAW
    function draw() {
      Engine.update(engine);
      background(51);
      //setgravity();
      //drawcircle();
    
      CalculateKE();
      //setgravity();
      for (var i =0;i< bodies.length;i++){ 
       for (var j =0;j< bodies.length;j++){
       if(i != j){
       var test = intersects(bodynumber[i],bodynumber[j]);
      }
      }
      }
    
      //heat slider value
     val = Heatslider.value();
     console.log(val);
    
     //heatslider changes with value
     if(val > 0)
     {
     world.gravity.y = 0;
     }
     else if (val == 0)
     {
     world.gravity.y = 0.2;
     applyforce(0);
     }
     else if (val < 0)
     {
     world.gravity.y = 0.2;
     applyforce(0.0008);
     }
    
    
    //try block
    function applyforce(mag) {
    for ( var i = 0; i < bodies.length ; i++)
    {
    for( var j = 0; j < bodies.length ; j++){
    var pvector = createVector((bodynumber[i].position.x),(bodynumber[i].position.y));
    var p2vector = createVector((bodynumber[j].position.x),(bodynumber[j].position.y));
    var distforce = dist(bodynumber[i].position.x, bodynumber[i].position.y ,bodynumber[j].position.x, bodynumber[j].position.y);
    var diffvector = p5.Vector.sub(pvector,p2vector);
    diffvector.normalize();
    diffvector.mult(mag);
    //line(diffvector);
    if(distforce > 40){
    Matter.Body.applyForce(bodynumber[j],p2vector,diffvector);
    }
    console.log(pvector,p2vector,diffvector,bodynumber[0]);
    
    }
    }  
    }
    
    //collision with ground collideRectRect(x, y, width, height, x2, y2, width2, height2 )
     for ( i = 0; i < bodies.length ; i++)
     {
     collides(bodynumber[i]);
     }
    
     function collides(circlebody){
     if ((circlebody.position.y + 30) >= (height - 15)){
     gcoll += 1;
     if(val == 0){
     circlebody.velocity.y = -abs(circlebody.velocity.x);
     }
     else if(val > 0){
     circlebody.velocity.y = -2 * abs(circlebody.velocity.x);
     }
     else if (val <0){
     circlebody.velocity.y = -0.20 * abs(circlebody.velocity.x);
     }
     console.log("groundcollide",gcoll);
     }
     }
    
    if (gcoll == 0) {
    applyforce(0.0008);
    var mag = 0.0008;
    }
    else
    {
    applyforce(0); 
    mag = 0;
     } 
    
     console.log("magnitude",mag);
    
      //text
      input.html(Heatslider.value());
      text(Heatslider.value(),40,500);
    
      //draw floor
      stroke(0);
      strokeWeight(1);
      fill(255,50);
      rect((width/2) -300, height -15, width, 15);
    
    
    
    
      //Gravity Adjustments
    /*function setgravity(){
    if (systemtemp >= 100)  { // Gas case
                            world.gravity.y = 0;
                            world.gravity.x = 0;
                             } 
    else if (systemtemp <= 0) { // Solid case
                            world.gravity.y = (100 - systemtemp) / (100 - 0);
                            world.gravity.x = world.gravity.y * 0.02;
                              } 
    else                    { // Liquid case
                            world.gravity.y = (100 - systemtemp) / (100 - 0);
                            world.gravity.x = world.gravity.y * 0.6;
                             }
    
    console.log("gravity",systemtemp,world.gravity.y,world.gravity.x);
    }*/
    
    
    //check circle collision
    function intersects(first,other){
        var d = dist(first.position.x, first.position.y ,other.position.x, other.position.y);
        if( d <= 30) {
        first.velocity.x = -abs(first.velocity.x);
        first.velocity.y = -abs(first.velocity.y);
        other.velocity.x = -abs(other.velocity.x);
        other.velocity.y = -abs(other.velocity.y);
        var test = 1;
        console.log(test);
        }
        }
    
    //move bubbles to give vibrations
    for (var i = 0; i < bodies.length; i++) {
    bodynumber[i].position.x = bodynumber[i].position.x  + 0.50*random(-1,1);
    bodynumber[i].position.y = bodynumber[i].position.y  + 0.50*random(-1,1);
                                             }
    
    
       //move bubbles to give angular vibrations
    for (var i = 0; i < bodies.length; i++) {
    bodynumber[i].angularVelocity = bodynumber[i].angularVelocity  + 0.50*random(-1,1);
                                             }                                      
    
    
    
    
     drawcircle();    
    }
    
     //draw function inside DRAW
     function drawcircle(){
      stroke(255);
      strokeWeight(2);
      fill(255, 50);
      for (var i = 0; i < bodies.length; i++) {
        var circle = bodies[i];
        var pos = circle.position;
        var r = 20;
        var angle = circle.angle;
        push();
        translate(pos.x, pos.y);
        rotate(angle);
        //image(img,0,0);
        ellipse(0, 0, 30, 30);
        //line(0, 0, r, 0);
        pop();  
        }
    
    //Attractive forces between all molecules
    function attractiveForce(first,other){
    var distance = dist(first.position.x, first.position.y ,other.position.x, other.position.y);
    var dxx = first.position.x - other.position.x;
    var dyy = first.position.y - other.position.y;
    var nx = dxx/distance;
    var ny = dyy/distance;
    }
    
    
    //instantaneous push to each molecule
    function move(){
     for (var i = 0; i < bodies.length; i++) {
     bodynumber[i].position.x = bodynumber[i].position.x  + random(-1,1);
     bodynumber[i].position.y = bodynumber[i].position.y  + random(-1,1);
     }
    }
    
    //increasing offset value on each draw() call
     for (var i = 0; i < bodies.length; i++) {
     bodynumber[i].offset = bodynumber[i].offset + 5;
     } 
    }
    
  • I have yet not loaded the images and working just with circles.

    Also, please find below code for CalculateKE.

    function CalculateKE() {
     var Totalvel = [];
     var Ke = 0;
     var TotalKE =0;
     for(i = 0 ; i< 20 ; i++)
     { 
     Totalvel[i] = Math.sqrt((bodynumber[i].velocity.x)*(bodynumber[i].velocity.x) + (bodynumber[i].velocity.y)*(bodynumber[i].velocity.y));
     Ke =  0.5*18*2*Totalvel[i]*Totalvel[i];
     TotalKE += Ke;
    
     }
     var averageKE = TotalKE/20;
    systemtemp = ((averageKE*2*100)/(1.5*1.38*6.022)) - 19 ;
    //console.log("averageKE",systemtemp,averageKE);
    
    }
    
  • Answer ✓

    Lin 133 in your code:

    if(distforce > 40){
      Matter.Body.applyForce(bodynumber[j],p2vector,diffvector);
    }
    

    I am afraid this is a very simplistic approach to handle your interactions. I am not an expert on this, but I can imagine that having a multiple bouncing system will get you in trouble as interactions are additive. It is after you loop through all the interactions in a single step (aka frame) that you will get the final position of each bouncing molecule. This final position could drive you into overlapping states. However, your code seems to fail even when the interaction is between two objects. You need to include some code that works not only on an "edge" interaction but on an actual overlapping interaction. There are two previous related java posts. With your js experience, I am confident you can manage reviewing these:

    https://forum.processing.org/two/discussion/24966/bouncing-balls-collision#latest
    https://forum.processing.org/two/discussion/comment/89968/#Comment_89968

    I am not familiar with the matter engine design. I am curious to know how they handle interactions and collisions. They have a Detector function which seems to do this. If you haven't done so, you should consider checking their provided examples.

    One last thing: What is the purpose of your code?

    In a more real model, for solid/liquid/gas interactions, your slider value should be affecting your molecule's kinetic energy and not the attractive forces. In reality, the molecular interaction is based on a potential model, where the forces are based on distance. This is just a thought for your virtual experiment... implementing it could be an overkill if you are aiming to do a simple demonstration. There are other aspects of your code that needs to be considered before implementing a potential model.

    Kf

  • @kfrajer :That's right, since Matter.js already takes care of velocity , imparting a random velocity externally is making the molecules overlap. Now I am applying instantaneous force instead of velocity(segment mentioned below).Thank you so much for this.

    for (var i = 0; i < bodies.length; i++) {
    bodynumber[i].position.x = bodynumber[i].position.x  + 0.50*random(-1,1);
    bodynumber[i].position.y = bodynumber[i].position.y  + 0.50*random(-1,1);
                                             }``
    

    I am trying to build a model for solid/liquid/gas interactions as a part of a chemistry simulation. Could you please provide me an example of such a model that affects a molecule's kinetic energy. I thought I was doing that by increasing the velocity by 0.5*random every sec. However, that was clearly wrong.

  • Answer ✓

    I am trying to build a model for solid/liquid/gas interactions as a part of a chemistry simulation.

    I do not have a proper model unfortunately. I mean, ideally you will have a bunch of molecules constrain in a space and you will adjust their velocities based on temperature (Assume no Boltzman distribution but more like single speed dictated by temperature in an initial state). Now you construct a model that describes attraction forces. For instance, hydrogen bonding. Last, you need another model for molecular "shell" repulsion. This last one is optional but could help in the cases when additive forces on a single molecule drive it to overlap other molecules.

    I found this relevant to your task: http://www.atomsinmotion.com/book/chapter5/md

    However, if you go to a design of this type, it could get complicated in no time. For example, as you saw in your previous attempt, even working with matter.js you ran into one of the first problems of simulations.... the anti-overlap algorithm not working properly. This by itself is challenging in programming because you are working with discrete steps (instead of continuous motion) which drives the model to prohibited states.

    I am not familiar with the matter engine as to be able to tell how it handles collision. Running the examples show it does a good job. However, I remove all the "external" forces (manual forces added by you) in our code to see if the engine could handle the bouncing effect. Unfortunately, I could still see overlapping. I didn't go any deeper as it will require to dig into the documentation.

    Your simulation should be doable but it is important first to clarify certain points. First point is conservation of energy. This is challenging in a way. This next example seems to apply elastic interactions during interactions: https://processing.org/examples/circlecollision.html However, it is a bit harder in a multiple collision system, specifically when multiple objects are interacting in a single step. Thinking about your end result, there is a challenge when there is condensation as when particles sticking together. Then you have dumbbells at a first level and these objects need to be treated as single units. Maybe matter.js will be able to handle this objects if you use the constrain.js module. I have to scratch my head because you will need to consider rotation of these objects. As you see, it gets a bit complicated. You also need to consider a force model to brake the dumbbell system, in case you increase the temperature of the universe or when another atom/molecule interacts/collides with them.

    Nevertheless conservation of energy is a point to consider. For example, check this example: https://processing.org/examples/bouncybubbles.html Here I don't think they use conservation of energy. When a collision happens, the simulate the interaction as in a spring model. They introduce a friction coefficient to try to reduce the energy of the system over time. If you set the gravity and friction to zero, you can see a case where the all system slows down and come to a stop. In this case you will need to introduce energy (heat) artificially to conserve the energy of the universe or implement proper elastic interactions. Slowing down is one of the effects in this model. You can experience the opposite, where particles gain energy without control. A damping model would be require to keep the system under control. In the example above, they use friction on the walls, an artificial means to control the simulation and to avoid the erratic behavior.

    Another simulation approach could be using a condensation/evaporation model. A blob that can absorb a particle and grow in volume. Or it can shrink by evaporation, peeling off particles, as the vapor coming from a coffee cup.

    At the end, I have a feeling you don't want to get into the complicated stuff. It is more about a demonstration. Is that correct?

    Kf

  • @kfrajer : Whoaa!! This covers all the points that I found in one of the existing Java codes. Unfortunately, the code is incomplete for me to debug or even run it.

    Yes, I am working on conserving the energy by not letting the velocity increase after a point. (would I have to find that point by trial and error? :( ) Matter.js takes care of everything else - Momentum, velocity , angular momentum etc.

    This is a chemistry simulation tool that would be used by the chemistry department of my University so I would have to work through the complicated stuff too.

    How can I attach the jar file here?

    Thank you again!

  • How can I attach the .jar file here?

    Don't you have its .java source? Anyways, consider using GitHub for posting complex code + data: *-:)
    https://GitHub.com/github

  • Hi @kfrajer , @GoToLoop PFA the .jar file at https://github.com/asaha23/Conn-ChemP5-Matter

    I have the .java code. Unfortunately it is incomplete.

  • Yes, I am working on conserving the energy by not letting the velocity increase after a point.

    If you code proper momentum conservation equations for particle interaction, then I would think conservation of energy would follow within the limits of computer precision and discrete calculations. You will notice these last two becomes a problem in programming. Any small error is mostly accumulative. Since you are running many frames per second, then errors will build over time. In particle interaction, you find not many people program this type of code mainly because there is a major effort to do so. People come up with simpler models. However, simpler models creates artifacts and unwanted results. If I were you, I will read more upon the matter.js documentation. I have a feeling they have implemented most of this stuff for you already. For the simulation you are trying to accomplish, you might need to check under the hood of this library. You need to understand how they are handling all the interactions internally and find the proper way to add forces without breaking the internal calculations.

    I would have to work through the complicated stuff too

    What complicated stuff are you considering in implementing?

    I have the .java code. Unfortunately it is incomplete.

    What do you mean it is incomplete?

    Kf

  • yes, the molecules are now getting attracted and repelling according to the heat slider value. However , I could not get the exact values for system temperature. For example, even at liquid state my system temp is showing to be around 250-300.

    By complicated stuff I was just referring to your earlier reply. Currently that is getting the correct values of temperature and kinetic energy.

    The java code is incomplete in the sense that I can't run it or even understand it because of the missing functions. The application was developed long back and we do not have the final source code.

Sign In or Register to comment.