Contents
Articles
Behaviors
Books
Director News
Director Web Sites
FAQ
Games
Mailing Lists
News Groups
Project Examples
Reviews
Software
Tools
Useful Web Sites
Utilities
Xtras

Don't miss these
Change ShapeType of a Shape cast member
WinXtra
DragNDrop Behaviour
Setup Anim
TaskXtra
Get browser versions
MP3Xtra
Billenium Transitions Xtra
AutoRez Monitor Resolution Switcher
Icon Shop
 

 

 

Behavior Trigonometry Class v0.6

Added on 12/3/2003

 

Compatibilities:
D6_5 D7 D8 D8_5 D9 Mac Parent PC Shockwave

This item has not yet been rated

Author: drZool (website)

Trigonometry class collection, Fast precalculated tables. Good set of basic functions for use in gamephysics amongst others. openLingo material.

-- @Name trigmath
-- @Version 1.6
-- @Type Parent
-- @Author Christoffer Enedahl
-- @Home www.enedahl.com
-- @Home www.openlingo.org

-- @History Added    v1.6 2003-10-27 GetFarAngle, InvCos, pAtan1
-- @History Added    v1.5 2003-03-20 vectorToAngle(), vectorToDegree() Lazy use of atan
-- @History Added    v1.4 2003-02-26 isPointInQuad()
-- @History Removed  v1.4 2003-02-21 atan2, it turns out that this function is an undoc'd lingofunction. use: atan(y,x)
-- @History Added    v1.3 2003-02-19 atan2
-- @History Optimize v1.2 2003-02-12 Using 3d functions for normalize2d and others
-- @History Added    v1.2 2003-02-12 magnitude2d
-- @History Added    v1.1 2003-01-16 vector functions
-- @History Created  v1.0 2003-01-15
--
-- @Description Precalculate sin-, cos- and radtables for fast calculations
-- @Description Some angle operations on points.
--
-- @Dependencies olmath.ls sgn bitshiftleft bitshiftright
--
--Usage
--  p = trigmath.rotatePoint     ( point(3,5), trigmath.angleToRad(-45) )
--  p = trigmath.rotatePointFast ( point(3,5), 315 )
--
-- @Todo Lots of trigonometry, feel free to contribute.

property pDegToRad
property pCosTable --index is degrees 1-360
property pSinTable --index is degrees 1-360
property pRadTable --index is degrees 1-360
property pAtan1    --Precalced Atan(1)

on new me
  
  pDegToRad = pi / 180.0
  pAtan1    = atan(1)
  
  --Precalculate sin-, cos- and radtables for fast calculations
  pCosTable = []
  pSinTable = []
  pRadTable = []
  repeat with i = 1 to 360
    pRadTable.append( me.degreeToRad(i) )
    pCosTable.append( cos( pRadTable[i] ) )
    pSinTable.append( sin( pRadTable[i] ) )
  end repeat
  
  return me
end

on degreeToRad(me, aDegree)
  return aDegree * pDegToRad
end

on radToDegree (me, aRadian)
  return aRadian / pDegToRad
end

on degreeToRadFast (me, aDegree)
  -- aDegre must be an integer degree between 1 - 360
  return pRadTable.getAt(aDegree)
end

on rotatePoint (me, aPoint, aTheta)
  -- aTheta is a radian number.
  p = point(.0,.0)
  
  vCos = cos(aTheta)
  vSin = sin(aTheta)
  
  p[1] = vCos*aPoint[1] - vSin*aPoint[2]
  p[2] = vSin*aPoint[1] + vCos*aPoint[2]
  
  return p
end

--aTheta must be an integer degree between 1 - 360
on rotatePointFast (me, aPoint, aTheta)
  p = point(0,0)
  
  p[1] = pCosTable[aTheta]*aPoint[1] - pSinTable[aTheta]*aPoint[2]
  p[2] = pSinTable[aTheta]*aPoint[1] + pCosTable[aTheta]*aPoint[2]
  
  return p
end

on distance2d (me,aPoint1,aPoint2)
  vVector = vector( aPoint1[1] - aPoint2[1], aPoint1[2] - aPoint2[2], 0)
  return vVector.magnitude
end

on distance2dFast (me,aPoint1,aPoint2)
  -- Remember the returned distance is squared the actual distance!
  -- it about 5-10% faster than distance2d
  d1 = aPoint1[1] - aPoint2[1]
  d2 = aPoint1[2] - aPoint2[2]
  return (d1*d1) + (d2*d2)
end

on approxDistance2d ( me, aPoint1, aPoint2)
  
  dx = abs( aPoint2.loch - aPoint2.loch )
  dy = abs( aPoint2.locv - aPoint2.locv )
  
  if dx < dy then
    vMin = dx
    vMax = dy
  else
    vMin = dy
    vMax = dx
  end if
  
  approx = ( vMax * 1007 ) + ( vMin * 441 )
  if ( vMax < ( bitshiftleft(vMin,4) )) then approx = approx - ( vMax * 40 )
  
  -- add 512 for proper rounding
  return ( bitshiftright( approx + 512, 10 ) )
end

on vector2d (me,aPoint1,aPoint2)
  return aPoint2 - aPoint1
end

on normalize2d (me,aPoint)
  vVector = vector( the loch of aPoint, the locv of aPoint, 0)
  vVector.normalize()
  return point( vVector[1], vVector[2])
end

on magnitude2d me, aPoint
  vVector = vector( aPoint[1], aPoint[2], 0)
  return vVector.magnitude
end

on magnitude2dFast me, aPoint
  -- Remember the returned distance is squared the actual distance!
  -- it about 5-10% faster than magnitude2d
  a = aPoint[1]
  b = aPoint[2]
  return (a*a) + (b*b)
end

on get2dNormal me, aVector
  -- the resulting vector is the normal, but it is not normalized.
  -- all that happens is a rotate by 90 degrees.
  
  p = point(0,0)
  p[1] = pCosTable[90]*aVector[1] - pSinTable[90]*aVector[2]
  p[2] = pSinTable[90]*aVector[1] + pCosTable[90]*aVector[2]
  
  return p
end

on vectorToDegree (me,aVector)
  --Lazy use of atan
   return me.radToDegree( atan(aVector.locv, aVector.loch) )
end

on vectorToAngle (me,aVector)
  --Lazy use of atan
   return atan(aVector.locv, aVector.loch)
end

on angleToVector (me, aTheta)
   return point( cos(aTheta), sin(aTheta) )
end

on dotproduct2d (me, a ,b)
  return dotproduct( vector( a[1],a[2],0), vector( b[1],b[2],0) )
end

on lineToQuad (me, aA, aB, aLineWidth, aEndLineWidth)
  -- makes a quad, to use for example with copyPixels, then you can draw lines with the ability to blend it.
  -- aEndLineWidth is optional
  
  vQuad = [aA,aA,aB,aB]
  
  vNormal = me.normalize2d( me.get2dNormal( me.vector2d(aA,aB) ) )
  
  if voidP(aEndLineWidth) then
    vNormal = vNormal * (aLineWidth/2.0)
    
    vQuad[1] = vQuad[1] + vNormal
    vQuad[2] = vQuad[2] - vNormal
    vQuad[3] = vQuad[3] - vNormal
    vQuad[4] = vQuad[4] + vNormal
  else
    vNormalEnd = vNormal * (aEndLineWidth/2.0)
    vNormal    = vNormal * (aLineWidth   /2.0)
    
    vQuad[1] = vQuad[1] + vNormal
    vQuad[2] = vQuad[2] - vNormal
    vQuad[3] = vQuad[3] - vNormalEnd
    vQuad[4] = vQuad[4] + vNormalEnd
  end if
  
  return vQuad
end

on isPointInQuad(me, aQuad, aPoint)
  --clockwize quad
  vNextPoint = [2,3,4,1]
  
  repeat with vVertexNum = 1 to 4
    vArea = me.TriangleAreaFast(aPoint, aQuad[ vVertexNum ], aQuad[ vNextPoint[ vVertexNum ] ] )
    if vArea < 0 then return 0
  end repeat
  
  return 1
end

on TriangleAreaFast(me, p, a, b )
  --This function does not produce an accurate area of an triangle, but fast results determing order of points. used in isPointInQuad,
  --if this result is negative: the points are counterclockwize, therefore the p lies outside of the line a-b
  return (a.loch-p.loch) * (b.locv-p.locv) - (b.loch-p.loch)*(a.locv-p.locv)
end

on terminate me
end

on GetFarAngle (me,c,a,b)
  --
  --   |
  --   |x
  -- a |   b
  --   |___
  --     c
  --
  -- return the radian angle of the far side of a triangle with known lengths
  -- the corner of the far side of c
  -- the triangle does not need to be a "right triangle"
  -- CosineStatement: a2 = b2 + c2 - 2bc · cos vA  
  --  
  --  x = a*a + b*b - c*c
  --  x = x / float(2*a*b)
  --  x = me.InvCos(x)  
  --  
  --  return x
  
  if a*b = 0 then return 0
  
  return me.InvCos( (a*a + b*b - c*c) / float(2*a*b) )
end

on InvCos me, X  
  y = Sqrt(-X * X + 1)
  if y = 0 then return 0 --y=NAN
  return atan(-X / y) + 2 * pAtan1
end

--Other functions to be lingolized
--Secant Sec(X) = 1 / Cos(X)
--Cosecant Cosec(X) = 1 / Sin(X)
--Cotangent Cotan(X) = 1 / Tan(X)
--Inverse Sine Arcsin(X) = Atn(X / Sqr(-X * X + 1))
--Inverse Cosine Arccos(X) = Atn(-X / Sqr(-X * X + 1)) + 2 * Atn(1)
--Inverse Secant Arcsec(X) = Atn(X / Sqr(X * X – 1)) + Sgn((X) – 1) * (2 * Atn(1))
--Inverse Cosecant Arccosec(X) = Atn(X / Sqr(X * X - 1)) + (Sgn(X) – 1) * (2 * Atn(1))
--Inverse Cotangent Arccotan(X) = Atn(X) + 2 * Atn(1)
--Hyperbolic Sine HSin(X) = (Exp(X) – Exp(-X)) / 2  
--Hyperbolic Cosine HCos(X) = (Exp(X) + Exp(-X)) / 2
--Hyperbolic Tangent HTan(X) = (Exp(X) – Exp(-X)) / (Exp(X) + Exp(-X))
--Hyperbolic Secant HSec(X) = 2 / (Exp(X) + Exp(-X))
--Hyperbolic Cosecant HCosec(X) = 2 / (Exp(X) – Exp(-X))
--Hyperbolic Cotangent HCotan(X) = (Exp(X) + Exp(-X)) / (Exp(X) – Exp(-X))
--Inverse Hyperbolic Sine HArcsin(X) = Log(X + Sqr(X * X + 1))
--Inverse Hyperbolic Cosine HArccos(X) = Log(X + Sqr(X * X – 1))
--Inverse Hyperbolic Tangent HArctan(X) = Log((1 + X) / (1 – X)) / 2
--Inverse Hyperbolic Secant HArcsec(X) = Log((Sqr(-X * X + 1) + 1) / X)
--Inverse Hyperbolic Cosecant HArccosec(X) = Log((Sgn(X) * Sqr(X * X + 1) + 1) / X)
--Inverse Hyperbolic Cotangent HArccotan(X) = Log((X + 1) / (X – 1)) / 2
--Logarithm to base N LogN(X) = Log(X) / Log(N)

 


Contact

MMI
36 South Court Sq
Suite 300
Newnan, GA 30263
USA

Send e-mail