I have an array test {1, 2, 4} and want to pass it in a function IncreaseResolution(float[,] origin) which should increase the length of the array. So basically I want to turn test {1, 2, 4} into test {1, 1.5, 2, 3, 4}. So what I want to do is take the initial array and add a value in between every value for the new array.
Also how could I do this but with a 2D array?
Sketch of how I want to smooth the array:
CodePudding user response:
This will probably work:
public float[] IncreaseResolution(float[] origin)
{
float[] dest = new float[origin.Length * 2 - 1];
dest[0] = origin[0];
for (int i = 0; i < origin.Length - 1; i )
{
float mid = origin[i 1] - origin[i];
dest[i * 2 1] = mid;
dest[i * 2 2] = origin[i 1];
}
return dest;
}
CodePudding user response:
To answer the question fully you want to deploy some kind of interpolation function to fill in values between the original grid nodes.
So is the question how to do the interpolation, or how to resize the array? Because, if you know the interpolation then you just create a new empty array of double size and do the math to fill in the values. As of this time, the math you want to use is not specified in the question and hence the question cannot be answered fully.
The example indicates a linear interpolation between nodes, but the values correspond to a parabola, so the end result would not be smooth at all.
Increasing the resolution of {1,2,4}
with a smooth curve results in {1, 1.375, 2, 2.875, 4}
as points of the curve 1 x/2 x2/2.
To illustrate the point, here is propose interpolation points from the question, overlayed to the smooth curve that goes through the original points.
You see how the new points are off the curve when {1,1.5,2,3,4}
is used?
The following just answers the question on how to increase the size of 1D and 2D arrays and keep existing values if possible.
1D
For 1D primitive types, use Array.Copy()
public static T[] Resize<T>(this T[] matrix, int newSize)
{
var result = new T[newSize];
Array.Copy(matrix, result, Math.Min(matrix.Length, result.Length));
return result;
}
with the following example code
float[] test = new[] { 1f, 2f, 3f };
float[] bigger = Resize(test, 2 * test.Length);
Console.WriteLine(string.Join(",", bigger));
// 1,2,3,0,0,0
2D
The problem with 2D arrays is the memory layout. They are row-major and are stored in memory row by row.
For example, the following 2D array is stored in memory as such
| a1 a2 |
| a3 a4 | => { .. a1, a2, a3, a4, ... }
So if you want to add a row, you can just append the array. But to add a column, you need to insert values between a2
and a3
for example
| a1 a2 b1 |
| a3 a4 b2 | => { .. a1, a2, b1, a3, a4, b2, ... }
So the above cannot be done with an Array.Copy()
operation anymore.
This means that the code below adds rows, but not columns
public static T[,] Resize<T>(this T[,] matrix, int newRows)
{
var result = new T[newRows, matrix.GetLength(1)];
Array.Copy(matrix, result, Math.Min(matrix.Length, result.Length));
return result;
}
To do this 2D resizing, you need to go row by row and copy the old data for each row
public static T[,] Resize<T>(this T[,] matrix, int newRows, int newColumns)
{
var result = new T[newRows, newColumns];
int oldRows = matrix.GetLength(0);
int oldColumns = matrix.GetLength(1);
for (int i = 0; i < Math.Min(oldRows, newRows); i )
{
Array.Copy(matrix, i * oldColumns, result, i * newColumns, Math.Min(oldColumns, newColumns));
}
return result;
}
with the following demo code
var test = new[,] { { 1f, 2f }, { 3f, 4f } };
var bigger = Resize(test, 4, 4);
for (int i = 0; i < bigger.GetLength(0); i )
{
for (int j = 0; j < bigger.GetLength(1); j )
{
Console.Write($" {bigger[i, j],-6}");
}
Console.WriteLine();
}
and output
1 2 0 0
3 4 0 0
0 0 0 0
0 0 0 0
Jagged 2D Array
Often in scientific computing one might use jagged arrays (arrays of arrays) because it is easier to do linear algebra. Here is a similar library function for jagged arrays.
public static T[][] Resize<T>(this T[][] matrix, int newRows, int newColumns)
{
var result = new T[newRows][];
int oldRows = matrix.Length;
int oldColumns = oldRows>0 ? matrix[0].Length : 0;
for (int i = 0; i < Math.Min(oldRows, newRows); i )
{
result[i] = Resize(matrix[i], newColumns);
}
for (int i = oldRows; i < newRows; i )
{
result[i] = new T[newColumns];
}
return result;
}