Существует несколько различных способов сделать это в зависимости от требуемой производительности и точности, а также объема геометрического кода, который вы готовы написать.
1. Использование FillContains
Один из способов - построить последовательную геометрию линии и использовать path.Data.FillContains (геометрия), чтобы определить, пересекают ли они фигуру. Что-то вроде этого:
Transform rotation = new RotateTransform { Angle = 30 };
double max = path.Width + path.Height;
double current = 0;
for(double delta = max/2; delta > 0.25; delta = delta/2)
{
var line = new LineGeometry(
new Point(centerX + current, centerY),
new Point(centerX + max, centerY),
rotation);
if(path.Data.FillContains(line))
current += delta;
}
var intersectPoint = rotation.Transform(new Point(current, 0));
2. Использование GetFlattenPathGeometry
Другой способ - использовать GetFlattenPathGeometry:
var flattened = path.Data.GetFlattenedPathGeometry();
var segment = pg.Figures[0].Segments[0] as PolyLineSegment;
Point[] points = segment.Points;
for(int i=0; i<points.Count-1; i++)
{
... check for intersection with the line from points[i] to points[i+1] ...
}
Это может быть быстрее, потому что геометрия обрабатывается только один раз, но требует от вас написания собственного алгоритма пересечения линий (который очень прост).
3. Использование PathGeometry.CreateFromGeometry
Самый эффективный способ - преобразовать данную геометрию в PathGeometry, а затем вручную выполнить итерации по фигурам и сегментам в геометрии:
var geo = PathGeometry.CreateFromGeometry (path.Data);
foreach (var figure in geo.Figures)
foreach (var сегмент на рисунке. Сегменты)
if (сегмент это LineSegment)
...
иначе, если (сегмент является ArcSegment)
...
иначе, если (сегмент является BezierSegment)
...
иначе, если (сегмент является QuadraticBezierSegment)
...
иначе, если (сегмент является PolyLineSegment)
...
иначе, если (сегмент является PolyBezierSegment)
...
иначе, если (сегмент является PolyQuadraticBezierSegment)
...
Этот подход требует довольно большого количества кода для геометрического анализа, но он чрезвычайно быстр, потому что WPF не нужно создавать сглаженную геометрию или повторять пересечения. Это техника, которую я обычно использую, когда мне нужно, чтобы мой код работал очень быстро.
Примечание по GetWidenedPathGeometry
Все, что я сказал до сих пор, даст вам пересечения между данными геометрического пути и вашей пересекающейся линией: оно не учитывает ширину линии, концевые заглавные буквы и т. Д. Чтобы принять это во внимание, вам необходимо GetWidenedPathGeometry
следующим образом:
var widenedData = path.Data.GetWidenedPathGeometry(new Pen { ... });
Где параметры Pen задаются из path.Stroke, path.StrokeWidth и т. Д.
После этого используйте один из вышеперечисленных приемов, заменив «path.Data» на «widenedData».