Function that calculates diffrent positions from an array c# - c#

I have a problem that I need help solving. Im supposed to create a function that calculates the distance between two positions. The positions are stored in two arrays, I can use as many parameters that I need to do this calculation
static double[] Latitudes = new double[] {
59.3261917, 57.7010496, 59.8939529, 65.5867395, 60.11021, 52.5069312, 48.859
};
static double[] Longitudes = new double[] {
17.7018773, 11.6136602, 10.6450348, 22.0422998, 24.7385057, 13.1445521, 2.2069765
};
I have been given an equation that will help me calculate the distance
distance = Math.sqrt( (x1 - x2)2 + (y1 - y2)2 )
My problem is that I can't get the elements from the arrays to the variables inside the function

Extract methods, split you problem into minor ones:
// Initial step:
// Distance between points
private static double Distance(double x1, double y1, double x2, double y2) {
return Math.Sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
}
// Next step:
// Distance between points given as arrays' items indexes
private static double Distance(double[] xs, double[] ys, int indexFrom, indexTo) {
return Distance(xs[indexFrom], ys[indexFrom], xs[indexTo], ys[indexTo]);
}
Then use
// What is the distance between 0-th and 2-nd point?
double result = Distance(Latitudes, Longitudes, 0, 2);
Console.WriteLine(result);
// What is the distance between all the points?
for (int from = 0; from < Math.Min(Latitudes.Length, Longitudes.Length); ++from)
for (int to = from + 1; to < Math.Min(Latitudes.Length, Longitudes.Length); ++to) {
Console.WriteLine($"Distance from item #{from} to item #{to} is {Distance(Latitudes, Longitudes, from, to)}");
}

Well first you need to decide which positions you want to compare. This would be done by index. Lets says you want to compare positions at index 0 with positions at index 2. Then the code to get the correct variables would be:
double x1 = Latitudes[0];
double y1 = Longitudes[0];
double x2 = Latitudes[2];
double y2 = Longitudes[2];
You can then feed those values into your function. Your function code is wrong and won't compile. The correct call for the function would be:
double distance = Math.Sqrt(Math.Pow(x1 - x2, 2) + Math.Pow(y1 - y2, 2));
In the interest of providing a more complete function for your class, and keeping in mind that your arrays are static, this will allow you to get the distance from any two given points based on index. Also, I expect this is a homework assignment so I am leaning towards your requirement to be creating a function similar to this:
double CalculateDistance(int index1, int index2)
{
double x1 = Latitudes[index1];
double y1 = Longitudes[index1];
double x2 = Latitudes[index2];
double y2 = Longitudes[index2];
return Math.Sqrt(Math.Pow(x1 - x2, 2) + Math.Pow(y1 - y2, 2));
}
You can then call this function as follows:
double distance = CalculateDistance(0, 2);

Show distance for all pairs
if (Latitudes.Length == Longitudes.Length)
{
for (int i = 0; i < Latitudes.Length - 1; i = i + 2)
{
double x1 = Longitudes[i];
double x2 = Longitudes[i + 1];
double y1 = Latitudes[i];
double y2 = Latitudes[i + 1];
double distance = Math.Sqrt(Math.Pow(x1 - x2, 2) + Math.Pow(y1 - y2, 2));
Console.WriteLine($"x1 = {x1}; x2 = {x2}; y1 = {y1}; y2 = {y2}; distance {distance}");
}
}

Related

Alternative to If Statements for dynamic use

I'm attempting to add a conditional test to the onpaint method using the Quantower API. While I'm not asking specific questions about that API, my query relates to the correct use for conditional tests.
What i'm trying to achieve is:
If current price is above a target price, draw a line;
if current price is above the line drawn in 1 above, draw another line; and so on.
At the moment, I have the code below (simplified for this post) which is nested if statements. What I was looking for was 1) is there a more efficient way of achieving the same result without nested if statements; and 2) how to make it dynamic (i.e. so its not limited to only 5 if statements and therefore 5 lines - if price increased significantly, 10 lines might need to be drawn)
double PTLevel = 10.5;
double PT1 = this.HighPrice.Value + PTLevel;
double PT2 = PT1 + PTLevel;
double PT3 = PT2 + PTLevel;
double PT4 = PT3 + PTLevel;
double PT5 = PT4 + PTLevel;
if (bar.Close > this.HighPrice.Value)
{
float PT1 = (float)this.CurrentChart.MainWindow.CoordinatesConverter.GetChartY(PT1);
graphics.DrawLine(Pen.Purple, X1, PT1, X2, PT1);
if (bar.Close > PT1)
{
float PT2 = (float)this.CurrentChart.MainWindow.CoordinatesConverter.GetChartY(PT2);
graphics.DrawLine(Pen.Purple, X1, PT2, X2, PT2);
if (bar.Close > PT2)
{
float PT3 = (float)this.CurrentChart.MainWindow.CoordinatesConverter.GetChartY(PT3);
graphics.DrawLine(Pen.Purple, X1, PT3, X2, PT3);
if (bar.Close > PT3)
{
float PT4 = (float)this.CurrentChart.MainWindow.CoordinatesConverter.GetChartY(PT4);
graphics.DrawLine(Pen.Purple, X1, PT4, X2, PT4);
if (bar.Close > PT4)
{
float PT5 = (float)this.CurrentChart.MainWindow.CoordinatesConverter.GetChartY(PT5);
graphics.DrawLine(Pen.Purple, X1, PT5, X2, PT5);
}
}
}
}
}
Xerillo's answer is good, but doesn't express the intent of your code.
This seems more what you are trying to do.
var pricePoint = HighPrice.Value;
while (bar.Close > pricePoint )
{
pricePoint += 10.5;
var y = CurrentChart.MainWindow.CoordinatesConverter.GetChartY(pricePoint);
graphics.DrawLine(Pen.Purple, X1, y, X2, y);
}
Do any casting if you deem necessary. Often it's not.
That's where loops come in handy. Put your prices in a list (in whichever order you need to check them in) and then loop through them updating the target whenever there's a higher value:
var prices = new [] { PT1, PT2, PT3, PT4, PT5 };
var currentTarget = this.HighPrice.Value;
foreach (var price in prices)
{
if (price > currentTarget)
{
currentTarget = this.CurrentChart
.MainWindow
.CoordinatesConverter
.GetChartY(price);
graphics.DrawLine(Pen.Purple, X1, currentTarget, X2, currentTarget);
}
}

Euclidean distance between the coordinates in the array

I calculate euclidean distance in c#.
Point[] points = new Point[100];
I have the coordinates of the points I created in this array.I want to calculate the distance between all points.
for (int i = 1; i < k+1; i++)
{
X1 = points[i].X;
X2 = points[i + 1].X;
Y1 = points[i].Y;
Y2 = points[i + 1].Y;
result = Math.Sqrt((X1 - X2) * (X1 - X2) + (Y1 - Y2) * (Y1 - Y2));
}
With this code I have calculated the distance between points (eg: distance between points a and b, distance between points c and d, etc.) but I couldn't calculate the distance between points a and c or the points b and b I want to calculate the distance between all points in this array. How do I do that?
You have to use 2 loops. The first loop assign values to X1 and the second loop assign values to X2.
This allows to calculate the Euclidean Distance between two points that aren't contiguous in the array.
You have to use 2 for loops to achieve that.
Also you would want to persist the euclidean distances between these points somewhere.
You probably want to go through the array twice.
Point[] points = new Point[100];
for(int i = 0; i < points.Length; i++)
for (int j = points.Length - 1; j >= i; j--)
{
float distance = 0;
if(i != j)
distance = CalculateDistance(points[i], points[j]);
// Do more stuff here
}
Obviously, you could simply run two for loops of equal lengths, but this will give you the same result twice. When i and j have the same value flipped (i = 10, j = 15 and later i = 15 and j = 10), you do the same calculation to get the same result. To prevent that I have my second loop only run about half the values to not redo calculations.
The CalculateDistance method does exactly the same as the code you have written before, in my case the following:
private static float CalculateDistance(Point point1, Point point2)
{
float X1 = point1.X;
float X2 = point1.Y;
float Y1 = point2.X;
float Y2 = point2.Y;
return (float)Math.Sqrt((X1 - X2) * (X1 - X2) + (Y1 - Y2) * (Y1 - Y2));
}
This way I can reuse and reorder my calculations at any time, because I only have to move a single line. Note that you can always just use the floats as parameters instead of locals, but I felt like this way would make it more readable here in this example.
I also skipped the calculations when the distance was equal, because the same values were compared.
public void Euclidea()
{
double result;
int X1,X2,Y1,Y2;
for (int i = 1; i < k+1; i++)
{
X1 = points[i].X;
Y1 = points[i].Y;
for (int j = 0; j < k; j++)
{
X2 = points[j + 1].X;
Y2 = points[j + 1].Y;
result = Math.Sqrt((X1 - X2) * (X1 - X2) + (Y1 - Y2) * (Y1 - Y2));
}
}
}
I solved the problem by typing this code
k=points.length()

Determine If Two Points Are Near

I have the following:
bool AreNear(Point Old, Point Current)
{
int x1 = Convert.ToInt32(Old.X);
int x2 = Convert.ToInt32(Current.X);
int y1 = Convert.ToInt32(Old.Y);
int y2 = Convert.ToInt32(Current.Y);
if (x1 == x2) {
if (y1 == y2) {
return true;
}
}
return false;
}
I want to return true in the function if the current point is in 25 pixels radius of the old point. Can anyone tell me how to do that?
You can use the Pythagorean formula to calculate the distance between two points. In C#:
var d = Math.Sqrt(Math.Pow(x1 - x2, 2) + Math.Pow(y1 - y2, 2))
Why does this work? Have a look at the following diagram and remember that a^2 + b^2 = c^2 holds for right triangles:
Just calculate the square of the distance using Pythagoras' theorem, and compare to the square of the radius:
bool ComparePoints(Point Old, Point Current)
{
int x1 = Convert.ToInt32(Old.X);
int x2 = Convert.ToInt32(Current.X);
int y1 = Convert.ToInt32(Old.Y);
int y2 = Convert.ToInt32(Current.Y);
int dx = x1 - x2;
int dy = y1 - y2;
return (dx*dx + dy*dy) < 25*25;
}
You can use Math.Abs to get the distance:
public static bool InDistance(Point Old, Point Current, int distance)
{
int diffX = Math.Abs(Old.X - Current.X);
int diffY = Math.Abs(Old.Y - Current.Y);
return diffX <= distance && diffY <= distance;
}
use it:
bool arePointsInDistance = InDistance(new Point(100, 120), new Point(120, 99), 25);
Try using the distance formula http://www.purplemath.com/modules/distform.htm and compare the distance <=25

Detect if circle A is completely inside circle B

Below is a function that detects if two circles intersect. I want to change it to only detect if the periferi of the circles intersect. Hence, if circle A is completely inside circle B, there is no collision!
How?
private bool IsCircleCollision(
int x1, int y1, int radius1,
int x2, int y2, int radius2)
{
int dx = x2 - x1;
int dy = y2 - y1;
int distance = (dx * dx) + (dy * dy);
int radii = radius1 + radius2;
if (distance < radii * radii)
{
return true;
}
else
{
return false;
}
}
You work this out by calculating the distance between the two centres, D say. There is an intersection if
abs(R1-R2) < D < R1+R2
where R1 and R2 are the radii of the two circles.
The first test, abs(R1-R2) < D handles the case when one circle's centre is inside the other's. And the second test, D < R1+R2, handles the case when neither circle contains the other's centre.
So, adapting your code we have:
private bool IsCircleCollision(
int x1, int y1, int radius1,
int x2, int y2, int radius2)
{
int dx = x2 - x1;
int dy = y2 - y1;
double D = Math.Sqrt(dx*dx + dy*dy);
return Math.Abs(radius1-radius2)<D && D<radius1+radius2;
}
If performance is important here, you can do without the call to Math.Sqrt like this:
private bool IsCircleCollision(
int x1, int y1, int radius1,
int x2, int y2, int radius2)
{
int dx = x2 - x1;
int dy = y2 - y1;
int Dsqr = dx*dx + dy*dy;
int rdiff = Math.Abs(radius1-radius2);
int rsum = radius1+radius2
return rdiff*rdiff<Dsqr && D<rsum*rsum;
}
The perimeters will be intersecting if and only if the distance between the two centers is less than or equal to the sum of the two radii but greater than or equal to their absolute difference. With this fact, it shouldn't be hard to re-write the function.
You could add a check to see if the distance + radius1 is less than radius2 or distance + radius2 is less than radius1, but then you'll need distance to be the actual distance rather than its square.
else if (Math.Sqrt(dx * dx + dy * dy) < Math.Abs(radius1 - radius2))

Circle collision formula

I have this formula for simple circle collision detection:
private bool CircleCollision(Rectangle Circle1, Rectangle Circle2)
{
int X1 = Circle1.Left;
int Y1 = Circle1.Top;
int X2 = Circle2.Left;
int Y2 = Circle2.Top;
int R1 = Circle1.Width / 2;
int R2 = Circle2.Width / 2;
int Radius = R1 + R2;
int dX = X2 - X1;
int dY = Y2 - Y1;
if (Math.Sqrt((dX * dX) + (dY * dY)) <= Math.Sqrt(Radius * Radius))
return true;
else
return false;
}
But it just expose detection whenever the two circles have same radius. What am I doing wrong?
Solved
int X1 = Circle1.Left + (Circle1.Width / 2);
int Y1 = Circle1.Top + (Circle1.Height / 2);
int X2 = Circle2.Left + (Circle2.Width / 2);
int Y2 = Circle2.Top + (Circle2.Height / 2);
To check if two circles overlap you can do:
var radius=circle1.Radius+circle2.Radius;
var deltaX=circle1.CenterX-circle2.CenterX;
var deltaY=circle1.CenterY-circle2.CenterY;
return deltaX*deltaX + deltaY*deltaY <= radius*radius;
Note that I'm calculating the distance of the centers, not of the top left corners. I'm also comparing with the squared radius so I don't need to use the expensive Math.Sqrt function, but that doesn't affect correctness.
Your code doesn't work because you use Left and Top instead of the position of the center. The difference between the top-left corners is the same as the difference between the centers if the radius is the same. This explains why your code only works in that special case.
Not sure why you use a rectangle to represent a circle. You can calculate the center as centerX = 0.5*(Left+Right). You should also add a check that Width==Height, else you might get an ellipse as parameter, and then this algorithm won't work.

Categories

Resources