Правильно разделить System.Windows.Media.PathGeometry

У меня есть один System.Windows.Media.PathGeometry, как это:1И я хотел бы разделить геометрию, чтобы каждая серая фигура была в новом объекте Geometry. Я попытался перебрать FigureColletion PathGeometry и поместить каждую фигуру в новую геометрию, но результат не такой, как я ожидал, потому что одна фигура описывает только один край фигуры, а не саму фигуру. Это означает, что к некоторым фигурам применяются аддитивные, а некоторые к вычитающим2Чтобы правильно разделить геометрию, я должен выяснить, какие PathFigures применяются, а какие вычитают. В типе PathFigure отсутствует свойство, которое дает мне информацию о том, как его применять. У кого-нибудь есть идеи, как решить эту проблему?

Заранее спасибо.

2 ответа

В настоящее время я пытаюсь сделать то же самое, так что вот мой план, а также некоторые мыслительный процесс.

Во-первых, конвертируйте все в 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, Могут быть странные случаи, когда это не работает, но это не важно.

Как будет выглядеть наше дерево? Я буду использовать цифры цифры из вашего примера. Нажмите здесь, чтобы увидеть дерево.

Как мы делаем дерево? Я думаю, что этот псевдокод легче понять, чем я, пытаясь описать его:

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 для корня.

Как мы превращаем дерево в наши PathGeometries? Начните с детей корня. Это аддитивные PathFigures, а их потомки - вычитающие PathFigures. С помощью .Combine() с GeometryCombineMode.ExcludeВы можете вычесть внуков корня из детей корня. Затем удалите всех дочерних элементов из root и включите правнуков root в новый список дочерних элементов и повторите.

Надеюсь, это понятно. Если это не так, пожалуйста, дайте мне знать, как улучшить ответ.

Если, как вы упомянули, PathFigureне пересекаются, т. е. сдерживание завершено, то если PathFigure A содержит B, тогда границы AABB для A также содержат границы B.

К сожалению я не думаю PathFigure имеет такое свойство, поэтому один из способов преодоления этого, вероятно, будет создавать отдельные новые PathGeometry объекты от каждого PathFigure внутри .Figures свойство, и хранить их в массиве. Затем отсортируйте этот массив, используя .Bounds.Contains свойство, то есть это: https://msdn.microsoft.com/en-us/library/ms557978(v=vs.110).aspx, вместо операции сравнения в обычной процедуре сортировки.

Теперь у вас есть список "Матрешка" PathGeometryы, начиная с самой внешней, выбирают каждую последующую пару и берут их объединение (.Combine как вы сказали). Если массив имеет нечетное количество элементов, то есть один слева в конце, то это должно иметь место на рисунке 4.

Другие вопросы по тегам