Code: Select all
; #include <iostream>
; int main()
; {
; std::cout << "Game over math! Game over!" << std::endl;
; return 0;
; //Naaah...PB is a lot more fun than this.
; }
; This is my math snippits, which I originally posted here:
; http://www.purebasic.fr/english/viewtopic.php?f=16&t=45701
; I frequently check to see, if there's any updates, but this
; seems not to be the case. Either there are only a few here
; with the knowledge (doubt that), nobody wants to share new
; knowledge (doubt that too) or people simply just don't care
; until they stumble into an urgent need for some math related code. (Most likely and quite normal)
; I've gathered my math in a module now and added some extras. I didn't ask any
; of the other excellent guys, who were willing to donate examples
; to let me add their code, so for now
; this is my math only - encapsulated in a module.
; Hope you will find it useful, at some point -
; far..far..away...In a distant galaxy ;-)
; Please, If you have any math - ANY math at all to share..Please add it to
; sticky post located at the link above. (Or not...Your choice naturally :-) )
; Best regards
; Peter (DK_PETER)
DeclareModule _MathOn
#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
#WEEK_TO_DAYS = 7 ;Edit: LOL! Constant name were reversed...
#DAY_TO_HOURS = 24 ;this one too
#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
Structure vector2D
x.f
y.f
EndStructure
Structure _2Dvector_pol
mag.f
dir.f
EndStructure
Structure vector3D
x.f
y.f
z.f
EndStructure
Structure quaternion
x.f
y.f
z.f
w.f
EndStructure
Structure _Sphere
x.f
y.f
z.f
radius.f
EndStructure
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 OrbitCalc3D(CenterX.f, CenterY.f, CenterZ.f, AngleX.f, AngleY.f, Radius.i)
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)
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)
EndDeclareModule
Module _MathOn
;returns the distance between two supplied points p and q
Procedure.d Distance(*p.POINT, *q.POINT)
dx.d = *p\x - *q\x ;horizontal difference
dy.d = *p\y - *q\y ;vertical difference
dist.d = 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)
distance = Abs(Px) - Abs(Lx)
ProcedureReturn distance
EndProcedure
;distance from a point to a horizontal line
Procedure.i FindDist2HorizLine(py.f, ly.f)
distance = Abs(Py) - Abs(Ly)
ProcedureReturn distance
EndProcedure
;Find the slope of a line
Procedure.f FindSlopeOfLine(*p1.POINT, *p2.POINT)
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)
; Calculate the normal force being exerted by the ramp
normal.f = weight * Cos(angle * #PI / 180)
; Calculate the force perpendicular To the normal
perpForce.f = weight * Sin(angle * #PI / 180)
; Calculate the amount of Static friction keeping the object at rest
stat_friction.f = 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)
;Calculate the normal force being exerted by the object
normal.f = weight * Cos(angle * PI / 180)
; Calculate the force perpendicular To the normal
perpForce.f = weight * Sin(angle * PI / 180)
;Calculate the amount of Static friction keeping the object at rest
kin_friction.f = fric_coeff * normal
;Calculate the sum of forces acting upon the object
total_force.f = 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)
;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)
KE.f = (mass/2)*(Pow(speed,2))
ProcedureReturn KE
EndProcedure
Procedure.f CalculateAngledWork(*obj.vector2D, friction.f, displacement.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
PE.f = mass * #GRAVITY * height
ProcedureReturn PE
EndProcedure
;move an object based on its angles and distance
Procedure OrbitCalc3D(CenterX.f, CenterY.f, CenterZ.f, AngleX.f, AngleY.f, Radius.i)
X = CenterX + Radius*Cos(AngleY)*Cos(AngleX)
Y = CenterY + Radius*Sin(AngleX)
Z = CenterZ + Radius*Sin(AngleY)*Cos(AngleX)
EndProcedure
;Example for Projectile Trajectory
Procedure Projectile_Trajectory(Screen_Bottom.i, Initial_vel.f, Initial_Angle.f)
x_pos.f = 0 ;starting point of projectile
y_pos.f = Screen_Bottom ;bottom of screen
y_velocity.f = 0 ;initial y velocity
x_velocity.f = 0 ;constant x velocity
gravity.f = 1 ;do want To fall too fast
velocity.f = Initial_vel ;whatever
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
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
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)
theta.f
theta = 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
ProcedureReturn @Obj
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)
seconds = Days * #DAYS_TO_HOURS * #HOURS_TO_MIN * #MIN_TO_SEC
ProcedureReturn seconds
EndProcedure
Procedure.f ConvertMilesToMeters(Miles.f)
meters.f = Miles * #KM_TO_MILES * #KM_TO_METERS
ProcedureReturn meters
EndProcedure
Procedure.f ConvertSpeedFromMiles(Miles)
meters.f = (Miles * #KM_TO_MILES * #KM_TO_METERS) / (#HOURS_TO_MIN * #MIN_TO_SEC)
EndProcedure
Procedure.f ConvertAccelerationMilesToMeters(Miles.f)
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)
If cels < #MINIMUM_CELCIUS
ProcedureReturn -1
Else
fahren.f = (9.0 / 5.0) * cels + 32
ProcedureReturn fahren
EndIf
EndProcedure
Procedure.f FarenheitToCelcius(Fahren.f)
celsius = ((Fahren - 32) * 5) / 9
ProcedureReturn celsius
EndProcedure
Procedure.d Fibonacci()
TheNext.d = 0
TheLast.d = 1
For x = 0 To 45
Debug Str(TheLast)
sum = TheNext + Thelast
TheNext = Thelast
TheLast = sum
Next x
EndProcedure
Procedure.f CalculateEnergyForWaterToBoil(Liters.f, InitTemp.f, FinalTemp.f)
;Energy = Joules
Energy.f = Liters * (FinalTemp - InitTemp) * 4184.0
ProcedureReturn Energy
EndProcedure
EndModule