MATH - Repost

Advanced game related topics
User avatar
DK_PETER
Addict
Addict
Posts: 898
Joined: Sat Feb 19, 2011 10:06 am
Location: Denmark
Contact:

MATH - Repost

Post by DK_PETER »

Apparently the game math sticky got unstuck to the bin after the forum got polished.

Unfortunately I didn't get the other member's code but here's my math assembled in a module.
Hopefully the previous postings from the other members will reappear.
Have fun.

(EnableExplicit - corrected - again :-))

Code: Select all

DeclareModule _Math
EnableExplicit

  #GRAVITY 						= 9.81 
  #KM_TO_MILES 				= 1.609
  #MILES_TO_KM 				= 0.621
  #KM_TO_METERS 			= 1000
  #METER_TO_INCH 			= 39.37
  #METER_TO_FEET 			= 3.281
  #INCH_TO_CM     		= 2.54
  #FOOT_TO_CM     		= 30.48
  #YARD_TO_CM     		= 91.44
  #CM_TO_INCH     		= 0.39370
  #DAYS_TO_WEEK 			= 7
  #HOURS_TO_DAY 			= 24
  #HOURS_TO_MIN 			= 60
  #HOURS_TO_SEC       = 3600
  #MIN_TO_SEC 				= 60
  #MINIMUM_CELCIUS		= -273.16
  #KILO_TONNE					= 1000
  #KILO_GRAMS					= 1000
  #OZ_TO_GRAMS				= 28.375
  #GRAMS_TO_OZ    		= 0.035
  #POUND_TO_KILO  		= 0.454
  #KILO_TO_POUND  		= 2.204
  #KILOBYTE_BYTE  		= 1024
  #NAUTICMILE_TO_MILE = 1.151 ;(length of a minute of longitude at equator)
  #NAUTICMILE_TO_FEET = 6076.115
  #FATHOM_TO_FEET     = 6
  #KB                 = 102928
  #MB                 = 103000
  #GB                 = 103001
  #TB                 = 103002
  
  
  Structure vector2D
    x.f
    y.f
  EndStructure
  
  Structure pt2d
    x.d
    y.d
  EndStructure

  Structure _2Dvector_pol
    mag.f
    dir.f
  EndStructure
  
  Structure vector3D
    x.f
    y.f
    z.f
  EndStructure
  
  Structure pt3f
    x.i
    y.i
    z.i
  EndStructure
  
  Structure quaternion
    x.f
    y.f
    z.f
    w.f
  EndStructure
  
  Structure _Sphere
    x.f
    y.f
    z.f
    radius.f
  EndStructure
  
  Structure _RGB
    R.i
    G.i
    B.i
  EndStructure
  
  Structure LINE_Vec2D_Rotate
    midPointX.i
    midPointY.i
    LineLen.i
    Rotate.i
    EndPosX.i
    EndPosY.i
  EndStructure
  
  Declare.d ColorDistance(*col1._RGB, *col2._RGB)
  Declare.d Distance(*p.POINT, *q.POINT)
  Declare.i FindDist2VertLine(px.f, lx.f)
  Declare.i FindDist2HorizLine(py.f, ly.f)
  Declare.f FindSlopeOfLine(*p1.POINT, *p2.POINT)
  Declare.f CalculateAccelerationSeconds(startVelocity.f, finalVelocity.f , time.f)
  Declare.f EqOne_vf(vi.f, a.f, t.f)
  Declare.f EqTwo_x(vf.f, vi.f, t.f)
  Declare.f EqThree_x(vi.f, t.f, a.f)
  Declare   CheckForMotion(angle.f, weight.f, fric_coeff.f)
  Declare.f CalcAccel(angle.f, weight.f, fric_coeff.f, mass.f)
  Declare.f CalculateWork(force.f, friction.f, displacement.f)
  Declare.f CalculateKineticEnergy(mass.f, speed.f)
  Declare.f CalculateAngledWork(*obj.vector2D, friction.f, displacement.f)
  Declare.f CalculatePotentialEnergy(mass.f ,height.f)
  Declare   Projectile_Trajectory(Screen_Bottom.i, Initial_vel.f, Initial_Angle.f)
  Declare   V2Dvector_comp_PolarToCompConversion(*vec._2Dvector_pol)
  Declare   V2Dvector_polar_CompToPolarConversion(*vec.vector2D)
  Declare.f AngleDisplacement(arc.f, radius.f)
  Declare.f AvgAngularVelocity(arcStart.f, arcEnd.f, time.f, radius.f)
  Declare.f AvgAngAcceleration(angVelBegin.f, angVelEnd.f, time.f)
  Declare.f TangVelocity(omega.f, radius.f)
  Declare.f LinearSpeed(mass.f, initialHeight.f, inertia.f)
  Declare   EulerToQuat(roll.f, pitch.f, yaw.f, *quat.quaternion)
  Declare.f SlopeBetweenPoints(*P1.POINT, *P2.POINT)
  Declare   FindThe2DMidPoint(*P1.POINT, *P2.POINT)
  Declare.f FindThe3DMidPoint(*P1.vector3D, *P2.vector3D)
  Declare   CollisionBetweenSpheres(*S1._Sphere, *S2._Sphere)
  Declare.f CalculateAngle2D(*P1.POINT, *P2.POINT, rad.d)
  Declare   CalcWeight3D(*obj.vector3D, mass.f, gravi.f)
  Declare.f Momentum(velocity.f, mass.f)
  Declare.f CalcDisplacement(velocity.f, _time.f)
  Declare.f CalcPosition(oldPosition.f, velocity.f, _time.f)
  Declare.f CalcAverageVelocity(_start.f , _End.f, time.f)
  Declare.f Ohm_Law(value1.f, value2.f, CalcType.i = 0)
  Declare   ConvertDaysToSeconds(Days.i)
  Declare.f ConvertMilesToMeters(Miles.f)
  Declare.f ConvertSpeedFromMiles(Miles.f)
  Declare.f ConvertAccelerationMilesToMeters(Miles.f)
  Declare.f CelciusToFahrenheit(cels.f)
  Declare.f FarenheitToCelcius(Fahren.f)
  Declare.d Fibonacci()
  Declare.f CalculateEnergyForWaterToBoil(Liters.f, InitTemp.f, FinalTemp.f)
  Declare.f RandomF(Min.f, Max.f, Res.i = 100000)
  Declare.i RandomI(min.i, Max.i, Res.i = 100000)
  Declare.i Random32bit()
  Declare.i AbsI(num.i)
  Declare.f AbsF(num.f)
  Declare   OrbitCalc3D(*ReturnVec.Vector3D, CenterX.f, CenterY.f, CenterZ.f, AngleX.f, AngleY.f, Radius.i)
  Declare   EOrbitCalc3D(*ReturnVec.Vector3D, CenterX.f, CenterY.f, CenterZ.f, AngleX.f, AngleY.f, RadiusX.i, RadiusY.i, RadiusZ.i )
  Declare.f FastDist(x1.f, y1.f, z1.f, x2.f, y2.f, z2.f)
  Declare.f calculateRelativeAngle2D(*origin.POINT, *P1.POINT)
  Declare.d radtodeg(Rad.d)
  Declare.d PointDirection(x.d, y.d, x2.d, y2.d)
  Declare   OrbitCalc2D(*ReturnVec.vector2D, CenterX.f, CenterY.f, AngleX.f, AngleY.f, Radius.i)
  Declare.i CircularMovement2D(StartPosX.i, StartPosY.i, Angle.f, Radius.i, *xp.POINT)
  Declare.f PercentageRemain(Value.f, Percent.f)
  Declare.f PercentageTaken(Value.f, Percent.f)
  Declare.f GetCubicVolume(Width.f, Height.f, Depth.f)
  Declare.f GetSquare(Width.f, Height.f)
  Declare.f GetAverage(List p.f())
  Declare.q Convert(Bytes.q, this = #KB) 
  Declare.i LineRotationEndPosition2D(*o.LINE_Vec2D_Rotate)
  Declare.i TriangleCtr(*PtCtr.pt3f, *Pt1.pt3f, *Pt2.pt3f, *Pt3.pt3f)
  Declare.i RotatePt2d(*pt1.pt2d, *pt2.pt2d, dAng.d)
  
EndDeclareModule

Module _Math
  
  Procedure.q Convert(Bytes.q, this = #KB) 
    Protected res.q
    Select this 
      Case #KB
        res = Bytes / 1024
      Case #MB
        res = (Bytes / 1024) / 1024
      Case #GB
        res = ((Bytes / 1024) / 1024) / 1024
      Case #TB
        res = (((Bytes / 1024) / 1024) / 1024)/ 1024
    EndSelect
    ProcedureReturn res
  EndProcedure
  
  Procedure.f GetAverage(List p.f())
    Protected res.f
    ForEach p()  
      res + p()
    Next 
    ProcedureReturn res / ListSize(P())
  EndProcedure
  
  Procedure.f GetSquare(Width.f, Height.f)
    ProcedureReturn width * Height
  EndProcedure
  
  Procedure.f GetCubicVolume(Width.f, Height.f, Depth.f)
    ProcedureReturn Width * Height * Depth  
  EndProcedure
  
  Procedure.f PercentageRemain(Value.f, Percent.f)
    ProcedureReturn value - (value * Percent / 100)
  EndProcedure
  
  Procedure.f PercentageTaken(Value.f, Percent.f)
    ProcedureReturn value * Percent / 100
  EndProcedure
  
  Procedure.i CircularMovement2D(StartPosX.i, StartPosY.i, Angle.f, Radius.i, *xp.POINT)
    *xp\x = StartPosX + Cos(Angle) * Radius
    *xp\y = StartPosY + Sin(Angle) * Radius
    ProcedureReturn #True
  EndProcedure
  
  Procedure.i AbsI(num.i)
    If num < 0
      ProcedureReturn num * -1
    EndIf
    ProcedureReturn num
  EndProcedure
  
  Procedure.f AbsF(num.f)
    If num < 0
      ProcedureReturn num * -1
    EndIf
    ProcedureReturn num
  EndProcedure
  
  Procedure.d radtodeg(Rad.d)
    ProcedureReturn Rad * 180 / #PI
  EndProcedure
  
  Procedure.d PointDirection(x.d, y.d, x2.d, y2.d)
    ProcedureReturn Degree(ATan2(y-y2, x2-x))
  EndProcedure
  
  Procedure.d ColorDistance(*col1._RGB, *col2._RGB)
    ProcedureReturn Sqr(Pow(*col1\R - *col2\R, 2) + Pow(*col1\G - *col2\G, 2) + Pow(*col1\B - *col2\B, 2))
  EndProcedure  ;purpose: To calculate the angle of an object from an arbitrary point (origin) in 2D space
                ;input:    origin - the location of the origin
                ;          P1 - the location of the object
                ;output: the angle from the origin to the object in degrees
  Procedure.f calculateRelativeAngle2D(*origin.POINT, *P1.POINT)
    Protected  ang.f, calc.f
    calc = (*P1\y - *origin\y) / (*P1\x - *origin\x)
    ang = Degree(ATan(calc))
    
    If *P1\y < *origin\y And *P1\x > *origin\x
      ProcedureReturn ang  ;angle is in the first quadrant
    ElseIf (*P1\y < *origin\y And *P1\x < *origin\x) Or (*P1\y > *origin\y And *P1\x < *origin\x)
      ProcedureReturn ang + 180 ;angle is in the second Or third quadrant
    Else
      ProcedureReturn ang + 360 ;angle is in the fourth quadrant
    EndIf
  EndProcedure
  
  ;The center inside a triangle
  Procedure TriangleCtr(*PtCtr.pt3f, *Pt1.pt3f, *Pt2.pt3f, *Pt3.pt3f)
  ;#-----------------------------------------------------------------
  
                 *PtCtr\x = ( (*Pt1\x + *Pt2\x + *Pt3\x) / 3)
                 *PtCtr\y = ( (*Pt1\y + *Pt2\y + *Pt3\y) / 3)
                 *PtCtr\z = ( (*Pt1\z + *Pt2\z + *Pt3\z) / 3)
               EndProcedure  
               
  ;rotate one point around another point
  Procedure RotatePt2d(*pt1.pt2d, *pt2.pt2d, dAng.d)
    ;#-----------------------------------------------
    ;Rotate pt2 Anti-Clockwise about pt1
    Protected dAngRad.d = Radian(dAng)
    Protected dDx.d, dDy.d
    
    dDx = (*pt2\x - *pt1\x)
    dDy = (*pt2\y - *pt1\y)
    
    *pt2\x = Cos(dAngRad) * dDx - Sin(dAngRad) * dDy + *pt1\x
    *pt2\y = Sin(dAngRad) * dDx + Cos(dAngRad) * dDy + *pt1\y
  EndProcedure  
  
  ;Returns the distance between two objects in 3D space  
  Procedure.f FastDist(x1.f, y1.f, z1.f, x2.f, y2.f, z2.f)
    Protected x3.f, y3.f, z3.f, dist.f
    x3.f = x1-x2:x3 = x3*x3
    y3.f = y1-y2:y3 = y3*y3
    z3.f = z1-z2:z3 = z3*z3
    dist.f = x3+y3+z3
    ProcedureReturn  dist
  EndProcedure
  
  ;returns the distance between two supplied points p and q
  Procedure.d Distance(*p.POINT, *q.POINT)
    Protected dx.d , dy.d, dist.d
    dx = *p\x - *q\x                  ;horizontal difference
    dy = *p\y - *q\y                  ;vertical difference
    dist = Sqr(dx*dx + dy*dy )        ;distance using Pythagoras theorem
    ProcedureReturn dist
  EndProcedure
  
  ;distance from a point to a vertical line
  Procedure.i FindDist2VertLine(px.f, lx.f)
    Protected distance.i
    distance = Abs(Px) - Abs(Lx)
    ProcedureReturn distance
  EndProcedure
  
  ;distance from a point to a horizontal line
  Procedure.i FindDist2HorizLine(py.f, ly.f)
    Protected distance.i
    distance = Abs(Py) - Abs(Ly)
    ProcedureReturn distance
  EndProcedure
  
  ;Find the slope of a line
  Procedure.f FindSlopeOfLine(*p1.POINT, *p2.POINT)
    Protected slope.f
    slope.f = (*p1\y - *p2\y) / (*p1\x + *p2\x)
    ProcedureReturn slope
  EndProcedure
  
  ;This function will calculate the acceleration in seconds.
  Procedure.f CalculateAccelerationSeconds(startVelocity.f, finalVelocity.f , time.f)
    ProcedureReturn (finalVelocity-startVelocity) / time
  EndProcedure	
  
  ;purpose: calculate final velocity, given initial velocity, acceleration and time
  ; input:   vi initial velocity
  ;          a  acceleration
  ;          t  time
  ; output:  our final velocity
  Procedure.f  EqOne_vf(vi.f, a.f, t.f)
    ProcedureReturn vi + a * t
  EndProcedure	
  
  ;purpose: calculate change in distance, given final velocity, initial velocity And time
  ; input:   vf final velocity
  ;          vi initial velocity
  ;          t  time
  ; output:  our change in distance
  Procedure.f EqTwo_x(vf.f, vi.f, t.f)
    ProcedureReturn  0.5 * (vf - vi) / t
  EndProcedure	
  
  ;purpose: calculate change in distance, given initial velocity, acceleration and time
  ; input:   vi initial velocity
  ;          t  time
  ;          a  acceleration
  ; output:  our change in distance
  Procedure.f EqThree_x(vi.f, t.f, a.f)
    ProcedureReturn vi * t + 0.5 * a * t * t
  EndProcedure	
  
  ;purpose: To determine whether an object on an incline will slide
  ; input:   angle       - the current angle of the incline
  ;            weight     - the weight of the object
  ;            fric_coeff - the coefficient of Static friction between surfaces
  ; output:  true If the object should slide, Else false
  Procedure CheckForMotion(angle.f, weight.f, fric_coeff.f)
    Protected normal.f, perpForce.f, stat_friction.f
    ; Calculate the normal force being exerted by the ramp
    normal = weight * Cos(angle * #PI / 180)
    ; Calculate the force perpendicular To the normal
    perpForce = weight * Sin(angle * #PI / 180)
    ; Calculate the amount of Static friction keeping the object at rest
    stat_friction = fric_coeff * normal
    ; Return true If the object should slide, Else false
    If perpForce > stat_friction
      ProcedureReturn #True
    Else
      ProcedureReturn #False
    EndIf
  EndProcedure	
  
  ;purpose: To determine whether an object on an incline will slide
  ;             and how fast the object should accelerate
  ; input:   angle - the current angle of the incline
  ;            weight - the weight of the object
  ;            fric_coeff - the coefficient of kinetic friction between surfaces
  ;            mass - the mass of the object
  ; output:  the acceleration of the object
  Procedure.f CalcAccel(angle.f, weight.f, fric_coeff.f, mass.f)
    Protected normal.f, perpForce.f, kin_friction.f, total_force.f
    ;Calculate the normal force being exerted by the object
    normal = weight * Cos(angle * #PI / 180)
    ; Calculate the force perpendicular To the normal
    perpForce = weight * Sin(angle * #PI / 180)
    ;Calculate the amount of Static friction keeping the object at rest
    kin_friction = fric_coeff * normal
    ;Calculate the sum of forces acting upon the object
    total_force = perpForce - kin_friction
    ;Return the acceleration of the object
    ProcedureReturn total_force / mass
  EndProcedure
  
  ;Here is a procedure that returns the amount of work done given a force,
  ;a friction force, And a displacement
  Procedure.f CalculateWork(force.f, friction.f, displacement.f)
    Protected netForce.f, temp.f
    ;calculate the difference of the forces.
    netForce.f = force-friction
    
    ;multiply by displacement
    temp.f = displacement * netForce
    ; Returns the value of the work in Joules
    ProcedureReturn temp
  EndProcedure	
  
  Procedure.f CalculateKineticEnergy(mass.f, speed.f)
    Protected KE.f = (mass/2)*(Pow(speed,2))
    ProcedureReturn KE
  EndProcedure	
  
  Procedure.f CalculateAngledWork(*obj.vector2D, friction.f, displacement.f)
    Protected temp.f, horizForce.f, work.f
    ;don't forget to convert to rads....
    temp.f = Cos(Radian(*obj\y))
    
    ;calculate the horizontal force;
    horizForce.f = *obj\x * temp
    
    work.f = calculateWork(horizForce,friction, displacement) ; Procedure is above an previous post
    
    ProcedureReturn work ;return the amount of work done considering an angled force:
  EndProcedure
  
  ;calculation For potential energy
  ; Example: A book weighs 1.5 pounds, and it is raised 2 meters off the ground
  ; formula: 1.5lbs (1N/0.2248lbs)  -  1N = 1kg*m/s2
  Procedure.f CalculatePotentialEnergy(mass.f ,height.f)
    ;PE = Potential energy
    Protected PE.f = mass * #GRAVITY * height
    ProcedureReturn PE
  EndProcedure	 
  
  Procedure.i Random32bit()
    ProcedureReturn (Random($FFFF) << 16) | Random($FFFF)
  EndProcedure

  ;Negative and positive extremes allowed 
  Procedure.f RandomF(Min.f, Max.f, Res.i = 100000)
    ProcedureReturn (Min + (Max - Min) * Random(Res) / Res)
  EndProcedure
  
  ;Negative and positive extremes allowed
  Procedure.i RandomI(min.i, Max.i, Res.i = 100000)
    ProcedureReturn (Min + (Max - Min) * Random(Res) / Res)
  EndProcedure
  
  ;Circular orbilat calculations 2D  
  Procedure OrbitCalc2D(*ReturnVec.vector2D, CenterX.f, CenterY.f, AngleX.f, AngleY.f, Radius.i)
    *ReturnVec\X = CenterX + Radius*Cos(AngleY)*Cos(AngleX)
    *ReturnVec\Y = CenterY + Radius*Sin(AngleX)
  EndProcedure
  
  
  ;Circular orbital calculations
  Procedure OrbitCalc3D(*ReturnVec.Vector3D, CenterX.f, CenterY.f, CenterZ.f, AngleX.f, AngleY.f, Radius.i)
    *ReturnVec\X = CenterX + Radius*Cos(AngleY)*Cos(AngleX)
    *ReturnVec\Y = CenterY + Radius*Sin(AngleX)
    *ReturnVec\Z = CenterZ + Radius*Sin(AngleY)*Cos(AngleX)
  EndProcedure
  
  ;Elliptic orbital calculations
  Procedure EOrbitCalc3D(*ReturnVec.Vector3D, CenterX.f, CenterY.f, CenterZ.f, AngleX.f, AngleY.f, RadiusX.i, RadiusY.i, RadiusZ.i )
    *ReturnVec\X = CenterX + RadiusX*Cos(AngleY)*Cos(AngleX)
    *ReturnVec\Y = CenterY + RadiusY*Sin(AngleX)
    *ReturnVec\Z = CenterZ + RadiusZ*Sin(AngleY)*Cos(AngleX)
  EndProcedure
  
  ;Example for Projectile Trajectory	 
  Procedure Projectile_Trajectory(Screen_Bottom.i, Initial_vel.f, Initial_Angle.f)
    Protected x_pos.f = 0                         ;starting point of projectile
    Protected y_pos.f = Screen_Bottom             ;bottom of screen
    Protected y_velocity.f = 0                    ;initial y velocity
    Protected x_velocity.f = 0                    ;constant x velocity
    Protected gravity.f = 1                       ;do want To fall too fast
    Protected  velocity.f = Initial_vel            ;whatever
    Protected angle.f = Initial_Angle             ;whatever, must be in radians
                                                  ;compute velocities in x,y
    x_velocity = velocity*Cos(angle)
    y_velocity = velocity*Sin(angle)
    ;do projectile loop Until object hits
    ;bottom of screen at Screen_Bottom
    While(y_pos < Screen_Bottom)
      ; update position
      x_pos + x_velocity
      y_pos + y_velocity
      ;update velocity
      y_velocity + gravity
    Wend
  EndProcedure		 
  
  ;purpose:  To convert a vector from magnitude/direction To component form
  ;input:    vec- a vector in magnitude/direction form
  ;output:   our converted vector
  Procedure V2Dvector_comp_PolarToCompConversion(*vec._2Dvector_pol)
    ;temporary variable which will hold the answer
    Protected  temp.vector2D
    ;Fill in our values
    temp\x = *vec\mag * Cos(*vec\dir * #PI / 180)
    temp\y = *vec\mag * Sin(*vec\dir * #PI / 180)
    ProcedureReturn @temp
  EndProcedure
  
  ;purpose:  To convert a vector from component To magnitude/direction form
  ;input:    vec- a vector in component form
  ;output:   our converted vector
  Procedure V2Dvector_polar_CompToPolarConversion(*vec.vector2D)
    ;temporary variable which will hold our answer
    Protected temp._2Dvector_pol
    ;Calculate our magnitude using the Pythagorean theorom
    temp\mag = Sqr(*vec\x * *vec\x + *vec\y * *vec\y)
    ;Error check To prevent a divide-by-zero
    If temp\mag = 0
      ProcedureReturn @temp
    EndIf
    ;Calculate our angle. We are using ASin() which will Return an angle
    ;in either the 1st Or the 4th quadrant
    temp\dir = (180 / #PI) * ASin(*vec\y / temp\mag)
    ;Adjust our angle in the event that it lies in the 2nd Or 3rd quadrant
    If *vec\x < 0
      temp\dir + 180
      ;Adjust our angle in the event that it lies in the 4th quadrant
    ElseIf *vec\x > 0 And *vec\y < 0
      temp\dir + 360
    EndIf
    
    ProcedureReturn @temp
  EndProcedure
  
  ;calculate the angular displacement given the arc length and radius
  Procedure.f AngleDisplacement(arc.f, radius.f)
    Protected theta.f = arc/radius
    ProcedureReturn theta
  EndProcedure	
  
  ;Average Angular Velocity
  Procedure.f AvgAngularVelocity(arcStart.f, arcEnd.f, time.f, radius.f)
    Protected initialDisplacement.f, endDisplacement.f,omega.f
    ;calculate the angular displacement.
    initialDisplacement = arcStart/radius
    endDisplacement = arcEnd/radius
    omega = (endDisplacement - initialDisplacement) / time
    ProcedureReturn omega
  EndProcedure	
  
  ;Average angular acceleration
  Procedure.f AvgAngAcceleration(angVelBegin.f, angVelEnd.f, time.f)
    Protected alpha.f
    alpha = (angVelEnd - angVelBegin)/time
    ProcedureReturn alpha
  EndProcedure	
  
  ;Tangential velocity
  Procedure.f TangVelocity(omega.f, radius.f)
    Protected  velT.f
    velT = omega*radius
    ProcedureReturn velT
  EndProcedure	
  
  Procedure.f LinearSpeed(mass.f, initialHeight.f, inertia.f)
    Protected energy.f = 0.0, halfMass.f, halfInertiaMass.f, linearSpeed.f ,temp.f = 0.0
    ;first figure out what is known For sure.
    energy = mass*initialHeight*#GRAVITY ; Define GRAVITY yourself..
                                         ;this term is used To hold the math equivalent of 1/2(m)vf^2
    halfMass = mass/2
    ;this term hold on To the formula equivalent of
    ;1/2(inertia)*(mass) r^2 * wf^2
    halfInertiaMass = inertia*mass/2
    ;make a holding place.
    temp = energy/(halfMass+halfInertiaMass)
    ;take the square root To find the speed in m/s
    linearSpeed = Sqr(temp)
    ProcedureReturn linearSpeed
  EndProcedure	
  
  ;here is a procedure that converts from Euler angles (roll, pitch, And yaw) To quaternion
  Procedure EulerToQuat(roll.f, pitch.f, yaw.f, *quat.quaternion)
    Protected cr.f, cp.f, cy.f, sr.f, sp.f, sy.f, cpcy.f, spsy.f
    ;compute all trigonometric values used To compute the quaternion
    cr = Cos(roll/2)
    cp = Cos(pitch/2)
    cy = Cos(yaw/2)
    
    sr = Sin(roll/2)
    sp = Sin(pitch/2)
    sy = Sin(yaw/2)
    
    cpcy = cp * cy
    spsy = sp * sy
    
    ;combine values To generate the vector And scalar For the quaternion
    *quat\w = cr * cpcy + sr * spsy
    *quat\x = sr * cpcy - cr * spsy
    *quat\y = cr * sp * cy + sr * cp * sy
    *quat\z = cr * cp * sy - sr * sp * cy
  EndProcedure	
  
  ;input:  P1 - representing point 1
  ;        P2 - representing point 2
  ;output: The slope between our 2 points
  Procedure.f SlopeBetweenPoints(*P1.POINT, *P2.POINT)
    Protected temp.f
    temp = (*P2\y - *P1\y) / (*P2\x - *P1\x)
    ProcedureReturn temp
  EndProcedure	
  
  ;purpose: calculate the midpoint of a line segment
  ;input: P1 - representing point 1
  ;       P2 - representing point 2
  ;output: midpoint between the two points
  Procedure FindThe2DMidPoint(*P1.POINT, *P2.POINT)
    Protected temp.POINT
    ;Calculate our midpoint
    temp\x = (*P1\x + *P2\x) / 2.0
    temp\y = (*P1\y + *P2\y) / 2.0
    ProcedureReturn @temp
  EndProcedure	
  
  ;purpose: calculate the midpoint of a line segment in 3D
  ;input: P1- point 1 (x,y,z)
  ;       P2- point 2
  ;output: the midpoint between the two points
  Procedure.f FindThe3DMidPoint(*P1.vector3D, *P2.vector3D)
    Protected temp.vector3D
    ;Calculate our midpoint
    temp\x = (*P1\x + *P2\x) / 2.0
    temp\y = (*P1\y + *P2\y) / 2.0
    temp\z = (*P1\z + *P2\z) / 2.0
    ProcedureReturn @temp
  EndProcedure	
  
  ;purpose: To detect a collision between 2 spheres
  ;input  : S1 - our first sphere
  ;         S2 - our second sphere
  ;output : True if there is a collision othewise False
  Procedure  CollisionBetweenSpheres(*S1._Sphere, *S2._Sphere)
    If (Pow(*S2\x - *S1\x,2) + Pow(*S2\y - *S1\y,2) + Pow(*S2\z - *S1\z,2) < Pow(*S1\radius + *S2\radius,2))
      ProcedureReturn #True
    Else
      ProcedureReturn #False
    EndIf
  EndProcedure	
  
  ;purpose: To calculate the angle between 2 objects in 2D space
  ;input:    P1 - the location of the first object
  ;          P2 - the location of the second object
  ; output: the angle between the objects in degrees
  Procedure.f CalculateAngle2D(*P1.POINT, *P2.POINT, rad.d)
    Protected  ang.f = 0.0, calc.f = 0.0
    calc = (*P2\y - *P1\y) / (*P2\x - *P1\x) 
    ang = ATan(calc) * Degree(rad)
    ;In the event that the angle is in the first quadrant
    If *P2\y < *P1\y And *P2\x > *P1\x
      ProcedureReturn ang
    ElseIf (*P2\y < *P1\y And *P2\x < *P1\x) Or (*P2\y > *P1\y And *P2\x < *P1\x)
      ;In the event of second Or third quadrant
      ProcedureReturn ang + 180
    Else
      ;If none of the above, it must be in the fourth
      ProcedureReturn ang + 360
    EndIf
  EndProcedure	
  
  ;purpose: To calculate the weight of an object based on its mass
  ;input:   mass - the mass of the object
  ;         grav - the amount of constant acceleration due To gravity
  ;output:  an structure with 3 floats representing the vector of weight
  Procedure CalcWeight3D(*obj.vector3D, mass.f, gravi.f)
    ;The value in y will be the only number changed, since gravity
    ;is only applied along the Y axis
    ;Calculate the weight, it is assumed that grav(ity) is a negative number
    *obj\y = mass * gravi
  EndProcedure
  
  ;Purpose: To find the momentum of object with a given mass,travelling at a certain velocity
  Procedure.f Momentum(velocity.f, mass.f)
    Protected momentum.f
    momentum = mass * velocity
    ProcedureReturn momentum
  EndProcedure	
  
  ;Pass velocity And time and return resulting displacement.
  Procedure.f CalcDisplacement(velocity.f, _time.f)
    ProcedureReturn velocity * _time
  EndProcedure
  
  ;Pass the old position , velocity And time and return new position specified by time.
  Procedure.f CalcPosition(oldPosition.f, velocity.f, _time.f)
    ProcedureReturn oldPosition + (velocity * _time)
  EndProcedure
  
  Procedure.f CalcAverageVelocity(_start.f , _End.f, time.f)
    ProcedureReturn (_End - _start) / time
  EndProcedure	
  ;Work = Force * Distance moved in the direction of the force
  ;Ohms law procedure
  Procedure.f Ohm_Law(value1.f, value2.f, CalcType.i = 0)
    Protected result.f
    Select CalcType
      Case 0     ;Voltage    -     value1 = current : value2 = resistance
        result = value1 * value2
      Case 1     ;Current    -     value1 = voltage : value2 = resistance
        result = value1 / value2
      Case 2     ;Resistance -     value1 = voltage : value2 = current
        result = value1 / value2
    EndSelect
    ProcedureReturn result
  EndProcedure
  
  Procedure ConvertDaysToSeconds(Days.i)
    Protected seconds = Days * #HOURS_TO_DAY * #HOURS_TO_MIN * #MIN_TO_SEC
    ProcedureReturn seconds
  EndProcedure
  
  Procedure.f ConvertMilesToMeters(Miles.f)
    Protected meters.f = Miles * #KM_TO_MILES * #KM_TO_METERS
    ProcedureReturn meters	
  EndProcedure		
  
  Procedure.f ConvertSpeedFromMiles(Miles.f)
    Protected meters.f = (Miles * #KM_TO_MILES * #KM_TO_METERS) / (#HOURS_TO_MIN * #MIN_TO_SEC)
    ProcedureReturn meters
  EndProcedure
  
  Procedure.f ConvertAccelerationMilesToMeters(Miles.f)
    Protected aclMet.f = (Miles * #KM_TO_MILES * #KM_TO_METERS) / (#HOURS_TO_MIN * #MIN_TO_SEC * #HOURS_TO_MIN *#MIN_TO_SEC)		
    ProcedureReturn aclMet
  EndProcedure
  
  Procedure.f CelciusToFahrenheit(cels.f)
    Protected  fahren.F
    If cels < #MINIMUM_CELCIUS
      ProcedureReturn -1
    Else
      fahren = (9.0 / 5.0) * cels + 32
      ProcedureReturn fahren
    EndIf
  EndProcedure
  
  Procedure.f FarenheitToCelcius(Fahren.f)
    Protected celsius = ((Fahren - 32) * 5) / 9
    ProcedureReturn celsius
  EndProcedure
  
  Procedure.d Fibonacci()
    Protected x, sum
    Protected TheNext.d = 0
    Protected TheLast.d = 1
    For x = 0 To 45
      sum = TheNext + Thelast
      TheNext = Thelast
      TheLast = sum
      Debug TheLast
    Next x
  EndProcedure
  
  Procedure.f CalculateEnergyForWaterToBoil(Liters.f, InitTemp.f, FinalTemp.f)
    ;Energy = Joules
    Protected Energy.f = Liters * (FinalTemp - InitTemp) * 4184.0		
    ProcedureReturn Energy
  EndProcedure
  
  
  Procedure.i LineRotationEndPosition2D(*o.LINE_Vec2D_Rotate)
    Protected cDgr = 360 - *o\Rotate + 180
    *o\EndPosX = *o\midPointX + Sin(cDgr * (2 * #PI / 360))
    *o\EndPosY = *o\midPointY + Cos(cDgr * (2 * #PI / 360))
    If *o\LineLen > 0
      *o\EndPosX * *o\LineLen
      *o\EndPosY * *o\LineLen
    EndIf
    
  EndProcedure
  
EndModule
From other excellent coders (used wayback machine)

Code: Select all

; BY FOZ
; ################################################################### ;
;/
;/  Vector Maths
;/
; ################################################################### ;

Structure Vector
  X.f
  Y.f
  Z.f
EndStructure

Procedure Vector_Add(*ReturnVector.Vector, *V1.Vector, *V2.Vector)
  *ReturnVector\X = *V1\X + *V2\X
  *ReturnVector\Y = *V1\Y + *V2\Y
  *ReturnVector\Z = *V1\Z + *V2\Z
EndProcedure

Procedure Vector_Subtract(*ReturnVector.Vector, *V1.Vector, *V2.Vector)
  *ReturnVector\X = *V1\X - *V2\X
  *ReturnVector\Y = *V1\Y - *V2\Y
  *ReturnVector\Z = *V1\Z - *V2\Z
EndProcedure

Procedure Vector_CrossProduct(*ReturnVector.Vector, *V1.Vector, *V2.Vector)
  *ReturnVector\X = *V1\Y * *V2\Z - *V2\Y * *V1\Z
  *ReturnVector\Y = *V1\Z * *V2\X - *V2\Z * *V1\X
  *ReturnVector\Z = *V1\X * *V2\Y - *V2\X * *V1\Y
EndProcedure

Procedure.f Vector_DotProduct(*V1.Vector, *V2.Vector)
  ProcedureReturn (*V1\X * *V2\X) + (*V1\Y * *V2\Y) + (*V1\Z * *V2\Z)
EndProcedure

Procedure.f Vector_Length(X.f, Y.f, Z.f)
  ProcedureReturn Sqr(X * X + Y * Y + Z * Z)
EndProcedure

Procedure Vector_Normalize(*NormVector.Vector)
  length.f = Vector_Length(*NormVector\X, *NormVector\Y, *NormVector\Z)
 
  *NormVector\X = *NormVector\X / length
  *NormVector\Y = *NormVector\Y / length
  *NormVector\Z = *NormVector\Z / length
EndProcedure


; ################################################################### ;
;/
;/  Matrix Maths
;/
; ################################################################### ;

Structure Matrix4
  W1.f
  X1.f
  Y1.f
  Z1.f
  W2.f
  X2.f
  Y2.f
  Z2.f
  W3.f
  X3.f
  Y3.f
  Z3.f
  W4.f
  X4.f
  Y4.f
  Z4.f
EndStructure

Procedure Matrix_Multiply(*NewMatrix.Matrix4, *M.Matrix4, *L.Matrix4)
  *NewMatrix\W1 = *M\W1 * *L\W1 + *M\X1 * *L\W2 + *M\Y1 * *L\W3 + *M\Z1 * *L\W4
  *NewMatrix\X1 = *M\W2 * *L\W1 + *M\X2 * *L\W2 + *M\Y2 * *L\W3 + *M\Z2 * *L\W4
  *NewMatrix\Y1 = *M\W3 * *L\W1 + *M\X3 * *L\W2 + *M\Y3 * *L\W3 + *M\Z3 * *L\W4
  *NewMatrix\Z1 = *M\W4 * *L\W1 + *M\X4 * *L\W2 + *M\Y4 * *L\W3 + *M\Z4 * *L\W4
 
  *NewMatrix\W2 = *M\W1 * *L\X1 + *M\X1 * *L\X2 + *M\Y1 * *L\X3 + *M\Z1 * *L\X4
  *NewMatrix\X2 = *M\W2 * *L\X1 + *M\X2 * *L\X2 + *M\Y2 * *L\X3 + *M\Z2 * *L\X4
  *NewMatrix\Y2 = *M\W3 * *L\X1 + *M\X3 * *L\X2 + *M\Y3 * *L\X3 + *M\Z3 * *L\X4
  *NewMatrix\Z2 = *M\W4 * *L\X1 + *M\X4 * *L\X2 + *M\Y4 * *L\X3 + *M\Z4 * *L\X4
 
  *NewMatrix\W3 = *M\W1 * *L\Y1 + *M\X1 * *L\Y2 + *M\Y1 * *L\Y3 + *M\Z1 * *L\Y4
  *NewMatrix\X3 = *M\W2 * *L\Y1 + *M\X2 * *L\Y2 + *M\Y2 * *L\Y3 + *M\Z2 * *L\Y4
  *NewMatrix\Y3 = *M\W3 * *L\Y1 + *M\X3 * *L\Y2 + *M\Y3 * *L\Y3 + *M\Z3 * *L\Y4
  *NewMatrix\Z3 = *M\W4 * *L\Y1 + *M\X4 * *L\Y2 + *M\Y4 * *L\Y3 + *M\Z4 * *L\Y4
 
  *NewMatrix\W4 = *M\W1 * *L\Z1 + *M\X1 * *L\Z2 + *M\Y1 * *L\Z3 + *M\Z1 * *L\Z4
  *NewMatrix\X4 = *M\W2 * *L\Z1 + *M\X2 * *L\Z2 + *M\Y2 * *L\Z3 + *M\Z2 * *L\Z4
  *NewMatrix\Y4 = *M\W3 * *L\Z1 + *M\X3 * *L\Z2 + *M\Y3 * *L\Z3 + *M\Z3 * *L\Z4
  *NewMatrix\Z4 = *M\W4 * *L\Z1 + *M\X4 * *L\Z2 + *M\Y4 * *L\Z3 + *M\Z4 * *L\Z4
EndProcedure

Procedure Matrix_FromEuler(*ReturnMatrix.Matrix4, angle_x.f, angle_y.f, angle_z.f)
  Protected.f A,b,C,D,E,f,AD,BD
 
  A       = Cos(angle_x)
  b       = Sin(angle_x)
  C       = Cos(angle_y)
  D       = Sin(angle_y)
  E       = Cos(angle_z)
  f       = Sin(angle_z)
  AD      =   A * D
  BD      =   b * D
 
  *ReturnMatrix\W1 =   C * E
  *ReturnMatrix\X1 =  -C * f
  *ReturnMatrix\Y1 =   D
  *ReturnMatrix\W2 =  BD * E + A * f
  *ReturnMatrix\X2 = -BD * f + A * E
  *ReturnMatrix\Y2 =  -b * C
  *ReturnMatrix\W3 = -AD * E + b * f
  *ReturnMatrix\X3 =  AD * f + b * E
  *ReturnMatrix\Y3 =   A * C
 
  *ReturnMatrix\Z1 = 0
  *ReturnMatrix\Z2 = 0
  *ReturnMatrix\Z3 = 0
  *ReturnMatrix\W4 = 0
  *ReturnMatrix\X4 = 0
  *ReturnMatrix\Y4 = 0
 
  *ReturnMatrix\Z4 =  1
EndProcedure

; ################################################################### ;
;/
;/  Quaternion Maths
;/
; ################################################################### ;

Structure Vector
  X.f
  Y.f
  Z.f
EndStructure

Structure Matrix4
  W1.f
  X1.f
  Y1.f
  Z1.f
  W2.f
  X2.f
  Y2.f
  Z2.f
  W3.f
  X3.f
  Y3.f
  Z3.f
  W4.f
  X4.f
  Y4.f
  Z4.f
EndStructure

Structure Quaternion
  X.f
  Y.f
  Z.f
  W.f
EndStructure

Procedure Quaternion_ToMatrix(*ReturnMatrix.Matrix4, *q.Quaternion)
  *ReturnMatrix\W1 = 1.0 - 2.0 * ( *q\Y * *q\Y + *q\Z * *q\Z );
  *ReturnMatrix\X1 = 2.0 * (*q\X * *q\Y + *q\Z * *q\w);
  *ReturnMatrix\Y1 = 2.0 * (*q\X * *q\Z - *q\Y * *q\w);
  *ReturnMatrix\Z1 = 0.0;
 
  ; Second row
  *ReturnMatrix\W2 = 2.0 * ( *q\X * *q\Y - *q\Z * *q\w );
  *ReturnMatrix\X2 = 1.0 - 2.0 * ( *q\X * *q\X + *q\Z * *q\Z );
  *ReturnMatrix\Y2 = 2.0 * (*q\Z * *q\Y + *q\X * *q\w );
  *ReturnMatrix\Z2 = 0.0;
 
  ; Third row
  *ReturnMatrix\W3 = 2.0 * ( *q\X * *q\Z + *q\Y * *q\w );
  *ReturnMatrix\X3 = 2.0 * ( *q\Y * *q\Z - *q\X * *q\w );
  *ReturnMatrix\Y3 = 1.0 - 2.0 * ( *q\X * *q\X + *q\Y * *q\Y );
  *ReturnMatrix\Z3 = 0.0;
 
  ; Fourth row
  *ReturnMatrix\W4 = 0;
  *ReturnMatrix\X4 = 0;
  *ReturnMatrix\Y4 = 0;
  *ReturnMatrix\Z4 = 1.0;
EndProcedure

Procedure Quaternion_ToEular(*ReturnEular.Vector, *q.Quaternion)
  Protected test.f = *q\X * *q\Y + *q\Z * *q\w;
  Protected.f heading, attitude, bank
 
  If (test > 0.499) ; singularity at north pole
    heading = 2 * ATan2(*q\X, *q\w);
    attitude = #PI/2;
    bank = 0;
  ElseIf (test < -0.499) ; singularity at south pole
    heading = -2 * ATan2(*q\X, *q\w);
    attitude = - #PI/2;
    bank = 0;
  Else
    Protected sqx.f = *q\X * *q\X;
    Protected sqy.f = *q\Y * *q\Y;
    Protected sqz.f = *q\Z * *q\Z;
   
    heading = ATan2(2 * *q\Y * *q\w - 2 * *q\X * *q\Z, 1 - 2 * sqy - 2 * sqz);
    attitude = ASin(2 * test);
    bank = ATan2(2 * *q\X * *q\w - 2 * *q\Y * *q\Z, 1 - 2 * sqx - 2 * sqz)
  EndIf
 
  *ReturnEular\Z = heading
  *ReturnEular\Y = bank - #PI/2
  *ReturnEular\X = attitude
EndProcedure

Procedure.f Quaternion_Length(*TempQuat.Quaternion)
  ProcedureReturn Sqr(*TempQuat\w * *TempQuat\w  +  *TempQuat\X * *TempQuat\X  +  *TempQuat\Y * *TempQuat\Y  +  *TempQuat\Z * *TempQuat\Z)
EndProcedure

Procedure Quaternion_Conjugate(*NewQuat.Quaternion, *Quat1.Quaternion)
  *NewQuat\X = -1 * *Quat1\X
  *NewQuat\Y = -1 * *Quat1\Y
  *NewQuat\Z = -1 * *Quat1\Z
  *NewQuat\w =      *Quat1\w
EndProcedure

Procedure Quaternion_Multiply(*NewQuat.Quaternion, *Quat1.Quaternion, *Quat2.Quaternion)
  *NewQuat\X =  *Quat1\X * *Quat2\w  +  *Quat1\Y * *Quat2\Z  -  *Quat1\Z * *Quat2\Y  +  *Quat1\w * *Quat2\X
  *NewQuat\Y = -*Quat1\X * *Quat2\Z  +  *Quat1\Y * *Quat2\W  +  *Quat1\Z * *Quat2\X  +  *Quat1\w * *Quat2\Y
  *NewQuat\Z =  *Quat1\X * *Quat2\Y  -  *Quat1\Y * *Quat2\X  +  *Quat1\Z * *Quat2\W  +  *Quat1\w * *Quat2\Z
  *NewQuat\w = -*Quat1\X * *Quat2\X  -  *Quat1\Y * *Quat2\Y  -  *Quat1\Z * *Quat2\Z  +  *Quat1\w * *Quat2\w
EndProcedure

Procedure Quaternion_Normalize(*TempQuat.Quaternion)
  TEMP_length.f = Quaternion_Length(*TempQuat)
  *TempQuat\X = *TempQuat\X / TEMP_length
  *TempQuat\Y = *TempQuat\Y / TEMP_length
  *TempQuat\Z = *TempQuat\Z / TEMP_length
  *TempQuat\w = *TempQuat\w / TEMP_length
EndProcedure

Procedure Quaternion_ApplyVector(*quat.Quaternion, *vecin.Vector, *vecout.Vector)
  Protected vecQuat.Quaternion, qResult.Quaternion, qTemp.Quaternion
  vecQuat\X = *vecin\X
  vecQuat\Y = *vecin\Y
  vecQuat\Z = *vecin\Z
  vecQuat\w = 0
 
  Quaternion_Conjugate(@qTemp, @vecQuat)
 
  Quaternion_Multiply(@qResult, @vecQuat, @qTemp)
  CopyStructure(@qResult, @qTemp, QUATERNION)
 
  Quaternion_Multiply(@qResult, *Quat, @qTemp)
 
  *vecout\X = qResult\X
  *vecout\Y = qResult\Y
  *vecout\Z = qResult\Z
EndProcedure

Procedure Quaternion_FromEuler(*TempQuat.Quaternion, Yaw.f, Pitch.f, Roll.f)
  If Yaw = 0 And Pitch = 0 And Roll = 0
    *TempQuat\X = 0
    *TempQuat\Y = 0
    *TempQuat\Z = 0
    *TempQuat\w = 1
    ProcedureReturn 0
  EndIf
 
  Roll = (Roll * 0.01745329) / 2
  Pitch = (Pitch * 0.01745329) / 2
  Yaw = (Yaw * 0.01745329) / 2
 
  cosRoll.f = Cos(Roll)
  cosPitch.f = Cos(Pitch)
  cosYaw.f = Cos(Yaw)
 
  sinRoll.f = Sin(Roll)
  sinPitch.f = Sin(Pitch)
  sinYaw.f = Sin(Yaw)
 
  cosPitchYaw.f = cosPitch * cosYaw
  sinPitchYaw.f = sinPitch * sinYaw
 
  *TempQuat\X = sinRoll * cosPitchYaw - cosRoll * sinPitchYaw
  *TempQuat\Y = cosRoll * sinPitch * cosYaw + sinRoll * cosPitch * sinYaw
  *TempQuat\Z = cosRoll * cosPitch * sinYaw - sinRoll * sinPitch * cosYaw
  *TempQuat\w = cosRoll * cosPitchYaw + sinRoll * sinPitchYaw
 
  Quaternion_Normalize(*TempQuat)
EndProcedure

Procedure Quaternion_FromAngleAxis(*TempQuat.Quaternion, X.f, Y.f, Z.f, angleDegrees.f)
  If X = 0 And Y = 0 And Z = 0
    *TempQuat\X = 0
    *TempQuat\Y = 0
    *TempQuat\Z = 0
    *TempQuat\w = 1
    ProcedureReturn 0
  EndIf
 
  TEMP_angle.f = angleDegrees * 0.01745329
  TEMP_angle = TEMP_angle / 2
  TEMP_scale.f = Sin(TEMP_angle)
 
  *TempQuat\X = X * TEMP_scale
  *TempQuat\Y = Y * TEMP_scale
  *TempQuat\Z = Z * TEMP_scale
  *TempQuat\w = Cos(TEMP_angle)
 
  Quaternion_Normalize(*TempQuat)
EndProcedure

; BY NITUVIOUS
; --------------------------------------------------------
; gl_MoveObjectToPointB(Object,X,Y)
; --------------------------------------------------------
; This function moves an object to an X Y point in all
;   directions. Movement speed is based on the array's
; speed. If the point is reached then the procedure
; returns true.
; Object - Name of an array and its element
; ToX, ToY, - Destination of the object
; --------------------------------------------------------
Procedure gl_MoveObjectToPointB(*Object.objstruct,ToX.f,ToY.f)
   Static Object.objstruct
   Static distance.f

   ; -- Checking if we have reached our destination
   If *Object\x >= ToX.f-*Object\h_speed And *Object\x <= ToX.f+*Object\h_speed
         *Object\x = ToX.f
      If *Object\y >= ToY.f-*Object\v_speed And *Object\y <= ToY.f+*Object\v_speed
         *Object\y = ToY.f
         ProcedureReturn #True ; -- Return true when destination has been reached
      EndIf
   EndIf   

   ; -- Increment position until we're at our destination
   distance.f=Sqr((ToX.f-*Object\x)*(ToX.f-*Object\x)+(ToY.f-*Object\y)*(ToY.f-*Object\y));
   *Object\x=*Object\x+*Object\h_speed*(ToX.f-*Object\x)/distance.f
   *Object\y=*Object\y+*Object\v_speed*(ToY.f-*Object\y)/distance.f
   ; x = x+speed * x2 / distance
 EndProcedure
 
Procedure.f Frac(a.f)
   result.f = a.f - Round(a.f,#PB_Round_Down)
   ProcedureReturn result.f
EndProcedure

;Debug frac(2003.5)
 
 ;BY STARGÅTE
 
 ; SI-Prefix
#Yotta = 1e24
#Zetta = 1e21
#Exa   = 1e18
#Peta  = 1e15
#Tera  = 1e12
#Giga  = 1e9
#Mega  = 1e6
#Kilo  = 1e3
#Hecto = 1e2
#Deca  = 1e1
#Deci  = 1e-1
#Centi = 1e-2
#Milli = 1e-3
#Micro = 1e-6
#Nano  = 1e-9
#Pico  = 1e-12
#Femto = 1e-15
#Atto  = 1e-18
#Zepto = 1e-21
#Yocto = 1e-24

; Binary-Prefix
#Kibi  = 1<<10
#Mebi  = 1<<20
#Gibi  = 1<<30
#Tebi  = 1<<40
#Pebi  = 1<<50
#Exbi  = 1<<60

; Time-Prefix
#Minute = 60
#Hour   = 3600
#Day    = 86400
#Week   = 604800

; Gaussian Function
Procedure.f Gauss(x.f, Radius.f=1.0)
  ProcedureReturn 0.3989422804014326779*Exp(-0.5*x*x/(Radius*Radius))/Radius
EndProcedure

; Error Function
Procedure.f Erf(x.f)
  ProcedureReturn Sign(x)*Sqr(1-Exp(-x*x*(1.273239544735162686+0.1400122886866666060*x*x)/(1+0.1400122886866666060*x*x)))
EndProcedure

; Inverse Error Function
Procedure.f InvErf(x.f)
  Protected Ln.f = Log(1-x*x)*0.5
  ProcedureReturn Sign(x)*Sqr(Sqr((4.546884979448284327+Ln)*(4.546884979448284327+Ln)-Ln*14.28446044815250805)-4.546884979448284327-Ln)
EndProcedure 

; Returns a random float in the interval [0.0, Maximum]
Macro RandomFloat(Maximum=1.0)
  ( Random(2147483647)*Maximum*4.6566128752457969241e-10 ) ; Random * 1/MaxRandom
EndMacro

; Returns a random sign {-1, 1}
Macro RandomSign()
  ( Random(1)*2-1 )
EndMacro

; Returns a random angle in radian in the interval [0.0, 2*Pi[
Macro RandomAngle()
  ( Random(2147483647)*2.9258361585343193621e-9 ) ; Random * 2*Pi/(MaxRandom+1)
EndMacro

; Returns a random float in normal distribution in the interval ]-Infinity, Infinity[
Macro RandomGaussian(Variance=1.0)
  ( InvErf(RandomFloat(2)-1)*Variance*1.414213562373095049 )
EndMacro

; BY DEMIVEC

;purpose: To calculate the angle of an object from an arbitrary point (origin) in 2D space
;input:    origin - the location of the origin
;          P1 - the location of the object
;output: the angle from the origin to the object in degrees
Procedure.f calculateRelativeAngle2D(*origin.POINT, *P1.POINT)
  Protected  ang.f, calc.f
  calc = (*P1\y - *origin\y) / (*P1\x - *origin\x)
  ang = Degree(ATan(calc))

  If *P1\y < *origin\y And *P1\x > *origin\x
    ProcedureReturn ang  ;angle is in the first quadrant
  ElseIf (*P1\y < *origin\y And *P1\x < *origin\x) Or (*P1\y > *origin\y And *P1\x < *origin\x)
    ProcedureReturn ang + 180 ;angle is in the second Or third quadrant
  Else
    ProcedureReturn ang + 360 ;angle is in the fourth quadrant
  EndIf
EndProcedure

; BY IDLE

;first 3 moments of inertia 2D
;   
;   1st moment, center of a mass

;   where
;       sumx + x
;       sum y + y
;   
;    cx = sumx / area
;    cy = sumy / area
;
;   2nd moment, inertia of mass around axis       

;   where
;       sumXX  +  (X*X)
;       sumYY  +  (Y*Y)   
;       sumXY  +  (X*Y)
;   
;   IX = SumXX - (Area * (cx * cx))
;   IY = SumYY - (Area * (cy * cy))
;   IXY = Sumxy - (Area * (cx * cy))
;
;   3rd moments, ra,rb, rc or shape parameter
;   *note the shape parameter is invariant to both scale and rotation for a given identical mass 
;    and can be used to identify shapes in some cases.
 
;   ta= Sqr((2.0 * ix * iY) - (4.0 *( ixy * ixy))/2.0)
;   Ra = (ix + iy) + ta
;   Rb = (ix + iy) - ta
;   Shape = (Ra / Rb)
;
;   orientation of mass   
;   
;       where
;         mmx  = Xmax - Xmin
;         mmy = Ymax - Ymin         
;
;     If ix = iy
;             orient = 45       
;     ElseIf mmx >= mmy     
;             orient = (0.5 * (ATan(2 * (Ixy / (Iy - ix))))) / (#PI / 180)
;     Else
;           orient = (0.5 * (ATan(2 * Ixy / (ix - Iy)))) / (#PI / 180)
;     EndIf

;example below

Structure moments
    ;moments
   ;1st 
    cx.f
    cy.f
    ;2nd
    ix.f
    iy.f
    ixy.f
    ;3rd
    ra.f
    rb.f
    shape.f
    ;orientation
    orient.f 
    ;elipse
    majoraxis.f
    minoraxis.f
    ;bounds
    Xmin.i
    Xmax.i
    Ymin.i
    Ymax.i
 EndStructure
 
Procedure GetMoments(img,x1,x2,y1,y2,color,*mom.moments)
  Protected x,y,px,area.f,sumX.f,sumY.f,sumXX.f,sumYY.f,sumXY.f
  Protected ta.f,mmx.f,mmy.f,cmx.f,cmy.f,orient.f
 
  *mom\Xmin = 99999
  *mom\Ymin = 99999
 
 If StartDrawing(ImageOutput(img))
 
   For x = x1 To x2
       For y = y1 To y2
     
        px = Point(x,y) 
     
         If px = color
           
              sumX + x 
              sumY + y 
              Area + 1   
              sumXX + (x*x)
              sumYY + (y*y) 
              sumXY + (x*y) 
                               
              If x < *mom\Xmin 
                 *mom\Xmin = x
              EndIf
               
              If x > *mom\XMax
                   *mom\Xmax = x
              EndIf
               
              If y < *mom\Ymin 
                 *mom\Ymin = y
              EndIf
               
              If y > *mom\Ymax
                 *mom\Ymax = y
              EndIf
            EndIf
          Next
     Next     
     
     StopDrawing()
     
     ;1st moments cx = centerX cy=centerY
     *mom\cx = sumx / Area
     *mom\cy = sumy / Area
 
     
     ;2nd moments Ix Iy Ixy 
     *mom\ix = SumXX - (Area * (cx * cx))
     *mom\iY = SumYY - (Area * (cy * cy))
     *mom\ixY = Sumxy - (Area * (cx * cy))
                   
     ;3rd moment shape parameter invarent to scale and rotation
     ta= Sqr((2.0 * *mom\ix * *mom\iY) - (4.0 *(*mom\ixy * *mom\ixy)) * 0.5)
           
     *mom\Ra = (*mom\ix + *mom\iy) + ta
     *mom\Rb = (*mom\ix + *mom\iy) - ta
     
     *mom\Shape = (*mom\Ra / *mom\Rb)
       
     mmx = (*mom\Xmax - *mom\Xmin)
     mmy = (*mom\Ymax - *mom\Ymin)
     cmx = (*mom\Xmax + *mom\Xmin) * 0.5
     cmy = (*mom\Ymax + *mom\Ymin) * 0.5
     dmx = *mom\cx - cmx
     dmy = *mom\cy - cmy
                   
     ;orientation       
      If *mom\ix = *mom\iy
             orient = 45       
      ElseIf mmx >= mmy
             orient = (0.5 * (ATan(2 * (*mom\Ixy / (*mom\iy - *mom\ix))))) / (#PI / 180)
             *mom\majoraxis = (mmx / Cos(Abs(orient) / (180 / #PI))) * 0.5
             *mom\minoraxis = (Area) / (#PI * *mom\majoraxis)
      Else
             orient = (0.5 * (ATan(2 * *mom\Ixy / (*mom\ix - *mom\Iy)))) / (#PI / 180)
             *mom\majoraxis = (mmy / Cos(Abs(orient) / (180 / #PI))) * 0.5
             *mom\minoraxis = (Area) / (#PI * *mom\majoraxis)
      EndIf
         
      If mmx = mmy  And Abs(*mom\ix- *mom\iy) < 1000
             orient = 0
      EndIf
     
      ;messy fudge to output  0 to 360 degrees
      If *mom\ixy > 0
           If *mom\iy > *mom\ix
                If dmx > dmy
                   orient = (360 + orient) / (180/#PI)
                Else
                   orient = (180 + orient) / (180/#PI)
                EndIf
             Else
                If dmx > dmy
                  orient = (90 - orient) / (180/#PI)
                Else
                  orient = (270 - orient) / (180/#PI)
                EndIf 
             EndIf
          Else
             If *mom\iy > *mom\ix
                If dmy > dmx
                  orient = (180 + orient) / (180/#PI)
                Else
                  orient = orient / (180/#PI)
                EndIf   
             Else
                If dmx > dmy
                  orient = (90 - orient) / (180/#PI)
                Else
                  orient = (270 - orient) / (180/#PI)
                EndIf   
             EndIf
        EndIf   
                   
      If orient < 0
            orient = 0
      EndIf     
     
      *mom\orient = orient
     
   EndIf   
         
 EndProcedure    
 
 ; BY StarBootics
 
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; Project name : Plane - Module
; File Name : Plane - Module.pb
; File version: 1.0.0
; Programming : OK
; Programmed by : StarBootics
; Date : 09-03-2015
; Last Update : 02-06-2016
; PureBasic code : V5.42 LTS
; Platform : Windows, Linux, MacOS X
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
;
; This code is free to be use where ever you like
; but you use it at your own risk.
;
; The author can in no way be held responsible
; for data loss, damage or other annoying
; situations that may occur.
;
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

CompilerIf #PB_Compiler_IsMainFile
 
  IncludeFile "Vector3 - Module.pb"
 
CompilerEndIf

DeclareModule Plane
 
  Structure Plane
   
    A.f
    B.f
    C.f
    D.f
   
  EndStructure
 
  Declare Update(*PlaneA.Plane, P_A.f, P_B.f, P_C.f, P_D.f)
  Declare Reset(*PlaneA.Plane)
  Declare ReadPlane(FileID.l, *PlaneA.Plane)
  Declare WritePlane(FileID.l, *PlaneA.Plane)
  Declare.s Format(*PlaneA.Plane, Decimal.b = 3)
  Declare UnFormat(*PlaneA.Plane, Formated.s)
 
  CompilerIf Defined(Vector3, #PB_Module)
    Declare.f Distance(*PlaneA.Plane, *VectorA.Vector3::Vector3)
    Declare.f Evaluate(*PlaneA.Plane, *VectorA.Vector3::Vector3)
    Declare FromPoints(*PlaneA.Plane, *VectorA.Vector3::Vector3, *VectorB.Vector3::Vector3, *VectorC.Vector3::Vector3)
    Declare IsPointInside(*PlaneA.Plane, *VectorA.Vector3::Vector3)
  CompilerEndIf
 
EndDeclareModule

Module Plane
 
  ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  ; <<<<< L'opérateur Update <<<<<
 
  Procedure Update(*PlaneA.Plane, P_A.f, P_B.f, P_C.f, P_D.f)
   
    *PlaneA\A = P_A
    *PlaneA\B = P_B
    *PlaneA\C = P_C
    *PlaneA\D = P_D
   
  EndProcedure
 
  ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  ; <<<<< L'opérateur Reset <<<<<

  Procedure Reset(*PlaneA.Plane)
   
    *PlaneA\A = 0.0
    *PlaneA\B = 0.0
    *PlaneA\C = 0.0
    *PlaneA\D = 0.0
   
  EndProcedure

  ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  ; <<<<< Lecture sur fichier Binaire <<<<<

  Procedure ReadPlane(FileID.l, *PlaneA.Plane)
   
    *PlaneA\A = ReadFloat(FileID)
    *PlaneA\B = ReadFloat(FileID)
    *PlaneA\C = ReadFloat(FileID)
    *PlaneA\D = ReadFloat(FileID)
   
  EndProcedure

  ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  ; <<<<< Écriture sur fichier Binaire <<<<<

  Procedure WritePlane(FileID.l, *PlaneA.Plane)
   
    WriteFloat(FileID, *PlaneA\A)
    WriteFloat(FileID, *PlaneA\B)
    WriteFloat(FileID, *PlaneA\C)
    WriteFloat(FileID, *PlaneA\D)
   
  EndProcedure
 
  ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  ; <<<<< Formatage de l'équation du plan <<<<<
 
  Procedure.s Format(*PlaneA.Plane, Decimal.b = 3)
   
    ProcedureReturn StrF(*PlaneA\A, Decimal) + "x + " + StrF(*PlaneA\B, Decimal) + "y + " + StrF(*PlaneA\C, Decimal) + "z = " + StrD(*PlaneA\D, Decimal)
  EndProcedure
 
  Procedure UnFormat(*PlaneA.Plane, Formated.s)
   
    *PlaneA\A = ValF(StringField(Trim(StringField(Formated, 1, "+")), 1, "x"))
    *PlaneA\B = ValF(StringField(Trim(StringField(Formated, 2, "+")), 1, "y"))
    *PlaneA\C = ValF(StringField(Trim(StringField(StringField(Formated, 1, "="), 3, "+")), 1, "z"))
    *PlaneA\D = ValF(Trim(StringField(Formated, 2, "=")))
   
  EndProcedure

  CompilerIf Defined(Vector3, #PB_Module)
   
    ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    ; <<<<< Distance Point plan <<<<<
 
    Procedure.f Distance(*PlaneA.Plane, *VectorA.Vector3::Vector3)
   
      ProcedureReturn (*PlaneA\A * *VectorA\i + *PlaneA\B * *VectorA\j + *PlaneA\C * *VectorA\k + *PlaneA\D) / Sqr(*PlaneA\A * *PlaneA\A + *PlaneA\B * *PlaneA\B + *PlaneA\C * *PlaneA\C)
    EndProcedure
 
    ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    ; <<<<< Évaluation du plan au point spécifié <<<<<
 
    Procedure.f Evaluate(*PlaneA.Plane, *VectorA.Vector3::Vector3)
   
      ProcedureReturn *PlaneA\A * *VectorA\i + *PlaneA\B * *VectorA\j + *PlaneA\C * *VectorA\k
    EndProcedure
 
    ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    ; <<<<< Un plan passant par 3 points <<<<<
 
    Procedure FromPoints(*PlaneA.Plane, *VectorA.Vector3::Vector3, *VectorB.Vector3::Vector3, *VectorC.Vector3::Vector3)
   
      Vector3::Minus(Alpha.Vector3::Vector3, *VectorB, *VectorA)
      Vector3::Minus(Beta.Vector3::Vector3, *VectorC, *VectorA)
      Vector3::CrossProduct(Normal.Vector3::Vector3, Alpha, Beta)
      Vector3::Unit(Normal)
      CopyMemory(Normal, *PlaneA, SizeOf(Vector3::Vector3))
      *PlaneA\D = *PlaneA\A * *VectorA\i + *PlaneA\B * *VectorA\j + *PlaneA\C * *VectorA\k
   
    EndProcedure
 
    Procedure IsPointInside(*PlaneA.Plane, *VectorA.Vector3::Vector3)
   
      If *PlaneA\A * *VectorA\i + *PlaneA\B * *VectorA\j + *PlaneA\C * *VectorA\k = *PlaneA\D
        Result = #True
      Else
        Result = #False
      EndIf
   
      ProcedureReturn Result
    EndProcedure

  CompilerEndIf

EndModule

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< Code généré en : 00.001 secondes (75000.00 lignes/seconde) <<<<<
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

CompilerIf #PB_Compiler_IsMainFile

  Vector3::Update(P.Vector3::Vector3, 0.0, 0.0, 1.0)
  Vector3::Update(Q.Vector3::Vector3, 4.0, 2.0, 3.0)
  Vector3::Update(R.Vector3::Vector3, -3.0, 1.0, 1.0)
 
  Vector3::Update(S.Vector3::Vector3, -9.0, -10.0, -25.0)
  Vector3::Update(T.Vector3::Vector3, 9.0, 10.0, 25.0)
 
  Plane::FromPoints(Plane.Plane::Plane, P, Q, R)
 
  Debug Plane::Format(Plane)
  Debug Plane::Evaluate(Plane, P)
  Debug Plane::Evaluate(Plane, Q)
  Debug Plane::Evaluate(Plane, R)
 
  Debug ""
 
  Debug Plane::IsPointInside(Plane, S)
  Debug Plane::IsPointInside(Plane, T)
 
  Debug ""
 
  Debug Plane::Distance(Plane, S)
  Debug Plane::Distance(Plane, T)

CompilerEndIf
Last edited by DK_PETER on Thu Jul 22, 2021 9:52 pm, edited 3 times in total.
Current configurations:
Ubuntu 20.04/64 bit - Window 10 64 bit
Intel 6800K, GeForce Gtx 1060, 32 gb ram.
Amd Ryzen 9 5950X, GeForce 3070, 128 gb ram.
Cyllceaux
Enthusiast
Enthusiast
Posts: 458
Joined: Mon Jun 23, 2014 1:18 pm
Contact:

Re: MATH - Repost

Post by Cyllceaux »

Nice... but there are some Errors in code.
You see them, if you write "EnableExplicit" in the Module-Code

PI does not exist

Code: Select all

Procedure.f CalcAccel(angle.f, weight.f, fric_coeff.f, mass.f)
normal.f = weight * Cos(angle * PI / 180)
; Calculate the force perpendicular To the normal
perpForce.f = weight * Sin(angle * PI / 180)
Obj does not exists

Code: Select all

Procedure CalcWeight3D(*obj.vector3D, mass.f, gravi.f)
*obj\y = mass * gravi
ProcedureReturn @Obj
Missing ProcedureReturn

Code: Select all

Procedure.f ConvertSpeedFromMiles(Miles.f)
Missing RadiusLineLen

Code: Select all

Procedure.i LineRotationEndPosition2D(*o.LINE_Vec2D_Rotate)
Missing ProcedureReturn

Code: Select all

Procedure.d Fibonacci()
Cyllceaux
Enthusiast
Enthusiast
Posts: 458
Joined: Mon Jun 23, 2014 1:18 pm
Contact:

Re: MATH - Repost

Post by Cyllceaux »

(EnableExplicit - corrected)
hey... now, the DeclareModule is missing. And. EnableExplicit should in the Module Part.

Code: Select all

Module _Math
	
	EnableExplicit

Still Missing ProcedureReturn

Code: Select all

Procedure.d Fibonacci()
Procedure.f ConvertSpeedFromMiles(Miles.f)
User avatar
STARGÅTE
Addict
Addict
Posts: 2067
Joined: Thu Jan 10, 2008 1:30 pm
Location: Germany, Glienicke
Contact:

Re: MATH - Repost

Post by STARGÅTE »

Hi DK_PETER,

Did you use these procedures by your own? I ask, because many procedures work wrong!
Here are my remarks:
  • Is there a reson, why in your PointDirection() x and y is swapped in ATan2 and also one times you write y-y2 and then x2-x ?
  • Why calculateRelativeAngle2D and CalculateAngle2D() uses only ATan() instead of ATan2? Dividing / (*P1\x - *origin\x) results in error when x-difference is zero
  • In which world your FastDist() returns a distance in 3D space? Its the square of the distance.
  • I do not understand what FindDist2VertLine() is calculating and why arguments are floats and the result is an integer? Same for FindDist2HorizLine()
  • FindSlopeOfLine() is wrong, here you divide (*p1\x + *p2\x) but it should be (*p1\x - *p2\x)
  • FindThe2DMidPoint() and FindThe3DMidPoint() can't work, because you can not return a pointer @temp from a protected variable. This pointer becomes invalid after procedure is finished. Further the procedure return type is float!?
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Lizard - Script language for symbolic calculations and moreTypeface - Sprite-based font include/module
GPI
PureBasic Expert
PureBasic Expert
Posts: 1394
Joined: Fri Apr 25, 2003 6:41 pm

Re: MATH - Repost

Post by GPI »

STARGÅTE wrote: Wed Jul 21, 2021 8:40 am In which world your FastDist() returns a distance in 3D space?
In many cases you can work with squares without problems.
"distance < 2" is true, then "distance² < 4²" is also true. As long as you only want to compare distances, it is faster than calculating the square root of a number.
Bitblazer
Enthusiast
Enthusiast
Posts: 733
Joined: Mon Apr 10, 2017 6:17 pm
Location: Germany
Contact:

Re: MATH - Repost

Post by Bitblazer »

DK_PETER wrote: Mon Jul 19, 2021 7:19 pmHopefully the previous postings from the other members will reappear.
Or you use the wayback macchine.
webpage - discord chat links -> purebasic GPT4All
User avatar
DK_PETER
Addict
Addict
Posts: 898
Joined: Sat Feb 19, 2011 10:06 am
Location: Denmark
Contact:

Re: MATH - Repost

Post by DK_PETER »

@StarGate and the rest of you excellent programmers.

I haven't used the procedures for a long time and they were originally converted from C.
I'll take a look at the procedures sooner or later - perhaps update the module accordingly with new functions and corrections where needed.
Right now I don't have much time. I hope you'll find some of them usefull otherwise discard the module until i'll
update it again.
Yeah.. wayback machine - always forget that most can be found there :)
Best regards
Current configurations:
Ubuntu 20.04/64 bit - Window 10 64 bit
Intel 6800K, GeForce Gtx 1060, 32 gb ram.
Amd Ryzen 9 5950X, GeForce 3070, 128 gb ram.
Post Reply