Note that there are some explanatory texts on larger screens.

plurals
  1. PORotation using atan2 is acting strangely
    primarykey
    data
    text
    <p>I'm trying to create a basic model editor but either I'm not understanding atan2 or it's not the right solution for me to be using, because it is returning unpredictable and frustrating results. I've been using a bit of code borrowed from another thread on this site to get the angle between two points, but the problem is, it's just not doing what I want and isn't rotating to the right place. Here's the class where I design my models, render them and drag them.</p> <pre><code>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&lt;Rectangle&gt; ClickableJointPoints = new ArrayList&lt;Rectangle&gt;(); 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 &lt; 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; } } </code></pre> <p>Here's the code for the skeleton class (it comes with a constructor that makes a basic model):</p> <pre><code>import java.util.ArrayList; public class Skeleton { ArrayList&lt;Joint&gt; ChildJoints = new ArrayList&lt;Joint&gt;(); /* * 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); } } </code></pre> <p>}</p> <p>And here's the code of the Joint class:</p> <pre><code>import java.util.ArrayList; public class Joint { ArrayList&lt;Joint&gt; ChildJoints = new ArrayList&lt;Joint&gt;(); 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; } } </code></pre> <p>}</p> <p>The code is still a bit messy because not everything is implemented but it's getting a bit irritating, because if I can't do this I can't really move on and the program doesn't do what it's supposed to. Basically, it's causing the angles to go to the wrong place. So if anybody understands my problem, please give me a hand. Thank you.</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload