How to detect overlapping circles and fill color a

2020-05-01 07:19发布

问题:

I created 5 circles with random x and y coordinates and radii using 3 arrays (for x, y and radius size). However, I need the circles to dynamically change color based on whether or not they overlap with another circle. So if one of the 5 circles doesn't overlap at all, it should be colored black. Overlapping circles should be cyan. Two circles are considered to overlap if the distance between their center points is less than the sum of their radii.

This is what I have written so far for the circles class. The following code will successfully draw the 5 circles in an applet window, and the distances are successfully calculated, but the problem is with the coloring. There's seems to be a logic error in the color filling and I don't see the problem here. Any suggestions? Thank you so much.

public class Circles extends Applet {

public void paint(Graphics page)
{
    Random locator = new Random();
    int [] xpt = new int [5];
    int [] ypt = new int [5];
    int [] rad = new int [5];

    setPreferredSize (new Dimension(300, 300));
    for (int i = 0; i < xpt.length; i++){

        xpt[i] = locator.nextInt(100); //need to set a number or it goes into millions, cannot set it in Random()
        ypt[i] = locator.nextInt(100);
        rad[i] = locator.nextInt(100);
        System.out.println("The #" + i +  " x-point: " + xpt[i] + " y-point: " + ypt[i] + " radius: " + rad[i]);  //for debugging purposes

        for (int j = 0; j < xpt.length; j++){
            double xpoint1 = xpt[i]+rad[i];
            double ypoint1 = ypt[i]+rad[i];
            double xpoint2 = xpt[j]+rad[j];
            double ypoint2 = ypt[j]+rad[j];
            double radius1 = rad[i];
            double radius2 = rad[j];
            double theDistance = distance(xpoint1,ypoint1,xpoint2,ypoint2); 
            System.out.println("Comparing " + i + " to " + j); //for debugging and logic checking
            if (i==j)
                ;
            else if (theDistance <= (radius1+radius2))
            {
                page.setColor(Color.cyan);
                page.fillOval(xpt[i], ypt[i], rad[i], rad[i]);
                //page.fillOval(xpt[j], ypt[j], rad[j], rad[j]);
                System.out.println("Overlap occurred. Colored " + i + " and " + j + " cyan.");
                System.out.println("Center points: ("+ xpoint1 +", "+ ypoint1 +") and ("+ xpoint2 + ", "+ ypoint2 + ").");
            }
            else  
            {
                page.setColor(Color.black);
                page.fillOval(xpt[i], ypt[i], rad[i], rad[i]);
                //page.fillOval(xpt[j], ypt[j], rad[j], rad[j]);
                System.out.println("No overlap. Made " + i + " and " + j + " black.");
            }
        }
    }
}

public static double distance(
        double x1, double y1, double x2, double y2) {
    return Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));

}
}

回答1:

The xpoint, ypoint, etc. lines are not doing what you think.

If you want to find if two circles are overlapping, you need to find if the distance between the centers of the circles is greater or less than the sum of their radii.

So:

function circlesCollide(x1, y1, r1, x2, y2, r2){
    return (distance(x1, y1, x2, y2) <= (r1 + r2));
}


回答2:

Why do you +rad[] here? You don't have to add the radius for comparing the distance.

        double xpoint1 = xpt[i]+rad[i];
        double ypoint1 = ypt[i]+rad[i];
        double xpoint2 = xpt[j]+rad[j];
        double ypoint2 = ypt[j]+rad[j];
 [...]
        double theDistance = distance(xpoint1,ypoint1,xpoint2,ypoint2); 
 [...]
        page.fillOval(xpt[i], ypt[i], rad[i], rad[i]);

You should use xpt / ypt for the distance. not xpoint1, and use - for value and 2 * radius for size ...... i.e.:

        double xpoint1 = xpt[i]-rad[i];
        double ypoint1 = ypt[i]-rad[i];
        double xpoint2 = xpt[j]-rad[j];
        double ypoint2 = ypt[j]-rad[j];
 [...]
        double theDistance = distance(xpt[i],ypt[i],xpt[j],ypt[j]); 
 [...]
        page.fillOval(xpoint1 , ypoint1, 2*rad[i], 2*rad[i]);