0

我正在尝试创建一个基本的模型编辑器,但要么我不理解 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;
    }
}

}

代码仍然有点混乱,因为并非所有内容都已实现,但它变得有点烦人,因为如果我不能做到这一点,我就无法真正继续前进,并且程序不会做它应该做的事情。基本上,它会导致角度到错误的位置。因此,如果有人理解我的问题,请帮帮我。谢谢你。

4

1 回答 1

0

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

于 2013-08-31T03:00:53.897 回答