检测点是否在正方形中的圆子集内

时间:2016-01-25 10:31:19

标签: php math collision-detection

我需要在网格中的圆圈内绘制图像。

请参见下面的网格/圆圈图片。

Example of grid

绿色圆圈是容器,不应在外面绘制图像。

见下面的例子。紫色方块=没有放置,黄色方块=放置(因为它们在绿色圆圈内并且它们将适合)。

彩色方块代表将要放置的图像。

正方形是50x50。网格图块为100x100。

Example where images should be placed.

目前,我的程序将生成圆形,网格并在每个网格图块内标记X,无论它是否在容器圆内。

请参阅下面的程序工作和放置图像的示例。

如果图像适合圆圈内的图块,我该怎么办?

图块不一定是圆圈内的100%。见第二张图片。请参阅中间底部的瓷砖。瓷砖略微突出圆圈,但图像50x50仍然可以放在瓷砖内。

请参阅下面的函数,将X放在每个网格中。 Current implementation

public function placeImages()
{
    $boxes = 5;
    $circumference = 700;
    $width = ($circumference / $boxes);

    $this->grid = array(
        array(
            'width'  =>
                array(
                    'x1' => 0,
                    'y1' => 0,
                    'x2' => 700,
                    'y2' => 0,
                ),
            'height' =>
                array(
                    'x1' => 0,
                    'y1' => 0,
                    'x2' => 0,
                    'y2' => 700,
                ),
        ),
        array(
            'width'  =>
                array(
                    'x1' => 0,
                    'y1' => 140,
                    'x2' => 700,
                    'y2' => 140,
                ),
            'height' =>
                array(
                    'x1' => 140,
                    'y1' => 0,
                    'x2' => 140,
                    'y2' => 700,
                ),
        ),
        array(
            'width'  =>
                array(
                    'x1' => 0,
                    'y1' => 280,
                    'x2' => 700,
                    'y2' => 280,
                ),
            'height' =>
                array(
                    'x1' => 280,
                    'y1' => 0,
                    'x2' => 280,
                    'y2' => 700,
                ),
        ),
        array(
            'width'  =>
                array(
                    'x1' => 0,
                    'y1' => 420,
                    'x2' => 700,
                    'y2' => 420,
                ),
            'height' =>
                array(
                    'x1' => 420,
                    'y1' => 0,
                    'x2' => 420,
                    'y2' => 700,
                ),
        ),
        array(
            'width'  =>
                array(
                    'x1' => 0,
                    'y1' => 560,
                    'x2' => 700,
                    'y2' => 560,
                ),
            'height' =>
                array(
                    'x1' => 560,
                    'y1' => 0,
                    'x2' => 560,
                    'y2' => 700,
                ),
        ),
        array(
            'width'  =>
                array(
                    'x1' => 0,
                    'y1' => 700,
                    'x2' => 700,
                    'y2' => 700,
                ),
            'height' =>
                array(
                    'x1' => 700,
                    'y1' => 0,
                    'x2' => 700,
                    'y2' => 700,
                ),
        ),
    );

    //This removes the grid item for the bottom and right lines, not needed within the loop.
    array_pop($this->grid);

    foreach ($this->grid as $grid) {
        $x = $grid['width']['x1'];
        $y = $grid['width']['y1'];

        for ($j = 0; $j < $boxes; $j++) {
            $this->drawLine($x, $y, ($x + $width), ($y + $width), '#ff3200');
            $this->drawLine(($x + $width), $y, $x, ($y + $width), '#ff3200');

            //50 × 50 = Image size
            $imageX = floor($x + ($width - 50) / 2);
            $imageY = floor($y + ($width - 50) / 2);;


            $image = Image::make(base_path('test.png'))->opacity(50);

            $this->image->insert($image, 'top-left', $imageX, $imageY);

            $x = $x + $width;
        }
    }
}

上面的代码是我程序的简化版本。网格数组是动态生成的,但我不认为这对这个问题很重要。

4 个答案:

答案 0 :(得分:1)

只要点在圆圈内,该等式就满足:

  

(x-center_x)^ 2 +(y-center_y)^ 2&lt;半径^ 2

所以你应该在插入图像之前检查它。

对于所有角落,您只会检查其中一个角落,具体取决于您的图表的四分之一。 f.e,右上角,image_x为$ x,image_y为$ y(whitout保持宽度并除以2)。左下角, - $ x,$ -y。

更详细,检查边界。考虑到圆被放置在(0,0)并且半径为700:

$bounding_x = $x;
$bounding_y = $y;

if($x > 0)
   $bounding_x += width;

if($x < 0)
   $bounding_x -= width;

if($y > 0)
   $bounding_y += width;

if($y < 0)
   $bounding_y -= width;

if ($bounding_x*$bounding_x + $bounding_y*$bounding_y < 490000)
//....insert image

答案 1 :(得分:1)

查找正方形是否在圆内的基本理论是检查它的所有四个角是否都在圆内。对于瓷砖和图像占位符都是如此。

圈子的属性

您需要先找到半径(r)和中心(cx,cy)。如果我们认为你的右上角是(0,0),那么:

radius = circumference / (pi * 2)    //considering 2(pi)r = circumference

cx, cy = (r, -r)    //your center is r away from the top-right 

检测

现在你应该浏览你的数组,看看所有瓷砖的所有角落是否都在圆圈内。让我们看看如何检测单个点是否在圆圈内。

function withinCircle(x, y) {       

   return ((r - x)*(r - x) + (y - r)*(y - r) < r * r) ;       

}

该函数测试点的xy坐标是否在半径之外。您的圆圈在飞机的270-360范围内的事实被认为是标志。

答案 2 :(得分:0)

您可以测试方块的角是否在圆圈内。 如果正方形的一个顶点是(a,b), 你将无法将其绘制为sqrt(a ^ 2 + b ^ 2)&gt;半径。

假设圆的中心具有坐标(0,0),如果不是这样,并且圆具有坐标(x,y),我们需要将所有点移动(-x, - y),在这种情况下,测试是:

sqrt((a-x)^ 2 +(b-y)^ 2)&gt;半径。

答案 3 :(得分:-1)

我假设圆圈由边界框(0,0)->(2r,2r)定义,并且方形为(x1,y1)->(x2,y2)

执行测试的有效方法是检查距离中心最远的角落是否位于圆圈内。

if (x1 < r) dx= r - x1; else dx= x2 - r;
if (y1 < r) dy= r - y1; else dy= y2 - r;
if dx * dx + dy * dy <= r * r
    // Wholly inside