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 Vector2 Direction
{
get
{
return (P1 - P0).Normalized;
}
}
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);
}
}
}