using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using Microsoft.Research.DynamicDataDisplay.Common;
using System.Diagnostics;
using System.Windows.Media;
namespace Microsoft.Research.DynamicDataDisplay
{
///
/// A central class in 2d coordinate transformation in DynamicDataDisplay.
/// Provides methods to transform point from one coordinate system to another.
/// Should be immutable.
///
public sealed class CoordinateTransform
{
private CoordinateTransform(DataRect visibleRect, Rect screenRect)
{
this.visibleRect = visibleRect;
this.screenRect = screenRect;
rxToScreen = screenRect.Width / visibleRect.Width;
ryToScreen = screenRect.Height / visibleRect.Height;
cxToScreen = visibleRect.XMin * rxToScreen - screenRect.Left;
cyToScreen = screenRect.Height + screenRect.Top + visibleRect.YMin * ryToScreen;
rxToData = visibleRect.Width / screenRect.Width;
ryToData = visibleRect.Height / screenRect.Height;
cxToData = screenRect.Left * rxToData - visibleRect.XMin;
cyToData = visibleRect.Height + visibleRect.YMin + screenRect.Top * ryToData;
}
#region Coeffs
double rxToScreen;
double ryToScreen;
double cxToScreen;
double cyToScreen;
double rxToData;
double ryToData;
double cxToData;
double cyToData;
#endregion
#region Creation methods
///
/// Creates CoordinateTransform fro specified rectangles and with Identity transform.
///
/// The visible rect.
/// The screen rect.
///
public static CoordinateTransform FromRects(DataRect visibleRect, Rect screenRect)
{
CoordinateTransform result = new CoordinateTransform(visibleRect, screenRect);
return result;
}
///
/// Closnes transform with current dataTransform and specified rectangles.
///
/// The visible rect.
/// The screen rect.
///
public CoordinateTransform WithRects(DataRect visibleRect, Rect screenRect)
{
CoordinateTransform copy = new CoordinateTransform(visibleRect, screenRect);
copy.dataTransform = dataTransform;
return copy;
}
///
/// Creates a new instance of CoordinateTransform with the given data transform.
///
/// The data transform.
///
public CoordinateTransform WithDataTransform(DataTransform dataTransform)
{
if (dataTransform == null)
throw new ArgumentNullException("dataTransform");
CoordinateTransform copy = new CoordinateTransform(visibleRect, screenRect);
copy.dataTransform = dataTransform;
return copy;
}
internal CoordinateTransform WithScreenOffset(double x, double y)
{
Rect screenCopy = screenRect;
screenCopy.Offset(x, y);
CoordinateTransform copy = new CoordinateTransform(visibleRect, screenCopy);
return copy;
}
internal static CoordinateTransform CreateDefault()
{
CoordinateTransform transform = new CoordinateTransform(new Rect(0, 0, 1, 1), new Rect(0, 0, 1, 1));
return transform;
}
#endregion
#region Transform methods
///
/// Transforms point from data coordinates to screen.
///
/// The point in data coordinates.
///
public Point DataToScreen(Point dataPoint)
{
Point viewportPoint = dataTransform.DataToViewport(dataPoint);
Point screenPoint = new Point(viewportPoint.X * rxToScreen - cxToScreen,
cyToScreen - viewportPoint.Y * ryToScreen);
return screenPoint;
}
///
/// Transforms point from screen coordinates to data coordinates.
///
/// The point in screen coordinates.
///
public Point ScreenToData(Point screenPoint)
{
Point viewportPoint = new Point(screenPoint.X * rxToData - cxToData,
cyToData - screenPoint.Y * ryToData);
Point dataPoint = dataTransform.ViewportToData(viewportPoint);
return dataPoint;
}
///
/// Transforms point from viewport coordinates to screen coordinates.
///
/// The point in viewport coordinates.
///
public Point ViewportToScreen(Point viewportPoint)
{
Point screenPoint = new Point(viewportPoint.X * rxToScreen - cxToScreen,
cyToScreen - viewportPoint.Y * ryToScreen);
return screenPoint;
}
///
/// Transforms point from screen coordinates to viewport coordinates.
///
/// The point in screen coordinates.
///
public Point ScreenToViewport(Point screenPoint)
{
Point viewportPoint = new Point(screenPoint.X * rxToData - cxToData,
cyToData - screenPoint.Y * ryToData);
return viewportPoint;
}
#endregion
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private DataRect visibleRect;
///
/// Gets the viewport rectangle.
///
/// The viewport rect.
public DataRect ViewportRect
{
get { return visibleRect; }
}
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private Rect screenRect;
///
/// Gets the screen rectangle.
///
/// The screen rect.
public Rect ScreenRect
{
get { return screenRect; }
}
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private DataTransform dataTransform = DataTransforms.Identity;
///
/// Gets the data transform.
///
/// The data transform.
public DataTransform DataTransform
{
get { return dataTransform; }
}
}
}