随机画圆,红色填充任何不与其他圆相交的圆。

4

  1. 程序启动时,绘制20个未填充圆,每个圆的半径和位置都是随机确定的。
  2. 如果一个圆的周长线段不与任何其他圆相交,则用红色绘制圆的轮廓。如果它与至少一个其他圆相交,则用黑色绘制它。
  3. 添加一个JButton,每次按下按钮时,都会创建一个新的圆集合,如上所述。

我已经完成了上面的1号和3号目标,但对于第二个目标感到困惑。

在介绍代码之前,让我来解释一下背后的数学。一个圆不与另一个圆相交有两种情况:

  1. 圆太远,不共享周长点,即它们中心点之间的距离大于它们半径的和(d > r1 + r2)。示例
  2. 一个圆完全在另一个圆内,它们的周长没有接触,即它们中心之间的距离小于它们半径的差(d < |r1 - r2|)。示例

我已经完成的部分:

  1. 要比较圆,必须在绘制之前指定它们,因此我使用for-loop将20个值存储在数组中,用于中心坐标(int[] x, int[] y)和半径(double[] radius)。
  2. 接下来,我使用嵌套的for-loop遍历数组并比较两个圆,除非一个圆与自身比较(索引j = 索引k)。如果圆相交,则g.setColor(Color.RED)。如果没有,则g.setColor(Color.BLACK)。

当我执行我的代码时,没有任何重叠的圆正确着色为红色。然而,一些重叠的圆也着成了红色。我假设它们在绘制时是无重叠的,在此之后才相交。如何修复代码以解决此时间上的差异?(问题区域位于IntersectingCircles类底部)

import java.awt.BorderLayout;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
import javax.swing.JFrame;
import javax.swing.JButton;

public class ButtonFrame extends JFrame 
{
    private final JButton resetButton = new JButton("Reset");

    public ButtonFrame()
    {
        super("Drawing Random Circles");
        setLayout(new BorderLayout());

        IntersectingCircles intersectingCircles = new IntersectingCircles();

        this.add(intersectingCircles, BorderLayout.CENTER);
        this.add(resetButton, BorderLayout.SOUTH);
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
        this.setSize(1400, 1400);

        ButtonHandler handler = new ButtonHandler();
        resetButton.addActionListener(handler);
    }

    private class ButtonHandler implements ActionListener
    {       
        @Override
        public void actionPerformed(ActionEvent event)
        {
            reset();
        }
    }

    public static void main(String[] args)
    {
        ButtonFrame buttonFrame = new ButtonFrame();
        buttonFrame.setVisible(true);
    }

    public void reset()
    {
        ButtonFrame buttonFrame = new ButtonFrame();
        buttonFrame.setVisible(true);
    }
}

class IntersectingCircles extends JPanel
{   
    private static final JButton resetButton = new JButton("Reset Circles");
    private static final JFrame frame = new JFrame("Intersecting Circles");

    @Override
    public void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        this.setBackground(Color.WHITE);

        int[] x = new int[20];
        int[] y = new int[20];
        int[] diameter = new int[20];
        double[] radius = new double[20]; 

        for (int i = 0; i < 20; i++)
        {
            int xCoord = (int)(Math.random() * 600);
            int yCoord = (int)(Math.random() * 600);
            int circleSize = (int)(Math.random() * 550);
            x[i] = xCoord;
            y[i] = yCoord;
            diameter[i] = circleSize;
            radius[i] = circleSize / 2.0;
        }

        for (int j = 0; j < 20; j++)
        {   
            for (int k = 0; k < 20; k++)
            {   
                if (k != j)
                {
                    if (((Math.sqrt((x[k] - x[j]) * (x[k] - x[j]) + (y[k] - y[j])
                        * (y[k] - y[j]))) > (radius[j] + radius[k])) ||
                        ((Math.sqrt((x[k] - x[j]) * (x[k] - x[j]) + (y[k] - y[j])
                        * (y[k] - y[j]))) < (Math.abs(radius[j] - radius[k]))))
                        g.setColor(Color.RED);
                    else
                        g.setColor(Color.BLACK);

                g.drawOval(x[j], y[j], diameter[j], diameter[j]);
                }
                else
                    continue;
            }
        }
    }
}

3
由于这是一项任务,我只会给出一个提示。彻底分开识别圆形重叠和标记圆形重叠为真/假的逻辑(步骤2)与绘制颜色边界(步骤3)。不要试图同时执行步骤2和3。 - paisanco
2
这种分离的示例可以在这里看到。 - trashgod
2
我已经完成了上面的目标#1和#3,但是我在目标#2上遇到了难题。假设您确定交集的方式没有限制,我建议您采用简单的方法来实现。请参考使用复杂形状进行碰撞检测获取一个可行的示例。 - Andrew Thompson
1个回答

2

在循环内的if语句中,您存在逻辑错误 - 您可以为其他一些圆对设置黑色,然后恢复为红色。 可能的解决方案草案:

  for (int j = 0; j < 20; j++)
    {   
        g.setColor(Color.RED);  //set non-intersect state
        for (int k = j + 1; k < 20; k++)  //avoid excessive work
        {   
                if (intersect test)
                  {
                    g.setColor(Color.BLACK);
                    break; //can stop here
                  };
            g.drawOval(x[j], y[j], diameter[j], diameter[j]);
        }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接