MathLib - SOHCAHTOA [Update 1/8/11]
Moderators: dorpond, trevor, Azhrei, giliath, Gamerdude, jay, Mr.Ice
Re: MathLib - SOHCAHTOA [Update 1/8/11]
Remind me tomorrow to look at this. Converting degrees and radians can be tricky when doing the formulas.
Downloads:
- Notepad++ MapTool addon
- RPEdit details (v1.3)
- Coding Tips: Modularity and Design
- Videos: Macro Writing Tools
Re: MathLib - SOHCAHTOA [Update 1/8/11]
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.
GETTING STARTED WITH MAPTOOLS - TUTORIALS, DOCS, VIDEOS, TOOLS, ETC
DISCORD (the new MT forum!)
My stuff
Excel Tools: Table and Light editors
MT Tools: Bag of Tricks: Tools for Maptool, Dungeon Builder I, Dungeon Builder II,onMouseOverEvent.
Frameworks: Dark Heresy, Rogue Trader, Deathwatch, Black Crusade, Only War, SET Card Game, RoboRally
Wiki: Debugging Tutorial, Speed Up Your Macros, Working With Two CODE Levels, Shortcut Keys, Avoiding Stack Overflow, READ THIS
DISCORD (the new MT forum!)
My stuff
Excel Tools: Table and Light editors
MT Tools: Bag of Tricks: Tools for Maptool, Dungeon Builder I, Dungeon Builder II,onMouseOverEvent.
Frameworks: Dark Heresy, Rogue Trader, Deathwatch, Black Crusade, Only War, SET Card Game, RoboRally
Wiki: Debugging Tutorial, Speed Up Your Macros, Working With Two CODE Levels, Shortcut Keys, Avoiding Stack Overflow, READ THIS
- Bone White
- Great Wyrm
- Posts: 1124
- Joined: Tue Aug 23, 2011 11:41 am
- Location: Cornwall, UK
Re: MathLib - SOHCAHTOA [Update 1/8/11]
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.
- Bone White
- Great Wyrm
- Posts: 1124
- Joined: Tue Aug 23, 2011 11:41 am
- Location: Cornwall, UK
Re: MathLib - SOHCAHTOA [Update 1/8/11]
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]
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.
- Bone White
- Great Wyrm
- Posts: 1124
- Joined: Tue Aug 23, 2011 11:41 am
- Location: Cornwall, UK
Re: MathLib - SOHCAHTOA [Update 1/8/11]
... 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.
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.
Re: MathLib - SOHCAHTOA [Update 1/8/11]
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.
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.
GETTING STARTED WITH MAPTOOLS - TUTORIALS, DOCS, VIDEOS, TOOLS, ETC
DISCORD (the new MT forum!)
My stuff
Excel Tools: Table and Light editors
MT Tools: Bag of Tricks: Tools for Maptool, Dungeon Builder I, Dungeon Builder II,onMouseOverEvent.
Frameworks: Dark Heresy, Rogue Trader, Deathwatch, Black Crusade, Only War, SET Card Game, RoboRally
Wiki: Debugging Tutorial, Speed Up Your Macros, Working With Two CODE Levels, Shortcut Keys, Avoiding Stack Overflow, READ THIS
DISCORD (the new MT forum!)
My stuff
Excel Tools: Table and Light editors
MT Tools: Bag of Tricks: Tools for Maptool, Dungeon Builder I, Dungeon Builder II,onMouseOverEvent.
Frameworks: Dark Heresy, Rogue Trader, Deathwatch, Black Crusade, Only War, SET Card Game, RoboRally
Wiki: Debugging Tutorial, Speed Up Your Macros, Working With Two CODE Levels, Shortcut Keys, Avoiding Stack Overflow, READ THIS
Re: MathLib - SOHCAHTOA [Update 1/8/11]
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)
)]
GETTING STARTED WITH MAPTOOLS - TUTORIALS, DOCS, VIDEOS, TOOLS, ETC
DISCORD (the new MT forum!)
My stuff
Excel Tools: Table and Light editors
MT Tools: Bag of Tricks: Tools for Maptool, Dungeon Builder I, Dungeon Builder II,onMouseOverEvent.
Frameworks: Dark Heresy, Rogue Trader, Deathwatch, Black Crusade, Only War, SET Card Game, RoboRally
Wiki: Debugging Tutorial, Speed Up Your Macros, Working With Two CODE Levels, Shortcut Keys, Avoiding Stack Overflow, READ THIS
DISCORD (the new MT forum!)
My stuff
Excel Tools: Table and Light editors
MT Tools: Bag of Tricks: Tools for Maptool, Dungeon Builder I, Dungeon Builder II,onMouseOverEvent.
Frameworks: Dark Heresy, Rogue Trader, Deathwatch, Black Crusade, Only War, SET Card Game, RoboRally
Wiki: Debugging Tutorial, Speed Up Your Macros, Working With Two CODE Levels, Shortcut Keys, Avoiding Stack Overflow, READ THIS