PeterT Posted August 3, 2006 Share Posted August 3, 2006 Is there an easy way to determine which side of a line a user has clicked on? I am currently trying to do it by getting the angle of the line, then determining the 180? sweep between the positive and negative directions of the line, then getting the click point and comparing the angle between this point and the centerpoint of my line. If this click point angle falls within the sweep angle of my line, I will know which side ithe click is on. I am getting a little fouled up though, with the relatoionship of positive and negative REAL variables versus positive and negative angle values. Is there an easier way to do this, or does anyone have some insight that might help me figure this out? Any ideas appreciated. Quote Link to comment
islandmon Posted August 4, 2006 Share Posted August 4, 2006 Use of Radians avoids negative angles...1?=0.01745.., 90?=1.5708.., 180?=3.1415.. Quote Link to comment
MullinRJ Posted August 8, 2006 Share Posted August 8, 2006 Is there an easier way to do this, or does anyone have some insight that might help me figure this out? Easier to understand, or easier to implement? I think the angle way may be easier to understand, but harder to implement when you cross the ?180? boundary. Even with positive degrees/radians, there is a 0/360?, or 0/2Pi boundary to contend with. I prefer to use vectors and the cross product to determine 2D rotation. It may not be easier to understand, but it is easier to implement, especially with the following code. Enjoy, Raymond procedure XProd; { Show whether a user-selected Point is to the Right or Left of a user-drawn Line. } { Your vantage point is standing at point P1 and looking at point P2. } VAR P1, P2, P3 :Point; function InARow (P1, P2, P3: Point): Boolean; { Returns TRUE if the angle from line P1-P2 to point P3 is collinear. } Begin InARow := ((P1.x - P2.x) * (P3.y - P2.y) - (P3.x - P2.x) * (P1.y - P2.y)) = 0; End; { InARow } function RotateCCW (P1, P2, P3: Point): Boolean; { Returns TRUE if the angle from line P1-P2 to point P3 is CCW. } Begin RotateCCW := ((P1.x - P2.x) * (P3.y - P2.y) - (P3.x - P2.x) * (P1.y - P2.y)) < 0; End; { RotateCCW } BEGIN {Interactively draw a line and display it. } GetLine(P1.x, P1.y, P2.x, P2.y); MoveTo(P1.x, P1.y); LineTo(P2.x, P2.y); Redraw; { Get a point to compare to the line. } GetPt(P3.x, P3.y); { Herald in the answer and display it for all to see! } SysBeep; if InARow(P1, P2, P3) then AlrtDialog('You clicked ON the line.') else if RotateCCW (P1, P2, P3) then AlrtDialog('You clicked on the LEFT side of the line.') else AlrtDialog('You clicked on the RIGHT side of the line'); { Clean up - throw away the line. } DelObject(H); END; RUN(XProd); Quote Link to comment
PeterT Posted August 8, 2006 Author Share Posted August 8, 2006 Thanks Raymond, That is a very short and clean piece of code that does exactly what I wanted. ( I added the H variable and the H:= LNewObj to get the cleanup to execute) I guess I need to brush up on Vectors, I have not used them before. The formula seems to get a bit clearer after staring at it for a while. Are there any other Vector formulas I should be aware of? That one sure seems useful. As I get more familiar with the VectorScript language, and more familiar with the available procedures, the challange of scripting seems to shift towards figuring out what formulas to use to manipulate the data in the script. Thanks for the insight. Quote Link to comment
MullinRJ Posted August 9, 2006 Share Posted August 9, 2006 Hi Peter, You're welcome. Sorry about the dangling H. I had "H := LNewObj;" in there earlier then opted to lose the assignment for the following. It should read: DelObject(LNewObj); Either way works. I tend toward minimalism whenever it is convenient. The forumlae are really expanded versions of U x V or CrossProduct(U, V) where U and V are defined from the three points P1, P2 & P3. By using the expanded versions I forego calculating U, V & W. But if you want to try it, declare P1, P2 & P3 as type Vector instead of type Point along with vectors U, V & W. The answer for crosproduct in 2D math is always in the Z direction or the returned vector. If the Z component is positive the rotation is CCW; if it's negative, CW; if it's zero, then collinear. The magnitude is unimportant in this case. VAR P1, P2, P3, U, V, W :Vector; ... function InARow (P1, P2, P3: Vector): Boolean; ... function RotateCCW (P1, P2, P3: Vector): Boolean; ... { longhand } U := P2 - P1; V := P3 - P1; W := crossproduct(U, V); { or minimally } W := crossproduct(P2-P1, P3-P1); { the answer } message(W.z); { test Z component for +, -, or 0 } To answer your question, "Are there any other Vector formulas I should be aware of?", the short answer is YES. It would be difficult to give a rough overview of the field. Suffice it to say that all computer graphics are based on vectors and matrices. The obvious recommendation is to also become familiar with Unit, Norm and DotProduct. Unit scales a vector to length of 1, and Norm returns the length of a vector (it's always positive). So, Norm(Unit(V)) is always 1 (unless V has zero length). DotProduct can be used to indicate if two lines/vectors are parallel or perpendicular. if (DotProduct(Unit(U), Unit(V) = 1) then { U & V are parallel } if (DotProduct(Unit(U), Unit(V) = 0) then { U & V are perpendicular } If you have a more specific question in the future it may be easier to answer. Glad I could help, Raymond Quote Link to comment
_c_ Posted August 9, 2006 Share Posted August 9, 2006 Raymond, thank you, that's a long-wished-for introduction to vectors. I don't know if I ever read a clearer one. Lands straight into my code snippets collection. To dwell together with many other RMullin code-snippet-friends! Orso! Quote Link to comment
MullinRJ Posted August 10, 2006 Share Posted August 10, 2006 Small typo. The VS command I was referring to is called UnitVec, not Unit. Raymond Quote Link to comment
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.