C# double rounded down to zero [duplicate] - c#

This question already has answers here:
Why does division result in zero instead of a decimal?
(5 answers)
Closed 5 years ago.
I have some C# code for converting an omnicam picture to a normal image. However, the formula is behaving differently than expected.
Code:
int Rin = 35; //Image specific variable
int Rout = 237; //Image specific variable
int cx = 312; //Image specific variable
int cy = 239; //Image specific variable
int width = (int) Math.Round(2 * Math.PI * Rout);
int height = (int) Math.Round((double)(Rout - Rin));
for (int i = 0; i < image.GetLength(0); i++)
{
double y1 = i / height;
double r = Rin + (1 - y1 * height);
for (int j = 0; j < image.GetLength(1); j++)
{
double x1 = j / width;
double theta = -2 * Math.PI * (j / width);
double xp = r * Math.Cos(theta) + cx;
double yp = r * Math.Sin(theta) + cy;
Console.WriteLine(theta + " = " + (-2 * Math.PI) + " * (" + j + " / " + width + ")");
Console.WriteLine(xp + " = " + r + " * " + Math.Cos(theta) + " + " + cx);
Console.WriteLine(yp + " = " + r + " * " + Math.Sin(theta) + " + " + cy);
Console.WriteLine("");
omnicam[i, j] = Color.FromArgb(1, 1, 1);
}
}
However, this prints out
0 = -6.28318530717959 * (82 / 1489)
348 = 36 * 1 + 312
239 = 36 * 0 + 239
If I print x1, it shows 0 for all values. However, I'm not sure why. The loop goes up to 895, and 895 / 1489 = 0.601... So why is it rounded down automatically?

double x1 = j / width;
Both j and width are INTs.
double x1 = j / (double)width;
Will give you the expected result.
If both of the arguments in C# is a int, then the result will be a int.
If any of the arguments in C# is a double, a double divide is used which results in a double.

Related

What does "-?" as double type represent in C#?

So I'm running iterations with this formula:
double x = 10 / 0.25 * ((0.0002 * x1 * (10 - 0.25 * x1)) + 0.00217 * x2 * (20 - 0.25 * x2)); With this process: Xn+1 = f(Xn).
And if you start from negative X you will eventually end up with (-/+) infinity, so after 6 iterations I'm supposed to get infinity, but what I got surprised me and I couldn't find anywhere what that is, I got "-?", I've tried comparing it to +/- infinity and tried to compare it to int numbers just to clarify what it is, but I cant get anything out of it, for example, I've tried if ("-?" > 1000) break;, and it doesn't outcome as "true". Neither am I getting any errors by comparing it to int/double, I need to stop iterations when I start going into infinity, how can I do that?
code:
public static double CalculateX1(double x1, double x2)
{
double x = 10 / 0.25 * ((0.0002 * x1 * (10 - 0.25 * x1)) + 0.00217 * x2 * (20 - 0.25 * x2));
return x;
}
public static double CalculateX2(double x2, double x1)
{
double y = 20 / 0.25 * ((0.00052 * x2 * (20 - 0.25 * x2)) + 0.0075 * x1 * (10 - 0.25 * x1));
return y;
}
static void Main(string[] args)
{
string writePath = #"C:\Users\evluc\Desktop\cord.txt";
double X = -5;
double Y = -5;
int pointer = 1;
double[,] coordinates = new double[10001, 2];
coordinates[0, 0] = X;
coordinates[0, 1] = Y;
for (int i = 0; i < 5000; i++)
{
//double XTemp = CalculateX1(X, Y);
//double YTemp = CalculateX2(Y, X);
//X = CalculateX1(coordinates[pointer - 1, 0], coordinates[pointer - 1, 1]);
//Y = CalculateX2(coordinates[pointer - 1, 1], coordinates[pointer - 1, 0]);
coordinates[pointer, 0] = CalculateX1(coordinates[pointer - 1, 0], coordinates[pointer - 1, 1]);
coordinates[pointer, 1] = CalculateX2(coordinates[pointer - 1, 1], coordinates[pointer - 1, 0]);
pointer++;
if (Math.Abs(coordinates[pointer, 0]) > 1000 || Math.Abs(coordinates[pointer, 1]) > 1000)
{
Console.WriteLine("infinity");
Console.ReadKey();
}
}
for (int i = 0; i < 5000; i++)
{
Console.WriteLine("X = " + coordinates[i, 0] + "," + "Y = " + coordinates[i, 1] + "; ");
}
}
I think whatever you use to display/inspect the value cannot print ∞.
double d = double.MinValue;
d *= 2;
Console.WriteLine($"{d}: IsInfinity: {double.IsNegativeInfinity(d)}");
-∞: IsInfinity: True
Stopping at infinity
Here's a loop that stops at infinity:
double d = 2;
var i = 1;
while(!double.IsInfinity(d))
{
d = i*d*d;
i = -i;
}
Console.WriteLine(d);
-∞

How do I merge layers using raw pixel data in C# UWP?

Because the Universal Windows Platform does not support flattening Bitmap "layers" by default, I have been creating an algorithm (based on one found here) to take each individual pixels of each layer, and overlay them one over another. The problem is that because I'm using Alpha to allow images to have transparent pixels, I am unsure how to properly merge the pixels so it looks as though one is being places on top of the other.
Here is my code so far:
private unsafe SoftwareBitmap CompileImage()
{
SoftwareBitmap softwareBitmap = new SoftwareBitmap(BitmapPixelFormat.Bgra8, Width, Height);
using (BitmapBuffer buffer = softwareBitmap.LockBuffer(BitmapBufferAccessMode.Write))
{
using (var reference = buffer.CreateReference())
{
byte* dataInBytes;
uint capacity;
((IMemoryBufferByteAccess)reference).GetBuffer(out dataInBytes, out capacity);
BitmapPlaneDescription bufferLayout = buffer.GetPlaneDescription(0);
for (int index = 0; index < layers.Length; index++)
{
for (int i = 0; i < bufferLayout.Height; i++)
{
for (int j = 0; j < bufferLayout.Width; j++)
{
if(index == 0)
{
dataInBytes[bufferLayout.StartIndex + bufferLayout.Stride * i + 4 * j + 0] =
layers[index].pixelData[bufferLayout.StartIndex + bufferLayout.Stride * i + 4 * j + 0]; //B
dataInBytes[bufferLayout.StartIndex + bufferLayout.Stride * i + 4 * j + 1] =
layers[index].pixelData[bufferLayout.StartIndex + bufferLayout.Stride * i + 4 * j + 1]; //G
dataInBytes[bufferLayout.StartIndex + bufferLayout.Stride * i + 4 * j + 2] =
layers[index].pixelData[bufferLayout.StartIndex + bufferLayout.Stride * i + 4 * j + 2]; //R
dataInBytes[bufferLayout.StartIndex + bufferLayout.Stride * i + 4 * j + 3] =
layers[index].pixelData[bufferLayout.StartIndex + bufferLayout.Stride * i + 4 * j + 3]; //A
}
else if(index > 0)
{
//Attempts to "Average" pixel data
dataInBytes[bufferLayout.StartIndex + bufferLayout.Stride * i + 4 * j + 0] =
(byte)(dataInBytes[bufferLayout.StartIndex + bufferLayout.Stride * i + 4 * j + 0] *
layers[index].pixelData[bufferLayout.StartIndex + bufferLayout.Stride * i + 4 * j + 0] / 2);
dataInBytes[bufferLayout.StartIndex + bufferLayout.Stride * i + 4 * j + 1] =
(byte)(dataInBytes[bufferLayout.StartIndex + bufferLayout.Stride * i + 4 * j + 1] *
layers[index].pixelData[bufferLayout.StartIndex + bufferLayout.Stride * i + 4 * j + 1] / 2);
dataInBytes[bufferLayout.StartIndex + bufferLayout.Stride * i + 4 * j + 2] =
(byte)(dataInBytes[bufferLayout.StartIndex + bufferLayout.Stride * i + 4 * j + 2] *
layers[index].pixelData[bufferLayout.StartIndex + bufferLayout.Stride * i + 4 * j + 2] / 2);
dataInBytes[bufferLayout.StartIndex + bufferLayout.Stride * i + 4 * j + 3] =
(byte)(dataInBytes[bufferLayout.StartIndex + bufferLayout.Stride * i + 4 * j + 3] *
layers[index].pixelData[bufferLayout.StartIndex + bufferLayout.Stride * i + 4 * j + 3] / 2);
}
}
}
}
}
}
return softwareBitmap;
}
The current algorithm will take the average BGRA values of each pixel in every layer, and return the result. This is not what I intended it to do. How do I go about correcting it? Thanks in advance
To apply an alpha mix you multiply the previous color by the inverse alpha and the current color by the alpha, of course you should do it on a 0-1 scale (that's why graphic cards work with floats for colors).
Per example, suppose you have three layers, A, B and C, you use A as a base, then mix it with B: (pseudocode)
//bAlpha is thge alpha value of the current pixel from B in byte value
var alpha = bAlpha / 255.0f;
var invAlpha = 1.0f - alpha;
//aRGB is the RGB value of the pixel on the layer A
//bRGB is the RGB value of the pixel on the layer B
var abRGB = aRGB * invAlpha + bRGB * alpha;
And now you apply the third layer:
//cAlpha is thge alpha value of the current pixel from C in byte value
alpha = cAlpha / 255.0f;
invAlpha = 1.0f - alpha;
//abRGB is the RGB value of the previously mixed layers
//cRGB is the RGB value of the pixel on the layer C
var abcRGB = abRGB * invAlpha + cRGB * alpha;
Of course all of this is on ARGB mode, there's also pARGB in which the colors are already premultiplied, so you only need to multiply the previous color by the inverse alpha and add the current color.
//bAlpha is the alpha value of the current pixel from B in byte value
var invAlpha = 1.0f - (bAlpha / 255.0f);
//aRGB is the RGB value of the pixel on the layer A
//bRGB is the RGB value of the pixel on the layer B
var abRGB = aRGB * invAlpha + bRGB;
invAlpha = 1.0f - (cAlpha / 255.0f);
//abRGB is the RGB value of the previously mixed layers
//cRGB is the RGB value of the pixel on the layer C
var abcRGB = abRGB * invAlpha + cRGB;

moving a curve by inverse slope of each point without overlap

I am trying to draw curves a specified distance away from a curve. Kind of like the sides of roads are always a set distance away from the yellow lines in the center. I have code to do this, however, when done using my code it ends up with overlap in one of the curves.
Here is my code:
for (int i = 0; i < curves.Count; i++)
{
for (float j = 0; j < 1; j += .001f)
{
Vector2 temp = Vector2.CatmullRom(curves[i].Points[0], curves[i].Points[1], curves[i].Points[2], curves[i].Points[3], j);
if (mid.Count != 0)
{
if (temp != mid[mid.Count - 1])
{
mid.Add(temp);
}
else Console.WriteLine(temp == mid[mid.Count - 1]);
}
else mid.Add(temp);
}
}
for (int i = 0; i < mid.Count; i++)
{
if (i == 0)
{
Vector2 slope = mid[i] - mid[i + 1];
double x = mid[i].X + (12 * Math.Cos(Math.Atan(-(slope.X / slope.Y)))),
y = mid[i].Y + (12 * Math.Sin(Math.Atan(-(slope.X / slope.Y))));
side1.Add(new Vector2((float)x, (float)y));
x = mid[i].X - (12 * Math.Cos(Math.Atan(-(slope.X / slope.Y))));
y = mid[i].Y - (12 * Math.Sin(Math.Atan(-(slope.X / slope.Y))));
side2.Add(new Vector2((float)x, (float)y));
}
else if (i < mid.Count - 1)
{
Vector2 slope1 = mid[i] - mid[i - 1],
slope2 = mid[i + 1] - mid[i];
Vector2 slope = (slope1 + slope2) / 2;
double x = mid[i].X + (12 * Math.Cos(Math.Atan(-(slope.X / slope.Y)))),
y = mid[i].Y + (12 * Math.Sin(Math.Atan(-(slope.X / slope.Y))));
side1.Add(new Vector2((float)x, (float)y));
x = mid[i].X - (12 * Math.Cos(Math.Atan(-(slope.X / slope.Y))));
y = mid[i].Y - (12 * Math.Sin(Math.Atan(-(slope.X / slope.Y))));
side2.Add(new Vector2((float)x, (float)y));
}
else
{
Vector2 slope = mid[i] - mid[i - 1];
double x = mid[i].X + (12 * Math.Cos(Math.Atan(-(slope.X / slope.Y)))),
y = mid[i].Y + (12 * Math.Sin(Math.Atan(-(slope.X / slope.Y))));
side1.Add(new Vector2((float)x, (float)y));
x = mid[i].X - (12 * Math.Cos(Math.Atan(-(slope.X / slope.Y))));
y = mid[i].Y - (12 * Math.Sin(Math.Atan(-(slope.X / slope.Y))));
side2.Add(new Vector2((float)x, (float)y));
}
}
And here is a photo of the result:
Curves with overlap
Any and all help would be appreciated.

How can I reset the i variable inside my for loop?

for (int k = 0; k < 32;k=k+1)
{
for (int j = 1; j < 32; j++)
{
double Score = (user0[k] * user0[j] + user1[k] * user1[j] + user2[k] * user2[j] + user3[k] * user3[j] + user4[k] * user4[j] + user5[k] * user5[j] + user6[k] * user6[j] + user7[k] * user7[j] + user8[k] * user8[j] + user9[k] * user9[j] + user10[k] * user10[j] + user11[k] * user11[j] + user12[k] * user12[j] + user13[k] * user13[j] + user14[k] * user14[j] + user15[k] * user15[j] + user16[k] * user16[j] + user17[k] * user17[j] + user18[k] * user18[j] + user19[k] * user19[j] + user20[k] * user20[j] + user21[k] * user21[j] + user22[k] * user22[j] + user23[k] * user23[j] + user24[k] * user24[j] + user25[k] * user25[j] + user26[k] * user26[j] + user27[k] * user27[j] + user28[k] * user28[j] + user29[k] * user29[j] + user30[k] * user30[j] + user31[k] * user31[j]) / ((Math.Sqrt(user0[k] * user0[k] + user1[k] * user1[k] + user2[k] * user2[k] + user3[k] * user3[k] + user4[k] * user4[k] + user5[k] * user5[k] + user6[k] * user6[k] + user7[k] * user7[k] + user8[k] * user8[k] + user9[k] * user9[k] + user10[k] * user10[k] + user11[k] * user11[k] + user12[k] * user12[k] + user13[k] * user13[k] + user14[k] * user14[k] + user15[k] * user15[k] + user16[k] * user16[k] + user17[k] * user17[k] + user18[k] * user18[k] + user19[k] * user19[k] + user20[k] * user20[k] + user21[k] * user21[k] + user22[k] * user22[k] + user23[k] * user23[k] + user24[k] * user24[k] + user25[k] * user25[k] + user26[k] * user26[k] + user27[k] * user27[k] + user28[k] * user28[k] + user29[k] * user29[k] + user30[k] * user30[k] + user31[k] * user31[k])) * (Math.Sqrt(user0[j] * user0[j] + user1[j] * user1[j] + user2[j] * user2[j] + user3[j] * user3[j] + user4[j] * user4[j] + user5[j] * user5[j] + user6[j] * user6[j] + user7[j] * user7[j] + user8[j] * user8[j] + user9[j] * user9[j] + user10[j] * user10[j] + user11[j] * user11[j] + user12[j] * user12[j] + user13[j] * user13[j] + user14[j] * user14[j] + user15[j] * user15[j] + user16[j] * user16[j] + user17[j] * user17[j] + user18[j] * user18[j] + user19[j] * user19[j] + user20[j] * user20[j] + user21[j] * user21[j] + user22[j] * user22[j] + user23[j] * user23[j] + user24[j] * user24[j] + user25[j] * user25[j] + user26[j] * user26[j] + user27[j] * user27[j] + user28[j] * user28[j] + user29[j] * user29[j] + user30[j] * user30[j] + user31[j] * user31[j])));
if (Score > simScore)
{
simScore = Score;
}
}
System.Console.WriteLine("Score =" + simScore);
}
I think you can ignore the long equation.
I need this program to compare 1 book to 32 other books.
The for (int k = 0; k < 5;k=k+1)loop is for the one selected book to be compared to 32 others (then give the greatest similarity rating).
The for (int j = 1; j < 32; j++) loop is to allow all the different books to be compared to the the book selected (book k).
The problem is that a book cannot be compared to itself because I think it ruins the equation and I get non-sensical values for the similarity ratings.
How can I omit a book?
(For example: When comparing k=3 (book 3) to other books, how can I make it so that j will not use the same reference?
Start the second loop from one past the first. Comparing the pair (a,b) is the same as comparing (b,a), so you don't need to start from the beginning with each subsequent book.
for (var k = 0; k < 5; k++)
{
for (var j = k + 1; j < 5; j++)
{
....
// if you need the complete set, you can store both
rating[j][k] = ...
rating[k][j] = ...
}
}
The most straightforward way would be to put an if statement that only evaluates the body of the second loop if k != j. I'm not familiar with C#, so there may be other ways of doing it that I'm not aware of, but this is how I would do it in Python.
How about using continue?
for (int k = 0; k < 32; k++) {
for (int j = 0; j < 32; j++) {
if (j == k)
continue;
// Compare
if (isMatch)
break;
}
}

mipmapping producing wrong results

I'm trying to generate the mipmap of an image. The pixels are stored as a byte[] and the format is {r,g,b,a,r,g,b,a,r,g,b,a ... }
What this is trying to do is get each group of four pixels in the image and find the average of those four pixels, then put that into a new image.
The result of creating all the mipmaps for a sample texture are here: http://imgur.com/KdEEzAw
If there is a way to create the mipmaps without using my own algorithm, and without directx or anything (i'm not using the mipmaps for rendering, i'm saving them to a file) that would be good
public static byte[] mipmap(byte[] inPixels, int width, int height)
{
// add one to width and height incase they are 1
byte[] outPixels = new byte[((width + 1) / 2) * ((height + 1) / 2) * 4];
for (int y = 0; y < height; y += 2)
{
for (int x = 0; x < width; x += 2)
{
// get the four red values
int[] r = new int[4];
r[0] = (int)inPixels[x + y * width + 0]; // top left
r[1] = (int)inPixels[(x + 1) + y * width + 0]; // top right
r[2] = (int)inPixels[(x + 1) + (y + 1) * width + 0]; // bottom right
r[3] = (int)inPixels[x + (y + 1) * width + 0]; // bottom left
// get the four green values
int[] g = new int[4];
g[0] = (int)inPixels[x + y * width + 1]; // top left
g[1] = (int)inPixels[(x + 1) + y * width + 1]; // top right
g[2] = (int)inPixels[(x + 1) + (y + 1) * width + 1]; // bottom right
g[3] = (int)inPixels[x + (y + 1) * width + 1]; // bottom left
// get the four blue values
int[] b = new int[4];
b[0] = (int)inPixels[x + y * width + 2]; // top left
b[1] = (int)inPixels[(x + 1) + y * width + 2]; // top right
b[2] = (int)inPixels[(x + 1) + (y + 1) * width + 2]; // bottom right
b[3] = (int)inPixels[x + (y + 1) * width + 2]; // bottom left
// get the four alpha values
int[] a = new int[4];
a[0] = (int)inPixels[x + y * width + 3]; // top left
a[1] = (int)inPixels[(x + 1) + y * width + 3]; // top right
a[2] = (int)inPixels[(x + 1) + (y + 1) * width + 3]; // bottom right
a[3] = (int)inPixels[x + (y + 1) * width + 3]; // bottom left
// the index in the new image, we divide by 2 because the image is half the size of the original image
int index = (x + y * width) / 2;
outPixels[index + 0] = (byte)((r[0] + r[1] + r[2] + r[3]) / 4);
outPixels[index + 1] = (byte)((g[0] + g[1] + g[2] + g[3]) / 4);
outPixels[index + 2] = (byte)((b[0] + b[1] + b[2] + b[3]) / 4);
outPixels[index + 3] = (byte)((a[0] + a[1] + a[2] + a[3]) / 4);
}
}
return outPixels;
}
I think the problem lies here:
inPixels[x + y * width + 0]
normally this runs correct when one array element is one pixel, only one element is one channel of one pixel. So each pixel starts a (x + (y * width)) * 4 so it should be something like this:
inPixels[((x + y * width) * 4) + 0]
I wrote some code for optimalization maybe you get some extra ideas, but i did not test it:
public static byte[] mipmap(byte[] inPixels, int width, int height)
{
// add one to width and height incase they are 0
byte[] outPixels = new byte[((width / 2) * (height / 2)) * 4];
// the offsets of the neighbor pixels (with *4 for the channel)
// this will automatically select a channel of a pixel one line down.
int[] neighborOffsets = new int[] { 0 * 4, 1 * 4, width * 4, (width + 1) * 4 };
// an 'offset for output buffer'
int outputOffset = 0;
// an 'offset for input buffer'
int inputOffset = 0;
for (int y = 0; y < height / 2; y++)
{
for (int x = 0; x < width / 2; x++)
{
// calculate the average of each channel
for (int channelIndex = 0; channelIndex < 4; channelIndex++)
{
int totalValue = 0;
for (int offset = 0; offset < 4; offset++)
totalValue = (int)inPixels[inputOffset + neighborOffsets[offset] + channelIndex];
// write it to the ouput buffer and increase the offset.
outPixels[outputOffset++] = (byte)(totalValue / 4);
}
// set the input offset on the next pixel. The next pixel is current + 2.
inputOffset += 2 * 4; // *4 for the channelcount (*4 will be optimized by the compiler)
}
inputOffset += width * 4; // skip an extra line. *4 for the channelcount (*4 will be optimized by the compiler)
}
return outPixels;
}
There maybe some little mistakes in it, but it probably run 4 times as fast. Try to avoid redundancy on multiplications.

Categories