MathLib - SOHCAHTOA [Update 1/8/11]

These are tools and utilities that make it easier to run games. This includes Lib: macro tokens dropped into MapTool to manage the game, a conversion file for CharacterTool to allow use in MapTool, or just about anything else you can think of -- except graphics with macros and anything specific to a particular campaign framework. Those are already covered by the Tilesets subforum and the Links and External Resources forum.

Moderators: dorpond, trevor, Azhrei, giliath, Gamerdude, jay, Mr.Ice

User avatar
aliasmask
RPTools Team
Posts: 9024
Joined: Tue Nov 10, 2009 6:11 pm
Location: Bay Area

Re: MathLib - SOHCAHTOA [Update 1/8/11]

Post by aliasmask »

Remind me tomorrow to look at this. Converting degrees and radians can be tricky when doing the formulas.

User avatar
wolph42
Winter Wolph
Posts: 9999
Joined: Fri Mar 20, 2009 5:40 am
Location: Netherlands
Contact:

Re: MathLib - SOHCAHTOA [Update 1/8/11]

Post by wolph42 »

I remember banging my head in the wall while working with MT angles. I know I've created some utile to help with this, they might be on my bag of tricks. It not ill need to look around.

User avatar
Bone White
Great Wyrm
Posts: 1124
Joined: Tue Aug 23, 2011 11:41 am
Location: Cornwall, UK

Re: MathLib - SOHCAHTOA [Update 1/8/11]

Post by Bone White »

I know that 0 facing angle is actually pointing east in MapTool, and Y counts positive in a south direction, hence [r: yDiff = 0 - (targetY - initiativeY)]. I may look into how to calculate the trig functions myself to see if I can figure out why.

User avatar
Bone White
Great Wyrm
Posts: 1124
Joined: Tue Aug 23, 2011 11:41 am
Location: Cornwall, UK

Re: MathLib - SOHCAHTOA [Update 1/8/11]

Post by Bone White »

Using http://en.wikipedia.org/wiki/Inverse_tr ... arctangent and checking my calculations through google's calculator, my code below gives a much better accuracy with arcTan, to within five decimal places of accuracy (in degrees using Math:lib's toDegrees() function when testing a perfect 45 degree angle, it produces 44.999996367593779960265468547835435976910

This leads me to believe that your arcTan function was erroneous. Please dissect my workings and prove me wrong.

arcTan()
[code=php][h: z = arg(0)]
[h: a = 999]
[h, for (i,10,0,-1), code :
    {
    [h: j = 2 * i - 1]
    [h: a = j + (i * z)*(i * z) / a]
    }
]
[h: macro.return = z / a] [/code]
Last edited by Bone White on Sun Aug 19, 2012 6:23 pm, edited 1 time in total.

User avatar
Bone White
Great Wyrm
Posts: 1124
Joined: Tue Aug 23, 2011 11:41 am
Location: Cornwall, UK

Re: MathLib - SOHCAHTOA [Update 1/8/11]

Post by Bone White »

... and the results of my labours, a UDF which returns two values. I have made the rounding remove decimal places, to avoid some finicky formatting issues I have around 180 angles, but the accuracy is there, the code just needs better parsing/translocation. Check my previous post in this thread for my version of arcTan()


getFacingAngle()
[code=php][h: '<!-- arg0 is the tokenID of the first arm, arg1 is the tokenID of the vertex. -->']
[h: '<!-- uses Bone White`s arcTan UDF -->']
[h: '<!--  macro.return is the angle you should face the arm token at using setTokenFacing() -->']

[h: armTokenID = arg(0)]
[h: vertexTokenID = arg(1)]
[h, if(getTokenFacing(vertexTokenID) == ""): assert(0,"Vertex token must have a facing",0)]
[h, if(getTokenFacing(armTokenID) == ""): assert(0,"Arm token must have a facing",0)]
[h: armTokenX = getTokenX(0, armTokenID)]
[h: armTokenY = getTokenY(0, armTokenID)]
[h: vertexTokenX = getTokenX(0, vertexTokenID)]
[h: vertexTokenY = getTokenY(0, vertexTokenID)]
[h: xDiff = vertexTokenX - armTokenX]
[h: yDiff = vertexTokenY - armTokenY]
[h, if ((yDiff == 0)&&(xDiff == 0)): assert(0,"Vertex token occupies the same grid square as the arm token",0)]
[h, if (yDiff != 0), code :{
    [h: tanAngle = arcTan(xDiff/yDiff)]
    [h: armTokenAngle = round(toDegrees(tanAngle), 0) + 90]
    };{
    [h, if(xDiff > 0): armTokenAngle = 0]
    [h, if(xDiff < 0): armTokenAngle = 180]
    }
]
[h, if(yDiff < 0): armTokenAngle = armTokenAngle]
[h, if(yDiff > 0): armTokenAngle = armTokenAngle + 180]
[h: macro.return = armTokenAngle] [/code]


getFlankAngle()
[code=php][h: '<!-- arg0 is the tokenID of the first arm, arg1 is the tokenID of the vertex. -->']
[h: '<!-- uses Bone White`s arcTan UDF -->']
[h: '<!-- macro.return is the angle at which the first token faces the second.  0 degrees is from behind, 180 degrees is from infront, 90 degrees is to the side -->']

[h: armTokenID = arg(0)]
[h: vertexTokenID = arg(1)]
[h, if(getTokenFacing(vertexTokenID) == ""): assert(0,"Vertex token must have a facing",0)]
[h, if(getTokenFacing(armTokenID) == ""): assert(0,"Arm token must have a facing",0)]
[h: armTokenX = getTokenX(0, armTokenID)]
[h: armTokenY = getTokenY(0, armTokenID)]
[h: vertexTokenX = getTokenX(0, vertexTokenID)]
[h: vertexTokenY = getTokenY(0, vertexTokenID)]
[h: xDiff = vertexTokenX - armTokenX]
[h: yDiff = vertexTokenY - armTokenY]
[h, if ((yDiff == 0)&&(xDiff == 0)): assert(0,"Vertex token occupies the same grid square as the arm token",0)]
[h, if (yDiff != 0), code :{
    [h: tanAngle = arcTan(xDiff/yDiff)]
    [h: armTokenAngle = round(toDegrees(tanAngle), 0) + 90]
    };{
    [h, if(xDiff > 0): armTokenAngle = 0]
    [h, if(xDiff < 0): armTokenAngle = 180]
    }
]
[h, if(yDiff < 0): armTokenAngle = armTokenAngle]
[h, if(yDiff > 0): armTokenAngle = armTokenAngle + 180]
[h: vertexFacing = getTokenFacing(vertexTokenID)]
[h: flankAngle = 360-vertexFacing + armTokenAngle]
[h, if(flankAngle >= 360): flankAngle = flankAngle - 360; flankAngle = flankAngle]
[h, if(flankAngle >= 360): flankAngle = flankAngle - 360; flankAngle = flankAngle]
[h, if(flankAngle > 180): flankAngle = 180 - (flankAngle - 180); flankAngle = flankAngle]
[h: macro.return = flankAngle] [/code]


I use the UDF as follows:

[code=php][h: setTokenFacing(getFacingAngle(getInitiativeToken(),getSelected()),getInitiativeToken())]
[r: angleOnTarget = getFlankAngle(getInitiativeToken(),getSelected())] [/code]


Just stick two tokens down, make sure each token has a facing, then move them around and use the macro.
EDIT: made the two UDF functions seperate.

User avatar
wolph42
Winter Wolph
Posts: 9999
Joined: Fri Mar 20, 2009 5:40 am
Location: Netherlands
Contact:

Re: MathLib - SOHCAHTOA [Update 1/8/11]

Post by wolph42 »

you do not happen to have a function lying around that you feed x,y,r,a and that returns x2,y2 ? Preferably where a==facing angle (which is totally off in regard of the real world angle.
so
x,y one point of the line
r length of the line
a facing direction of the line where a=0 results in a vertical line upwards

e.g.
(x,y,r,a)
(0,0,50,0) returns {"x":0,"y":-50}
(10,10,50,90) returns {"x":-40,"y":10}
(20,20,40,270) returns {"x":60,"y":20}
etc.

User avatar
wolph42
Winter Wolph
Posts: 9999
Joined: Fri Mar 20, 2009 5:40 am
Location: Netherlands
Contact:

Re: MathLib - SOHCAHTOA [Update 1/8/11]

Post by wolph42 »

never mind already got it:

Code: Select all

[h:macro.return = strformat(
'{"x":%s,"y":%s}', 
arg(0) + round(arg(2)*math.cos(math.toRadians(arg(3)+90)),0),
arg(1) - round(arg(2)*math.sin(math.toRadians(arg(3)+90)),0)
)] 

Post Reply

Return to “Drop-In Macro Resources”