C# 为什么相邻的矩形会产生带状效果?

C# 为什么相邻的矩形会产生带状效果?,c#,wpf,canvas,rectangles,visual-artifacts,C#,Wpf,Canvas,Rectangles,Visual Artifacts,我使用以下代码创建了一些矩形: 双倍宽度=6.546; 对于(int i=0;i

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

双倍宽度=6.546;
对于(int i=0;i<50;i++)
{
var rect=新矩形()
{
宽度=宽度,
高度=i*10,
填充=画笔。蓝色,
};
Canvas.SetLeft(矩形,i*宽度);
Canvas.SetBottom(rect,0);
canvas.Children.Add(rect);
}
结果如下:


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

首先,请在代码中添加这一行(在添加
矩形之前),看看问题是多么容易解决

 canvas.SnapsToDevicePixels = true;
与一些答案(包括我的第一个答案)中提到的相反,这个问题与浮点数无关,而是与
WPF
中使用的渲染系统有关,称为设备独立单位测量,但这可能会导致设备在每英寸96点(dpi)以上运行时产生伪影. Microsoft已清除此问题:

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


但是,
SnapToDevicePixels
属性也提供了解决方案。(请参阅)

这里的关键问题是
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会不希望地增加对象的大小。其他解决方案通过允许您将宽度保持在更接近所需大小的位置而对此进行改进。

像素不是浮点。它们是不可分割的。尝试将宽度设置为整数。您不应该看到它们。使用
intwidth=6进行测试未产生任何错误bands@It'sNotALie.:更改
width
会更改图形中的坡度,因此无法达到原始目的。我认为我不能使用矩形,因为它不是UIElement:“在将其添加到画布时无法从'System.drawing.RectangleF'转换为'System.Windows.UIElement'。是的,你是对的,我不熟悉WPF,我将尝试一些其他方法来解决这个问题,我将发布另一个答案later@epalm看看这个新答案,尽情享受吧!抱歉,添加
SnapsToDevicePixels=true
仍然会在我的一些数据集上产生大量的视觉瑕疵。使用ceil(宽度):使用SnapsToDevicePixels: