1 /*
2  * NPlot - A charting library for .NET
3  *
4  * Transform2D.cs
5  * Copyright (C) 2003-2006 Matt Howlett and others.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without modification,
9  * are permitted provided that the following conditions are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright notice, this
12  *    list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright notice,
14  *    this list of conditions and the following disclaimer in the documentation
15  *    and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
21  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
22  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
26  * OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 using System.Drawing;
30 
31 namespace NPlot
32 {
33     /// <summary>
34     /// Encapsulates functionality for transforming world to physical coordinates optimally.
35     /// </summary>
36     /// <remarks>The existence of the whole ITransform2D thing might need revising. Not convinced it's the best way.</remarks>
37     public class Transform2D
38     {
39         /// <summary>
40         /// Constructs the optimal ITransform2D object for the supplied x and y axes.
41         /// </summary>
42         /// <param name="xAxis">The xAxis to use for the world to physical transform.</param>
43         /// <param name="yAxis">The yAxis to use for the world to physical transform.</param>
44         /// <returns>An ITransform2D derived object for converting from world to physical coordinates.</returns>
GetTransformer(PhysicalAxis xAxis, PhysicalAxis yAxis)45         public static ITransform2D GetTransformer(PhysicalAxis xAxis, PhysicalAxis yAxis)
46         {
47             ITransform2D ret = null;
48 
49 //			if (xAxis.Axis.IsLinear && yAxis.Axis.IsLinear && !xAxis.Axis.Reversed && !yAxis.Axis.Reversed)
50 //				ret = new FastTransform2D( xAxis, yAxis );
51 //			else
52 //				ret = new DefaultTransform2D( xAxis, yAxis );
53 
54             ret = new DefaultTransform2D(xAxis, yAxis);
55 
56             return ret;
57         }
58 
59         /// <summary>
60         /// This class does world -> physical transforms for the general case
61         /// </summary>
62         public class DefaultTransform2D : ITransform2D
63         {
64             private readonly PhysicalAxis xAxis_;
65             private readonly PhysicalAxis yAxis_;
66 
67             /// <summary>
68             /// Constructor
69             /// </summary>
70             /// <param name="xAxis">The x-axis to use for transforms</param>
71             /// <param name="yAxis">The y-axis to use for transforms</param>
DefaultTransform2D(PhysicalAxis xAxis, PhysicalAxis yAxis)72             public DefaultTransform2D(PhysicalAxis xAxis, PhysicalAxis yAxis)
73             {
74                 xAxis_ = xAxis;
75                 yAxis_ = yAxis;
76             }
77 
78             /// <summary>
79             /// Transforms the given world point to physical coordinates
80             /// </summary>
81             /// <param name="x">x coordinate of world point to transform.</param>
82             /// <param name="y">y coordinate of world point to transform.</param>
83             /// <returns>the corresponding physical point.</returns>
Transform(double x, double y)84             public PointF Transform(double x, double y)
85             {
86                 return new PointF(
87                     xAxis_.WorldToPhysical(x, false).X,
88                     yAxis_.WorldToPhysical(y, false).Y);
89             }
90 
91             /// <summary>
92             /// Transforms the given world point to physical coordinates
93             /// </summary>
94             /// <param name="worldPoint">the world point to transform</param>
95             /// <returns>the corresponding physical point</returns>
Transform(PointD worldPoint)96             public PointF Transform(PointD worldPoint)
97             {
98                 return new PointF(
99                     xAxis_.WorldToPhysical(worldPoint.X, false).X,
100                     yAxis_.WorldToPhysical(worldPoint.Y, false).Y);
101             }
102         }
103 
104         /// <summary>
105         /// This class does highly efficient world->physical and physical->world transforms
106         /// for linear axes.
107         /// </summary>
108         public class FastTransform2D : ITransform2D
109         {
110             private readonly PageAlignedPhysicalAxis xAxis_;
111             private readonly PageAlignedPhysicalAxis yAxis_;
112 
113             /// <summary>
114             /// Constructor
115             /// </summary>
116             /// <param name="xAxis">The x-axis to use for transforms</param>
117             /// <param name="yAxis">The y-axis to use for transforms</param>
FastTransform2D(PhysicalAxis xAxis, PhysicalAxis yAxis)118             public FastTransform2D(PhysicalAxis xAxis, PhysicalAxis yAxis)
119             {
120                 xAxis_ = new PageAlignedPhysicalAxis(xAxis);
121                 yAxis_ = new PageAlignedPhysicalAxis(yAxis);
122             }
123 
124             /// <summary>
125             /// Transforms the given world point to physical coordinates
126             /// </summary>
127             /// <param name="x">x coordinate of world point to transform.</param>
128             /// <param name="y">y coordinate of world point to transform.</param>
129             /// <returns>the corresponding physical point.</returns>
Transform(double x, double y)130             public PointF Transform(double x, double y)
131             {
132                 return new PointF(
133                     xAxis_.WorldToPhysicalClipped(x),
134                     yAxis_.WorldToPhysicalClipped(y));
135             }
136 
137             /// <summary>
138             /// Transforms the given world point to physical coordinates
139             /// </summary>
140             /// <param name="worldPoint">the world point to transform</param>
141             /// <returns>the corresponding physical point</returns>
Transform(PointD worldPoint)142             public PointF Transform(PointD worldPoint)
143             {
144                 return new PointF(
145                     xAxis_.WorldToPhysical(worldPoint.X),
146                     yAxis_.WorldToPhysical(worldPoint.Y));
147             }
148         }
149     }
150 }