Закрепите сегмент линии на многоугольник в C#

В этом примере найдены фрагменты сегмента линии, которые лежат внутри и снаружи многоугольника. Он рисует части сегмента, которые лежат вне многоугольника с розовым фоном, и он рисует части сегмента внутри полигона желтым цветом.

Основная идея состоит в том, чтобы найти все точки пересечения между отрезком линии и краями многоугольника. Метод FindIntersection, используемый в этом примере, вычисляет значение t между 0.0 и 1.0, которое указывает положение точки пересечения вдоль сегмента линии. Значение 0.0 означает, что пересечение находится в первой конечной точке сегмента, 1.0 означает, что пересечение находится во второй конечной точке сегмента, а значения между 0.0 и 1.0 означают, что пересечение находится между ними.

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

В следующем коде показан метод ClipLineWithPolygon, который находит точки пересечения.

// Возвращаем точки, в которых сегмент входит и выходит из многоугольника.
private PointF[] ClipLineWithPolygon(
    out bool starts_outside_polygon,
    PointF point1, PointF point2,
    List polygon_points)
{
    // Создание списков для хранения точек
    // пересечение и их значения t.
    List intersections = new List();
    List t_values = new List();

    // Добавить начальную точку сегмента.
    intersections.Add(point1);
    t_values.Add(0f);
    starts_outside_polygon =
        !PointIsInPolygon(point1.X, point1.Y,
            polygon_points.ToArray());

    // Исследуем края многоугольника.
    for (int i1 = 0; i1 < polygon_points.Count; i1++)
    {
        // Получим конечные точки для этого ребра.
        int i2 = (i1 + 1) % polygon_points.Count;

        // Смотрите, где край пересекает сегмент.
        bool lines_intersect, segments_intersect;
        PointF intersection, close_p1, close_p2;
        float t1, t2;
        FindIntersection(point1, point2,
            polygon_points[i1], polygon_points[i2],
            out lines_intersect, out segments_intersect,
            out intersection, out close_p1, out close_p2,
            out t1, out t2);

        // Смотрите, пересекает ли отрезок ребро.
        if (segments_intersect)
        {
            // Смотрите, нужно ли записывать это пересечение.

            // Записываем это пересечение.
            intersections.Add(intersection);
            t_values.Add(t1);
        }
    }

    // Добавить конечную точку сегмента.
    intersections.Add(point2);
    t_values.Add(1f);

    // Сортируем точки пересечения по значению t.
    PointF[] intersections_array = intersections.ToArray();
    float[] t_array = t_values.ToArray();
    Array.Sort(t_array, intersections_array);

    // Вернем пересечения.
    return intersections_array;
}

Этот метод достаточно понятен.

Информацию о методе PointIsInPolygon см. в сообщении Определить, находится ли точка внутри многоугольника в C# .

Информацию о методе FindIntersection см. в сообщении Определить, где две строки пересекаются в C# .

Источник: http://csharphelper.com/blog/2016/01/clip-a-line-segment-to-a-polygon-in-c/

1 Звезда2 Звезды3 Звезды4 Звезды5 Звезд (Пока оценок нет)
Adblock
detector