I've created some rectangles using the following code:
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);
}
Here is the result:
There are vertical lines of varying lightness. Why do they appear? They can be avoided by using a large width
value. Is there any other way to avoid them?
The key problem here is that
Width = width
sets the rectangle width to 6, butCanvas.SetLeft(rect, i * width)
sets the positions of the rectangles to 0, 6, 13, 19, 26,… (as integers obtained by truncating products of approximately 0, 6.546, 13.092, 19.638, 26.184,…). As you can see, some of the positions are 7 units apart, such as 6 and 13 or 19 and 26. Therefore, the six-unit rectangle does not span the seven-unit distance.In this case, setting the width with
Width = ceil(width)
(which is 7) guarantees that the rectangles are wide enough to span the distances between them.Although this answer suggests that you use
int
numbers, it is not clear that this is desirable. If you convert the calculations toint
, you must either set the positions to multiples of one integer (6 or 7) or figure out a way to calculate the same positions (0, 6, 13, 19, 26,…) by using integer arithmetic instead of floating-point. The former is a choice to change the drawing to suit the arithmetic, which is undesirable. The latter preserves the slope in your drawing but has the same banding issue.That answer also suggests using a floating-point version of the drawing objects. That is a reasonable approach. Note, however, that this merely reduces the rounding errors (from integer units to the finer floating-point units, at this magnitude); it does not eliminate them. In large drawings, there may still be an occasional drawing artifact unless you take care to avoid it. So understanding the details is important. Even with floating-point, you would want to ensure the width is set to be at least as large as any change in position.
Another option is to change the scale of the canvas, if your drawing interface supports that. If you can multiply the scale by 1000 (but keep the final drawing the same size), then your scale changes from 6.546 to 6546, and you can set the width to exactly 6546 instead of 6000 or 7000. As you can see, we are back to the key issue: You must set the width to a value at least as great as the difference between any two positions.
As stated previously, setting the width to 7 would make this drawing acceptable. The reason I discuss other solutions is that, in some drawings, changing the width from the ideal of 6.546 to 7 increases the size of the object undesirably. The other solutions improve upon that by allowing you to maintain a width closer to the desired size.