Dynamically create a point array - c#

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();

Related

Efficient way to fill a 2d array with position based values

There is the following code:
public int[,] GenerateArray(int size)
{
int[,] data = new int[size, size];
for (int x = 0; x < size; ++x)
for (int y = 0; y < size; ++y)
data[x, y] = x * y; // Example calculation function that depends on indexes
return data;
}
As you can see, I'm trying to fill a 2d array with values. Each element's value is calculated based on it's indexes. The amount of data that needs to be processed is enourmous, so it's taking some time to deal with it. Is there a more effecient method of achieving this? Like, using a GPU shader or something.
Can you use not array, but math function instead? If you need [2123,453] position you just calculate it's data using your func(2123,453). If you need to safe data you can safe just this modified section.
I think you can parallel calculations using GPU based Task.Run
What's the array size and calculation function?

Is there a faster for me to look to a specific index without using an array?

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).

Jagged Multidimensional Arrays in C#

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.

Compute the local max/min for a given X Y series

I have an array consist of Point2D ( which has two members, x and y), e.g., Point2D[] points. You cna think of this array as a series of points on a X Y graph. The array is sorted in such a way that it is arranged from the smaller Point2D.X to the bigger Point2D.X
My question is simple: how do you find the points ( and the corresponding item index right before and after those points) that are the local maxima/minima? Recall that local max/min is defined mathematically as dy/dx=0. So my task is that I would need to find the those points where dy/dx=0.
Please note that the the extreme points may or may not located right inside the Point2D array, as the graph is a smooth curve, not an linearly-piece-wise polyline. An extreme point can be the middle point of two points inside the array. for instance.
Is there any existing libraries/ components that already do this in C#?
Here is my method:
public class Point2D
{
public double X;
public double Y;
}
public class PointWithIndex
{
// the extreme point where dy/dx=0
public Point2D ExtremePoints;
// the index of the array for the point that locates right before this ExtremePoints
public int PrevItemIndex;
}
public static List<PointWithIndex> FindLocalExtrema(List<Point2D> xyPoints)
{
// the algorithm to find the max/min points of xyPoints
}
I suggest running a loop 0 < i < n - 1, check if P[i - 1].Y < P[i].Y && P[i + 1].Y < P[i].Y, then P[i] is a max. do the same with min.
I'm not sure if this is what you are looking for: The Catmull-Rom Spline which you can easily compute using the XNA Framework (in C#) as shown here.
The idea is: you will generate -iteratively or recursively- points using Catmull-Rom until you hit your local maxima.

Is an array valid for vertex element data for programmable graphics pipline?

In response to my previous qeustion posted here:
What is a good code structure for api-independant vertex processing?
If I have say a vertex structure with an array of floating point values such as:
public struct Vertex
{
float[] array = new float[4];
public Vertex(float x, float, y, float z, float w)
{
array[0] = x; array[1] = y; array[2] = z; array[3] = w;
}
}
Could that vertex structure be sent to a vertex buffer (using OpenGL or DirectX)? Does an array contain any other byte data or does it only contain the data of the floating point values? Like if I were (in DirectX) use this vertex as Transformed in a declaration could I send the vertex to a buffer and all that will be sent is the floating point values, or will the array contain other information that could break my shader program?
No, don't do it. the structure may not be correctly aligned or have extra data...its generally not a safe thing to do considering that the .net framework may change and those are not guaranteed feature.
Your best bet is to prepare the data into float array[] and pick up the pointer using the fixed keyword. in that way I can ASSURE (i'm doing it by myself) that works fine.
Anyway don't try to do extra things as optimizing on these petty things. They will never be the bottleneck in your app/game. (not even really important)
Do what makes your code more readable-maintanable.
Remember anyway that the speed of struct vs array is different depending on what are you doing. Generally struct are faster on random access, array are faster on linear access, so if you have some REALLY intensive part of application (like a software skinner is) try to choose the correct for your need.
I'm not a C# programmer, but it looks here that you store a array reference (pointer) in the Vertex struct, hence an array of Vertex would be an array of pointers. A graphics API demands a continous sequence of floats.
Try:
public struct Vertex
{
public fixed float array[4];
public Vertex(float x, float, y, float z, float w)
{
array[0] = x; array[1] = y; array[2] = z; array[3] = w;
}
}

Categories