Закрепите сегмент линии на многоугольник в 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# .
