/Utilities/Math/VectorRange.cs
C# | 361 lines | 234 code | 34 blank | 93 comment | 13 complexity | 0c645acea9ab5e364a6e0f75c86bf8ea MD5 | raw file
Possible License(s): Apache-2.0
- using System;
- using System.Diagnostics;
- using System.IO;
- using System.Runtime.InteropServices;
- using Delta.Utilities.Datatypes;
- using Delta.Utilities.Helpers;
- using NUnit.Framework;
-
- namespace Delta.Utilities.Math
- {
- /// <summary>
- /// The VectorRange object is used to store one or two vectors, which
- /// result in a 3D range.
- /// </summary>
- [StructLayout(LayoutKind.Sequential)]
- [DebuggerDisplay("VectorRange(Start={Start}, End={End})")]
- public struct VectorRange : ISaveLoadBinary
- {
- #region Constants
- /// <summary>
- /// Zero range, will always return 0.
- /// </summary>
- public static readonly VectorRange Zero = new VectorRange(Vector.Zero);
-
- /// <summary>
- /// One range, will always return 1.
- /// </summary>
- public static readonly VectorRange One = new VectorRange(Vector.One);
-
- /// <summary>
- /// Zero to One range, will return a random values between 0 and 1.
- /// </summary>
- public static readonly VectorRange ZeroToOne =
- new VectorRange(Vector.Zero, Vector.One);
- #endregion
-
- #region Start (Public)
- /// <summary>
- /// Start value of the range.
- /// </summary>
- public Vector Start
- {
- get
- {
- return internalStart;
- }
- set
- {
- if (internalStart != value)
- {
- internalStart = value;
- Difference = End - Start;
- }
- }
- }
- #endregion
-
- #region End (Public)
- /// <summary>
- /// End value of the range.
- /// </summary>
- public Vector End
- {
- get
- {
- return internalEnd;
- }
- set
- {
- if (internalEnd != value)
- {
- internalEnd = value;
- Difference = End - Start;
- }
- }
- }
- #endregion
-
- #region Difference (Public)
- /// <summary>
- /// Difference between Start and End.
- /// </summary>
- public Vector Difference
- {
- get;
- private set;
- }
- #endregion
-
- #region RandomValue (Public)
- /// <summary>
- /// Returns a random value between Start and End.
- /// </summary>
- /// <returns>Float</returns>
- public Vector RandomValue
- {
- get
- {
- // Note: We do not need to randomize if start is the same value as end
- if (Start == End)
- {
- return Start;
- }
-
- return new Vector(RandomHelper.RandomFloat(Start.X, End.X),
- RandomHelper.RandomFloat(Start.Y, End.Y),
- RandomHelper.RandomFloat(Start.Z, End.Z));
- }
- }
- #endregion
-
- #region Private
-
- #region internalStart (Private)
- private Vector internalStart;
- #endregion
-
- #region internalEnd (Private)
- private Vector internalEnd;
- #endregion
-
- #endregion
-
- #region Constructors
- /// <summary>
- /// Create range with fixed value.
- /// </summary>
- /// <param name="setStartAndEndValue">Set start and end value</param>
- public VectorRange(Vector setStartAndEndValue)
- : this()
- {
- Start = setStartAndEndValue;
- End = setStartAndEndValue;
- }
-
- /// <summary>
- /// Create range with given minimum and maximum values.
- /// </summary>
- /// <param name="setStartValue">Set start value</param>
- /// <param name="setEndValue">Set end value</param>
- public VectorRange(Vector setStartValue, Vector setEndValue)
- : this()
- {
- Start = setStartValue;
- End = setEndValue;
- }
- #endregion
-
- #region ISaveLoadBinary Members
- /// <summary>
- /// Loads VectorRange from a stream (just Start and End).
- /// </summary>
- /// <param name="reader">The stream that will be used.</param>
- public void Load(BinaryReader reader)
- {
- Start.Load(reader);
- End.Load(reader);
- }
-
- /// <summary>
- /// Saves VectorRange to a stream (just Start and End).
- /// </summary>
- /// <param name="writer">The stream that will be used.</param>
- public void Save(BinaryWriter writer)
- {
- Start.Save(writer);
- End.Save(writer);
- }
- #endregion
-
- #region op_Implicit (Operator)
- /// <summary>
- /// Operator to assign a vector range from vector value.
- /// </summary>
- public static implicit operator VectorRange(Vector value)
- {
- return new VectorRange(value);
- }
- #endregion
-
- #region op_Equality (Operator)
- /// <summary>
- /// Operator to check for equality
- /// </summary>
- /// <param name="a">First value of the comparison.</param>
- /// <param name="b">Second value of the comparison.</param>
- public static bool operator ==(VectorRange a, VectorRange b)
- {
- return b.Start == a.Start &&
- b.End == a.End;
- }
- #endregion
-
- #region op_Inequality (Operator)
- /// <summary>
- /// Operator to check for inequality
- /// </summary>
- /// <param name="a">First value of the comparison.</param>
- /// <param name="b">Second value of the comparison.</param>
- public static bool operator !=(VectorRange a, VectorRange b)
- {
- return b.Start != a.Start ||
- b.End != a.End;
- }
- #endregion
-
- #region GetValue (Public)
- /// <summary>
- /// Get value
- /// </summary>
- /// <param name="percentageFactor">Percentage (in the range of [0,1]) to
- /// get the value based of the set Start and End. E.g. a factor of "0.5"
- /// will return "3" for a range of [2,4].</param>
- public Vector GetValue(float percentageFactor)
- {
- return Start + (Difference * percentageFactor);
- }
- #endregion
-
- #region GetHashCode (Public)
- /// <summary>
- /// GetHashCode
- /// </summary>
- public override int GetHashCode()
- {
- return Start.GetHashCode() ^ End.GetHashCode();
- }
- #endregion
-
- #region Equals (Public)
- /// <summary>
- /// Equals
- /// </summary>
- /// <param name="obj">Object</param>
- public override bool Equals(object obj)
- {
- return (obj is VectorRange)
- ? this == (VectorRange)obj
- : base.Equals(obj);
- }
- #endregion
-
- #region ToString (Public)
- /// <summary>
- /// To string
- /// </summary>
- public override string ToString()
- {
- return "Vector(Start=" + Start + ", End=" + End + ")";
- }
- #endregion
-
- /// <summary>
- /// Tests
- /// </summary>
- internal class VectorRangeTests
- {
- #region TestConstructor
- /// <summary>
- /// Test constructor
- /// </summary>
- [Test]
- public void TestConstructor()
- {
- VectorRange testRange = new VectorRange(
- new Vector(10, 5, 4),
- new Vector(1, 6, 3));
- Assert.Equal(testRange.Start.X, 10);
- Assert.Equal(testRange.Start.Y, 5);
- Assert.Equal(testRange.Start.Z, 4);
- Assert.Equal(testRange.End.X, 1);
- Assert.Equal(testRange.End.Y, 6);
- Assert.Equal(testRange.End.Z, 3);
-
- testRange = new VectorRange(new Vector(10, 5, 4));
- Assert.Equal(testRange.Start.X, 10);
- Assert.Equal(testRange.Start.Y, 5);
- Assert.Equal(testRange.Start.Z, 4);
- Assert.Equal(testRange.End.X, 10);
- Assert.Equal(testRange.End.Y, 5);
- Assert.Equal(testRange.End.Z, 4);
- }
- #endregion
-
- #region TestNegativeRanges
- /// <summary>
- /// Test negative ranges
- /// </summary>
- [Test]
- public void TestNegativeRanges()
- {
- Vector start = new Vector(-10f, -20f, -5f);
- Vector end = new Vector(10f, 20f, 5f);
- VectorRange negativeRange = new VectorRange(start, end);
-
- Assert.Equal(negativeRange.GetValue(0.0f), start);
- Assert.Equal(negativeRange.GetValue(0.5f), new Vector(0f, 0f, 0f));
- Assert.Equal(negativeRange.GetValue(1.0f), end);
-
- Vector randomValue = negativeRange.RandomValue;
- Assert.Between(randomValue.X, start.X, end.X);
- Assert.Between(randomValue.Y, start.Y, end.Y);
- Assert.Between(randomValue.Z, start.Z, end.Z);
- }
- #endregion
-
- #region TestRanges
- /// <summary>
- /// Test different ranges
- /// </summary>
- [Test]
- public void TestRanges()
- {
- // Min and Max value both are assigned the given value
- VectorRange singleRange = new VectorRange(new Vector(2, 5, 4));
- Assert.True(singleRange.Start == singleRange.End);
- Assert.Equal(new Vector(2, 5, 4), singleRange.Start);
-
- // Test the implicit conversion from vector
- singleRange = new Vector(4.3f, 1.2f, 4f);
- Assert.Equal(singleRange, new VectorRange(new Vector(4.3f, 1.2f, 4f)));
- }
- #endregion
-
- #region GetValue
- /// <summary>
- /// Get value
- /// </summary>
- [Test]
- public void GetValue()
- {
- VectorRange range = new VectorRange(
- new Vector(10, 5, 12), Vector.Zero);
-
- Assert.Equal(range.GetValue(0f), new Vector(10, 5, 12));
- Assert.Equal(range.GetValue(0.5f), new Vector(5f, 2.5f, 6f));
- Assert.Equal(range.GetValue(1f), new Vector(0, 0, 0));
- }
- #endregion
-
- #region GetValueLogging
- /// <summary>
- /// Get value logging test
- /// </summary>
- [Test]
- public void GetValueLogging()
- {
- Vector start = new Vector(-10f, -20f, -5f);
- Vector end = new Vector(10f, 20f, 5f);
- VectorRange negativeRange = new VectorRange(start, end);
-
- for (float pos = 0.0f; pos <= 1.01f; pos += 0.1f)
- {
- Console.WriteLine(pos.ToString("0.0") + " > " +
- negativeRange.GetValue(pos));
- }
- }
- #endregion
- }
- }
- }