布朗运动模拟无法正确模拟粒子碰撞

时间:2016-03-23 16:55:43

标签: javascript physics collision

我正在尝试创建一个用于试验布朗运动的模拟。这个想法是使每个粒子(点)随机移动并相互碰撞,同时保留总能量。那,我确实成功了。

现在有问题的部分是使这些点状粒子与大圆碰撞并正确编程碰撞。不同之处在于我使粒子在相互碰撞后朝向完全随机的角度移动,但是当它们与圆圈碰撞时,它们之前的路径和速度以及圆圈的路径和速度决定了结果。所以我试图做的是转换到一个连接到圆心的坐标系,计算每个粒子的碰撞点,它们在上一步进入圆圈,然后计算它们到达的角度。现在,粒子的动量被分解为两个分量:切向分量保持不变,而径向分量根据碰撞定律而变化。这也会影响圆的运动。计算完所有碰撞后,我们返回原始参考系统,并绘制所有对象。

代码可以在下面找到,它似乎被打破了。我想在用角度计算时我错了,因为有些粒子可以在一点到达圆圈,然后退出"通过它的另一面。我只是在跟踪这一切时失去了轨道。我是一个完整的编程新手,所以......嗯......温柔,拜托。 :)另一个奇怪的事情是,圆圈趋向于向早期开始移动的方向移动,这不是它应该做的。

给出粒子的质量,用它的半径计算圆的质量。

您可以在此网站上找到模拟:

http://sixy.uw.hu/brown

尚未完成,但启动按钮工作正常。 :)

我要问的代码部分在这里:(我可以给你整个代码吗?)

function animateParticles() {
        if ($('N').value != particleCount || $('S').value != circle.R) {
           reset();
        }

        switch (activeGraph) {
                case '#graph':
                    chartOptions.title.text = 'Távolság';
                    chartOptions.axisY.title = 'd [px]';
                    break;

        if (Date.now() > lastAnim + 22) {
            context.clearRect(0, 0, canvas.width, canvas.height);

            // Particles step and collide
            for (var i in particle) {
                // Particle steps
                {
                    particle[i].x += particle[i].vx;
                    particle[i].y += particle[i].vy;
                }

                // If not in the circle
                if ((circle.x - particle[i].x) * (circle.x - particle[i].x) + (circle.y - particle[i].y) * (circle.y - particle[i].y) > circle.R * circle.R) {
                    // Collides with some of the rest of the particles
                    for (var j = 1; j <= $('N').value; j += Math.ceil(particleCount / (Math.random() * 50 + 50))) {
                        // If that's not in the circle as well
                        if ((circle.x - particle[j].x) * (circle.x - particle[j].x) + (circle.y - particle[j].y) * (circle.y - particle[j].y) > circle.R * circle.R) {
                            // If not himself
                            if (j != i) {
                                if (particle[i].coll == 0) {
                                    // Collide
                                    if (Math.pow((particle[i].x - particle[j].x), 2) + Math.pow((particle[i].y - particle[j].y), 2) <= 4) {
                                        var tkpx = (particle[i].vx + particle[j].vx) / 2;
                                        var tkpy = (particle[i].vy + particle[j].vy) / 2;
                                        var fi = Math.random() * 2 * Math.PI;
                                        var index;
                                        var ix = particle[i].vx;
                                        var iy = particle[i].vy;

                                        particle[i].vx = Math.sqrt(Math.pow((ix - tkpx), 2) + Math.pow((iy - tkpy), 2)) * Math.cos(fi) + tkpx;
                                        particle[i].vy = Math.sqrt(Math.pow((ix - tkpx), 2) + Math.pow((iy - tkpy), 2)) * Math.sin(fi) + tkpy;
                                        particle[j].vx = -Math.sqrt(Math.pow((ix - tkpx), 2) + Math.pow((iy - tkpy), 2)) * Math.cos(fi) + tkpx;
                                        particle[j].vy = -Math.sqrt(Math.pow((ix - tkpx), 2) + Math.pow((iy - tkpy), 2)) * Math.sin(fi) + tkpy;
                                    }
                                }
                            }
                            if (particle[i].coll >= 1) {
                                particle[i].coll -= 1;
                            }
                        }
                    }
                }

                // Collision with the walls
                {
                    if (particle[i].x >= canvas.width) {
                        var temp;
                        temp = particle[i].x - canvas.width;
                        particle[i].x = canvas.width - temp;
                        particle[i].vx *= -1

                    }
                    if (particle[i].x <= 0) {
                        var temp;
                        temp = -particle[i].x;
                        particle[i].x = temp;
                        particle[i].vx *= -1;
                    }
                    if (particle[i].y >= canvas.height) {
                        var temp;
                        temp = particle[i].y - canvas.height;
                        particle[i].y = canvas.height - temp;
                        particle[i].vy *= -1;
                    }
                    if (particle[i].y <= 0) {
                        var temp;
                        temp = -particle[i].y;
                        particle[i].y = temp;
                        particle[i].vy *= -1;
                    }
                }
            }
            //console.log(circle);
            // Circle steps and collides with particles
            var cu = 0;
            var cv = 0;
            for (var i in particle) {
                if ((circle.x - particle[i].x) * (circle.x - particle[i].x) + (circle.y - particle[i].y) * (circle.y - particle[i].y) < circle.R * circle.R) {
                    var pu;
                    var pv;
                    var px;
                    var py;
                    var px0;
                    var py0;
                    var t;
                    var t2;
                    var Tx;
                    var Ty;
                    var fi;
                    var p;
                    var q;
                    var cuu;
                    var cvv;
                    px = particle[i].x - circle.x;
                    py = particle[i].y - circle.y;
                    pu = particle[i].vx - circle.vx;
                    pv = particle[i].vy - circle.vy;
                    px0 = px - particle[i].vx;
                    py0 = py - particle[i].vy;
                    // Calculating the meeting point of the collision
                    t = (-(px0 * pu + py0 * pv) - Math.sqrt(circle.R * circle.R * (pu * pu + pv * pv) - Math.pow(px0 * pv - py0 * pu, 2))) / (pu * pu + pv * pv);
                    t2 = ((px - px0) * (px - px0) + (py - py0) * (py - py0)) / Math.sqrt(pu * pu + pv * pv) - t;
                    Tx = px0 + t * pu;
                    Ty = py0 + t * pv;
                    //console.log("TX: ", Tx);
                    //console.log("TY: ", Ty);
                    // Calculating the angle
                    {
                        if (Tx > 0 && Ty >= 0) {
                            fi = 2 * Math.PI - Math.atan(Ty / Tx);
                        }
                        else if (Tx < 0 && Ty >= 0) {
                            fi = Math.PI - Math.atan(Ty / Tx);
                        }
                        else if (Tx < 0 && Ty < 0) {
                            fi = Math.PI / 2 + Math.atan(Ty / Tx);
                        }
                        else if (Tx > 0 && Ty < 0) {
                            fi = -Math.atan(Ty / Tx);
                        }
                        else if (Tx = 0 && Ty >= 0) {
                            fi = 3 / 2 * Math.PI;
                        }
                        else if (Tx = 0 && Ty < 0) {
                            fi = Math.PI / 2;
                        }
                    }
                    //console.log("FI:", fi);
                    p = pu * Math.cos(fi) + pv * Math.sin(fi);
                    q = -pu * Math.sin(fi) + pv * Math.cos(fi);
                    cuu = 2 * q / (circle.M + 1);
                    cvv = 0;
                    q *= (1 - circle.M) / (1 + circle.M);
                    cu += cuu * Math.cos(-fi) + cvv * Math.sin(-fi);
                    cv += -cuu * Math.sin(-fi) + cvv * Math.cos(-fi);
                    //console.log("CU: ", cu);
                    //console.log("CV: ", cv);
                    pu = p * Math.cos(-fi) + q * Math.sin(-fi);
                    pv = -p * Math.sin(-fi) + q * Math.cos(-fi);
                    px = Tx + t2 * pu;
                    py = Ty + t2 * pv;
                    particle[i].x = px + circle.x;
                    particle[i].y = py + circle.y;
                    particle[i].vx = pu + circle.vx;
                    particle[i].vy = pv + circle.vy;
                }
            }
            // Moving circle
            {
                circle.vx += cu;
                circle.vy += cv;
                circle.x += circle.vx;
                circle.y += circle.vy;
                for (var i in particle) {
                    while ((circle.x - particle[i].x) * (circle.x - particle[i].x) + (circle.y - particle[i].y) * (circle.y - particle[i].y) < circle.R * circle.R) {
                        particle[i].x += circle.vx / Math.abs(circle.vx);
                        particle[i].y += circle.vy / Math.abs(circle.vy);
                    }
                }
                circlePath.push({x: circle.x, y: circle.y});
                if (Date.now() > lastDraw + 500) {
                    items.push({
                        y: Math.sqrt((circle.x - canvas.width / 2) * (circle.x - canvas.width / 2) + (circle.y - canvas.height / 2) * (circle.y - canvas.height / 2)),
                        x: (items.length + 1) / 2
                    });
                    drawChart(activeGraph);
                    lastDraw = Date.now();
                }
            }

            //console.log(circle);
            drawCircle();
            for (var i in particle) drawParticle(particle[i]);
            lastAnim = Date.now();
        }
        animation = window.requestAnimationFrame(animateParticles);
    }

0 个答案:

没有答案