Это очень хороший вопрос.Я реализовал тот же алгоритм на C # некоторое время назад.Алгоритм строит общий контур из двух многоугольников (т.е. строит объединение без дырок).Вот оно.
Шаг 1. Создайте график, описывающий многоугольники.
Ввод: первый многоугольник (n точек), второй многоугольник (м баллов).Выход: график.Вершина - точка многоугольника точки пересечения.
Мы должны найти пересечения.Выполните итерацию всех сторон многоугольника в обоих многоугольниках [O (n * m)] и найдите любые пересечения.
Если пересечение не найдено, просто добавьте вершины и соедините их с ребром.
Если найдены какие-либо пересечения, отсортируйте их по длине до начальной точки, добавьте все вершины (начало, конец и пересечения) и соедините их (уже в отсортированном порядке) с ребром.
Шаг 2. Проверка построенного графа
Если мы не нашли точек пересечения при построении графа, мы имеем одно из следующих условий:
- Полигон1 содержит полигон2 - возвратный полигон1
- Полигон2 содержит полигон1 - возвратный полигон2
- Полигон1 и полигон2 не пересекаются.Вернуть polygon1 И polygon2.
Шаг 3. Найти левую нижнюю вершину.
Найти минимальные координаты x и y (minx, miny).Затем найдите минимальное расстояние между (minx, miny) и точками многоугольника.Эта точка будет левой нижней точкой.
Шаг 4. Построение общего контура.
Мы начинаем проходить график с левой нижней точки и продолжаем, пока не вернемся к нему.В начале мы отмечаем все ребра как непосещенные.На каждой итерации вы должны выбрать следующую точку и отметить ее как посещенную.
Чтобы выбрать следующую точку, выберите ребро с максимальным внутренним углом в направлении против часовой стрелки.
Я рассчитываю два вектора: вектор1 для текущего ребра и вектор2 для каждого следующего не посещенного ребра (какпредставлены на рисунке).
Для векторов я рассчитываю:
- Скалярное произведение (точечное произведение).Возвращает значение, связанное с углом между векторами.
- Векторное произведение (перекрестное произведение).Возвращает новый вектор.Если z-координата этого вектора положительна, скалярное произведение дает мне прямой угол в направлении против часовой стрелки.Иначе (z-координата отрицательна), я рассчитываю получить угол между векторами как 360 - угол от скалярного произведения.
В результате я получаю ребро (и соответствующую следующую вершину) с максимальным углом,
Я добавляю в список результатов каждую пройденную вершину.Список результатов - многоугольник объединения.
Замечания
- Этот алгоритм позволяет объединить несколько полигонов - применять итеративно с парами полигонов.
- Если у вас есть путь, состоящий измного кривых и линий Безье, вы должны сначала сгладить этот путь.