Блог пользователя ifsmirnov

Автор ifsmirnov, 14 лет назад, По-русски

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

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

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

Ну и наконец один вопрос из практики. Есть у нас два совпадающих квадрата с вершинами
2 -2
2 2
-2 2
2 2
Их сумма Минковского, если считать вторым методом - ожидаемый квадрат со стороной 8. Теперь сдвинем квадраты (при этом сумма Минковского тоже должна лишь сдвинуться на некоторый вектор!).
3 -1
3 3
-1 3
-1 -1

1 -2
1 2
-3 2
-3 -2
Снова считаем сумму Минковского вторым методом (не передвигая центры тяжести в начало координат) и получаем какой-то непонятный восьмиугольник. Значит, центр тяжести все-таки играет роль? Но если мы добавим несколько фиктивных точек на серединах сторон, то все опять съедет и появятся подобные баги.

Что я делаю не так? Буду благодарен, если поможете разобраться.
  • Проголосовать: нравится
  • +6
  • Проголосовать: не нравится

14 лет назад, # |
  Проголосовать: нравится +10 Проголосовать: не нравится
Про второй способ я ничего не знаю. Первый способ точно правильный. Нужно использовать ориентированные ребра (векторные разности последовательных вершин) и оба полигона обходить в одну сторону (по или против часовой стрелки).
14 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
Во втором способе вы забыли сделать обратный перенос. если первый многоугольник бил перенесен на вектор а1 а второй на а2 то найденной многоугольник нужнго перенести на вектор (-а1-а2).
  • 14 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    Да, спасибо, про перенос я забыл. Но меня больше волнует, почему фигуры получаются разной формы. Если перенести восьмиугольник на вектор, квадратом он от этого не станет.
    • 14 лет назад, # ^ |
      Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

      что значит разной форми ?
      >>Если перенести восьмиугольник на вектор, квадратом он от этого не станет.
      таково свойство паралельного переноса.

    • 14 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      Извините, не понял вопрос.
14 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
Второй способ неверен. Можно проверить на примере двух отрезков: (-1, -1) - (1, 1) и (-1, 1) - (1, -1).
Второй способ не внесёт изменений в картину. А ответ - квадрат с вершинами (2, 0), (0, 2 ), (-2, 0), (0, -2).
Центр масс важен для данного метода, но не для суммы Минковского.
  • 14 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    Вы видимо упустили вот это.
    "Для каждого луча возьмем векторную сумму точек пересечения его с обоими многоугольниками, это будет какая-то вершина их суммы Минковского."
    Если в Вашэм примере эл сделать, то все получиься как нада.

    • 14 лет назад, # ^ |
      Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

      Фраза в кавычках безусловно верна. Но обладает некоторой неполнотой, если мягко выразиться.
      У нас 4 вершины, значит луча тоже 4. Получаем 4 точки (векторные суммы), которые по совместительству являются концами наших отрезков. Что с ними потом делать, не описано. Поскольку мы хотим из нескольких точек сделать фигуру, я предположил, что дальше берётся выпуклая оболочка (это, вообще говоря, глупо, потому что искомая сумма не всегда является выпуклым множеством, но что ещё можно сделать с набором точек, ума не приложу). И мы получаем квадрат, да, но с неправильными вершинами: а именно теми же концами отрезков.
      • 14 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится
        Сумма Минковского от выпуклих множеств как мне кажеться должна бить випуклой. ;) Не так ли ?

        • 14 лет назад, # ^ |
            Проголосовать: нравится 0 Проголосовать: не нравится
          Ок, это я пост не прочитал. Только в моём примере они выпуклые и метод не работает.
          • 14 лет назад, # ^ |
            Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

            Почемуже ? Вы верное предложение сделали...

            "Поскольку мы хотим из нескольких точек сделать фигуру, я предположил, что дальше берётся выпуклая оболочка"

            В Вашем примере все работает.
            • 14 лет назад, # ^ |
                Проголосовать: нравится 0 Проголосовать: не нравится
              Ну хорошо, как из концов изначальных отрезков получаются вершины правильного ответа в моём примере?
              Можно сказать, что эти точки являются вершинами ответа. Но это то же самое, что выпуклая оболочка (если всё выпукло изначально).
              • 14 лет назад, # ^ |
                  Проголосовать: нравится 0 Проголосовать: не нравится
                как я понимаю.
                Точками пересечение будут концы отрезков. (-1, -1) - (1, 1) и (-1, 1) - (1, -1).
                Дальше нужно взять все возможние их сумми и найти выпуклую оболочку. Это и будет ответ.
                • 14 лет назад, # ^ |
                    Проголосовать: нравится 0 Проголосовать: не нравится
                  Нет, такой алгоритм, конечно, правильный, но имеет квадратичное время работы. Первый линеен.
                  Описан не такой метод. Про лучи внимательно прочитайте. Складывается не вершина с каждой вершиной из другого многоугольника, а вершина с некоторой точкой другого многоугольника.
                  • 14 лет назад, # ^ |
                      Проголосовать: нравится 0 Проголосовать: не нравится
                    Извините, за линию похоже єто не работает.
                  • 14 лет назад, # ^ |
                      Проголосовать: нравится 0 Проголосовать: не нравится
                    Действительно... Возможно это работает именно для многоугольников, а для отрезков уже нет,
                    • 14 лет назад, # ^ |
                        Проголосовать: нравится 0 Проголосовать: не нравится
                      Нет, это неважно. Можно сделать из этих отрезков тонкие прямоугольники и получить ту же фигню. Просто на отрезках виднее.
14 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
Первый способ должен работать. Да, он работает для двух ломаных, ограничивающих выпуклые многоугольники, получается тоже ломаная, ограничивающая результат. А чем он не нравится? Казалось бы, граница — самый простой способ задать многоугольник.

Пример применения для двух квадратов из поста: (-2, -2) -- (-2, +2) -- (+2, +2) -- (+2, -2) -- cycle.
Рёбра каждого квадрата имеют координаты (4, 0), (0, 4), (-4, 0), (0, -4).
Значит, получается многоугольник с рёбрами (8, 0), (0, 8), (-8, 0), (0, -8).
Теперь его надо построить из нужной точки, скажем, из суммы первых вершин каждого квадрата как векторов, то есть (-4, -4), и начиная с правильного ребра.

Во втором способе как минимум неверное предположение: центр масс многоугольника, если это не треугольник, не обязательно получается как среднее арифметическое отдельно по x и по y всех вершин.
  • 14 лет назад, # ^ |
      Проголосовать: нравится -13 Проголосовать: не нравится
    хмм... А можете привести пример где это не так? 
    • 14 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      “Это” — это про центр масс?

      На сторону треугольника ставим точку — четвёртую вершину. Реальный центр масс не изменился. А посчитанный как среднее арифметическое вершин сместился к поставленной точке.

      Если не нравится, что настоящих вершин всё ещё три — двигаем точку на eps наружу так, чтобы четырёхугольник стал строго выпуклым.
14 лет назад, # |
Rev. 4   Проголосовать: нравится 0 Проголосовать: не нравится

По мотивам второго метода придумал такой метод, он вроде правильный:
Пройдем по всем вершинам одного. Для каждой вершины найдем какой-нибудь вектор, смотрящий из нее "наружу", то есть находящийся между внешними нормалями смежных вершине сторон (например, возьмем векторную сумму этих сторон нормалей). Найдем во втором  полигоне вершину, самую далекую в этом направлении, то есть имеющую максимальное скалярное произведение с этим вектором. Сложим эти две вершины, добавим в ответ. Поменяем местами полигоны и сделаем то же самое. Получим в ответе множество вершин. Если идти везде по порядку, то можно во-первых искать соответствующую вершину бегущим указателем, во-вторых делать оба симметричных случая сразу (то есть не менять местами полигоны и не запускать второй раз), в-третьих сразу получать вершины в порядке обхода. Получается метод с той же идеей, что и первый, но сложнее в реализации.
  • 14 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    Метод. Только я бы сказал, что по мотивам первого. Отличие только в чисто геометрической технике. Что тут от второго - не понятно.
    И векторная сумма сторон не пойдёт (например когда угол тупой и одна сторона много короче другой).
    • 14 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      Не могу придумать контрпример к сумме. Вроде бы я даже доказал, что сумма этих векторов будет по внешнюю сторону от обеих сторон: каждый вектор лежит на своей стороне, и добавление к нему второго сдвинет его в нужную сторону, чтобы он оказался с внешней стороны.
      • 14 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится
        Во внешнюю сторону очевидно да, но не между нормалями. Для этого надо, например, нормали сложить.
        Но этого видимо и не надо, а вы имели с виду, что вектор должен быть между продолжениями сторон.
        • 14 лет назад, # ^ |
            Проголосовать: нравится 0 Проголосовать: не нравится
          Точно, следует складывать нормали, я перепутал с продолжениями сторон. Вектор дожен быть между нормалями (потому что этот вектор должен задавать такое напрвление, что эта вершина самая далекая в нем).
14 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
А где можно порешать пару задач на сумму Минковского? А то я во второй раз с этим сталкиваюсь, читаю какую-то теорию, но без практики особо чётко ничего не понимаю.