Calculate derived points

i’ll stand by what i posted (any potential typos from free-hand forum typing notwithstanding) - the accepted way to solve this class of problems is via the 2d rotation formula.

the only little “trick” in this particular problem’s wording is the translation of p1. ie, you must first remove the translation to p1 (that’s what dx/dy do) to put p2 back on the origin, then apply the 2d rotation (that’s the cosx-siny, cosy+sinx bit), then translate xy’ back to p1 (that’s the p1x+, p1y+ bit).  still textbook stuff though.

BUT… that’s not to say that you can’t solve it other ways. (fe, get the original line’s angle and magnitude, add/sub the half angle, recreate the other lines via basic trig).  however, that’s the long way to do it, and needs (at least) an additional atan2 for the angle, and a sqrt for the magnitude.

first quarter trig ought to still cover the angle sum rule, and from there it’s just a tiny step til you could derive the 2d rotation formula for yourself.  (you don’t even need to know that you’re applying a matrix transform to a vector - you are, of course, but in 1st qtr trig you wouldn’t call it that yet)

a geometric solution is also possible, using similar triangles, but omg - once you grok the trig you’d never do it with plain geometry (btw, that’s a brilliant pun right there – too bad that few will appreciate it!  :D)

Hey guys!  I typoed when modifying Dave’s code to fit my example.

I feel bad, because my mistake reflected badly on Dave’s code and Dave is, as I said, a math wiz.

I have updated the example.  Just re-download the code here:

https://github.com/roaminggamer/RG_FreeStuff/raw/master/AskEd/2018/01/jakePoints.zip

Trigonometry is what you need.  https://www.mathsisfun.com/sine-cosine-tangent.html

Thank you I read the guide but I still have problems I can find the distance but not the point.

Can you help me with some code?

This is what I’ve tried until now

 local p1x,p1y,p2x,p2y = 50, 100, 250, 400 display.newLine( p1x,p1y,p2x,p2y ) local c = display.newCircle( p1x, p1y, 40 ) c:setFillColor( 1, 0, 0, 0 ) c.strokeWidth=1 c:setStrokeColor( 1, 0, 0 ) local dx, dy = p2x-p1x, p2y-p1y local m = math.sqrt(dx\*dx+dy\*dy) print("===\>", m) local ang = 45 local sen = math.sin(ang) print(sen)

Why not just use a math library  like math2din SSK2?

The following code, calculates:

  1. The vector from P1 to P2 as a table { x = #, y = # } 

  2. The angle of that vector.

  3. The length of that vector.

  4. The desired angle between P3 and P4.

  5. P3 as a normalized vector from the angle - half the desired angle

  6. P3 as P3 scaled by length

  7. P4 in the same way as P3

    – Given p1 and p2 in the form { x = #, y = # } or as an object. local vec = ssk.math2d.diff( p1, p2 ) local angle = ssk.math2d.vector2Angle(vec) local len = ssk.math2d.length( vec ) local angleBetween_p3_p4 = 30 local p3 = ssk.math2d.angle2Vector( angle - angleBetween_p3_p4/2, true ) p3 = ssk.mat2d.scale( p3, len ) local p4 = ssk.math2d.angle2Vector( angle + angleBetween_p3_p4/2, true ) p4 = ssk.mat2d.scale( p4, len )

It isn’t super efficient, but you can always get the code, combine the steps, then minimize it.

Note: SSK2’s math2d comes with *Fast variants of each of the above functions.  These are much faster and ONLY operate on discrete x,y vaues:

-- Given p1 and p2 in the form { x = #, y = # } or as an object. local vx, vy = ssk.math2d.diffFast( p1.x, p1.y, p2.x, p2.y ) local angle = ssk.math2d.vector2AngleFast( vx, vy ) local len = ssk.math2d.lengthFast( vx, vy) local angleBetween\_p3\_p4 = 30 local p3x, p3y = ssk.math2d.angle2VectorFast( angle - angleBetween\_p3\_p4/2) p3x, p3y = ssk.mat2d.scaleFast( p3x, p3y, len ) local p4x, p4y = ssk.math2d.angle2VectorFast( angle + angleBetween\_p3\_p4/2) p4x, p4y = ssk.mat2d.scaleFast( p4x, p4y, len ) local p3 = { x = p3x, y = p3y } local p4 = { x = p4x, y = p4y }

As an added bonus, if you read the definitions for those *Fast functions the math will be easy to follow and combine into a single function if you choose to.

Ex: Compare scale() versus scaleFast()

-- == -- ssk.math2d.scale( ..., scale [, altRet]) - Calculates a scaled vector scale \* \<x1, y1\> = \<scale \* x1, scale \* y1\> -- == function math2do.scale( ... ) -- ( objA, scale [, altRet] ) or ( x1, y1, scale, [, altRet] ) if( type(arg[1]) == "number" ) then local x,y = arg[1] \* arg[3], arg[2] \* arg[3] if(arg[4]) then return { x=x, y=y } else return x,y end else local x,y = arg[1].x \* arg[2], arg[1].y \* arg[2] if(arg[3]) then return x,y else return { x=x, y=y } end end end

function math2do.scaleFast( x, y, scale ) return x \* scale, y \* scale end

If all of this is totally foreign to you, I can suggest an excellent summary.

Download: Tricks Of The Windows Game Programming Gurus

Then read Appendix C starting on page 911

There is a lot of other relevant stuff in the book too, like chapter 13 (Basic Physics Modelling) and so on.

As old as this book is, and ignore the fact it focuses on Windows, owning a physics copy is worthwhile.  I have one and still read from it on occasion.  It’s got tons of gems in it.

Thanks so much @roaminggamer

Everything works fine, I’ll study your code today.

I gave a quick look at the book. I understand why our need a paper version. It is very useful and full of ideas

sounds homework cheating, textbook 2d rotation formula, but anyway…

local p1x, p1y = 100, 100 local p2x, p2y = 300, 200 local theta = math.pi/8 local c, s = math.cos(theta), math.sin(theta) local dx, dy = p2x-p1x, p2y-p1y local p3x, p3y = p1x+dx\*c-dy\*s, p1y+dy\*c+dx\*s local p4x, p4y = p1x+dx\*c+dy\*s, p1y+dy\*c-dx\*s

grading tip:  many alternative/equivalent ways to rearrange the c,s,dx,dy terms, but automatic 50% penalty for using an arctangent anywhere in your answer!    :smiley:

something, however, does not come back:

local p1={x=160,y=400} local p2={x=160,y=100} local vec = ssk.math2d.diff( p1, p2 ) local angle = ssk.math2d.vector2Angle(vec) local len = ssk.math2d.length( vec ) local angleBetween\_p3\_p4 = 90 local p3 = ssk.math2d.angle2Vector( angle - angleBetween\_p3\_p4/2, true ) p3 = ssk.math2d.scale( p3, len ) local p4 = ssk.math2d.angle2Vector( angle + angleBetween\_p3\_p4/2, true ) p4 = ssk.math2d.scale( p4, len ) --test display.newLine(p1.x,p1.y,p2.x,p2.y) local l3 = display.newLine(p1.x,p1.y,p3.x,p3.y) l3:setStrokeColor( 1, 0, 0 ) local l4 = display.newLine(p1.x,p1.y,p4.x,p4.y) l4:setStrokeColor( 0, 1, 0 )

the orange scheme is what I would have expected

Why instead the lines are not equidistant from the main line?

@Jake,

take a look at Dave’s answer.  I know that Dave probably did this off the top of his head because he is a smart math guy. 

That said, you’ll find that if you combine the code from my math2d functions, then reduce and optimize you’ll come up with something similar.

The takeaway I hope to send is, knowing how to break the problem down into its component parts (either directly via Trig calcs or vector math) is critical.  Then you can  optimize if necessary. 

Simply having a specific solution give to you is great for the current problem, but less helpful in the long run because you don’t learn anything from it.  Dave got as smart as he is (and as good at math) through repetition and solving.

PS - Dave’s solution is by far the fastest (compared to mine.)

ok the solution of @davebollinger it works as I expect.

So now studying his logic and the logic of the functions of @roaminggamer It should come on a good thing.

Thank you so much to both of you, you have taken away many problems

I hope to understand and go it alone further

The calculation was missing one step:

 p4 = ssk.math2d.scale( p4, len ) p3 = ssk.math2d.add(p1, p3) p4 = ssk.math2d.add(p1, p4) return p3, p4

Give a man a fish as they say…

Working example: https://github.com/roaminggamer/RG_FreeStuff/raw/master/AskEd/2018/01/jakePoints.zip

Includes my code and Dave’s (ed.lua or dave.lua)

@Dave - I think the vector length is not being incorporated in your soln.

Update: Nope I’m an idgit.  I typed some code wrong when converting yours for the example.

https://www.youtube.com/watch?v=TmvRn2ucLRo&feature=youtu.be

in fact the solution of @davebollinger it only works with that angle if I’m understanding well

@roaminggamer now everything works well

@Sphere Game Studios today I received a fish but not for this I will sleep. I use the time to build a fishing rod

I would still like to thank all of you for your help in the different ways

Final note, this code calculates those points as if they are on the arc of a perfect circle.

If you were looking to calculate them as if they were the missing points in two right-triangles, the calculation is a little different.

IF you want P2, P3, and P4 to be cotangent you need to calculate the length differently.

The solution dave gave you can work for any angle if you replace

local theta = math.pi/8 local c, s = math.cos(theta), math.sin(theta)

with

local myAngle = 30 --any angle in degrees here local theta = math.pi/180 \* myAngle local c, s = math.cos(theta), math.sin(theta)

@roaminggamer

at the moment it’s fine with the perfec radius t too but I would like to know the other way too.

I do not want you to waste any more time, I see if I can alone

@Sphere Game Studios

this also helps me I want to learn as much as possible…