javapolygongeometry-surface

Draw a circle on each edge of an n-polygon


Given a list of n circles, each of diameter d, I want to generate an n-gon (polygon of n lengths), with side lengths d, and draw a circle on each of its edges.

I encountered this problem while developing an application.

The formula for the radius of the polygon with N sides, given a length a for each side, is

My code

Game Frame

import javax.swing.JFrame;


public class gameFrame extends JFrame{  
    static int width = 400;
    static int height = 400;
  
    public static void main(String[] args) {
    
        gameFrame frame = new gameFrame();
        gamePanel panel = new gamePanel();

        frame.add(panel);
    
        frame.setTitle("Tutorial");
        frame.setSize(400, 400);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        frame.setVisible(true);
        frame.setResizable(true);
    
        panel.initializeList();
        panel.fpsTimer.start();
    
    }
}

Game Panel

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Arc2D;
import java.util.ArrayList;

import javax.swing.JPanel;
import javax.swing.Timer;

public class gamePanel extends JPanel{
    static ArrayList<Point2D> coordinates = new ArrayList<Point2D>();
    static int d = 20;

    Timer fpsTimer = new Timer(10, new ActionListener() {
        @Override
            public void actionPerformed(ActionEvent e) {
            repaint();
        
        }
    });

    public void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g;
        
            //paint the circles with the coordinates in list 'coordinates'
            for(Point2D point : coordinates) {
                g2d.setColor(Color.BLACK);
                Shape circle = new Arc2D.Double(point.x,
                        point.y,
                        d,
                        d,
                        0 , 360, Arc2D.CHORD);
                g2d.fill(circle);
            }
    
        }

    public void initializeList() {
        Point2D center = new Point2D(0,0);
    
        int n = 15; // number of sides of polygon
        float alpha = 360/ n;    // angle of each triangle in the polygon
        float angle = 0;       // incremental angle for the loop 

        float side = d;         // desired length of each side    
        float radius = (float) (side / (2*Math.sin(Math.PI / n)));  // R = a / (2*(sin(PI/n))) formula
    
        //verifying that the circle radius isn't larger than the frame
        if(!(radius >= gameFrame.width || radius >= gameFrame.height)) {
        
            //center of the circle
            center.x = (gameFrame.width)/2;
            center.y = (gameFrame.height)/2; 
    
            for(int i = 0 ; i < n ; i++) {
                coordinates.add(new Point2D((center.x + Math.sin(angle)*radius),
                        (center.y -Math.cos(angle)*radius)));
                angle += alpha;
                }
        }
    
    
    }
}

Point2D (for simplicity)

public class Point2D {
    double x;
    double y;

    public Point2D(double x , double y) {
        this.x = x;
        this.y = y;
    }
}

The outputs and reflection

For n=15 and d=20 as shown above, the output is

Some circles overlap. Surprisingly, if I modify angle += alpha to angle += alpha+0.295; in GamePanel initializeList(), I get the desired result :

For n=14 the output is even scarier :

I have spent a ridiculous amount of time on this bug. Does anyone have any idea what is going wrong?


Solution

  • Java Math uses angles in radians.
    So calculate alpha in radians like this:

    double alpha = Math.toRadians(360.0/ n);
    

    Just update the line and it should fix the issue.

    Also, for more accuracy use double type instead of float for each variable.