I need to draw a Fermat spiral in C#. I did it, but I want my drawing to be filled in PictureBox, no matter how big real size is.
public void DrawSpiral(double delta, double numCycles, int oX, int oY, SpiralType spiralType, Color color, Graphics g)
{
double a = Convert.ToInt32(textBox1.Text);
Pen p = new Pen(color, 1);
double prevX = oX;
double prevY = oY;
double X = oX;
double Y = oY;
double fi = Convert.ToInt32(textBox2.Text);
double radius = 0;
while (fi <= (numCycles * 360))
{
fi += delta;
if (spiralType == SpiralType.FermaPlus)
{
radius = a * Math.Sqrt(fi);
}
else if (spiralType == SpiralType.FermaMinus)
{
radius = -a * Math.Sqrt(fi);
}
prevX = X;
prevY = Y;
X = (radius * Math.Cos(fi / 180 * Math.PI)) + oX;
Y = (radius * Math.Sin(fi / 180 * Math.PI)) + oY;
g.DrawLine(p, (float)prevX, (float)prevY, (float)X, (float)Y);
}
}
private void DrawButton_Click(object sender, EventArgs e)
{
pictureBox1.Refresh();
Graphics g = pictureBox1.CreateGraphics();
DrawSpiral(2, 5, 150, 150, SpiralType.FermaPlus, Color.Blue, g);
DrawSpiral(2, 5, 150, 150, SpiralType.FermaMinus, Color.Red, g);
}
So, what should I do to have my drawing to be full filled in the PictureBox.
Here is one way to do it:
Change the signature of the DrawSpiral
to include the ClientSize
of the PictureBox
instead of some center coordinates:
public void DrawSpiral(double delta, double numCycles, int spiralType,
Color color, Graphics g, Size sz)
Then calculate the center dynamically:
int oX = sz.Width / 2;
int oY = sz.Height / 2;
double prevX = oX;
double prevY = oY;
double X = oX;
double Y = oY;
Next calculate the factor a
:
a = sz.Width / 2 / Math.Sqrt( numCycles * 360);
Finally call the method only from the Paint
event, passing out the valid Graphics
object:
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
Size sz = pictureBox1.ClientSize;
DrawSpiral(2, 5, SpiralType.FermaPlus, Color.Blue, g, sz);
DrawSpiral(2, 5, SpiralType.FermaMinus, Color.Red, g, sz);
}
Upon resizing the PictureBox
it will still fill the area with the same number of loops..:
A few notes:
The quality and performance could be improved by first collecting the data in a List<Point> points
and then using DrawLines(pen, points.ToArray())
I used just the width
when I calculated the factor a
. Use Math.Min(sz.Width, sz.Height)
to always fit it into a non-square box!
I left your offset calculation in place; but you could instead do a g.TranslateTransform()
..
The PictureBox
will Invalidate/Refresh
itself upon resizing. If you change any parameters do call Invalidate
to pick them up!