Free cookie consent management tool by TermsFeed Policy Generator

source: branches/FitnessLandscapeAnalysis/HeuristicLab.Analysis.FitnessLandscape.Views/FDC/HeatMapControl.cs @ 15528

Last change on this file since 15528 was 7128, checked in by epitzer, 13 years ago

#1696 Integrate fitness landscape analysis plugins from Heureka! repository.

File size: 6.2 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.ComponentModel;
4using System.Drawing;
5using System.Linq;
6using System.Windows.Forms;
7
8namespace HeuristicLab.Analysis.FitnessLandscape.FDC {
9  public partial class HeatMapControl : Control {
10
11    public const int N_BINS = 50;
12
13    public HeatMapControl() {
14      InitializeComponent();
15    }
16
17    private List<PointF> points = new List<PointF>();
18
19    public void AddPoints(IEnumerable<PointF> points) {
20      this.points.AddRange(points);
21      ForceUpdate();
22    }
23
24    public void Clear() {
25      points.Clear();
26      ForceUpdate();
27    }
28
29    private Bitmap bitmap = null;
30
31    protected override void OnPaint(PaintEventArgs pe) {
32      if (bitmap != null)
33        pe.Graphics.DrawImage(bitmap, new Rectangle(0, 0, Width, Height));
34      base.OnPaint(pe);
35    }
36
37    public static RectangleF CreateBounds(IEnumerable<PointF> points, BackgroundWorker worker, DoWorkEventArgs a) {
38      if (points.Count() == 0)
39        return new RectangleF(0, 0, 1, 1);
40      double minX = points.Select(p => p.X).Min();
41      if (worker.CancellationPending) {
42        a.Cancel = true;
43        return new RectangleF(0, 0, 1, 1);
44      }
45      double maxX = points.Select(p => p.X).Max();
46      if (worker.CancellationPending) {
47        a.Cancel = true;
48        return new RectangleF(0, 0, 1, 1);
49      }
50      double minY = points.Select(p => p.Y).Min();
51      if (worker.CancellationPending) {
52        a.Cancel = true;
53        return new RectangleF(0, 0, 1, 1);
54      }
55      double maxY = points.Select(p => p.Y).Max();
56      if (worker.CancellationPending) {
57        a.Cancel = true;
58        return new RectangleF(0, 0, 1, 1);
59      }
60      return new RectangleF((float)minX, (float)minY, (float)(maxX - minX), (float)(maxY - minY));
61    }
62
63    public static double[,] CreateHeapMap(IEnumerable<PointF> points, int hBins, int vBins, BackgroundWorker worker, DoWorkEventArgs a) {
64      RectangleF bounds = CreateBounds(points, worker, a);
65      MatrixBuffer<int> countMap = new MatrixBuffer<int>(hBins, vBins);
66      foreach (PointF p in points) {
67        if (worker.CancellationPending) {
68          a.Cancel = true;
69          return null;
70        }
71        int x = (int)Math.Round((hBins - 1) * (p.X - bounds.X) / bounds.Width);
72        int y = (int)Math.Round((vBins - 1) * (p.Y - bounds.Y) / bounds.Height);
73        countMap[x, y] += 1;
74      }
75      int maxCount = countMap.Max();
76      double[,] heatMap = new double[hBins, vBins];
77      if (maxCount > 0) {
78        for (int x = 0; x < hBins; x++) {
79          for (int y = 0; y < vBins; y++) {
80            if (worker.CancellationPending) {
81              a.Cancel = true;
82              return null;
83            }
84            heatMap[x, y] = 1.0 * countMap[x, y] / maxCount;
85          }
86        }
87      }
88      return heatMap;
89    }
90
91    private static Bitmap CreateBitmap(IEnumerable<PointF> points, int width, int height, BackgroundWorker worker, DoWorkEventArgs a) {
92      ColorGradient gradient = new ColorGradient();
93      gradient[0.0] = Color.Blue;
94      gradient[0.5] = Color.Green;
95      gradient[1.0] = Color.Red;
96      var heatMap = CreateHeapMap(points, N_BINS, N_BINS, worker, a);
97      double binWidth = 1.0 * width / N_BINS;
98      double binHeight = 1.0 * height / N_BINS;
99      if (worker.CancellationPending) {
100        a.Cancel = true;
101        return new Bitmap(1, 1);
102      }
103      Bitmap bitmap = new Bitmap(width, height);
104      using (Graphics g = Graphics.FromImage(bitmap)) {
105        for (int x = 0; x < heatMap.GetLength(0); x++) {
106          for (int y = 0; y < heatMap.GetLength(1); y++) {
107            if (worker.CancellationPending) {
108              a.Cancel = true;
109              break;
110            }
111            using (Brush b = new SolidBrush(gradient[heatMap[x, y]])) {
112              g.FillRectangle(b, (float)(x * binWidth), (float)(y * binHeight), (float)binWidth, (float)binHeight);
113            }
114          }
115        }
116        g.Flush();
117      }
118      return bitmap;
119    }
120
121    private void HeatMapControl_Resize(object sender, EventArgs e) {
122      if (bitmap == null || bitmap.Width < Width || bitmap.Height < bitmap.Height)
123        ForceUpdate();
124    }
125
126    BackgroundWorker worker;
127    object workerLock = new object();
128
129    public void ForceUpdate() {
130      lock (workerLock) {
131        if (worker != null)
132          worker.CancelAsync();
133        worker = new BackgroundWorker() {
134          WorkerSupportsCancellation = true
135        };
136        Bitmap bitmap = null;
137        IEnumerable<PointF> points = this.points.ToList();
138        int width, height;
139        width = height = Math.Min(Width, Height);
140        worker.DoWork += (s, a) => {
141          bitmap = CreateBitmap(points, width, height, worker, a);
142        };
143        worker.RunWorkerCompleted += (s, a) => {
144          if (!a.Cancelled) {
145            SetBitmap(bitmap);
146            lock (workerLock) {
147              this.worker = null;
148            }
149          }
150        };
151        worker.RunWorkerAsync();
152      }
153    }
154
155    private void SetBitmap(Bitmap bitmap) {
156      if (InvokeRequired) {
157        Invoke(new Action<Bitmap>(SetBitmap));
158      } else {
159        this.bitmap = bitmap;
160        Invalidate();
161      }
162    }
163
164  }
165
166  public class MatrixBuffer<T> : IEnumerable<T> {
167
168    private T[,] matrix;
169
170    public MatrixBuffer(int x, int y) {
171      matrix = new T[x, y];
172    }
173
174    public T this[int x, int y] {
175      get {
176        if (IsInside(x, y))
177          return matrix[x, y];
178        else
179          return default(T);
180      }
181      set {
182        if (IsInside(x, y))
183          matrix[x, y] = value;
184      }
185    }
186
187    public bool IsInside(int x, int y) {
188      return x >= 0 && x < matrix.GetLength(0) && y >= 0 && y < matrix.GetLength(1);
189    }
190
191
192    #region IEnumerable<T> Members
193
194    public IEnumerator<T> GetEnumerator() {
195      foreach (T e in matrix)
196        yield return e;
197    }
198
199    #endregion
200
201    #region IEnumerable Members
202
203    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
204      return matrix.GetEnumerator();
205    }
206
207    #endregion
208  }
209}
Note: See TracBrowser for help on using the repository browser.