Расположите точки в определенных секторах круга, начиная с центра - PullRequest
0 голосов
/ 01 марта 2011

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

$dot[1] = secto12;
$dot[2] = secto6;
$dot[3] = secto8;
$dot[4] = secto2;
$dot[5] = secto8;
$dot[6] = secto3;
etc...

Мы могли бы использовать PHP или JavaScript.

Я могу представить себе функцию, имитирующую центростремительную силу. Или, может быть, какая-то процедура аналитической геометрии. Или что угодно ...

Любая идея приветствуется. THX .-

Ответы [ 5 ]

1 голос
/ 01 марта 2011

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

  1. Выберитезапуск тета наугад, в желаемом бин.Это расположение точки на «вершине» (краю круга).
  2. Для каждой точки, уже находящейся в ячейке, определите ее (угловое) расстояние до выбранной линии падения.Это простая геометрия, чтобы определить, с какой точкой будет сталкиваться падающая точка, и где она будет находиться, когда это произойдет.Этого достаточно для снежинок.
  3. Мрамор может скользить;посмотрите на соседей по неподвижной точке, со стороны которой касалась падающая точка.Мы можем определить, с каким соседом скользящая точка встретится первой.Смотреть на стены.(Мы не будем беспокоиться о том, чтобы подпрыгивать, смещать неподвижные точки или становиться в воздухе - сим не должен быть таким хорошим.)
  4. Если скользящая точка соприкасается с соседом на противоположной стороне, она останавливается.Если он вступает в контакт с той же стороны, он может свободно скользить по соседу - мы должны повторить предыдущий шаг.

PS Это даст довольно хорошую упаковку, которая, вероятно, все, что вам нужно. оптимальную упаковку действительно трудно найти.

1 голос
/ 01 марта 2011

Есть две половины этого: математика позиционирования точек и механизм рендеринга для отображения круга + точек.

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

Во второй половине я предлагаю изучить Raphael , библиотеку Javascript для простого рисования фигур и другой векторной графики с использованием SVG.

0 голосов
/ 24 марта 2011

enter image description here

Решение, которое я использовал, немного сложнее. И не является общим. Нам нужно вычислить определенные вещи вручную ($ factor (вариации углов) и $ dots (количество точек для рисования на определенном радиусе)).

Но я хочу дать основные идеи для кого-то, кому нужно нечто подобное:

1 .- Мы используем уравнение, которое находит заданную точку:
0.- центральная точка: ($ x0, $ y0)
1.- радиус: $ r
2.- угол: $ угол

$x = floor($x0 + $r * sin($angle * pi() / 180));
$y = floor($y0 + $r * -cos($angle * pi() / 180));

2 .- Мы наносим точки (определенное количество точек), меняя радиус и угол
Количество точек зависит от радиуса. Больше радиуса, больше точек. Нам нужно определить функцию, которая рисует точки сектор за сектором.

3 .- Нам нужно вычислить некоторые вещи вручную ($ factor (вариации углов) и $ dots (количество точек для рисования на определенном радиусе)). Вот оно:

if ($r >= 90) {
    $dots = 4;
    $factor = 12.1;
}
if ($r >= 100) {
    $dots = 4;
    $factor = 12.4;
}
if ($r >= 110) {
    $dots = 5;
    $factor = 8.4;
}
if ($r >= 120) {
    $dots = 6;
    $factor = 6.2;
}
if ($r >= 130) {
    $dots = 7;
    $factor = 5.2;
}
if ($r >= 140) {
    $dots = 8;
    $factor = 4.4;
}
if ($r >= 150) {
    $dots = 9;
    $factor = 3.8;
}
if ($r >= 200) {
    $dots = 10;
    $factor = 3.40;
}
if ($r >= 220) {
    $dots = 11;
    $factor = 3.0;
}

Это основные идеи, чтобы решить это, хитрым способом.

4 . Очевидно, этот код (внутри функции) должен вызываться внутри вложенных циклов (в моем случае 3)

function plot($sector, $start) {
    ....
}

$ start - угол от начала рисования: 0, 30, 60, ..., 330

??? ОК, вот функция. Наслаждайтесь:

function plot($sector, $start) {

    static $static;
    $x0 = 0;
    $y0 = 0;

    if ( ! isset($static[$sector])) {
        /*
         * factor: related to the amplitude of the arc on which dots are drawn. (11.1 -> 3.0)
         * dots: how many dots draw towards the right. (3 -> 10)
         * r: radius in pixels. (60 -> 240)
         * jstatic: save last position of dot drawn.
         *
         */
        $static[$sector]['factor'] = 11.1;
        $static[$sector]['dots'] = 4;
        $static[$sector]['r'] = 60;
        $static[$sector]['jstatic'] = 0;
    }

    $factor = $static[$sector]['factor'];
    $dots = $static[$sector]['dots'];
    $r = $static[$sector]['r'];
    $jstatic = $static[$sector]['jstatic'];

    for ($j = $jstatic; $j < $dots; $j ++ ) {
        if ($r >= 90) {
            $dots = 4;
            $factor = 12.1;
        }
        if ($r >= 100) {
            $dots = 4;
            $factor = 12.4;
        }
        if ($r >= 110) {
            $dots = 5;
            $factor = 8.4;
        }
        if ($r >= 120) {
            $dots = 6;
            $factor = 6.2;
        }
        if ($r >= 130) {
            $dots = 7;
            $factor = 5.2;
        }
        if ($r >= 140) {
            $dots = 8;
            $factor = 4.4;
        }
        if ($r >= 150) {
            $dots = 9;
            $factor = 3.8;
        }
        if ($r >= 200) {
            $dots = 10;
            $factor = 3.40;
        }
        if ($r >= 220) {
            $dots = 11;
            $factor = 3.0;
        }

        if ($j == $dots - 1) {
            $j = 0;
            $jstatic = 0;
            // increase radius (by 10 pixels --each dot have 7 pixel of diameter) to the next arc.
            $r = $r + 10;
        }

        // stop if circumference is reached.
        if ($r > 240)
            break;

        $angle = $factor * $j + $start;

        // (x, y) is...
        $x = floor($x0 + $r * sin($angle * pi() / 180));
        $y = floor($y0 + $r * -cos($angle * pi() / 180));

        $pos['x'] = $x;
        $pos['y'] = $y;

        $jstatic ++;

        // save all dat by each sector
        $static[$sector]['factor'] = $factor;
        $static[$sector]['dots'] = $dots;
        $static[$sector]['r'] = $r;
        $static[$sector]['jstatic'] = $jstatic;

        /*
         * only for debugging:
         * counting how many dots are drawn
          static $countDots = 0;
          global $countDots;
          $countDots++;
         */
        return $pos;
    }
}
0 голосов
/ 08 марта 2011

Это довольно просто решить с помощью sfc или кривой Гильберта или кода Грея. На самом деле кривая Гильберта является гамильтоновым обходом графа, и таким образом генерируется серый код. Вы можете искать в сети информацию о сером коде и о том, как он используется для правильного определения секторов на жестком диске. Если для решения этой проблемы использовать кривую Гильберта, то ее ограничения заключаются в том, что круг должен покрывать плоскость степени 2. Другая проблема состоит в том, что она является только приближенной, но очень хорошей.

0 голосов
/ 02 марта 2011

Создание физического движка для имитации кругов и стен, хотя и более сложное, чем вы ожидали, не очень сложно. Если вы используете интеграцию Verlet для контроля местоположения и скорости движения шариков, столкновения между шариками и между шариками и стенками сегмента становятся тривиально простыми - вы просто перемещаете оскорбительные шарики на минимальное расстояние, необходимое для разрешения столкновения. Ответ на столкновение - потеря скорости и т. Д. Обрабатывается неявно.

Вы настроили бы свою систему таким образом, чтобы шарики были притянуты к центру круга и были вынуждены остаться:

  1. На некотором расстоянии от центра
  2. В пределах своего сегмента
  3. На некотором расстоянии от других шаров

Простое физическое моделирование обеспечит хорошую упаковку для шаров, и вы получите классную анимацию бесплатно.

Это является хорошим объяснением подхода (все, что касается раздела "Твердые тела", уместно)

...