» «

9 replies to this topic
nordi
• ##### nordi

Rat

• Members
• Joined: 17 Mar 2014

### #1 Posted 03 May 2014 - 06:09 PM Edited by nordi, 16 August 2014 - 05:36 PM.

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.

pedro2555
• ##### pedro2555

Open Sourcer

• Members
• Joined: 02 Sep 2012

### #2 Posted 03 May 2014 - 10:33 PM Edited by pedro2555, 03 May 2014 - 10:35 PM.

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.

• nordi likes this

Silent
• ##### Silent

Chief Vision™ Alterer

• GTA Mods Staff
• Joined: 01 Feb 2010
Contribution Award [Mods]
Best Script/Plugin 2014 [SilentPatch]
Most Respected 2014
Most Talented [Modding] 2013
Best Map 2013 [ViceCityStories PC Edition]
Best Vehicle 2013 [III Aircraft]
Modder of the Year 2012

### #3 Posted 04 May 2014 - 11:39 AM

Note that 'f' is expressed in radians.

```radians = degrees / 180
```

You forgot to multiply by Pi

nordi
• ##### nordi

Rat

• Members
• Joined: 17 Mar 2014

### #4 Posted 04 May 2014 - 02:18 PM

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 !

nordi
• ##### nordi

Rat

• Members
• Joined: 17 Mar 2014

### #5 Posted 04 May 2014 - 05:44 PM Edited by nordi, 05 May 2014 - 08:26 AM.

The entire circle is 365px * 365px (12.88cm * 12.88cm).

I think the problem is from sin(f), I am using the wrong value ...

pedro2555
• ##### pedro2555

Open Sourcer

• Members
• Joined: 02 Sep 2012

### #6 Posted 04 May 2014 - 07:40 PM Edited by pedro2555, 05 May 2014 - 08:43 AM.

@Silent

I forgot pi indeed, the actual conversion goes as:

```radians = pi * degrees / 180
```

@nordi

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.

nordi
• ##### nordi

Rat

• Members
• Joined: 17 Mar 2014

### #7 Posted 05 May 2014 - 08:43 AM Edited by nordi, 05 May 2014 - 06:27 PM.

@nordi

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)

pedro2555
• ##### pedro2555

Open Sourcer

• Members
• Joined: 02 Sep 2012

### #8 Posted 05 May 2014 - 09:00 AM Edited by pedro2555, 05 May 2014 - 10:01 AM.

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 point
Point center = new Point(canvas.Width / 2, canvas.Height / 2);
// Last used point for drawing a line
Point lastPoint = Point.Empty;
// Current point being calculated
Point 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.

• LordOfTheBongs likes this

nordi
• ##### nordi

Rat

• Members
• Joined: 17 Mar 2014

### #9 Posted 05 May 2014 - 11:13 AM Edited by nordi, 05 May 2014 - 06:26 PM.

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 point
Point center = new Point(canvas.Width / 2, canvas.Height / 2);
// Last used point for drawing a line
Point lastPoint = Point.Empty;
// Current point being calculated
Point 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.c...ius-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)

pedro2555
• ##### pedro2555

Open Sourcer

• Members
• Joined: 02 Sep 2012

### #10 Posted 05 May 2014 - 12:23 PM Edited by pedro2555, 05 May 2014 - 01:17 PM.

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
// 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 center
Point center = new Point(
canvas.Width / 2,
canvas.Height / 2);

// the easieast is the fourth quadrant, the image box should have it's top left corner at point 0 of the circle
fourthQuadrant.Size = new Size(38, 38); // 0,0

// 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 circle
center.X,

// the remaining quadrants are the mirrors
// second quadrant is the mirror of the first

// the third is the mirror of the fourt
center.Y);