Draw a curve of the Cycloid - c#

Good time of day. It is necessary to draw a graph of the cycloids, the radius is specified by the user. Managed to paint only half of the period, I do not understand what it is.
Code'm applying.
My function:
return r * Math.Acos((r - y) / r) - Math.Sqrt(2 * r * y - Math.Pow(y, 2));
And my Main part:
GraphPane pane = zedGraph.GraphPane;
pane.CurveList.Clear();
PointPairList list = new PointPairList();
double r = 20;
double xmax = 50;
for (double y = 0; y < xmax; y+=0.5)
{
list.Add(CountIt(y, r), y);
}
LineItem myCurve = pane.AddCurve("Cycloid", list, Color.Red, SymbolType.None);
zedGraph.AxisChange();
zedGraph.Invalidate();
Apparently it is necessary to consider the situation when y>2r, or that should be several possible x? I do not understand how to get out of the situation.

It is simpler to use parametric equations (with t=0..2*Pi for one period):
x = r * (t - sin(t))
y = r * (1 - cos(t))
If you want to continue using Cartesian equation x(y) - change limit for y to correct value 2 * r and mirror the second part like this:
for (double y = 0; y < 2 * r; y+=0.5)
{
list.Add(CountIt(y, r), y);
}
for (double y = 2 * r; y >= 0; y-=0.5)
{
list.Add(2 * Pi * r - CountIt(y, r), y);
}
If you need to draw few periods, limiting xmax:
p = 0;
while true do
{
for (double y = 0; y < 2 * r; y+=0.5)
{ x = 2 * Pi * r * p + CountIt(y, r);
if (x > xmax)
break;
list.Add(x, y);
}
for (double y = 2 * r; y >= 0; y-=0.5)
{
x = 2 * Pi * r * (p + 1) - CountIt(y, r);
if (x > xmax)
break;
list.Add(x, y);
}
p++;
}

Related

Problem with different outcome with DCT transformation on image while converting C++ to C#

I tried to write APP that would make DCT-2 transformation on image fragment and then transform back with inverse DCT-2. I have found code in c++/opencv that I tried to convert to C#, but somehow, I have different outcome at some point. Here is the code i tried to convert:
for (unsigned v = 0; v < BLOCK_SIZE; ++v)
{
for (unsigned u = 0; u < BLOCK_SIZE; ++u)
{
const double cu = (u == 0) ? 1.0 / sqrt(2) : 1.0;
const double cv = (v == 0) ? 1.0 / sqrt(2) : 1.0;
double dctCoeff = 0;
for (unsigned y = 0; y < BLOCK_SIZE; ++y)
{
for (unsigned x = 0; x < BLOCK_SIZE; ++x)
{
double uCosFactor = cos((double)(2 * x + 1) * M_PI * (double)u / (2 * (double) BLOCK_SIZE));
double vCosFactor = cos((double)(2 * y + 1) * M_PI * (double)v / (2 * (double) BLOCK_SIZE));
double pixel = (double)(lenaNoseGrey.at<unsigned char>(cv::Point(x,y)));
dctCoeff += pixel * uCosFactor * vCosFactor;
}
}
dctCoeff *= (2 / (double) BLOCK_SIZE) * cu * cv;
lenaNoseDct.at<double>(cv::Point(u,v)) = dctCoeff;
}
}
And here is mine:
for (int v = 0; v < BLOCK_SIZE; ++v)
{
for (int u = 0; u < BLOCK_SIZE; ++u)
{
double cu = (u == 0) ? 1.0 / Math.Sqrt(2) : 1.0;
double cv = (v == 0) ? 1.0 / Math.Sqrt(2) : 1.0;
double dctCoeff = 0;
double dctCoeffAlpha = 0;
for (int y1 = 0; y1 < BLOCK_SIZE; ++y1)
{
for (int x1 = 0; x1 < BLOCK_SIZE; ++x1)
{
double uCosFactor = Math.Cos((2 * x1 + 1) * Math.PI * u / (2 * (double)BLOCK_SIZE));
double vCosFactor = Math.Cos((2 * y1 + 1) * Math.PI * v / (2 * (double)BLOCK_SIZE));
double pixel = (double)bitmapaWy1.GetPixel((x1 + 284), (y1 + 313)).R;
double pixelalpha = (double)bitmapaWy1.GetPixel((x1 + 284), (y1 + 313)).A;
dctCoeff += pixel * uCosFactor * vCosFactor;
//dctCoeffAlpha += pixelalpha * uCosFactor * vCosFactor;
dctCoeffAlpha = pixelalpha;
}
}
dctCoeffAlpha *= (2 / (double)BLOCK_SIZE) * cu * cv;
dctCoeff *= (2 / (double)BLOCK_SIZE) * cu * cv;
macierz[u, v] = dctCoeff;
}
}
I have different outcome in my matrix, but when i convert matrix from the C++ code above with my inverse code, it works well.
Can you find what have I done wrong? One difference I can spot is with getpixel method, but it is performed on exact same grayscaled image and image fragment that C++ code was performed.
When i inverse my matrix to image again, I can see image, but it has lot of random pixels that are too white, or too black.
Problem is solved, the issue was too much code, actual code i posted works, problem was code I had after it, which was changing "dctcoeff" to byte and it was inside loop, so value of dct didnt reset to 0;
int BLOCK_SIZE = 16;
double[,] macierz = new double[16, 16];
for (int v = 0; v < BLOCK_SIZE; ++v)
{
for (int u = 0; u < BLOCK_SIZE; ++u)
{
double cu = (u == 0) ? 1.0 / Math.Sqrt(2) : 1.0;
double cv = (v == 0) ? 1.0 / Math.Sqrt(2) : 1.0;
double dctCoeff = 0;
for (int y1 = 0; y1 < BLOCK_SIZE; ++y1)
{
for (int x1 = 0; x1 < BLOCK_SIZE; ++x1)
{
double uCosFactor = Math.Cos((2 * x1 + 1) * Math.PI * u / (2 * (double)BLOCK_SIZE));
double vCosFactor = Math.Cos((2 * y1 + 1) * Math.PI * v / (2 * (double)BLOCK_SIZE));
double pixel = bitmapaWy1.GetPixel((x1 + 284), (y1 + 313)).R;
dctCoeff += pixel * uCosFactor * vCosFactor;
//dctCoeffAlpha += pixelalpha * uCosFactor * vCosFactor;
}
}
dctCoeff *= (2 / (double)BLOCK_SIZE) * cu * cv;
macierz[u, v] = dctCoeff;
}
}
This code works like a charm. I hope some good soul will use it, becouse i spent about 20h into making it work.
This is clearly a precision issue.
Most likely the problem is at the following line:
macierz[u, v] = dctCoeff;
I also have doubt in:
double pixel = (double)bitmapaWy1.GetPixel((x1 + 284), (y1 + 313)).R;
double pixelalpha = (double)bitmapaWy1.GetPixel((x1 + 284), (y1 + 313)).A;
dctCoeff += pixel * uCosFactor * vCosFactor;
//dctCoeffAlpha += pixelalpha * uCosFactor * vCosFactor;
dctCoeffAlpha = pixelalpha;

How to draw a spherical shell?

I'm trying to arrange points in a spherical shell in C#. I have code to arrange a bunch of points (I'm doing finite element analysis) in a spherical pattern with radius of double earthRadius. I can't figure out how to do the same for a spherical shell like the type pictured here. Ideas?
for (double x = -earthRadius; x < earthRadius; x += pointIncrement) //taken from http://stackoverflow.com/questions/8671385/sphere-drawing-in-java and slightly altered to make more efficient
{
for (double y = -earthRadius; y < earthRadius; y += pointIncrement)
{
for (double z = -earthRadius; z < earthRadius; z += pointIncrement)
{
if ((x * x) + (y * y) + (z * z) <= earthRadius * earthRadius)
{
earth.AddPoint(new Vector(x, y, z), 0);
totalPoints++;
}
}
}
}
I figured this out using just Cartesian coordinates. I elected not to use spherical coordinates because it was a suboptimal solution: it made the code less elegant and using Math.Sin() and Math.Cos() would have slowed it down. Here's the eventual solution I got:
for (double x = -earthRadius; x < earthRadius; x += pointIncrement) //taken from http://stackoverflow.com/questions/8671385/sphere-drawing-in-java and slightly altered to make more efficient
{
for (double y = -earthRadius; y < earthRadius; y += pointIncrement)
{
for (double z = -earthRadius; z < earthRadius; z += pointIncrement)
{
if ((x * x) + (y * y) + (z * z) <= earthRadius * earthRadius)
{
if ((x * x) + (y * y) + (z * z) >= (earthRadius - shellThickness) * (earthRadius - shellThickness))
{
earth.AddPoint(new Vector(x, y, z), 0); // need to figure out how to calculate masspoint
totalPoints++;
}
}
}
}
}
Notice that I simply added another if statement. I (foolishly) didn't use the && operator because I thought it reduced readability.

Simple Mandelbrot renderer runs out of memory

Ive been trying to make an simple mandelbrot renderer just to get myself into c# and forms, but when i render the image the program runs out of memory sometimes.
The memory builds up to 2GB and then crashes.
But sometimes it builds up i a jigsaw pattern like this and dont crash:
http://puu.sh/l2ri9/2fcd47e6d7.png
==============Code to render================
Renderer.CreateGraphics().Clear(Color.White);
double minR = System.Convert.ToDouble(MinR.Value);
double maxR = System.Convert.ToDouble(MaxR.Value);
double minI = System.Convert.ToDouble(MaxI.Value);
double maxI = System.Convert.ToDouble(MinI.Value);
int maxN = System.Convert.ToInt32(Iterations.Value);
SolidBrush MandelColor = new SolidBrush(Color.Red);
for (int y = 0; y < Renderer.Height; y++)
{
for (int x = 0; x < Renderer.Width; x++)
{
double cr = fitInRRange(x, Renderer.Width, minR, maxR);
double ci = fitInIRange(y, Renderer.Height, minI, maxI);
int n = findMandelbrot(cr, ci, maxN);
double t = ((n + 0.0) / (maxN + 0.0));
MandelColor.Color = Color.FromArgb(System.Convert.ToInt32(9 * (1 - t) * t * t * t * 255), System.Convert.ToInt32(15 * (1 - t) * (1 - t) * t * t * 255), System.Convert.ToInt32(8.5 * (1 - t) * (1 - t) * (1 - t) * t * 255));
Renderer.CreateGraphics().FillRectangle(MandelColor, x, y, 1, 1);
}
}
===Link To Github page===
https://github.com/JimAlexBerger/MandelbrotProject
Why not move Renderer.CreateGraphics() outside of the loop? The memory leak is probably caused by redundantly calling Renderer.CreateGraphics() without calling IDisposable.Dispose() on the Graphics object.
double minR = System.Convert.ToDouble(MinR.Value);
double maxR = System.Convert.ToDouble(MaxR.Value);
double minI = System.Convert.ToDouble(MaxI.Value);
double maxI = System.Convert.ToDouble(MinI.Value);
int maxN = System.Convert.ToInt32(Iterations.Value);
SolidBrush MandelColor = new SolidBrush(Color.Red);
using(var graphics = Renderer.CreateGraphics())
{
graphics.Clear(Color.White);
for (int y = 0; y < Renderer.Height; y++)
{
for (int x = 0; x < Renderer.Width; x++)
{
double cr = fitInRRange(x, Renderer.Width, minR, maxR);
double ci = fitInIRange(y, Renderer.Height, minI, maxI);
int n = findMandelbrot(cr, ci, maxN);
double t = ((n + 0.0) / (maxN + 0.0));
MandelColor.Color = Color.FromArgb(System.Convert.ToInt32(9 * (1 - t) * t * t * t * 255), System.Convert.ToInt32(15 * (1 - t) * (1 - t) * t * t * 255), System.Convert.ToInt32(8.5 * (1 - t) * (1 - t) * (1 - t) * t * 255));
gfx.FillRectangle(MandelColor, x, y, 1, 1);
}
}
}

Draw Cosx with specific period width

how can i draw a period of Cosx with width =100 and height 50?
my recent code is very hard to control them :(
// this to find y with each x to draw Cos
for (int i = 0, j = 0; i < 50; i += 1, j++)
{
int y = (int)((Math.Cos((double)i * height/10F * Math.PI / cy) + 1.0) * (cx - 1) / widtd/10F);
poi.SetValue(new Point(i, y),j); // poi is an aray of point
}
Based on OP's last comment I assume "width" means a single period. Therefore to calculate the points of a cosine function with amplitude amp and a period of period looks like this:
int amp = 50, period = 100;
Point[] poi = new Point[period];
for (int x = 0; x < period; x++)
{
int y = (int)(amp * Math.Cos(x * 2 * Math.PI * (1.0 / period)));
poi[x] = new Point(x, y);
}
Note that this is a "1:1" calculation, i.e. one point is one pixel.
I found solution here:
string filename = #"D:\test.bmp";
int width = 200;
int height = 300;
Bitmap b = new Bitmap(width, height);
for (int i = 0; i < width; i++)
{
int y = (int)((Math.Cos((double)i * 2.0 * Math.PI / width) + 1.0) * (height - 1) / 2.0);
b.SetPixel(i, y, Color.Black);
}
b.Save(filename);

Loop from x1,y1 to x2,y2, no matter in which order they are

I want to be able to select part of an image via two Points (p1,p2). My problem is that I want to use the same loop regardless in which order they are.
right now I have this:
for (int x = p1.X; x != p2.X; x += Math.Sign(p2.X - p1.X))
{
for (int y = p1.Y; y != p2.Y; y += Math.Sign(p2.Y - p1.Y))
{
MessageBox.Show(String.Format("{0} {1}", x, y));
}
}
With that loop I don't get all of the numbers:
e.g. from 1/1 to 3/3 only gones till 2/2.
I some how need to loop through both loops one more time, but since I don't know which way I'm actually looping (decreasing or increasing) I can't just add/ subtract one from the loop.
any help would be appreciated!
You can just loop from the lowest X to the highest X, and then do the same for Y.
for (int x = Math.Min(p1.X, p2.X); x <= Math.Max(p1.X, p2.X); x++){
for (int y = Math.Min(p1.Y, p2.Y); y <= Math.Max(p1.Y, p2.Y); y++){
MessageBox.Show(String.Format("{0} {1}", x, y));
}
}
This will not walk down from [3,3] to [1,1]. If you actually care about the direction, this approach won't work.
Point p1 = new Point(1, 1);
Point p2 = new Point(3, 3);
int dx = Math.Sign(p2.X - p1.X);
int dy = Math.Sign(p2.Y - p1.Y);
for (int x = p1.X; x != p2.X + dx; x += dx)
{
for (int y = p1.Y; y != p2.Y + dy; y += dy)
{
Console.WriteLine("{0} {1}", x, y);
}
}

Categories