Understanding Marching Square algorithm - c#

The following picture is retrieved from Wikipedia:
I haven't understood this part:
I have two questions here:
Where did they obtain [8,4,1,2] from and what did they want to tell us by that?
Take a look at cell [0, 0] whose value is 13. If I go clockwise along with its contouring values, I obtain the binary string 0010 which is 2. How does the 1st cell-value become 13?
.
enum What
{
lines, surface, both
}
class Program
{
public static void Print(int[,] data, int xn, int yn)
{
for (int j = 0; j < yn; j++)
{
for (int i = 0; i < xn; i++)
{
Console.Write(data[i,j] + ", ");
}
Console.WriteLine();
}
}
public static int[,] normalize(int[,] data, int xn, int yn)
{
for (int j = 0; j < yn; j++)
{
for (int i = 0; i < xn; i++)
{
if (data[i, j] > 1)
{
data[i, j] = 0;
}
else
{
data[i, j] = 1;
}
}
}
return data;
}
public static int[,] marching_square(int x, int y, int[,] data, int isovalue, What what)
{
int xn = x;
int yn = y;
data = normalize(data, xn, yn);
int[,] bitMask = new int[xn - 1, yn - 1];
for (int j = 0; j < yn - 1; j++)
{
for (int i = 0; i < xn - 1; i++)
{
StringBuilder sb = new StringBuilder();
sb.Append(data[i, j]);
sb.Append(data[i, j + 1]);
sb.Append(data[i + 1, j]);
sb.Append(data[i + 1, j + 1]);
bitMask[i, j] = Convert.ToInt32(sb.ToString(), 2);
}
}
return bitMask;
}
static void Main(string[] args)
{
int[,] data = new int[,] {
{ 1,1,1,1,1 },
{ 1,2,3,2,1 },
{ 1,3,3,3,1 },
{ 1,2,3,2,1 },
{ 1,1,1,1,1 }
};
Print(data, 5,5);
int[,] bitMask = marching_square(5,5,data, 0, What.lines);
Print(bitMask, 4, 4);
}
}
Output:
1, 1, 1, 1, 1,
1, 2, 3, 2, 1,
1, 3, 3, 3, 1,
1, 2, 3, 2, 1,
1, 1, 1, 1, 1,
14, 10, 10, 11,
12, 0, 0, 3,
12, 0, 0, 3,
13, 5, 5, 7,
I inverted the bits. But, the output looks different.

Related

Microsoft Solver Foundation gives wrong answer for a simple ILP

I want to solve a binary Linear Problem in C# using Microsoft Solver Foundation. I don't know why I get wrong answer. The Objective Value should be 41.1 but I get 213. The value of 5 variables should be 1 and the other ones should be 0. But I get many many variables with wrong values.
The sum of each row of the matrix should be <= 1. That are my constraints, and as you see in Constraint_arr I get the right constraints.
Thanks for any help.
Define decision variables:
SolverContext context = SolverContext.GetContext();
Model model = context.CreateModel();
Decision[,] x = new Decision[name_column.Length, 7];
for (int i = 0; i < name_column.Length; i++)
{
for (int j = 0; j < 7; j++)
{
x[i, j] = new Decision(Domain.IntegerRange(0,1), "x" + i + j);
}
}
for (int i = 0; i < name_column.Length; i++)
{
for (int j = 0; j < 7; j++)
{
model.AddDecisions(x[i, j]);
}
}
Create Constraint and add it to model:
Term[] Constraint_arr = new Term[name_column.Length];
Term tempC;
int jj;
for (int i = 0; i < name_column.Length; i++)
{
tempC = 0;
for (jj= 0; jj < 7; jj++)
{
if(vars_Matrix[i,jj] == 1)
{
tempC += x[i,jj];
}
}
Constraint_arr[i] = tempC;
model.AddConstraints("constraint" + i, Constraint_arr[i] <= 1);
}
Create Objective Function:
Term objective_Func = 0;
Term tempZ;
for (int i = 0; i < name_column.Length; i++)
{
tempZ = 0;
for (int j = 0; j < 7; j++)
{
tempZ += x[i, j] * ratio[i];
}
objective_Func+= tempZ;
}
model.AddGoal("Goal", GoalKind.Maximize, objective_Func);
print the answer:
Solution solution = context.Solve(new SimplexDirective());
Report report = solution.GetReport();
for (int i = 0; i < name_column.Length; i++)
{
for (int j = 0; j < 7; j++)
{
Console.Write(x[i, j]);
}
Console.WriteLine();
}
Console.Write("{0}", report);
Console.ReadLine();
The following MiniZinc model arrives at 14 as maximum value for the objective:
set of int: rows = 1..5;
set of int: cols = 1..7;
array[rows, cols] of 0..1: vars_Matrix = [|0, 0, 1, 0, 1, 1, 1
|0, 0, 1, 1, 0, 1, 1
|0, 0, 1, 0, 0, 0, 0
|0, 0, 1, 1, 0, 1, 1
|0, 0, 0, 0, 1, 0, 0|];
array[cols] of var 0..1: c;
var int: obj;
% constraint
% obj = sum(i in rows)(
% sum(j in cols) (
% c[i] * vars_Matrix[i, j]
% )
% );
constraint
obj = sum([ sum([ c[i] * vars_Matrix[i, j] | j in cols ]) | i in rows ]);
solve maximize(obj);
Output
c = array1d(1..7, [1, 1, 1, 1, 1, 1, 1]);
obj = 14;
The same result is obtained from the following Z3py model:
from z3 import *
s = Optimize()
Rows = range(5);
Cols = range(7);
vars_Matrix = [[0, 0, 1, 0, 1, 1, 1],
[0, 0, 1, 1, 0, 1, 1],
[0, 0, 1, 0, 0, 0, 0],
[0, 0, 1, 1, 0, 1, 1],
[0, 0, 0, 0, 1, 0, 0]]
c = [Int("c" + str(i+1)) for i in Rows]
obj = Int("obj")
for i in Rows:
s.add(c[i] >= 0, c[i] <= 1)
s.add(obj == Sum( [ Sum( [ c[i] * vars_Matrix[i][j] for j in Cols ] ) for i in Rows ] ))
s.maximize(obj)
if sat == s.check():
print(s.model())
else:
print("No solution. Sorry!")

C# flattening/expanding a 3D matrix into a jagged array

I have to flatted a 3d array in order to be serialized.
Let's start with this:
int[,,] array3D = new int[,,] {
{ { 1, 2 }, { 3, 4 }, {5,6 }, {7,8 } },
{ { 9, 10}, { 11, 12},{ 13,14} , {15,16 }},
{ { 17, 18}, { 19, 20},{ 21,22}, {23,24 } }
};
which makes it like this (something like 1,2,3,4,...,24):
So now I have this s/r
public static T[] Flatten<T>(T[,,] arr)
{
int rows0 = arr.GetLength(0);
int rows1 = arr.GetLength(1);
int rows2 = arr.GetLength(2);
T[] arrFlattened = new T[rows0 * rows1* rows2];
int i, j, k;
for (k = 0; k < rows2; k++)
{
for (j = 0; j < rows1; j++)
{
for (i = 0; i < rows0; i++)
{
var test = arr[i, j, k];
int index = i + j * rows0 + k * rows1;
arrFlattened[index] = test;
}
}
}
return arrFlattened;
}
which flattens the 3d matrix into a 1d array
I am not smart enough to understand if the procedure is correct but let's go further.
I then Expand with the following s/r
public static T[,,] Expand<T>(T[] arr, int rows0, int rows1)
{
int length = arr.GetLength(0);
int rows2 = length / rows0 / rows1;
T[,,] arrExpanded = new T[rows0, rows1, rows2];
for (int k = 0; k < rows2; k++)
{
for (int j = 0; j < rows1; j++)
{
for (int i = 0; i < rows0; i++)
{
T test = arr[i + j * rows0 + k * rows1];
arrExpanded[i, j, k] = test;
}
}
}
return arrExpanded;
}
but the result is the following:
So nothing like 1,2,3,4,5....24
I know that the error might be a trivial one but try as I might I can't find it.
Thank in advance.
Patrick
Thanks for helping all 3 solution were amazing and working but I chose the one more easily to understand and debug for me
I am assuming that you want to know what is the mistake in your code more than you want to know the quickest way to get to the answer. Your index calculation is wrong. You are calculating it like this:
int index = i + j * rows0 + k * rows1;
But you actually need to multiply the last term not just by rows1 but by rows0 too:
int index = i + j * rows0 + k * rows1 * rows0;
Also, it makes sense to swap the order of dimensions that are iterated in for loops to get results in order. The final code for that would be:
public static T[] Flatten<T>(T[,,] arr)
{
int rows0 = arr.GetLength(0);
int rows1 = arr.GetLength(1);
int rows2 = arr.GetLength(2);
T[] arrFlattened = new T[rows0 * rows1* rows2];
int i, j, k;
for (k = 0; k < rows0; k++)
{
for (j = 0; j < rows1; j++)
{
for (i = 0; i < rows2; i++)
{
var test = arr[k, j, i];
int index = i + j * rows2 + k * rows1 * rows2;
arrFlattened[index] = test;
}
}
}
return arrFlattened;
}
public static T[,,] Expand<T>(T[] arr, int rows0, int rows1)
{
int length = arr.GetLength(0);
int rows2 = length / rows0 / rows1;
T[,,] arrExpanded = new T[rows0, rows1, rows2];
int i, j, k;
for (k = 0; k < rows0; k++)
{
for (j = 0; j < rows1; j++)
{
for (i = 0; i < rows2; i++)
{
T test = arr[i + j * rows2 + k * rows1 * rows2];
arrExpanded[k, j, i] = test;
}
}
}
return arrExpanded;
}
You could give this a go:
void Main()
{
int[,,] array3D = new int[,,]
{
{ { 1, 2 }, { 3, 4 }, {5,6 }, {7,8 } },
{ { 9, 10}, { 11, 12},{ 13,14} , {15,16 }},
{ { 17, 18}, { 19, 20},{ 21,22}, {23,24 } }
};
var flattened = array3D.Cast<int>().ToArray();
var restored = Expand(flattened, 3, 4);
}
public static T[,,] Expand<T>(T[] arr, int rows0, int rows1)
{
int length = arr.GetLength(0);
int rows2 = length / rows0 / rows1;
int x = 0;
T[,,] arrExpanded = new T[rows0, rows1, rows2];
for (int i = 0; i < rows0; i++)
{
for (int j = 0; j < rows1; j++)
{
for (int k = 0; k < rows2; k++)
{
T test = arr[x++];
arrExpanded[i, j, k] = test;
}
}
}
return arrExpanded;
}
It worked fine for me.
With a help of Linq OfType<T>(), it's easy to have int[] from any multidimensional array:
var result = source.OfType<int>().ToArray();
Demo:
using System.Linq;
...
int[,,] array3D = new int[,,] {
{ { 1, 2}, { 3, 4}, { 5, 6}, { 7, 8 } },
{ { 9, 10}, { 11, 12}, { 13, 14}, {15, 16 } },
{ { 17, 18}, { 19, 20}, { 21, 22}, {23, 24 } },
};
var result = array3D.OfType<int>().ToArray();
Console.Write(string.Join(", ", result));
Outcome:
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24
We can use modulo arithmetics to Expand array back:
private static T[,,] Expand<T>(T[] value, int length1, int length2, int length3) {
T[,,] result = new T[length1, length2, length3];
for (int i = 0; i < value.Length; ++i) {
int r = i / (length3 * length2);
int c = i / length3 % length2;
int h = i % length3;
result[r, c, h] = value[i];
}
return result;
}
E.g.
int[,,] back = Expand(result, 3, 4, 2);
To flatten a multidimensional array just use Cast<T>().ToArray().
var d3 = new int[,,]
{
{ { 1, 2 }, { 3, 4 }, {5,6 }, {7,8 } },
{ { 9, 10}, { 11, 12},{ 13,14} , {15,16 }},
{ { 17, 18}, { 19, 20},{ 21,22}, {23,24 } }
};
var d1 = d3.Cast<int>().ToArray();
Console.WriteLine(string.Join(" ", d1));
Gives:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
To expand use this:
static int[,,] Expand(int[] array, int size2, int size3)
{
var size = new[] { array.Length / size2 / size3, size2, size3 };
var res = Array.CreateInstance(typeof(int), size);
for (var i = 0; i < array.Length; i++)
res.SetValue(array[i], GetMultidimensionalIndex(i, size));
return (int[,,])res;
}
static int[] GetMultidimensionalIndex(int index, int[] size)
{
var factors = size.Select((item, i) => size.Skip(i).Aggregate((a, b) => a * b)).ToArray();
var factorsHelper = factors.Zip(factors.Skip(1).Append(1), (Current, Next) => new { Current, Next }).ToArray();
return factorsHelper.Select(item => index % item.Current / item.Next).ToArray();
}
Usage:
var d3 = new int[,,]
{
{ { 1, 2 }, { 3, 4 }, {5,6 }, {7,8 } },
{ { 9, 10}, { 11, 12},{ 13,14} , {15,16 }},
{ { 17, 18}, { 19, 20},{ 21,22}, {23,24 } }
};
Console.WriteLine("Original:");
Print3DArray(d3);
var flat = d3.Cast<int>().ToArray();
Console.WriteLine("Flat:");
Console.WriteLine(string.Join(" ", flat));
var expanded = Expand(flat, d3.GetLength(1), d3.GetLength(2));
Console.WriteLine("Expanded:");
Print3DArray(expanded);
with helper method:
static void Print3DArray(int[,,] array)
{
Console.WriteLine("{");
for (int i = 0; i < array.GetLength(0); i++)
{
Console.Write(" {");
for (int j = 0; j < array.GetLength(1); j++)
{
Console.Write(" {");
for (int k = 0; k < array.GetLength(2); k++)
{
Console.Write($" {array[i, j, k]}");
}
Console.Write(" }");
}
Console.WriteLine(" }");
}
Console.WriteLine("}");
}
Gives:
Original:
{
{ { 1 2 } { 3 4 } { 5 6 } { 7 8 } }
{ { 9 10 } { 11 12 } { 13 14 } { 15 16 } }
{ { 17 18 } { 19 20 } { 21 22 } { 23 24 } }
}
Flat:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
Expanded:
{
{ { 1 2 } { 3 4 } { 5 6 } { 7 8 } }
{ { 9 10 } { 11 12 } { 13 14 } { 15 16 } }
{ { 17 18 } { 19 20 } { 21 22 } { 23 24 } }
}

How find template from array?

How find template in array ?
Template
int[] = {X, X, X}; //(example 3,3,3)
, or template
int[,] temp2 =
{
{X, X, ?}
{?, X, X}
}
Example
int[,] temp2 =
{
{3, 3, 1}
{2, 3, 3}
}
For example, in such an array?
int[,] a = new int[,]
{
{ 1, 4, 5, 3, 4 },
{ 1, 2, 3, 1, 3 },
{ 1, 1, 2, 4, 4 },
{ 4, 4, 3, 3, 3 },
{ 3, 4, 4, 5, 5 }
};
Is there a faster way than searching each cell and its neighboring cells?
If you are looking for patterns inside a bigger array, probably checking cell by cell is the only way to do it. You could do some complex optimizations for skipping the ? values and speedup a little, but I don't think it would easily work.
A sample code that should do what you asked:
// null means anything is ok, X is 0, Y is 1, Z is 2...
int?[,] temp = new int?[,]
{
{0, 0, null},
{null, 0, 0}
};
int[,] a = new int[,]
{
{ 0, 1, 1, 2, 4, 4, 1 },
{ 0, 1, 4, 4, 3, 3, 3 },
{ 0, 2, 3, 4, 4, 5, 5 }
};
int row, col;
bool success = CheckPattern(temp, a, out row, out col);
Console.WriteLine("Success: {0}, row: {1}, col: {2}", success, row, col);
and then
private static bool CheckPattern(int?[,] temp, int[,] data, out int row, out int col)
{
int rowsT = temp.GetLength(0);
int colsT = temp.GetLength(1);
int rowsD = data.GetLength(0);
int colsD = data.GetLength(1);
// Find the "maximum" value of the template (how many different
// condition are there... If there is only "X" then 1, "X", "Y" then 2,
// "X", "Y", "Z" then 3...
int max = -1;
for (int i = 0; i < rowsT; i++)
{
for (int j = 0; j < rowsT; j++)
{
if (temp[i, j] != null)
{
max = Math.Max(temp[i, j].Value, max);
}
}
}
// We save in an array the "current" values of "X", "Y", "Z", ...
int?[] values = new int?[max + 1];
for (int i = 0; i < rowsD - rowsT + 1; i++)
{
for (int j = 0; j < colsD - colsT + 1; j++)
{
Array.Clear(values, 0, values.Length);
bool success = true;
// Check the template
for (int k = 0; k < rowsT; k++)
{
for (int r = 0; r < colsT; r++)
{
if (temp[k, r] != null)
{
int? curr = values[temp[k, r].Value];
if (curr == null)
{
// If this is the first time we check this
// condition, then any value is good
values[temp[k, r].Value] = data[i + k, j + r];
}
else if (curr.Value == data[i + k, j + r])
{
// For subsequent instances we check this
// condition, then the data must have the
// value found in the previous instance
}
else
{
success = false;
break;
}
}
}
if (!success)
{
break;
}
}
if (success)
{
row = i;
col = j;
return true;
}
}
}
row = 0;
col = 0;
return false;
}
This piece of code should work even for multiple conditions "X", "Y"...

Insertion sort in C# using left and right boundaries

How to create a method for insertion sort using boundaries specifically left and right.
public static void InsertionWorker<TYPE>(TYPE[] data, int left, int right) where TYPE : IComparable<TYPE>
{
TYPE temp;
for (int firstSorted = 0; firstSorted < data.Length - 1; firstSorted++)
for (int current = firstSorted + 1; current > 0; current--)
{
if (data[current - 1].CompareTo(data[current]) < 0)
{
temp = data[current - 1];
data[current - 1] = data[current];
data[current] = temp;
}
current--;
}
}
public static void Insertion<TYPE>(TYPE[] data) where TYPE : IComparable<TYPE>
{
InsertionWorker(data, 0, data.Length - 1);
}
Implementation of Insertion sort in C# using left and right boundaries:
class Program
{
public static void InsertionWorker<T>(T[] data, int left, int right) where T : IComparable<T>
{
for (var i = left; i < right + 1; i++)
{
T tmp = data[i];
int j;
for (j = i - 1; j >= left && tmp.CompareTo(data[j]) < 0; j--)
{
data[j + 1] = data[j];
}
data[j + 1] = tmp;
}
}
static void Main(string[] args)
{
// test data array
var a = new[] {234, 2, 11111, 34, 24, 23, 4, 432, 42, 423, 1, 4, 123, 124, 32, 345, 45, 3, 7, 56,9999999};
// Run insertion sort by provided boundaries
InsertionWorker(a, 7, a.Length-1);
// InsertionWorker(a, 0, 8);
foreach (int t in a)
{
Console.WriteLine(t);
}
Console.ReadKey();
}
}
Insertion sort

Printing 2D array in matrix format

I have a 2D array as follows:
long[,] arr = new long[4, 4] {{ 0, 0, 0, 0 },
{ 1, 1, 1, 1 },
{ 0, 0, 0, 0 },
{ 1, 1, 1, 1 }};
I want to print the values of this array in matrix format like:
0 0 0 0
1 1 1 1
0 0 0 0
1 1 1 1
How can I do this?
You can do it like this (with a slightly modified array to show it works for non-square arrays):
long[,] arr = new long[5, 4] { { 1, 2, 3, 4 }, { 1, 1, 1, 1 }, { 2, 2, 2, 2 }, { 3, 3, 3, 3 }, { 4, 4, 4, 4 } };
int rowLength = arr.GetLength(0);
int colLength = arr.GetLength(1);
for (int i = 0; i < rowLength; i++)
{
for (int j = 0; j < colLength; j++)
{
Console.Write(string.Format("{0} ", arr[i, j]));
}
Console.Write(Environment.NewLine + Environment.NewLine);
}
Console.ReadLine();
like so:
long[,] arr = new long[4, 4] { { 0, 0, 0, 0 }, { 1, 1, 1, 1 }, { 0, 0, 0, 0 }, { 1, 1, 1, 1 } };
var rowCount = arr.GetLength(0);
var colCount = arr.GetLength(1);
for (int row = 0; row < rowCount; row++)
{
for (int col = 0; col < colCount; col++)
Console.Write(String.Format("{0}\t", arr[row,col]));
Console.WriteLine();
}
I wrote extension method
public static string ToMatrixString<T>(this T[,] matrix, string delimiter = "\t")
{
var s = new StringBuilder();
for (var i = 0; i < matrix.GetLength(0); i++)
{
for (var j = 0; j < matrix.GetLength(1); j++)
{
s.Append(matrix[i, j]).Append(delimiter);
}
s.AppendLine();
}
return s.ToString();
}
To use just call the method
results.ToMatrixString();
Here is how to do it in Unity:
(Modified answer from #markmuetz so be sure to upvote his answer)
int[,] rawNodes = new int[,]
{
{ 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0 }
};
private void Start()
{
int rowLength = rawNodes.GetLength(0);
int colLength = rawNodes.GetLength(1);
string arrayString = "";
for (int i = 0; i < rowLength; i++)
{
for (int j = 0; j < colLength; j++)
{
arrayString += string.Format("{0} ", rawNodes[i, j]);
}
arrayString += System.Environment.NewLine + System.Environment.NewLine;
}
Debug.Log(arrayString);
}
Your can do it like this in short hands.
int[,] values=new int[2,3]{{2,4,5},{4,5,2}};
for (int i = 0; i < values.GetLength(0); i++)
{
for (int k = 0; k < values.GetLength(1); k++) {
Console.Write(values[i,k]);
}
Console.WriteLine();
}
you can do like this also
long[,] arr = new long[4, 4] { { 0, 0, 0, 0 }, { 1, 1, 1, 1 }, { 0, 0, 0, 0 }, { 1, 1, 1, 1 }};
for (int i = 0; i < arr.GetLength(0); i++)
{
for (int j = 0; j < arr.GetLength(1); j++)
{
Console.Write(arr[i,j]+" ");
}
Console.WriteLine();
}
If using a square matrix:
int[,] mat = new int[,]{{ 1, 0, 0 },{ 0, 1, 0},{ 0, 0, 1}};
int i=1;
foreach(int e in mat){
Console.Write(i%Math.Sqrt(mat.Length)==0? $"{e}\n" : e);
i+=1;
}

Categories

Resources