完全填充自定义几何图形

时间:2011-12-13 21:14:08

标签: c# wpf

我正在试图弄清楚如何完全填充自定义几何体。这似乎应该是一个常见的问题,但我还没有真正找到任何解决方案。

我有以下几何示例:

    <Path Fill="White" Stretch="Fill" Stroke="Black" StrokeThickness="2">
        <Path.Data>
            <PathGeometry
                Figures="M112,296C112,296 136,296 136,320 M112,344C112,344 136,344 136,320 M112,296L112,296 96,296 96,344 112,344"/>
        </Path.Data>
    </Path>

产生以下结果:

Undesired Fill Result

这是我希望看到的结果:

Desired Fill Result

任何想法?我知道我可以制作一个弧形并且可以解决这个特殊情况,但在我的应用程序中,用户可以绘制任何类型的几何体,因此结果可以由任意数量的“基元”组成(PolyLineSegments,EllipseGeometries,ArcSegments等)如果生成的几何体包含某种类型的封闭区域,我想准确填充该区域。

修改

如果我确保所有三个相邻的几何图形重叠并使用以下代码创建一个联合的CombinedGeometry,那么这是一个CombinedGeometry的示例:

        <Path Grid.Row="2" Fill="White" Stretch="Fill" Stroke="Black" StrokeThickness="2">
        <Path.Data>
            <CombinedGeometry GeometryCombineMode="Union">
                <CombinedGeometry.Geometry1>
                    <CombinedGeometry GeometryCombineMode="Union">
                        <CombinedGeometry.Geometry1>
                            <PathGeometry
                                Figures="M111,293C111,296 136,293 136,325"/>
                        </CombinedGeometry.Geometry1>
                        <CombinedGeometry.Geometry2>
                            <PathGeometry
                                Figures="M111,346C111,344 136,344 136,320"/>
                        </CombinedGeometry.Geometry2>
                    </CombinedGeometry>
                </CombinedGeometry.Geometry1>
                <CombinedGeometry.Geometry2>
                    <PathGeometry
                        Figures="M125,296L115,296 96,296 96,344 120,344"/>
                </CombinedGeometry.Geometry2>
            </CombinedGeometry>
        </Path.Data>
    </Path>

结果如下:

Combined Geometry

我希望它只会结合笔画并自动找出新的连续多边形的正确填充...无赖。

编辑2:

嗯所以我想我已经提出了几种可能的解决方案,这些解决方案都不像我希望的那样容易。第一个选项是使用CombineGeometry结构组合上面的所有几何,然后在结果“CombineGeometry”上调用“GetFlattenedPathGeometry”以获得PathGeometry。接下来,我迭代在PathGeometry中的每个图形,然后删除那些是洞(我认为你应该能够通过去除所有其他完全包含的图形来做,或者孔可以遵循顺时针方向或逆时针坐标,不确定..),如果一切顺利,你应该留下一个完全填充的几何。

第二个选项是在所得到的路径上再次调用“GetFlattenedPathGeometry”,以便获得路径的基于顶点的多边形近似(没有所有曲线,弧,椭圆等符号,我们想要一条路径只包含点和线)。之后,您只需将所有结果图形/线段组合成一个图形,其中的线段按顺时针或逆时针顺序排列。

我已经测试了两种方法,它们似乎至少与上面概述的简单测试用例一起工作,尽管它们不适用于更复杂的形状(自相交,凹陷等)。我需要的支持。所以问题仍然存在,我该怎么做?

编辑3:

这是一个更复杂的几何图形,其中排序/组合变得更加困难:

        <Path Fill="White" Stretch="Fill" Stroke="Black" StrokeThickness="2">
        <Path.Data>
            <PathGeometry
            Figures="M104,160C104,160 72,160 72,136
                M104,128C104,128 72,128 72,152
                M152,232L152,232 152,216 120,216 120,160 128,160
                M152,232L152,232 72,232 104,216 104,160 96,160
                M104,128L104,128 168,128
                M128,160L128,160 168,160
                M165,160L168,160 200,128
                M200,160L200,160 200,128
                M200,160L200,160 168,128 152,128"/>
        </Path.Data>
    </Path>

产生:

enter image description here

3 个答案:

答案 0 :(得分:5)

您的示例几何体是三个相邻形状的组合,不会重叠。在外边缘上绘制笔划仅仅因为形状没有关闭而内部笔划线不存在。虽然可能看起来形状正在合并并且笔划作为一个整体应用于几何体,但这不是正在发生的事情。

关闭孔成为一个更复杂的问题,即以编程方式检测孔并以适当的形状将其关闭,或者创建一个没有孔的新组合形状(可能通过检测和跟踪外部点)。我不知道WPF中的任何功能可以帮助您完成此任务。确实存在CombinedGeometry类,它可以生成两个重叠形状的并集。此示例中的形状不重叠。

如果没有上下文,很难推荐解决方案。如果这是一个自由格式绘图程序,用户可能只需要在中间绘制另一个形状来关闭几何体。

答案 1 :(得分:2)

将其视为“连接点”问题:)

你有5分:

  • 96,296 - 左上角(角落)
  • 112,296 - bezier曲线的顶部 - 开始
  • 136,320 - 第一个贝塞尔曲线的最右端 - 第二个的开始
  • 112,344 - 第二个bezier的底部
  • 96,344 - 左下角(角落)

现在,我们将连接它们。

<Path Fill="White" Stretch="Fill" Stroke="Black" StrokeThickness="2">
    <Path.Data>
        <PathGeometry Figures="M112,296 C112,296 136,296 136,320 C136,320 136,344 112,344 M112,344 96,344 96,296 112,296"/>
    </Path.Data>
</Path>

您还可以使用&lt; GeometryGroup FillRule =“Nonzero”...&gt;从第一篇文章填写您的自定义路径。默认值是FillRule =“EvenOdd”,它会产生类似你的填充。*

有关路径迷你语言的详细信息,请参阅路径标记语法(http://msdn.microsoft.com/en-us/library/ms752293.aspx)。

  • 更改&lt;路径&gt;到&lt; GeometryGroup&gt;

编辑1:

我稍微重新排序了你的路径:

<Path Fill="White" Stretch="Fill" Stroke="Black" StrokeThickness="2">
    <Path.Data>
        <PathGeometry Figures="M72,152 C72,152 72,128 104,128 L168,128 200,160 200,128 168,160 120,160 120,216 152,216 152,232 72,232 104,216 104,160 C104,160 72,160 72,136"/>
    </Path.Data>
</Path>

这给了我们:

New shape

绘制路径就像在矢量编辑软件中使用某种“绘制形状”工具一样,你必须选择下一个点,当你没有下一个点时 - 形状会自动关闭(最后一个点连接到第一个一,但只是为了填充形状 - 当我们看到新形状的“鼻子”时,我们可以看到它是如何完成的。 在您的示例中,您有9个单独的形状(每个形状在单独的行中,其中M指定新图的开头),并且它们都在上述方式中填充。

当然,您可以使用GeometryGroup(使用FillRule)或CombinedGeometry(使用CombinedGeometryMode)来连接形状。

答案 2 :(得分:1)

我发现an interesting article使用wpf创建形状,使用sigg文件创建的图形工具如inkscape。这可能会给你一些见解。