C# - generating points along a fraction of a circles circumference - c#

I have the below algorithm which generates a number of points along the circumference of a circle for collision events in my program. (This works perfectly as far as I can tell).
bool Collision_True = false;
for (int Angle = 0; Angle <= 359; Angle += 5)
{
int X = (CentreX + (Radius * Math.Cos(Angle));
int Y = (CentreY + (Radius * Math.Sin(Angle));
Point point = new Point(X, Y);
if (Collision_True == false)
{
Collision_True = Player_Collisions(point);
}
}
return Collision_True;
However I want to change this so it only generates points on the bottom third of the circle, I tried changing the values in the for loop as follows:
for (int Angle = 120; Angle <= 240; Angle += 5)
{
...
}
But the points generated are still around the complete circumference of the circle instead of just the bottom third.
Any ideas? Thanks.

You need to convert to radians
for (int angleDegrees = 120; angleDegrees <= 240; angleDegrees += 5)
{
double angleRadians = angleDegrees / 180 * Math.PI;
int X = (CentreX + (Radius * Math.Cos(angleRadians));
int Y = (CentreY + (Radius * Math.Sin(angleRadians));
...

Related

Get random point on circle on a segment that has a specific heading

I have a circle, with a specific radius. Inside the circle I have a point with the X, Y coords. I also have a heading, for example 210. How can I get a random point INSIDE THE CIRCLE on the segment that I draw from the point to the margin of the circle? Thanks!
double radiusCircle = 10;
double y = -3;
double x = -Math.Sqrt(3 * 9);
double angleRad = Math.Atan2(y, x);
double angleDeg = angleRad * 180 / Math.PI; // 210 (-150) degrees
double distancePointCenter = Math.Sqrt(x * x + y * y);
double distancePointMargin = radiusCircle - distancePointCenter;
Random rand = new Random(123);
for (int i = 0 i < 10; i++)
{ // Generate 10 random points
double randomPointDistToCenter = distancePointCenter + distancePointMargin * rand.NextDouble();
double xRandomPoint = randomPointDistToCenter * Math.Cos(angleRad);
double yRandomPoint = randomPointDistToCenter * Math.Sin(angleRad);
}

How to decrease and increase values as a curve

I am trying to do a digging tool for my game, I have x and y coordinates of point A and B, what I want to do is create a curve between these points, nothing graphical I just need loop through the coordinates (float x, float y).
I am not good at explaining so here is a visual example;
The first image is what's happen if I just use a for loop to decrease the y value until middle and then increase it from the middle to end.
//Very specific code for my example
//I wrote it just for this example so I am not sure if it works
float y;
float x;
public void Example(float startX, float endX, float startY, float endY, float depth)
{
y = startY;
x = startX;
float changeAmountOfY = depth / (endX - startX);
for (int i = (int)startX; i < (startX + endX) / 2; i++)
{
x++;
y -= changeAmountOfY;
}
for (int i = (int)(startX + endX) / 2; i < endX; i++)
{
x++;
y += changeAmountOfY;
}
}
public void ChangeCoordinates()
{
Example(100f, 200f, 100f, 100f, 50f);
}
The second image is what I need.
I am developing the game on unity and I am using Vector2 for the coordinates but it is not important.
Pure C# or even C++ is welcome.
It is also fine if someone can just explain the math behind what I am trying to do.
Maybe this can help:
// Calculate radius
int radius = (B.X - A.X) / 2;
// Calculate middle
int middle_x = A.X + radius;
int middle_y = A.Y;
// or
int middle_y = (A.Y + B.Y) / 2;
// Coordinates for a semicircle
// 0 to 180 degree
for (int i = 0; i <= 180; i++)
{
double x_coordinate = middle_x + radius * Math.Cos(i * Math.PI / 180);
// Opened to bottom
double y_coordinate = middle_y + radius * Math.Sin(i * Math.PI / 180);
// or opened to top
double y_coordinate = middle_y - radius * Math.Sin(i * Math.PI / 180);
}
Take a look at unit circle.

Drawing triangles given user input

So I'm trying to make a Program that will draw a triangle given some user input. The variables that the user provides are angleA, angleB, andleC, and the corresponding sides. The code I have set up to find the three points of the angle is as follows.
double angle_A = double.Parse(angleA.Text);
double angle_B = double.Parse(angleB.Text);
double angle_C = double.Parse(angleC.Text);
double side_A = double.Parse(sideA.Text);
double side_B = double.Parse(sideB.Text);
double side_C = double.Parse(sideC.Text);
double triangleHeight = Area * 2 / (double.Parse(sideB.Text));
double height = canvas.Height;
double width = canvas.Width;
int aX, aY, bX, bY, cX, cY;
aY = Convert.ToInt32(canvas.Height - triangleHeight / 2);
if (angle_A <= 90 && angle_C <= 90)
{
aX = Convert.ToInt32((width - side_B) / 2);
}
else if (angle_A > 90)
{
double extraLength = Math.Sqrt(Math.Pow(side_C, 2) - Math.Pow(triangleHeight, 2));
aX = Convert.ToInt32(width - ((width - (side_B + extraLength)) / 2) + side_B);
}
else if (angle_C > 90)
{
double extraLength = Math.Sqrt(Math.Pow(side_A, 2) - Math.Pow(triangleHeight, 2));
aX = Convert.ToInt32((width - side_B + extraLength) / 2);
}
else
{
aX = 0;
MessageBox.Show("ERROR: No such triangle exists", "ERROR:");
}
cX = aX + Convert.ToInt32(side_B);
cY = aY;
bX = Convert.ToInt32(side_A * Math.Cos(Math.PI * angle_C / 180) + cX);
bY = Convert.ToInt32(side_A * Math.Sin(Math.PI * angle_C / 180) - cY);
Point pointA = new Point(aX, aY);
Point pointB = new Point(bX, bY);
Point pointC = new Point(cX, cY);
Point[] points = new Point[3] { pointA, pointB, pointC };
return points;
This returns the three points that the paint method should use to draw the triangle. However, when I insert the values, the triangle it draws looks nothing like the triangle I have described with the user input. Any thoughts on why this is? Thanks in advance.
P.S. The error is not in my code, as it gives me no errors and does not crash. It is strictly a math error that I have not been able to locate.
I imagine the triangle ABC with corners A and C along the base line with A to the left and C to the right, and B somewhere above them. Side A is the side opposite corner A, and so on.
As Damien_the_Unbeliever says, you should only allow input of, say, side B, side C and angle of corner A. Validate that A is not over 180 degrees. Start off with A at the origin, so we know straight away that xA = 0, yA = 0, xC = length of side B, yC=0, xB = side C * cos A, and yB = side C * sin A. I believe this works even if A is over 90 degrees, you do get a negative value for xB but don't worry, continue anyway!
Now all you have to do is centre the triangle on the canvas. I don't understand where you are getting Area from. It makes no sense to calculate the triangle's height from its area. The triangle height is yB, you can calculate the offset you need to centre it vertically as you know, so long as yB <= height. Add the same y offset to all the points.
The horizontal offset is a bit more complicated! If xB is negative, I would add an offset to all the x values to bring xB to 0, this positions your triangle at the left side of the canvas, and its width is given by the new xC. If xB is non-negative, the width is the maximum of xC or xB. Then you can calculate the x offset from the width as you know.
I have had time to do some of the code, for example values; this will draw a triangle but not yet centre it:
int sideB = 100;
int sideC = 143;
int angleA = 28;
double angleARadians = Math.PI * angleA / 180.0;
int[] xs = new int[3];
int[] ys = new int[3];
//1st corner is at the origin
xs[0] = 0; ys[0] = 0;
//Then the third corner is along the x axis from there to the length of side B
xs[2] = sideB; ys[2] = 0;
// The second corner is up a bit above the x axis. x could be negative.
// Note, when you draw it, the y axis extends downwards, so a positive y value will be drawn below the x axis.
xs[1] = (int)Math.Round(sideC * Math.Cos(angleARadians));
ys[1] = (int)Math.Round(sideC * Math.Sin(angleARadians));
//If Bx is negative, move all the points over until it's 0
if (xs[1] < 0)
{
int zeroX = xs[1] * -1;
for (int i = 0; i < 3; i++)
{
xs[i] += zeroX;
}
}
// Now centre the triangle on the canvas.
// Firstly find the width of the triangle. Point B could be to the left of A, or between A and C, or to the right of C.
// So the left most point of the triangle is the minimum of A or B, and the right most point is the maximum of B or C.
int minX = Math.Min(xs[0],xs[1]);
int maxX = Math.Max(xs[2], xs[1]);
//The height of the triangle is yB.
int offsetX = (panCanvas.Width - (maxX - minX)) / 2;
int offsetY = (panCanvas.Height - ys[1]) / 2;
//offset all the points by the same amount, to centre the triangle.
for (int i = 0; i < 3; i++)
{
xs[i] += offsetX;
ys[i] += offsetY;
}
Given the three sides of a triangle a, b, and c the coordinates of the vertices are
P=[0,0]
Q=[a,0]
R=[(a^2+c^2-b^2)/(2*a), sqrt(c^2*(2*(a^2+b^2)-c^2)-(a+b)^2*(a-b)^2)/(4*a^2))]
Example, a=6, b=4 and c=8
P=[0,0]
Q=[6,0]
R=[7,√15]

Moving rectangle is not moving according to coordinates given

I have a picturebox with a picture as a background (infact a map), and on it I am spawning rectangles. These rectangles are supposed to move by given points. The rectangle is moving with assigned speed, and after reaching (or getting close) to one of the points, it starts moving to the next one. My problem however is, the rectangle doesnt move directly to the given point, it is just proceeding to get close to only one of the coordinates, so there are situations where the Y coordinate of the rectangle, and the Y coordinate of the point are the same, but the rectangle is like 60 pixels of and wont move.
Below I am adding a picture as an example of the movement. Blue is expected route, red is the actual one. I have checked the coordinates like a hundred times, they are correct, the rectangle is just moving elsewhere. Note: this only happens at some of the points.
Here is the code I am using to count the movement of the rectangle relative to axis X and Y.
public void Move_calculate(Graphics g)
{
if (points[passed].X == 0 || points[passed].Y == 0) // this happens when the rectangle reaches it final point - it stays where it is (working fine)
{
Redraw(g);
return;
}
speed = randomNumbers.Next(7, 13);
if (points[passed].X > x_coordinate && points[passed].Y > y_coordinate)
{
Bx = points[passed].X;
By = points[passed].Y;
distanceForAlfaX = Bx - x_coordinate; // x_coordinate is the x coordinate of the rectangle
distanceForAlfaY = By - y_coordinate;
if (distanceForAlfaX <= 20 || distanceForAlfaY <= 20) speed = 5; // slowing down when approaching the point
if (distanceForAlfaX + distanceForAlfaY <= 15) passed += 1;
alpha = (distanceForAlfaY / distanceForAlfaX); // tangent alpha
x_change = (int)(speed * (Math.Cos(alpha))); // get distance moved relative to axis X
y_change = (int)Math.Sqrt(((speed * speed) + (x_change * x_change))); // again distance for axis Y, using Pythagoras theorem
x_coordinate += x_change;
y_coordinate += y_change;
}
else if (points[passed].X > x_coordinate && points[passed].Y < y_coordinate)
{
Bx = points[passed].X;
By = points[passed].Y;
distanceForAlfaX = Bx - x_coordinate;
distanceForAlfaY = y_coordinate - By;
if (distanceForAlfaX <= 20 || distanceForAlfaY <= 20) speed = 5;
if (distanceForAlfaX + distanceForAlfaY <= 15) passed += 1;
alpha = (distanceForAlfaY / distanceForAlfaX);
x_change = (int)(speed * (Math.Cos(alpha)));
y_change = (int)Math.Sqrt(((speed * speed) + (x_change * x_change)));
x_coordinate += x_change;
y_coordinate -= y_change;
}
else if (points[passed].X < x_coordinate && points[passed].Y > y_coordinate)
{
Bx = points[passed].X;
By = points[passed].Y;
distanceForAlfaX = x_coordinate - Bx;
distanceForAlfaY = By - y_coordinate;
if (distanceForAlfaX <= 20 || distanceForAlfaY <= 20) speed = 5;
if (distanceForAlfaX+distanceForAlfaY <= 15) passed += 1;
alpha = (distanceForAlfaY / distanceForAlfaX);
x_change = (int)(speed * (Math.Cos(alpha)));
y_change = (int)Math.Sqrt(((speed * speed) + (x_change * x_change)));
x_coordinate -= x_change;
y_coordinate += y_change;
}
else if (points[passed].X < x_coordinate && points[passed].Y < y_coordinate)
{
Bx = points[passed].X;
By = points[passed].Y;
distanceForAlfaX = x_coordinate - Bx;
distanceForAlfaY = y_coordinate - By;
if (distanceForAlfaX <= 20 || distanceForAlfaY <= 20) speed = 5;
if (distanceForAlfaX + distanceForAlfaY <= 15) passed += 1;
alpha = (distanceForAlfaY / distanceForAlfaX);
x_change = (int)(speed * (Math.Cos(alpha)));
y_change = (int)Math.Sqrt(((speed * speed) + (x_change * x_change)));
x_coordinate -= x_change;
y_coordinate -= y_change;
}
else
{
MessageBox.Show("Something went wrong"); // just notify me that it isnt working again..
}
Pen p = new Pen(Color.Turquoise, 2);
r = new Rectangle(x_coordinate, y_coordinate, 5, 5); // redraw the rectangle
g.DrawRectangle(p, r);
p.Dispose();
}
I have no idea why this is happening, could anyone help with this?
P.S.
There is absolutely no need for the movement to be smooth, the positions of rectangles will be updated once per two seconds using a Timer. For now it is temporarily set to a button.
EDIT:
Here is the foreach code. The labels are just the coordinates shown next to the PictureBox
foreach (aircraft acft in aircrafts) // aircraft is an array aircrafts[]
{
label2.Text = "xp" + acft.points[acft.passed].X;
label3.Text = "yp" + acft.points[acft.passed].Y;
label4.Text = acft.passed.ToString();
label5.Text = "y" + acft.y_coordinate.ToString();
//MessageBox.Show(acft.points[0].X.ToString());
acft.Move_calculate(e.Graphics);
spawn = string.Empty;
}
EDIT2: All variables in aircraft class
public string callsign;
public int speed;
public double heading;
public bool moving = false;
public Point[] points;
public double alpha;
public int x_change;
public int y_change;
public int x_coordinate;
public int y_coordinate;
public int Bx;
public int By;
public double distanceForAlfaX;
public double distanceForAlfaY;
public int passed = 0;
public Rectangle r;
I guess, there's a math mistake in
y_change = (int)Math.Sqrt(((speed * speed) + (x_change * x_change)));
Moreover...
// again distance for axis Y, using Pythagoras theorem
Let Mr.Pythagoras be, I would rather use the same as for X axis
y_change = (int)(speed * (Math.Sin(alpha)));
Have you checked your coordinate system? (https://web.archive.org/web/20140710074441/http://bobpowell.net/coordinatesystems.aspx)
Sorry, wrong link for your issue. Try debugging using Control.PointToClient to make sure all coordinates are expressed in client space. (https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.control.pointtoclient)
You could try:
Point cPoint = this.PointToClient(new Point(x_coordinate, y_coordinate));
Size cSize = new Size(5,5);
r = new Rectangle(cPoint, cSize); // redraw the rectangle
g.DrawRectangle(p, r);
Could you post the data types of your variables to clarify your code? You might be losing precision somewhere, especially if you're using integer division.
(Note for DJ KRAZE, a -= b; in C# can also mean a = a - b; Context matters.)

Moving the mouse along a diagonal line

What kind of math algorithm could I use to calculate the path to move a mouse? I simply want to have this type of function:
animateMouseDiag(int X, int Y){
//Move mouse 1 step towards goal, for loop most likely, from the current Mouse.Position
Thread.Sleep(1);
}
For example, if I give it animateMouseDiag(100,300), it would move the mouse 100 to the right and 300 down, but diagonally, not right-then-down in an 'L'. Similarly, if I gave it (-50,-200) it would move it to those relative coordinates (50 left and 200 up) along the diagonal path.
Thank you! (By the way, this is an alt account since I feel like an idiot asking about basic high school math on my main. I just can't translate it into programming.)
EDIT: I have come up with this:
public static void animateCursorTo(int toX, int toY)
{
double x0 = Cursor.Position.X;
double y0 = Cursor.Position.Y;
double dx = Math.Abs(toX-x0);
double dy = Math.Abs(toY-y0);
double sx, sy, err, e2;
if (x0 < toX) sx = 1;
else sx = -1;
if (y0 < toY) sy = 1;
else sy = -1;
err = dx-dy;
for(int i=0; i < toX; i++){
//setPixel(x0,y0)
e2 = 2*err;
if (e2 > -dy) {
err = err - dy;
x0 = x0 + sx;
}
if (e2 < dx) {
err = err + dx;
y0 = y0 + sy;
}
Cursor.Position = new Point(Convert.ToInt32(x0),Convert.ToInt32(y0));
}
}
This is Bresenham's line algorithm. Strangely though, the lines don't draw on a set angle. They seem to be gravitating towards the top left of the screen.
Store the position coordinates as floating point values, then you can represent the direction as a unit vector and multiply by a specific speed.
double mag = Math.Sqrt(directionX * directionX + directionY * directionY);
mouseX += (directionX / mag) * speed;
mouseY += (directionY / mag) * speed;

Categories

Resources