Jump to content
  • Advertisement
Sign in to follow this  
Nibbles

Draw ellipse within rectangle

This topic is 1240 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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

 

Share this post


Link to post
Share on other sites
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.

Edited by Buckeye

Share this post


Link to post
Share on other sites

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!

Share this post


Link to post
Share on other sites

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;
		}
	}
} 

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!