Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Problems.GrammaticalOptimization/DynamicDataDisplay/Charts/Isolines/IsolineGraph.cs @ 13777

Last change on this file since 13777 was 12503, checked in by aballeit, 10 years ago

#2283 added GUI and charts; fixed MCTS

File size: 7.2 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.Diagnostics;
4using System.Windows;
5using System.Windows.Controls;
6using System.Windows.Media;
7using System.Windows.Shapes;
8using Microsoft.Research.DynamicDataDisplay.Charts.Isolines;
9using Microsoft.Research.DynamicDataDisplay.Common.Auxiliary;
10using Microsoft.Research.DynamicDataDisplay.Common;
11
12namespace Microsoft.Research.DynamicDataDisplay.Charts
13{
14  /// <summary>
15  /// Draws isolines on given two-dimensional scalar data.
16  /// </summary>
17  public sealed class IsolineGraph : IsolineRenderer
18  {
19    private static Brush labelBackground = new SolidColorBrush(Color.FromArgb(130, 255, 255, 255));
20
21    /// <summary>
22    /// Initializes a new instance of the <see cref="IsolineGraph"/> class.
23    /// </summary>
24    public IsolineGraph()
25    {
26      Content = content;
27      Viewport2D.SetIsContentBoundsHost(this, true);
28    }
29
30    protected override void OnPlotterAttached()
31    {
32      CreateUIRepresentation();
33      UpdateUIRepresentation();
34    }
35
36    private readonly Canvas content = new Canvas();
37
38    protected override void UpdateDataSource()
39    {
40      base.UpdateDataSource();
41
42      CreateUIRepresentation();
43      rebuildText = true;
44      UpdateUIRepresentation();
45    }
46
47    protected override void OnLineThicknessChanged()
48    {
49      foreach (var path in linePaths)
50      {
51        path.StrokeThickness = StrokeThickness;
52      }
53    }
54
55    private List<FrameworkElement> textBlocks = new List<FrameworkElement>();
56    private List<Path> linePaths = new List<Path>();
57    protected override void CreateUIRepresentation()
58    {
59      if (Plotter2D == null)
60        return;
61
62      content.Children.Clear();
63      linePaths.Clear();
64
65      if (Collection != null)
66      {
67        DataRect bounds = DataRect.Empty;
68
69        foreach (var line in Collection.Lines)
70        {
71          foreach (var point in line.AllPoints)
72          {
73            bounds.Union(point);
74          }
75
76          Path path = new Path
77          {
78            Stroke = new SolidColorBrush(Palette.GetColor(line.Value01)),
79            StrokeThickness = StrokeThickness,
80            Data = CreateGeometry(line),
81            Tag = line
82          };
83          content.Children.Add(path);
84          linePaths.Add(path);
85        }
86
87        Viewport2D.SetContentBounds(this, bounds);
88
89        if (DrawLabels)
90        {
91          var transform = Plotter2D.Viewport.Transform;
92          double wayBeforeText = new Rect(new Size(2000, 2000)).ScreenToData(transform).Width;
93          Annotater.WayBeforeText = wayBeforeText;
94          var textLabels = Annotater.Annotate(Collection, Plotter2D.Viewport.Visible);
95
96          foreach (var textLabel in textLabels)
97          {
98            var text = CreateTextLabel(textLabel);
99            content.Children.Add(text);
100            textBlocks.Add(text);
101          }
102        }
103      }
104    }
105
106    private FrameworkElement CreateTextLabel(IsolineTextLabel textLabel)
107    {
108      var transform = Plotter2D.Viewport.Transform;
109      Point screenPos = textLabel.Position.DataToScreen(transform);
110
111      double angle = textLabel.Rotation;
112      if (angle < 0)
113        angle += 360;
114      if (135 < angle && angle < 225)
115        angle -= 180;
116
117      string tooltip = textLabel.Value.ToString("F"); //String.Format("{0} at ({1}, {2})", textLabel.Text, textLabel.Position.X, textLabel.Position.Y);
118      Grid grid = new Grid
119      {
120        RenderTransform = new RotateTransform(angle),
121        Tag = textLabel,
122        RenderTransformOrigin = new Point(0.5, 0.5),
123        ToolTip = tooltip
124      };
125
126      TextBlock res = new TextBlock
127      {
128        Text = textLabel.Value.ToString("F"),
129        Margin = new Thickness(3,1,3,1)
130      };
131
132      //res.Measure(SizeHelper.CreateInfiniteSize());
133
134      Rectangle rect = new Rectangle
135      {
136        Stroke = Brushes.Gray,
137        Fill = labelBackground,
138        RadiusX = 8,
139        RadiusY = 8
140      };
141
142      grid.Children.Add(rect);
143      grid.Children.Add(res);
144
145      grid.Measure(SizeHelper.CreateInfiniteSize());
146
147      Size textSize = grid.DesiredSize;
148      Point position = new Point(screenPos.X - textSize.Width / 2, screenPos.Y - textSize.Height / 2);
149
150      Canvas.SetLeft(grid, position.X);
151      Canvas.SetTop(grid, position.Y);
152      return grid;
153    }
154
155    private Geometry CreateGeometry(LevelLine lineData)
156    {
157      var transform = Plotter2D.Viewport.Transform;
158
159      StreamGeometry geometry = new StreamGeometry();
160      using (var context = geometry.Open())
161      {
162        context.BeginFigure(lineData.StartPoint.DataToScreen(transform), false, false);
163        context.PolyLineTo(lineData.OtherPoints.DataToScreenAsList(transform), true, true);
164      }
165      geometry.Freeze();
166      return geometry;
167    }
168
169    private bool rebuildText = true;
170    protected override void OnViewportPropertyChanged(ExtendedPropertyChangedEventArgs e)
171    {
172      if (e.PropertyName == "Visible" || e.PropertyName == "Output")
173      {
174        bool isVisibleChanged = e.PropertyName == "Visible";
175        DataRect prevRect = isVisibleChanged ? (DataRect)e.OldValue : new DataRect((Rect)e.OldValue);
176        DataRect currRect = isVisibleChanged ? (DataRect)e.NewValue : new DataRect((Rect)e.NewValue);
177
178        // completely rebuild text only if width and height have changed many
179        const double smallChangePercent = 0.05;
180        bool widthChangedLittle = Math.Abs(currRect.Width - prevRect.Width) / currRect.Width < smallChangePercent;
181        bool heightChangedLittle = Math.Abs(currRect.Height - prevRect.Height) / currRect.Height < smallChangePercent;
182
183        rebuildText = !(widthChangedLittle && heightChangedLittle);
184      }
185      UpdateUIRepresentation();
186    }
187
188    private void UpdateUIRepresentation()
189    {
190      if (Plotter2D == null) return;
191
192      foreach (var path in linePaths)
193      {
194        LevelLine line = (LevelLine)path.Tag;
195        path.Data = CreateGeometry(line);
196      }
197
198      var transform = Plotter2D.Viewport.Transform;
199      Rect output = Plotter2D.Viewport.Output;
200      DataRect visible = Plotter2D.Viewport.Visible;
201
202      if (rebuildText && DrawLabels)
203      {
204        rebuildText = false;
205        foreach (var text in textBlocks)
206        {
207          if (text.Visibility == Visibility.Visible)
208            content.Children.Remove(text);
209        }
210        textBlocks.Clear();
211
212        double wayBeforeText = new Rect(new Size(100, 100)).ScreenToData(transform).Width;
213        Annotater.WayBeforeText = wayBeforeText;
214        var textLabels = Annotater.Annotate(Collection, Plotter2D.Viewport.Visible);
215        foreach (var textLabel in textLabels)
216        {
217          var text = CreateTextLabel(textLabel);
218          textBlocks.Add(text);
219          if (visible.Contains(textLabel.Position))
220          {
221            content.Children.Add(text);
222          }
223          else
224          {
225            text.Visibility = Visibility.Hidden;
226          }
227        }
228      }
229      else
230      {
231        foreach (var text in textBlocks)
232        {
233          IsolineTextLabel label = (IsolineTextLabel)text.Tag;
234          Point screenPos = label.Position.DataToScreen(transform);
235          Size textSize = text.DesiredSize;
236
237          Point position = new Point(screenPos.X - textSize.Width / 2, screenPos.Y - textSize.Height / 2);
238
239          if (output.Contains(position))
240          {
241            Canvas.SetLeft(text, position.X);
242            Canvas.SetTop(text, position.Y);
243            if (text.Visibility == Visibility.Hidden)
244            {
245              text.Visibility = Visibility.Visible;
246              content.Children.Add(text);
247            }
248          }
249          else if (text.Visibility == Visibility.Visible)
250          {
251            text.Visibility = Visibility.Hidden;
252            content.Children.Remove(text);
253          }
254        }
255      }
256    }
257  }
258}
Note: See TracBrowser for help on using the repository browser.