3

I'm currently working on a program which enables user to draw various geometric shapes. However, I got some issues on calculating and placing the angle objects onto my Canvas panel accurately. The angle object is basically an extension of the Arc2D object, which provides a additional method called computeStartAndExtent(). Inside my Angle class, this method computes and finds the necessary starting and extension angle values:

private void computeStartAndExtent()
    {
        double ang1 = Math.toDegrees(Math.atan2(b1.getY2() - b1.getY1(), b1.getX2() - b1.getX1()));
        double ang2 = Math.toDegrees(Math.atan2(b2.getY2() - b2.getY1(), b2.getX2() - b2.getX1()));

        if(ang2 < ang1)
        {
            start = Math.abs(180 - ang2);
            extent = ang1 - ang2;
        }
        else
        {
            start = Math.abs(180 - ang1);
            extent = ang2 - ang1;
        }
        start -= extent;
    }

It is a bit buggy code that only works when I connect two lines to each other, however, when I connect a third one to make a triangle, the result is like the following,

enter image description here

As you see the ADB angle is the only one that is placed correctly. I couldn't figure how to overcome this. If you need some additional info/code please let me know.

EDIT: b1 and b2 are Line2D objects in computeStartAndExtent() method.

Thank you.

Burak.
  • 598
  • 7
  • 19

1 Answers1

1

There are some of things that can be made to simplify the calculation:

  • Keep the vertices ordered, so that it is always clear how to calculate the vertex angles pointing away from the corner
  • Furthermore, always draw the polygon to the same direction; then you can always draw the angles to the same direction. The example below assumes the polygon is drawn clockwise. The same angle calculation would result in the arcs drawn outside given a polygon drawn counterclockwise.

Example code; is not quite the same as yours as I don't have your code, but has similar functionality:

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.geom.Arc2D;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class Polygon extends JPanel {
    private static final int RADIUS = 20;

    private final int[] xpoints = {
            10, 150, 80, 60
    };
    private final int[] ypoints = {
            10, 10, 150, 60
    };
    final Arc2D[] arcs;

    Polygon() {
        arcs = new Arc2D[xpoints.length];
        for (int i = 0; i < arcs.length; i++) {
            // Indices of previous and next corners
            int prev = (i + arcs.length - 1) % arcs.length;
            int next = (i + arcs.length + 1) % arcs.length;
            // angles of sides, pointing outwards from the corner
            double ang1 = Math.toDegrees(Math.atan2(-(ypoints[prev] - ypoints[i]), xpoints[prev] - xpoints[i]));
            double ang2 = Math.toDegrees(Math.atan2(-(ypoints[next] - ypoints[i]), xpoints[next] - xpoints[i]));
            int start = (int) ang1;
            int extent = (int) (ang2 - ang1);
            // always draw to positive direction, limit the angle <= 360
            extent = (extent + 360) % 360;
            arcs[i] = new Arc2D.Float(xpoints[i] - RADIUS, ypoints[i] - RADIUS, 2 * RADIUS, 2 * RADIUS, start, extent, Arc2D.OPEN);
        }
    }

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

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);

        g.drawPolygon(xpoints, ypoints, xpoints.length);
        Graphics2D g2d = (Graphics2D) g;
        for (Shape s : arcs) {
            g2d.draw(s);
        }
    }

    public static void main(String args[]){
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame("Polygon");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new Polygon());
                frame.pack();
                frame.setVisible(true);
            }
        });
    }
}

Results in:

Screenshot of a polygon

kiheru
  • 6,588
  • 25
  • 31
  • Firstly thank you sir for you answer, however, I want to ask couple of more things. My vertex objects are dynamic and has a listener to the mouse event, which results in wrong arc (angle) orientation or position when I change the location of these vertices. They must adapt to the any circumstance and show the internal angle of the given particular shape. I really stuck on doing that. – Burak. May 06 '15 at 15:36
  • @VerumInfiniti In that case you need to do more work. The angles can be calculated as before as long as you are careful with the directions, but determining on which side (ie to which direction draw) you want the arc becomes complicated. For simple polygons it's [simple](http://stackoverflow.com/questions/22159120/how-to-determine-which-side-of-a-polygon-edge-is-inside-a-polygon-and-which-is). I'm not quite sure what to do about intersecting polygons. Determining whether a point is inside can be done by calculating the winding number, maybe that be can adapted for deciding the arc direction. – kiheru May 06 '15 at 16:22