В настоящее время я пытаюсь сделать то же самое, так что вот мой план, а также некоторые мыслительного процесса.
Во-первых, преобразуйте все в PathGeometries. Метод FillContains(Geometry geometry)
- это то, что я хочу использовать, чтобы увидеть, что внутри чего. Проблема с .Bounds.Contains
заключается в том, что если у вас есть форма C с точкой посередине, точка будет содержаться в ограничивающем прямоугольнике, но не в форме.
Затем создайте структуру данных дерева. Если PathGeometry A содержит PathGeometry B, A будет предком B в дереве. Другой ответ здесь предполагает использование списка, но это не сработает. Остальная часть этого параграфа истолковывает почему. Предположим, что есть два PathFigures, и ни один из них не находится внутри другого: после сортировки списка мы предположили бы, что он находится внутри другого. Мы можем объяснить это без лишней дополнительной работы, но теперь предположим, что есть две PathFigures, окруженные третьей PathFigure (например, число 8): после сортировки мы получаем только одно отверстие, чтобы быть частью 8. Мы можем, возможно, учитывать это также. Последняя проблема: предположим, что A содержит B и C содержит D, но они помещаются в список в порядке {A, C, B, D}: некоторые алгоритмы сортировки (например, BubbleSort) оставят их в этом порядке, потому что нет формы содержит своего соседа. Списки здесь слишком запутаны.
Итак, для нашего дерева, какой корневой узел? Корневой узел будет тем, что содержит все. Если вы хотите создать такую вещь, вы можете взять Союз всех ваших PathGeometries и использовать .Bounds
. Могут быть странные случаи, когда это не работает, но это не важно.
Как будет выглядеть наше дерево? Я буду использовать цифры цифр из вашего примера. Нажмите here, чтобы увидеть дерево.
Как мы можем сделать дерево? Я думаю, что это псевдокод легче понять, чем я пытаюсь описать его:
TreeNode.AddNode(PathGeometry geomToAdd)
{
bool containedByChild = false
foreach (TreeNode current in this.Children)
{
if (current.FillContains(geomToAdd)
{
containedByChild = true
current.AddNode(geomToAdd)
}
}
if (!containedByChild)
this.Children.Add(geomToAdd)
}
В отличие от бинарного дерева, у нас есть список детей, вместо фиксированного числа детей. Листом в дереве является любой узел с пустым списком детей. Поскольку корневой узел должен содержать все, вы можете просто вызвать этот метод в корне, не требуя определения PathGeometry для root.
Как мы превращаем дерево в наши PathGeometries? Начните с детей root. Это аддитивные PathFigures, а их дети являются субтрактивными PathFigures. Используя .Combine()
с GeometryCombineMode.Exclude
, вы можете вычесть внуков root из детей root. Затем удалите всех детей из корня и превратите правнуков корня в новый список детей и повторите.
Надеюсь, это ясно. Если это не так, пожалуйста, дайте мне знать, как улучшить ответ.
- PathFigures обязательно непересекающиеся? cos, если они пересекаются, тогда вещи становятся более сложными –
Нет, они никогда не пересекаются. Я анализирую все геометрии, прежде чем применять эту операцию. Если есть пересечения, пересекающиеся геометрии будут объединены (через Geometry.Combine (...), а затем PathGeometry.GetOutlinedPath (...)). Функция GetOutlinedPath должна предотвращать пересекающиеся фигуры. – Timo