Physical simulation about Balance

Hello, I am trying to develop a physical simulation of Balance for educational purpose.
How can I make the simulation more realistic by controlling the blocks/Mass of the squares and not just the density?

There is something that bothers me that I did not know how to solve, why when I put two squares of equal density that are not balanced.

this is my code:

 const stage = frame.stage;
            let stageW = frame.width;
            let stageH = frame.height;
        

            const rect = [];

            const units = [
                { unit: "1 mg", density: 0.001, color: "red" },       // ميليغرام
                { unit: "1 cg", density: 0.01, color: "orange" },     // سنتغرام
                { unit: "1 dg", density: 0.1, color: "grey" },      // ديسغرام
                { unit: "1 g", density: 1.0, color: "green" },        // غرام
                { unit: "1 dag", density: 10.0, color: "blue" },      // ديكاغرام
                { unit: "1 hg", density: 100.0, color: "black" },    // هيكتوغرام
                { unit: "1 kg", density: 1000.0, color: "brown" },     // كيلوغرام
                { unit: "1 mg", density: 0.001, color: "red" },       // ميليغرام
                { unit: "1 cg", density: 0.01, color: "orange" },     // سنتغرام
                { unit: "1 dg", density: 0.1, color: "grey" },      // ديسغرام
                { unit: "1 g", density: 1.0, color: "green" },        // غرام
                { unit: "1 dag", density: 10.0, color: "blue" },      // ديكاغرام
                { unit: "1 hg", density: 100.0, color: "black" },    // هيكتوغرام
                { unit : "1 kg", density: 1000.0, color: "brown" }     // كيلوغرام
          
                ];

            const physics = new Physics({
                gravity: 9,
            });

  loop(units, (unit, index)=> {
                const minSize = 10; 
                const maxSize = 70; 
                const minDensity = Math.min(...units.map(unit => unit.density)); 
                const maxDensity = Math.max(...units.map(unit => unit.density)); 

                const size = minSize + (maxSize - minSize) * ((Math.log10(unit.density) - Math.log(minDensity)) / (Math.log10(maxDensity) - Math.log10(minDensity)));


                const square = new Rectangle(size, size, unit.color)
                    .centerReg()
                    .pos(100 + index * 100, 300) 
                    .addPhysics(true, 0, "rectangle", unit.density, .1)
                    .addTo();

                    rect.push(square); 
                square.addTo(); 


                const label = new Label({
                    text: unit.unit,
                    size: size/2,
                    color: "white",
                    align: "center",
                    valign: "center"
                }).centerReg(square); 

               // label.addTo(); 
            });
         

             const beam = new Rectangle(600, 40, "brown").centerReg().pos(400,650)
            .addPhysics(true, 0, "rectangle", 0.8, 0.8, 0.8, 1); // 
            
            
            const pivot = new Circle(20, "black").centerReg().loc(beam.x,beam.y) //loc(beam.x, beam.y+20)
            .addPhysics(false); 
            
            physics.join({obj1:beam, obj2:pivot, type: "revolute" });

   physics.debug();    
            physics.drag([units]);
            physics.noDrag([beam,pivot]);

Try setting the blocks right at the end so you can tell they are spaced along the same.

image

Even so, it does seem a little hit and miss but these are balancing. You could perhaps play with the angular setting (I see you have) of the bar to see if that adds or reduces a friction effect on the rotation. Also, you might want to increase friction on the bar and or rectangles so the rectangles slide less down the bar.

In terms of the actual physics calculations, these are being done by Box2D which has been around for a long time and probably pretty bug free - and as good as it can get for simulations. I have seen an object fall directly onto a very thin rectangle pointing up and having it balance on it ;-). Sometimes it is too exact :wink:

Also use the scaleTo() to scale the labels to the size of the boxes - I know, you are just testing... but it is an easy thing ;-).

And welcome to the ZIM Forum!

Also, if you are wanting the debug to scale with scaling the window you can use

// or frame - or whatever your reference
F.on("resize", ()=>{physics.updateDebug()})

oh, thanks DR.Abstract , i found a way to get the real Mass of rect but i dont know in which units or system, i have set the density to all of rect to 1,
but i failed

    rect.forEach(element => {
                console.log(element.body.GetMass())
            }) 

Check out Box2D for things like units. Also, others may have tried to do something similar in Box2D and you might find info with a search. Use Box2D in behind the scene and just make it easier to use but otherwise, are not changing how it does its calculations.

1 Like