基本的なモデル エディターを作成しようとしていますが、atan2 を理解していないか、予測不可能で苛立たしい結果が返されるため、使用するのに適切なソリューションではありません。このサイトの別のスレッドから借用したコードを少し使用して、2 点間の角度を取得しましたが、問題は、それが望んでいることを実行しておらず、正しい場所に回転していないことです。これは、モデルを設計し、レンダリングしてドラッグするクラスです。
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;
}
}
}
すべてが実装されているわけではないため、コードはまだ少し乱雑ですが、少しいらいらしています。基本的に、角度が間違った場所に行く原因となっています。誰かが私の問題を理解しているなら、手を貸してください。ありがとうございました。