#region CPL License /* Nuclex Framework Copyright (C) 2002-2009 Nuclex Development Labs This library is free software; you can redistribute it and/or modify it under the terms of the IBM Common Public License as published by the IBM Corporation; either version 1.0 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the IBM Common Public License for more details. You should have received a copy of the IBM Common Public License along with this library */ #endregion using System; using Microsoft.Xna.Framework; namespace Nuclex.Geometry.Lines { /// Segment of a line (Typical line with starting and ending location) #if !NO_SERIALIZATION [Serializable] #endif public class Segment2 : ILine2 { /// Initializes a new line segment [System.Diagnostics.DebuggerStepThrough] public Segment2() { Start = Vector2.Zero; End = Vector2.Zero; } /// Constructs a new line as copy of an existing instance /// Existing instance to copy [System.Diagnostics.DebuggerStepThrough] public Segment2(Segment2 other) { Start = other.Start; End = other.End; } /// Initializes a new line segment /// Starting location of the line segment /// Ending location of the line segment [System.Diagnostics.DebuggerStepThrough] public Segment2(Vector2 start, Vector2 end) { Start = start; End = end; } /// Locates the nearest point on the line to some arbitrary location /// Location to which the closest point is determined /// The closest point on the line to the specified location public Vector2 ClosestPointTo(Vector2 location) { // If the line's start and end location are identical we would be dividing by // zero further down, so we'll handle this case seperately if(Start == End) return Start; // Calculate the position of an orthogonal vector on the line pointing // towards the location that the caller specified Vector2 direction = Vector2.Normalize(End - Start); float position = Vector2.Dot(location - Start, direction); // Clip the position onto the length of the line segment return Start + direction * Math.Min(Math.Max(position, 0.0f), 1.0f); } /// Checks two segment instances for inequality /// First instance to be compared /// Second instance fo tbe compared /// True if the instances differ or exactly one reference is set to null public static bool operator !=(Segment2 first, Segment2 second) { return !(first == second); } /// Checks two segment instances for equality /// First instance to be compared /// Second instance fo tbe compared /// True if both instances are equal or both references are null public static bool operator ==(Segment2 first, Segment2 second) { if(ReferenceEquals(first, null)) return ReferenceEquals(second, null); return first.Equals(second); } /// Checks whether another instance is equal to this instance /// Other instance to compare to this instance /// True if the other instance is equal to this instance public override bool Equals(object other) { return Equals(other as Segment2); } /// Checks whether another instance is equal to this instance /// Other instance to compare to this instance /// True if the other instance is equal to this instance public virtual bool Equals(Segment2 other) { if(other == null) return false; else return (this.Start == other.Start) && (this.End == other.End); } /// Obtains a hash code of this instance /// The hash code of the instance public override int GetHashCode() { unchecked { return Start.GetHashCode() + End.GetHashCode(); } } /// Locate which side of a line a point is on /// Starting point of a line segment that is interpreted as line /// Ending point of a line segment that is interpreted as line /// Location which is checked for the side it is on /// 1 if it is on the positive side, -1 for negative, 0 for on the line public static Side Orientation(Vector2 start, Vector2 end, Vector2 point) { double determinant = (end.X - start.X) * (point.Y - start.Y) - (point.X - start.X) * (end.Y - start.Y); if(determinant >= 0.0) return Side.Positive; else return Side.Negative; } /// The starting point of the line segment public Vector2 Start; /// The ending point of the line segment public Vector2 End; } } // namespace Nuclex.Geometry.Ranges