Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Problems.GrammaticalOptimization/DynamicDataDisplay/Transforms/DataTransforms.cs @ 13792

Last change on this file since 13792 was 12503, checked in by aballeit, 9 years ago

#2283 added GUI and charts; fixed MCTS

File size: 15.7 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Windows;
5using System.Windows.Media;
6
7namespace Microsoft.Research.DynamicDataDisplay
8{
9  /// <summary>
10  /// Base class for all data transforms.
11  /// Defines methods to transform point from data coordinate system to viewport coordinates and vice versa.
12  /// Derived class should be immutable; to perform any changes a new new instance with different parameters should be created.
13  /// </summary>
14  public abstract class DataTransform
15  {
16    /// <summary>
17    /// Transforms the point in data coordinates to viewport coordinates.
18    /// </summary>
19    /// <param name="pt">The point in data coordinates.</param>
20    /// <returns>Transformed point in viewport coordinates.</returns>
21    public abstract Point DataToViewport(Point pt);
22    /// <summary>
23    /// Transforms the point in viewport coordinates to data coordinates.
24    /// </summary>
25    /// <param name="pt">The point in viewport coordinates.</param>
26    /// <returns>Transformed point in data coordinates.</returns>
27    public abstract Point ViewportToData(Point pt);
28
29    private static readonly DataRect defaultDomain = DataRect.Empty;
30    /// <summary>
31    /// Gets the data domain of this dataTransform.
32    /// </summary>
33    /// <value>The data domain of this dataTransform.</value>
34    public virtual DataRect DataDomain { get { return defaultDomain; } }
35  }
36
37  /// <summary>
38  /// Represents identity data transform, which applies no transformation.
39  /// is by default in CoordinateTransform.
40  /// </summary>
41  public sealed class IdentityTransform : DataTransform
42  {
43    /// <summary>
44    /// Initializes a new instance of the <see cref="IdentityTransform"/> class.
45    /// </summary>
46    public IdentityTransform() { }
47
48    /// <summary>
49    /// Transforms the point in data coordinates to viewport coordinates.
50    /// </summary>
51    /// <param name="pt">The point in data coordinates.</param>
52    /// <returns></returns>
53    public override Point DataToViewport(Point pt)
54    {
55      return pt;
56    }
57
58    /// <summary>
59    /// Transforms the point in viewport coordinates to data coordinates.
60    /// </summary>
61    /// <param name="pt">The point in viewport coordinates.</param>
62    /// <returns></returns>
63    public override Point ViewportToData(Point pt)
64    {
65      return pt;
66    }
67  }
68
69  /// <summary>
70  /// Represents a logarithmic transform of y-values of points.
71  /// </summary>
72  public sealed class Log10YTransform : DataTransform
73  {
74    /// <summary>
75    /// Initializes a new instance of the <see cref="Log10YTransform"/> class.
76    /// </summary>
77    public Log10YTransform() { }
78
79    /// <summary>
80    /// Transforms the point in data coordinates to viewport coordinates.
81    /// </summary>
82    /// <param name="pt">The point in data coordinates.</param>
83    /// <returns></returns>
84    public override Point DataToViewport(Point pt)
85    {
86      double y = pt.Y;
87
88      if (y < 0)
89        y = Double.MinValue;
90      else
91        y = Math.Log10(y);
92
93      return new Point(pt.X, y);
94    }
95
96    /// <summary>
97    /// Transforms the point in viewport coordinates to data coordinates.
98    /// </summary>
99    /// <param name="pt">The point in viewport coordinates.</param>
100    /// <returns></returns>
101    public override Point ViewportToData(Point pt)
102    {
103      return new Point(pt.X, Math.Pow(10, pt.Y));
104    }
105
106    /// <summary>
107    /// Gets the data domain of this dataTransform.
108    /// </summary>
109    /// <value>The data domain of this dataTransform.</value>
110    public override DataRect DataDomain
111    {
112      get { return DataDomains.YPositive; }
113    }
114
115  }
116
117  /// <summary>
118  /// Represents a logarithmic transform of x-values of points.
119  /// </summary>
120  public sealed class Log10XTransform : DataTransform
121  {
122    /// <summary>
123    /// Initializes a new instance of the <see cref="Log10XTransform"/> class.
124    /// </summary>
125    public Log10XTransform() { }
126
127    /// <summary>
128    /// Transforms the point in data coordinates to viewport coordinates.
129    /// </summary>
130    /// <param name="pt">The point in data coordinates.</param>
131    /// <returns></returns>
132    public override Point DataToViewport(Point pt)
133    {
134      double x = pt.X;
135
136      if (x < 0)
137        x = Double.MinValue;
138      else
139        x = Math.Log10(x);
140
141      return new Point(x, pt.Y);
142    }
143
144    /// <summary>
145    /// Transforms the point in viewport coordinates to data coordinates.
146    /// </summary>
147    /// <param name="pt">The point in viewport coordinates.</param>
148    /// <returns></returns>
149    public override Point ViewportToData(Point pt)
150    {
151      return new Point(Math.Pow(10, pt.X), pt.Y);
152    }
153
154    /// <summary>
155    /// Gets the data domain.
156    /// </summary>
157    /// <value>The data domain.</value>
158    public override DataRect DataDomain
159    {
160      get { return DataDomains.XPositive; }
161    }
162  }
163
164  /// <summary>
165  /// Represents a mercator transform, used in maps.
166  /// Transforms y coordinates.
167  /// </summary>
168  public sealed class MercatorTransform : DataTransform
169  {
170    /// <summary>
171    /// Initializes a new instance of the <see cref="MercatorTransform"/> class.
172    /// </summary>
173    public MercatorTransform()
174    {
175      CalcScale(maxLatitude);
176    }
177
178    /// <summary>
179    /// Initializes a new instance of the <see cref="MercatorTransform"/> class.
180    /// </summary>
181    /// <param name="maxLatitude">The maximal latitude.</param>
182    public MercatorTransform(double maxLatitude)
183    {
184      this.maxLatitude = maxLatitude;
185      CalcScale(maxLatitude);
186    }
187
188    private void CalcScale(double maxLatitude)
189    {
190      double maxLatDeg = maxLatitude;
191      double maxLatRad = maxLatDeg * Math.PI / 180;
192      scale = maxLatDeg / Math.Log(Math.Tan(maxLatRad / 2 + Math.PI / 4));
193    }
194
195    private double scale;
196    /// <summary>
197    /// Gets the scale.
198    /// </summary>
199    /// <value>The scale.</value>
200    public double Scale
201    {
202      get { return scale; }
203    }
204
205    private double maxLatitude = 85;
206    /// <summary>
207    /// Gets the maximal latitude.
208    /// </summary>
209    /// <value>The max latitude.</value>
210    public double MaxLatitude
211    {
212      get { return maxLatitude; }
213    }
214
215    /// <summary>
216    /// Transforms the point in data coordinates to viewport coordinates.
217    /// </summary>
218    /// <param name="pt">The point in data coordinates.</param>
219    /// <returns></returns>
220    public sealed override Point DataToViewport(Point pt)
221    {
222      double y = pt.Y;
223      if (-maxLatitude <= y && y <= maxLatitude)
224      {
225        y = scale * Math.Log(Math.Tan(Math.PI * (pt.Y + 90) / 360));
226      }
227
228      return new Point(pt.X, y);
229    }
230
231    /// <summary>
232    /// Transforms the point in viewport coordinates to data coordinates.
233    /// </summary>
234    /// <param name="pt">The point in viewport coordinates.</param>
235    /// <returns></returns>
236    public sealed override Point ViewportToData(Point pt)
237    {
238      double y = pt.Y;
239      if (-maxLatitude <= y && y <= maxLatitude)
240      {
241        double e = Math.Exp(y / scale);
242        y = 360 * Math.Atan(e) / Math.PI - 90;
243      }
244
245      return new Point(pt.X, y);
246    }
247  }
248
249  /// <summary>
250  /// Represents transform from polar coordinate system to rectangular coordinate system.
251  /// </summary>
252  public sealed class PolarToRectTransform : DataTransform
253  {
254    /// <summary>
255    /// Initializes a new instance of the <see cref="PolarToRectTransform"/> class.
256    /// </summary>
257    public PolarToRectTransform() { }
258
259    /// <summary>
260    /// Transforms the point in data coordinates to viewport coordinates.
261    /// </summary>
262    /// <param name="pt">The point in data coordinates.</param>
263    /// <returns></returns>
264    public override Point DataToViewport(Point pt)
265    {
266      double r = pt.X;
267      double phi = pt.Y;
268
269      double x = r * Math.Cos(phi);
270      double y = r * Math.Sin(phi);
271
272      return new Point(x, y);
273    }
274
275    /// <summary>
276    /// Transforms the point in viewport coordinates to data coordinates.
277    /// </summary>
278    /// <param name="pt">The point in viewport coordinates.</param>
279    /// <returns></returns>
280    public override Point ViewportToData(Point pt)
281    {
282      double x = pt.X;
283      double y = pt.Y;
284      double r = Math.Sqrt(x * x + y * y);
285      double phi = Math.Atan2(y, x);
286
287      return new Point(r, phi);
288    }
289  }
290
291  /// <summary>
292  /// Represents a data transform which applies rotation around specified center at specified angle.
293  /// </summary>
294  public sealed class RotateDataTransform : DataTransform
295  {
296    /// <summary>
297    /// Initializes a new instance of the <see cref="RotateDataTransform"/> class.
298    /// </summary>
299    /// <param name="angleInRadians">The angle in radians.</param>
300    public RotateDataTransform(double angleInRadians)
301    {
302      this.center = new Point();
303      this.angle = angleInRadians;
304    }
305
306    /// <summary>
307    /// Initializes a new instance of the <see cref="RotateDataTransform"/> class.
308    /// </summary>
309    /// <param name="angleInRadians">The angle in radians.</param>
310    /// <param name="center">The center of rotation.</param>
311    public RotateDataTransform(double angleInRadians, Point center)
312    {
313      this.center = center;
314      this.angle = angleInRadians;
315    }
316
317    private readonly Point center;
318    /// <summary>
319    /// Gets the center of rotation.
320    /// </summary>
321    /// <value>The center.</value>
322    public Point Center
323    {
324      get { return center; }
325    }
326
327    private readonly double angle;
328    /// <summary>
329    /// Gets the rotation angle.
330    /// </summary>
331    /// <value>The angle.</value>
332    public double Angle
333    {
334      get { return angle; }
335    }
336
337    /// <summary>
338    /// Transforms the point in data coordinates to viewport coordinates.
339    /// </summary>
340    /// <param name="pt">The point in data coordinates.</param>
341    /// <returns></returns>
342    public override Point DataToViewport(Point pt)
343    {
344      return Transform(pt, angle);
345    }
346
347    /// <summary>
348    /// Transforms the point in viewport coordinates to data coordinates.
349    /// </summary>
350    /// <param name="pt">The point in viewport coordinates.</param>
351    /// <returns></returns>
352    public override Point ViewportToData(Point pt)
353    {
354      return Transform(pt, -angle);
355    }
356
357    private Point Transform(Point pt, double angle)
358    {
359      Vector vec = pt - center;
360      double currAngle = Math.Atan2(vec.Y, vec.X);
361      currAngle += angle;
362
363      Vector rotatedVec = new Vector(Math.Cos(currAngle), Math.Sin(currAngle)) * vec.Length;
364
365      return center + rotatedVec;
366    }
367  }
368
369  /// <summary>
370  /// Represents data transform performed by multiplication on given matrix.
371  /// </summary>
372  public sealed class MatrixDataTransform : DataTransform
373  {
374    /// <summary>
375    /// Initializes a new instance of the <see cref="MatrixDataTransform"/> class.
376    /// </summary>
377    /// <param name="matrix">The transform matrix.</param>
378    public MatrixDataTransform(Matrix matrix)
379    {
380      this.matrix = matrix;
381      this.invertedMatrix = matrix;
382      invertedMatrix.Invert();
383    }
384
385    private readonly Matrix matrix;
386    private readonly Matrix invertedMatrix;
387
388    /// <summary>
389    /// Transforms the point in data coordinates to viewport coordinates.
390    /// </summary>
391    /// <param name="pt">The point in data coordinates.</param>
392    /// <returns></returns>
393    public override Point DataToViewport(Point pt)
394    {
395      return matrix.Transform(pt);
396    }
397
398    /// <summary>
399    /// Transforms the point in viewport coordinates to data coordinates.
400    /// </summary>
401    /// <param name="pt">The point in viewport coordinates.</param>
402    /// <returns></returns>
403    public override Point ViewportToData(Point pt)
404    {
405      return invertedMatrix.Transform(pt);
406    }
407  }
408
409  /// <summary>
410  /// Represents a chain of transforms which are being applied consequently.
411  /// </summary>
412  public sealed class CompositeDataTransform : DataTransform
413  {
414    /// <summary>
415    /// Initializes a new instance of the <see cref="CompositeDataTransform"/> class.
416    /// </summary>
417    /// <param name="transforms">The transforms.</param>
418    public CompositeDataTransform(params DataTransform[] transforms)
419    {
420      if (transforms == null)
421        throw new ArgumentNullException("transforms");
422      foreach (var transform in transforms)
423      {
424        if (transform == null)
425          throw new ArgumentNullException("transforms", Strings.Exceptions.EachTransformShouldNotBeNull);
426      }
427
428      this.transforms = transforms;
429    }
430
431    /// <summary>
432    /// Initializes a new instance of the <see cref="CompositeDataTransform"/> class.
433    /// </summary>
434    /// <param name="transforms">The transforms.</param>
435    public CompositeDataTransform(IEnumerable<DataTransform> transforms)
436    {
437      if (transforms == null)
438        throw new ArgumentNullException("transforms");
439
440      this.transforms = transforms;
441    }
442
443    private readonly IEnumerable<DataTransform> transforms;
444    /// <summary>
445    /// Gets the transforms.
446    /// </summary>
447    /// <value>The transforms.</value>
448    public IEnumerable<DataTransform> Transforms
449    {
450      get { return transforms; }
451    }
452
453    /// <summary>
454    /// Transforms the point in data coordinates to viewport coordinates.
455    /// </summary>
456    /// <param name="pt">The point in data coordinates.</param>
457    /// <returns></returns>
458    public override Point DataToViewport(Point pt)
459    {
460      foreach (var transform in transforms)
461      {
462        pt = transform.DataToViewport(pt);
463      }
464
465      return pt;
466    }
467
468    /// <summary>
469    /// Transforms the point in viewport coordinates to data coordinates.
470    /// </summary>
471    /// <param name="pt">The point in viewport coordinates.</param>
472    /// <returns></returns>
473    public override Point ViewportToData(Point pt)
474    {
475      foreach (var transform in transforms.Reverse())
476      {
477        pt = transform.ViewportToData(pt);
478      }
479
480      return pt;
481    }
482  }
483
484  /// <summary>
485  /// Represents a data transform, performed by given lambda function.
486  /// </summary>
487  public sealed class LambdaDataTransform : DataTransform
488  {
489    /// <summary>
490    /// Initializes a new instance of the <see cref="DelegateDataTransform"/> class.
491    /// </summary>
492    /// <param name="dataToViewport">The data to viewport transform delegate.</param>
493    /// <param name="viewportToData">The viewport to data transform delegate.</param>
494    public LambdaDataTransform(Func<Point, Point> dataToViewport, Func<Point, Point> viewportToData)
495    {
496      if (dataToViewport == null)
497        throw new ArgumentNullException("dataToViewport");
498      if (viewportToData == null)
499        throw new ArgumentNullException("viewportToData");
500
501      this.dataToViewport = dataToViewport;
502      this.viewportToData = viewportToData;
503    }
504
505    private readonly Func<Point, Point> dataToViewport;
506    /// <summary>
507    /// Gets the data to viewport transform delegate.
508    /// </summary>
509    /// <value>The data to viewport func.</value>
510    public Func<Point, Point> DataToViewportFunc
511    {
512      get { return dataToViewport; }
513    }
514
515    private readonly Func<Point, Point> viewportToData;
516    /// <summary>
517    /// Gets the viewport to data transform delegate.
518    /// </summary>
519    /// <value>The viewport to data func.</value>
520    public Func<Point, Point> ViewportToDataFunc
521    {
522      get { return viewportToData; }
523    }
524
525    /// <summary>
526    /// Transforms the point in data coordinates to viewport coordinates.
527    /// </summary>
528    /// <param name="pt">The point in data coordinates.</param>
529    /// <returns></returns>
530    public override Point DataToViewport(Point pt)
531    {
532      return dataToViewport(pt);
533    }
534
535    /// <summary>
536    /// Transforms the point in viewport coordinates to data coordinates.
537    /// </summary>
538    /// <param name="pt">The point in viewport coordinates.</param>
539    /// <returns></returns>
540    public override Point ViewportToData(Point pt)
541    {
542      return viewportToData(pt);
543    }
544  }
545
546  /// <summary>
547  /// Contains default data transforms.
548  /// </summary>
549  public static class DataTransforms
550  {
551    private static readonly IdentityTransform identity = new IdentityTransform();
552    /// <summary>
553    /// Gets the default identity data transform.
554    /// </summary>
555    /// <value>The identity data transform.</value>
556    public static IdentityTransform Identity
557    {
558      get
559      {
560        return identity;
561      }
562    }
563  }
564}
Note: See TracBrowser for help on using the repository browser.