Free cookie consent management tool by TermsFeed Policy Generator

source: branches/FitnessLandscapeAnalysis/VRPProblemAnalyzer/PictureGenerator.cs @ 7316

Last change on this file since 7316 was 7316, checked in by svonolfe, 12 years ago

Added Picture generator (#1696)

File size: 9.9 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5using System.Drawing;
6using System.Windows.Forms.DataVisualization.Charting;
7using System.IO;
8
9namespace VRPProblemAnalyzer {
10  public class PictureGenerator {
11    private static int TourSize = 1000;
12    private static double MinDemandSize = 2;
13    private static double MaxDemandSize = TourSize / 25.0;
14
15    private static int TourBorder = (int)Math.Ceiling(MaxDemandSize);
16
17    private static int ChartWidth = TourSize / 2;
18    private static int ChartHeight = 250;
19   
20    private static int DemandSegments = 10;
21
22    private static int DistanceSegments = 10;
23
24    public static Image GeneratePicture(TSPLIBParser problemInstance, SolutionParser solution) {   
25      Image tourVisualization = GenerateTourVisualization(problemInstance, solution);
26      Image demandDistribution = GenerateDemandDistribution(problemInstance);
27      Image distanceDistribution = GenerateDistanceDistribution(problemInstance);
28
29      Bitmap bmp = new Bitmap(Math.Max(TourSize, ChartWidth * 2), tourVisualization.Height + ChartHeight);
30      using (Graphics g = Graphics.FromImage(bmp)) {
31        g.FillRectangle(Brushes.White, 0, 0, bmp.Width, bmp.Height);
32        g.DrawImage(tourVisualization, 0, 0);
33        g.DrawImage(demandDistribution, 0, tourVisualization.Height);
34        g.DrawImage(distanceDistribution, ChartWidth, tourVisualization.Height);
35      }
36      return bmp;
37    }
38
39    private static Image GenerateTourVisualization(TSPLIBParser problemInstance, SolutionParser solution) {
40      double[,] coordinates = problemInstance.Vertices;
41
42      double xMin = double.MaxValue, yMin = double.MaxValue, xMax = double.MinValue, yMax = double.MinValue;
43      for (int i = 0; i < coordinates.GetLength(0); i++) {
44        if (xMin > coordinates[i, 0]) xMin = coordinates[i, 0];
45        if (yMin > coordinates[i, 1]) yMin = coordinates[i, 1];
46        if (xMax < coordinates[i, 0]) xMax = coordinates[i, 0];
47        if (yMax < coordinates[i, 1]) yMax = coordinates[i, 1];
48      }
49      double xWidth = xMax - xMin;
50      double yHeight = yMax - yMin;
51
52      int width, height;
53      if (xWidth > yHeight) {
54        width = TourSize;
55        height = (int)Math.Round(TourSize * (yHeight / xWidth));
56      } else {
57        width = (int)Math.Round(TourSize * (xWidth / yHeight));
58        height = TourSize;
59      }
60      Bitmap bitmap = new Bitmap(width, height);
61
62      double xStep = (width - 2 * TourBorder) / xWidth;
63      double yStep = (height - 2 * TourBorder) / yHeight;
64
65      Pen[] pens = {new Pen(Color.FromArgb(100, 92,20,237)), new Pen(Color.FromArgb(100, 237,183,20)), new Pen(Color.FromArgb(100, 237,20,219)), new Pen(Color.FromArgb(100, 20,237,76)),
66                    new Pen(Color.FromArgb(100, 237,61,20)), new Pen(Color.FromArgb(100, 115,78,26)), new Pen(Color.FromArgb(100, 20,237,229)), new Pen(Color.FromArgb(100, 39,101,19)),
67                    new Pen(Color.FromArgb(100, 230,170,229)), new Pen(Color.FromArgb(100, 142,136,89)), new Pen(Color.FromArgb(100, 157,217,166)), new Pen(Color.FromArgb(100, 31,19,101)),
68                    new Pen(Color.FromArgb(100, 173,237,20)), new Pen(Color.FromArgb(100, 230,231,161)), new Pen(Color.FromArgb(100, 142,89,89)), new Pen(Color.FromArgb(100, 93,89,142)),
69                    new Pen(Color.FromArgb(100, 146,203,217)), new Pen(Color.FromArgb(100, 101,19,75)), new Pen(Color.FromArgb(100, 198,20,237)), new Pen(Color.FromArgb(100, 185,185,185)),
70                    new Pen(Color.FromArgb(100, 179,32,32)), new Pen(Color.FromArgb(100, 18,119,115)), new Pen(Color.FromArgb(100, 104,158,239)), new Pen(Color.Black)};
71
72      foreach (Pen pen in pens) {
73        pen.Width = 2;
74      }
75
76      using (Graphics graphics = Graphics.FromImage(bitmap)) {
77        graphics.FillRectangle(Brushes.White, 0, 0, width, height);
78
79        int currentTour = 0;
80        foreach (List<int> tour in solution.Routes) {
81          Point[] tourPoints = new Point[tour.Count + 2];
82          int[] customerSizes = new int[tour.Count];
83          int lastCustomer = 0;
84
85          for (int i = -1; i <= tour.Count; i++) {
86            int location = 0;
87
88            if (i == -1 || i == tour.Count)
89              location = 0; //depot
90            else
91              location = tour[i];
92
93            Point locationPoint = new Point(TourBorder + ((int)((coordinates[location, 0] - xMin) * xStep)),
94                            bitmap.Height - (TourBorder + ((int)((coordinates[location, 1] - yMin) * yStep))));
95            tourPoints[i + 1] = locationPoint;
96
97            if (i != -1 && i != tour.Count) {
98              customerSizes[i] = (int)Math.Round(MinDemandSize + problemInstance.Demands[location] / problemInstance.Capacity * (MaxDemandSize - MinDemandSize));
99            }
100            lastCustomer = location;
101          }
102
103          graphics.DrawPolygon(pens[((currentTour >= pens.Length) ? (pens.Length - 1) : (currentTour))], tourPoints);
104
105          using(Brush brush = new SolidBrush(Color.FromArgb(100, 0, 0, 0))) {
106            for (int i = 0; i < tour.Count; i++) {
107              int size = customerSizes[i];
108              graphics.FillEllipse(brush, tourPoints[i + 1].X - size, tourPoints[i + 1].Y - size, size * 2, size * 2);
109            }
110          }
111
112          graphics.FillRectangle(Brushes.Blue, tourPoints[0].X - 5, tourPoints[0].Y - 5, 10, 10);
113
114          currentTour++;
115        }
116      }
117
118      for (int i = 0; i < pens.Length; i++)
119        pens[i].Dispose();
120
121      return bitmap;
122    }
123
124    private static List<Tuple<double, int>> GetDemandDistribution(TSPLIBParser problemInstance) {
125      var result = new List<Tuple<double, int>>();
126
127      double step = problemInstance.Capacity / (double)DemandSegments;
128      double current = 0;
129
130      while(current < problemInstance.Capacity) {
131        int count = problemInstance.Demands.Where(d => d > current && d <= current + step).Count();
132        result.Add(new Tuple<double, int>(current + step / 2, count));
133        current += step;           
134      }
135     
136      return result;
137    }
138
139    private static Image GenerateDemandDistribution(TSPLIBParser problemInstance) {     
140      Chart chart = new Chart();
141      chart.Size = new Size(ChartWidth, ChartHeight);
142
143      chart.Titles.Add("Demand Distribution");
144      chart.ChartAreas.Add("");
145
146      chart.ChartAreas[0].BackColor = Color.White;
147
148      chart.ChartAreas[0].AxisX.Title = "Demand";
149      chart.ChartAreas[0].AxisX.Minimum = 0;
150      chart.ChartAreas[0].AxisX.Maximum = problemInstance.Capacity;
151      chart.ChartAreas[0].AxisX.Interval = problemInstance.Capacity / (double)DemandSegments;
152      chart.ChartAreas[0].AxisX.MajorGrid.Enabled = false;
153
154      chart.ChartAreas[0].AxisY.Title = "Customers";
155      chart.ChartAreas[0].AxisY.Minimum = 0;
156      chart.ChartAreas[0].AxisY.Maximum = problemInstance.Vertices.GetLength(0);
157      chart.ChartAreas[0].AxisY.MajorGrid.Enabled = true;
158      chart.ChartAreas[0].AxisY.MajorGrid.LineColor = Color.FromArgb(100, Color.Blue);
159
160      chart.Series.Add("");
161      chart.Series[0].ChartType = SeriesChartType.Column;
162
163      foreach (Tuple<double, int> entry in GetDemandDistribution(problemInstance)) {
164        chart.Series[0].Points.AddXY(entry.Item1, entry.Item2);
165      }
166
167      Image image;
168      using (var chartimage = new MemoryStream()) {
169        chart.SaveImage(chartimage, ChartImageFormat.Png);
170        image = Image.FromStream(chartimage);
171      }
172      return image;
173    }
174
175    private static double GetAverageDistance(int customer, double[,] vertices) {
176      double dist = 0;
177      int count = 0;
178
179      for (int i = 0; i < vertices.GetLength(0); i++) {
180        if (i != customer) {
181          dist += Utils.GetDistance(vertices, customer, i);
182          count++;
183        }
184      }
185
186      return dist / count;
187    }
188
189    private static List<Tuple<double, int>> GetDistanceDistribution(TSPLIBParser problemInstance) {
190      var result = new List<Tuple<double, int>>();
191
192      double step = 1.0 / (double)DistanceSegments;
193      double current = 0;
194
195      List<double> averageDistances = new List<double>();
196      for (int i = 0; i < problemInstance.Vertices.GetLength(0); i++) {
197        averageDistances.Add(GetAverageDistance(i, problemInstance.Vertices));
198      }
199
200        while (current < 1.0) {
201          int count = averageDistances.Where(d => d > current && d <= current + step).Count();
202          result.Add(new Tuple<double, int>(current + step / 2, count));
203          current += step;
204        }
205
206      return result;
207    }
208
209    private static Image GenerateDistanceDistribution(TSPLIBParser problemInstance) {
210      Chart chart = new Chart();
211      chart.Size = new Size(ChartWidth, ChartHeight);
212
213      chart.Titles.Add("Distance Distribution");
214      chart.ChartAreas.Add("");
215
216      chart.ChartAreas[0].BackColor = Color.White;
217
218      chart.ChartAreas[0].AxisX.Title = "Distance";
219      chart.ChartAreas[0].AxisX.Minimum = 0;
220      chart.ChartAreas[0].AxisX.Maximum = 1;
221      chart.ChartAreas[0].AxisX.Interval = 1.0 / (double)DistanceSegments;
222      chart.ChartAreas[0].AxisX.MajorGrid.Enabled = false;
223
224      chart.ChartAreas[0].AxisY.Title = "Customers";
225      chart.ChartAreas[0].AxisY.Minimum = 0;
226      chart.ChartAreas[0].AxisY.Maximum = problemInstance.Vertices.GetLength(0);
227      chart.ChartAreas[0].AxisY.MajorGrid.Enabled = true;
228      chart.ChartAreas[0].AxisY.MajorGrid.LineColor = Color.FromArgb(100, Color.Blue);
229
230      chart.Series.Add("");
231      chart.Series[0].ChartType = SeriesChartType.Column;
232
233      foreach (Tuple<double, int> entry in GetDistanceDistribution(problemInstance)) {
234        chart.Series[0].Points.AddXY(entry.Item1, entry.Item2);
235      }
236
237      Image image;
238      using (var chartimage = new MemoryStream()) {
239        chart.SaveImage(chartimage, ChartImageFormat.Png);
240        image = Image.FromStream(chartimage);
241      }
242      return image;
243    }
244  }
245}
Note: See TracBrowser for help on using the repository browser.