Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are the hard bounds for drawing coordinates in GDI+?

I am rendering an interpolation curve thusly:

e.Graphics.DrawLines(new Pen(Color.Red), _interpolationPoints.ToArray());

which sometimes throws an OverflowException.

Examination of the _interpolationPoints array shows some very large values in scientific notation e.g. {X = 0.0 Y = -1.985174E+10}

I suspect that Y = -1.985174E+10 is a value that GDI+ cannot handle. That's fine but what are the max/min X and Y values into which I can draw and so constrain the data (and warn the user) rather than catching the overflow exception during paint? Are the limits documented?

For example, I would like to do something like this:

if (yVal < float.MinValue || yval > float.MaxValue) 
      throw new OverflowException("Interpolation value too large to be rendered.");

during the population of the _interpolationPoints array and stop the process. (float mix/max does not work btw. i still get the exception.)

like image 568
Paul Sasik Avatar asked Aug 12 '10 14:08

Paul Sasik


3 Answers

OK, I needed to know so I tested incrementally and came up with these limits:

positive:    1,073,741,951
negative:   -1,073,741,760

The code I used looked something like this:

int lastGoodVal = 0;
for (int i = -1073000000; i > -1073832999; i -= 1)
{
    g.DrawLine(Pens.Blue, new Point(0,0), new Point(0, i));
    lastGoodVal = i;
}

The loop above was the final test, stepping by 1, through a range of negative values established by earlier tests. As you can see, lastGoodVal holds the last successful painting iteration and therefore the real limit which I'll use as a constant.

I tried to correlate these numbers to a value in the .NET primitives but couldn't. Each limit is close to the value of 2^30 but is not exactly on it. Any other insight would be much appreciated.

I also only tested with the DrawLine method. It's possible that different limits exist for other functions in the API but I have not had a chance to explore that yet.

Also, after finishing this experiment and then Googling for the value 1073741951 I came across this article which correlates my findings. I also found this in a Mono code archive of some sort which mentions a near, though not exact correlation to float limits.

like image 54
Paul Sasik Avatar answered Oct 07 '22 20:10

Paul Sasik


FYI - I ran into this situation with a simple implementation of a 2D plot. When I zoomed in too far on the image the corresponding pixel locations were WAY off the display area and caused Graphics.DrawLine to throw an OverflowException. So naturally I added a check to ensure that the values where within the limits defined by Paul above. 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).

After further investigation I discovered that a value of 8,388,607 (0x7FFFFF) draws the line correctly and a value of 8,388,608 (0x800000) inverts the line.

Looks like signed 24-bit values are used here.

like image 31
JustPassingBy Avatar answered Oct 07 '22 19:10

JustPassingBy


I've not heard of specific limits for DrawLines() or any other GDI drawing function. Why don't you use e.ClipRectangle as a constraint?

Drawing points outside the visible region is not needed anyway. Just make sure that only lines are discarded that have both points outside.

like image 32
msteiger Avatar answered Oct 07 '22 19:10

msteiger