corrade-vassal – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 vero 1 /*
2 * Copyright (c) 2006-2014, openmetaverse.org
3 * All rights reserved.
4 *
5 * - Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * - Redistributions of source code must retain the above copyright notice, this
9 * list of conditions and the following disclaimer.
10 * - Neither the name of the openmetaverse.org nor the names
11 * of its contributors may be used to endorse or promote products derived from
12 * this software without specific prior written permission.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
18 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 * POSSIBILITY OF SUCH DAMAGE.
25 */
26  
27 using System;
28 using System.Runtime.InteropServices;
29 using System.Globalization;
30  
31 namespace OpenMetaverse
32 {
33 /// <summary>
34 /// A two-dimensional vector with floating-point values
35 /// </summary>
36 [Serializable]
37 [StructLayout(LayoutKind.Sequential)]
38 public struct Vector2 : IComparable<Vector2>, IEquatable<Vector2>
39 {
40 /// <summary>X value</summary>
41 public float X;
42 /// <summary>Y value</summary>
43 public float Y;
44  
45 #region Constructors
46  
47 public Vector2(float x, float y)
48 {
49 X = x;
50 Y = y;
51 }
52  
53 public Vector2(float value)
54 {
55 X = value;
56 Y = value;
57 }
58  
59 public Vector2(Vector2 vector)
60 {
61 X = vector.X;
62 Y = vector.Y;
63 }
64  
65 #endregion Constructors
66  
67 #region Public Methods
68  
69 /// <summary>
70 /// Test if this vector is equal to another vector, within a given
71 /// tolerance range
72 /// </summary>
73 /// <param name="vec">Vector to test against</param>
74 /// <param name="tolerance">The acceptable magnitude of difference
75 /// between the two vectors</param>
76 /// <returns>True if the magnitude of difference between the two vectors
77 /// is less than the given tolerance, otherwise false</returns>
78 public bool ApproxEquals(Vector2 vec, float tolerance)
79 {
80 Vector2 diff = this - vec;
81 return (diff.LengthSquared() <= tolerance * tolerance);
82 }
83  
84 /// <summary>
85 /// Test if this vector is composed of all finite numbers
86 /// </summary>
87 public bool IsFinite()
88 {
89 return Utils.IsFinite(X) && Utils.IsFinite(Y);
90 }
91  
92 /// <summary>
93 /// IComparable.CompareTo implementation
94 /// </summary>
95 public int CompareTo(Vector2 vector)
96 {
97 return Length().CompareTo(vector.Length());
98 }
99  
100 /// <summary>
101 /// Builds a vector from a byte array
102 /// </summary>
103 /// <param name="byteArray">Byte array containing two four-byte floats</param>
104 /// <param name="pos">Beginning position in the byte array</param>
105 public void FromBytes(byte[] byteArray, int pos)
106 {
107 if (!BitConverter.IsLittleEndian)
108 {
109 // Big endian architecture
110 byte[] conversionBuffer = new byte[8];
111  
112 Buffer.BlockCopy(byteArray, pos, conversionBuffer, 0, 8);
113  
114 Array.Reverse(conversionBuffer, 0, 4);
115 Array.Reverse(conversionBuffer, 4, 4);
116  
117 X = BitConverter.ToSingle(conversionBuffer, 0);
118 Y = BitConverter.ToSingle(conversionBuffer, 4);
119 }
120 else
121 {
122 // Little endian architecture
123 X = BitConverter.ToSingle(byteArray, pos);
124 Y = BitConverter.ToSingle(byteArray, pos + 4);
125 }
126 }
127  
128 /// <summary>
129 /// Returns the raw bytes for this vector
130 /// </summary>
131 /// <returns>An eight-byte array containing X and Y</returns>
132 public byte[] GetBytes()
133 {
134 byte[] byteArray = new byte[8];
135 ToBytes(byteArray, 0);
136 return byteArray;
137 }
138  
139 /// <summary>
140 /// Writes the raw bytes for this vector to a byte array
141 /// </summary>
142 /// <param name="dest">Destination byte array</param>
143 /// <param name="pos">Position in the destination array to start
144 /// writing. Must be at least 8 bytes before the end of the array</param>
145 public void ToBytes(byte[] dest, int pos)
146 {
147 Buffer.BlockCopy(BitConverter.GetBytes(X), 0, dest, pos + 0, 4);
148 Buffer.BlockCopy(BitConverter.GetBytes(Y), 0, dest, pos + 4, 4);
149  
150 if (!BitConverter.IsLittleEndian)
151 {
152 Array.Reverse(dest, pos + 0, 4);
153 Array.Reverse(dest, pos + 4, 4);
154 }
155 }
156  
157 public float Length()
158 {
159 return (float)Math.Sqrt(DistanceSquared(this, Zero));
160 }
161  
162 public float LengthSquared()
163 {
164 return DistanceSquared(this, Zero);
165 }
166  
167 public void Normalize()
168 {
169 this = Normalize(this);
170 }
171  
172 #endregion Public Methods
173  
174 #region Static Methods
175  
176 public static Vector2 Add(Vector2 value1, Vector2 value2)
177 {
178 value1.X += value2.X;
179 value1.Y += value2.Y;
180 return value1;
181 }
182  
183 public static Vector2 Clamp(Vector2 value1, Vector2 min, Vector2 max)
184 {
185 return new Vector2(
186 Utils.Clamp(value1.X, min.X, max.X),
187 Utils.Clamp(value1.Y, min.Y, max.Y));
188 }
189  
190 public static float Distance(Vector2 value1, Vector2 value2)
191 {
192 return (float)Math.Sqrt(DistanceSquared(value1, value2));
193 }
194  
195 public static float DistanceSquared(Vector2 value1, Vector2 value2)
196 {
197 return
198 (value1.X - value2.X) * (value1.X - value2.X) +
199 (value1.Y - value2.Y) * (value1.Y - value2.Y);
200 }
201  
202 public static Vector2 Divide(Vector2 value1, Vector2 value2)
203 {
204 value1.X /= value2.X;
205 value1.Y /= value2.Y;
206 return value1;
207 }
208  
209 public static Vector2 Divide(Vector2 value1, float divider)
210 {
211 float factor = 1 / divider;
212 value1.X *= factor;
213 value1.Y *= factor;
214 return value1;
215 }
216  
217 public static float Dot(Vector2 value1, Vector2 value2)
218 {
219 return value1.X * value2.X + value1.Y * value2.Y;
220 }
221  
222 public static Vector2 Lerp(Vector2 value1, Vector2 value2, float amount)
223 {
224 return new Vector2(
225 Utils.Lerp(value1.X, value2.X, amount),
226 Utils.Lerp(value1.Y, value2.Y, amount));
227 }
228  
229 public static Vector2 Max(Vector2 value1, Vector2 value2)
230 {
231 return new Vector2(
232 Math.Max(value1.X, value2.X),
233 Math.Max(value1.Y, value2.Y));
234 }
235  
236 public static Vector2 Min(Vector2 value1, Vector2 value2)
237 {
238 return new Vector2(
239 Math.Min(value1.X, value2.X),
240 Math.Min(value1.Y, value2.Y));
241 }
242  
243 public static Vector2 Multiply(Vector2 value1, Vector2 value2)
244 {
245 value1.X *= value2.X;
246 value1.Y *= value2.Y;
247 return value1;
248 }
249  
250 public static Vector2 Multiply(Vector2 value1, float scaleFactor)
251 {
252 value1.X *= scaleFactor;
253 value1.Y *= scaleFactor;
254 return value1;
255 }
256  
257 public static Vector2 Negate(Vector2 value)
258 {
259 value.X = -value.X;
260 value.Y = -value.Y;
261 return value;
262 }
263  
264 public static Vector2 Normalize(Vector2 value)
265 {
266 const float MAG_THRESHOLD = 0.0000001f;
267 float factor = DistanceSquared(value, Zero);
268 if (factor > MAG_THRESHOLD)
269 {
270 factor = 1f / (float)Math.Sqrt(factor);
271 value.X *= factor;
272 value.Y *= factor;
273 }
274 else
275 {
276 value.X = 0f;
277 value.Y = 0f;
278 }
279 return value;
280 }
281  
282 /// <summary>
283 /// Parse a vector from a string
284 /// </summary>
285 /// <param name="val">A string representation of a 2D vector, enclosed
286 /// in arrow brackets and separated by commas</param>
287 public static Vector3 Parse(string val)
288 {
289 char[] splitChar = { ',' };
290 string[] split = val.Replace("<", String.Empty).Replace(">", String.Empty).Split(splitChar);
291 return new Vector3(
292 float.Parse(split[0].Trim(), Utils.EnUsCulture),
293 float.Parse(split[1].Trim(), Utils.EnUsCulture),
294 float.Parse(split[2].Trim(), Utils.EnUsCulture));
295 }
296  
297 public static bool TryParse(string val, out Vector3 result)
298 {
299 try
300 {
301 result = Parse(val);
302 return true;
303 }
304 catch (Exception)
305 {
306 result = Vector3.Zero;
307 return false;
308 }
309 }
310  
311 /// <summary>
312 /// Interpolates between two vectors using a cubic equation
313 /// </summary>
314 public static Vector2 SmoothStep(Vector2 value1, Vector2 value2, float amount)
315 {
316 return new Vector2(
317 Utils.SmoothStep(value1.X, value2.X, amount),
318 Utils.SmoothStep(value1.Y, value2.Y, amount));
319 }
320  
321 public static Vector2 Subtract(Vector2 value1, Vector2 value2)
322 {
323 value1.X -= value2.X;
324 value1.Y -= value2.Y;
325 return value1;
326 }
327  
328 public static Vector2 Transform(Vector2 position, Matrix4 matrix)
329 {
330 position.X = (position.X * matrix.M11) + (position.Y * matrix.M21) + matrix.M41;
331 position.Y = (position.X * matrix.M12) + (position.Y * matrix.M22) + matrix.M42;
332 return position;
333 }
334  
335 public static Vector2 TransformNormal(Vector2 position, Matrix4 matrix)
336 {
337 position.X = (position.X * matrix.M11) + (position.Y * matrix.M21);
338 position.Y = (position.X * matrix.M12) + (position.Y * matrix.M22);
339 return position;
340 }
341  
342 #endregion Static Methods
343  
344 #region Overrides
345  
346 public override bool Equals(object obj)
347 {
348 return (obj is Vector2) ? this == ((Vector2)obj) : false;
349 }
350  
351 public bool Equals(Vector2 other)
352 {
353 return this == other;
354 }
355  
356 public override int GetHashCode()
357 {
358 int hash = X.GetHashCode();
359 hash = hash * 31 + Y.GetHashCode();
360 return hash;
361 }
362  
363 /// <summary>
364 /// Get a formatted string representation of the vector
365 /// </summary>
366 /// <returns>A string representation of the vector</returns>
367 public override string ToString()
368 {
369 return String.Format(Utils.EnUsCulture, "<{0}, {1}>", X, Y);
370 }
371  
372 /// <summary>
373 /// Get a string representation of the vector elements with up to three
374 /// decimal digits and separated by spaces only
375 /// </summary>
376 /// <returns>Raw string representation of the vector</returns>
377 public string ToRawString()
378 {
379 CultureInfo enUs = new CultureInfo("en-us");
380 enUs.NumberFormat.NumberDecimalDigits = 3;
381  
382 return String.Format(enUs, "{0} {1}", X, Y);
383 }
384  
385 #endregion Overrides
386  
387 #region Operators
388  
389 public static bool operator ==(Vector2 value1, Vector2 value2)
390 {
391 return value1.X == value2.X && value1.Y == value2.Y;
392 }
393  
394 public static bool operator !=(Vector2 value1, Vector2 value2)
395 {
396 return value1.X != value2.X || value1.Y != value2.Y;
397 }
398  
399 public static Vector2 operator +(Vector2 value1, Vector2 value2)
400 {
401 value1.X += value2.X;
402 value1.Y += value2.Y;
403 return value1;
404 }
405  
406 public static Vector2 operator -(Vector2 value)
407 {
408 value.X = -value.X;
409 value.Y = -value.Y;
410 return value;
411 }
412  
413 public static Vector2 operator -(Vector2 value1, Vector2 value2)
414 {
415 value1.X -= value2.X;
416 value1.Y -= value2.Y;
417 return value1;
418 }
419  
420 public static Vector2 operator *(Vector2 value1, Vector2 value2)
421 {
422 value1.X *= value2.X;
423 value1.Y *= value2.Y;
424 return value1;
425 }
426  
427  
428 public static Vector2 operator *(Vector2 value, float scaleFactor)
429 {
430 value.X *= scaleFactor;
431 value.Y *= scaleFactor;
432 return value;
433 }
434  
435 public static Vector2 operator /(Vector2 value1, Vector2 value2)
436 {
437 value1.X /= value2.X;
438 value1.Y /= value2.Y;
439 return value1;
440 }
441  
442  
443 public static Vector2 operator /(Vector2 value1, float divider)
444 {
445 float factor = 1 / divider;
446 value1.X *= factor;
447 value1.Y *= factor;
448 return value1;
449 }
450  
451 #endregion Operators
452  
453 /// <summary>A vector with a value of 0,0</summary>
454 public readonly static Vector2 Zero = new Vector2();
455 /// <summary>A vector with a value of 1,1</summary>
456 public readonly static Vector2 One = new Vector2(1f, 1f);
457 /// <summary>A vector with a value of 1,0</summary>
458 public readonly static Vector2 UnitX = new Vector2(1f, 0f);
459 /// <summary>A vector with a value of 0,1</summary>
460 public readonly static Vector2 UnitY = new Vector2(0f, 1f);
461 }
462 }