Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Problems.GrammaticalOptimization/DynamicDataDisplay/Charts/Isolines/FastIsolineRenderer.cs @ 12747

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

#2283 added GUI and charts; fixed MCTS

File size: 6.5 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5using System.Windows.Media;
6using System.Windows;
7using System.Diagnostics;
8using Microsoft.Research.DynamicDataDisplay.Common.Auxiliary;
9using Microsoft.Research.DynamicDataDisplay.Charts.Shapes;
10using System.Windows.Threading;
11using System.Globalization;
12using Microsoft.Research.DynamicDataDisplay.Charts.NewLine;
13using System.Windows.Data;
14
15namespace Microsoft.Research.DynamicDataDisplay.Charts.Isolines
16{
17  public class FastIsolineRenderer : IsolineRenderer
18  {
19    private List<IsolineCollection> additionalLines = new List<IsolineCollection>();
20    private const int subDivisionNum = 10;
21
22    protected override void CreateUIRepresentation()
23    {
24      InvalidateVisual();
25    }
26
27    protected override void OnPlotterAttached()
28    {
29      base.OnPlotterAttached();
30
31      FrameworkElement parent = (FrameworkElement)Parent;
32      Binding collectionBinding = new Binding("IsolineCollection") { Source = this };
33      parent.SetBinding(IsolineCollectionProperty, collectionBinding);
34    }
35
36    protected override void OnRender(DrawingContext drawingContext)
37    {
38      if (Plotter2D == null) return;
39      if (Collection == null) return;
40      if (DataSource == null) return;
41      if (Collection.Lines.Count == 0)
42      {
43        IsolineBuilder.DataSource = DataSource;
44        IsolineBuilder.MissingValue = MissingValue;
45        Collection = IsolineBuilder.BuildIsoline();
46      }
47
48      IsolineCollection = Collection;
49
50      var dc = drawingContext;
51      var strokeThickness = StrokeThickness;
52      var collection = Collection;
53
54      var bounds = DataRect.Empty;
55      // determining content bounds
56      foreach (LevelLine line in collection)
57      {
58        foreach (Point point in line.AllPoints)
59        {
60          bounds.Union(point);
61        }
62      }
63
64      Viewport2D.SetContentBounds(this, bounds);
65      ViewportPanel.SetViewportBounds(this, bounds);
66
67      if (bounds.IsEmpty) return;
68
69      // custom transform with output set to renderSize of this control
70      var transform = Plotter2D.Transform.WithRects(bounds, new Rect(RenderSize));
71
72      // actual drawing of isolines
73      RenderIsolineCollection(dc, strokeThickness, collection, transform);
74
75      //var additionalLevels = GetAdditionalIsolines(collection);
76
77      //var additionalIsolineCollections = additionalLevels.Select(level => IsolineBuilder.BuildIsoline(level));
78
79      //foreach (var additionalCollection in additionalIsolineCollections)
80      //{
81      //    RenderIsolineCollection(dc, strokeThickness, additionalCollection, transform);
82      //}
83
84      RenderLabels(dc, collection);
85
86      //    foreach (var additionalCollection in additionalIsolineCollections)
87      //    {
88      //        RenderLabels(dc, additionalCollection);
89      //    }
90    }
91
92    private IEnumerable<double> GetAdditionalIsolines(IsolineCollection collection)
93    {
94      var dataSource = DataSource;
95      var visibleMinMax = dataSource.GetMinMax(Plotter2D.Visible);
96      var visibleMinMaxRatio = (collection.Max - collection.Min) / visibleMinMax.GetLength();
97
98      var log = Math.Log10(visibleMinMaxRatio);
99      if (log > 0.9)
100      {
101        var upperLog = Math.Ceiling(log);
102        var divisionsNum = Math.Pow(10, upperLog);
103        var delta = (collection.Max - collection.Min) / divisionsNum;
104
105        var start = Math.Ceiling(visibleMinMax.Min / delta) * delta;
106
107        var x = start;
108        while (x < visibleMinMax.Max)
109        {
110          yield return x;
111          x += delta;
112        }
113      }
114    }
115
116    private void RenderLabels(DrawingContext dc, IsolineCollection collection)
117    {
118      if (Plotter2D == null) return;
119      if (collection == null) return;
120      if (!DrawLabels) return;
121
122      var viewportBounds = ViewportPanel.GetViewportBounds(this);
123      if (viewportBounds.IsEmpty)
124        return;
125
126      var strokeThickness = StrokeThickness;
127      var visible = Plotter2D.Visible;
128      var output = Plotter2D.Viewport.Output;
129
130      var transform = Plotter2D.Transform.WithRects(viewportBounds, new Rect(RenderSize));
131      var labelStringFormat = LabelStringFormat;
132
133      // drawing constants
134      var labelRectangleFill = Brushes.White;
135
136      var biggerViewport = viewportBounds.ZoomOutFromCenter(1.1);
137
138      // getting and filtering annotations to draw only visible ones
139      Annotater.WayBeforeText = Math.Sqrt(visible.Width * visible.Width + visible.Height * visible.Height) / 8 * WayBeforeTextMultiplier;
140      var annotations = Annotater.Annotate(collection, visible)
141      .Where(annotation =>
142      {
143        Point viewportPosition = annotation.Position.DataToViewport(transform);
144        return biggerViewport.Contains(viewportPosition);
145      });
146
147      var labelsScale = LabelsScaling;
148
149      // drawing annotations
150      foreach (var annotation in annotations)
151      {
152        FormattedText text = CreateFormattedText(annotation.Value.ToString(LabelStringFormat));
153        Point position = annotation.Position.DataToScreen(transform);
154
155        var labelTransform = CreateTransform(annotation, text, position);
156
157        // creating rectange stroke
158        double colorRatio = (annotation.Value - collection.Min) / (collection.Max - collection.Min);
159        colorRatio = MathHelper.Clamp(colorRatio);
160        Color rectangleStrokeColor = Palette.GetColor(colorRatio);
161        SolidColorBrush rectangleStroke = new SolidColorBrush(rectangleStrokeColor);
162        Pen labelRectangleStrokePen = new Pen(rectangleStroke, 2);
163
164        dc.PushTransform(new ScaleTransform(1, labelsScale));
165        dc.PushTransform(labelTransform);
166        {
167          var bounds = RectExtensions.FromCenterSize(position, new Size(text.Width, text.Height));
168          bounds = bounds.ZoomOutFromCenter(1.3);
169          dc.DrawRoundedRectangle(labelRectangleFill, labelRectangleStrokePen, bounds, 8, 8);
170
171          DrawTextInPosition(dc, text, position);
172        }
173        dc.Pop();
174        dc.Pop();
175      }
176    }
177
178    private static void DrawTextInPosition(DrawingContext dc, FormattedText text, Point position)
179    {
180      var textPosition = position;
181      textPosition.Offset(-text.Width / 2, -text.Height / 2);
182      dc.DrawText(text, textPosition);
183    }
184
185    private static Transform CreateTransform(IsolineTextLabel isolineLabel, FormattedText text, Point position)
186    {
187      double angle = isolineLabel.Rotation;
188      if (angle < 0)
189        angle += 360;
190      if (90 < angle && angle < 270)
191        angle -= 180;
192
193      RotateTransform transform = new RotateTransform(angle, position.X, position.Y);
194      return transform;
195    }
196
197    private static FormattedText CreateFormattedText(string text)
198    {
199      FormattedText result = new FormattedText(text,
200        CultureInfo.CurrentCulture, System.Windows.FlowDirection.LeftToRight, new Typeface("Arial"), 12, Brushes.Black);
201      return result;
202    }
203  }
204}
Note: See TracBrowser for help on using the repository browser.