我目前正在尝试做同样的事情,所以这是我的计划,以及一些思考过程。
首先,将所有内容都转换为 PathGeometry。该FillContains(Geometry geometry)
方法是我想用来查看内容的内容。问题.Bounds.Contains
在于,如果您有一个中间有一个点的 C 形状,则该点将包含在边界矩形中,但不包含在形状中。
接下来,创建一个树数据结构。如果 PathGeometry A 包含 PathGeometry B,则 A 将是树中 B 的祖先。这里的另一个答案建议使用列表,但这也行不通。本段的其余部分解释了原因。假设有两个 PathFigure 并且一个都不在另一个里面:在对列表进行排序之后,我们会假设一个在另一个里面。我们可以在没有太多额外工作的情况下解释这一点,但现在假设有两个 PathFigure 被第三个 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。
我们如何将树变成我们的 PathGeometry?从根的孩子开始。这些是加法 PathFigure,它们的子节点是减法 PathFigure。使用.Combine()
with GeometryCombineMode.Exclude
,您可以从 root 的子代中减去 root 的孙代。然后,从 root 中删除所有孩子,并将 root 的曾孙变成它的新孩子列表,然后重复。
希望这很清楚。如果不是,请让我知道如何改进答案。