Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version

Introduction to Numerical Solutions

, 24 Feb 2012 CPOL
An introduction to numerical solver algorithms with general purpose demonstration code.
///////////////////////////////////////////////////////////////////////////////
//
//  SurfacePlot.cs
//
//  By Philip R. Braica (HoshiKata@aol.com, VeryMadSci@gmail.com)
//
//  Distributed under the The Code Project Open License (CPOL)
//  http://www.codeproject.com/info/cpol10.aspx
///////////////////////////////////////////////////////////////////////////////

// Using.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;

// Namespace.
namespace SolverDemo
{
    /// <summary>
    /// Color coded surface plot.
    /// </summary>
    public partial class SurfacePlot : UserControl
    {
        protected List<Color> m_colorList = new List<Color>();
        protected List<double> m_xaxis = new List<double>();
        protected List<double> m_yaxis = new List<double>();
        protected List<double> m_values = new List<double>();
        protected Bitmap m_back = null;
        protected Bitmap m_front = null;

        /// <summary>
        /// Surface plot
        /// </summary>
        public SurfacePlot()
        {
            InitializeComponent();
            pictureBox1.SizeChanged += new EventHandler(pictureBox1_SizeChanged);
        }

        /// <summary>
        /// Label the axises, or not.
        /// </summary>
        public bool LabelAxis { get; set; }

        /// <summary>
        /// Picture box1 changed size.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void pictureBox1_SizeChanged(object sender, EventArgs e)
        {
            Redraw();
        }

        /// <summary>
        /// Cause a redraw.
        /// </summary>
        public void Redraw()
        {
            timer1.Enabled = true;
        }

        /// <summary>
        /// Color list.
        /// </summary>
        public List<Color> ColorList
        {
            get { return m_colorList; }
            set { m_colorList = value; }
        }

        /// <summary>
        /// X axis
        /// </summary>
        public List<double> XAxis
        {
            get { return m_xaxis; }
            set { m_xaxis = value; }
        }

        /// <summary>
        /// Y axis
        /// </summary>
        public List<double> YAxis
        {
            get { return m_yaxis; }
            set { m_yaxis = value; }
        }

        /// <summary>
        /// List of values.
        /// </summary>
        public List<double> Values
        {
            get { return m_values; }
            set { m_values = value; }
        }

        /// <summary>
        /// Debounce redraw.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void timer1_Tick(object sender, EventArgs e)
        {
            timer1.Enabled = false;
            doRedraw();
        }

        /// <summary>
        /// Select a color from the value.
        /// </summary>
        /// <param name="min"></param>
        /// <param name="max"></param>
        /// <param name="v"></param>
        /// <returns></returns>
        protected Color ColorFromValue(double min, double max, double v)
        {
            if (max == min) return m_colorList[0];
            int mcl = m_colorList.Count;
            double f = (v - min) * ((double)mcl) / (max - min);
            int lw = (int)f;
            int hw = lw + 1;
            lw = lw < 0 ? 0 : lw < mcl ? lw : mcl - 1;
            hw = hw < 0 ? 0 : hw < mcl ? hw : mcl - 1;
            double r = f - (double)lw;
            r = r < 0 ? 0 : r > 1 ? 1 : r;
            int ac = (int)((m_colorList[lw].A * (1 - f)) + (m_colorList[hw].A * f));
            int rc = (int)((m_colorList[lw].R * (1 - f)) + (m_colorList[hw].R * f));
            int gc = (int)((m_colorList[lw].G * (1 - f)) + (m_colorList[hw].G * f));
            int bc = (int)((m_colorList[lw].B * (1 - f)) + (m_colorList[hw].B * f));
            ac = ac < 0 ? 0 : ac > 255 ? 255 : ac;
            rc = rc < 0 ? 0 : rc > 255 ? 255 : rc;
            gc = gc < 0 ? 0 : gc > 255 ? 255 : gc;
            bc = bc < 0 ? 0 : bc > 255 ? 255 : bc;
            return Color.FromArgb(ac, rc, gc, bc);
        }

        /// <summary>
        /// Do a redraw.
        /// </summary>
        protected void doRedraw()
        { 
            if ((m_xaxis == null) || (m_yaxis == null) || (m_values== null) || (m_colorList == null)) return;
            if ((m_values.Count < 1) || (m_xaxis.Count < 1) || (m_yaxis.Count < 1) || (m_colorList.Count < 1)) return;

            float w = (float)pictureBox1.Width;
            float h = (float)pictureBox1.Height;
            if ((w < 10) || (h < 10)) return;
            bool redo = (m_back == null);
            redo = (redo == false) ? ((m_back.Width != w) || (m_back.Height != h)) : true;
            Bitmap tmp = null;
            if (redo)
            {
                tmp = m_back;
                m_back = new Bitmap((int)w, (int)h, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
            }

            double[,] vals = new double[m_xaxis.Count, m_yaxis.Count];

            double minx = m_xaxis[0];
            double maxx = m_xaxis[m_xaxis.Count-1];
            double miny = m_yaxis[0];
            double maxy = m_yaxis[m_yaxis.Count-1];
            double minv = m_values[0];
            double maxv = m_values[0];
            for (int i = 1; i < m_values.Count; i++)
            {
                double v = m_values[i];
                minv = minv < v ? minv : v;
                maxv = maxv > v ? maxv : v;
            }
            float ix = 0; 
            float iy = 0;
            float tw = (float)w / m_xaxis.Count;
            float th = (float)h / m_yaxis.Count;
            using (Graphics g = Graphics.FromImage(m_back))
            {
                for (int i = 1; i < m_values.Count; i++)
                {
                    double v = m_values[i];
                    Color c = ColorFromValue(minv, maxv, v);
                    using (SolidBrush sb = new SolidBrush(c))
                    {
                        g.FillRectangle(sb, ix * tw, iy * th, tw, th);
                    }
                    ix++;
                    if (ix >= m_xaxis.Count)
                    {
                        ix = 0;
                        iy++;
                    }
                }
            }

            tmp = m_front;
            m_front = m_back;
            m_back = tmp;
            pictureBox1.Image = m_front;
        }

    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

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.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

HoshiKata
Software Developer (Senior) KMC Systems
United States United States
Phil is a Principal Software developer focusing on weird yet practical algorithms that run the gamut of embedded and desktop (PID loops, Kalman filters, FFTs, client-server SOAP bindings, ASIC design, communication protocols, game engines, robotics).
 
In his personal life he is a part time mad scientist, full time dad, and studies small circle jujitsu, plays guitar and piano.

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.150123.1 | Last Updated 24 Feb 2012
Article Copyright 2012 by HoshiKata
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid