(defun c:ang2dist nil
(setq obj (vlax-ename->vla-object (setq ent (car (entsel ))))) ;;select block/vla
(setq baseblk (vlax-get obj 'insertionpoint)) ;; base point
(setq sspline (ssget "_C" (mapcar '+ baseblk '(5 5)) (mapcar '- baseblk '(10 10)) '((0 . "LWPOLYLINE")(8 . "pline")))) ; select pline
(setq entpline (ssname sspline 0))
(setq vert (vlax-curve-getendparam entpline)) ;get total verticie
(setq id 0) ; number verticie id
(setq dist (- (vlax-curve-getdistatparam entpline (1+ id)) (vlax-curve-getdistatparam entpline id))) ;get dist verticie id
(setq ang (angle '(0.0 0.0 0.0) (vlax-curve-getfirstderiv entpline id))) ;get angle verticie -> radian
(setq lst (list (list (r2d ang) dist))) ; creat list
)
r2d link here >> https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/bearing-and-distance-lisp-modification/td-p/9373785
(defun r2d (r) (if (>= (* 180.0 (/ r pi)) 360) (- (* 180.0 (/ r pi)) 360) (* 180.0 (/ r pi))))
Solved! Go to Solution.
Solved by pbejse. Go to Solution.
Solved by Kent1Cooper. Go to Solution.
Solved by dlanorh. Go to Solution.
Removed should have looked at dwg 1st.
Is pline Clockwise or anticlock wise ? Needs an answer.
The vertices as a list is easy so make a list of Blk ins to vert point, distance and angle, find closest one ie smallest distance. Then just loop through the list again vertice dist ang outputting.
(setq plent (entsel "\nPick pline"))
(if plent (setq co-ord (mapcar 'cdr (vl-remove-if-not '(lambda (x) (= (car x) 10)) (entget (car plent))))))
@Anonymous wrote:example: if I select the block with attribute 01 it returns me (128.75 42.0185)
attribute block 05 (308.75 42.0185 276.103 12.6343)
attribute block 02 (96.103 12.6343 132.667 23.556) [...]
Are those the expected results based on your sample drawing? or is it something else?
Are you trying to get the angle and distance from the insertion point of each block to the nearest vertex of the polyline?
Or are you trying to get the angle and distance of each polyline segment?
When I run your code on your drawing it always returns (128.75 42.0185). This is the angle (not the bearing) and distance of the first segment of the polyline, irrespective of which block I select. This is because you are always checking the angle and distance of the polyline from (id) to (+ id 1) (vertex 0 to vertex 1) no matter which block you select
I am not one of the robots you're looking for
Or are you trying to get the angle and distance of each polyline segment?
Exact angle and distance !!!
When I run your code on your drawing it always returns (128.75 42.0185). This is the angle (not the bearing) and distance of the first segment of the polyline, irrespective of which block I select. This is because you are always checking the angle and distance of the polyline from (id) to (+ id 1) (vertex 0 to vertex 1) no matter which block you select
I realized this, I wanted to understand how to get the ID of the vertices in front of each block. generating the result that I showed in the example.
@Anonymous
I can see that you use the term vertex ID. Do you know how's that related to the curve's "parameter"?
(vlax-curve-GetParamAtPoint...) Do you understand what the value of "param" (parameter) represents? Is the value of a parameter different for different curve types? Line vs. polyline...
If someone knows where is some nice (possibly graphical) explanation what param represents, please share the link here. I don't know and don't want to draw it... thx
So where is the issue?
Get the list of all vertices (coordinates), sort them by a distance to your ins-point, then get the param of the closest one.
This should sort it.
(defun c:ang2dist ( / obj baseblk sspline ent ep cpt cp fp pp np ang dist lst)
(setq obj (vlax-ename->vla-object (setq ent (car (entsel ))))) ;;select block/vla
(setq baseblk (vlax-get obj 'insertionpoint)) ;; base point
(setq sspline (ssget "_C" (mapcar '+ baseblk '(5 5)) (mapcar '- baseblk '(10 10)) '((0 . "LWPOLYLINE")(8 . "pline")))) ; select pline
(setq ent (ssname sspline 0))
(setq ep (vlax-curve-getendparam ent)
cpt (vlax-curve-getclosestpointto ent baseblk)
cp (vlax-curve-getparamatpoint ent cpt)
fp (rem cp 1.0)
cp (fix cp)
)
(if (> fp 0.49999)
(setq cp (1+ cp) pp (if (> cp 0) (1- cp) nil) np (if (< cp ep) (1+ cp) nil))
(setq pp (if (> cp 0) (1- cp) nil) np (if (< cp ep) (1+ cp) nil))
)
(cond ( (and cp np)
(setq ang (angle (vlax-curve-getpointatparam ent cp) (vlax-curve-getpointatparam ent np))
dist (distance (vlax-curve-getpointatparam ent cp) (vlax-curve-getpointatparam ent np))
lst (cons (list (r2d ang) dist) lst)
)
)
)
(cond ( (and cp pp)
(setq ang (angle (vlax-curve-getpointatparam ent cp) (vlax-curve-getpointatparam ent pp))
dist (distance (vlax-curve-getpointatparam ent cp) (vlax-curve-getpointatparam ent pp))
lst (cons (list (r2d ang) dist) lst)
)
)
)
(setq lst (apply 'append lst))
)
You will still need to insert (defun r2d)
(Edited to correct code)
I am not one of the robots you're looking for
Here's my approach:
(defun c:ang2dist (/ ent baseblk sspline entpline neapt idpar idpt predata postdata)
(setq
ent (car (entsel "\nSelect Block: "))
baseblk (cdr (assoc 10 (entget ent))) ; base point
sspline (ssget "_C" (mapcar '+ baseblk '(5 5)) (mapcar '- baseblk '(5 5)) '((0 . "LWPOLYLINE") (8 . "pline"))) ; find pline
entpline (ssname sspline 0)
neapt (vlax-curve-getClosestPointTo entpline baseblk) ; closest point to Block insertion
idpar (fix (+ (vlax-curve-getParamAtPoint entpline neapt) 0.5)); nearest whole parameter value
idpt (vlax-curve-getPointAtParam entpline idpar); vertex location there
predata
(if (setq prept (vlax-curve-getPointAtParam entpline (1- idpar)))
(list
(read (angtos (angle idpt prept) 0 4)) ; angle to previous vertex [degrees]
(distance idpt prept); distance to there
); list
); if & predata
postdata
(if (setq postpt (vlax-curve-getPointAtParam entpline (1+ idpar)))
(list
(read (angtos (angle idpt postpt) 0 4)) ; angle to following vertex [degrees]
(distance idpt postpt); distance to there
); list
); if & postdata
lst (append predata postdata) ; create list
); setq
); defun
It doesn't require a radians-to-degrees conversion function, and it doesn't require converting the Block to a VLA object, and it doesn't require determining the number of vertices, nor sorting them in any way, and it uses a simpler way to find the closest vertex to a Block's insertion point.
I kept most of your variable names, but adjusted some for clarity [and added some]. I left 'lst' out of the localized variables list, so it will survive after the end of the routine.
For a Block closest to an end vertex, the data about the direction from there that doesn't exist will simply be nil, so the final list will include only the information about the direction that does exist.
[The singular is vertex; the plural is vertices.]
@Kent1Cooper wrote:
Here's my approach:
(defun c:ang2dist (/ ent baseblk sspline entpline neapt idpar idpt predata postdata) ... predata (if (setq prept (vlax-curve-getPointAtParam entpline (1- idpar))) (list (read (angtos (angle idpt prept) 0 4)) (distance idpt prept) ) ) postdata (if (setq postpt (vlax-curve-getPointAtParam entpline (1+ idpar))) (list (read (angtos (angle idpt postpt) 0 4)) (distance idpt postpt) ) ) lst (append predata postdata) ) )
Nice @Kent1Cooper , I only got to the point postdata and left it at that 😊
👍
@dlanorh wrote:
This should sort it.
(setq ang (angle (vlax-curve-getpointatparam ent cp) (vlax-curve-getpointatparam ent np) ) dist (distance (vlax-curve-getpointatparam ent cp) (vlax-curve-getpointatparam ent np) ) lst (cons (list (r2d ang) dist) lst) ) ...
I used a similar approach to get the data, then i run out of gas 😊
(mapcar '(lambda (f)
(f (vlax-curve-getpointatparam e pr)
(vlax-curve-getpointatparam e pr+)
)
)
(list angle distance))
For me like the others find the closest pline. then just get its vertices ((x y) (x y) (x y)...) then make a distance function
This is distance from insert point to the (nth of the co-ords, save as a list ((ang dist)...) once smallest is found you know the starting position in your vertice list so can proceed till end of this list with angle and distance.
You know, MJ, that Owen Wengerd advised us not to rely on parameters. But I think that's only because he can create polylines with "quirky" parameters. He's a genius in my book. The way I see it, parameters are the indices for vertices, starting at zero. Like @Kent1Cooper, I have never had a problem using parameters within polylines. There are plenty of Visual Lisp functions that can convert a parameter to a point or distance, and vice versa. I really can't do without them. I think my favorite is getfirstderiv which returns the angle as a vector of the tangent at any point.
God bless Peter Petrov!
John F. Uhden
@Kent1Cooper wrote "[The singular is vertex; the plural is vertices.]"
I am impressed with your progress with grammar.
Test, which is correct?
A. A group of men see the sunset.
or
B. A group of men sees the sunset.
John F. Uhden
Another...
(defun c:ang2dist (/ rtd Ll&Ur _PointsAndParam blocks i sspline e point pts atv v prv nxt data ) (defun rtd (a) (/ (* a 180.0) pi)) (defun _PointsAndParam (e / p l) (if (eq (setq p (vlax-curve-getEndParam e)) (fix p)) (repeat (setq p (1+ (fix p))) (setq l (cons (list (setq p (1- p)) (vlax-curve-getPointAtParam e p) ) l ) ) ) ) ) (defun Ll&Ur (p f) (setq fz 10.00);<--- size of the box (polar p (* pi f) (* fz (sqrt 2))) ) (if (setq blocks (ssget '((0 . "INSERT") (66 . 1)))) (repeat (setq i (sslength blocks)) (setq e (ssname blocks (setq i (1- i)))) (setq ipoint (cdr (assoc 10 (entget e)))) (setq atv (getpropertyvalue e "NUMBER")) ;<--- Hard coded TAG name (if (setq sspline (ssget "C" (Ll&Ur ipoint 0.25) (Ll&Ur ipoint 1.25) '((0 . "LWPOLYLINE") (8 . "pline")) ) ) (progn (setq pts (_PointsAndParam (setq pl (ssname sspline 0)))) (setq v (vl-sort pts '(lambda (a b) (< (distance ipoint (Cadr a)) (distance ipoint (Cadr b)) ) ) ) ) (setq DAta (cons (list atv (append (if (setq prv (assoc (1- (Caar v)) pts)) (list (rtd (angle (cadar v) (cadr prv))) (distance (cadar v) (cadr prv)) ) ) (if (setq nxt (assoc (1+ (Caar v)) pts)) (list (rtd (angle (cadar v) (cadr nxt))) (distance (cadar v) (cadr nxt)) ) ) ) ) Data ) ) ) ) ) ) Data )
Select objects: (("05" (308.75 42.0185 276.103 12.6343)) ("01" (128.75 42.0185)) ("02" (96.103 12.6343 132.667 23.556)) ("03" (312.667 23.556 136.959 53.9246)))
This version uses the selected polylines coordinates in line with @Sea-Haven suggestion instead of closestpointto approach.
HTH
Can't find what you're looking for? Ask the community or share your knowledge.