Click here to Skip to main content
15,885,032 members
Articles / Programming Languages / C#

Sharp3D.Math - A 3D math library for .NET

Rate me:
Please Sign up or sign in to vote.
4.30/5 (32 votes)
9 Jun 20041 min read 223.3K   6.6K   79  
A 3D math library written in C#
#region Sharp3D.Math, Copyright(C) 2003-2004 Eran Kampf, Licensed under LGPL.
//	Sharp3D.Math math library
//	Copyright (C) 2003-2004  
//	Eran Kampf
//	tentacle@zahav.net.il
//	http://tentacle.flipcode.com
//
//	This library is free software; you can redistribute it and/or
//	modify it under the terms of the GNU Lesser General Public
//	License as published by the Free Software Foundation; either
//	version 2.1 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 GNU
//	Lesser General Public License for more details.
//
//	You should have received a copy of the GNU Lesser General Public
//	License along with this library; if not, write to the Free Software
//	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#endregion
using System;
using System.Diagnostics;
using System.Runtime.Serialization;
using System.Security.Permissions;

using Sharp3D.Math.Core;

namespace Sharp3D.Math.Geometry3D
{
	/// <summary>
	/// Represents a plane in 3D space.
	/// </summary>
	/// <remarks>
	/// The plane is described by a normal and a constant (N,D) which 
	/// denotes that the plane is consisting of points Q that
	/// satisfies (N dot Q)+D = 0.
	/// </remarks>
	[Serializable]
	public struct Plane : ISerializable, ICloneable
	{
		#region Private Fields
		private Vector3F _normal;
		private float _const;
		#endregion

		#region Constructors
		/// <summary>
		/// Initializes a new instance of the <see cref="Plane"/> class using given normal and constant values.
		/// </summary>
		/// <param name="normal">The plane's normal vector.</param>
		/// <param name="constant">The plane's constant value.</param>
		public Plane(Vector3F normal, float constant)
		{
			_normal	= normal;
			_const	= constant;
		}

		/// <summary>
		/// Initializes a new instance of the <see cref="Plane"/> class using given normal and a point.
		/// </summary>
		/// <param name="normal">The plane's normal vector.</param>
		/// <param name="point">A point on the plane in 3D space.</param>
		public Plane(Vector3F normal, Vector3F point)
		{
			_normal = normal;
			_const	= Vector3F.DotProduct(normal, point);
		}

		/// <summary>
		/// Initializes a new instance of the <see cref="Plane"/> class using 3 given points.
		/// </summary>
		/// <param name="p0">A point on the plane in 3D space.</param>
		/// <param name="p1">A point on the plane in 3D space.</param>
		/// <param name="p2">A point on the plane in 3D space.</param>
		public Plane(Vector3F p0, Vector3F p1, Vector3F p2)
		{
			_normal = Vector3F.CrossProduct(p2-p1, p0-p1);
			_normal.Normalize();
			_const	= Vector3F.DotProduct(_normal, p0);
		}

		/// <summary>
		/// Initializes a new instance of the <see cref="Plane"/> class using given a plane to assign values from.
		/// </summary>
		/// <param name="p">A 3D plane to assign values from.</param>
		public Plane(Plane p)
		{
			_normal	= p.Normal;
			_const	= p.Constant;
		}

		/// <summary>
		/// Initializes a new instance of the <see cref="Plane"/> class with serialized data.
		/// </summary>
		/// <param name="info">The object that holds the serialized object data.</param>
		/// <param name="context">The contextual information about the source or destination.</param>
		private Plane(SerializationInfo info, StreamingContext context)
		{
			_normal = (Vector3F)info.GetValue("Normal", typeof(Vector3F));
			_const	= info.GetSingle("Constant");
		}
		#endregion

		#region Constants
		/// <summary>
		/// Plane on the X axis.
		/// </summary>
		public static readonly Plane XPlane = new Plane(Vector3F.XAxis, Vector3F.Zero);
		/// <summary>
		/// Plane on the Y axis.
		/// </summary>
		public static readonly Plane YPlane = new Plane(Vector3F.YAxis, Vector3F.Zero);
		/// <summary>
		/// Plane on the Z axis.
		/// </summary>
		public static readonly Plane ZPlane = new Plane(Vector3F.ZAxis, Vector3F.Zero);
		#endregion

		#region Public Properties
		/// <summary>
		/// Gets or sets the plane's normal vector.
		/// </summary>
		public Vector3F Normal
		{
			get { return _normal; }
			set { _normal = value;}
		}
		/// <summary>
		/// Gets or sets the plane's constant value.
		/// </summary>
		public float Constant
		{
			get { return _const; }
			set { _const = value;}
		}
		#endregion

		#region ICloneable Members
		/// <summary>
		/// Creates an exact copy of this <see cref="Plane"/> object.
		/// </summary>
		/// <returns>The <see cref="Plane"/> object this method creates, cast as an object.</returns>
		object ICloneable.Clone()
		{
			return new Plane(this);
		}
		/// <summary>
		/// Creates an exact copy of this <see cref="Plane"/> object.
		/// </summary>
		/// <returns>The <see cref="Plane"/> object this method creates.</returns>
		public Plane Clone()
		{
			return new Plane(this);
		}
		#endregion
	
		#region ISerializable Members
		/// <summary>
		/// Populates a <see cref="SerializationInfo"/> with the data needed to serialize the target object.
		/// </summary>
		/// <param name="info">The <see cref="SerializationInfo"/> to populate with data. </param>
		/// <param name="context">The destination (see <see cref="StreamingContext"/>) for this serialization.</param>
		[SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter=true)]
		public void GetObjectData(SerializationInfo info, StreamingContext context)
		{
			info.AddValue("Normal", _normal, typeof(Vector3F));
			info.AddValue("Constant", _const);
		}
		#endregion

		#region Public Methods
		/// <summary>
		/// Flip the plane.
		/// </summary>
		public void Flip()
		{
			_normal = -_normal;
		}
		/// <summary>
		/// Creates a new flipped plane (-normal, constant).
		/// </summary>
		/// <returns>A new <see cref="Plane"/> instance.</returns>
		public Plane GetFlipped()
		{
			return new Plane(-_normal, _const);
		}
		/// <summary>
		/// Returns the points's position relative to the plane itself (i.e Front/Back/On)
		/// </summary>
		/// <param name="p">A point in 3D space.</param>
		/// <returns>A <see cref="MathFunctions.Sign"/>.</returns>
		public MathFunctions.Sign GetSign(Vector3F p) 
		{
			return MathFunctions.GetSign( GetDistanceToPlane( p ) );
		}
		/// <summary>
		/// Get the shortest distance from a 3D vector to the plane.
		/// </summary>
		/// <param name="p">A <see cref="Vector3F"/> instance.</param>
		/// <returns>A float representing the shortest distance from the given vector to the plane.</returns>
		public float GetDistanceToPlane(Vector3F p) 
		{
			return Vector3F.DotProduct( p, this.Normal ) - this.Constant; 
		}
		/// <summary>
		/// Determine whether the line connecting P0 to P1 intersects the plane.
		/// </summary>
		/// <param name="p0">A <see cref="Vector3F"/> instance.</param>
		/// <param name="p1">A <see cref="Vector3F"/> instance.</param>
		/// <returns>True if the line intersects the plane; otherwise, False.</returns>
		public bool IsIntersection(Vector3F p0, Vector3F p1) 
		{
			int sign0 = (int) MathFunctions.GetSign( GetDistanceToPlane( p0 ) );
			int sign1 = (int) MathFunctions.GetSign( GetDistanceToPlane( p1 ) );
			
			return ( sign0 < 0 && sign1 > 0 ) || ( sign0 > 0 && sign1 <= 0 );
		}

		/// <summary>
		/// Determine the exact location where a given line intersects the plane
		/// </summary>
		/// <param name="p0">A <see cref="Vector3F"/> instance.</param>
		/// <param name="p1">A <see cref="Vector3F"/> instance.</param>
		/// <returns>A <see cref="Vector3F"/> instance containing the intersection location.</returns>
		public Vector3F GetIntersection(Vector3F p0, Vector3F p1) 
		{
			Debug.Assert( IsIntersection( p0, p1 ) == true );

			Vector3F Direction = p1 - p0;
			float denominator = Vector3F.DotProduct( Normal, Direction );
			if( denominator == 0 ) 
			{
				throw new DivideByZeroException( "Can not get the intersection of a plane with a line when they are parallel to each other." );
			}
			float t = ( Constant - Vector3F.DotProduct( Normal, p0 ) ) / denominator;
			return	p0 + Direction * t;
		}
		#endregion

		#region Overrides
		/// <summary>
		/// Returns the hashcode for this instance.
		/// </summary>
		/// <returns>A 32-bit signed integer hash code.</returns>
		public override int GetHashCode()
		{
			return _normal.GetHashCode() ^ _const.GetHashCode();
		}
		/// <summary>
		/// Returns a value indicating whether this instance is equal to
		/// the specified object.
		/// </summary>
		/// <param name="obj">An object to compare to this instance.</param>
		/// <returns>True if <paramref name="obj"/> is a <see cref="Vector2D"/> and has the same values as this instance; otherwise, False.</returns>
		public override bool Equals(object obj)
		{
			if(obj is Plane) 
			{
				Plane p = (Plane)obj;
				return (_normal == p.Normal) && (_const == p.Constant);
			}
			return false;
		}

		/// <summary>
		/// Returns a string representation of this object.
		/// </summary>
		/// <returns>A string representation of this object.</returns>
		public override string ToString()
		{
			return string.Format("Plane[n={0}, c={1}]", _normal.ToString(), _const.ToString());
		}
		#endregion
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
Israel Israel
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions