StreamGeometry结合

时间:2014-08-28 10:25:56

标签: c# wpf geometry

我有复杂的StreamGeometry,我想剪辑它。不幸的是,看起来StreamGeometry不支持合并。

这是一个测试。

的Xaml:

<Path x:Name="path" Stroke="Red"/>

代码:

var clip = new RectangleGeometry(new Rect(50, 50, 10, 10));
var rect = new RectangleGeometry(new Rect(0, 0, 100, 100));
var stream = new StreamGeometry();
using (var geometry = stream.Open())
{
    geometry.BeginFigure(new Point(0, 0), false, true);
    geometry.LineTo(new Point(0, 100), true, false);
    geometry.LineTo(new Point(100, 100), true, false);
    geometry.LineTo(new Point(100, 0), true, false);
}

//path.Data = rect;
//path.Data = stream;
//path.Data = clip;
//path.Data = Geometry.Combine(rect, clip, GeometryCombineMode.Intersect, null);
//path.Data = Geometry.Combine(stream, clip, GeometryCombineMode.Intersect, null);

取消注释第一行(显示rect)或第二行(显示stream)会产生相同的视觉效果:

取消注释第三行(显示clip)或第四行(显示cliprect的交集)将产生:

取消注释最后一行(显示clipgeometry的交集)会产生空白屏幕。

我的问题是:如何组合(剪辑)StreamGeometry

我知道有UIElement.Clip,但是:

// blank screen
path.Data = stream;
path.Clip = clip;

// blank screen as well
path.Data = stream;
path.Clip = clip;

2 个答案:

答案 0 :(得分:1)

解决方案很简单:不要使用StreamGeometry

例如,这将起作用(改为使用PathGeometry):

var clip = new RectangleGeometry(new Rect(50, 50, 10, 10));
var geometry = new PathGeometry(new[] { new PathFigure(new Point(0, 0), new[] {
    new LineSegment(new Point(0, 100), true),
    new LineSegment(new Point(100, 100), true),
    new LineSegment(new Point(100, 0), true),
}, true) });
path.Data = Geometry.Combine(clip, geometry, GeometryCombineMode.Intersect, null);

结果:

非常重要!

看起来UIElement.Clip仍会呈现不可见的部分(mayhap只有StreamGeometry)!永远不要用它!剪辑几何之前分配它。

答案 1 :(得分:1)

您绝对可以合并StreamGeometry个对象。为此,您希望使用CombinedGeometry对象。这是一个简单的扩展方法,用于绘制带孔的多边形:

public static void DrawPolygon(this DrawingContext context, Brush brush, Pen pen, IEnumerable<Point> exteriorRing, IEnumerable<IEnumerable<Point>> interiorRings = null)
{
    StreamGeometry geo = new StreamGeometry();
    Geometry finalGeometry = geo;

    using (StreamGeometryContext ctxExterior = geo.Open())
    {
        ctxExterior.BeginFigure(exteriorRing.First(), (brush != null), true);
        ctxExterior.PolyLineTo(exteriorRing.Skip(1).ToArray(), (pen != null), false);

        if (interiorRings != null)
        {
            foreach (var ring in interiorRings)
            {
                var interiorGeometry = new StreamGeometry();

                using (var ctxInterior = interiorGeometry.Open())
                {
                    ctxInterior.BeginFigure(ring.First(), true, true);
                    ctxInterior.PolyLineTo(ring.Skip(1).ToArray(), (pen != null), false);
                }

                finalGeometry = new CombinedGeometry(GeometryCombineMode.Exclude, finalGeometry, interiorGeometry);
            }
        }
    }

    context.DrawGeometry(brush, pen, finalGeometry);
}