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
I'am trying to Draw a Triangle in through three points, with known coordinates enclosed within the Triangle.
I wrote this algorithm to do all this, but the code is slow.
Can anyone give me another easy and faster way to draw a Triangle?
I have got the algorithm of drawing the line from this site but do not mention the post sorry.
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
public partial class Form1 : Form
{
int Screen_height;
int Screen_width;
List<int> Pointsx = new List<int>(new int[] { });
List<int> Pointsy = new List<int>(new int[] { });
List<int> edge_one_Tranglex= new List<int>(new int[] { });
List<int> edge_one_Trangley = new List<int>(new int[] { });
List<int> edge_two_Tranglex = new List<int>(new int[] { });
List<int> edge_two_Trangley = new List<int>(new int[] { });
List<int> edge_three_Tranglex = new List<int>(new int[] { });
List<int> edge_three_Trangley = new List<int>(new int[] { });
int edge = 1;
Bitmap bmp;
int start = 0;
int center_x;
int center_y;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
Screen_height = panel1.Height;
Screen_width = panel1.Width;
Console.WriteLine(" " + Screen_height + "," + Screen_width);
}
private void panel1_Paint(object sender, PaintEventArgs e)
{
if (start == 0)
{
var sw = new Stopwatch();
sw.Start();
bmp = new Bitmap(panel1.Width, panel1.Height);
panel1.BackgroundImage = (Image)bmp;
panel1.BackgroundImageLayout = ImageLayout.None;
//from x to x2 and from y to y2
//D_line(100, 10, -100, 20);
D_Triangle(-300, 10, 100, 20, 100, -100);
sw.Stop();
Console.WriteLine("" + sw.Elapsed);
start += 1;
}
}
public void D_line(int x, int y, int x2, int y2)
{
center_x = Screen_width / 2;
center_y = Screen_height / 2;
line(center_x + x, center_y - y, center_x + x2, center_y - y2);
}
public void line(int x, int y, int x2, int y2)
{
int w = x2 - x;
int h = y2 - y;
int dx1 = 0, dy1 = 0, dx2 = 0, dy2 = 0;
if (w < 0) dx1 = -1; else if (w > 0) dx1 = 1;
if (h < 0) dy1 = -1; else if (h > 0) dy1 = 1;
if (w < 0) dx2 = -1; else if (w > 0) dx2 = 1;
int longest = Math.Abs(w);
int shortest = Math.Abs(h);
if (!(longest > shortest))
{
longest = Math.Abs(h);
shortest = Math.Abs(w);
if (h < 0) dy2 = -1; else if (h > 0) dy2 = 1;
dx2 = 0;
}
int numerator = longest >> 1;
for (int i = 0; i <= longest; i++)
{
//putpixel(x, y, color);
bmp.SetPixel(x, y, Color.Red);
//my code
if (edge == 1)
{
edge_one_Tranglex.Add(x);
edge_one_Trangley.Add(y);
}
if (edge == 2)
{
edge_two_Tranglex.Add(x);
edge_two_Trangley.Add(y);
}
if (edge == 3)
{
edge_three_Tranglex.Add(x);
edge_three_Trangley.Add(y);
}
if (edge >= 4)
{
if (!Pointsx.Contains(x) || !Pointsy.Contains(y))
{
Pointsx.Add(x);
Pointsy.Add(y);
}
}
numerator += shortest;
if (!(numerator < longest))
{
numerator -= longest;
x += dx1;
y += dy1;
}
else
{
x += dx2;
y += dy2;
}
}
edge++;
// edge_two_Trangle.ForEach(p => Console.WriteLine(p));
}
void D_Triangle(int x1, int y1, int x2, int y2, int x3, int y3)
{
D_line(x1, y1, x2, y2);
D_line(x2, y2, x3, y3);
D_line(x3, y3, x1, y1);
int a = edge_two_Tranglex.Count();
for(int i =1; i < a -1;)
{
line(center_x + x1, center_y - y1, edge_two_Tranglex[i], edge_two_Trangley[i]);
i++;
}
}
}
From what i have read and found about the writablebitmap am i not able to change it in a different thread then the one that created it. But i should be able to created it on a diffrent thread then the UI thread, then freze it and parse it to the UI thread for display. Example: Thread cannot access the object
However when i do this, do it tell me "The calling thread cannot access this object because a different thread owns it." who is this, when i have frozen the bitmap?
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Timer imageTimer = new Timer(41);
imageTimer.Elapsed += async (sender, args) =>
{
ImageSource image = await GetImage((int)Math.Ceiling(Image.Width), (int)Math.Ceiling(Image.Height));
DispatcherHelper.CheckBeginInvokeOnUI(() => {
Image.Source = image;
});
};
imageTimer.Start();
}
public Task<WriteableBitmap> GetImage(int width, int height)
{
return Task.Factory.StartNew(() =>
{
WriteableBitmap bitmap = BitmapFactory.New(width, height);
using (bitmap.GetBitmapContext())
{
bitmap.Clear(System.Windows.Media.Colors.AliceBlue);
Random rnd = new Random();
Color[] Colors = new Color[100];
for (int i = 0; i <= 99; i++)
{
Colors[i] = Color.FromRgb((byte)rnd.Next(0, 255), (byte)rnd.Next(0, 255),
(byte)rnd.Next(0, 255));
}
double size = width / 50;
for (int i = 0; i <= 49; i++)
{
int from = (int)Math.Ceiling(size * (double)i);
int to = (int)Math.Ceiling(size * (double)(i + 1)) - 1;
var color = Colors[i];
bitmap.DrawFilledRectangle(from, 0, to, height, color);
}
}
bitmap.Freeze();
return bitmap;
});
}
}
public static class KasperWriteableBitMapExtentions
{
public static void DrawFilledRectangle(this WriteableBitmap bmp, int x1, int y1, int x2, int y2, Color color)
{
// Use refs for faster access (really important!) speeds up a lot!
int w = bmp.PixelWidth;
int h = bmp.PixelHeight;
// Check boundaries
if (x1 < 0) { x1 = 0; }
if (y1 < 0) { y1 = 0; }
if (x2 < 0) { x2 = 0; }
if (y2 < 0) { y2 = 0; }
if (x1 > w) { x1 = w; }
if (y1 > h) { y1 = h; }
if (x2 > w) { x2 = w; }
if (y2 > h) { y2 = h; }
for (int y = y1; y < y2; y++)
{
for (int x = x1; x <= x2; x++)
{
bmp.SetPixel(x, y, color);
}
}
}
}
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)));
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