为什么裁剪的几何图形不等于绘制的几何图形? [英] Why clipped geometry is not equal to drawn geometry?

查看:136
本文介绍了为什么裁剪的几何图形不等于绘制的几何图形?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

目标:剪辑和绘制相同的几何体。

问题:剪切的几何体不等于绘制的几何体。

注意:使用形状并且EdgeMode是别名。

警告:下一个代码行无法解决问题:

Goal: To clip and draw the same geometry.
Problem: Clipped geometry is not equal to drawn geometry.
Notes: Shapes are used and EdgeMode is Aliased.
Warning: The next code lines doesn't fix the problem:

RenderOptions.SetBitmapScalingMode(canvas, BitmapScalingMode.NearestNeighbor);
canvas.SnapsToDevicePixels = true;
canvas.UseLayoutRounding = true;



问题:如何解决问题?

附加问题:剪辑作为区域是什么?

代码:


Question: How to solve the problem?
Additional question: What does clip take as region?
Code:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        this.Loaded += delegate
        {
            this.KeyDown += MainWindow_KeyDown;

            canvas = new Canvas();
            this.Content = canvas;
            canvas.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;
            canvas.VerticalAlignment = System.Windows.VerticalAlignment.Top;
            canvas.Width = Math.Round(500d);
            canvas.Height = Math.Round(500d);

            RenderOptions.SetEdgeMode(canvas, EdgeMode.Aliased);

            canvas.Background = Brushes.Black;
            canvas.MouseLeftButtonDown += (sender, e) =>
            {
                down = true;

                lines = new Polyline();
                lines.Stroke = Brushes.White;
                canvas.Children.Add(lines);
            };

            canvas.MouseRightButtonDown += (sender, e) =>
            {
                RenderOptions.SetEdgeMode(canvas, EdgeMode.Unspecified);
            };
            canvas.MouseUp += delegate
            {
                RenderTargetBitmap rtb = new RenderTargetBitmap((int)Math.Round(500d), (int)Math.Round(500d), 96, 96, PixelFormats.Default);
                rtb.Render(canvas);
                canvas.Children.Clear();
                ImageBrush image = new ImageBrush();
                image.ImageSource = rtb;
                canvas.Background = image;

                down = false;
                thickness = 1;
            };
            canvas.MouseMove += canvas_MouseMove;
        };
    }

    Canvas canvas;
    Polyline lines;
    List<LineGeometry> linegeoms = new List<LineGeometry>();
    bool down;
    double thickness = 1;

    void canvas_MouseMove(object sender, MouseEventArgs e)
    {
        if (down)
            lines.Points.Add(new Point(e.GetPosition(canvas).X, e.GetPosition(canvas).Y));
    }

    int add = 5;

    void MainWindow_KeyDown(object sender, KeyEventArgs e)
    {
        if (e.Key == Key.Up)
            thickness += add;

        if (e.Key == Key.Down)
            thickness -= add;

        if (thickness <= 0)
            thickness = 1;

        Light();
    }

    void Light()
    {
        canvas.Children.Clear();
        Geometry linesgeom = this.lines.RenderedGeometry;

        Color color = Colors.White;
        double add = 255 / (thickness);
        color.A = 127;

        for (double i = thickness; i > 0; )
        {
            Geometry geom1 = linesgeom.GetWidenedPathGeometry(new Pen(Brushes.Transparent, i--));
            Geometry geom2 = linesgeom.GetWidenedPathGeometry(new Pen(Brushes.Transparent, i));
            CombinedGeometry combined = new CombinedGeometry(GeometryCombineMode.Exclude, geom1, geom2);

            Path path = new Path();
            path.Data = geom1;
            path.Fill = new SolidColorBrush(color);
            path.Clip = combined;

            canvas.Children.Add(path);
        }
    }
}

推荐答案

Mike Danes在msdn上的回答:

https://social.msdn.microsoft.com/Forums/en-US/cf584e19-af0d-42d4-8aa5-bc9a2d06be3a/why-clipped-geometry-is-not-equal- to-drawn-geometry [ ^ ]



但它不一定相关对于绘图,像Exclude这样的几何操作在此中起作用。请尝试以下示例:

Answered by Mike Danes on msdn:
https://social.msdn.microsoft.com/Forums/en-US/cf584e19-af0d-42d4-8aa5-bc9a2d06be3a/why-clipped-geometry-is-not-equal-to-drawn-geometry[^]

But it's not necessarily related to drawing, geometry operations like Exclude play a part in this. Try the following example:
void Light()
{
    canvas.Children.Clear();
    Geometry linesgeom = this.lines.RenderedGeometry;

    for (double i = thickness; i > 0; )
    {
        var geom1 = linesgeom.GetWidenedPathGeometry(new Pen(Brushes.Transparent, i--));
        var geom2 = linesgeom.GetWidenedPathGeometry(new Pen(Brushes.Transparent, i));
        var combined = Geometry.Combine(geom1, geom2, GeometryCombineMode.Exclude, null);
        combined = Geometry.Combine(combined, geom1, GeometryCombineMode.Exclude, null);

        if (!combined.IsEmpty())
        {
            canvas.Children.Add(new Path {
                Data = combined,
                Stroke = Brushes.Blue,
                Fill = Brushes.Red
            });
        }
    }
}



在此示例中,geom2从geom1中排除,然后从结果中排除geom1。从理论上讲,最终结果应该是空的,如果你用直线试试,你会发现没有任何东西显示出来。但是,一旦你用更复杂的线条尝试它,蓝线开始出现。这些线条反映了几何操作的不精确结果。



想想看,任何此类操作都需要计算线交叉点。即使确定这2行的点具有整数坐标,2行的交点的坐标也是有理数。例如,线(0,0) - (3,1)和(1,0) - (1,1)在(1,1 / 3)处相交。使用标准数字类型(如int,float和double)无法准确表示1/3。



技术上可以使用自定义有理类型来执行此类计算但在你仍然必须转换为浮点数(因为这是DirectX所理解的)并最终转换为整数(因为屏幕像素具有整数坐标)。在某个地方,一些不准确的地方会潜入。


In this example geom2 is exclude from geom1 and then geom1 is excluded from the result. Theoretically the final result should be empty and if you try this with a straight line you'll see that nothing is displayed. But as soon you try it with a more complex line blue lines start to show up. Those lines reflect the inexact result of geometric operations.

Think about it, any such operations will require computing line intersection points. The coordinates of the intersection point of 2 lines are rational numbers even if the points that determine those 2 lines have integer coordinates. For example, lines (0,0)-(3,1) and (1,0)-(1,1) intersect at (1,1/3). That 1/3 cannot be represented exactly using standard numeric types like int, float and double.

It's technically possible to use custom rational types to perform such computations but in the end you still have to convert to float (because that's what DirectX understands) and ultimately to integer (because screen pixels have integer coordinates). Somewhere along the way some inaccuracies will sneak in.


这篇关于为什么裁剪的几何图形不等于绘制的几何图形?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆