Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
473 views
in Technique[技术] by (71.8m points)

swing - Rotating a triangle around a point java

I am having trouble. I need to rotate an equilateral triangle around it's centre by using the drag listener and click listener. The triangle should grow but now change angles and be rotated by a point while being centred at the middle of the triangle. This is my problem, it is currently dragging by the point 3 and rotating around point 1. I have an array of values x and y and it stores 4 values each containing the initial point first at ordinal value 0 and point 1 2 and 3 at the corresponding values.

`

public class DrawTriangle extends JFrame {

enter code here
/** The Constant NUMBER_3. */
private static final int NUMBER_3 = 3;

/** The Constant EQUL_ANGLE. */
@SuppressWarnings("unused")
private static final double EQUL_ANGLE = 1;

/** The Constant TRIANGLE_POINTS. */
private static final int TRIANGLE_POINTS = 4;

/** The Constant _400. */
private static final int SIZE = 400;

/** The x points. */
private int [] xPoints = new int[TRIANGLE_POINTS];

/** The y points. */
private int [] yPoints = new int[TRIANGLE_POINTS];

private int xInitial;

private int yInitial;

/** The x. */
private double x = EQUL_ANGLE;

/** The new x. */
private double newX;

/** The new y. */
private double newY;

/**
 * Instantiates a new draw triangle.
 */
public DrawTriangle() {
    super("Dimitry Rakhlei");
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setContentPane(new DrawTrianglePanel());
    setSize(SIZE, SIZE); // you can change this size but don't make it HUGE!
    setVisible(true);
}

/**
 * The Class DrawTrianglePanel.
 */
private class DrawTrianglePanel extends JPanel implements MouseListener,
        MouseMotionListener {

    /**
     * Instantiates a new draw triangle panel.
     */
    public DrawTrianglePanel() {
        addMouseListener(this);
        addMouseMotionListener(this);
    }

    /**
     * Drawing the triangle.
     *
     * @param g
     *            the g
     * @see javax.swing.JComponent#paintComponent(java.awt.Graphics)
     */
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        // DRAWING CODE HERE
        g.drawPolygon(xPoints, yPoints, 3);
        System.out.println("Paint called");
    }



    /**
     * (non-Javadoc).
     *
     * @param e
     *            the e
     * @see java.awt.event.MouseListener#mousePressed
     * (java.awt.event.MouseEvent)
     */
    public void mousePressed(MouseEvent e) {
        System.out.println("Mouse pressed called");
        e.getPoint();
        xPoints[0] = e.getPoint().x;
        yPoints[0] = e.getPoint().y;
        repaint();

    }

    /**
     * (non-Javadoc).
     *
     * @param e
     *            the e
     * @see java.awt.event.MouseListener#mouseReleased
     * (java.awt.event.MouseEvent)
     */
    public void mouseReleased(MouseEvent e) {
        System.out.println("Mouse released called");
    }

    /**
     * (non-Javadoc).
     *
     * @param e
     *            the e
     * @see java.awt.event.MouseMotionListener#mouseDragged
     * (java.awt.event.MouseEvent)
     */
    public void mouseDragged(MouseEvent e) {
        System.out.println("Mouse dragged called");
        newX = e.getPoint().x;
        newY = e.getPoint().y;
        xPoints[1] = (int) newX;
        yPoints[1] = (int) newY;


        newX = xPoints[0] + (xPoints[1]-xPoints[0])*Math.cos(x) - (yPoints[1]-yPoints[0])*Math.sin(x);

        newY = yPoints[0] + (xPoints[1]-xPoints[0])*Math.sin(x) + (yPoints[1]-yPoints[0])*Math.cos(x);

        xPoints[2] = (int) newX;
        yPoints[2] = (int) newY;

        newX = xPoints[0] + (xPoints[1]-xPoints[0])*Math.cos(x) - (yPoints[1]-yPoints[0])*Math.sin(x);

        newY = yPoints[0] + (xPoints[1]-xPoints[0])*Math.sin(x) + (yPoints[1]-yPoints[0])*Math.cos(x);

        xPoints[3] = (int) newX;
        yPoints[3] = (int) newY;

        repaint();
    }

    /**
     * (non-Javadoc).
     *
     * @param e
     *            the e
     * @see java.awt.event.MouseListener#mouseEntered
     * (java.awt.event.MouseEvent)
     */
    public void mouseEntered(MouseEvent e) {
        System.out.println("Mouse Entered.");
    }

    /**
     * (non-Javadoc).
     *
     * @param e
     *            the e
     * @see java.awt.event.MouseListener#mouseExited
     * (java.awt.event.MouseEvent)
     */
    public void mouseExited(MouseEvent e) {
        System.out.println("Mouse exited.");
    }

    /**
     * (non-Javadoc).
     *
     * @param e
     *            the e
     * @see java.awt.event.MouseListener#mouseClicked
     * (java.awt.event.MouseEvent)
     */
    public void mouseClicked(MouseEvent e) {
    }

    /**
     * (non-Javadoc).
     *
     * @param e
     *            the e
     * @see java.awt.event.MouseMotionListener#mouseMoved
     * (java.awt.event.MouseEvent)
     */
    public void mouseMoved(MouseEvent e) {
    }

}

/**
 * The main method.
 *
 * @param args
 *            the arguments
 */
public static void main(String[] args) {
    new DrawTriangle();
}

};` 

My issue is that this code basically runs correctly but I am told the vertex point of rotation has to be in the middle of the triangle. Mine is the first point.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Start by taking a look at 2D Graphics, in particular Transforming Shapes, Text, and Images.

Basically, your "polygon" will have a definable size (the maximum x/y point), from this, you can determine the center position of the "polygon", for example...

protected Dimension getTriangleSize() {
    int maxX = 0;
    int maxY = 0;
    for (int index = 0; index < xPoints.length; index++) {
        maxX = Math.max(maxX, xPoints[index]);
    }
    for (int index = 0; index < yPoints.length; index++) {
        maxY = Math.max(maxY, yPoints[index]);
    }
    return new Dimension(maxX, maxY);
}

This just returns the maximum x and y bounds of your polygon. This allows you to calculate the center position of the polygon. You'll see why in a second why you don't need to actually specify the origin point...

Next, we calculate a AffineTransform, which is the applied to the Graphics context directly...

Graphics2D g2d = (Graphics2D) g.create();
AffineTransform at = new AffineTransform();
Dimension size = getTriangleSize();
int x = clickPoint.x - (size.width / 2);
int y = clickPoint.y - (size.height / 2);
at.translate(x, y);
at.rotate(Math.toRadians(angle), clickPoint.x - x, clickPoint.y - y);
g2d.setTransform(at);
g2d.drawPolygon(xPoints, yPoints, 3);
// Guide
g2d.setColor(Color.RED);
g2d.drawLine(size.width / 2, 0, size.width / 2, size.height / 2);
g2d.dispose();

This not only translates the triangle position, but will also rotate it. What this means you can create a normalised polygon (whose origin point is 0x0) and allow the Graphics context to place it where you want it, this makes life SO much easier...

Now, the rotation calculation is based on calculating the angle between two points, the "click" point and the "drag" point...

angle = -Math.toDegrees(Math.atan2(e.getPoint().x - clickPoint.x, e.getPoint().y - clickPoint.y)) + 180;

Which is based on the solution in this question

For example...

enter image description here

The red line is simple a guide to show that the tip of the triangle is point towards the mouse...

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.AffineTransform;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class DrawTriangle extends JFrame {

    /**
     * The x points.
     */
    private int[] xPoints = new int[]{0, 25, 50};

    /**
     * The y points.
     */
    private int[] yPoints = new int[]{50, 0, 50};

    double angle = 0f;

    /**
     * Instantiates a new draw triangle.
     */
    public DrawTriangle() {
        super("Dimitry Rakhlei");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setContentPane(new DrawTrianglePanel());
        pack();
        setLocationRelativeTo(null);
        setVisible(true);
    }

    /**
     * The Class DrawTrianglePanel.
     */
    private class DrawTrianglePanel extends JPanel implements MouseListener,
                    MouseMotionListener {

        private Point clickPoint;

        /**
         * Instantiates a new draw triangle panel.
         */
        public DrawTrianglePanel() {
            addMouseListener(this);
            addMouseMotionListener(this);
            clickPoint = new Point(100, 100);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        protected Dimension getTriangleSize() {

            int maxX = 0;
            int maxY = 0;
            for (int index = 0; index < xPoints.length; index++) {
                maxX = Math.max(maxX, xPoints[index]);
            }
            for (int index = 0; index < yPoints.length; index++) {
                maxY = Math.max(maxY, yPoints[index]);
            }
            return new Dimension(maxX, maxY);
        }

        /**
         * Drawing the triangle.
         *
         * @param g the g
         * @see javax.swing.JComponent#paintComponent(java.awt.Graphics)
         */
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);

            Graphics2D g2d = (Graphics2D) g.create();
            AffineTransform at = new AffineTransform();
            Dimension size = getTriangleSize();
            int x = clickPoint.x - (size.width / 2);
            int y = clickPoint.y - (size.height / 2);
            at.translate(x, y);
            at.rotate(Math.toRadians(angle), clickPoint.x - x, clickPoint.y - y);
            g2d.setTransform(at);
            g2d.drawPolygon(xPoints, yPoints, 3);
            // Guide
            g2d.setColor(Color.RED);
            g2d.drawLine(size.width / 2, 0, size.width / 2, size.height / 2);
            g2d.dispose();

        }

        /**
         * (non-Javadoc).
         *
         * @param e the e
         * @see java.awt.event.MouseListener#mousePressed (java.awt.event.MouseEvent)
         */
        @Override
        public void mousePressed(MouseEvent e) {
            System.out.println("Mouse pressed called");
            //          clickPoint = e.getPoint();
            repaint();

        }

        /**
         * (non-Javadoc).
         *
         * @param e the e
         * @see java.awt.event.MouseListener#mouseReleased (java.awt.event.MouseEvent)
         */
        @Override
        public void mouseReleased(MouseEvent e) {
            System.out.println("Mouse released called");
        }

        /**
         * (non-Javadoc).
         *
         * @param e the e
         * @see java.awt.event.MouseMotionListener#mouseDragged (java.awt.event.MouseEvent)
         */
        public void mouseDragged(MouseEvent e) {
            System.out.println("Mouse dragged called");

            angle = -Math.toDegrees(Math.atan2(e.getPoint().x - clickPoint.x, e.getPoint().y - clickPoint.y)) + 180;

            repaint();
        }

        /**
         * (non-Javadoc).
         *
         * @param e the e
         * @see java.awt.event.MouseListener#mouseEntered (java.awt.event.MouseEvent)
         */
        public void mouseEntered(MouseEvent e) {
            System.out.println("Mouse Entered.");
        }

        /**
         * (non-Javadoc).
         *
         * @param e the e
         * @see java.awt.event.MouseListener#mouseExited (java.awt.event.MouseEvent)
         */
        public void mouseExited(MouseEvent e) {
            System.out.println("Mouse exited.");
        }

        /**
         * (non-Javadoc).
         *
         * @param e the e
         * @see java.awt.event.MouseListener#mouseClicked (java.awt.event.MouseEvent)
         */
        public void mouseClicked(MouseEvent e) {
        }

        /**
         * (non-Javadoc).
         *
         * @param e the e
         * @see java.awt.event.MouseMotionListener#mouseMoved (java.awt.event.MouseEvent)
         */
        public void mouseMoved(MouseEvent e) {
        }

    }

    /**
     * The main method.
     *
     * @param args the arguments
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                new DrawTriangle();
            }
        });
    }

}

Now, before you jump all over me and complain that the solution is "too complex", understand that I'm an idiot, seriously, my 2 year old has a better grasp on basic mathematics then I do, this is the most simplistic solution I can come up with that doesn't melt my brain and uses the dual array polygon API. Personally, I'd use the Shape API, but that's not what you started with...


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...