1

我使用以下代码创建了一些矩形:

double width = 6.546;

for (int i = 0; i < 50; i++)
{
    var rect = new Rectangle()
    {
        Width = width,
        Height = i * 10,
        Fill = Brushes.Blue,
    };

    Canvas.SetLeft(rect, i * width);
    Canvas.SetBottom(rect, 0);

    canvas.Children.Add(rect);
}

结果如下:

垂直条带

有不同亮度的垂直线。它们为什么会出现?它们可以通过使用较大的width值来避免。有没有其他方法可以避免它们?

4

2 回答 2

2

这里的关键问题是Width = width将矩形宽度设置为 6,但Canvas.SetLeft(rect, i * width)将矩形的位置设置为 0、6、13、19、26、...(通过截断大约 0、6.546、13.092、19.638、26.184 的乘积获得的整数,……)。可以看到,有些位置是相隔 7 个单位的,比如 6 和 13 或 19 和 26。因此,六单位矩形不跨越七单位距离。

在这种情况下,将宽度设置为Width = ceil(width)(7) 可确保矩形足够宽以跨越它们之间的距离。

尽管此答案建议您使用int数字,但尚不清楚这是否可取。如果将计算转换为int,则必须将位置设置为一个整数(6 或 7)的倍数,或者通过使用整数算术找出一种方法来计算相同的位置(0、6、13、19、26,...)而不是浮点数。前者是改变绘图以适应算术的选择,这是不可取的。后者保留了绘图中的斜率,但具有相同的条带问题。

该答案还建议使用绘图对象的浮点版本。这是一个合理的做法。但是请注意,这只是减少了舍入误差(从整数单位到更精细的浮点单位,在这个数量级);它不会消除它们。在大型图纸中,可能仍会偶尔出现绘图伪影,除非您注意避免它。所以了解细节很重要。即使使用浮点,您也希望确保将宽度设置为至少与位置的任何变化一样大。

如果您的绘图界面支持,另一个选项是更改画布的比例。如果您可以将比例乘以 1000(但保持最终绘图的大小相同),那么您的比例将从 6.546 变为 6546,并且您可以将宽度设置为 6546 而不是 6000 或 7000。如您所见,我们是回到关键问题:您必须将宽度设置为至少与任意两个位置之间的差值一样大的值。

如前所述,将宽度设置为 7 将使该绘图可接受。我讨论其他解决方案的原因是,在某些图纸中,将宽度从理想的 6.546 更改为 7 会不希望地增加对象的大小。其他解决方案通过允许您保持更接近所需尺寸的宽度来改进这一点。

于 2013-08-08T12:37:45.177 回答
0

首先,请将此行添加到代码中(在添加之前Rectangle),看看问题是多么容易消失!

 canvas.SnapsToDevicePixels = true;

与包括我的第一个答案在内的一些答案所提到的相反,这个问题与浮点数无关,而是与WPF所谓的与设备无关的单位测量中使用的渲染系统有关,但这可能会导致设备在大于每英寸 96 点 (dpi)。微软清除了这个问题:

...由于抗锯齿,这种 dpi 独立性可以创建不规则的边缘渲染。当边缘的位置落在设备像素的中间而不是设备像素之间时,可能会出现这些伪影,通常被视为模糊或“软”边缘(参考

但解决方案也由SnapToDevicePixels财产提供。(见此

于 2013-08-08T00:19:29.303 回答