StreamGeometry结合
我有复杂的StreamGeometry
,我想剪辑它。 不幸的是,看起来StreamGeometry
不支持组合。
这是一个测试。
XAML:
码:
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
)或第四行(显示clip
和rect
交集)将产生:
取消注释最后一行(显示clip
和geometry
交集)会产生空白屏幕。
我的问题是: 如何组合(剪辑)StreamGeometry ?
我知道有UIElement.Clip
,但是:
// blank screen path.Data = stream; path.Clip = clip; // blank screen as well path.Data = stream; path.Clip = clip;
解决方案很简单: 不要使用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
)! 永远不要用它! 在分配之前剪辑几何体。
你绝对可以组合StreamGeometry
对象。 为此,您需要使用CombinedGeometry
对象。 这是一个用于绘制带孔的多边形的简单扩展方法:
public static void DrawPolygon(this DrawingContext context, Brush brush, Pen pen, IEnumerable exteriorRing, IEnumerable> 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); }