So I've done a lot of searching this morning on "angles", and I couldn't find anything for getting the "out-of-plane" angle.
I'd like the user to pick two points, and return somehow the angle out of plane.
Thanks
KP
This ... ?
(if (and (setq p (getpoint "\n First point :")) (setq p1 (getpoint "\n Second point :" p)) ) (print (angle p p1)) )
Maybe this .... ?
(if (and (setq a (getpoint "\n First point :")) (setq b (getpoint "\n Second point :" a)) ) (progn (setq ang (- (angle a b) (angle a (polar a 0.0 (distance a b))))) (print (* 180.0 (/ ang pi)) ) ) )
This returns the same value, which is the value IN plane, not OUT OF plane or FROM plane
Appreciate the efforts though
Would you upload an image or a drawing showing your desire of the XY plane 's angle?
It's the same principle as useing the distance command. When a user picks two points using the distance command there are some values retuned to the command prompt. I've copied an example based on two random points:
Distance = 1'-3 7/16", Angle in XY Plane = 314.97223515, Angle from XY Plane = 1.20000000
Delta X = 0'-10 233/256", Delta Y = -0'-10 235/256", Delta Z = 0'-0 83/256"
I'd like to have the exact value that represents "Angle from XY Plane" returned to a variable somehow.
Does this clean up what I'm asking?
Thanks
KP
@kpennell wrote:So I've done a lot of searching this morning on "angles", and I couldn't find anything for getting the "out-of-plane" angle.
I'd like the user to pick two points, and return somehow the angle out of plane.
....
Something like this, perhaps:
(setq
p1 (getpoint "\nPick first point: ")
p2 (getpoint "\nPick second point: ")
distinXY (distance (list (car p1) (cadr p1) 0) (list (car p2) (cadr p2) 0))
deltaZ (- (caddr p2) (caddr p1))
angfromXYplane (angtos (atan (/ deltaZ distinXY)))
)
or, with fewer variables:
(setq
p1 (getpoint "\nPick first point: ")
p2 (getpoint "\nPick second point: ")
); setq
(angtos
(atan
(/
(- (caddr p2) (caddr p1)); = change in Z
(distance (list (car p1) (cadr p1) 0) (list (car p2) (cadr p2) 0)); = distance projected in XY plane
); /
); atan
); angtos
I do find that it always returns positive values -- e.g. from 0,0,0 to 1,0,-1 returns 315 degrees. If you'd rather have that say -45 degrees, you'd need to do some conversion somewhere.
@Kent1Cooper wrote:....I do find that it always returns positive values -- e.g. from 0,0,0 to 1,0,-1 returns 315 degrees. If you'd rather have that say -45 degrees, you'd need to do some conversion somewhere.
Like this, for instance:
(setq
p1 (getpoint "\nPick first point: ")
p2 (getpoint "\nPick second point: ")
); setq
(strcat
(if (< (caddr p2) (caddr p1)) "-" "")
(angtos
(atan
(/
(abs (- (caddr p2) (caddr p1)))
(distance (list (car p1) (cadr p1) 0) (list (car p2) (cadr p2) 0))
); /
); atan
); angtos
); strcat
For some reasons, I wrote this code to replace native Distance command. It will give you the angle from XY plane among other infos.
(defun C:DI16 (/ *error* lst msg p1 p2 oldzin) (defun *error* (msg) (and msg (not (eq msg "Function cancelled")) (princ msg) ) (setvar 'dimzin oldzin) (princ) ) (setq oldzin (getvar 'dimzin)) (setvar 'dimzin 1) (and (setq p1 (getpoint "\nFirst Point: ")) (setq p2 (getpoint p1 "\nSecond Point: ")) (setq lst (mapcar '- p2 p1) lst1 (mapcar '(lambda (x) (rtos x 2 16)) lst) ) (setq lst1 (cons (angtos (atan (caddr lst) (sqrt (+ (expt (car lst) 2) (expt (cadr lst) 2)))) (getvar 'aunits) 16) lst1)) (setq lst1 (cons (angtos (atan (cadr lst) (car lst)) (getvar 'aunits) 16) lst1)) (setq lst1 (cons (rtos (distance p1 p2) 2 16) lst1)) (mapcar '(lambda (x msg) (princ (strcat msg x)) ) lst1 (list "\nDistance = " "\nAngle in XY Plane = " "\nAngle from XY Plane = " "\nDelta X = " "\nDelta Y = " "\nDelta Z = " ) ) ) (*error* nil) (textscr) (princ) )
This is almost it. The value that is returned depends on the units. This tells me that the true angle won't bereturned to do any real calculations.
Thanks KC
KP
Hey KC
Here's what I did. I removed the angtos function, which converts the value to a string based on the units of the drawing, and did the radians-to-degrees calculation.
It works out the way I wanted it too, with the added check to see whick point is/was lower than the other.
(setq p1 (getpoint "Select first point: "))
(setq p2 (getpoint "Select second point: "))
(setq ang (angle p1 p2))
(setq p1z (caddr p1))
(setq p2z (caddr p2))
(setq distinXY (distance (list (car p1) (cadr p1) 0) (list (car p2) (cadr p2) 0)))
(setq deltaZ (- (caddr p2) (caddr p1)))
(setq first_angle (atan (/ deltaZ distinXY)))
(cond
((< p1z p2z)(setq first_angle (* -180.0 (/ first_angle pi))))
((> p1z p2z)(setq first_angle (* 180.0 (/ first_angle pi))))
)
Thanks so much for the direction.
Hi,
I use this, is good for you?
(defun C:ID-Angle ( / pt_o pt_f dxf_11 ang ang_z)
(initget 8)
(setq pt_o (getpoint "\nGive the first point: "))
(if (null pt_o) (setq pt_o (getvar "lastpoint")))
(cond
(pt_o
(initget 41)
(setq pt_f (getpoint pt_o "\nGive the second point: "))
(cond
(pt_f
(setq dxf_11
(trans
(mapcar
'(lambda (x / ) (/ x (distance (trans pt_o 1 0) (trans pt_f 1 0))))
(mapcar '- (trans pt_f 1 0) (trans pt_o 1 0))
)
0 1 T
)
)
(if (zerop (car dxf_11))
(setq ang "infinity")
(setq ang (angtos (atan (/ (cadr dxf_11) (car dxf_11)))))
)
(if (= (caddr dxf_11) 1.0)
(setq dev_z "infinity")
(if (zerop (caddr dxf_11))
(setq ang_z (angtos 0.0))
(setq ang_z (angtos (atan (sqrt (/ 1.0 (- (/ 1.0 (* (caddr dxf_11) (caddr dxf_11))) 1.0))))))
)
)
(prompt (strcat "\nAngle in XY Plane = " ang " - Angle from XY Plane = " ang_z))
(alert (strcat "Angle in XY Plane = " ang " - Angle from XY Plane = " ang_z))
)
)
)
)
(prin1)
)
@kpennell wrote:....
Here's what I did. I removed the angtos function, which converts the value to a string based on the units of the drawing, and did the radians-to-degrees calculation.
It works out the way I wanted it too, with the added check to see whick point is/was lower than the other.
(setq p1 (getpoint "Select first point: "))
(setq p2 (getpoint "Select second point: "))
(setq ang (angle p1 p2))
(setq p1z (caddr p1))
(setq p2z (caddr p2))
(setq distinXY (distance (list (car p1) (cadr p1) 0) (list (car p2) (cadr p2) 0)))
(setq deltaZ (- (caddr p2) (caddr p1)))
(setq first_angle (atan (/ deltaZ distinXY)))
(cond
((< p1z p2z)(setq first_angle (* -180.0 (/ first_angle pi))))
((> p1z p2z)(setq first_angle (* 180.0 (/ first_angle pi))))
)
Thanks so much for the direction.
You're welcome. It wasn't clear from the initial message whether you wanted to just report the result to the User [what mine opted for] or make further use of it. Here's a more concise way to save a value for the latter, consolidating multiple (setq) functions into one, and eliminating some variables that are used only once, so they may as well just have their calculations at the places where they're used, and skip the variables.
(setq
p1 (getpoint "Select first point: ")
p2 (getpoint "Select second point: ")
deltaZ (- (caddr p2) (caddr p1))
first_angle
(/ ; start of radians-to-degrees conversion
(*
(if (> deltaZ 0) 1 -1); p2 above or below p1
180
(atan
(/
(abs deltaZ); positive whatever the relationship
(distance (list (car p1) (cadr p1) 0) (list (car p2) (cadr p2) 0)); XY differential
); end /
); end atan
); end *
pi
); end / & first_angle
); setq
Kent, you can shorten your code a little bit more.
If you use (abs deltaz) in combination with a positive number, ATAN function always returns a number between 0 and pi / 2, so you don't need (if (> deltaZ 0) 1 -1).
Atan function can take 2 arguments, so no need (/ (abs deltaZ) (distance ...
Further, if you use (atan (/ a b)) and b is zero, you get "divide by zero.." message. (atan a b) will take care of that situation and will return pi / 2. But you already know that...
So, your code may look like:
(setq p1 (getpoint "Select first point: ") p2 (getpoint "Select second point: ") deltaZ (- (caddr p2) (caddr p1)) first_angle (/ ; start of radians-to-degrees conversion (* ;;; (if (> deltaZ 0) 1 -1); p2 above or below p1 180 (atan ;;; (/ (abs deltaZ); positive whatever the relationship (distance (list (car p1) (cadr p1) 0) (list (car p2) (cadr p2) 0)); XY differential ;;; ); end / ); end atan ); end * pi ); end / & first_angle ); setq
@phanaem wrote:Kent, you can shorten your code a little bit more.
If you use (abs deltaz) in combination with a positive number, ATAN function always returns a number between 0 and pi / 2, so you don't need (if (> deltaZ 0) 1 -1).
Atan function can take 2 arguments, so no need (/ (abs deltaZ) (distance ...
Further, if you use (atan (/ a b)) and b is zero, you get "divide by zero.." message. (atan a b) will take care of that situation and will return pi / 2. But you already know that...
So, your code may look like:
....
I think you may have missed part of the purpose. If the two points are [for example] 0,0,0 and 1,0,-1, with the second point at a downward angle from the first relative to the XY plane, the return is -45.0 from both my routine and kpennell's, but from yours it's 45.0 [positive], the same return as if the second point were 1,0,[+]1. So you do need the (if (> deltaZ 0) 1 -1) line, or some other way [I can think of at least one] to give a negative return for a second point lower than the first point.
No, I wasn't aware of (atan) optionally taking two arguments, so yes, the (/) function could be removed. Dividing by zero would happen only if the two selected points are the same in the XY coordinates [above/below each other or coincident]. If they are the same point [including Z], yours would return 0,0, implying that the second point is at a 0-degree angle from the first point relative to the XY plane [the same as if they were, say, 0,0,0 and 1,0,0]. Technically, AutoCAD would consider it to be, just as the (angle) function returns 0 if it's given the same point twice, but I would consider it to be at no angle. I couldn't say what the OP would prefer, but for me, I think I would want to be warned that I had picked the same point twice. Probably a check on that, before the angle calculation, would be best, because it would preserve the viability of points vertically aligned, whereas leaving it to a divide-by-zero error message wouldn't.
Yes, I missed that part on the negative angle. In this case, is even easier. The second argument in atan function is always positive so the angle returned is from -pi/2 to pi/2.
(setq p1 (getpoint "Select first point: ") p2 (getpoint "Select second point: ") first_angle (/ (* 180 (atan (- (caddr p2) (caddr p1)) (distance (list (car p1) (cadr p1)) (list (car p2) (cadr p2))) ) ) pi ) )
Remains to solve the situation when the same point is picked twice..
@Anonymous wrote:
You know what would be incredible useful? To have Kent Cooper's lisp "ReportSlope.slp" to give you the data FROM the xy plane, and not OF the xy plane.
....
That should be doable enough. ReportSlope.lsp is restricted to reporting the angle from the X axis in the XY plane [as described in the comments at the top] because that's what the (angle) function returns, ignoring any Z-direction component. So it would need to calculate the 3D angle otherwise, but that's not hard.
But some questions:
Would it be better to report an absolute-value kind of angle, as ReportSlope.lsp does, or would you want to distinguish between upward and downward slopes? For instance, would a Line from 0,0,0 to 1,0,1 be reported as 45 degrees, but one from 0,0,0 to 1,0,-1 as -45 degrees, or should they both be considered just 45 degrees?
What about a Line drawn between the same points, but in the opposite direction? Should a Line drawn from 1,0,1 to 0,0,0 be -45 degrees because that's its drawn direction, or [+]45 degrees because that's its angle off the XY plane? What about if neither end is on the XY plane?
@Kent1Cooper wrote:
@Anonymous wrote:
You know what would be incredible useful? To have Kent Cooper's lisp "ReportSlope.slp" to give you the data FROM the xy plane, and not OF the xy plane.
........
Would it be better to report an absolute-value kind of angle...?
....
On the assumption that the answer to the question above is Yes, try the attached ReportSlopeZ.lsp with its RSZ command. If you want other permutations on how it decides whether an angle is positive or negative, how to deal with things entirely away from the XY plane, etc., describe them, and maybe they can be worked in. Lightly tested.
Can't find what you're looking for? Ask the community or share your knowledge.