Free cookie consent management tool by TermsFeed Policy Generator

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

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

#1330

  • worked on visualization (and MDS)
File size: 11.6 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.ComponentModel;
24using System.Drawing;
25using System.Globalization;
26using System.Windows.Forms;
27using HeuristicLab.Core.Views;
28using HeuristicLab.Data;
29using HeuristicLab.Encodings.PermutationEncoding;
30using HeuristicLab.MainForm;
31
32namespace HeuristicLab.Problems.QuadraticAssignment.Views {
33  /// <summary>
34  /// The base class for visual representations of a path tour for a TSP.
35  /// </summary>
36  [View("QAPAssignment View")]
37  [Content(typeof(QAPAssignment), true)]
38  public sealed partial class QAPAssignmentView : ItemView {
39    private Bitmap bitmap;
40
41    public new QAPAssignment Content {
42      get { return (QAPAssignment)base.Content; }
43      set { base.Content = value; }
44    }
45
46    /// <summary>
47    /// Initializes a new instance of <see cref="PathTSPTourView"/>.
48    /// </summary>
49    public QAPAssignmentView() {
50      InitializeComponent();
51    }
52
53    protected override void DeregisterContentEvents() {
54      Content.PropertyChanged -= new PropertyChangedEventHandler(Content_PropertyChanged);
55      base.DeregisterContentEvents();
56    }
57    protected override void RegisterContentEvents() {
58      base.RegisterContentEvents();
59      Content.PropertyChanged += new PropertyChangedEventHandler(Content_PropertyChanged);
60    }
61
62    protected override void OnContentChanged() {
63      base.OnContentChanged();
64      if (Content == null) {
65        qualityViewHost.Content = null;
66        pictureBox.Image = null;
67        assignmentViewHost.Content = null;
68      } else {
69        qualityViewHost.Content = Content.Quality;
70        GenerateImage();
71        assignmentViewHost.Content = Content.Assignment;
72      }
73    }
74
75    protected override void SetEnabledStateOfControls() {
76      base.SetEnabledStateOfControls();
77      qualityGroupBox.Enabled = Content != null;
78      pictureBox.Enabled = Content != null;
79      assignmentGroupBox.Enabled = Content != null;
80      distancesRadioButton.Enabled = Content != null;
81      weightsRadioButton.Enabled = Content != null;
82      redrawButton.Enabled = Content != null;
83    }
84
85    private void GenerateImage() {
86      if ((pictureBox.Width > 0) && (pictureBox.Height > 0)) {
87        if (Content == null) {
88          pictureBox.Image = null;
89          if (bitmap != null) bitmap.Dispose();
90          bitmap = null;
91        } else {
92          bool drawDistances = distancesRadioButton.Checked;
93          DoubleMatrix coordinates = Content.Coordinates;
94          DoubleMatrix distances = Content.Distances;
95
96          if ((coordinates == null || coordinates.Rows == 0)
97            && (distances == null || distances.Rows == 0)) {
98            Bitmap newBitmap = new Bitmap(pictureBox.Width, pictureBox.Height);
99            using (Graphics g = Graphics.FromImage(newBitmap)) {
100              string str = "No coordinates and no distance matrix specified.";
101              SizeF strSize = g.MeasureString(str, Font);
102              g.DrawString(str, Font, Brushes.Black, (float)(newBitmap.Width - strSize.Width) / 2.0f, (float)(newBitmap.Height - strSize.Height) / 2.0f);
103            }
104            pictureBox.Image = newBitmap;
105            if (bitmap != null) bitmap.Dispose();
106            bitmap = newBitmap;
107          } else {
108            if ((coordinates == null || coordinates.Rows == 0)
109              && Content.ViewCoordinates == null) {
110              coordinates = GetCoordinatesByMDS(distances);
111              Content.ViewCoordinates = coordinates;
112            } else if ((coordinates == null || coordinates.Rows == 0)
113              && Content.ViewCoordinates != null) {
114              coordinates = Content.ViewCoordinates;
115            }
116
117            DoubleMatrix weights = Content.Weights;
118            Permutation assignment = Content.Assignment;
119
120            GenerateImage(drawDistances, coordinates, distances, weights, assignment);
121          }
122        }
123      }
124    }
125
126    private void GenerateImage(bool drawDistances, DoubleMatrix coordinates, DoubleMatrix distances, DoubleMatrix weights, Permutation assignment) {
127      Bitmap newBitmap = new Bitmap(pictureBox.Width, pictureBox.Height);
128      double xMin = double.MaxValue, yMin = double.MaxValue, xMax = double.MinValue, yMax = double.MinValue;
129      double maxWeight = double.MinValue, maxDistance = double.MinValue;
130      for (int i = 0; i < coordinates.Rows; i++) {
131        if (xMin > coordinates[i, 0]) xMin = coordinates[i, 0];
132        if (yMin > coordinates[i, 1]) yMin = coordinates[i, 1];
133        if (xMax < coordinates[i, 0]) xMax = coordinates[i, 0];
134        if (yMax < coordinates[i, 1]) yMax = coordinates[i, 1];
135
136        for (int j = i + 1; j < coordinates.Rows; j++) {
137          if (weights[i, j] + weights[j, i] > maxWeight)
138            maxWeight = weights[i, j] + weights[j, i];
139
140          if (distances[i, j] > maxDistance)
141            maxDistance = distances[i, j];
142          else if (distances[j, i] > maxDistance)
143            maxDistance = distances[j, i];
144        }
145      }
146
147      int border = 20;
148      double xStep = xMax != xMin ? (pictureBox.Width - 2 * border) / (xMax - xMin) : 1;
149      double yStep = yMax != yMin ? (pictureBox.Height - 2 * border) / (yMax - yMin) : 1;
150
151      Point[] points = new Point[coordinates.Rows];
152      for (int i = 0; i < coordinates.Rows; i++)
153        points[i] = new Point(border + ((int)((coordinates[i, 0] - xMin) * xStep)),
154                              newBitmap.Height - (border + ((int)((coordinates[i, 1] - yMin) * yStep))));
155
156      Random rand = new Random();
157      using (Graphics graphics = Graphics.FromImage(newBitmap)) {
158        graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
159        graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
160        if ((assignment != null) && (assignment.Length == coordinates.Rows) && (assignment.Validate())) {
161          for (int i = 0; i < assignment.Length - 1; i++) {
162            for (int j = i + 1; j < assignment.Length; j++) {
163              Point start, end;
164              string caption = String.Empty;
165              double d = Math.Max(distances[i, j], distances[j, i]);
166              if (drawDistances) {
167                start = points[i];
168                end = points[j];
169                float width = (float)Math.Ceiling(5.0 * d / maxDistance);
170                graphics.DrawLine(new Pen(Color.IndianRed, width), start, end);
171                if (distances[i, j] != distances[j, i])
172                  caption = distances[i, j].ToString(CultureInfo.InvariantCulture.NumberFormat)
173                    + " / " + distances[j, i].ToString(CultureInfo.InvariantCulture.NumberFormat);
174                else
175                  caption = distances[i, j].ToString(CultureInfo.InvariantCulture.NumberFormat);
176              } else {
177                start = points[assignment[i]];
178                end = points[assignment[j]];
179                double w = weights[i, j] + weights[j, i];
180                if (w > 0) {
181                  float width = (float)Math.Ceiling(5.0 * w / maxWeight);
182                  graphics.DrawLine(new Pen(Color.MediumBlue, width), start, end);
183                  caption = w.ToString(CultureInfo.InvariantCulture.NumberFormat);
184                }
185                if (!String.IsNullOrEmpty(caption)) {
186                  double r = rand.NextDouble();
187                  while (r < 0.2 || r > 0.8) r = rand.NextDouble();
188                  float x = (float)(start.X + (end.X - start.X) * r + 5);
189                  float y = (float)(start.Y + (end.Y - start.Y) * r + 5);
190                  graphics.DrawString(caption, Font, Brushes.Black, x, y);
191                }
192              }
193            }
194          }
195        }
196        for (int i = 0; i < points.Length; i++) {
197          Point p = new Point(points[assignment[i]].X - 3, points[assignment[i]].Y - 3);
198          graphics.FillRectangle(Brushes.Black, p.X, p.Y, 8, 8);
199          graphics.DrawString(i.ToString(), Font, Brushes.Black, p.X, p.Y + 10);
200        }
201      }
202      pictureBox.Image = newBitmap;
203      if (bitmap != null) bitmap.Dispose();
204      bitmap = newBitmap;
205    }
206
207    private DoubleMatrix GetCoordinatesByMDS(DoubleMatrix distances) {
208      /*Random random = new Random();
209      int points = distances.Rows;
210      DoubleMatrix coordinates = new DoubleMatrix(points, 2);
211      double rad = (2 * Math.PI) / coordinates.Rows;
212      for (int i = 0; i < coordinates.Rows; i++) {
213        coordinates[i, 0] = 10 * Math.Cos(rad * i);
214        coordinates[i, 1] = 10 * Math.Sin(rad * i);
215      }
216      for (int iterations = 0; iterations < 1000; iterations++) {
217        for (int i = 0; i < points; i++) {
218          double x = coordinates[i, 0], y = coordinates[i, 1];
219          for (int j = 0; j < points; j++) {
220            if (i != j) {
221              double dx = coordinates[i, 0] - coordinates[j, 0];
222              double dy = coordinates[i, 1] - coordinates[j, 1];
223              double l = Math.Sqrt(dx * dx + dy * dy);
224              double dl = distances[i, j];
225              if (Math.Abs(dx) < double.Epsilon) dx = random.NextDouble() + 1;
226              if (Math.Abs(dy) < double.Epsilon) dy = random.NextDouble() + 1;
227              x += random.NextDouble() * ((coordinates[j, 0] + (dx / l) * dl) - x);
228              y += random.NextDouble() * ((coordinates[j, 1] + (dy / l) * dl) - y);
229            }
230          }
231          coordinates[i, 0] = x;
232          coordinates[i, 1] = y;
233        }
234        Content.ViewCoordinates = coordinates;
235      }
236      return coordinates;*/
237      double error;
238      return MultidimensionalScaling.Classic(distances, out error);
239    }
240
241    private void Content_PropertyChanged(object sender, PropertyChangedEventArgs e) {
242      if (InvokeRequired)
243        Invoke(new PropertyChangedEventHandler(Content_PropertyChanged), sender, e);
244      else {
245        switch (e.PropertyName) {
246          case "Coordinates":
247          case "Distances":
248          case "Weights":
249            GenerateImage();
250            break;
251          case "Assignment":
252            GenerateImage();
253            assignmentViewHost.Content = Content.Assignment;
254            break;
255          case "Quality":
256            break;
257          case "ViewCoordinates":
258            if (Content.ViewCoordinates != null)
259              GenerateImage(distancesRadioButton.Checked, Content.ViewCoordinates, Content.Distances, Content.Weights, Content.Assignment);
260            break;
261          default:
262            break;
263        }
264      }
265    }
266
267    private void pictureBox_SizeChanged(object sender, EventArgs e) {
268      GenerateImage();
269    }
270
271    private void radioButton_CheckedChanged(object sender, EventArgs e) {
272      GenerateImage();
273    }
274
275    private void redrawButton_Click(object sender, EventArgs e) {
276      Content.ViewCoordinates = null;
277      GenerateImage();
278    }
279  }
280}
Note: See TracBrowser for help on using the repository browser.