2016-12-14 3 views
2

Учитывая две (очень упрощенным) классов:Перебор всех (I, J) -элементов в круге

class Rectangle { 
    public: 
    int iL,jL; // lower left point of rectangle 
    int width, length; // width: in i-direction, length: in j-direction 
}; 

class Circle { 
    public: 
    int iC,jC; // center-point of circle 
    int radius; 
}; 

Если я хочу, чтобы перебрать все элементы в Rectangle, я могу просто сделать это:

for (int i = iL; i < iL-width; i--) 
    for (int j = jL; j < jL+length; j++) 
    doSomething(); 

Моя проблема заключается в реализации смарт способ перебора всех элементов в Circle. Мое текущее решение выглядит следующим образом:

for (int i = iC-radius; i <= iC+radius; i++) 
    for (int j = jC-radius; j <= jC+radius; j++) 
    if (sqrt(pow(i-iC,2)+pow(j-jC,2)) <= r) // checking if (i,j) lies within the circle (or its boundary) 
     doSomething(); 

Однако для получения radius большой мое текущее решение является очень дорогим по времени (так как я прикасаюсь много элементов, которые не находятся в Circle и так как я всегда нужно оценивать pow) , Можете ли вы подумать о более интеллектуальном и эффективном способе итерации по всем Circle -элементам?

+0

[полярная система координат] (https://en.wikipedia.org/wiki/ Polar_coordinate_system) – Drop

+0

Итак, у меня есть дискретная 2D-форма (с i, j-точками), где лежат несколько кругов и прямоугольников. Если я использую полярные координаты, у меня возникает такая же проблема: как я должен перебирать угол \ phi? Мне нужно. (psuedocode :) 'for (double phi = 0; phi <360; phi ++)', и это невозможно. – Kapa11

+0

http://stackoverflow.com/a/7227057/6313992 –

ответ

4

Для каждой строки найдите первый столбец, принадлежащий кругу, и перейдите от этого столбца к одному зеркальному относительно центра круга. Псевдокод

for (int iy = - radius to radius; iy++) 
    dx = (int) sqrt(radius * radius - iy * iy) 
    for (int ix = - dx to dx; ix++) 
     doSomething(CX + ix, CY + iy); 
+0

Спасибо, я проверю это. Но я буду менять ix- и iy-loop для улучшения локальности кэша :) – Kapa11

+0

Emm ... На большинстве языков (включая C++) 2D-массивы хранятся «по строкам», поэтому обычно описывается порядок. Возможно, вы имеете в виду некоторые другие обстоятельства, хотя ... – MBo

+0

Но в вашем фрагменте кода вы выполняете итерацию по каждому y (j-направлению), а затем по каждому x (i-направлению). Таким образом, для каждого столбца вы проверяете каждую строку. Но, как вы сказали, проверка каждой строки одна за другой будет лучше – Kapa11

0

Пусть радиус круга равен r. Рассмотрим квадрат размера (2r + 1) * (2r + 1) вокруг круга, который нужно нарисовать. Таким образом, эквидистантные точки в квадрате сохраняются в 2D-массиве.

Теперь пройдите через каждую точку внутри квадрата. Для каждой точки (x, y), если (x, y) лежит внутри круга (или x^2 + y^2 < r^2), напечатайте ее. Например, равноудаленные друг от друга точек образуют массив 10x10, и выбранный «центр» массива в точке (х, у):

for i from 0 to 9 { 
    for j from 0 to 9 { 
     a = i - x 
     b = j - y 
     if a*a + b*b <= r*r { 
      // Do something here 
     } 
    } 
} 
+0

Разве это не то, что я делаю в данный момент, и код, который мне не нравится с ?!?! – Kapa11

Смежные вопросы