#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