I have a list of positions denoted by X and Y. [{3,4}, {5,5}, {6,5},{7,8}]
public class Position {
public int X { get; set; }
public int Y { get; set; }
}
I need to find positions which will be present in the linear graph Starting
x=1 and y=0. [{1,0},{2,1},{3,2},{4,3}, ...].
I do not have the list which denotes the graph. I am looking for a way to find the positions based on starting point of the graph.
I can create the list of possibilities and find the matching positions. Before I do that I want to know is there a better approach?
The points are on a straight line. The formula for the points you mention is: y = x - 1. You can apply this formula in a where clause:
var x = new List<Position>();
...
var pointsOnLine = x.Where(p => p.Y == p.X -1);
You can do this also if you have another line or formula.
Related
Given an array of geo coordinates and another geo coordinate, I would like to find the nearest coordinate(s) to it.
For example, given the array:
lat long
52.525782 13.316927
52.526409 13.319083
52.525678 13.320317
And the point: 52.525730, 13.314556, then the first point 52.525782, 13.316927 will be returned, as it is the closest one.
Is the only way of acheiving it is looping through all the array and finding the distance between the points? What happens if the array contains too much coordinates?
You can try it using LINQ, but the inner workings of LINQ would still loop over your collection. For example:
//Your list with coordinates
List<GeoCoordinate> coords = new List<GeoCoordinate>();
//The coord you want to compare
GeoCoordinate crd = new GeoCoordinate();
//Sorts the list based on the proximity of the coords to crd
var sortedCoords = coords.OrderBy(x => x.GetDistanceTo(crd)).ToList();
I know it doesn't use an array, but I find using lists is easier.
I think that should work, let me know if it does!
struct coord
{
public double lat;
public double lon;
}
public void Main(coord coord)
{
var coords = new[]{ new coord(){lat=1, lon=1} };
var closest = coords.Min(p => Math.Abs(p.lat - coord.lat) + Math.Abs(p.lon - coord.lon));
}
I want to check if a Rectangle(A Player) , intersects with one of the rectangles in a list (List).
I am currently using a for loop , which makes it slow , and poor performance.
for (int i = 0; i < gameObjects.objectList.Count; i++)
{
if (gameObjects.objectList[i].IntersectsWith(gameObjects.player))
{
gameObjects.objectList.RemoveAt(i); // if the player collided with an object, remove that object
}
}
How can I make it more efficient / is there another way to do it faster?
You can try organize your rectangles in a structure called k-d-tree.
It gives you up to O(log N) complexity in a large rectangle array (> 100).
F.e. make binary tree with fixed length, say, 2. Divide your space into left and right halves, then each half divide into top and bottom quarters (and so on).
Inside leaf node create a list on rectangles. If a rectangles falls into left half and top quarter, locate it in the list of this quarter.
A rectangle may be locates in a few list at the same time (f.e. in case if it falls in left and right halves).
To check intersection you should test rectangle in responding halves and quarters.
Or, you removes too many rectangles, it's faster to copy remaining rectangles into the new list in your own code.
Small example.
public enum CheckBy
{
Horizontal,
Vertical
}
public class Node
{
public Node First { get; set; }
public Node Second { get; set; }
public int Coordinate { get; set; }
public CheckBy CheckBy { get; set; }
public List<Rectangle> Rectangles { get; set; }
}
public bool IsRectangleInFist(Node node, Rectangle rectangle)
{
if (node.CheckBy == CheckBy.Horizontal)
return rectangle.Left <= node.Coordinate;
return rectangle.Top <= node.Coordinate;
}
public bool IsRectangelInSecond(Node node, Rectangle rectangle)
{
if (node.CheckBy == CheckBy.Horizontal)
return rectangle.Right >= node.Coordinate;
return rectangle.Bottom >= node.Coordinate;
}
public void AddRectangleInSuitableNode(Node node, Rectangle rectangle)
{
if (InRectangleInFirst(node, rectangle))
AddRectangleInSuitableNode(node.First, rectangle);
if (InRectangleInSecond(node, rectangle))
AddRectangleInSuitableNode(node.Second, rectangle);
}
public void SearchIntersectedRectangles(Node node, Rectangle rectangle, List<Rectangles> result)
{
// If not-leaf node
if (node.Rectangles == null && node.First != null && node.Second != null)
{
if (IsRectangleInFirst(node, rectangle))
SearchIntersecatedRectangles(node.First, rectangle, result);
if (IsRectangleInSecond(node, rectangle))
SearchIntersecatedRectangles(node.Second, rectangle, result);
return;
}
result.AddRangle(Rectangles.Where(r => r.IsIntersect(rectangle)));
}
These all lines makes simple 2D-tree. First, make the tree:
// Say, all rectangles would be inside this "space"
const int leftest = -1000;
const int rightest = 1000;
const int bottomest = -1000;
const int toppest = 1000;
// Tree with depth == 2
var tree = new Node
{
CheckBy = CheckBy.Hozirontal,
Coordinate = (leftest + rightest)/2,
First = new Node
{
CheckBy = CheckBy.Vertical,
Coordintate = (toppest + bottomest)/2,
Rectangles = new List<Rectangle>(),
},
Second = new Node
{
CheckBy = CheckBy.Vertical,
Coordintate = (toppest + bottomest)/2,
Rectangles = new List<Rectangle>(),
},
}
Then, sort all rectangles in this tree:
foreach (var rectangle in rectangles)
AddRectangleInSuitableNode(tree, rectangle);
Now you can fast get intersecting rectangles:
var intersecting = new List<Rectangles>();
SearchIntersecatedRectangles(tree, targetRectangle, intersecting);
// Here you can remove intersecting rectangles...
Basically, you need to stop checking all of the rectangles every time. You need to somehow figure out which rectangles are located in the vicinity of the player.
You could use some kind of spatial grid to store your rectangles so you could quickly find adjacent rectangles to be checked for collision. See this tutorial for example: N Tutorial B - Broad-Phase Collision.
I doubt it will be faster but you can always do it with Ling in a one liner:
gameObjects.objectList = gameObjects.objectList
.Select(go => go)
.Where(go => !go.IntersectsWith(gameObjects.player))
.ToList();
This essentially sets the list to one where any gameObject that collides with player is removed.
Also note that it is usually faster to process a sorted list first, so doing this:
gameObjects.objectList = gameObjects.objectList
.OrderBy(go => go.X)
.ThenBy(go => go.Y)
.ToList();
may help speed things up a bit. Doing this ordering every frame will be slow though so it will be worth ordering the objects as they are added to the list.
I am new at EmguCV & C# and I have a project that find circles' info (centers' X & Y coordinates) from USB Camera. According to these coordinates, prototype machine moves rollers with stepper motor x-axis or y-axis.
I used CircleF with HoughCircles and found coordinates with this code:
CircleF[] circles = imgProcessed.HoughCircles(new Gray(100), new Gray(50), 2, imgProcessed.Height / 4, 30, 45)[0];
I want to create 2d array from CircleF to apply array process and apply mathematical operations to circles' X and Y values.
I thought that if I convert "circles" CircleF to array, these processes are easier.
I know CircleF is a kind of array, but I cannot apply some array process (like sorting) on it. I want to sort X values of circles' centers from small to large. I cannot do that like Array.Sort(circles)
Does anybody help me about this situation?
or if it is possible to apply array process on CircleF, how can I apply?
Code samples would be useful. Thanks for now.
What exactly do you mean by "array process"? CircleF basically just "wraps" the center coordinate of the circle along with the radius and area. Take a look at the following which is taken from the Emgu.Cv.dll:
public struct CircleF : IEquatable<CircleF>
{
public CircleF(PointF center, float radius);
public double Area { get; }
public PointF Center { get; set; }
[XmlAttribute("Radius")]
public float Radius { get; set; }
public bool Equals(CircleF circle2);
}
So when iterating your array of CircleF structs you can:
for(int i=0;i < circles.Length;i++){
var currCircleF = circles[i];
//do something with currCircleF, e.g. change radius,center,etc.
}
To sort the array of circles according to the value of center X:
var sortedCircleFbyX = circles.OrderBy(c => c.Center.X).ToArray();
The result is an array of CircleF. You can then perform processing like:
//do more processing
foreach (var circleF in sortedCircleFbyX)
{
MoveStepperMotor(circleF.Center);
}
I want to be able to display a Bing map in a Windows 8/Store app with an array of pushpins/waypoints at a zoom setting that will show every location, but no more than that - IOW, I want as much detail as possible while still showing all of the locations/coordinates.
I have this pseudocode:
public static int GetMapZoomSettingForCoordinates(List<String> coordinatesList)
{
string furthestNorth = GetFurthestNorth(coordinatesList);
string furthestSouth = GetFurthestSouth(coordinatesList);
string furthestEast = GetFurthestEast(coordinatesList);
string furthestWest = GetFurthestWest(coordinatesList);
int milesBetweenNorthAndSouthExtremes = GetMilesBetween(furthestNorth, furthestSouth);
int milesBetweenEastAndWestExtremes = GetMilesBetween(furthestEast, furthestWest);
int greaterCardinalDistance = Math.Max(milesBetweenNorthAndSouthExtremes, milesBetweenEastAndWestExtremes);
return GetZoomSettingForDistance(greaterCardinalDistance);
}
...but the "sticking point" (the hard part) are the "milesBetween" functions. Is there an existing algorithm for computing the miles between two coordinates?
I do realize this is a U.S.-centric bunch of code for now (miles vs. kilometers); that is, for now, as designed.
UPDATE
This is my new pseudocode (actual compiling code, but untested):
public static int GetMapZoomSettingForCoordinates(List<string> coordinatePairsList)
{
List<double> LatsList = new List<double>();
List<double> LongsList = new List<double>();
List<string> tempList = new List<string>();
foreach (string s in coordinatePairsList)
{
tempList.AddRange(s.Split(';'));
double dLat;
double.TryParse(tempList[0], out dLat);
double dLong;
double.TryParse(tempList[0], out dLong);
LatsList.Add(dLat);
LongsList.Add(dLong);
tempList.Clear();
}
double furthestNorth = GetFurthestNorth(LatsList);
double furthestSouth = GetFurthestSouth(LatsList);
double furthestEast = GetFurthestEast(LongsList);
double furthestWest = GetFurthestWest(LongsList);
int milesToDisplay =
HaversineInMiles(furthestWest, furthestNorth, furthestEast, furthestSouth);
return GetZoomSettingForDistance(milesToDisplay);
}
private static double GetFurthestNorth(List<double> longitudesList)
{
double northernmostVal = 0.0;
foreach (double d in longitudesList)
{
if (d > northernmostVal)
{
northernmostVal = d;
}
}
return northernmostVal;
}
...I still don't know what GetZoomSettingForDistance() should be/do, though...
UPDATE 2
This is "more better":
public static int GetMapZoomSettingForCoordinates(List<Tuple<double, double>> coordinatePairsList)
{
var LatsList = new List<double>();
var LongsList = new List<double>();
foreach (Tuple<double,double> tupDub in coordinatePairsList)
{
LatsList.Add(tupDub.Item1);
LongsList.Add(tupDub.Item2);
}
double furthestNorth = GetFurthestNorth(LongsList);
double furthestSouth = GetFurthestSouth(LongsList);
double furthestEast = GetFurthestEast(LatsList);
double furthestWest = GetFurthestWest(LatsList);
int milesToDisplay =
HaversineInMiles(furthestWest, furthestNorth, furthestEast, furthestSouth);
return GetZoomSettingForDistance(milesToDisplay);
}
UPDATE 3
I realized that my logic was backwards, or wrong, at any rate, regarding meridians of longitude and parallels of latitude. While it's true that meridians of longitude are the vertical lines ("drawn" North-to-South or vice versa) and that parallels of latitude are the horizontal lines ("drawn" East-to-West), points along those line represent the North-South location based on parallels of latitude, and represent East-West locations based on meridians of longitude. This seemed backwards in my mind until I visualized the lines spinning across (longitude) and up and over (latitude) the earth, rather than simply circling the earth like the rings of Saturn do; what also helped get my perception right was reminding myself that it is the values of the meridians of longitude that determine in which time zone one finds themselves. SO, the code above should change to pass latitudes to determine furthest North and furthest South, and conversely pass longitudes to determine furthest East and furthest West.
You can use the Haversine formula to compute the distance along the surface of a sphere.
Here's a C++ function to compute the distance using the Earth as the size of the sphere. It would easily be convertible to C#.
Note that the formula can be simplified if you want to just find the distance either latitudinally or longitudinally (which it sounds like you are trying to do).
To get the straight line distance you use the Pythagorean Theorem to find the hypotenuse.
d = ((delta x)^2 + (delta y)^2)^.5
Basically square both the changes in the x direction and the y direction, add them, then take the square root.
in your pseudo code it looks like you could have many points and you want to find a maximum distance that should encompass all of them, which makes sense if you are trying to figure out a scale for the zoom of the map. The same formula should work, just use milesBetweenEastAndWestExtremes for delta x, and milesBetweenNorthAndSouthExtremes for delta y. You may opt to add a fixed amount to this just to make sure you don't have points right on the very edge of the map.
The most basic way of representing a quadrile plane (a bunch of squares) is to use a two-dimensional array.
In C# we declare this as int[,] and can make our plane as big as we want:
string[3,3] => tic-tac-toe board (or similar)
string[8,8] => chess or checkers board
To "move" an item on the plane, we would just asign it toa new "position"
//using our tic-tac-toe board:
string[0,0] = "x"; //top-left
string[1,1] = "o"; //middle-middle
//to move
string[0,1] = bN; //Black Knight's starting positon
string[2,2] = bN; //Black Knight moves
string[0,1] = String.Empty;
So, how would you represent a hexagonal plane (a bunch of hexagons) and how would movement from one position to the next be handled?
Note: This is not purely theoretical, as I have an idea for a little game in my head which would require this kind of movement, but I can't wrap my head around how it would be done. I've looked through some of the other questions here, but can't really find a good match...
I do not know if this is the optimal solution but what I would do is create a new class of board the board would be a collection of "cells" each cell would contain a pointer to each of it's neighboring cell (or null if the cell is on a edge). You could implement some iterators on the board class that would walk the cells.
You would have to treat it more like a List instead of a vector. But it is at least a start.
Another solution is set you board up like this
and still just use the [,] to access each cell but it will take a little more math to figure out if you are traversing cells (Up Right is [+1,-1], Right is [+1,0], Down Right is [0,+1], Down Left is [-1,+1], Left is [-1,0], Up Left is [0,-1])
EDIT
If you want vertical walls instead of a slant just take make your width(X) equal X + Y*2 then on each row make the current row number (y) and make the cells 0 to Y-y and X-y to X off limits.
Example:
const int X = 10;
const int Y = 10;
int grid[,] = new int[X+(2*Y), Y];
bool IsCellOffLimits(int x, int y)
{
return (x < Y-y || x > X-y || y < 0 || y > Y);
}
you waste a little memory space but it gives you a board like this
If you are Very Clever© you can just use the normal space but just have your code have anything in that Y-y or X-y range be on the opposite side of the board. But ill leave that code up to the reader.
Three directions, left/right, up/down, funny angle one way/other way.
public class Player
{
public int X { get; set; }
public int Y { get; set; }
public void MoveLeft() { X++; }
public void MoveRight() { X--; }
public void MoveUp() { Y++; }
public void MoveDown() { Y--; }
public void MoveFunny() { Y++; X++; }
public void MoveOtherFunny() { Y--; X--; }
}