1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
8 //
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
11 //
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19 //
20 // Copyright (c) 2007 Novell, Inc. (http://www.novell.com)
21 //
22 // Authors:
23 //	Chris Toshok (toshok@novell.com)
24 //
25 
26 using System.ComponentModel;
27 using System.Globalization;
28 using System.Windows.Converters;
29 using System.Windows.Markup;
30 using System.Windows.Media;
31 
32 namespace System.Windows {
33 
34 	[Serializable]
35 	[ValueSerializer (typeof (VectorValueSerializer))]
36 	[TypeConverter (typeof (VectorConverter))]
37 	public struct Vector : IFormattable
38 	{
VectorSystem.Windows.Vector39 		public Vector (double x, double y)
40 		{
41 			this._x = x;
42 			this._y = y;
43 		}
44 
EqualsSystem.Windows.Vector45 		public bool Equals (Vector value)
46 		{
47 			return _x == value.X && _y == value.Y;
48 		}
49 
EqualsSystem.Windows.Vector50 		public override bool Equals (object o)
51 		{
52 			if (!(o is Vector))
53 				return false;
54 
55 			return Equals ((Vector)o);
56 		}
57 
GetHashCodeSystem.Windows.Vector58 		public override int GetHashCode ()
59 		{
60 			unchecked
61 			{
62 				return (_x.GetHashCode () * 397) ^ _y.GetHashCode ();
63 			}
64 		}
65 
EqualsSystem.Windows.Vector66 		public static bool Equals (Vector vector1, Vector vector2)
67 		{
68 			return vector1.Equals (vector2);
69 		}
70 
AddSystem.Windows.Vector71 		public static Point Add (Vector vector, Point point)
72 		{
73 			return new Point (vector.X + point.X, vector.Y + point.Y);
74 		}
75 
AddSystem.Windows.Vector76 		public static Vector Add (Vector vector1, Vector vector2)
77 		{
78 			return new Vector (vector1.X + vector2.X,
79 					   vector1.Y + vector2.Y);
80 		}
81 
AngleBetweenSystem.Windows.Vector82 		public static double AngleBetween (Vector vector1, Vector vector2)
83 		{
84 			double cos_theta = (vector1.X * vector2.X + vector1.Y * vector2.Y) / (vector1.Length * vector2.Length);
85 
86 			return Math.Acos (cos_theta) / Math.PI * 180;
87 		}
88 
CrossProductSystem.Windows.Vector89 		public static double CrossProduct (Vector vector1, Vector vector2)
90 		{
91 			// ... what operation is this exactly?
92 			return vector1.X * vector2.Y - vector1.Y * vector2.X;
93 		}
94 
DeterminantSystem.Windows.Vector95 		public static double Determinant (Vector vector1, Vector vector2)
96 		{
97 			// same as CrossProduct, it appears.
98 			return vector1.X * vector2.Y - vector1.Y * vector2.X;
99 		}
100 
DivideSystem.Windows.Vector101 		public static Vector Divide (Vector vector, double scalar)
102 		{
103 			return new Vector (vector.X / scalar, vector.Y / scalar);
104 		}
105 
MultiplySystem.Windows.Vector106 		public static double Multiply (Vector vector1, Vector vector2)
107 		{
108 			return vector1.X * vector2.X + vector1.Y * vector2.Y;
109 		}
110 
MultiplySystem.Windows.Vector111 		public static Vector Multiply (Vector vector, Matrix matrix)
112 		{
113 			return new Vector (vector.X * matrix.M11 + vector.Y * matrix.M21,
114 					   vector.X * matrix.M12 + vector.Y * matrix.M22);
115 		}
116 
MultiplySystem.Windows.Vector117 		public static Vector Multiply (double scalar, Vector vector)
118 		{
119 			return new Vector (scalar * vector.X, scalar * vector.Y);
120 		}
121 
MultiplySystem.Windows.Vector122 		public static Vector Multiply (Vector vector, double scalar)
123 		{
124 			return new Vector (scalar * vector.X, scalar * vector.Y);
125 		}
126 
NegateSystem.Windows.Vector127 		public void Negate ()
128 		{
129 			_x = -_x;
130 			_y = -_y;
131 		}
132 
NormalizeSystem.Windows.Vector133 		public void Normalize ()
134 		{
135 			double ls = LengthSquared;
136 			if (ls == 1)
137 				return;
138 
139 			double l = Math.Sqrt (ls);
140 			_x /= l;
141 			_y /= l;
142 		}
143 
SubtractSystem.Windows.Vector144 		public static Vector Subtract (Vector vector1, Vector vector2)
145 		{
146 			return new Vector (vector1.X - vector2.X, vector1.Y - vector2.Y);
147 		}
148 
ParseSystem.Windows.Vector149 		public static Vector Parse (string source)
150 		{
151 			if (source == null)
152 				throw new ArgumentNullException ("source");
153 			var tokenizer = new NumericListTokenizer (source, CultureInfo.InvariantCulture);
154 			double x;
155 			double y;
156 			if (!double.TryParse (tokenizer.GetNextToken (), NumberStyles.Float, CultureInfo.InvariantCulture, out x) ||
157 			    !double.TryParse (tokenizer.GetNextToken (), NumberStyles.Float, CultureInfo.InvariantCulture, out y))
158 			{
159 				throw new FormatException (string.Format ("Invalid Vector format: {0}", source));
160 			}
161 			if (!tokenizer.HasNoMoreTokens ())
162 			{
163 				throw new InvalidOperationException("Invalid Vector format: " + source);
164 			}
165 			return new Vector(x, y);
166 		}
167 
ToStringSystem.Windows.Vector168 		public override string ToString ()
169 		{
170 			return ToString(null);
171 		}
172 
ToStringSystem.Windows.Vector173 		public string ToString (IFormatProvider provider)
174 		{
175 			return ToString (null, provider);
176 		}
177 
IFormattable.ToStringSystem.Windows.Vector178 		string IFormattable.ToString (string format, IFormatProvider provider)
179 		{
180 			return ToString (format, provider);
181 		}
182 
ToStringSystem.Windows.Vector183 		private string ToString(string format,IFormatProvider formatProvider)
184 		{
185 			if (formatProvider == null)
186 				formatProvider = CultureInfo.CurrentCulture;
187 			if (format == null)
188 				format = string.Empty;
189 			var separator = NumericListTokenizer.GetSeparator (formatProvider);
190 			var vectorFormat  = string.Format ("{{0:{0}}}{1}{{1:{0}}}", format, separator);
191 			return string.Format (formatProvider, vectorFormat, _x, _y);
192 		}
193 
194 		public double Length {
195 			get { return Math.Sqrt (LengthSquared); }
196 		}
197 
198 		public double LengthSquared {
199 			get { return _x * _x + _y * _y; }
200 		}
201 
202 		public double X {
203 			get { return _x; }
204 			set { _x = value; }
205 		}
206 
207 		public double Y {
208 			get { return _y; }
209 			set { _y = value; }
210 		}
211 
212 		/* operators */
operator PointSystem.Windows.Vector213 		public static explicit operator Point (Vector vector)
214 		{
215 			return new Point (vector.X, vector.Y);
216 		}
217 
operator SizeSystem.Windows.Vector218 		public static explicit operator Size (Vector vector)
219 		{
220 			return new Size (vector.X, vector.Y);
221 		}
222 
operator -System.Windows.Vector223 		public static Vector operator - (Vector vector1, Vector vector2)
224 		{
225 			return Subtract (vector1, vector2);
226 		}
227 
operator -System.Windows.Vector228 		public static Vector operator - (Vector vector)
229 		{
230 			Vector result = vector;
231 			result.Negate ();
232 			return result;
233 		}
234 
operator !=System.Windows.Vector235 		public static bool operator != (Vector vector1, Vector vector2)
236 		{
237 			return !Equals (vector1, vector2);
238 		}
239 
operator ==System.Windows.Vector240 		public static bool operator == (Vector vector1, Vector vector2)
241 		{
242 			return Equals (vector1, vector2);
243 		}
244 
operator *System.Windows.Vector245 		public static double operator * (Vector vector1, Vector vector2)
246 		{
247 			return Multiply (vector1, vector2);
248 		}
249 
operator *System.Windows.Vector250 		public static Vector operator * (Vector vector, Matrix matrix)
251 		{
252 			return Multiply (vector, matrix);
253 		}
254 
operator *System.Windows.Vector255 		public static Vector operator * (double scalar, Vector vector)
256 		{
257 			return Multiply (scalar, vector);
258 		}
259 
operator *System.Windows.Vector260 		public static Vector operator * (Vector vector, double scalar)
261 		{
262 			return Multiply (vector, scalar);
263 		}
264 
operator /System.Windows.Vector265 		public static Vector operator / (Vector vector, double scalar)
266 		{
267 			return Divide (vector, scalar);
268 		}
269 
operator +System.Windows.Vector270 		public static Point operator + (Vector vector, Point point)
271 		{
272 			return Add (vector, point);
273 		}
274 
operator +System.Windows.Vector275 		public static Vector operator + (Vector vector1, Vector vector2)
276 		{
277 			return Add (vector1, vector2);
278 		}
279 
280 		double _x;
281 		double _y;
282 	}
283 
284 }
285