Note: I define a 'Jagged Multidimensional' specifically as jmArray[][,].
I'm trying to wrap my head around the use of this type of array, in order to hold simple coordinates, a pair of Integers. This array will be used to create a 3x3 grid, so in my head I'm seeing:
jmArray[N][X,Y]
Where N is the number of the grid slice, and X,Y are the coordinates of the slice. So:
jmArray[2][3,2]
Would mean that slice 2 lies at coordinate 3,2.
I've been trying to assign values to each slice, but I'm stuck somewhere...
jmArray[0][,] = new int[1,2] {{3,3}};
A little help in understanding how to do this properly would be nice.
Unless I'm misunderstanding you, a simpler way to do this would be to create a dictionary of size 3 tuples.
var space = Dictionary<Tuple<int, int, int>, TPointValue>;
// Fill up space with some points
space[Tuple.Create(3,3,1)] = new TPointValue(42);
// Retrieve point from 3d space
TPointValue point3_3_1 = space[Tuple.Create(3,3,1)];
I'll concede that in its current form, this approach makes retrieval of planes or basis lines cumbersome and inefficient compared to jagged arrays, although it does makes assignment and retrieval of points very efficient.
However: if you were to wrap this data structure in a class of your own that provides methods for accessing planes/lines etc, you could very easily and efficiently calculate the keys required to obtain any set of points beforehand, eg. those within a plane/line/polygon, and then access these points very efficiently.
PS: Note that the value at a point need not be some fancy type like TPointValue, it could be just a string or float or whatever you like.
You can achieve it like this:
int[][,] jmArray = new int[3][,];
jmArray[0] = new int[1,2] {{3,3}};
Instead of a complicated array a simple class with meaningful names might work better:
class Slice
{
int X = 0;
int Y = 0;
public Slice()
{
}
public Slice(int _X, int _Y)
{
X = _X;
Y = _Y;
}
}
Slice[] Slices = new Slice[9];
The index of the array will be the position of the slice.
Related
I'm reading data from a sensor. The sensor give an array of points (x,y). But as you can see in the image, there is a lot of noise:
.
I need to clean the data in a way that the data filtered, give a few points . Using something like Median,adjacent averaging, mean of the xy points or an algorithm that removes the noise. I know that there are a bunch of libraries in Python that make the work automatically. All the auto libraries that I found are base on image analysis and I think they do not work for this case because this is different, these are points (x,y) in a dataset.
point-cloud noise cleaned:
PD: I wanted to do the median of the points but i got confused when i tried with an bidimensional array (this mean ListOfPoints[[x,y],[x,y],[x,y],[x,y],[x,y],[x,y]]) I didn't know how to make that calculation with for or while to iterate and make the calc. I prefer C#, but if there is a solution in other language without libraries, I would be open to it.
One of the methods you can use is k_means algorithm. This picture briefly explains this algorithm k_means
This link fully explains the k_means algorithm. Also, how to create a loop on the input data. I don't think any additional explanation is needed k_means algorithm
K_menans algorithm is very simple and you will understand it with the first Google search
You could try doing a weighted average of the Y-value at sampled X-positions. Something like this:
List<Point2> filtered_points = new List<Point2>();
for (int x = xmin; x <= xmax; x++)
{
double weight_sum = 0;
List<double> weights = new List<double>();
foreach (Point2 p in point_list)
{
double w = 1.0/((p.x - x)*(p.x - x) + 1e-3);
weights.Add(w);
weight_sum += w;
}
double y = 0;
for (int i = 0; i < point_list.Count; i++)
{
y += weights[i]*point_list[i].y / weight_sum;
}
filtered_points.Add(new Point2(x, y));
}
You would probably need to tune the weights to get nice results. Also, in the example I am using a quadratic decay, but other weighting functions can be used (linear decay, gaussian function...)
I'm creating kind of a 2D map where which coord has a tile class attached to it,
The tile class would have its coord inside of it, and some other values that would be accessed later, but I would like to have that map with no size limitations. The problem is, I want to see the values inside of some tile in that map, for example: I'm at coord(25,30) and I want to know a bool value inside the tile class in each adjacent tile.
And if I use an array, I would have maybe the fastest way to check the coord of a tile, e.g. an array of 2 indexes. I could make each index be a x and a y coord respectively, so I would only check that coord when seeing the values on a tile. But the map would have a limit in size.
And if I use a list the map won't have a limit in size but I can't check the coordinate directly, so I would need to go through each created tile with a foreach loop, and check if the coord inside that tile, is the same as the one I am looking for.
My current solution is to have a second List with only the coordinates, and have it assigned when I create a tile, so the index in the coordinate list is the same as in the tile list. So when I need to check for a tile, I do a CoordinateList.Contains(coordinate), and if that is true, then I put the index of that coordinate as the index that the code should look in the tile List.
I want a faster way to check a tile, without a size limitation.
So far, with the tile List I got around 3200ms for each time I checked the whole map (about 2000 tiles in the list).
And with the mapCoord List I got around 1500ms (around 2000 tiles and coords).
And with the array I was getting a pretty fast response (never measured it) but less than I second for sure... Since I never had to check for the whole Array, but one for a certain index.
Examples for easier understanding of my problem:
note1: It does not fill all the array.
note2: It wouldn't always be rectangular.
int size = 50;
Tile[,] mapArray = new Tile[size,size];
List<Tile> mapList = new List<Tile>();
List<Vector2Int> mapCoord = new List<Vector2Int>();
void CreateMap()
{
for(int x = size/2; size <= size/2; x++)
{
for(int y = size/2; size <= size/2; y++)
{
if(x > 2 && y > 3)
{
mapArray[x,y] = new Tile(new Vector2Int(x,y), false, 32);
mapList.add(new Tile(new Vector2Int(x,y), false, 32));
mapCoord.add(new Vector2Int(x,y));
}
}
}
}
So if I was to check a tile in the array, in the array I would just check the coord, since the tile coord would be the same as the array index, but it would have a size limit.
And if I was to check the tile in the list, I would need to do a foreach loop like this. Pretty bad for performance and optimization.
Tile desiredTile = null;
for each(Tile tile in mapTiles)
{
if(tile.Coord == DesiredCoord)
desiredTile = tile;
}
And the best way so far, is checking the mapCoord list like this:
if(mapCoord.Contains(desiredCoord))
{
desiredTile = mapList[mapCoord.IndexOf(DesiredCoord)];
}
Look up "sparse array" as a way to do this. One possible implementation is a Dictionary where the key is effectively a tuple of two ints (x and y). If the game starts with a standard boundary (say +/- 100 of the starting point) you could mix and match, a 200x200 array and the dictionary beyond that. You can also get creative by having multiple rectangular regions, each as an array.
If your total address space fits into a short integer (+/- 32k), then you could do something like this:
[StructLayout(LayoutKind.Explicit)]
struct IntXY
{
[FieldOffset(0)] Int16 X;
[FieldOffset(2)] Int16 Y;
[FieldOffset(0)] UInt32 AsAnUnsignedInteger;
public override int GetHashCode()
{
return AsAnUnsignedInteger.GetHashCode();
}
}
and use that as the key in your Dictionary (using LayoutKind.Explicit makes this is effectively the same as a C/C++ union - the X and Y shorts take up the same combined 32 bits as the unsigned int). It's probably cheaper than a Tuple<int, int> (though you'd probably want to test my guess).
I have created my own class 'Geolocation' which just holds double variables 'longitude' and 'latitude'.
I have a List and another static Geolocation object. I need to loop through my List and analyse which of these locations is closest to the static location. By 'closest' I am referring to real life distance, so I think it would be called a geospatial analysis.
My own pseudo idea is along the lines of this.
Geolocation[] closestPositions = new Geolocation[]
for (int i = 0; i < TrainStations.AllStations.Count; i++)
{
Geolocation A = TrainStations.AllStations[i];
Geolocation B = DataHandler.UserCurrentPosition;
if (A and B are closer than what is stored in closestPosition)
{
closestPosition[0] = A;
closestPosition[1] = B;
}
}
By the end of this loop I would be left with the two closest points (more specifically which train station in the city is closest to the user's current position).
However, I'm really not sure if the way my pesudo code would function is most efficient, and I don't know how to do the actual analysis (get the distances from A to B and measure which is shortest).
Rather than creating my own class 'Geolocation', I should have used the inbuilt System.Device.Location.GeoCoordinate class.
https://msdn.microsoft.com/en-us/library/system.device.location.geocoordinate(v=vs.110).aspx
This class has a function 'GetDistanceTo(Geocoordinate)' which "Returns the distance between the latitude and longitude coordinates that are specified by this GeoCoordinate and another specified GeoCoordinate."
I can use this in my loop, using GeoCordinate objects, to analyse which points are closest.
I would like to draw a curve using graphics.DrawCurve and I have x and y values in separate arrays (float x[] and float y[]). As DrawCurve needs point array as input, I need to convert or dynamically create the point array from the float arrays x and y. Is there any quick way for this?
I have around 20000 points for plotting the curve, Is it good idea to use graphics.DrawCurve on this purpose?
There are several questions to answer.
I couldn't find out how to allocate a point array.
Well, there is no difference in allocating a point array than to do so for any other kind of array:
const int size = 100;
Point[] pointArray = new Point[size];
But arrays are missing some "convenience". For example, they have a fixed size that you need to specify at the point of initialization (allocation). And if you need more space, you have to manually create a new (bigger) array and copy all the values from the old to the new.
That's why almost everywhere you would work with an array, you're probably better off using a list:
List<Point> pointList = new List<Point>();
And then, wherever you actually need to pass an array, you can simply get it via:
Point[] pointArray = pointList.ToArray();
dynamically collect the x and y values in the allocated point array
When you work with a list, that's as easy as:
pointList.Add(new Point(x, y));
We don't know how you fill your float x[] and float y[]. If possible, I'd not have those two separate arrays in the first place and simply use the pointList from the start. With one caveat: a System.Drawing.Point only works with int values, not with float values. So I assume you meant to collect int values for the coordinates.
dynamically create the point array from the float arrays x and y
If you cannot change the collection of the coordinates and have to work with those arrays, you can "zip" them together like this:
IEnumerable<Point> points = x.Zip(y, (xCoord, yCoord) =>
(new Point((int)xCoord, (int)yCoord));
Or, if you know you need an array:
Point[] pointArray = x.Zip(y, (xCoord, yCoord) =>
(new Point((int)xCoord, (int)yCoord)).ToArray();
For this, you need to be able to use System.Linq (in other words higher than .Net 2.0).
If you cannot use Linq, you have to do it "by hand". Something like:
int size = Math.Min(x.Length, y.Length);
Point[] pointArray = new Point[size];
for (int index = 0; index < size; index++)
{
pointArray[index] = new Point((int)x[index], (int)y[index]);
}
You can create List<Point> which is better than arrays.
List<Point> list = new List<Point>();
Point point=new Point(10,15);
list.Add(point);
You can get all x and y coordinates from two arrays and put together in list as points and than use this list to draw curve.
Given the values in both arrays have the same Index you can itereate over them, create points and add them to a list.
List<Point> points = new List<Point>();
for(int i = 0; i < x.Length; i++){
points.Add(new Point(x[i],y[i]);
}
I don't see a particular problem in using DrawCurve here.
If you need an array of Points use points.ToArray();
Hopefully a quick question. I have an IEnumerable of type Position where Position is defined as follows:
public class Position {
public double Latitude { get; set; }
public double Longitude { get; set; }
}
What I need to do is quickly sort through the IEnumerable to find elements that fall within a certain distance of eachother. The elements in the IEnumerable do not get populated in any specific order, but at any one time I need to be able to compute which of the members of the IEnumerable fall within x kilometers of eachother.
Now, I already have a Haversine implementation and for argument's sake, we can say it's called GetDistance and has the following signature:
double GetDistance(Position one, Position two);
I've got a few ideas, but none of them feel particularly efficient to my mind. To give a little more info, it's unlikely the IEnumerable will ever hold more than 10,000 items at any one time.
What I'd like to arrive at is something, perhaps an extension method, that lets me invoke it to return an IEnumerable which contains just the subset from the original collection which meets the criteria, for example:
OriginalEnumerable.GetMembersCloserThan(kilometers: 100);
Any help, much appreciated.
EDIT: For clarity, consider the IEnumerable I want to search describes a circle with radius r. It's members are coordinates within the circle. I'm trying to determine which members (points) are within a given proximity of eachother.
Something like this? Assuming GetDistance is available.
public static IEnumerable<Position> GetMembersCloserThan(this IEnumerable<Position> positions, double maxDistance)
{
return positions.Where(a => positions.Any(b => a != b && GetDistance(a, b) < maxDistance));
}
Edit I see now you are also interested in performance. The above is not particularly fast, though it is not horribly slow either since the math is pretty simple for comparing distances. Let me know if it satisfies your requirements.
Edit 2 This one is much faster--it won't test against past failures and will automatically add a match to the success list
public static IEnumerable<Position> GetMembersCloserThan(this IEnumerable<Position> positions, double maxDistance)
{
List<Position> closePositions = new List<Position>();
List<Position> testablePositions = positions.ToList();
foreach (Position position in positions)
{
// Skip this one, it has already been matched.
if (closePositions.Contains(position))
continue;
bool isClose = false;
foreach (Position testAgainstPosition in testablePositions)
{
if (position == testAgainstPosition)
continue;
if (GetDistance(position, testAgainstPosition) < maxDistance)
{
// Both the position and the tested position pass.
closePositions.Add(position);
closePositions.Add(testAgainstPosition);
isClose = true;
break;
}
}
// Don't test against this position in the future, it was already checked.
if (!isClose)
{
testablePositions.Remove(position);
}
}
return closePositions;
}
If you need more performance: Put the items in a Lists sorted by latitude.
To calculate your desired set of locations, iterate one of them. But for your distance calculation, you only need to consider the items, that are at most 100km different in latitude. That means, you can go back item by item, until the difference is greater than 100km. You need to wrap around the end of the list, however.
Mark all items (or yyield return) that are closer than 100km and move on.
Although I cannot quantify the expense, the sorting should amortize for large sets. Also, it may perform bad if most point lie at similar latitude. If that is an issue, use a 2D-Dictionary with rounded coordinates as keys.