Jump to content

[C#] circular menu


Recommended Posts

Hey

 

 

So, I am making a circular menu, but I am stuck with the button position.

I created my circular menu (with the button, background, etc.) on Photoshop, then split each button of the circular menu (on photoshop).

Now on visual studio, I am assigning a PictureBox for each button, but:

 

How can I calculate the X & Y position for each button ? Because right now, the only solution I see is to try manually values, but it won't look good (and not be really circular ...)

 

I am using a base circle in the middle, which the location is:

And the other buttons of the menu, are supposed to be around it.

 

Thanks.

Edited by nordi
Link to comment
https://gtaforums.com/topic/705894-c-circular-menu/
Share on other sites

pedro2555

Somewhere on this forum I've explained this process already.

 

If I understood correctly, what you want is a Point (x an y), for a given radius and angle, is that correct ?

 

If yes, that is achieved with the trigonometric functions Sin and Cos, which are available within the Math class in .NET.

 

Basically for a given point 'a,b' at the center of a circumference of radius 'c', to get a point 'd,e' on the circumference perimeter at angle 'f', you would use:

d = a + (sin(f) * c)e = b + (cos(f) * c)

Note that 'f' is expressed in radians.

radians = degrees / 180

Point coordinates are expressed as 'x,y', for the corresponding axis.

 

Don't take my word for this, I haven't tested before posting, and so, I provide this information as is.

Edited by pedro2555
Link to comment
https://gtaforums.com/topic/705894-c-circular-menu/#findComment-1065311622
Share on other sites

Note that 'f' is expressed in radians.

radians = degrees / 180

 

You forgot to multiply by Pi ;)

Link to comment
https://gtaforums.com/topic/705894-c-circular-menu/#findComment-1065314676
Share on other sites

Somewhere on this forum I've explained this process already.

 

If I understood correctly, what you want is a Point (x an y), for a given radius and angle, is that correct ?

 

If yes, that is achieved with the trigonometric functions Sin and Cos, which are available within the Math class in .NET.

 

Basically for a given point 'a,b' at the center of a circumference of radius 'c', to get a point 'd,e' on the circumference perimeter at angle 'f', you would use:

d = a + (sin(f) * c)e = b + (cos(f) * c)

Note that 'f' is expressed in radians.

radians = degrees / 180

Point coordinates are expressed as 'x,y', for the corresponding axis.

 

Don't take my word for this, I haven't tested before posting, and so, I provide this information as is.

 

Thanks, that's what I needed !

Link to comment
https://gtaforums.com/topic/705894-c-circular-menu/#findComment-1065315414
Share on other sites

pedro2555

@Silent

 

I forgot pi indeed, the actual conversion goes as:

radians = pi * degrees / 180

@nordi

 

Please re-check the degree to radian calculation with the formula above. Also your calculations seem wrong.

 

Where you have:

double X2 = Game.Resolution.Width / 2f + (Math.Sin(15 / 180 * Math.PI) * 45);double Y2 = Game.Resolution.Height / 2f + (Math.Cos(15 / 180 * Math.PI) * 45);

I believe you want to place something at 15 degrees, if so try the snippet bellow,

double X2 = menu.Location.X + Math.Sin(Math.PI * 15 / 180) * 45;double Y2 = menu.Location.Y + Math.Cos(Math.PI * 15 / 180) * 45;

also,

Game.Resolution.Width / 2f

is redundant, since it is first calculated and store in menu.Location.X.

 

And since 15 degrees is static, you should calculate on the side and pass the radians hardcoded to void unnecessary bottlenecks.

Edited by pedro2555
Link to comment
https://gtaforums.com/topic/705894-c-circular-menu/#findComment-1065317338
Share on other sites

@nordi

 

Please re-check the degree to radian calculation with the formula above. Also your calculations seem wrong.

 

Where you have:

double X2 = Game.Resolution.Width / 2f + (Math.Sin(15 / 180 * Math.PI) * 45);double Y2 = Game.Resolution.Height / 2f + (Math.Cos(15 / 180 * Math.PI) * 45);

I believe you want to place something at 15 degrees, if so try the snippet bellow,

double X2 = menu.Location.X + Math.Sin(Math.PI * 15 / 180);double Y2 = menu.Location.Y + Math.Cos(Math.PI * 15 / 180);

also,

Game.Resolution.Width / 2f

is redundant, since it is first calculated and store in menu.Location.X.

 

 

After doing some research on google, it appears, Cos have to be used for the X value, and Sin for the Y value.

After spending time, trying different values & doing some edit to the formula you provided, I managed to get the right degrees for the button position, the only problem left is the button positions: For some reason the X & Y of the base circle seems to be wrong (A & B, on your formula), but the weirdest thing is that 2 buttons are at the correct position, while the other 3 buttons are misplaced (i'm using the same formula for all of the buttons though, which should give me whether the right position for all buttons or the wrong position for all ...).

 

Here is the current code: (X3 & Y3 ; X5 & Y5 are at the correct position, but others are not)

Edited by nordi
Link to comment
https://gtaforums.com/topic/705894-c-circular-menu/#findComment-1065320499
Share on other sites

pedro2555

I told you I haven't tested anything, I went for memory and it has been a long time since I made use of this (school time actually).

 

I think you have no clue what trigonometry is, I will not give a full blow explanation, but the following picture should help you:

trigonometric-table-1_opt.jpg

 

So, yes, from the table Cosine is Y while Sine is X. My bad there. You should also note that they return a value for a radius of 1 with center at 0,0. That's why you have to sum the actual center and multiply by the actual radius.

 

The following code is tested and draws a perfect circle

// Draw a circle (values in pixels)// Circle center pointPoint center = new Point(canvas.Width / 2, canvas.Height / 2);// Center radiusint radius = 30;// Last used point for drawing a linePoint lastPoint = Point.Empty;// Current point being calculatedPoint currentPoint = Point.Empty;for (int i = 0; i < 360; i++){	// Calculate a new point	currentPoint = new Point(		(int)(center.X + Math.Cos(Math.PI * i / 180) * radius),  // Calculate X		(int)(center.Y + Math.Sin(Math.PI * i / 180) * radius)); // Calculate Y	// If we a have last point, draw a line	if (lastPoint != Point.Empty)		e.Graphics.DrawLine(new Pen(Color.Black), lastPoint, currentPoint);	lastPoint = currentPoint;}

The icons are offset because you are using point based on screen but their parent is the form. If you draw them at 0,0 they should appear on the top left corner of the form and not the screen.

Edited by pedro2555
  • Like 1
Link to comment
https://gtaforums.com/topic/705894-c-circular-menu/#findComment-1065320572
Share on other sites

I told you I haven't tested anything, I went for memory and it has been a long time since I made use of this (school time actually).

 

I think you have no clue what trigonometry is, I will not give a full blow explanation, but the following picture should help you:

 

 

So, yes, from the table Cosine is Y while Sine is X. My bad there. You should also note that they return a value for a radius of 1 with center at 0,0. That's why you have to sum the actual center and multiply by the actual radius.

 

The following code is tested and draws a perfect circle

// Draw a circle (values in pixels)// Circle center pointPoint center = new Point(canvas.Width / 2, canvas.Height / 2);// Center radiusint radius = 30;// Last used point for drawing a linePoint lastPoint = Point.Empty;// Current point being calculatedPoint currentPoint = Point.Empty;for (int i = 0; i < 360; i++){	// Calculate a new point	currentPoint = new Point(		(int)(center.X + Math.Cos(Math.PI * i / 180) * radius),  // Calculate X		(int)(center.Y + Math.Sin(Math.PI * i / 180) * radius)); // Calculate Y	// If we a have last point, draw a line	if (lastPoint != Point.Empty)		e.Graphics.DrawLine(new Pen(Color.Black), lastPoint, currentPoint);	lastPoint = currentPoint;}

The icons are offset because you are using point based on screen but their parent is the form. If you draw them at 0,0 they should appear on the top left corner of the form and not the screen.

 

 

I do understand how it works, especially after reading this: http://www.wikihow.com/Calculate-the-Radius-of-a-Circle But, I can't get it to work ! Here is how I understand things, based on your last code:

  • center, is the coordinates of the center of the circle, which on my code is menu.Location.X & menu.Location.Y ;
  • i on your code, is the coordinates of the point(x & y) on the circle, which is my X1, Y1 ; X2, Y2 ; X3,Y3 ; etc.
  • radius: is the distance between the center of the circle and the point on the circle, which on my code is 38.

After multiple try, I managed to get the correct i, and the correct radius because the button are well placed regarding these 2 values. So obviously, the problem can only come from the circle center coordinates (because the angle, and radius is fine, but the position on the circle isn't). Plus I'm using exactly the same formula as you do, so it can't be a code / formula error ;).

 

My form position is: the Game resolution /2, and the menu position (the center of the circle) is the form position /2

fire extinguisher but you can't see it very well it's on the right bottom)

Edited by nordi
Link to comment
https://gtaforums.com/topic/705894-c-circular-menu/#findComment-1065321034
Share on other sites

pedro2555

We are complicating this. Take a look at following code, it is a windows form project, with a panel called canvas. The following is the method Load():

// canvas is the parent container of our pictures, so parent and canvas are the same thing and in your case are the form itself// Center of the circle is at parent.width/2, parent.height/2// Circle radius is 38// Each quadrant image is 38x38// Quadrants ids go like this////   2  |1//   ___|____//   3  |4//      |//// Note: //      1. There is no need to wrap all images inside an image box, you can simply place the four image boxes on the form itself. This isn't HTML ;D.//      2. All elements have their point 0 at the top left corner, not their center//      3. Since it is only 4 images this can be very much simple//          Basically you have for diferent locations://              1 - 0,-1//              2 - -1,-1//              3 - -1,0//              4 - 0,0// Canvas centerPoint center = new Point(	canvas.Width / 2,	canvas.Height / 2);// circle radiusint radius = 38;// the easieast is the fourth quadrant, the image box should have it's top left corner at point 0 of the circlePictureBox fourthQuadrant = new PictureBox();fourthQuadrant.Location = center;fourthQuadrant.Size = new Size(38, 38); // 0,0fourthQuadrant.BorderStyle = BorderStyle.FixedSingle;canvas.Controls.Add(fourthQuadrant);// the first quadrant should have axis X of it's location also at 0, but the Y axis must be shifted to the edge of the circlePictureBox firstQuadrant = new PictureBox();firstQuadrant.Location = new Point(	center.X,	center.Y - radius); firstQuadrant.Size = new Size(38, 38);firstQuadrant.BorderStyle = BorderStyle.FixedSingle;canvas.Controls.Add(firstQuadrant);// the remaining quadrants are the mirrors// second quadrant is the mirror of the firstPictureBox secondQuadrant = new PictureBox();secondQuadrant.Location = new Point(	center.X - radius,	center.Y - radius);secondQuadrant.Size = new Size(38, 38);secondQuadrant.BorderStyle = BorderStyle.FixedSingle;canvas.Controls.Add(secondQuadrant);// the third is the mirror of the fourtPictureBox thirdQuadrant = new PictureBox();thirdQuadrant.Location = new Point(	center.X - radius,	center.Y);thirdQuadrant.Size = new Size(38, 38);thirdQuadrant.BorderStyle = BorderStyle.FixedSingle;canvas.Controls.Add(thirdQuadrant);
Edited by pedro2555
Link to comment
https://gtaforums.com/topic/705894-c-circular-menu/#findComment-1065321292
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • 0 User Currently Viewing
    0 members, 0 Anonymous, 0 Guests

×
×
  • Create New...

Important Information

By using GTAForums.com, you agree to our Terms of Use and Privacy Policy.