Как написать алгоритм спирали?

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

Есть массив координат точек с координатами xy, которые совпадают. Надо расположить эти точки по спирали вокруг первоначальной координаты.

По факту - есть набор событий в Google Maps, которые указывают в 1 точку и надо их расположить вокруг этой точки по спирали, чтобы можно было видеть каждый маркер. Правда, там рядом тоже есть точки другие и надо избежать новых перекрытий, но это уже моя проблема :)
  • Вопрос задан
  • 10782 просмотра
Пригласить эксперта
Ответы на вопрос 7
icelaba
@icelaba
Знаю и умею всё
Заходите сюда
ru.wikipedia.org/wiki/%D0%90%D1%80%D1%85%D0%B8%D0%...

Если спираль устраивает
записываете r = k*phi
x = r*cos(phi)
y = r*sin(phi)

предположим точек N
for(i=0;i!=N;++i){
phi =i*some_const;
r = k*i;
x = r*cos(phi)
y = r*sin(phi)
draw(x,y, "что вы тут хотите рисовать")
}
константы
k some_const подбираете сами
Ответ написан
metamorph
@metamorph
В изложении своих мыслей Вы, к сожалению, тоже не сильны.

Что такое "с координатами xy, которые совпадают"? С чем совпадают?
Что за "первоначальная координата"? Она как-то задается?
А события, указывающие в одну точку - это вообще что?..
Ответ написан
iiil
@iiil
Инженер и вэб-дизайнер, рисую.
Вот пример на jQuery. Честно говоря, я не понял, на чем Вам надо ) Сначала написал, а потом подумал. Ну алгоритм в примере Вы можете посмотреть, а на нужный язык перепишете сами )
jsfiddle.net/iiil/yLTnx/22
Ответ написан
@Mercury13
Программист на «си с крестами» и не только
Думаю, проще всего делать не спираль Архимеда, а её приближение методом Эйлера. Пусть у нас есть некое расстояние dSafe, на котором должны быть кружочки друг от друга.

Чтобы поставить второй кружочек, отойдём от центрального на вектор (dSafe, 0). Для третьего и дальше поступим так.

Найдём угол касательной к спирали Архимеда. Касательный вектор будет a единиц по радиус-вектору (a — коэффициент спирали r=aф) и r единиц по нормали. Таким образом, если мы в точке (x, y), у нас получается касательный вектор вот такой.
t = (a·x + r·y; a·y − r·x), r = sqrt(x² + y²)

Нормируем этот вектор до длины dSafe и добавляем к (x, y).
Штука номер один. Параметр спирали прямо пропорционален безопасному расстоянию (вы это увидите ниже в коде). И штука номер два — только «бесконечно малые» шаги (при нулевом a, т. е. окружность) будут держать нас на окружности, шаги побольше будут выносить нас наружу, для компенсации сделаем a отрицательным.

Вот действующий код (на C++ Builder’е)

namespace {

const double dSafe = 30;
const int rSafe = dSafe / 2;
const double a = -0.3 * dSafe;

int toPixel(double x)
{
    return floor(x + 0.5) + 200;
}

}

void TfmMain::drawPoint(double x, double y)
{
    int xx = toPixel(x);
    int yy = toPixel(y);
    Canvas->Ellipse(xx - rSafe, yy - rSafe, xx + rSafe, yy + rSafe);
}

void __fastcall TfmMain::FormPaint(TObject *Sender)
{
    Canvas->Brush->Style = bsClear;
    Canvas->Pen->Color = clBlack;

    double x = 0, y = 0;
    drawPoint(x, y);
    x += dSafe;
    drawPoint(x, y);

    for (int i = 0; i < 120; ++i) {
        double r = sqrt(x*x + y*y);
        double tx = a*x + r*y;
        double ty = a*y - r*x;
        double tLen = sqrt(tx*tx + ty*ty);
        double k = dSafe / tLen;
        x += tx * k;
        y += ty * k;
        drawPoint(x, y);
    }
}
Ответ написан
@Mercury13
Программист на «си с крестами» и не только
И ещё одна штука. Две-семь точек надо располагать по-другому (одна в центре, остальные по кругу на расстоянии dSafe от неё; ну или на худой конец подобрать коэффициент a, чтобы спираль расходилась лишь чуть-чуть). Для восьми-одиннадцати точек надо подбирать индивидуальные a. И только для двенадцати и более подходит a = −0,3·dSafe.
Ответ написан
@do6rolet
import turtle
import math
turtle.shape('turtle')
k=0.1
rad=0.1
# рассчет идет по формуле p=k*ф;
# переход из полярной системы координат в декартовую осуществляется
# по формулам: x=p*cosф y=p*sinф
# cos&sin вычисляем через радианы, и приращение перемещения задаем
# через увелечение переменой rad
for i in range (500):
x=k*math.degrees(rad)*math.cos(rad) # тело цикла. при публикации съедаются пробелы
y=k*math.degrees(rad)*math.sin(rad) # тело цикла
turtle.goto(x,y) # тело цикла
rad+=0.1 # тело цикла
turtle.exitonclick() # выход из черепашки по клику
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы