Draw ellipse within rectangle

Started by
2 comments, last by MarkS_ 9 years, 1 month ago

Hi,

Just having an annoying problem that is just on the edge of my sight. I have a function to draw a circle:


void CircleShape(int size)
{
    Vector2 center = new Vector2(size / 2, size / 2);
    for (int y = 0; y < size; y++)
    {
        int dy = (center.y - y);

        for (int x = 0; x < size; x++)
        {
            int dx = (center.x - x);

            double dist = Mathf.Sqrt(dx * dx + dy * dy);

            if (dist <= (size / 2))
            {
                SetPixel(x, y, Color.white);
            }
        }
    }
}

I would like to have to be able to provide a width, height instead of just size to be able to produce a circle or ellipse. Does that completely change my code or is there a simpler solution here?

Thanks,

Scott

Advertisement

I would like to have to be able to provide a width, height instead of just size to be able to produce a circle or ellipse. Does that completely change my code or is there a simpler solution here?

Yes, it will change your code. No, there isn't a simpler solution. You'll also have to decide what you mean by "height" and "width."

That is, the general formula for the locus of points on an ellipse with semi-major and -minor axes aligned with the x/y axes, and centered at the origin is:

x2 / a2 + y2 / b2 = 1

EDIT: Note that describes a circle if a = b = r.

That link also describes the locus for an ellipse not centered at the origin.

Off the top of my head - Given y: x = sqrt( a2 * ( 1 - y2 / b2 ) )

EDIT2: Note that sqrt has 2 roots, a positive and negative. I.e., for each y value there will be 2 solutions for x, one on either side of the y axis. Further, if you decide to implement your function using that approach, you can range y from 0 to b, and plot points at (-x, -y), (-x, +y), (+x, -y) and (+x, +y). That is more efficient because it gives you 4 points for the price of 1 sqrt.

Depending on your implementation, that's a lot of sqrt's (which are expensive computationally). However, that should give you an idea.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

Thank you! I came across that formula shortly before heading out for groceries, having you reply with it saves me the trouble of determining if that's what I needed. Thanks for the quick reply and with 2 edits!

Here is some code I've used in the past. Fully integer based, which may or may not be needed, but it draws an ellipse within a rectangle.


void FrameEllipse(long left,long top,long right,long bottom)
{
	long		a,b,x,y,temp;
	long long	d1,d2;
	long long	a2,b2,a2b2,a2sqr,b2sqr,a4sqr,b4sqr;
	long long	a8sqr,b8sqr,a4sqr_b4sqr;
	long long	fn,fnw,fw;
	long long	fnn,fnnw,fnwn,fnwnw,fnww,fww,fwnw;

	if(right < left)
	{
		temp = left;
		left = right;
		right = temp;
	}
	if(bottom < top)
	{
		temp = top;
		top = bottom;
		bottom = temp;
	}

	a = (right - left) / 2;
	b = (bottom - top) / 2;

	x = 0;
	y = b;

	a2 = a * a;
	b2 = b * b;
	a2b2 = a2 + b2;
	a2sqr = a2 + a2;
	b2sqr = b2 + b2;
	a4sqr = a2sqr + a2sqr;
	b4sqr = b2sqr + b2sqr;
	a8sqr = a4sqr + a4sqr;
	b8sqr = b4sqr + b4sqr;
	a4sqr_b4sqr = a4sqr + b4sqr;

	fn = a8sqr + a4sqr;
	fnn = a8sqr;
	fnnw = a8sqr;
	fnw = a8sqr + a4sqr - b8sqr * a + b8sqr;
	fnwn = a8sqr;
	fnwnw = a8sqr + b8sqr;
	fnww = b8sqr;
	fwnw = b8sqr;
	fww = b8sqr;
	d1 = b2 - b4sqr * a + a4sqr;

	while((fnw < a2b2) || (d1 < 0) || ((fnw - fn > b2) && (y > 0)))
	{
		SetPixel(right - x,bottom - y,Color.white);
		SetPixel(left + x,bottom - y,Color.white);
		SetPixel(left + x,top + y,Color.white);
		SetPixel(right - x,top + y,Color.white);

		y--;
		if((d1 < 0) || (fnw - fn > b2))
		{
			d1 += fn;
			fn += fnn;
			fnw += fnwn;
		}else{
			x++;
			d1 += fnw;
			fn += fnnw;
			fnw += fnwnw;
		}
	}

	fw = fnw - fn + b4sqr;
	d2 = d1 + (fw + fw - fn - fn + a4sqr_b4sqr + a8sqr) / 4;
	fnw += b4sqr - a4sqr;

	while(x <= a)
	{
		SetPixel(right - x,bottom - y,Color.white);
		SetPixel(left + x,bottom - y,Color.white);
		SetPixel(left + x,top + y,Color.white);
		SetPixel(right - x,top + y,Color.white);

		x++;
		if(d2 < 0)
		{
			y--;
			d2 += fnw;
			fw += fwnw;
			fnw += fnwnw;
		}else{
			d2 += fw;
			fw += fww;
			fnw += fnww;
		}
	}
} 

This topic is closed to new replies.

Advertisement