使用atan2进行旋转的动作很奇怪

时间:2013-08-31 02:27:25

标签: java math atan2

我正在尝试创建一个基本的模型编辑器,但要么我不理解atan2,要么它不适合我使用,因为它返回了不可预测和令人沮丧的结果。 我一直在使用从这个站点的另一个线程借来的一些代码来获得两点之间的角度,但问题是,它只是没有做我想要的并且没有旋转到正确的位置。 这是我设计模型的类,渲染它们并拖动它们。

import java.awt.*;
import java.awt.event.*;
import java.util.*;

import javax.swing.*;

public class ModelDesigner extends JPanel implements MouseListener, MouseMotionListener{
Skeleton CurrentSkeleton = new Skeleton();
ArrayList<Rectangle> ClickableJointPoints = new ArrayList<Rectangle>();
Joint SelectionJoint = null;

boolean Dragging = false;
Point ClickPoint = new Point(0, 0);

public ModelDesigner(){
    setBackground(Color.white);
    addMouseListener(this);
    addMouseMotionListener(this);
}

public void paintComponent(Graphics g){
    super.paintComponent(g);
    Graphics2D g2 = (Graphics2D) g.create();
    RenderSkeleton(g2, CurrentSkeleton);
}

void RenderSkeleton(Graphics2D g2, Skeleton e){
    for (Joint j : e.ChildJoints){
        RenderJoint(g2, j, getWidth() / 2, 10, 0);
    }
}

void RenderJoint(Graphics2D g2, Joint j, int ParentX, int ParentY, double r){
    g2.setColor(Color.black);
    Point p = getEndPointOfRotatedLine(j.Rotation + r, j.X, j.Y, j.Length);
    g2.drawLine(ParentX + j.X, ParentY + j.Y, ParentX + p.x, ParentY + p.y);
    g2.setColor(Color.red);
    g2.fillOval(ParentX + p.x - 3, ParentY + p.y - 3, 6, 6);
    if (j.HasChildren){
        for (Joint j2 : j.ChildJoints){
            RenderJoint(g2, j2, ParentX + p.x, ParentY + p.y, j.Rotation);
        }
    }
}

public static Point getEndPointOfRotatedLine(double angle, int x, int y, int length){
    Point p = new Point();
    p.x = (int) (x + length * Math.cos(angle));
    p.y = (int) (y + length * Math.sin(angle));
    return p;
}

@Override
public void mouseDragged(MouseEvent e) {
    Rectangle Click = new Rectangle(e.getX(), e.getY(), 1, 1);
    if (Dragging){
        SelectionJoint.Rotation = getAngle(ClickPoint, new Point(Click.x, Click.y));
        repaint();
    }
}

public double getAngle(Point orig, Point target) {
    double angle = (double) (Math.atan2(target.y - orig.y, target.x - orig.x));

    if(angle < 0){
        angle += 360;
    }

    return angle;
}

@Override
public void mouseMoved(MouseEvent arg0) {

}

@Override
public void mouseClicked(MouseEvent e) {

}

@Override
public void mouseEntered(MouseEvent e) {

}

@Override
public void mouseExited(MouseEvent e) {

}

@Override
public void mousePressed(MouseEvent e) {
    Rectangle Click = new Rectangle(e.getX(), e.getY(), 1, 1);
    /*
     *  Point p = getEndPointOfRotatedLine(j.Rotation, j.X, j.Y, j.Length);
     *  ClickableJointPoints.add(new Rectangle(p.x - 3, p.y - 3, 6, 6));
     */
    for (Joint j : CurrentSkeleton.ChildJoints){
        Point p = getEndPointOfRotatedLine(j.Rotation, j.X, j.Y , j.Length);
        //this.getGraphics().drawRect(p.x - 3 + (getWidth() / 2), p.y - 3 + 10, 6, 6);
        if (new Rectangle(p.x - 3 + getWidth() / 2, p.y - 3 + 10, 6, 6).intersects(Click)){
            System.out.println("intersection");
            SelectionJoint = j;
            Dragging = true;
            ClickPoint = p;
            return;
        }else{
            if (j.HasChildren){
                for (Joint j2 : j.ChildJoints){
                    if (getIntersectionOfRectAndJoints(Click, j2, j.X + p.x, j.Y + p.y, j.Rotation)){
                        return;
                    }
                }
            }
        }
    }

}

public boolean getIntersectionOfRectAndJoints(Rectangle r, Joint j, int parentX, int parentY, double rotation){
    Point p = getEndPointOfRotatedLine(j.Rotation + rotation, j.X, j.Y, j.Length);
    this.getGraphics().drawRect(parentX + p.x - 3 + (getWidth() / 2), parentY + p.y - 3 + 10, 6, 6);
    if (new Rectangle(parentX + p.x - 3 + getWidth() / 2, parentY + p.y - 3 + 10, 6, 6).intersects(r)){
        System.out.println("intersection");
        SelectionJoint = j;
        Dragging = true;
        ClickPoint = p;
        return true;
    }else{
        if (j.HasChildren){
            for (Joint j2 : j.ChildJoints){
                if (getIntersectionOfRectAndJoints(r, j2, parentX + j.X + p.x, parentY + j.Y + p.y, j.Rotation)){
                    return true;
                }
            }
        }
    }
    return false;
}

@Override
public void mouseReleased(MouseEvent e) {
    Dragging = false;
}
}

这是骨架类的代码(它带有一个构建基本模型的构造函数):

import java.util.ArrayList;

public class Skeleton {
ArrayList<Joint> ChildJoints = new ArrayList<Joint>();

/* 
 * The constructor just adds a fancy default skeleton, you should be able to add
 * and remove limbs, as well as change lengths eventually.
 */
public Skeleton(){
    //add the primary parent joint
    Joint HeadJoint = new Joint();
    HeadJoint.Length = 10;
    HeadJoint.Rotation = Math.toRadians(90);
    Joint Spine = new Joint();
    Spine.Length = 100;
    Spine.Rotation = Math.toRadians(0);
    Joint leftArm = new Joint();
    leftArm.Length = 50;
    leftArm.Rotation = Math.toRadians(45);
    Joint rightArm = new Joint();
    rightArm.Length = 50;
    rightArm.Rotation = Math.toRadians(315);
    Joint leftLeg = new Joint();
    leftLeg.Length = 60;
    leftLeg.Rotation = Math.toRadians(112);
    Joint rightLeg = new Joint();
    rightLeg.Length = 60;
    rightLeg.Rotation = Math.toRadians(68);
    Joint bottomLeftLeg = new Joint();
    bottomLeftLeg.Length = 35;
    bottomLeftLeg.Rotation = Math.toRadians(-10);
    Joint bottomRightLeg = new Joint();
    bottomRightLeg.Length = 35;
    bottomRightLeg.Rotation = Math.toRadians(10);
    ChildJoints.add(HeadJoint);
    HeadJoint.AddChild(Spine);
    HeadJoint.AddChild(leftArm);
    HeadJoint.AddChild(rightArm);
    Spine.AddChild(leftLeg);
    Spine.AddChild(rightLeg);
    leftLeg.AddChild(bottomLeftLeg);
    rightLeg.AddChild(bottomRightLeg);
}

public void MoveSkeleton(int newX, int newY){
    for (Joint j : ChildJoints){
        j.MoveJoint(newX, newY);
    }
}

}

以下是Joint类的代码:

import java.util.ArrayList;

public class Joint {
ArrayList<Joint> ChildJoints = new ArrayList<Joint>();

int Length = 0;
double Rotation = 0.0;

boolean HasChildren = false;

int X;
int Y;

String JointName = "unknown joint";

public void MoveJoint(int newX, int newY){
    X = newX;
    Y = newY;
    for (Joint j : ChildJoints){
        if (j.HasChildren){
            j.MoveJoint(newX, newY);
        }else{
            j.X = newX;
            j.Y = newY;
        }
    }
}

public void AddChild(Joint j){
    ChildJoints.add(j);
    HasChildren = true;
}

public void RemoveChild(int v){
    if (ChildJoints.size() == 0){
        HasChildren = false;
    }
}

}

代码仍然有点凌乱,因为并非所有内容都已实现,但它有点令人恼火,因为如果我不能这样做,我就无法继续前进,程序也没有按照预期进行操作。 基本上,它导致角度到错误的地方。所以,如果有人理解我的问题,请帮我一把。谢谢。

1 个答案:

答案 0 :(得分:0)

我已经在一定程度上解决了这个问题。我在初始化时忘记向ClickPoint添加正确的坐标,例如父关节的x和y位置以及实际的渲染坐标。感谢大家的帮助,这对我来说是一个愚蠢的错误。