13,799,674 members

#### Stats

79.7K views
127 bookmarked
Posted 11 May 2010
Licenced Ms-PL

# Visualizing Complex Functions

, 23 May 2010
A program to produce beautiful and informative images of complex functions.
 Complex Explorer ComplexExplorer.exe Meta.Numerics.dll ComplexExplorer ComplexExplorer Icon.ico Properties ```﻿using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Drawing; using System.Globalization; using System.IO; using System.Text; using System.Windows.Forms; using Meta.Numerics; using Meta.Numerics.Functions; namespace ComplexExplorer { public partial class ComplexExplorerForm : Form { public ComplexExplorerForm () { InitializeComponent(); } // create an image based on the current complex function public void DrawImage () { // get the function to evaluate Function f = functions[functionList.SelectedIndex].Function; Bitmap image = new Bitmap(imageBox.Width, imageBox.Height); // iterate over all image pixels for (int x = 0; x < imageBox.Width; x++) { double re = re_min + x * (re_max - re_min) / imageBox.Width; for (int y = 0; y < imageBox.Height; y++) { double im = im_max - y * (im_max - im_min) / imageBox.Height; // form a complex number based on the pixel value Complex z = new Complex(re, im); // compute the value of the current complex function for that complex number Complex fz = f(z); // don't try to plot non-numeric values (e.g. at poles) if (Double.IsInfinity(fz.Re) || Double.IsNaN(fz.Re) || Double.IsInfinity(fz.Im) || Double.IsNaN(fz.Im)) continue; // convert the complex function value to a HSV color triplet ColorTriplet hsv = ColorMap.ComplexToHsv(fz); // convert the HSV color triplet to an RBG color triplet ColorTriplet rgb = ColorMap.HsvToRgb(hsv); int r = (int) Math.Truncate(255.0 * rgb.X); int g = (int) Math.Truncate(255.0 * rgb.Y); int b = (int) Math.Truncate(255.0 * rgb.Z); Color color = Color.FromArgb(r, g, b); // plot the point image.SetPixel(x, y, color); } } // put the image in the image box control imageBox.Image = image; } // bounds in the complex plane private double re_min = -3.0; private double re_max = +3.0; private double im_min = -3.0; private double im_max = +3.0; // the list of complex functions available private List functions = new List(); // when a new function is selected, re-draw image private void functionList_SelectedIndexChanged (object sender, EventArgs e) { valueText.Text = String.Empty; DrawImage(); } // when the image is clicked on, display the function value private void imageBox_MouseClick (object sender, MouseEventArgs e) { if (functionList.SelectedIndex < 0) return; double re = re_min + e.X * (re_max - re_min) / imageBox.Width; double im = im_max - e.Y * (im_max - im_min) / imageBox.Height; Complex z = new Complex(re, im); Complex fz = functions[functionList.SelectedIndex].Function(z); valueText.Text = String.Format(CultureInfo.CurrentCulture, "f({0}) = {1}", FormatComplex(z), FormatComplex(fz)); } // formatting a complex number private static string FormatComplex (Complex z) { StringBuilder text = new StringBuilder(); double re = z.Re; double im = z.Im; if ((re != 0.0) || (im == 0.0)) { text.AppendFormat(CultureInfo.CurrentCulture, "{0:g4}", re); } if (im != 0.0) { if (im < 0.0) { text.Append(CultureInfo.CurrentCulture.NumberFormat.NegativeSign); im = -im; } else { if (re != 0.0) text.Append(CultureInfo.CurrentCulture.NumberFormat.PositiveSign); } text.AppendFormat(CultureInfo.CurrentCulture, "{0:g4}", im); text.Append("i"); } return (text.ToString()); } // save file private void saveButton_Click (object sender, EventArgs e) { SaveFileDialog dialog = new SaveFileDialog(); dialog.Filter = "Portable Network Graphics (*.png)|*.png"; dialog.RestoreDirectory = true; if (dialog.ShowDialog() == DialogResult.OK) { using (Stream writer = dialog.OpenFile()) { if (writer == null) return; imageBox.Image.Save(writer, System.Drawing.Imaging.ImageFormat.Png); } } } // setup behavior private void ComplexExplorerForm_Load (object sender, EventArgs e) { // load functions functions.AddRange(new ComplexFunction[] { new ComplexFunction() { Label = "z", Function = delegate(Complex z) { return (z); } }, new ComplexFunction() { Label = "z^2 - 1", Function = delegate(Complex z) { return ((z-1.0) * (z+ 1.0)); } }, new ComplexFunction() { Label = "z^3 + 1", Function = delegate(Complex z) { return (z*z*z + 1.0); } }, new ComplexFunction() { Label = "1/z", Function = delegate(Complex z) { return(1.0/z); } }, // Claudio Rocchini's example function from http://en.wikipedia.org/wiki/File:Color_complex_plot.jpg new ComplexFunction() { Label = "(z^2-1)(z-2-i)^2/(z^2+2+2i)", Function = delegate(Complex z) { Complex zs = z - 2.0 - ComplexMath.I; return((z*z-1.0)*zs*zs/(z*z+2.0+2.0*ComplexMath.I)); } }, new ComplexFunction() { Label = "sqrt(z)", Function = ComplexMath.Sqrt }, new ComplexFunction() { Label = "exp(z)", Function = ComplexMath.Exp }, new ComplexFunction() { Label = "ln(z)", Function = ComplexMath.Log }, new ComplexFunction() { Label = "Gamma(z)", Function = AdvancedComplexMath.Gamma }, new ComplexFunction() { Label = "Psi(z)", Function = AdvancedComplexMath.Psi }, new ComplexFunction() { Label = "Faddeeva(z)", Function = AdvancedComplexMath.Faddeeva } }); // bind functions to function list foreach (ComplexFunction function in functions) { functionList.Items.Add(function.Label); } // select first function functionList.SelectedIndex = 0; } // call up web site when footer is clicked private void footerLabel_LinkClicked (object sender, LinkLabelLinkClickedEventArgs e) { Process.Start("http://www.meta-numerics.net"); } } } ```

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

## Share

 United States
I am a .NET developer who works daily on enterprise-scale applications using C#, SQL, XML, ASP.NET, and myriad other technologies. My academic background is in physics and economics.

I am the original architect of Sandcastle managed reference documentation engine and of the Meta.Numerics library for scientific computation.

 Pro