Anastasia
Anastasia

Reputation: 29

Draw random dots inside a circle

I would like to draw 50 random dots within a given circle. The problem is the dots are not contained in the circle. Here is a runnable example:

package mygraphicsshapehomework;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JFrame;


public class MyGraphicsShapeHomeWork extends JFrame {


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


      public MyGraphicsShapeHomeWork() {
        super("Title"); 
        setBounds(600, 400, 700, 400);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);
    }

    @Override
    public void paint(Graphics g) {
        super.paint(g);
        Graphics2D g2 = (Graphics2D) g;

        g2.drawOval(40, 40, 90, 90); 

        Color newColor = new Color(255, 0, 0); 
        g2.setColor(newColor); 

        for (int i = 0; i < 50; i++) {
            int x =  (int) Math.ceil(Math.random() * 10);
            int y =  (int) Math.ceil(Math.random() * 10);            

                g2.fillOval(i+x, i+y, 3, 3);   // ???          

        }

    }    
}

Here is the result it produces:

enter image description here

How can I draw the dots within the circle only?

Upvotes: 0

Views: 1810

Answers (2)

gkgkgkgk
gkgkgkgk

Reputation: 717

For the position of the dots, generate random coordinates within the bounds of the outer circle. In order to generate these coordinates, the radius of the point from the center of the circle must be less than that of the outer circle. Get a random angle using

float a = Math.random() * Math.PI * 2; 

Then, subtract a random value from the outer radius:

outerR - (Math.sqrt(Math.random()) * outerR)

and assign the positions to:

double x = Math.cos(a)*newR;
double y = Math.sin(a)*newR;

I'm sure there is a more mathematical approach to this, but this was the simplest in my opinion.

Upvotes: 1

tenorsax
tenorsax

Reputation: 21233

To get a random point in a circle with radius R find a random angle and a random radius:

double a = random() * 2 * PI; 
double r = R * sqrt(random()); 

Then the coordinates of the point are:

double x = r * cos(a)
double y = r * sin(a)

Here are some notes about the drawing part. You should not paint directly on top level container such as JFrame. Instead, use JComponent or JPanel. Override paintComponent() for painting rather than paint() and don't forget to call super.paintComponent(g)

Take a look at Performing Custom Painting tutorial for more information.

Do not use setBounds(), override panel's getPreferredSize() and pack() the frame. Also, you rarely need to extend JFrame.

Here is a basic example that demonstrates drawing with a sub-pixel precision:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Ellipse2D;

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

public class TestDots extends JPanel{
    public static final int POINTS_NUM = 1000;
    public static final Color POINT_COLOR = Color.RED;

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

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

        Graphics2D g2 = (Graphics2D) g;

        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);

        double padding = 10;
        double radius = Math.min(this.getWidth(), this.getHeight()) / 2 - padding * 2;

        g2.draw(new Ellipse2D.Double(padding, padding, radius * 2, radius * 2));
        g2.setColor(POINT_COLOR); 

        for (int i = 0; i < POINTS_NUM; i++) {
            double a = Math.random() * 2 * Math.PI;
            double r = radius * Math.sqrt(Math.random());
            double x = r * Math.cos(a) + radius + padding;
            double y = r * Math.sin(a) + radius + padding;

            g2.draw(new Ellipse2D.Double(x, y, 1, 1));
        }
    }

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

Here is a result:

enter image description here

Upvotes: 4

Related Questions