计算模拟磁场的箭头角度的问题

问题描述 投票:0回答:1

我正在编写最多 4 个电荷的磁场模拟器,但我不明白角度计算有什么问题。

函数generarCargas是创建箭头的函数,抱歉,如果我没有发表评论,如果您对代码有任何疑问,我会立即回答。

JS:

//Funcion angle
function angle(cx, cy, ex, ey) {
    const dy = ey - cy;
    const dx = ex - cx;
    const rad = Math.atan2(dy, dx);
    const deg = (rad * 180) / Math.PI;
    return deg;
}

//Funcion getPositionAtCenter
function getPositionAtCenter(element) {
    const { top, left, width, height } = element.getBoundingClientRect();
    return {
        x: left + width / 2,
        y: top + height / 2,
    };
}

//Funcion getDistanceBetweenElements
function getDistanceBetweenElements(a, b) {
    const aPosition = getPositionAtCenter(a);
    const bPosition = getPositionAtCenter(b);

    return Math.hypot(aPosition.x - bPosition.x, aPosition.y - bPosition.y);
}



function generarCargas(selectValues) {
    const arrows = document.querySelectorAll(".arrow");

    selectValues.forEach((carga) => {
        const cargaDiv = document.createElement("div");
        cargaDiv.className = "carga";
        const div = document.createElement("div");
        cargaDiv.appendChild(div);
        div.textContent = carga;
        allCampo.appendChild(cargaDiv);
        valoresCarga = carga;
    });

    let dragItem = null;
    let offsetX = 0;
    let offsetY = 0;

    allCampo.addEventListener("mousedown", (e) => {
        const cargaDiv = e.target.closest(".carga");

        if (cargaDiv) {
            dragItem = cargaDiv;
            offsetX = e.clientX - cargaDiv.getBoundingClientRect().left;
            offsetY = e.clientY - cargaDiv.getBoundingClientRect().top;

            document.addEventListener("mousemove", handleDrag);
            document.addEventListener("mouseup", () => {
                document.removeEventListener("mousemove", handleDrag);
                dragItem = null;
            });

            function handleDrag(e) {
                if (dragItem) {
                    const posX = e.clientX - offsetX;
                    const posY = e.clientY - offsetY;
                    dragItem.style.left = posX + "px";
                    dragItem.style.top = posY + "px";
                }
                const cargas = document.querySelectorAll(".carga");

                arrows.forEach((arrow) => {
                    let angles = [];

                    let eRx = 0;
                    let eRy = 0;
                    let resultantAngle;

                    cargas.forEach((carga, index) => {
                        let qx = getPositionAtCenter(carga).x;
                        let qy = getPositionAtCenter(carga).y;
                        let distancia = getDistanceBetweenElements(arrow, carga) / 100;
                        let e;

                        const rekt = arrow.getBoundingClientRect();
                        const anchorX = rekt.left + rekt.width / 2;
                        const anchorY = rekt.top + rekt.height / 2;
                        let angleDeg = angle(qx, qy, anchorX, anchorY);

                        let cargaValue = parseInt(carga.textContent);

                        if (cargaValue < 0) {
                            angleDeg = angleDeg - 180;
                            cargaValue = -cargaValue;
                        }

                        e = (k * cargaValue) / Math.pow(distancia, 2);

                        let ex = e * Math.cos((angleDeg * Math.PI) / 180);
                        let ey = e * Math.sin((angleDeg * Math.PI) / 180);

                        eRx += ex;
                        eRy += ey;

                        angles.push(angleDeg);
                    });

                    let resultant = Math.sqrt(Math.pow(eRx, 2) + Math.pow(eRy, 2));

                    let tanAlpha = eRy / eRx;
                    let alpha = (Math.atan(tanAlpha) * 180) / Math.PI;

                    arrow.style.transform = "rotate(" + alpha + "deg)";
                });
            }
        }
    });
}

生成的箭头图像: Results

javascript math physics
1个回答
0
投票

您的代码似乎大部分设置正确,可以计算模拟磁场的角度。但是,如何处理角度计算可能存在问题,尤其是在考虑多个费用及其累积效应时。以下是一些可能解决该问题的建议和代码片段:

  1. 多个电荷的角度计算:处理多个电荷时,您需要计算所有单个矢量(由于每个电荷)的合成矢量。您的代码似乎正在执行此操作,但如何汇总角度或如何计算结果可能存在问题。
  2. 处理负电荷:您添加了一个条件,如果电荷为负,则将角度减去 180 度。这可能不是处理负电荷的最佳方法。负电荷产生的力的方向应与正电荷的方向相反,但这并不一定会转化为 180 度的转变。
  3. 合成向量计算:合成向量计算看起来是正确的,但要确保
    tanAlpha
    alpha
    的计算正确。使用
    Math.atan2(eRy, eRx)
    可能会更稳健,因为它可以处理所有象限以及零分母的可能性。

这是对代码部分计算每个箭头角度的修改尝试:

// Inside handleDrag function
arrows.forEach((arrow) => {
    let eRx = 0;
    let eRy = 0;

    cargas.forEach((carga) => {
        const { x: qx, y: qy } = getPositionAtCenter(carga);
        const distancia = getDistanceBetweenElements(arrow, carga) / 100;
        const cargaValue = parseInt(carga.textContent);

        const rekt = arrow.getBoundingClientRect();
        const anchorX = rekt.left + rekt.width / 2;
        const anchorY = rekt.top + rekt.height / 2;
        let angleDeg = angle(qx, qy, anchorX, anchorY);

        let e = (k * Math.abs(cargaValue)) / Math.pow(distancia, 2);

        // Adjust direction for negative charges
        if (cargaValue < 0) {
            angleDeg += 180;
        }

        let ex = e * Math.cos((angleDeg * Math.PI) / 180);
        let ey = e * Math.sin((angleDeg * Math.PI) / 180);

        eRx += ex;
        eRy += ey;
    });

    let alpha = Math.atan2(eRy, eRx) * (180 / Math.PI);
    arrow.style.transform = `rotate(${alpha}deg)`;
});

本次修订使用

Math.atan2
来更准确地计算角度,并确保只需将角度调整180度即可处理负电荷。这应该更准确地代表具有多个电荷的磁场的物理原理。

© www.soinside.com 2019 - 2024. All rights reserved.