0

I have a control that contains shapes drawn with GDI+ and the user can zoom into it. If he zooms in far the actual coordinates that the shapes are drawn at get quite large.

Now I zoomed into the location of the left edge of a circle drawn by FillEllipse and after a while the circle suddenly flips and I actually see a right edge instead of a left edge.

I extracted the coordinates and put up a simple program that reproduces the problem (All thats needed for it is a form, with two radiobuttons and a picturebox of sufficient size on it):

Public Class Form1

    Private Sub Draw()
        'Create a canvas
        Dim bmp As New Bitmap(PictureBox1.Width, PictureBox1.Height)
        Using g As Graphics = Graphics.FromImage(bmp)
            g.Clear(Color.Black)

            'X location, Y location and the diameter of the circle to draw
            Dim x, y, dia As Single

            If RadioButton1.Checked Then
                'This works as expected
                x = 561
                y = -3993174.7
                dia = 7986931.0
            Else
                'This comes out flipped
                x = 561
                y = -4436903.7
                dia = 8874368.0
            End If

            'Define and draw the ellipse
            Dim rectf As New RectangleF(x, y, dia, dia)
            g.FillEllipse(Brushes.Red, rectf)
            g.DrawEllipse(Pens.LightGreen, rectf)
            'Mark the circle's vertical center
            g.DrawLine(Pens.Blue, 0.0F, y + dia / 2, CSng(bmp.Width), y + dia / 2)
        End Using

        'Display the image
        If PictureBox1.Image IsNot Nothing Then PictureBox1.Image.Dispose()
        PictureBox1.Image = bmp
    End Sub

    Private Sub RadioButton1_CheckedChanged(sender As Object, e As EventArgs) Handles RadioButton1.CheckedChanged
        'Redraw on radiobutton check change
        Draw()
    End Sub
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Draw()
    End Sub
End Class

In the images below the red part is the ellipse that is being drawn, black is the background, and the blue line is the vertical center of the ellipse as calculated from the coordinates I put in.

If you run that program and select RadioButton1 you will see the following:

enter image description here

All is well, the circle is drawn to the right.

However if you select RadioButton2 you see:

enter image description here

The circle suddenly is flipped horizontally and is drawn to the left.

I suspect that somehow the large values interfere but I honestly can't see a reason how this outcome can be produced. Can someone shed some light why GDI+ gets upset and how I can fix it?

Both answers in VB.NET and in C# are very much appreciated.

Jens
  • 6,275
  • 2
  • 25
  • 51
  • 1
    maybe it is an issue of contrast, but I cant see any circle at all, just a petite blue line and a garishly bright red background. – Ňɏssa Pøngjǣrdenlarp Jan 24 '15 at 18:40
  • 2
    @Plutonix: I believe that the ellipse is the red part. It's just so large that the curvature is basically undetectable visually. – Peter Duniho Jan 24 '15 at 18:47
  • Yes that is true. The red part is the ellipse that is being drawn. I probably should have pointed that out more, as it is only apparent from the code I posted. – Jens Jan 24 '15 at 19:13
  • GDI+ indeed has plenty of overflow issues, only practical approach is to limit how deeply you zoom in. – Hans Passant Jan 24 '15 at 19:14
  • This [post](http://stackoverflow.com/a/23255170/2330053) indicates a similar problem: "Interestingly though when the Y value got too large (but less than suggested positive value of 1,073,741,951) the resulting line went from being drawn down as expected (to a Y pixel location greater than my last reasonable point) to being drawn up (to the top of the window)." – Idle_Mind Jan 24 '15 at 19:23
  • 1
    By the way, your comments in the code about which portion draws correct/flipped are backwards: RadioButton1 draws correctly, while RadioButton2 draws flipped. – Idle_Mind Jan 24 '15 at 19:28
  • 2
    Other than the admittedly vague "sounds like overflow" answer, I don't have anything specific to offer. However, I will note that `2^31 / 8874368.0` is `241.9872`, and that many displays are configured at 120dpi, making the number `241.9872`, which is very close to `120 * 2`, a very intriguing coincidence. In any case, the true solution is that you will need to pre-scale your rendering to ensure you don't exceed GDI+'s coordinate system limits. – Peter Duniho Jan 24 '15 at 19:43
  • @Idle_Mind You're correct, I already had changed the comments in my VS code but somehow forget to transfer it. Your other answer is also very interesting. I think I will implement a boundary system for the shapes (which are by the way part of a 2D plot control as well ;-)) to avoid large coordinates. Using reasonably large bounds won't change the appearance anyways. – Jens Jan 24 '15 at 20:16

0 Answers0