diff options
Diffstat (limited to 'algorithm.mod/algorithm.bmx')
-rw-r--r-- | algorithm.mod/algorithm.bmx | 645 |
1 files changed, 322 insertions, 323 deletions
diff --git a/algorithm.mod/algorithm.bmx b/algorithm.mod/algorithm.bmx index 065a254..c449f5f 100644 --- a/algorithm.mod/algorithm.bmx +++ b/algorithm.mod/algorithm.bmx @@ -1,323 +1,322 @@ -' Copyright (c) 2006 Ian Cowburn -' -' Permission is hereby granted, free of charge, to any person obtaining a copy of -' this software and associated documentation files (the "Software"), to deal in -' the Software without restriction, including without limitation the rights to -' use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -' of the Software, and to permit persons to whom the Software is furnished to do -' so, subject to the following conditions: -' -' The above copyright notice and this permission notice shall be included in all -' copies or substantial portions of the Software. -' -' THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -' IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -' FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -' AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -' LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -' OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -' SOFTWARE. -' -' $Id$ -' -Rem -bbdoc: noddybox.algorithm -EndRem -Module noddybox.algorithm - -ModuleInfo "Framework: Various algorithm routines" -ModuleInfo "Copyright: Ian Cowburn -- released under the MIT License" -ModuleInfo "Author: Ian Cowburn" -ModuleInfo "Version: $Revision$" - -Strict -Import brl.math -Import brl.linkedlist - -Rem -bbdoc: Used to return integer points from algorithms. -EndRem -Type TAlgoPoint - Rem - bbdoc: The X co-ordinate of the point - EndRem - Field x:Int - Rem - bbdoc: The Y co-ordinate of the point - EndRem - Field y:Int - - Rem - bbdoc: Create a point. - returns: Newly created point. - about: @x and @y are initialised with the passed parameters. - EndRem - Function Create:TAlgoPoint(x:Int, y:Int) - Local o:TAlgoPoint=New TAlgoPoint - o.x=x - o.y=y - Return o - End Function - -End Type - -Rem -bbdoc: Used to return double points from algorithms. -EndRem -Type TAlgoPointD - Rem - bbdoc: The X co-ordinate of the point - EndRem - Field x:Double - Rem - bbdoc: The Y co-ordinate of the point - EndRem - Field y:Double - - Rem - bbdoc: Create a point. - returns: Newly created point. - about: @x and @y are initialised with the passed parameters. - EndRem - Function Create:TAlgoPointD(x:Double, y:Double) - Local o:TAlgoPointD=New TAlgoPointD - o.x=x - o.y=y - Return o - End Function - -End Type - -Rem -bbdoc: Used to return 3D points from algorithms. -EndRem -Type TAlgoPoint3D - Rem - bbdoc: The X co-ordinate of the point - EndRem - Field x:Double - Rem - bbdoc: The Y co-ordinate of the point - EndRem - Field y:Double - Rem - bbdoc: The Z co-ordinate of the point - EndRem - Field z:Double - - Rem - bbdoc: Create a point. - returns: Newly created point. - about: @x, @y and @z are initialised with the passed parameters. - EndRem - Function Create:TAlgoPoint3D(x:Double, y:Double, z:Double) - Local o:TAlgoPoint3D=New TAlgoPoint3D - o.x=x - o.y=y - o.z=z - Return o - End Function - -End Type - -Rem -bbdoc: Rotates a point. -returns: The rotated point. -about: @x, @y are rotated around 0,0 by @angle, which is the value in degrees multiplied by ten. -about: To speed things up a simple 3600 element lookup table is used, so @angle <u>must</u> be 0 to 3599 inclusive, or a runtime error will result. -EndRem -Function DoRotate:TAlgoPoint(x:Int, y:Int, angle:Int) - AlgoStatic.Init() - - Local dx:Double=x - Local dy:Double=y - Local dco:Double=AlgoStatic.co[angle] - Local dsi:Double=algoStatic.si[angle] - - Return TAlgoPoint.Create(dco*dx+(-dsi)*dy,dsi*dx+dco*dy) -End Function - -Rem -bbdoc: Rotates a point (double version) -returns: The rotated point. -about: @x, @y are rotated around 0,0 by @angle, which is the value in degrees multiplied by ten. -about: To speed things up a simple 3600 element lookup table is used, so @angle <u>must</u> be 0 to 3599 inclusive, or a runtime error will result. -EndRem -Function DoRotateD:TAlgoPointD(x:Double, y:Double, angle:Int) - AlgoStatic.Init() - - Local dco:Double=AlgoStatic.co[angle] - Local dsi:Double=algoStatic.si[angle] - - Return TAlgoPointD.Create(dco*x+(-dsi)*y,dsi*x+dco*y) -End Function - -Rem -bbdoc: Implements a Bresenham style line. -returns: A list of points making up the line. -about: @px1, @py1, @px2 and @py2 are the end points of the line. -EndRem -Function DoLine:TList(p1x:Int, p1y:Int, p2x:Int, p2y:Int) - Local list:TList=CreateList() - Local f:Int - Local dx:Int - Local dy:Int - Local ix:Int - Local iy:Int - Local incrE:Int - Local incrNE:Int - Local d:Int - Local x:Int - Local y:Int - Local ymode:Int - - dx=p2x-p1x - dy=p2y-p1y - - ix=Sgn(dx) - iy=Sgn(dy) - - dx=Abs(dx) - dy=Abs(dy) - - If dy>dx - ymode=True - d=dx*2-dy - incrE=dx*2 - incrNE=(dx-dy)*2 - Else - ymode=False - d=dy*2-dx - incrE=dy*2 - incrNE=(dy-dx)*2 - EndIf - - x=p1x - y=p1y - - list.AddLast(TAlgoPoint.Create(x,y)) - - If ymode - While y<>p2y - If d<=0 - d:+incrE - y:+iy - Else - d:+incrNE - y:+iy - x:+ix - EndIf - - list.AddLast(TAlgoPoint.Create(x,y)) - Wend - Else - While x<>p2x - If d<=0 - d:+incrE - x:+ix - Else - d:+incrNE - y:+iy - x:+ix - EndIf - - list.AddLast(TAlgoPoint.Create(x,y)) - Wend - EndIf - - Return list -End Function - - -Rem -bbdoc: Returns the points for degrees 0-359 on the described circle. -returns: A list of points making up the circle. -about: @x, @y is the centre of the circle, @r it's radius. -EndRem -Function DoCircle:TAlgoPoint[](x:Int, y:Int, r:Int) - Local p:TAlgoPoint[]=New TAlgoPoint[360] - Local f:Int - - AlgoStatic.Init() - - For f=0 To 359 - p[f]=TAlgoPoint.Create(x+r*AlgoStatic.si[f*10],y+r*AlgoStatic.co[f*10]) - Next - - Return p -End Function - - -Rem -bbdoc: Returns the points where a sphere intersects a 3D line. -returns: null if they don't intersect, one point if it intersects as a tangent, two points otherwise. -about: @x1, @y1, @z1, @x2, @y2 and @z2 describe the line. @cx, @cy, @cz and @rad describe the sphere. -about: Leave the Z co-ords as zero to do a 2D check. -EndRem -Function CircleIntersects:TAlgoPoint3D[](x1:Double, y1:Double, z1:Double, x2:Double, y2:Double, z2:Double, cx:Double, cy:Double, cz:Double, rad:Double) - Local a:Double = Square(x2-x1) + Square(y2-y1) + Square(z2-z1) - Local b:Double = 2 * ( (x2-x1)*(x1-cx) + (y2-y1)*(y1-cy) + (z2-z1)*(z1-cz) ) - Local c:Double = Square(x1) + Square(y1) + Square(z1) + Square(cx) + Square(cy) + Square(cz) - 2 * ( cx*x1 + cy*y1 + cz*z1 ) - Square(rad) - Local i:Double = b*b-4*a*c - - If i<0 - Return Null - ElseIf i=1.0 - Local m:Double = -b/(2*a) - If m<0.0 Or m>1.0 - Return Null - EndIf - Local p:TAlgoPoint3D[]=New TAlgoPoint3D[1] - p[0]=TAlgoPoint3D.Create( x1+m*(x2-x1), y1+m*(y2-y1), z1 + m*(z2-z1)) - Return p - Else - Local e:Double = Sqr(Square(b) - 4*a*c) - Local m1:Double = (-b + e) / (2*a) - Local m2:Double = (-b - e) / (2*a) - - If (m2<0.0 Or m2>1.0) And (m1<0.0 Or m1>1.0) - Return Null - ElseIf (m1<0.0 Or m1>1.0) - Local p:TAlgoPoint3D[]=New TAlgoPoint3D[1] - p[0]=TAlgoPoint3D.Create( x1+m2*(x2-x1), y1+m2*(y2-y1), z1+m2*(z2-z1)) - Return p - ElseIf m2<0.0 Or m2>1.0 - Local p:TAlgoPoint3D[]=New TAlgoPoint3D[1] - p[0]=TAlgoPoint3D.Create( x1+m1*(x2-x1), y1+m1*(y2-y1), z1+m1*(z2-z1)) - Return p - Else - Local p:TAlgoPoint3D[]=New TAlgoPoint3D[2] - p[0]=TAlgoPoint3D.Create( x1+m1*(x2-x1), y1+m1*(y2-y1), z1+m1*(z2-z1)) - p[1]=TAlgoPoint3D.Create( x1+m2*(x2-x1), y1+m2*(y2-y1), z1+m2*(z2-z1)) - Return p - EndIf - EndIf - -End Function - - -Private - -Type AlgoStatic - Global done:Int=False - Global si:Double[] - Global co:Double[] - - Function Init() - If Not done - si=New Double[3600] - co=New Double[3600] - - For Local f:Int=0 To 3599 - si[f]=Sin(Double(f)/10) - co[f]=Cos(Double(f)/10) - Next - - done=True - EndIf - End Function -End Type - -Function Square:Double(x:Double) - Return x*x -End Function +' Copyright (c) 2006 Ian Cowburn
+'
+' Permission is hereby granted, free of charge, to any person obtaining a copy of
+' this software and associated documentation files (the "Software"), to deal in
+' the Software without restriction, including without limitation the rights to
+' use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+' of the Software, and to permit persons to whom the Software is furnished to do
+' so, subject to the following conditions:
+'
+' The above copyright notice and this permission notice shall be included in all
+' copies or substantial portions of the Software.
+'
+' THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+' IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+' FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+' AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+' LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+' OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+' SOFTWARE.
+'
+' $Id$
+'
+Rem
+bbdoc: noddybox.algorithm
+EndRem
+Module noddybox.algorithm
+
+ModuleInfo "Framework: Various algorithm routines"
+ModuleInfo "Copyright: Ian Cowburn -- released under the MIT License"
+ModuleInfo "Author: Ian Cowburn"
+ModuleInfo "Version: $Revision$"
+
+Import brl.math
+Import brl.linkedlist
+
+Rem
+bbdoc: Used to return integer points from algorithms.
+EndRem
+Type TAlgoPoint
+ Rem
+ bbdoc: The X co-ordinate of the point
+ EndRem
+ Field x:Int
+ Rem
+ bbdoc: The Y co-ordinate of the point
+ EndRem
+ Field y:Int
+
+ Rem
+ bbdoc: Create a point.
+ returns: Newly created point.
+ about: @x and @y are initialised with the passed parameters.
+ EndRem
+ Function Create:TAlgoPoint(x:Int, y:Int)
+ Local o:TAlgoPoint=New TAlgoPoint
+ o.x=x
+ o.y=y
+ Return o
+ End Function
+
+End Type
+
+Rem
+bbdoc: Used to return double points from algorithms.
+EndRem
+Type TAlgoPointD
+ Rem
+ bbdoc: The X co-ordinate of the point
+ EndRem
+ Field x:Double
+ Rem
+ bbdoc: The Y co-ordinate of the point
+ EndRem
+ Field y:Double
+
+ Rem
+ bbdoc: Create a point.
+ returns: Newly created point.
+ about: @x and @y are initialised with the passed parameters.
+ EndRem
+ Function Create:TAlgoPointD(x:Double, y:Double)
+ Local o:TAlgoPointD=New TAlgoPointD
+ o.x=x
+ o.y=y
+ Return o
+ End Function
+
+End Type
+
+Rem
+bbdoc: Used to return 3D points from algorithms.
+EndRem
+Type TAlgoPoint3D
+ Rem
+ bbdoc: The X co-ordinate of the point
+ EndRem
+ Field x:Double
+ Rem
+ bbdoc: The Y co-ordinate of the point
+ EndRem
+ Field y:Double
+ Rem
+ bbdoc: The Z co-ordinate of the point
+ EndRem
+ Field z:Double
+
+ Rem
+ bbdoc: Create a point.
+ returns: Newly created point.
+ about: @x, @y and @z are initialised with the passed parameters.
+ EndRem
+ Function Create:TAlgoPoint3D(x:Double, y:Double, z:Double)
+ Local o:TAlgoPoint3D=New TAlgoPoint3D
+ o.x=x
+ o.y=y
+ o.z=z
+ Return o
+ End Function
+
+End Type
+
+Rem
+bbdoc: Rotates a point.
+returns: The rotated point.
+about: @x, @y are rotated around 0,0 by @angle, which is the value in degrees multiplied by ten.
+about: To speed things up a simple 3600 element lookup table is used, so @angle <u>must</u> be 0 to 3599 inclusive, or a runtime error will result.
+EndRem
+Function DoRotate:TAlgoPoint(x:Int, y:Int, angle:Int)
+ AlgoStatic.Init()
+
+ Local dx:Double=x
+ Local dy:Double=y
+ Local dco:Double=AlgoStatic.co[angle]
+ Local dsi:Double=algoStatic.si[angle]
+
+ Return TAlgoPoint.Create(dco*dx+(-dsi)*dy,dsi*dx+dco*dy)
+End Function
+
+Rem
+bbdoc: Rotates a point (double version)
+returns: The rotated point.
+about: @x, @y are rotated around 0,0 by @angle, which is the value in degrees multiplied by ten.
+about: To speed things up a simple 3600 element lookup table is used, so @angle <u>must</u> be 0 to 3599 inclusive, or a runtime error will result.
+EndRem
+Function DoRotateD:TAlgoPointD(x:Double, y:Double, angle:Int)
+ AlgoStatic.Init()
+
+ Local dco:Double=AlgoStatic.co[angle]
+ Local dsi:Double=algoStatic.si[angle]
+
+ Return TAlgoPointD.Create(dco*x+(-dsi)*y,dsi*x+dco*y)
+End Function
+
+Rem
+bbdoc: Implements a Bresenham style line.
+returns: A list of points making up the line.
+about: @px1, @py1, @px2 and @py2 are the end points of the line.
+EndRem
+Function DoLine:TList(p1x:Int, p1y:Int, p2x:Int, p2y:Int)
+ Local list:TList=CreateList()
+ Local f:Int
+ Local dx:Int
+ Local dy:Int
+ Local ix:Int
+ Local iy:Int
+ Local incrE:Int
+ Local incrNE:Int
+ Local d:Int
+ Local x:Int
+ Local y:Int
+ Local ymode:Int
+
+ dx=p2x-p1x
+ dy=p2y-p1y
+
+ ix=Sgn(dx)
+ iy=Sgn(dy)
+
+ dx=Abs(dx)
+ dy=Abs(dy)
+
+ If dy>dx
+ ymode=True
+ d=dx*2-dy
+ incrE=dx*2
+ incrNE=(dx-dy)*2
+ Else
+ ymode=False
+ d=dy*2-dx
+ incrE=dy*2
+ incrNE=(dy-dx)*2
+ EndIf
+
+ x=p1x
+ y=p1y
+
+ list.AddLast(TAlgoPoint.Create(x,y))
+
+ If ymode
+ While y<>p2y
+ If d<=0
+ d:+incrE
+ y:+iy
+ Else
+ d:+incrNE
+ y:+iy
+ x:+ix
+ EndIf
+
+ list.AddLast(TAlgoPoint.Create(x,y))
+ Wend
+ Else
+ While x<>p2x
+ If d<=0
+ d:+incrE
+ x:+ix
+ Else
+ d:+incrNE
+ y:+iy
+ x:+ix
+ EndIf
+
+ list.AddLast(TAlgoPoint.Create(x,y))
+ Wend
+ EndIf
+
+ Return list
+End Function
+
+
+Rem
+bbdoc: Returns the points for degrees 0-359 on the described circle.
+returns: A list of points making up the circle.
+about: @x, @y is the centre of the circle, @r it's radius.
+EndRem
+Function DoCircle:TAlgoPoint[](x:Int, y:Int, r:Int)
+ Local p:TAlgoPoint[]=New TAlgoPoint[360]
+ Local f:Int
+
+ AlgoStatic.Init()
+
+ For f=0 To 359
+ p[f]=TAlgoPoint.Create(x+r*AlgoStatic.si[f*10],y+r*AlgoStatic.co[f*10])
+ Next
+
+ Return p
+End Function
+
+
+Rem
+bbdoc: Returns the points where a sphere intersects a 3D line.
+returns: null if they don't intersect, one point if it intersects as a tangent, two points otherwise.
+about: @x1, @y1, @z1, @x2, @y2 and @z2 describe the line. @cx, @cy, @cz and @rad describe the sphere.
+about: Leave the Z co-ords as zero to do a 2D check.
+EndRem
+Function CircleIntersects:TAlgoPoint3D[](x1:Double, y1:Double, z1:Double, x2:Double, y2:Double, z2:Double, cx:Double, cy:Double, cz:Double, rad:Double)
+ Local a:Double = Square(x2-x1) + Square(y2-y1) + Square(z2-z1)
+ Local b:Double = 2 * ( (x2-x1)*(x1-cx) + (y2-y1)*(y1-cy) + (z2-z1)*(z1-cz) )
+ Local c:Double = Square(x1) + Square(y1) + Square(z1) + Square(cx) + Square(cy) + Square(cz) - 2 * ( cx*x1 + cy*y1 + cz*z1 ) - Square(rad)
+ Local i:Double = b*b-4*a*c
+
+ If i<0
+ Return Null
+ ElseIf i=1.0
+ Local m:Double = -b/(2*a)
+ If m<0.0 Or m>1.0
+ Return Null
+ EndIf
+ Local p:TAlgoPoint3D[]=New TAlgoPoint3D[1]
+ p[0]=TAlgoPoint3D.Create( x1+m*(x2-x1), y1+m*(y2-y1), z1 + m*(z2-z1))
+ Return p
+ Else
+ Local e:Double = Sqr(Square(b) - 4*a*c)
+ Local m1:Double = (-b + e) / (2*a)
+ Local m2:Double = (-b - e) / (2*a)
+
+ If (m2<0.0 Or m2>1.0) And (m1<0.0 Or m1>1.0)
+ Return Null
+ ElseIf (m1<0.0 Or m1>1.0)
+ Local p:TAlgoPoint3D[]=New TAlgoPoint3D[1]
+ p[0]=TAlgoPoint3D.Create( x1+m2*(x2-x1), y1+m2*(y2-y1), z1+m2*(z2-z1))
+ Return p
+ ElseIf m2<0.0 Or m2>1.0
+ Local p:TAlgoPoint3D[]=New TAlgoPoint3D[1]
+ p[0]=TAlgoPoint3D.Create( x1+m1*(x2-x1), y1+m1*(y2-y1), z1+m1*(z2-z1))
+ Return p
+ Else
+ Local p:TAlgoPoint3D[]=New TAlgoPoint3D[2]
+ p[0]=TAlgoPoint3D.Create( x1+m1*(x2-x1), y1+m1*(y2-y1), z1+m1*(z2-z1))
+ p[1]=TAlgoPoint3D.Create( x1+m2*(x2-x1), y1+m2*(y2-y1), z1+m2*(z2-z1))
+ Return p
+ EndIf
+ EndIf
+
+End Function
+
+
+Private
+
+Type AlgoStatic
+ Global done:Int=False
+ Global si:Double[]
+ Global co:Double[]
+
+ Function Init()
+ If Not done
+ si=New Double[3600]
+ co=New Double[3600]
+
+ For Local f:Int=0 To 3599
+ si[f]=Sin(Double(f)/10)
+ co[f]=Cos(Double(f)/10)
+ Next
+
+ done=True
+ EndIf
+ End Function
+End Type
+
+Function Square:Double(x:Double)
+ Return x*x
+End Function
|