Free cookie consent management tool by TermsFeed Policy Generator

source: branches/QAP/HeuristicLab.Problems.QuadraticAssignment.Views/3.3/QAPView.cs @ 5641

Last change on this file since 5641 was 5641, checked in by abeham, 12 years ago

#1330

  • worked on visualization (and MDS)
File size: 13.0 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Drawing;
24using System.Drawing.Drawing2D;
25using System.Drawing.Text;
26using System.Globalization;
27using System.Windows.Forms;
28using HeuristicLab.Common;
29using HeuristicLab.Data;
30using HeuristicLab.Encodings.PermutationEncoding;
31
32namespace HeuristicLab.Problems.QuadraticAssignment.Views {
33  public partial class QAPView : UserControl {
34    private Bitmap bitmap;
35    private Bitmap defaultBitmap;
36
37    private DoubleMatrix distances;
38    public DoubleMatrix Distances {
39      get { return distances; }
40      set {
41        DeregisterDistancesEvents();
42        distances = value;
43        RegisterDistancesEvents();
44        OnRedraw();
45      }
46    }
47
48    private DoubleMatrix weights;
49    public DoubleMatrix Weights {
50      get { return weights; }
51      set {
52        DeregisterWeightsEvents();
53        weights = value;
54        RegisterWeightsEvents();
55        OnRedraw();
56      }
57    }
58
59    private Permutation assignment;
60    public Permutation Assignment {
61      get { return assignment; }
62      set {
63        DeregisterAssignmentEvents();
64        assignment = value;
65        RegisterAssignmentEvents();
66        OnRedraw();
67      }
68    }
69
70    private void DeregisterDistancesEvents() {
71      if (Distances != null) {
72        Distances.Reset -= new EventHandler(Redraw);
73        Distances.RowsChanged -= new EventHandler(Redraw);
74        Distances.ColumnsChanged -= new EventHandler(Redraw);
75        Distances.ItemChanged -= new EventHandler<EventArgs<int, int>>(Redraw);
76      }
77    }
78
79    private void RegisterDistancesEvents() {
80      if (Distances != null) {
81        Distances.Reset += new EventHandler(Redraw);
82        Distances.RowsChanged += new EventHandler(Redraw);
83        Distances.ColumnsChanged += new EventHandler(Redraw);
84        Distances.ItemChanged += new EventHandler<EventArgs<int, int>>(Redraw);
85      }
86    }
87
88    private void DeregisterWeightsEvents() {
89      if (Weights != null) {
90        Weights.Reset -= new EventHandler(Redraw);
91        Weights.RowsChanged -= new EventHandler(Redraw);
92        Weights.ColumnsChanged -= new EventHandler(Redraw);
93        Weights.ItemChanged -= new EventHandler<EventArgs<int, int>>(Redraw);
94      }
95    }
96
97    private void RegisterWeightsEvents() {
98      if (Weights != null) {
99        Weights.Reset += new EventHandler(Redraw);
100        Weights.RowsChanged += new EventHandler(Redraw);
101        Weights.ColumnsChanged += new EventHandler(Redraw);
102        Weights.ItemChanged += new EventHandler<EventArgs<int, int>>(Redraw);
103      }
104    }
105
106    private void DeregisterAssignmentEvents() {
107      if (Assignment != null) {
108        Assignment.Reset -= new EventHandler(Redraw);
109        Assignment.ItemChanged -= new EventHandler<EventArgs<int>>(Redraw);
110      }
111    }
112
113    private void RegisterAssignmentEvents() {
114      if (Assignment != null) {
115        Assignment.Reset += new EventHandler(Redraw);
116        Assignment.ItemChanged += new EventHandler<EventArgs<int>>(Redraw);
117      }
118    }
119
120    private void Redraw(object sender, EventArgs e) {
121      if (sender is RadioButton && !((RadioButton)sender).Checked)
122        return;
123      OnRedraw();
124    }
125
126    private void Redraw(object sender, EventArgs<int, int> e) {
127      OnRedraw();
128    }
129
130    public QAPView() {
131      InitializeComponent();
132      SetupDefaultBitmap();
133      pictureBox.Resize += new EventHandler(pictureBox_Resize);
134    }
135
136    private void pictureBox_Resize(object sender, EventArgs e) {
137      SetupDefaultBitmap();
138    }
139
140    private void SetupDefaultBitmap() {
141      if (defaultBitmap != null) defaultBitmap.Dispose();
142      defaultBitmap = new Bitmap(pictureBox.Width, pictureBox.Height);
143      using (Graphics g = Graphics.FromImage(defaultBitmap)) {
144        g.TextRenderingHint = TextRenderingHint.AntiAlias;
145        g.SmoothingMode = SmoothingMode.AntiAlias;
146
147        string msg = "No visualization available";
148        SizeF strSize = g.MeasureString(msg, Font);
149        g.DrawString(msg, Font, Brushes.Black, (float)(pictureBox.Width - strSize.Width) / 2.0f, (float)(pictureBox.Height - strSize.Height) / 2.0f);
150      }
151    }
152
153    private void OnRedraw() {
154      if (InvokeRequired) {
155        Invoke((Action)OnRedraw, null);
156      } else {
157        GenerateImage();
158      }
159    }
160
161    private void GenerateImage() {
162      Bitmap newBitmap = null;
163      errorLabel.Text = "Error: -";
164      if (distancesRadioButton.Checked && Distances != null && Distances.Rows > 0
165        && Distances.Rows == Distances.Columns) {
166        newBitmap = GenerateDistanceImage();
167      } else if (weightsRadioButton.Checked && Weights != null && Weights.Rows > 0
168        && Weights.Rows == Weights.Columns) {
169        newBitmap = GenerateWeightsImage();
170      } else if (assignmentRadioButton.Checked
171        && Assignment != null && Assignment.Length > 0
172        && Weights != null && Weights.Rows > 0
173        && Distances != null && Distances.Rows > 0
174        && Weights.Rows == Weights.Columns
175        && Distances.Rows == Distances.Columns
176        && Assignment.Length == Weights.Rows
177        && Assignment.Length == Distances.Rows) {
178        newBitmap = GenerateAssignmentImage();
179      }
180
181      pictureBox.Image = newBitmap != null ? newBitmap : defaultBitmap;
182      if (bitmap != null) bitmap.Dispose();
183      bitmap = newBitmap;
184    }
185
186    private Bitmap GenerateDistanceImage() {
187      if ((pictureBox.Width > 0) && (pictureBox.Height > 0)) {
188        Bitmap newBitmap = new Bitmap(pictureBox.Width, pictureBox.Height);
189
190        double error;
191        DoubleMatrix coordinates = MultidimensionalScaling.Metric(distances, out error);
192        errorLabel.Text = "Error: " + error.ToString(CultureInfo.CurrentCulture.NumberFormat);
193        double xMin = double.MaxValue, yMin = double.MaxValue, xMax = double.MinValue, yMax = double.MinValue;
194        double maxDistance = double.MinValue;
195        for (int i = 0; i < coordinates.Rows; i++) {
196          if (xMin > coordinates[i, 0]) xMin = coordinates[i, 0];
197          if (yMin > coordinates[i, 1]) yMin = coordinates[i, 1];
198          if (xMax < coordinates[i, 0]) xMax = coordinates[i, 0];
199          if (yMax < coordinates[i, 1]) yMax = coordinates[i, 1];
200
201          for (int j = i + 1; j < coordinates.Rows; j++) {
202            if (distances[i, j] > maxDistance) maxDistance = distances[i, j];
203            if (distances[j, i] > maxDistance) maxDistance = distances[j, i];
204          }
205        }
206
207        int border = 20;
208        double xStep = xMax != xMin ? (pictureBox.Width - 2 * border) / (xMax - xMin) : 1;
209        double yStep = yMax != yMin ? (pictureBox.Height - 2 * border) / (yMax - yMin) : 1;
210
211        Point[] points = new Point[coordinates.Rows];
212        for (int i = 0; i < coordinates.Rows; i++)
213          points[i] = new Point(border + ((int)((coordinates[i, 0] - xMin) * xStep)),
214                                newBitmap.Height - (border + ((int)((coordinates[i, 1] - yMin) * yStep))));
215
216        using (Graphics graphics = Graphics.FromImage(newBitmap)) {
217          graphics.SmoothingMode = SmoothingMode.AntiAlias;
218          graphics.TextRenderingHint = TextRenderingHint.AntiAlias;
219          graphics.DrawString("Showing Locations spaced out according to their distances", Font, Brushes.Black, 5, 2);
220
221          for (int i = 0; i < coordinates.Rows - 1; i++) {
222            for (int j = i + 1; j < coordinates.Rows; j++) {
223              Point start = points[i], end = points[j];
224              string caption = String.Empty;
225              double d = Math.Max(distances[i, j], distances[j, i]);
226              float width = (float)Math.Ceiling(5.0 * d / maxDistance);
227              if (d > 0) {
228                graphics.DrawLine(new Pen(Color.IndianRed, width), start, end);
229                if (distances[i, j] != distances[j, i])
230                  caption = distances[i, j].ToString(CultureInfo.InvariantCulture.NumberFormat)
231                    + " / " + distances[j, i].ToString(CultureInfo.InvariantCulture.NumberFormat);
232                else
233                  caption = distances[i, j].ToString(CultureInfo.InvariantCulture.NumberFormat);
234              }
235            }
236          }
237
238          for (int i = 0; i < points.Length; i++) {
239            Point p = new Point(points[i].X - 3, points[i].Y - 3);
240            graphics.FillRectangle(Brushes.Black, p.X, p.Y, 8, 8);
241            graphics.DrawString(i.ToString(), Font, Brushes.Black, p.X, p.Y + 10);
242          }
243        }
244        return newBitmap;
245      }
246      return null;
247    }
248
249    private Bitmap GenerateWeightsImage() {
250      if ((pictureBox.Width > 0) && (pictureBox.Height > 0)) {
251        Bitmap newBitmap = new Bitmap(pictureBox.Width, pictureBox.Height);
252
253        double error;
254        DoubleMatrix coordinates = MultidimensionalScaling.Classic(weights, out error);
255        errorLabel.Text = "Error: " + error.ToString(CultureInfo.CurrentCulture.NumberFormat);
256        double xMin = double.MaxValue, yMin = double.MaxValue, xMax = double.MinValue, yMax = double.MinValue;
257        double maxWeight = double.MinValue;
258        for (int i = 0; i < coordinates.Rows; i++) {
259          if (xMin > coordinates[i, 0]) xMin = coordinates[i, 0];
260          if (yMin > coordinates[i, 1]) yMin = coordinates[i, 1];
261          if (xMax < coordinates[i, 0]) xMax = coordinates[i, 0];
262          if (yMax < coordinates[i, 1]) yMax = coordinates[i, 1];
263
264          for (int j = i + 1; j < coordinates.Rows; j++) {
265            if (weights[i, j] + weights[j, i] > maxWeight)
266              maxWeight = weights[i, j] + weights[j, i];
267          }
268        }
269
270        int border = 20;
271        double xStep = xMax != xMin ? (pictureBox.Width - 2 * border) / (xMax - xMin) : 1;
272        double yStep = yMax != yMin ? (pictureBox.Height - 2 * border) / (yMax - yMin) : 1;
273
274        Point[] points = new Point[coordinates.Rows];
275        for (int i = 0; i < coordinates.Rows; i++)
276          points[i] = new Point(border + ((int)((coordinates[i, 0] - xMin) * xStep)),
277                                newBitmap.Height - (border + ((int)((coordinates[i, 1] - yMin) * yStep))));
278
279        Random rand = new Random();
280        using (Graphics graphics = Graphics.FromImage(newBitmap)) {
281          graphics.SmoothingMode = SmoothingMode.AntiAlias;
282          graphics.TextRenderingHint = TextRenderingHint.AntiAlias;
283          graphics.DrawString("Showing Facilities spaced out according to their weights", Font, Brushes.Black, 5, 2);
284
285          for (int i = 0; i < coordinates.Rows - 1; i++) {
286            for (int j = i + 1; j < coordinates.Rows; j++) {
287              Point start = points[i], end = points[j];
288              string caption = String.Empty;
289              double d = Math.Max(distances[i, j], distances[j, i]);
290              double w = weights[i, j] + weights[j, i];
291              if (w > 0) {
292                float width = (float)Math.Ceiling(3.0 * w / maxWeight);
293                graphics.DrawLine(new Pen(Color.MediumBlue, width), start, end);
294                caption = w.ToString(CultureInfo.InvariantCulture.NumberFormat);
295              }
296              if (!String.IsNullOrEmpty(caption)) {
297                double r = rand.NextDouble();
298                while (r < 0.2 || r > 0.8) r = rand.NextDouble();
299                float x = (float)(start.X + (end.X - start.X) * r + 5);
300                float y = (float)(start.Y + (end.Y - start.Y) * r + 5);
301                graphics.DrawString(caption, Font, Brushes.Black, x, y);
302              }
303            }
304          }
305          for (int i = 0; i < points.Length; i++) {
306            Point p = new Point(points[i].X - 3, points[i].Y - 3);
307            graphics.FillRectangle(Brushes.Black, p.X, p.Y, 8, 8);
308            graphics.DrawString(i.ToString(), Font, Brushes.Black, p.X, p.Y + 10);
309          }
310        }
311        return newBitmap;
312      }
313      return null;
314    }
315
316    private Bitmap GenerateAssignmentImage() {
317      return null;
318    }
319
320    private void CustomDispose(bool disposing) {
321      DeregisterDistancesEvents();
322      DeregisterWeightsEvents();
323      DeregisterAssignmentEvents();
324      if (bitmap != null) bitmap.Dispose();
325      bitmap = null;
326      defaultBitmap.Dispose();
327      defaultBitmap = null;
328    }
329  }
330}
Note: See TracBrowser for help on using the repository browser.