代码之家  ›  专栏  ›  技术社区  ›  Chris Dennett

查找用于旋转的三角角给定实体的位置、初始旋转和目标点到“面向”

  •  3
  • Chris Dennett  · 技术社区  · 14 年前

    我正在用Java编写一个群集算法,但我在某个点上(在二维平面上使用Ardor3D库)陷入了困境。

    基本上,我需要找到角度差来添加到当前旋转。如果你只能得到它的指向方式,应该用极坐标指向北方0度,而不是差,不用担心,我有一个方法,它返回角度差,考虑到角度和负角度上的环绕。

    alt text

    目前,我有以下代码,这显然是行不通的,因为算法没有参考初始旋转:

      long tpf = currUpdateTimeMS - lastUpdateTimeMS;
    
      Vector2 pos = new Vector2();
      rt.getPosition(pos);
    
      double rot = pos.angleBetween(app.getAvgBoidPos(new Vector2()).normalizeLocal());
      rt.setRotation(rot);
    
      pos.addLocal(
       Math.cos((rot - MathUtils.HALF_PI)) * (tpf / 10f),
       Math.sin((rot - MathUtils.HALF_PI)) * (tpf / 10f)
      );
      rt.setPosition(pos);
    
      super.updateLogic();
    

    更新的代码(不起作用,从第一个答案开始):

        long tpf = currUpdateTimeMS - lastUpdateTimeMS;
        //rt.setRotation(rt.getRotation() + ((tpf / (ROT_SPEED / 2f)) % 360));
    
        Vector2 avgpos = app.getAvgBoidPos(new Vector2());
        Vector2 pos = rt.getPosition(new Vector2());
        avgpos.subtractLocal(pos);
    
        double angleRads = rt.getRotation() * FastMath.DEG_TO_RAD;
        double rot = MathUtils.acos((
            (avgpos.getX() * MathUtils.sin(angleRads)
        ) +
            (avgpos.getY() * MathUtils.cos(angleRads)
        )) / ((Math.pow(avgpos.getX(), 2) + Math.pow(avgpos.getY(), 2)) * 0.5));
    
        double adegdiff = rot * FastMath.RAD_TO_DEG;
    
        rt.setRotation(rt.getRotation() - adegdiff);
        double newrot = rt.getRotation();
    
        pos.addLocal(
            Math.cos((newrot - MathUtils.HALF_PI)) * (tpf / 10f),
            Math.sin((newrot - MathUtils.HALF_PI)) * (tpf / 10f)
        );
        rt.setPosition(pos);
    
        super.updateLogic();
    

    基于另一个答案的另一个修改:

        long tpf = currUpdateTimeMS - lastUpdateTimeMS;
        //rt.setRotation(rt.getRotation() + ((tpf / (ROT_SPEED / 2f)) % 360));
    
        Vector2 avgpos = app.getAvgBoidPos(new Vector2());
        Vector2 pos = rt.getPosition(new Vector2());
        avgpos.subtractLocal(pos);
    
        double rot = pos.angleBetween(
            app.getAvgBoidPos(new Vector2()).normalizeLocal()
        ) - (rt.getRotation() * MathUtils.DEG_TO_RAD);
    
        rt.setRotation(rt.getRotation() - (rot * MathUtils.RAD_TO_DEG));
        double newrot = rt.getRotation();
    
        pos.addLocal(
            Math.cos((newrot - MathUtils.HALF_PI)) * (tpf / 10f),
            Math.sin((newrot - MathUtils.HALF_PI)) * (tpf / 10f)
        );
        rt.setPosition(pos);
    
        super.updateLogic();
    

    我不太擅长数学题,所以代码比公式更有用:)

    • 实体当前位置
    • 实体(极轴定向)的当前旋转(度)

    输出

    • 要添加或减去当前旋转的度数或弧度
    • ... 或以极向角表示的度数或弧度

    克里斯

    4 回复  |  直到 14 年前
        1
  •  2
  •   andand    14 年前

    可以使用点积确定当前方向和要面对的点之间的角度(以弧度为单位)的余弦。假设执行观察的代理位于原点,并且朝向由相对于Y轴的角度θ给定的某个方向(即0度为“向上”或“向北”)。你想找出这个方向和面对一个点(x,y)的角度差θ'。由以下人员提供:

    θ' = cos-1[(x*sin(θ) + y*cos(θ)) / sqrt(x2 + y2)]

    从θ中减去θ'将使代理朝向目标。

    如果代理不在源位置,只需从要查看的对象中减去代理的位置即可将其转换为上述形式。

        3
  •  0
  •   fasseg    14 年前

    这里是一个如何在两个具有共同原点的向量之间找到夹角的实现。这是根据这里描述的算法一起破解的: http://www.wikihow.com/Find-the-Angle-Between-Two-Vectors

    public class DeltaDoodle {
    
        private double delta(ColumnVector v1,ColumnVector v2) throws Exception{
            double sp=scalarProduct(v1,v2);
            double magV1=magnitude(v1);
            double magV2=magnitude(v2);
            return Math.acos(sp/(magV1*magV2)) * (180/Math.PI);
        }
    
        private double scalarProduct(ColumnVector a, ColumnVector b) {
            return (a.x*b.x) + (a.y*b.y);
        }
        private double magnitude(ColumnVector a){
            return Math.sqrt((a.x*a.x) + (a.y*a.y));
        }
    
        public static void main(String[] args) {
            DeltaDoodle v=new DeltaDoodle();
            try {
                System.out.println("angle: " + v.delta(new ColumnVector(5, 5), new ColumnVector(1,1)));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
    }
    
    public class ColumnVector {
        public final double x, y;
    
        public ColumnVector(double x1, double x2) {
            this.x = x1;
            this.y = x2;
        }
    }
    

    希望能帮上忙。。。

        4
  •  0
  •   Beta    14 年前

    Vector2 pos = new Vector2(); 
    rt.getPosition(pos); 
    
    double rot = pos.angleBetween(app.getAvgBoidPos(new Vector2()).normalizeLocal()) - rt.getRotation();
    

    P、 S.忘了提:这个 rot 是指角度差。旋转实体这么多,它应该指向目标。

    编辑:
    谢谢,代码确实有用(我误解了 angleBetween

    这是从实体到点的向量(如果语法错误,请原谅,我不懂java):

    Vector2 pos = new Vector2(); 
    rt.getPosition(pos); 
    
    Vector2 direction = app.getAvgBoidPos(new Vector2());
    direction.subtractLocal(pos);
    

    现在,我们将其规格化,得到指向该点的单位向量,并取角度差:

    double rot = rt.getRotation().angleBetween(direction.normalizeLocal())