4

I know GDI+ is a bit antiquated, but I'm currently being forced to use it in in a WinForms app to draw complex CAD type models.

I encountered what I believe is the same issue as: Why is my c# paint method running out of memory? as described by the currently accepted answer (https://stackoverflow.com/a/7501899/9300908) as well as some comments. I've ensured my brushes, pens, and fonts are disposed of as well as bitmaps and other gdi objects. I'm drawing 10s to 100s of thousands of arcs with the DrawArc() function and the same arc (1.13 degrees) each time is giving me trouble. I suspect I have encountered the small arc bug.

I'm planning to simply draw a line instead of an arc at whenever the conditions exceed a certain threshold, but I'm struggling to define the threshold. I'm trying to find a good source for what size is too small (I see references to < 1 degree, < 2 pixels, < 3.5 degrees) so that I don't need to rely on the exception handler especially when dealing with similarly small arcs.

The referenced answer as well as comments refer to a number of Microsoft Connect articles that are unavailable now that Microsoft Connect is now retired. I don't seem to have the magic sauce to find it in the visual studio developer community where I thought it might be moved to. Anyone have any reference material on the DrawArc bug or maybe an alternative workaround?

Connect references:

Mentioned on msdn regarding DrawPath:

Other forums I've found point back to the referenced question.

Update

Environment is x64, .NET 4.5.2

1.13 is the sweepAngle (see below for the effective values). It and the startAngle are both native floats.

I can recreate the exception with this sample code from a new WinForms app.

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        // g is a graphics object created from a 1920W x 1080H Bitmap:
        using (Bitmap mBitmapModel = new Bitmap(1920, 1080))
        {
            using (Graphics g = Graphics.FromImage(mBitmapModel))
            {
                float lStartAngle = -0.00816029962F;
                float lSweepAngle = 1.13203466F;
                RectangleF lRect = new RectangleF(742.741333F, 157.927505F, 3.28945208F, 3.28945208F);

                using (Pen lPen = new Pen(Color.Blue, 2F))
                {
                    g.DrawArc(lPen, lRect, lStartAngle, lSweepAngle);
                }
            }
        }
    }
}
Community
  • 1
  • 1
pigeon
  • 151
  • 9
  • 3
    https://stackoverflow.com/a/14939562/17034 – Hans Passant Oct 25 '19 at 17:01
  • With *the same arc (1.13 degrees)*, do you mean the start angle, the sweep angle or the difference? Did you explicitly use `float` values or there's some conversion going on? What is the distance between the start point and the end point when the exception is raised? Can you post a sample of the code that generates the exception? The .Net FW version in use is equally useful, as is the target of the drawing (the *canvas* where the drawings is performed). – Jimi Oct 25 '19 at 17:44
  • @Jimi, updated the post with your questions answered. Thanks. – pigeon Oct 25 '19 at 18:54
  • 1
    You cannot draw an Arc in a `3x3` sized rect with a Pen of size `2f`. If you set the Pen to `1f` it will most probably draw it. Check these values and decide what is more important, the Pen size of the (calculated?) rectangle size. You could round the values (see the `Rectangle.Round()` method). This kind of precision, drawing in a Bitmap object, may generate other issues, though. You may want to reduce the complexity. – Jimi Oct 25 '19 at 19:17
  • You could scale the Bitmap and the drawing up, then re-scale when the drawing is completed. + Set `g.PixelOffsetMode = PixelOffsetMode.Half`. I don't see any anti-aliasing, maybe just because it's POC code. If you actually use antialiasing, also consider that pixel/half-pixel – Jimi Oct 25 '19 at 19:37
  • 1
    @Jimi, you're definitely right. Reducing the pen size allows it work. I will have to do some checking. The pen width generally doesn't change. Being a CAD type application, scaling/zoom and position is being used to convert from engineering units (e.g. inches) to pixels on the screen so it's a bit arbitrary depending on what the user is trying to view. I will try with some trial and error and check the rect size vs pen ratio, assuming rect size should be about double the pen width. – pigeon Oct 25 '19 at 19:37
  • Try using the widen method to turn the pen stroke into points. If the pen size is the issue, you should get an error there as well. If not, you can at least examine the points. – Frank Hileman Nov 04 '19 at 21:23

0 Answers0