From 4e957167ed4753101141f2c65a4624c864bfbd61 Mon Sep 17 00:00:00 2001 From: Tiberiu Chibici Date: Fri, 29 May 2015 10:47:32 +0300 Subject: [PATCH] Implemented vector2, rectangle, line segment. --- Game/Assets/Scripts/Model/LineSegment.cs | 100 ++++++++ Game/Assets/Scripts/Model/LineSegment.cs.meta | 12 + Game/Assets/Scripts/Model/Rectangle.cs | 77 ++++++ Game/Assets/Scripts/Model/Rectangle.cs.meta | 12 + Game/Assets/Scripts/Model/Vector2.cs | 230 ++++++++++++++++++ .../Model/{Point.cs.meta => Vector2.cs.meta} | 0 6 files changed, 431 insertions(+) create mode 100644 Game/Assets/Scripts/Model/LineSegment.cs create mode 100644 Game/Assets/Scripts/Model/LineSegment.cs.meta create mode 100644 Game/Assets/Scripts/Model/Rectangle.cs create mode 100644 Game/Assets/Scripts/Model/Rectangle.cs.meta create mode 100644 Game/Assets/Scripts/Model/Vector2.cs rename Game/Assets/Scripts/Model/{Point.cs.meta => Vector2.cs.meta} (100%) diff --git a/Game/Assets/Scripts/Model/LineSegment.cs b/Game/Assets/Scripts/Model/LineSegment.cs new file mode 100644 index 0000000..65d2606 --- /dev/null +++ b/Game/Assets/Scripts/Model/LineSegment.cs @@ -0,0 +1,100 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace TransportGame.Model +{ + public struct LineSegment + { + public float X0 { get; private set; } + public float Y0 { get; private set; } + public float X1 { get; private set; } + public float Y1 { get; private set; } + + public Vector2 P0 + { + get + { + return new Vector2(X0, Y0); + } + } + public Vector2 P1 + { + get + { + return new Vector2(X1, Y1); + } + } + + public float Length + { + get + { + return (P1 - P0).Length; + } + } + + public float LengthSq + { + get + { + return (P1 - P0).LengthSq; + } + } + + public LineSegment(Vector2 p0, Vector2 p1) + : this() + { + X0 = p0.X; Y0 = p0.Y; + X1 = p1.X; Y1 = p1.Y; + } + + public LineSegment(float x0, float y0, float x1, float y1) + : this() + { + X0 = x0; Y0 = y0; + X1 = x1; Y1 = y1; + } + + public static Vector2? Intersect(LineSegment a, LineSegment b) + { + float s1x = a.X1 - a.X0, s1y = a.Y1 - a.Y0; + float s2x = b.X1 - b.X0, s2y = b.Y1 - b.Y0; + + float det = (-s2x * s1y + s1x * s2y); + + // Avoid division by zero + // Note: this is an edge case, the vectors might be parallel or colliniar + if (det == 0) return null; + + float s = (-s1y * (a.X0 - b.X0) + s1x * (a.Y0 - b.Y0)) / det; + float t = (s2x * (a.Y0 - b.Y0) - s2y * (a.X0 - b.X0)) / det; + + // Collision detected + if (s >= 0 && s <= 1 && t >= 0 && t <= 1) + return new Vector2(a.X0 + t * s1x, a.Y0 + t * s1y); + + // No collision + return null; + } + + /// + /// Calculates the distance from point p to line segment + /// + /// Line + /// Point + /// Distance + public static float Distance(LineSegment line, Vector2 p) + { + float det = (line.Y1 - line.Y0) * p.X - (line.X1 - line.X0) * p.Y + + line.X1 * line.Y0 - line.Y1 * line.X0; + return Math.Abs(det) / line.Length; + } + + public override string ToString() + { + return string.Format("({0}, {1})->({2}, {3})", X0, Y0, X1, Y1); + } + } +} diff --git a/Game/Assets/Scripts/Model/LineSegment.cs.meta b/Game/Assets/Scripts/Model/LineSegment.cs.meta new file mode 100644 index 0000000..a68ae4b --- /dev/null +++ b/Game/Assets/Scripts/Model/LineSegment.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: eaabdeeb068e1dc46a7a9da6fd47f393 +timeCreated: 1432847695 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Game/Assets/Scripts/Model/Rectangle.cs b/Game/Assets/Scripts/Model/Rectangle.cs new file mode 100644 index 0000000..ecbf0f3 --- /dev/null +++ b/Game/Assets/Scripts/Model/Rectangle.cs @@ -0,0 +1,77 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace TransportGame.Model +{ + public struct Rectangle + { + public float Left { get; set; } + public float Top { get; set; } + public float Right { get; set; } + public float Bottom { get; set; } + + public Rectangle(float left, float top, float right, float bottom) + : this() + { + Left = left; + Top = top; + Right = right; + Bottom = bottom; + + if (left > right) + throw new ArgumentException("Left must be smaller than right."); + + if (top > bottom) + throw new ArgumentException("Top must be smaller than bottom."); + } + + public float Width + { + get + { + return Right - Left; + } + set + { + Right = Left + value; + } + } + + public float Height + { + get + { + return Bottom - Top; + } + set + { + Bottom = Top + value; + } + } + + public bool Contains(float x, float y) + { + return x >= Left && x <= Right && y >= Top && y <= Bottom; + } + + public bool Contains(Vector2 p) + { + return Contains(p.X, p.Y); + } + + public static bool Intersects (Rectangle a, Rectangle b) + { + return !(b.Left > a.Right || + b.Right < a.Left || + b.Top > a.Bottom || + b.Bottom < a.Top); + } + + public override string ToString() + { + return string.Format("({0}, {1}, {2}, {3})", Left, Top, Right, Bottom); + } + } +} diff --git a/Game/Assets/Scripts/Model/Rectangle.cs.meta b/Game/Assets/Scripts/Model/Rectangle.cs.meta new file mode 100644 index 0000000..bae31f6 --- /dev/null +++ b/Game/Assets/Scripts/Model/Rectangle.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 01c02a9fd2c3d0142905c23fb3142b6f +timeCreated: 1432824087 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Game/Assets/Scripts/Model/Vector2.cs b/Game/Assets/Scripts/Model/Vector2.cs new file mode 100644 index 0000000..710319c --- /dev/null +++ b/Game/Assets/Scripts/Model/Vector2.cs @@ -0,0 +1,230 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using UnityEngine; + +namespace TransportGame.Model +{ + public struct Vector2 + { + /// + /// Zero vector + /// + public static readonly Vector2 Zero = new Vector2(0, 0); + + /// + /// Unit vector + /// + public static readonly Vector2 Unit = new Vector2(1, 0); + + /// + /// Gets the X component + /// + public float X { get; private set; } + + /// + /// Gets the Y component + /// + public float Y { get; private set; } + + /// + /// Initializes a vector2 + /// + /// X component + /// Y component + public Vector2(float x, float y) + : this() + { + X = x; + Y = y; + } + + /// + /// Gets the length of the vector + /// + public float Length + { + get + { + return (float)Math.Sqrt(LengthSq); + } + } + + /// + /// Gets the length of the vector squared + /// + public float LengthSq + { + get + { + return X * X + Y * Y; + } + } + + /// + /// Gets the normalized vector + /// + /// Normalized vector + public Vector2 Normalized + { + get + { + float len = Length; + return new Vector2(X / len, Y / len); + } + } + + /// + /// Rotates vector by given number of radians + /// + /// + /// + public Vector2 Rotate(float radians) + { + float sin = (float)Math.Sin(radians); + float cos = (float)Math.Cos(radians); + + return new Vector2(X * cos - Y * sin, X * sin + Y * cos); + } + + /// + /// Rotates vector by given number of degrees + /// + /// + /// + public Vector2 RotateDeg(float degrees) + { + return Rotate(degrees * (float)Math.PI / 180f); + } + + /// + /// Sum operator + /// + /// First vector + /// Second vector + /// Result of addition + public static Vector2 operator +(Vector2 a, Vector2 b) + { + return new Vector2(a.X + b.X, a.Y + b.Y); + } + + /// + /// Subtract operator + /// + /// First vector + /// Second vector + /// Result of subtraction + public static Vector2 operator -(Vector2 a, Vector2 b) + { + return new Vector2(a.X - b.X, a.Y - b.Y); + } + + /// + /// Multiply by constant + /// + /// Vector + /// Constant + /// Result + public static Vector2 operator *(Vector2 a, float c) + { + return new Vector2(a.X * c, a.Y * c); + } + + /// + /// Multiply by constant + /// + /// Constant + /// Vector + /// Result + public static Vector2 operator *(float c, Vector2 a) + { + return new Vector2(a.X * c, a.Y * c); + } + + /// + /// Divide by constant + /// + /// Vector + /// Constant + /// Result + public static Vector2 operator /(Vector2 a, float c) + { + return new Vector2(a.X / c, a.Y / c); + } + + /// + /// Equality operator + /// + /// First vector + /// Second vector + /// True if vectors are equal + public static bool operator ==(Vector2 a, Vector2 b) + { + return a.X == b.X && a.Y == b.Y; + } + /// + /// Inequality operator + /// + /// First vector + /// Second vector + /// True if vectors are not equal + public static bool operator !=(Vector2 a, Vector2 b) + { + return a.X != b.X || a.Y != b.Y; + } + + /// + /// Calculates dot product of two vectors + /// + /// First vector + /// Second vector + /// Dot product + public static float Dot(Vector2 a, Vector2 b) + { + return a.X * b.X + a.Y * b.Y; + } + + /// + /// Gets the vector corresponding with specified angle (in radians) + /// + /// Radians + /// Vector + public static Vector2 FromRadians(float rads) + { + return new Vector2((float)Math.Cos(rads), (float)Math.Sin(rads)); + } + + /// + /// Gets the vector corresponding with specified angle (in degrees) + /// + /// Degrees + /// Vector + public static Vector2 FromDegrees(float degs) + { + float rads = (degs * (float)Math.PI / 180f); + return FromRadians(rads); + } + + public override string ToString() + { + return String.Format("({0}, {1})", X, Y); + } + + public override bool Equals(object obj) + { + if (obj is Vector2) + { + Vector2 other = (Vector2)obj; + return X == other.X && Y == other.Y; + } + + return false; + } + + public override int GetHashCode() + { + return X.GetHashCode() * 7 + Y.GetHashCode(); + } + } +} diff --git a/Game/Assets/Scripts/Model/Point.cs.meta b/Game/Assets/Scripts/Model/Vector2.cs.meta similarity index 100% rename from Game/Assets/Scripts/Model/Point.cs.meta rename to Game/Assets/Scripts/Model/Vector2.cs.meta