Jypeli  5
The simple game programming library
Vector.cs
Siirry tämän tiedoston dokumentaatioon.
1 #region MIT License
2 /*
3  * Copyright (c) 2009 University of Jyväskylä, Department of Mathematical
4  * Information Technology.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24 #endregion
25 
26 /*
27  * Authors: Tero Jäntti, Tomi Karppinen, Janne Nikkanen.
28  */
29 
30 using System;
31 using AdvanceMath;
32 using System.Globalization;
33 using System.Collections.Generic;
34 
35 namespace Jypeli
36 {
37  // NOTES:
38  //
39  // TJ: In addition to the types Vector2 from XNA and Vector2D from AdvanceMath, we
40  // have a vector type of our own!
41  //
42  // PROS:
43  // * No need to have "using AdvanceMath" in games, keeps the interface clean and simple.
44  // * Has less methods and properties, again keeping the interface clean and simple.
45  // * Less typing in the name :P
46  //
47  // CONS:
48  // * Does it add overhead in execution? I don't think so, if the compiler is smart at all.
49  // Since the vectors are struct types, their handling should be done entirely in the stack.
50 
51 
55  [Save]
56  public struct Vector
57  {
61  public static readonly Vector Zero = new Vector( 0.0, 0.0 );
62 
66  public static readonly Vector UnitX = new Vector( 1.0, 0.0 );
67 
71  public static readonly Vector UnitY = new Vector( 0.0, 1.0 );
72 
76  public static readonly Vector Diagonal = new Vector( 1.0, 1.0 );
77 
81  public Vector LeftNormal
82  {
83  get { return new Vector( -Y, X ); }
84  }
85 
89  public Vector RightNormal
90  {
91  get { return new Vector( Y, -X ); }
92  }
93 
99  private static Vector FromLengthAndAngle( double length, double angle )
100  {
101  Vector result;
102  result.X = length * Math.Cos( angle );
103  result.Y = length * Math.Sin( angle );
104  return result;
105  }
106 
110  public static Vector FromLengthAndAngle( double length, Angle angle )
111  {
112  return FromLengthAndAngle( length, angle.Radians );
113  }
114 
118  public static Vector FromAngle( Angle angle )
119  {
120  return FromLengthAndAngle( 1, angle.Radians );
121  }
122 
126  public static double Distance( Vector p1, Vector p2 )
127  {
128  double x, y;
129  x = p1.X - p2.X;
130  y = p1.Y - p2.Y;
131  return MathHelper.Sqrt( (float)(x * x + y * y) );
132  }
133 
140  public static double DotProduct( Vector left, Vector right )
141  {
142  return left.Y * right.Y + left.X * right.X;
143  }
144 
153  public static double CrossProduct( Vector left, Vector right )
154  {
155  return left.Magnitude * right.Magnitude * ( right.Angle - left.Angle ).Sin;
156  }
157 
164  public static Vector ComponentProduct( Vector a, Vector b )
165  {
166  return new Vector( a.X * b.X, a.Y * b.Y );
167  }
168 
169  public double ScalarProjection( Vector unitVector )
170  {
171  return ( Vector.DotProduct( this, unitVector ) / unitVector.MagnitudeSquared );
172  }
173 
174  public Vector Project( Vector to )
175  {
176  return ScalarProjection( to ) * to;
177  }
178 
183  public Vector Normalize()
184  {
185  return this / this.Magnitude;
186  }
187 
193  public static Vector Min( params Vector[] vectors )
194  {
195  int minIndex = 0;
196  double minMagnitude = vectors[0].Magnitude;
197 
198  for ( int i = 1; i < vectors.Length; i++ )
199  {
200  double m = vectors[i].Magnitude;
201  if ( m < minMagnitude )
202  {
203  minIndex = i;
204  minMagnitude = m;
205  }
206  }
207 
208  return vectors[minIndex];
209  }
210 
216  public static Vector Max( params Vector[] vectors )
217  {
218  int maxIndex = 0;
219  double maxMagnitude = vectors[0].Magnitude;
220 
221  for ( int i = 1; i < vectors.Length; i++ )
222  {
223  double m = vectors[i].Magnitude;
224  if ( m > maxMagnitude )
225  {
226  maxIndex = i;
227  maxMagnitude = m;
228  }
229  }
230 
231  return vectors[maxIndex];
232  }
233 
239  public static Vector Average( IEnumerable<Vector> vectors )
240  {
241  double sumX = 0;
242  double sumY = 0;
243  int count = 0;
244 
245  foreach ( var v in vectors )
246  {
247  sumX += v.X;
248  sumY += v.Y;
249  count++;
250  }
251 
252  return count > 0 ? new Vector( sumX, sumY ) / count : Vector.Zero;
253  }
254 
260  public static Vector Average( params Vector[] vectors )
261  {
262  double sumX = 0;
263  double sumY = 0;
264 
265  foreach ( var v in vectors )
266  {
267  sumX += v.X;
268  sumY += v.Y;
269  }
270 
271  return vectors.Length > 0 ? new Vector( sumX, sumY ) / vectors.Length : Vector.Zero;
272  }
273 
274  [Save] public double X;
275  [Save] public double Y;
276 
280  public double Magnitude
281  {
282  get { return Math.Sqrt( MagnitudeSquared ); }
283  }
284 
288  public double MagnitudeSquared
289  {
290  get { return X * X + Y * Y; }
291  }
292 
298  public Vector( double X, double Y )
299  {
300  this.X = X;
301  this.Y = Y;
302  }
303 
307  public Angle Angle
308  {
309  get
310  {
311  double a = Math.Atan2( Y, X );
312  if ( a < 0 )
313  a += 2 * Math.PI;
314  return Angle.FromRadians( a );
315  }
316  }
317 
322  public override string ToString()
323  {
324  return ToString( NumberFormatInfo.InvariantInfo );
325  }
326 
327  public string ToString( IFormatProvider formatProvider )
328  {
329  string x = X.ToString( formatProvider );
330  string y = Y.ToString( formatProvider );
331  return string.Format( "({0},{1})", x, y );
332  }
333 
334  public static Vector Parse( string vectorStr )
335  {
336  return Parse( vectorStr, NumberFormatInfo.InvariantInfo );
337  }
338 
339  public static Vector Parse( string vectorStr, IFormatProvider formatProvider )
340  {
341  string[] splitStr = vectorStr.Split( '(', ',', ')' );
342 
343  if ( splitStr.Length != 4 )
344  throw new FormatException( "Not a vector string: " + vectorStr );
345 
346  double x = double.Parse( splitStr[1], formatProvider );
347  double y = double.Parse( splitStr[2], formatProvider );
348 
349  return new Vector( x, y );
350  }
351 
352  public static Vector operator +( Vector left, Vector right )
353  {
354  Vector result;
355  result.X = left.X + right.X;
356  result.Y = left.Y + right.Y;
357  return result;
358  }
359 
360  public static Vector operator -( Vector left, Vector right )
361  {
362  Vector result;
363  result.X = left.X - right.X;
364  result.Y = left.Y - right.Y;
365  return result;
366  }
367 
368  public static Vector operator *( Vector source, double scalar )
369  {
370  Vector result;
371  result.X = source.X * scalar;
372  result.Y = source.Y * scalar;
373  return result;
374  }
375 
376  public static Vector operator *( double scalar, Vector source )
377  {
378  return source * scalar;
379  }
380 
381  public static Vector operator /( Vector source, double scalar )
382  {
383  // TJ: Let's not implement this using operator* in order to
384  // avoid rounding errors.
385  Vector result;
386  result.X = source.X / scalar;
387  result.Y = source.Y / scalar;
388  return result;
389  }
390 
391  public static Vector operator -( Vector source )
392  {
393  Vector result;
394  result.X = -source.X;
395  result.Y = -source.Y;
396  return result;
397  }
398 
399  public override int GetHashCode()
400  {
401  return ObjectHelper.GetHashCode( X.GetHashCode(), Y.GetHashCode() );
402  }
403 
404  public override bool Equals( object obj )
405  {
406  double x, y;
407 
408  if ( obj is Vector )
409  {
410  x = ( (Vector)obj ).X;
411  y = ( (Vector)obj ).Y;
412  }
413  else if ( obj is Vector2D )
414  {
415  x = ( (Vector2D)obj ).X;
416  y = ( (Vector2D)obj ).Y;
417  }
418  else if ( obj is Vector3D )
419  {
420  x = ( (Vector3D)obj ).X;
421  y = ( (Vector3D)obj ).Y;
422  }
423  else if ( obj is Vector4D )
424  {
425  x = ( (Vector4D)obj ).X;
426  y = ( (Vector4D)obj ).Y;
427  }
428  else
429  return false;
430 
431 #if WINDOWS_PHONE
432  // TK: Double.Epsilon is too small for the phone to recognize
433  return ( Math.Abs( this.X - x ) < float.Epsilon ) && ( Math.Abs( this.Y - y ) < float.Epsilon );
434 #else
435  return ( Math.Abs( this.X - x ) < double.Epsilon ) && ( Math.Abs( this.Y - y ) < double.Epsilon );
436 #endif
437  }
438 
439  public static bool operator ==( Vector left, Vector right )
440  {
441 #if WINDOWS_PHONE
442  // TK: Double.Epsilon is too small for the phone to recognize
443  return ( Math.Abs( left.X - right.X ) < float.Epsilon ) && ( Math.Abs( left.Y - right.Y ) < float.Epsilon );
444 #else
445  return ( Math.Abs( left.X - right.X ) < double.Epsilon ) && ( Math.Abs( left.Y - right.Y ) < double.Epsilon );
446 #endif
447  }
448 
449  public static bool operator !=( Vector left, Vector right )
450  {
451  return !( left == right );
452  }
453 
454  public static explicit operator Vector( Vector2D v )
455  {
456  return new Vector( v.X, v.Y );
457  }
458 
459  public static explicit operator Vector2D( Vector v )
460  {
461  return new Vector2D( v.X, v.Y );
462  }
463 
464  public static explicit operator Vector( Microsoft.Xna.Framework.Vector2 v )
465  {
466  return new Vector( v.X, v.Y );
467  }
468 
469  public static explicit operator Microsoft.Xna.Framework.Vector2( Vector v )
470  {
471  return new Microsoft.Xna.Framework.Vector2( (float)v.X, (float)v.Y );
472  }
473 
474  public static implicit operator Vector( Microsoft.Xna.Framework.Vector3 v )
475  {
476  return new Vector( v.X, v.Y );
477  }
478 
479  public static implicit operator Microsoft.Xna.Framework.Vector3( Vector v )
480  {
481  return new Microsoft.Xna.Framework.Vector3( (float)v.X, (float)v.Y, 0 );
482  }
483  }
484 }
static Vector operator/(Vector source, double scalar)
Definition: Vector.cs:381
static readonly Vector UnitX
Vaakasuuntainen yksikkövektori (pituus 1, suunta oikealle).
Definition: Vector.cs:66
double Magnitude
Vektorin pituus.
Definition: Vector.cs:281
static Vector operator+(Vector left, Vector right)
Definition: Vector.cs:352
static Vector FromAngle(Angle angle)
Luo vektorin kulman perusteella yksikköpituudella.
Definition: Vector.cs:118
Angle Angle
Kulma radiaaneina.
Definition: Vector.cs:308
Suuntakulma (rajoitettu -180 ja 180 asteen välille) asteina ja radiaaneina. Tietoja kulmasta: http://...
Definition: Angle.cs:40
static bool operator!=(Vector left, Vector right)
Definition: Vector.cs:449
Apuluokka kaikille olioille
Definition: ObjectHelper.cs:11
static readonly Vector UnitY
Pystysuuntainen yksikkövektori (pituus 1, suunta ylös).
Definition: Vector.cs:71
static bool operator==(Vector left, Vector right)
Definition: Vector.cs:439
override string ToString()
Vektori merkkijonona muodossa (x,y)
Definition: Vector.cs:322
static readonly Vector Zero
Nollavektori.
Definition: Vector.cs:61
static int GetHashCode(params object[] objects)
Palauttaa hajautuskoodin usean olion kokoelmalle.
Definition: ObjectHelper.cs:18
override bool Equals(object obj)
Definition: Vector.cs:404
Vector Project(Vector to)
Definition: Vector.cs:174
static Vector Average(params Vector[] vectors)
Palauttaa kahden tai useamman vektorin keskiarvon.
Definition: Vector.cs:260
static Vector Average(IEnumerable< Vector > vectors)
Palauttaa kahden tai useamman vektorin keskiarvon.
Definition: Vector.cs:239
static Vector Parse(string vectorStr)
Definition: Vector.cs:334
double ScalarProjection(Vector unitVector)
Definition: Vector.cs:169
static Vector Min(params Vector[] vectors)
Palauttaa lyhimmän vektorin.
Definition: Vector.cs:193
static Vector FromLengthAndAngle(double length, Angle angle)
Luo vektorin pituuden ja kulman perusteella.
Definition: Vector.cs:110
static double CrossProduct(Vector left, Vector right)
Ristitulo. Palauttaa kohtisuoraan vektoreita vastaan olevan uuden vektorin pituuden. Tuloksen merkki kertoo kumpaan suuntaan vektori osoittaa.
Definition: Vector.cs:153
double Y
Definition: Vector.cs:275
Vector LeftNormal
Vasen normaali.
Definition: Vector.cs:82
static Angle FromRadians(double radian)
Luo kulman annettujen radiaanien mukaan.
Definition: Angle.cs:316
static double DotProduct(Vector left, Vector right)
Pistetulo.
Definition: Vector.cs:140
double X
Definition: Vector.cs:274
static readonly Vector Diagonal
Diagonaalivektori (1,1)
Definition: Vector.cs:76
double Radians
Palauttaa tai asettaa kulman radiaaneina.
Definition: Angle.cs:86
static Vector Max(params Vector[] vectors)
Palauttaa pisimmän vektorin.
Definition: Vector.cs:216
static double Distance(Vector p1, Vector p2)
Etäisyys kahden pisteen välillä.
Definition: Vector.cs:126
static Vector Parse(string vectorStr, IFormatProvider formatProvider)
Definition: Vector.cs:339
double MagnitudeSquared
Vektorin pituuden neliö.
Definition: Vector.cs:289
string ToString(IFormatProvider formatProvider)
Definition: Vector.cs:327
2D-vektori.
Definition: Vector.cs:56
static Vector operator*(Vector source, double scalar)
Definition: Vector.cs:368
Vector(double X, double Y)
Luo uuden vektorin komponenteista.
Definition: Vector.cs:298
static Vector operator-(Vector left, Vector right)
Definition: Vector.cs:360
Vector Normalize()
Palauttaa uuden vektorin, jonka suunta pysyy samana, mutta pituudeksi tulee 1.0.
Definition: Vector.cs:183
override int GetHashCode()
Definition: Vector.cs:399
Vector RightNormal
Oikea normaali.
Definition: Vector.cs:90
static Vector ComponentProduct(Vector a, Vector b)
Kertoo kaksi vektoria komponenteittain.
Definition: Vector.cs:164