#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; using Nuclex.Geometry.Volumes; using Nuclex.Geometry.Areas; namespace Nuclex.Geometry.Lines { /// Line (extending to infinity on both directions) #if !NO_SERIALIZATION [Serializable] #endif public class Line3 : ILine3 { /// Initializes a new line [System.Diagnostics.DebuggerStepThrough] public Line3() { Offset = Vector3.Zero; Direction = Vector3.Right; } /// Constructs a new line as copy of an existing instance /// Existing instance to copy [System.Diagnostics.DebuggerStepThrough] public Line3(Line3 other) { Offset = other.Offset; Direction = other.Direction; } /// Initializes a new line /// Offset of the line from the coordinate system's center /// Vector the defines the direction of the line [System.Diagnostics.DebuggerStepThrough] public Line3(Vector3 offset, Vector3 direction) { Offset = offset; Direction = direction; } /// 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 Vector3 ClosestPointTo(Vector3 location) { Vector3 distance = location - Offset; float ratio = Vector3.Dot(Direction, distance) / Direction.LengthSquared(); return Offset + Direction * ratio; } /// Checks two line 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 !=(Line3 first, Line3 second) { return !(first == second); } /// Checks two line 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 ==(Line3 first, Line3 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 Line3); } /// 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(Line3 other) { if(other == null) return false; else return (this.Offset == other.Offset) && (this.Direction == other.Direction); } /// Obtains a hash code of this instance /// The hash code of the instance public override int GetHashCode() { unchecked { return Offset.GetHashCode() + Direction.GetHashCode(); } } /// Determines where the range clips a sphere /// Sphere that will be checked for intersection /// The times at which the range enters or leaves the volume public LineContacts FindContacts(Sphere3 sphere) { return Collisions.Line3Sphere3Collider.FindContacts( Offset, Direction, sphere.Center, sphere.Radius ); } /// Determines where the range clips an axis aligned box /// Box that will be checked for intersection /// The times at which the range enters or leaves the volume public LineContacts FindContacts(AxisAlignedBox3 box) { return Collisions.Line3Aabb3Collider.FindContacts( Offset - box.Center, Direction, box.Dimensions / 2.0f ); } /// Determines where the range clips a box /// Box that will be checked for intersection /// The times at which the range enters or leaves the volume public LineContacts FindContacts(Box3 box) { // Convert line to box coordinates Vector3 difference = Offset - box.Center; Vector3 relativeCenter = new Vector3( Vector3.Dot(difference, box.Transform.Right), Vector3.Dot(difference, box.Transform.Up), Vector3.Dot(difference, box.Transform.Forward) ); Vector3 relativeDirection = new Vector3( Vector3.Dot(Direction, box.Transform.Right), Vector3.Dot(Direction, box.Transform.Up), Vector3.Dot(Direction, box.Transform.Forward) ); return Collisions.Line3Aabb3Collider.FindContacts( relativeCenter, relativeDirection, box.Dimensions / 2.0f ); } /// Determines where the range clips a triangle /// Triangle that will be checked for intersection /// The times at which the range touches the triangle, if at all public LineContacts FindContacts(Triangle3 triangle) { return Collisions.Line3Triangle3Collider.FindContacts( Offset, Direction, triangle.A, triangle.B, triangle.C ); } /// Determines where the range clips a plane /// Plane that will be checked for intersection /// The times at which the range touches the plane, if at all public LineContacts FindContacts(Plane3 plane) { return Collisions.Line3Plane3Collider.FindContacts( Offset, Direction, plane.Offset, plane.Normal ); } /// Offset of the line from the coordinate system's center public Vector3 Offset; /// Direction into which the line extends public Vector3 Direction; } } // namespace Nuclex.Geometry.Ranges