Ambiguous cases in Marching square algorithm - c#

If we take Wikipedia article on Marching square into account, we see that case#5 and case#10 are said to be ambiguous cases.
I have implemented Marching Square as follows and I am not understanding how an ambiguous case can arise:
public class LinesRectangle
{
public Graphics Graphics { get; set; }
public Color Color { get; set; }
public Pen Pen { get; set; }
public int Thickness { get; set; }
public LinesRectangle()
{
Color = Color.Blue;
Thickness = 2;
Pen = new Pen(Color, Thickness);
}
public void DrawLines(int x, int y, int width, int code)
{
int height = width;
Graphics.DrawRectangle(Pen, new System.Drawing.Rectangle(x, y, width, height));
int x1 = 0, y1 = 0;
int x2 = 0, y2 = 0;
switch (code)
{
case 0:
case 15:
break;
case 1:
case 14:
x1 = x; y1 = y + height/2;
x2 = x + width/2; y2 = y + height;
Graphics.DrawLine(Pen, x1, y1, x2, y2);
break;
case 2:
case 13:
x1 = x + width/2; y1 = y + height;
x2 = x + width; y2 = y + height/2;
Graphics.DrawLine(Pen, x1, y1, x2, y2);
break;
case 3:
case 12:
x1 = x; y1 = y + height / 2;
x2 = x + width; y2 = y + height / 2;
Graphics.DrawLine(Pen, x1, y1, x2, y2);
break;
case 4:
case 11:
x1 = x+width/2; y1 = y;
x2 = x + width; y2 = y + height / 2;
Graphics.DrawLine(Pen, x1, y1, x2, y2);
break;
case 5:
x1 = x ; y1 = y + height/2;
x2 = x + width/2; y2 = y;
Graphics.DrawLine(Pen, x1, y1, x2, y2);
x1 = x + width / 2; y1 = y + height;
x2 = x + width; y2 = y + height / 2;
Graphics.DrawLine(Pen, x1, y1, x2, y2);
break;
case 6:
case 9:
x1 = x + width / 2; y1 = y;
x2 = x + width/2; y2 = y + height;
Graphics.DrawLine(Pen, x1, y1, x2, y2);
break;
case 7:
case 8:
x1 = x; y1 = y + height / 2;
x2 = x + width / 2; y2 = y;
Graphics.DrawLine(Pen, x1, y1, x2, y2);
break;
case 10:
x1 = x + width / 2; y1 = y;
x2 = x + width; y2 = y + height / 2;
Graphics.DrawLine(Pen, x1, y1, x2, y2);
x1 = x; y1 = y + height / 2;
x2 = x + width / 2; y2 = y + height;
Graphics.DrawLine(Pen, x1, y1, x2, y2);
break;
}
}
}
You can see here each of the cases are taken care of individually.
Output:
Can anyone tell me what I am missing?
Driver Program:
public enum What
{
lines, surface, both
}
public partial class DrawingForm : System.Windows.Forms.Form
{
public int [,] Data { get; set; }
public 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 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 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 + 1, j]);
sb.Append(data[i + 1, j + 1]);
sb.Append(data[i, j + 1]);
bitMask[i, j] = Convert.ToInt32(sb.ToString(), 2);
}
}
return bitMask;
}
public DrawingForm()
{
InitializeComponent();
}
private void MainForm_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
int[,] data = new int[,] {
{ 1,1,1,1,1 },
{ 1,2,3,2,1 },
{ 1,3,1,3,1 },
{ 1,2,3,2,1 },
{ 1,1,1,1,1 }
};
int[,] bitMask = marching_square(5, 5, data, 0, What.lines);
Graphics g = this.CreateGraphics();
LinesRectangle rect = new LinesRectangle();
rect.Graphics = g;
for (int j = 0; j < 4; j++)
{
for (int i = 0; i < 4; i++)
{
rect.DrawLines(i*50, j*50, 50, bitMask[i,j]);
}
}
}
}
Edit: In case of the following data (as pointed out by #JeremyLakeman):
{ 2,1,2,1,2 },
{ 1,2,1,2,1 },
{ 2,1,2,1,2 },
{ 1,2,1,2,1 },
{ 2,1,2,1,2 }
my program produced the following output:

Your example doesn't include any ambiguous cases. What output would you expect with the following input;
{ 2,1,2,1,2 },
{ 1,2,1,2,1 },
{ 2,1,2,1,2 },
{ 1,2,1,2,1 },
{ 2,1,2,1,2 }
Circles around the 1's? Circles around the 2's? Diagonal lines?
Edit;
From your code;
case 5:
x1 = x ; y1 = y + height/2;
x2 = x + width/2; y2 = y;
Graphics.DrawLine(Pen, x1, y1, x2, y2);
x1 = x + width / 2; y1 = y + height;
x2 = x + width; y2 = y + height / 2;
Graphics.DrawLine(Pen, x1, y1, x2, y2);
break;
case 10:
x1 = x + width / 2; y1 = y;
x2 = x + width; y2 = y + height / 2;
Graphics.DrawLine(Pen, x1, y1, x2, y2);
x1 = x; y1 = y + height / 2;
x2 = x + width / 2; y2 = y + height;
Graphics.DrawLine(Pen, x1, y1, x2, y2);
break;
You could swap those case labels. You could pick one, delete the other, and merge the cases. You could look at more surrounding pixels to pick one. You could roll a random number to pick which way to draw it.
But you didn't. You arbitrarily decided that you would always draw those cases this way.

Oh man, I understand you. Surprisingly thats a good question!
Ambiguity is seen clearly in a moment when you decide if "value above the isovalue" is black or white and opposite for the "value below the isovalue".
Let me explain what I mean.
If you do algorithm by hand you can get following results. The only choice you do while following algorithm described on wiki - is to decide what color to use when painting nodes.
{ 1, 1, 1 },
{ 1, 2, 1 },
{ 1, 1, 1 }
has no ambiguous cases so the choice does not matter - resulting image will be the same no matter if '1' is a "black dot" or a "white dot".
BUT lets see example with ambiguous cases:
{ 1, 2, 1 },
{ 2, 1, 2 },
{ 1, 2, 1 }
algorith would provide a circle around the middle point if '1's are white, and same algorithm would provide 4 arcs near the middle points if '1's are chosen to be black.
I think moment of choice is in normalize function at
if (data[i, j] > 1)
If you change ">" to "<" you will get change of image for ambigous cases. And it would change nothing for non-ambigous cases. Ambiguity is easier to understand if you look at methods idea not algorithm. Look at saddle point - there is ambiguity in drawing contour because from the one hand saddle point is a minimum and from the other its a maximum - depends on direction of measurements.
Hope that helps to clear the confusion.
Edit: I elaborated in comments but for visibility I'm duplicating it here

Related

i wanted to implement C# Bresenham's line algorithm but it just draw horizontal lines , i want it to draw lines with angles as i saw in many tutorials

what i got when i run it
here's my code i take input from user to draw line using brenesham but it just draw horizontal line even when i tried with many values i have same issue so i want it to draw line with angel as i saw in my tutorials where they implement it with angles not just horizontal angel
private void button2_Click(object sender, EventArgs e)
{
int x1 = Convert.ToInt32(textBox5.Text);
int y1 = Convert.ToInt32(textBox6.Text);
int x2 = Convert.ToInt32(textBox7.Text);
int y2 = Convert.ToInt32(textBox8.Text);
Point p1 = new Point(x1, y1);
Point p2 = new Point(x2, y2);
Bresenham_Line(p1, p2);
}
private void Bresenham_Line(Point p1, Point p2)
{
double x, y, x2, y2;
Bitmap pp = new Bitmap(this.Width, this.Height);
double dx = p2.X - p1.X;
double dy = p2.Y - p2.Y;
double p = 2 * (dy - dx);
double c1 = 2 * dy;
double c2 = 2 * (dy - dx);
x = p1.X; y = p1.Y;
pp.SetPixel((int)x, (int)y, Color.Blue);
x2 = p2.X; y2 = p2.Y;
while (x < x2)
{
if (p < 0)
{
p += c1;
}
else
{
p += c2;
y += 1;
}
x++;
pp.SetPixel((int)x, (int)y, Color.Black);
}
pictureBox1.Image = pp;
}
i added photo from what i get when i run it

SystemArgumentOutOfRangeException C#

namespace Cropping_Image
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
var img = new Bitmap(Image.FromFile(#"C:\Users\Overnighter\Desktop\test.png"));
int num = 1;
int x1 = 0;
var x2 = 120;
int y1 = 0;
var y2 = 120;
while (x2 != img.Width)
{
var width = x2 - x1+1;
var height = y2 - y1+1;
var result = new Bitmap(width, height);
for (var i = x1; i <= x2; i++)
for (var j = y1; j <= y2; j++)
result.SetPixel(i - x1, j - y2, img.GetPixel(i, j));
result.Save(#"C:\Users\Overnighter\Desktop\file\"+ num +".png");
num++;
x1 += 120;
x2 += 120;
}
}
}
}
Specification of the Error:
System.ArgumentOutOfRangeException: "The parameter must be positive and less than the height.
Parameter name: y "
How can I fix this error?
In that Piece of code:
result.SetPixel(**i - x1**, **j - y2**, img.GetPixel(i, j));
You need to be sure that i - x1 (x parameter) and j - y2 (y parameter) are positive,
i think that something like that should be enought to remove the exception:
for (var i = x1; i <= x2; i++)
for (var j = y1; j <= y2; j++)
if((i - x1)>=0 && (j - y2)>=0)
result.SetPixel(i - x1, j - y2, img.GetPixel(i, j));
but if you get that message you're probably soing something wrong u.u

calculate the Euclidean distance between an array in c# with function

I want to calculate a euclidean distance between points that the user enter,so as you can see here :
static void Main(string[] args)
{
int numtest = int.Parse(Console.ReadLine());
int[,] points=new int[10,2];
for (int i = 0; i < numtest; i++)
{
Console.WriteLine("point " +(i+1).ToString()+" x: ");
points[i, 0] = int.Parse(Console.ReadLine());
Console.WriteLine("point " + (i + 1).ToString() + " y: ");
points[i, 1] = int.Parse(Console.ReadLine());
}
}
public float[] calculate(int[,] points)
{
for (int i = 0; i <points.Length ; i++)
{
}
}
is there any function in c# that can do this ?
I need to have each distance value between all points in my array
Here is how to implement the distance calculation between two given points, to get you started:
int x0 = 0;
int y0 = 0;
int x1 = 100;
int y1 = 100;
int dX = x1 - x0;
int dY = y1 - y0;
double distance = Math.Sqrt(dX * dX + dY * dY);
Try following
public void calculate(double[,] points)
{
var distanceArray = new double[points.Length, points.Length];
for (int i = 0; i < points.Length; i++)
for (int j = 0; j < points.Length; j++)
distanceArray[i, j] = Distance(points[i, 0], points[i, 1], points[j, 0], points[j, 1]);
}
public static double Distance(double x1, double y1, double x2, double y2)
=> Math.Sqrt(((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)));

I am having trouble with Bresenham's algorithm

It only works when slope is between 0 and 1. i'm not sure where to go from here. thanks for your help! This method reads in two points and draws the line between them using bresenhams algo. I don't know where to go to optimize it for all lines. thanks for your help.
void Bresenhams(int x1, int y1, int xk, int yk)
{
int deltaX = xk - x1;
int deltaY = yk - y1;
int error = 0;
int y = y1;
int x = x1;
int doubleDeltaX = 2 * deltaX;
bool steep = Math.Abs(yk - y1) > Math.Abs(xk - x1);
canvas.SetPixel(x1, y1, Color.Black);
if (!steep)
{
for (int i = x1 + 1; i <= xk; i++)
{
if (x1 > xk)
{
int temp = x1;
x1 = xk;
xk = temp;
temp = y1;
y1 = yk;
yk = temp;
}
error = error + deltaY;
if (error > deltaX)
{
y++;
error -= doubleDeltaX;
}
canvas.SetPixel(i, y, Color.Black);
}
}
else
{
for (int i = y1 + 1; i <= yk; i++)
{
if (y1 > yk)
{
int temp = x1;
x1 = xk;
xk = temp;
temp = y1;
y1 = yk;
yk = temp;
}
error = error + deltaY;
if (error > deltaY)
{
y++;
error -= doubleDeltaX;
}
canvas.SetPixel(x, i, Color.Black);
}
}
pictureBox1.Image = canvas;
}
Divide a circle into 8 parts. You can run Bresenham over one octant and draw all 8 at the same time. For center at 0,0:
0-45 x,y
45-90 y,x
90-135 -y,x
135-180 -x,y
180-225 -x,-y
225-270 -y,-x
270-315 y,-x
315-360 x,-y

How to write bresenham algorithms in c#?

I wrote like this but it works only in 50% cases. Can someone tell what's wrong?
public void Bresenham(int x1,int y1,int x2,int y2,Color c)
{
double dx = x2 - x1;
double dy = y2 - y1;
double d = 2*dy-dx; //aux variable
double p1 = 2 * dy ;
double p2 = 2 * (dy - dx);
int x = x1;
int y = y1;
int xend;
c = kolor;
if (x1 > x2)
{
x = x2;
y = y2;
xend = x1;
}
else
{
x = x1;
y = y1;
xend = x2;
}
bitmapa.SetPixel(x, y,c);
try
{
while (x < xend)
{
x++;
if (d < 0)
{
d += p1;
}
else
{
d += p2;
y += 1;
}
bitmapa.SetPixel(x, y, c);
}
}
Thanks:)
At first shot, you are missing a case when other coordinate should be handled like now your are handling Y. You now handle the case when DY < DX, you should also handle case when DX < DY, i.e. slope of the line is different.
To understand what I'm saying, look steep here.
And actually, your algorithm will work only in 1/4 cases.

Categories

Resources