-1
    Polygon arrow = new Polygon();
    arrow.addPoint(0, 5);
    arrow.addPoint(-5, -5);
    arrow.addPoint(5, -5);

    AffineTransform tx = new AffineTransform();
    double angle = Math.atan2(y2 - y1, x2 - x1);
    tx.translate(x2 + Config.VERTEX_RADIUS / 2, y2 + Config.VERTEX_RADIUS / 2);
    tx.rotate((angle - Math.PI / 2));

    graphics.setColor(Color.BLACK);
    graphics.draw(new Line2D.Double(x1, y1, x2, y2));
    graphics.setTransform(tx);
    graphics.fill(arrow);

screen: http://imglink.ru/show-image.php?id=254ac13712ad825a1a1b99181170f747

EDIT So, I changed the code on the advice of MadProgrammer, but there is such an unpleasant shift of the arrow. screen -> http://www.imglink.ru/show-image.php?id=f1d6d3dfdb52972d731690e031af7d71

private void drawEdgeLine(Graphics2D graphics, double x1, double y1, double x2, double y2) {

    graphics.setColor(Color.BLACK);
    graphics.draw(new Line2D.Double(x1, y1, x2, y2));

    ArrowHead arrowHead = new ArrowHead();
    double length = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
    double t1 = Config.VERTEX_RADIUS / length;
    double t2 = (length - Config.VERTEX_RADIUS) / length;
    double arrowX, arrowY;
    if (t1 > t2) {
        arrowX = x1 + t1 * (x2 - x1);
        arrowY = y1 + t1 * (y2 - y1);
    } else {
        arrowX = x1 + t2 * (x2 - x1);
        arrowY = y1 + t2 * (y2 - y1);
    }

    double angle = Math.atan2(y2 - y1, x2 - x1);
    /*double angleDegrees = Math.toDegrees(angle + Math.PI);
    System.out.println(angleDegrees);
    if (angleDegrees > 90 && angleDegrees < 270) {
        arrowY += Config.ARROW_HEAD_SIZE / 2;
    } else {
        arrowX -= Config.ARROW_HEAD_SIZE / 2;
    }*/

    AffineTransform transform = AffineTransform.getTranslateInstance(arrowX, arrowY);
    transform.rotate(angle + Math.PI / 2);
    arrowHead.transform(transform);
    graphics.draw(arrowHead);
}

}

class ArrowHead extends Path2D.Double {

public ArrowHead() {
    double size = Config.ARROW_HEAD_SIZE;
    moveTo(0, size);
    lineTo(size / 2, 0);
    lineTo(size, size);
}

}

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
MaxB
  • 635
  • 1
  • 9
  • 22
  • So, rotation will occur at the top/left corner of the anchor point (`0x0`). What I tend to do, is translate the area to where I want the object positioned, so the anchor point becomes `0x0` the rotate around the centre of the object, remember to undo the mess when you're done – MadProgrammer Jan 25 '20 at 01:49

1 Answers1

0

So, rotation will occur at the top/left corner (0x0 or "origin point"). For a component, this has already been translated to the top/left corner for your convince.

You also need to take into consideration that transformations are compounding, so you need to make sure you undo them when you're done - especially because the Graphics context in Swing is shared ... and that could really screw things up.

So. The basic idea is:

  • Translate the content to where you want the shape drawn
  • Rotate the context around the centre of the shape, this will "generally" produce a desired result
  • Reset the transformation

The following example demonstrates the basic idea and uses a Timer to spin the shape

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Path2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

class Main {

    public static void main(String[] args) {
        new Main();
    }

    public Main() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class ArrowHead extends Path2D.Double {

        public ArrowHead() {
            int size = 10;
            moveTo(0, size);
            lineTo(size / 2, 0);
            lineTo(size, size);
            closePath();
        }

    }

    public class TestPane extends JPanel {

        private ArrowHead arrow = new ArrowHead();
        private double angleOfAttack = 0;

        public TestPane() {
            Timer timer = new Timer(5, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    angleOfAttack += 0.5;
                    repaint();
                }
            });
            timer.start();
        }

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

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            // Snap shot the current context
            Graphics2D g2d = (Graphics2D) g.create();

            // Translate to somewhere you want the arrow painted ...
            g2d.translate(50, 50);
            // The bounding box of the arrow...
            Rectangle bounds = arrow.getBounds();

            // A guide, showing where the arrow is been painted without the rotation
            g2d.setColor(Color.RED);
            g2d.draw(bounds);

            // Rotate abount the middle of the arrow...
            g2d.rotate(Math.toRadians(angleOfAttack), bounds.width / 2, bounds.height / 2);
            g2d.setColor(Color.BLACK);
            // Draw the arrow
            g2d.fill(arrow);

            // Discard the transformations so we don't effect anyone else
            g2d.dispose();
        }

    }

}

You might also want to take a look at Connect two circles with a line, which is a more complicated example of this concept, but which seems to be more inline with what you are trying to achieve

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • Ok, take a look at what I've offered, you have two complete examples that you can run and modify to your hearts content, you can see how the code is working and see how changes affect it. Now, look at what you've offered me - a number of out-of-context snippets, where there are so many un-answered questions about state and context. You need to distill you question down to a [mcve] and before you tell me it's "too hard" - I've done it, twice – MadProgrammer Jan 25 '20 at 22:27