# William W. Tarpley # Using Projections to find the Distance from a Point to a Line # Math 151 Honors # Fall 2011 # Instructor: Philip Yasskin restart: with(Maplets): with(Maplets[Tools]): with(Maplets[Elements]): with(plots): StartEngine(); randomize(): right:= ["Bullseye!", "Great!", "That's absolutely right!", "You're unstoppable!", "Correct!", "You nailed that one!", "YES!", "Way to go!", "I knew you could do it!", "Perfecto!", "Youre awesome!", "That's amazing!", "You're a math whiz!", "Whoop!", "Nice job!", "That's right!", "That's the way!", "I like the sound of that!", "Ding! That's correct!", "You're a genius!", "Right on the mark!", "Brick...house!", "Oh yeah!", "Wonderful!", "Excellent!", "You got it!", "Can I get a what what!", "Holla!", "You're incredible!"]: rightrand := rand(1..nops(right)): wrong:=["Try again.", "Nope. I'm sorry.", "C'mon, you can do it.", "You can do better.", "You're close.", "Look closer.", "Put on your thinking cap.", "Better luck next time.", "Keep trying.", "Never give up.", "Try again. I have faith in you.", "Try harder."]: wrongrand := rand(1..nops(wrong)): hint:=["Now try it yourself.", "There it is. Now figure it out.", "The hint is great, but try it yourself.", "That was practice. Try it again.", "Don't settle for the hint. Work it out."]: hintrand := rand(1..nops(hint)): randm:=rand(-3..3): randb:=rand(-5..5): randcoord:=rand(-10..10): ask:=proc() global m,b,x0,y0, CorrectA,CorrectB,Correctu,Correctv,Correctw,Correctproj,CorrectD; m:=randm(); while m=0 do m:=randm(); end do; b:=randb(); x0:=randcoord(); y0:=randcoord(); while y0=m*x0+b do y0:=randcoord(); end do; CorrectA,CorrectB,Correctu,Correctv,Correctw,Correctproj,CorrectD:=false,false,false,false,false,false,false; Set(TFpt=(P = (x0,y0))); Set(TFln=(y = m*x + b)); Set(TFx1="", TFx1(editable)=true); Set(TFy1="", TFy1(editable)=true); Set(BCA(enabled)=true); Set(BSA(enabled)=true); Set(TFx2="", TFx2(editable)=true); Set(TFy2="", TFy2(editable)=true); Set(BCB(enabled)=true); Set(BSB(enabled)=true); Set(TFu="", TFu(editable)=false); Set(BCu(enabled)=false); Set(BSu(enabled)=false); Set(TFv="", TFv(editable)=false); Set(BCv(enabled)=false); Set(BSv(enabled)=false); Set(TFw="", TFw(editable)=false); Set(BCw(enabled)=false); Set(BSw(enabled)=false); Set(TFproj="", TFproj(editable)=false); Set(BCproj(enabled)=false); Set(BSproj(enabled)=false); Set(TFD="", TFD(editable)=false); Set(BCD(enabled)=false); Set(BSD(enabled)=false); Set(replyA="", replyA(background)=white); Set(replyB="", replyB(background)=white); Set(replyu="", replyu(background)=white); Set(replyv="", replyv(background)=white); Set(replyw="", replyw(background)=white); Set(replyproj="", replyproj(background)=white); Set(replyD="", replyD(background)=white); Set(reply="", reply(background)=white); end proc: hintAB:=proc() Set(reply="Pick two easy values for x, such as 0 or 1, plug them into the equation for the line, and calculate the y values.", reply(background)="Orange", reply(foreground)=black); end proc: checkA:=proc() global m,b,x0,y0, CorrectA,CorrectB,Correctu,Correctv,Correctw,Correctproj,CorrectD; local userx1, usery1; userx1:=Get(TFx1::realcons, corrections=true, update=true): usery1:=Get(TFy1::realcons, corrections=true, update=true): if usery1=m*userx1+b then Set(replyA="Correct", replyA(background)=green, replyA(foreground)=black); Set(reply=right[rightrand()], reply(background)=green, reply(foreground)=black); CorrectA:=true; Set(TFx1(editable)=false); Set(TFy1(editable)=false); Set(BCA(enabled)=false); Set(BSA(enabled)=false); if CorrectB then Set(TFu(editable)=true); Set(BCu(enabled)=true); Set(BSu(enabled)=true); Set(TFv(editable)=true); Set(BCv(enabled)=true); Set(BSv(enabled)=true); end if; else Set(replyA="Incorrect", replyA(background)=red, replyA(foreground)=white); Set(reply=wrong[wrongrand()], reply(background)=red, reply(foreground)=white); end if; end proc: showA:=proc() global m,b,x0,y0, CorrectA,CorrectB,Correctu,Correctv,Correctw,Correctproj,CorrectD; Set(TFx1=0); Set(TFy1=b); Set(replyA="Shown", replyA(background)=yellow, replyA(foreground)=black); Set(reply=hint[hintrand()], reply(background)=yellow, reply(foreground)=black); CorrectA:=true; Set(TFx1(editable)=false); Set(TFy1(editable)=false); Set(BCA(enabled)=false); Set(BSA(enabled)=false); if CorrectB then Set(TFu(editable)=true); Set(BCu(enabled)=true); Set(BSu(enabled)=true); Set(TFv(editable)=true); Set(BCv(enabled)=true); Set(BSv(enabled)=true); end if; end proc: checkB:=proc() global m, b, x0, y0, CorrectA,CorrectB,Correctu,Correctv,Correctw,Correctproj,CorrectD; local userx2, usery2; userx2:=Get(TFx2::realcons, corrections=true, update=true): usery2:=Get(TFy2::realcons, corrections=true, update=true): if usery2=m*userx2+b then Set(replyB="Correct", replyB(background)=green, replyB(foreground)=black); Set(reply=right[rightrand()], reply(background)=green, reply(foreground)=black); CorrectB:=true; Set(TFx2(editable)=false); Set(TFy2(editable)=false); Set(BCB(enabled)=false); Set(BSB(enabled)=false); if CorrectA then Set(TFu(editable)=true); Set(BCu(enabled)=true); Set(BSu(enabled)=true); Set(TFv(editable)=true); Set(BCv(enabled)=true); Set(BSv(enabled)=true); end if; else Set(replyB="Incorrect", replyB(background)=red, replyB(foreground)=white); Set(reply=wrong[wrongrand()], reply(background)=red, reply(foreground)=white); end if; end proc: showB:=proc() global m,b,x0,y0, CorrectA,CorrectB,Correctu,Correctv,Correctw,Correctproj,CorrectD; Set(TFx2=1); Set(TFy2=m+b); Set(replyB="Shown", replyB(background)=yellow, replyB(foreground)=black); Set(reply=hint[hintrand()], reply(background)=yellow, reply(foreground)=black); CorrectB:=true; Set(TFx2(editable)=false); Set(TFy2(editable)=false); Set(BCB(enabled)=false); Set(BSB(enabled)=false); if CorrectA then Set(TFu(editable)=true); Set(BCu(enabled)=true); Set(BSu(enabled)=true); Set(TFv(editable)=true); Set(BCv(enabled)=true); Set(BSv(enabled)=true); end if; end proc: hintu:=proc() Set(reply="To find u = AP = P - A simply subtract the coordinates of A from the coordinates of P: P - A = [P1 - A1, P2 - A2].", reply(background)="Orange", reply(foreground)=black); end proc: checku:=proc() global m, b, x0, y0, CorrectA,CorrectB,Correctu,Correctv,Correctw,Correctproj,CorrectD; local userx1,usery1,useru; userx1:=Get(TFx1::realcons, corrections=true, update=true): usery1:=Get(TFy1::realcons, corrections=true, update=true): useru:=Get(TFu::list, corrections=true, update=true): if useru=[x0-userx1,y0-usery1] then Set(replyu="Correct", replyu(background)=green, replyu(foreground)=black); Set(reply=right[rightrand()], reply(background)=green, reply(foreground)=black); Correctu:=true; Set(TFu(editable)=false); Set(BCu(enabled)=false); Set(BSu(enabled)=false); if Correctw then Set(TFproj(editable)=true); Set(BCproj(enabled)=true); Set(BSproj(enabled)=true); end if; else Set(replyu="Incorrect", replyu(background)=red,replyu(foreground)=white); Set(reply=wrong[wrongrand()], reply(background)=red, reply(foreground)=white); end if; end proc: showu:=proc() global m, b, x0, y0, CorrectA,CorrectB,Correctu,Correctv,Correctw,Correctproj,CorrectD; local userx1, usery1; userx1:=Get(TFx1::realcons, corrections=true, update=true): usery1:=Get(TFy1::realcons, corrections=true, update=true): Set(TFu=[x0-userx1,y0-usery1]); Set(replyu="Shown", replyu(background)=yellow, replyu(foreground)=black); Set(reply=hint[hintrand()], reply(background)=yellow, reply(foreground)=black); Correctu:=true; Set(TFu(editable)=false); Set(BCu(enabled)=false); Set(BSu(enabled)=false); if Correctw then Set(TFproj(editable)=true); Set(BCproj(enabled)=true); Set(BSproj(enabled)=true); end if; end proc: hintv:=proc() Set(reply="To find v = AB = B - A simply subtract the coordinates of A from the coordinates of B: B - A = [B1 - A1, B2 - A2].", reply(background)="Orange", reply(foreground)=black); end proc: checkv:=proc() global m, b, x0, y0, CorrectA,CorrectB,Correctu,Correctv,Correctw,Correctproj,CorrectD; local userx1, usery1, userx2, usery2, userv; userx1:=Get(TFx1::realcons, corrections=true, update=true): usery1:=Get(TFy1::realcons, corrections=true, update=true): userx2:=Get(TFx2::realcons, corrections=true, update=true): usery2:=Get(TFy2::realcons, corrections=true, update=true): userv:=Get(TFv::list, corrections=true, update=true): if userv=[userx2-userx1,usery2-usery1] then Set(replyv="Correct", replyv(background)=green, replyv(foreground)=black); Set(reply=right[rightrand()], reply(background)=green, reply(foreground)=black); Correctv:=true; Set(TFv(editable)=false); Set(BCv(enabled)=false); Set(BSv(enabled)=false); Set(TFw(editable)=true); Set(BCw(enabled)=true); Set(BSw(enabled)=true); else Set(replyv="Incorrect", replyv(background)=red,replyv(foreground)=white); Set(reply=wrong[wrongrand()], reply(background)=red, reply(foreground)=white); end if; end proc: showv:=proc() global m, b, x0, y0, CorrectA,CorrectB,Correctu,Correctv,Correctw,Correctproj,CorrectD; local userx1, usery1, userx2, usery2; userx1:=Get(TFx1::realcons, corrections=true, update=true): usery1:=Get(TFy1::realcons, corrections=true, update=true): userx2:=Get(TFx2::realcons, corrections=true, update=true): usery2:=Get(TFy2::realcons, corrections=true, update=true): Set(TFv=[userx2-userx1,usery2-usery1]); Set(replyv="Shown", replyv(background)=yellow, replyv(foreground)=black); Set(reply=hint[hintrand()], reply(background)=yellow, reply(foreground)=black); Correctv:=true; Set(TFv(editable)=false); Set(BCv(enabled)=false); Set(BSv(enabled)=false); Set(TFw(editable)=true); Set(BCw(enabled)=true); Set(BSw(enabled)=true); end proc: hintw:=proc() Set(reply="To be perpendicular, v and w must satisfy v.w = 0.\nIn 2 dimensions, an easy way to do this is to interchange components and flip the sign of one component.\nFor example, if v = [a , b] then w = [b , -a].", reply(background)="Orange", reply(foreground)=black); end proc: checkw:=proc() global m, b, x0, y0, CorrectA,CorrectB,Correctu,Correctv,Correctw,Correctproj,CorrectD; local userv, userw; userv:=Get(TFv::list, corrections=true, update=true): userw:=Get(TFw::list, corrections=true, update=true): if userw[1]*userv[1]+userw[2]*userv[2] = 0 then Set(replyw="Correct", replyw(background)=green, replyw(foreground)=black); Set(reply=right[rightrand()], reply(background)=green, reply(foreground)=black); Correctw:=true; Set(TFw(editable)=false); Set(BCw(enabled)=false); Set(BSw(enabled)=false); if Correctu then Set(TFproj(editable)=true); Set(BCproj(enabled)=true); Set(BSproj(enabled)=true); end if; else Set(replyw="Incorrect", replyw(background)=red,replyw(foreground)=white); Set(reply=wrong[wrongrand()], reply(background)=red, reply(foreground)=white); end if; end proc: showw:=proc() global m, b, x0, y0, CorrectA,CorrectB,Correctu,Correctv,Correctw,Correctproj,CorrectD; local userx1, usery1, userx2, usery2; userx1:=Get(TFx1::realcons, corrections=true, update=true): usery1:=Get(TFy1::realcons, corrections=true, update=true): userx2:=Get(TFx2::realcons, corrections=true, update=true): usery2:=Get(TFy2::realcons, corrections=true, update=true): Set(TFw=[usery2-usery1,-1*(userx2-userx1)]); Set(replyw="Shown", replyw(background)=yellow, replyw(foreground)=black); Set(reply=hint[hintrand()], reply(background)=yellow, reply(foreground)=black); Correctw:=true; Set(TFw(editable)=false); Set(BCw(enabled)=false); Set(BSw(enabled)=false); if Correctu then Set(TFproj(editable)=true); Set(BCproj(enabled)=true); Set(BSproj(enabled)=true); end if; end proc: hintproj:=proc() Set(reply="The scalar projection is the dot product of the two vectors divided by the magnitude of the vector being projected upon.\nIn this case, it is (w.u)/|w|.", reply(background)="Orange", reply(foreground)=black); end proc: checkproj:=proc() global m, b, x0, y0, CorrectA,CorrectB,Correctu,Correctv,Correctw,Correctproj,CorrectD; local userx1, usery1, userx2, usery2, useru, userv, userw, userproj; userx1:=Get(TFx1::realcons, corrections=true, update=true): usery1:=Get(TFy1::realcons, corrections=true, update=true): userx2:=Get(TFx2::realcons, corrections=true, update=true): usery2:=Get(TFy2::realcons, corrections=true, update=true): userproj:=Get(TFproj::realcons, corrections=true, update=true): if simplify(userproj- ( ( (x0-userx1)*(usery2-usery1)-(y0-usery1)*(userx2-userx1) ) / ( sqrt((usery2-usery1)^2+(userx2-userx1)^2) ) ) )=0 then Set(replyproj="Correct", replyproj(background)=green, replyproj(foreground)=black); Set(reply=right[rightrand()], reply(background)=green, reply(foreground)=black); Correctproj:=true; Set(TFproj(editable)=false); Set(BCproj(enabled)=false); Set(BSproj(enabled)=false); Set(TFD(editable)=true); Set(BCD(enabled)=true); Set(BSD(enabled)=true); else Set(replyproj="Incorrect", replyproj(background)=red,replyproj(foreground)=white); Set(reply=wrong[wrongrand()], reply(background)=red, reply(foreground)=white); end if; end proc: showproj:=proc() global m, b, x0, y0, CorrectA,CorrectB,Correctu,Correctv,Correctw,Correctproj,CorrectD; local userx1, usery1, userx2, usery2, useru, userv, userw, userproj; userx1:=Get(TFx1::realcons, corrections=true, update=true): usery1:=Get(TFy1::realcons, corrections=true, update=true): userx2:=Get(TFx2::realcons, corrections=true, update=true): usery2:=Get(TFy2::realcons, corrections=true, update=true): Set(TFproj= ( ( (x0-userx1)*(usery2-usery1)-(y0-usery1)*(userx2-userx1) ) / ( sqrt((usery2-usery1)^2+(userx2-userx1)^2) ) ) ); Set(replyproj="Shown", replyproj(background)=yellow, replyproj(foreground)=black); Set(reply=hint[hintrand()], reply(background)=yellow, reply(foreground)=black); Correctproj:=true; Set(TFproj(editable)=false); Set(BCproj(enabled)=false); Set(BSproj(enabled)=false); Set(TFD(editable)=true); Set(BCD(enabled)=true); Set(BSD(enabled)=true); end proc: hintD:=proc() Set(reply="A scalar projection may be negative, but a distance must be positive. So the distance is the absolute value of the scalar projection.", reply(background)="Orange", reply(foreground)=black); end proc: checkD:=proc() global m, b, x0, y0, CorrectA,CorrectB,Correctu,Correctv,Correctw,Correctproj,CorrectD; local userx1, usery1, userx2, usery2, useru, userv, userw, userproj, userD; userproj:=Get(TFproj::realcons, corrections=true, update=true): userD:=Get(TFD::realcons, corrections=true, update=true): if simplify(userD-abs(userproj))=0 then Set(replyD="Correct", replyD(background)=green, replyD(foreground)=black); Set(reply=right[rightrand()], reply(background)=green, reply(foreground)=black); CorrectD:=true; Set(TFD(editable)=false); Set(BCD(enabled)=false); Set(BSD(enabled)=false); elif simplify(userD+abs(userproj))=0 then Set(replyD="Almost", replyD(background)="Orange", replyD(foreground)=black); Set(reply="Remember, distance must be positive.", reply(background)="Orange", reply(foreground)=black); else Set(replyD="Incorrect", replyD(background)=red,replyD(foreground)=white); Set(reply=wrong[wrongrand()], reply(background)=red, reply(foreground)=white); end if; end proc: showD:=proc() global m, b, x0, y0, CorrectA,CorrectB,Correctu,Correctv,Correctw,Correctproj,CorrectD; local userx1, usery1, userx2, usery2, useru, userv, userw, userproj, userD; userproj:=Get(TFproj::realcons, corrections=true, update=true): Set(TFD=abs(userproj)); Set(replyD="Shown", replyD(background)=yellow, replyD(foreground)=black); Set(reply=hint[hintrand()], reply(background)=yellow, reply(foreground)=black); CorrectD:=true; Set(TFD(editable)=false); Set(BCD(enabled)=false); Set(BSD(enabled)=false); end proc: DistancePointLine:=Maplet(onstartup = RunWindow(MAIN), Window[MAIN](title="Using Projections to find the Distance from a Point to a Line", [ halign=none, [ halign=none, Button("New Line and Point", Evaluate(function = "ask"), background=magenta), HorizontalGlue(), Button("Quit", Shutdown(), background=pink) ], [ border=true, halign=none, HorizontalGlue(), caption="Goal: Find the distance between the given point and line:", TextField[TFpt](" P = (x0,y0)", editable=false, background=white), HorizontalGlue(), TextField[TFln](" y = m*x + b", editable=false, background=white), HorizontalGlue() ], BoxColumn( border=true, halign=none, spacing=0, inset=0, caption="Step 1: Find two points on the line:", [ halign=none, "A: x1 =", TextField[TFx1](width=5, background=turquoise, editable=false), "y1 =", TextField[TFy1](width=5, background=turquoise, editable=false), HorizontalGlue(), Button("Hint", Evaluate(function = "hintAB"), background="Orange"), Button[BCA]("Check", Evaluate(function = "checkA"), background=green, enabled=false), TextField[replyA](width=10, editable=false, background=white), Button[BSA]("Show", Evaluate(function = "showA"), background=yellow, enabled=false) ], [ halign=none, "B: x2 =", TextField[TFx2](width=5, background=turquoise, editable=false), "y2 =", TextField[TFy2](width=5, background=turquoise, editable=false), HorizontalGlue(), Button("Hint", Evaluate(function = "hintAB"), background="Orange"), Button[BCB]("Check", Evaluate(function = "checkB"), background=green,enabled=false), TextField[replyB](width=10, editable=false, background=white), Button[BSB]("Show", Evaluate(function = "showB"), background=yellow,enabled=false) ] ), [ border=true, halign=none, caption="Step 2: Find the vector u = AP, from the point A on the line to the point P: Enter it in the form [x,y].", "u = ", TextField[TFu](width=25, background=turquoise, editable=false), HorizontalGlue(), Button("Hint", Evaluate(function = "hintu"), background="Orange"), Button[BCu]("Check", Evaluate(function = "checku"), background=green,enabled=false), TextField[replyu](width=10, editable=false, background=white), Button[BSu]("Show", Evaluate(function = "showu"), background=yellow,enabled=false) ], [ border=true, halign=none, caption="Step 3: Find the vector v = AB, tangent to the line: Enter it in the form [x,y].", "v = ", TextField[TFv](width=25, background=turquoise, editable=false), HorizontalGlue(), Button("Hint", Evaluate(function = "hintv"), background="Orange"), Button[BCv]("Check", Evaluate(function = "checkv"), background=green,enabled=false), TextField[replyv](width=10, editable=false, background=white), Button[BSv]("Show", Evaluate(function = "showv"), background=yellow,enabled=false) ], [ border=true, halign=none, caption="Step 4: Find a vector w, perpendicular to the line: Enter it in the form [x,y].", "w = ", TextField[TFw](width=25, background=turquoise, editable=false), HorizontalGlue(), Button("Hint", Evaluate(function = "hintw"), background="Orange"), Button[BCw]("Check", Evaluate(function = "checkw"), background=green,enabled=false), TextField[replyw](width=10, editable=false, background=white), Button[BSw]("Show", Evaluate(function = "showw"), background=yellow,enabled=false) ], [ border=true, halign=none, caption="Step 5: Find the scalar projection of u onto the perpendicular vector w:", "proj = ", TextField[TFproj](width=23, background=turquoise, editable=false), HorizontalGlue(), Button("Hint", Evaluate(function = "hintproj"), background="Orange"), Button[BCproj]("Check", Evaluate(function = "checkproj"), background=green,enabled=false), TextField[replyproj](width=10, editable=false,background=white), Button[BSproj]("Show", Evaluate(function = "showproj"), background=yellow,enabled=false) ], [ border=true, halign=none, caption="Step 6: Find the distance from the point to the line:", "D = ", TextField[TFD](width=25, background=turquoise, editable=false), HorizontalGlue(), Button("Hint", Evaluate(function = "hintD"), background="Orange"), Button[BCD]("Check", Evaluate(function = "checkD"), background=green,enabled=false), TextField[replyD](width=10, editable=false, background=white), Button[BSD]("Show", Evaluate(function = "showD"), background=yellow,enabled=false) ], [ TextBox[reply](width=40, height=4, editable=false, background=white) ], [ halign=none, "Instructor: Philip Yasskin", HorizontalGlue(), "Programmer: William W. Tarpley", HorizontalGlue(), "Copyright 2011, P. Yasskin" ] ] ) ): Display( DistancePointLine );