есть такая интересная штука -
фрактал.
самый известный фрактал -
множество Мандельброта.
мне удалось раздобыть исходный код построения этого чудо-рисунка на C#
[offtopic]
// <remarks>
// Mandel.cs Copyright 2005, written by Pierre Leclercq
// </remarks>
namespace Mandelbrot
{
public class Mandel
{
//
// Protected fields
//
protected System.Windows.Forms.ProgressBar m_ProgressBar;
//
// Constructor
//
public Mandel(System.Windows.Forms.ProgressBar pProgressBar)
{
m_ProgressBar = pProgressBar;
}
//
// Properties
//
//
// Public members
//
public System.Drawing.Bitmap GetBitmap(
int pImageWidth,
int pImageHeight,
double pXMin,
double pXMax,
double pYMin,
double pYMax,
int pMaxIterationCount)
{
try
{
int i = 0;
int j = 0;
int[][] lValues = new int[pImageHeight][];
for (i = 0; i < pImageHeight; i++)
{
lValues[i] = new int[pImageWidth];
}
CalculateLevels(
lValues,
pImageWidth,
pImageHeight,
pXMin,
pXMax,
pYMin,
pYMax,
pMaxIterationCount);
System.Drawing.Bitmap lBitmap = new System.Drawing.Bitmap(pImageWidth, pImageHeight, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
byte lRed = 0;
byte lGreen = 0;
byte lBlue = 0;
int lPixelByteCount = 4;
int lAlphaPos = 3;
int lRedPos = 2;
int lGreenPos = 1;
int lBluePos = 0;
int lPixelCount = pImageHeight * pImageWidth;
int lPixelPos = 0;
m_ProgressBar.Minimum = 0;
m_ProgressBar.Maximum = lPixelCount;
m_ProgressBar.Value = 0;
System.Drawing.Imaging.BitmapData lBitmapData = new System.Drawing.Imaging.BitmapData();
lBitmap.LockBits(
new System.Drawing.Rectangle(
0,
0,
pImageWidth,
pImageHeight),
System.Drawing.Imaging.ImageLockMode.WriteOnly,
System.Drawing.Imaging.PixelFormat.Format32bppArgb,
lBitmapData);
unsafe
{
System.Byte* lStartPtr = (System.Byte*)((void*)lBitmapData.Scan0);
int lEndToStart = lBitmapData.Stride - pImageWidth * lPixelByteCount;
System.Byte* lPtr = lStartPtr;
for (j = 0; j < pImageHeight; j++)
{
for (i = 0; i < pImageWidth; i++)
{
GetColorFromLevel(
lValues[j][i],
pMaxIterationCount,
out lRed,
out lGreen,
out lBlue);
lPtr[lAlphaPos] = 255;
lPtr[lRedPos] = lRed;
lPtr[lGreenPos] = lGreen;
lPtr[lBluePos] = lBlue;
lPtr += lPixelByteCount;
lPixelPos++;
}
lPtr += lEndToStart;
m_ProgressBar.Value = lPixelPos;
System.Windows.Forms.Application.DoEvents();
}
}
lBitmap.UnlockBits(lBitmapData);
return lBitmap;
}
catch
{
return null;
}
}
//
// Protected members
//
protected double GetPotential(
double pX,
double pY,
int pMaxIterationCount)
{
int lIteration = 0;
double lX = pX;
double lY = pY;
double lX2 = lX * lX;
double lY2 = lY * lY;
double lTemp = 0;
while ((lIteration < pMaxIterationCount) && ((lX2 + lY2) < 10000.0))
{
lTemp = lX2 - lY2 + pX;
lY = 2 * lX * lY + pY;
lX = lTemp;
lX2 = lX * lX;
lY2 = lY * lY;
lIteration++;
}
if (lIteration < pMaxIterationCount)
{
return 0.5 * System.Math.Log(lX2 + lY2) / System.Math.Pow(2.0, (double)lIteration);
}
else
{
return 0.0;
}
}
protected int GetLevel(
double pX,
double pY,
int pMaxIterationCount)
{
int lIteration = 0;
double lX = 0;
double lY = 0;
double lX2 = 0;
double lY2 = 0;
double lTemp = 0;
while ((lIteration < pMaxIterationCount) && ((lX2 + lY2) < 10000.0))
{
lTemp = lX2 - lY2 + pX;
lY = 2 * lX * lY + pY;
lX = lTemp;
lX2 = lX * lX;
lY2 = lY * lY;
lIteration++;
}
return lIteration;
}
protected void CalculateLevels(
int[][] pArrays,
int pImageWidth,
int pImageHeight,
double pXMin,
double pXMax,
double pYMin,
double pYMax,
int pMaxIterationCount)
{
int lMaxImageXIndex = pImageWidth - 1;
int lMaxImageYIndex = pImageHeight - 1;
double lX = 0.0;
double lY = 0.0;
double lXExtent = pXMax - pXMin;
double lYExtent = pYMax - pYMin;
double lXFactor = lXExtent / (double)lMaxImageXIndex;
double lYFactor = lYExtent / (double)lMaxImageYIndex;
double lFactor = System.Math.Min(lXFactor, lYFactor);
int lPixelCount = pImageHeight * pImageWidth;
int lPixelPos = 0;
m_ProgressBar.Minimum = 0;
m_ProgressBar.Maximum = lPixelCount;
m_ProgressBar.Value = 0;
for (int j = 0; j < pImageHeight; j++)
{
lY = pYMin + (double)j * lFactor;
for (int i = 0; i < pImageWidth; i++)
{
lX = pXMin + (double)i * lFactor;
pArrays[j][i] = GetLevel(lX, lY, pMaxIterationCount);
lPixelPos++;
m_ProgressBar.Value = lPixelPos;
System.Windows.Forms.Application.DoEvents();
}
}
}
protected void CalculatePotentials(double[][] pArrays,
int pImageWidth,
int pImageHeight,
double pXMin,
double pXMax,
double pYMin,
double pYMax,
int pMaxIterationCount)
{
int lMaxImageXIndex = pImageWidth - 1;
int lMaxImageYIndex = pImageHeight - 1;
double lX = 0.0;
double lY = 0.0;
double lXExtent = pXMax - pXMin;
double lYExtent = pYMax - pYMin;
double lXFactor = lXExtent / (double)lMaxImageXIndex;
double lYFactor = lYExtent / (double)lMaxImageYIndex;
int lPixelCount = pImageHeight * pImageWidth;
int lPixelPos = 0;
m_ProgressBar.Minimum = 0;
m_ProgressBar.Maximum = lPixelCount;
m_ProgressBar.Value = 0;
for (int j = 0; j < pImageHeight; j++)
{
lY = pYMin + (double)j * lYFactor;
for (int i = 0; i < pImageWidth; i++)
{
lX = pXMin + (double)i * lXFactor;
pArrays[j][i] = GetPotential(lX, lY, pMaxIterationCount);
lPixelPos++;
m_ProgressBar.Value = lPixelPos;
System.Windows.Forms.Application.DoEvents();
}
}
}
protected void GetColorFromLevel(
int pLevel,
int pMaxIteration,
out byte pRed,
out byte pGreen,
out byte pBlue)
{
double lRatio = (double)pLevel / (double)pMaxIteration;
pRed = 0;
pGreen = 0;
pBlue = 0;
if ((lRatio >= 0) && (lRatio < 0.125))
{
pRed = (byte)(((lRatio - 0) / 0.125) * ((double)512) + 0.5);
pGreen = 0;
pBlue = 0;
}
if ((lRatio >= 0.125) && (lRatio < 0.250))
{
pRed = 255;
pGreen = (byte)(((lRatio - 0.125) / 0.125) * ((double)512) + 0.5);
pBlue = 0;
}
if ((lRatio >= 0.250) && (lRatio < 0.375))
{
pRed = (byte)((1.0 - ((lRatio - 0.250) / 0.125)) * ((double)512) + 0.5);
pGreen = 255;
pBlue = 0;
}
if ((lRatio >= 0.375) && (lRatio < 0.500))
{
pRed = 0;
pGreen = 255;
pBlue = (byte)(((lRatio - 0.375) / 0.125) * ((double)512) + 0.5);
}
if ((lRatio >= 0.500) && (lRatio < 0.625))
{
pRed = 0;
pGreen = (byte)((1.0 - ((lRatio - 0.500) / 0.125)) * ((double)512) + 0.5);
pBlue = 255;
}
if ((lRatio >= 0.625) && (lRatio < 0.750))
{
pRed = (byte)(((lRatio - 0.625) / 0.125) * ((double)512) + 0.5);
pGreen = 0;
pBlue = 255;
}
if ((lRatio >= 0.750) && (lRatio < 0.875))
{
pRed = 255;
pGreen = (byte)(((lRatio - 0.750) / 0.125) * ((double)512) + 0.5);
pBlue = 255;
}
if ((lRatio >= 0.875) && (lRatio <= 1.000))
{
pRed = (byte)((1.0 - ((lRatio - 0.875) / 0.125)) * ((double)512) + 0.5);
pGreen = (byte)((1.0 - ((lRatio - 0.875) / 0.125)) * ((double)512) + 0.5);
pBlue = (byte)((1.0 - ((lRatio - 0.875) / 0.125)) * ((double)512) + 0.5);
}
}
//
// Event handlers
//
}
}
[/offtopic]
и ехешник - прилагается, можно рассмотреть кое-какие детали
если понравится - можете посмотреть в гугле разные фракталы, там и видео есть, но самому как-то приятно по нему поползать) хоть там и не такая крутая детализация)
зы. самое интересное - на конце иглы =)