2007-06-13 19:39:38 +00:00
/ *
* Copyright ( c ) 2007 Pascal vd Heiden , www . codeimp . com
* This program is released under GNU General Public License
*
* This program 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 General Public License for more details .
*
* /
using System ;
using System.Collections ;
using System.Collections.Generic ;
using System.Globalization ;
using System.Text ;
2007-06-14 12:37:46 +00:00
using CodeImp.DoomBuilder.Geometry ;
2007-06-13 19:39:38 +00:00
namespace CodeImp.DoomBuilder.Map
{
internal class Linedef : IDisposable
{
#region = = = = = = = = = = = = = = = = = = Constants
#endregion
#region = = = = = = = = = = = = = = = = = = Variables
2007-06-14 12:37:46 +00:00
// Map
2007-06-14 13:09:55 +00:00
private MapSet map ;
2007-06-14 12:37:46 +00:00
// List items
private LinkedListNode < Linedef > mainlistitem ;
private LinkedListNode < Linedef > startvertexlistitem ;
private LinkedListNode < Linedef > endvertexlistitem ;
2007-06-13 19:39:38 +00:00
// Vertices
private Vertex start ;
private Vertex end ;
// Sidedefs
private Sidedef front ;
private Sidedef back ;
2007-06-14 12:37:46 +00:00
// Cache
private float lengthsq ;
private float length ;
//private float angle;
2007-06-13 19:39:38 +00:00
// Properties
private int flags ;
private int action ;
private int tag ;
private byte [ ] args ;
// Disposing
private bool isdisposed = false ;
#endregion
#region = = = = = = = = = = = = = = = = = = Properties
2007-06-14 13:09:55 +00:00
public Vertex Start { get { return start ; } }
public Vertex End { get { return end ; } }
2007-06-14 12:37:46 +00:00
public Sidedef Front { get { return front ; } }
public Sidedef Back { get { return back ; } }
2007-06-13 19:39:38 +00:00
public bool IsDisposed { get { return isdisposed ; } }
#endregion
#region = = = = = = = = = = = = = = = = = = Constructor / Disposer
// Constructor
2007-06-14 13:09:55 +00:00
public Linedef ( MapSet map , LinkedListNode < Linedef > listitem , Vertex start , Vertex end )
2007-06-13 19:39:38 +00:00
{
// Initialize
2007-06-14 12:37:46 +00:00
this . map = map ;
this . mainlistitem = listitem ;
2007-06-13 19:39:38 +00:00
this . start = start ;
this . end = end ;
2007-06-14 12:37:46 +00:00
// Attach to vertices
startvertexlistitem = start . AttachLinedef ( this ) ;
endvertexlistitem = end . AttachLinedef ( this ) ;
// Calculate values
Recalculate ( ) ;
2007-06-13 19:39:38 +00:00
// We have no destructor
GC . SuppressFinalize ( this ) ;
}
// Diposer
public void Dispose ( )
{
// Not already disposed?
if ( ! isdisposed )
{
2007-06-14 12:37:46 +00:00
// Already set isdisposed so that changes can be prohibited
isdisposed = true ;
// Remove from main list
mainlistitem . List . Remove ( mainlistitem ) ;
2007-06-13 19:39:38 +00:00
// Detach from vertices
2007-06-14 12:37:46 +00:00
start . DetachLinedef ( startvertexlistitem ) ;
end . DetachLinedef ( endvertexlistitem ) ;
2007-06-13 19:39:38 +00:00
// Dispose sidedefs
front . Dispose ( ) ;
back . Dispose ( ) ;
// Clean up
2007-06-14 12:37:46 +00:00
mainlistitem = null ;
startvertexlistitem = null ;
endvertexlistitem = null ;
2007-06-13 19:39:38 +00:00
start = null ;
end = null ;
front = null ;
back = null ;
2007-06-14 12:37:46 +00:00
map = null ;
2007-06-13 19:39:38 +00:00
}
}
#endregion
2007-06-14 12:37:46 +00:00
#region = = = = = = = = = = = = = = = = = = Management
// This attaches a sidedef on the front
public void AttachFront ( Sidedef s ) { if ( front = = null ) front = s ; else throw new Exception ( "Linedef already has a front Sidedef." ) ; }
// This attaches a sidedef on the back
public void AttachBack ( Sidedef s ) { if ( back = = null ) back = s ; else throw new Exception ( "Linedef already has a back Sidedef." ) ; }
// This detaches a sidedef from the front
public void DetachSidedef ( Sidedef s ) { if ( front = = s ) front = null ; else if ( back = = s ) back = null ; else throw new Exception ( "Specified Sidedef is not attached to this Linedef." ) ; }
// This recalculates cached values
public void Recalculate ( )
{
// Delta vector
Vector2D delta = end . Position - start . Position ;
// Recalculate values
lengthsq = delta . GetLengthSq ( ) ;
length = ( float ) Math . Sqrt ( lengthsq ) ;
//angle = delta.GetAngle();
}
2007-06-14 13:09:55 +00:00
// This copies all properties to another line
public void CopyPropertiesTo ( Linedef l )
{
// Copy properties
l . action = action ;
l . args = ( byte [ ] ) args . Clone ( ) ;
l . flags = flags ;
l . tag = tag ;
}
2007-06-14 12:37:46 +00:00
#endregion
#region = = = = = = = = = = = = = = = = = = Mathematics
// This returns the shortest distance from given coordinates to line
public float DistanceToSq ( Vector2D p , bool bounded )
{
Vector2D v1 = start . Position ;
Vector2D v2 = end . Position ;
// Calculate intersection offset
float u = ( ( p . x - v1 . x ) * ( v2 . x - v1 . x ) + ( p . y - v1 . y ) * ( v2 . y - v1 . y ) ) / lengthsq ;
// Limit intersection offset to the line
if ( bounded ) if ( u < 0f ) u = 0f ; else if ( u > 1f ) u = 1f ;
// Calculate intersection point
Vector2D i = v1 + u * ( v2 - v1 ) ;
// Return distance between intersection and point
// which is the shortest distance to the line
float ldx = p . x - i . x ;
float ldy = p . y - i . y ;
return ldx * ldx + ldy * ldy ;
}
// This returns the shortest distance from given coordinates to line
public float DistanceTo ( Vector2D p , bool bounded )
{
return ( float ) Math . Sqrt ( DistanceToSq ( p , bounded ) ) ;
}
2007-06-13 19:39:38 +00:00
2007-06-14 12:37:46 +00:00
// This tests on which side of the line the given coordinates are
// returns < 0 for front (right) side, > 0 for back (left) side and 0 if on the line
public float SideOfLine ( Vector2D p )
{
Vector2D v1 = start . Position ;
Vector2D v2 = end . Position ;
// Calculate and return side information
return ( p . y - v1 . y ) * ( v2 . x - v1 . x ) - ( p . x - v1 . x ) * ( v2 . y - v1 . y ) ;
}
2007-06-13 19:39:38 +00:00
#endregion
}
}