Вычисление каждой декартовой точки в круге - PullRequest
2 голосов
/ 25 марта 2012

У меня есть массив: int [] [] lawn = new int [980] [1280];

, в котором хранятся значения высоты ножей на газоне.

В моем симуляции у меня есть робот, который обходит газон и режет ножи.

мой робот имеет форму круга с диаметром (rDiameter).Система координат выполнена с помощью Double, а мой газон находится в целых числах.

Я разработал два "алгоритма", которые позволяют роботу подстригать газон, но я не удовлетворен, потому что точность моих алгоритмов не высокахватит и производительности тоже.

Мой вопрос, есть ли способ сделать это, кроме идей, о которых я уже подумал?

Или мне нужно изменить реализацию моегогазон, чтобы получить лучшие результаты?

Не стесняйтесь спрашивать что-нибудь, если я не достаточно ясно.

Вот код для моих двух алгоритмов (k означает робот), centerPosition возвращает центрмоего робота (так что центр круга)

approach with square
    int bottomLeftCornerX = (int) (k.getCenterPosition().getX() - simulParams.getKDiameter() / 2);
    int bottomLeftCornerY = (int) (k.getCenterPosition().getY() - simulParams.getKDiameter() / 2);

    for (int i = bottomLeftCornerX; i < bottomLeftCornerX + simulParams.getKDiameter(); i++) {
        for (int j = bottomLeftCornerY; j < bottomLeftCornerY + simulParams.getKDiameter(); j++) {
            ((LawnArea) lawn.getBladeHeight()).cutBladeInArea(j, i);
        }
    }

А вот тот, с подходом круга (в основном это формула окружности, присутствующая в Википедии ...):

for (int r = 0; r < simulParams.getKDiameter() / 2; r++) {

        for (double t = 0; t < 2 * Math.PI; t = t + 0.1) {
            Point2D p = circumference(k.getCenterPosition().getX(), k.getCenterPosition().getY(), t, r);
            int intX = (int) Math.ceil(p.getX());
            int intY = (int) Math.ceil(p.getY());
                ((LawnArea) lawn.getBladeHeight()).cutBladeInArea(intY, intX);
            }
        }
    }

Ответы [ 2 ]

1 голос
/ 25 марта 2012

Первый подход (основанный на ограничительной рамке) - хорошее начало. Но теперь вам просто нужно добавить условие, которое проверяет, находится ли каждая точка внутри ограничительной рамки также в круге.

Что-то вроде:

for each (point p inside bounding-box) {
    if (p inside circle centred at k) {
        cutBlade(p);
    }
}

Вы можете улучшить это, заметив, что в каждом ряду (или столбце) ограничительной рамки набор лезвий, которые необходимо разрезать, являются соседними. Если вы рассчитываете конечные точки этого диапазона, вам не нужны никакие условия.

Что-то вроде:

for each (x inside bounding-box) {
    calculate y_first;
    calculate y_last;
    for (y = y_first; y < y_last; y++) {
        cutBlade(x,y);
    }
}
0 голосов
/ 26 марта 2012

Для удобства чтения: k.x - это координата x, k.y - это координата y, k.r - радиус.

for(int y = (int)Math.max(0, Math.ceil(k.y - k.r)); y <= (int)Math.min(980, Math.floor(k.y + k.r)); y++) {
    doulbe dx = Math.sqrt(k.r * k.r - Math.abs(y-k.y) * Math.abs(y-k.y));
    for(int x = Math.max(0, (int)Math.ceil(k.x - dx)); x <= (int)Math.min(1280, Math.floor(k.x + dx)); x++) {
        cut(x,y);
    }
}

Существует два цикла:Первый предназначен для координаты y и начинается в k.y - k.r и продолжается до k.y + k.r, если круг находится на поле полностью (я не знал, всегда ли это было, если да, то вы не можете добраться до углов), так что сверху вниз ваш экран.Второй для координаты х.Наименьшее и наибольшее x вычисляются с помощью формул (kx - x) ² + (ky - y) ² = k.r².При этом вы получаете только очки в вашем круге.Это немного меньше из-за преобразования double в int.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...