I'm having a problem with trying to get the vertex points of a polyline in Autolisp. What I am currently needing to do is get the vertex points into a list, which I'm able to do. Then step through those points and do some comparisons on them to determine if that is the point where I'm going to mirror some entities around. But if the points are at X 0.0 or Y 0.0 they come in as: -2.17541e-031. I'm told that this is a scientific number and is so small that when I try to process it for comparison AutoCAD throws an error on me saying: bad argument type for compare: I tried running another loop after that and tell the program if the number is smaller than 0.0001 then set a new variable to zero and add it to a new list. But it tells me the same error. Is there a way around this? I appreciate any help.
(setq out(ssget "x" (list (cons 8 "Outside*")))) ;;Build a selection set from the outside boundary polyline (setq outname(ssname out 0)) ;;Get the name of the first entity in the selection set (setq outlist(entget outname)) ;;Get the DXF codes for the outside boundary (setq vertexlist1(list)) ;;Create an empty list for polyline vertex collection (foreach vtpt outlist (if (= 10 (car vtpt)) (setq vertexlist1 (append vertexlist1 (list (cdr vtpt) ) ) ) ) ) (setq vertexlist2(list)) ;;Create an empty list for converted vertex points (foreach vtpt vertexlist1 (if (< (car vtpt) 0.0001) (setq vtpt1 0) (if (< (cdr vtpt) 0.0001) (setq vtpt2 0) (setq vertexlist2 (append vertexlist2 (list vtpt1 vtpt2 ) ) ) ) ) )
Solved! Go to Solution.
Solved by _gile. Go to Solution.
Solved by _gile. Go to Solution.
Solved by Kent1Cooper. Go to Solution.
Hi,
The problem is you are trying to compare a list (y) to an atom y. Try changing this: (if (< (cdr vtpt) 0.0001) to (if (< (cadr vtpt) 0.0001) .
Gaston Nunez
Hi,
You can use something like this sub routine which converts any number, even in lists whatever the nesting level.
(defun trueZero (x) (cond ((listp x) (mapcar 'trueZero x)) ((and (numberp x) (< x 0.00001)) 0) (x) ) )
(trueZero 1e-12) => 0
(trueZero '(21 28 1e-12)) => (21 28 0)
(trueZero '((21 28 1e-12) (32 15 1e-12))) => ((21 28 0) (32 15 0))
Thanks for the feedback guys. I'll try those out as soon as I can. I had to get the program written pretty quick for immediate use so I kind of cheated and just did a move command of all entities -0.25,-0.25. Then processed the points did my mirroring and then moved the part back to 0,0. I'll go back and try to write a revised version of the program using the methods you suggested. Appreciate it.
@hgasty1001 wrote:
....
The problem is you are trying to compare a list (y) to an atom y. Try changing this: (if (< (cdr vtpt) 0.0001) to (if (< (cadr vtpt) 0.0001) .
....
I agree, but would also suggest that you add an element:
(if (< (abs (cadr vtpt)) 0.0001)
and similarly for the X component. After all, I assume that if the value is, say, -3, you don't want it changed to 0.
You could also handle the possibility of positive or negative values very close to zero this way:
(if (equal (cadr vtpt) 0 1e-4)
Same caveat as in my previous message....
(truezero '(-34 12 87))
returns
(0 12 87)
It should be something like:
(defun trueZero (x)
(cond
((listp x) (mapcar 'trueZero x))
((and (numberp x) (< (abs x) 0.00001)) 0)
(x)
)
)
Another approach:
(defun fixZero (ptlist)
(mapcar
'(lambda (coord) (if (equal coord 0 1e-8) 0 coord)) ;;; or whatever level of precision you prefer
ptlist
); mapcar
); defun
e.g.:
(fixZero '(-1.1234e-10 9e-11 -34))
returns
(0 0 -34)
Ok, so I tried the fixZero defun in my Measurement program and it keeps telling me this:
no function definition: FIXZERO
I haven't used sub-programs in my main programs with AutoLisp before, is the way I have this even close to being right?
(defun fixZero (ptlist) (mapcar '(lambda (coord) (if (equal coord 0 1e-8) 0 coord)) ;;; or whatever level of precision you prefer ptlist ); mapcar ); defun (setq out(ssget "x" (list (cons 8 "Outside*")))) ;;Build a selection set from the outside boundary polyline (setq outname(ssname out 0)) ;;Get the name of the first entity in the selection set (setq outlist(entget outname)) ;;Get the DXF codes for the outside boundary (setq vertexlist1(list)) ;;Create an empty list for polyline vertex collection (foreach vtpt outlist (if (= 10 (car vtpt)) (setq vertexlist1 (append vertexlist1 (list (cdr vtpt) ) ) ) ) ) (setq vertexlist2(list)) (foreach vtpt vertexlist1 (setq vtpt1 (car vtpt)) (setq vtpt2 (cadr vtpt)) (fixZero vtpt1) (fixZero vtpt2) (setq vertexlist2 (append vertexlist2 (list vtpt1 vtpt2 ) ) ) )
Nevermind, I got it. I was manually loading sections of the program and didn't load that defun before running the rest of the program. Thanks for the help Kent. This is what I ended up with:
(defun trueZero (x) (cond ((listp x) (mapcar 'trueZero x)) ((and (numberp x) (< (abs x) 0.00001)) 0) (x) ) ) ;-------------------------------------------- (setq out(ssget "x" (list (cons 8 "Outside*")))) (setq outname(ssname out 0)) (setq outlist(entget outname)) (setq vertexlist1(list)) (foreach vtpt outlist (if (= 10 (car vtpt)) (setq vertexlist1 (append vertexlist1 (list (cdr vtpt) ) ) ) ) )
This returns: ((-2.17541e-031 -1.77636e-015) (28.75 -5.29722e-015) (28.75 3.299) (4.04011e-016 3.299) (-2.17541e-031 -1.77636e-015))
Then:
(setq vertexlist2(list)) (foreach vtpt vertexlist1 (setq vtpt1 (car vtpt)) (setq vtpt2 (cadr vtpt)) (setq vtpt3(trueZero vtpt1)) (setq vtpt4(trueZero vtpt2)) (setq vertexlist2 (append vertexlist2 (list vtpt3 vtpt4 ) ) ) )
This returns: (0 0 28.75 0 28.75 3.299 0 3.299 0 0)
This is just what I needed. Thanks for all the help!
Oopss !... I posted too quick.
Try this:
(defun trueZero (x) (cond ((listp x) (mapcar 'trueZero x)) ((and (numberp x) (equal x 0 0.00001)) 0) (x) ) ) (defun test (/ out vertexList) (if (setq out (ssget "x" '((0 . "LWPOLYLINE") (8 . "Outside*")))) (foreach p (entget (ssname out 0)) (if (= 10 (car p)) (setq vertexList (cons (trueZero (cdr p)) vertexList)) ) ) ) (reverse vertexList) )
Is there a way to get the bulge value of each vertex point at the same time so that they are included in the list together?
(defun test (/ out vertexBulgeList)
(if (setq out (ssget "x" '((0 . "LWPOLYLINE") (8 . "Outside*"))))
(foreach p (entget (ssname out 0))
(if (= 10 (car p))
(setq vertexBulgeList (cons (trueZero (cdr p)) vertexBulgeList))
)
(if (= 42 (car p))
(setq vertexBulgeList
(cons (list (car vertexBulgeList) (cdr p))
(cdr vertexBulgeList)
)
)
)
)
)
(reverse vertexBulgeList)
)
You could also write it as:
(defun test ( / enx itm lst sel ) (if (setq sel (ssget "_x" '((0 . "LWPOLYLINE") (8 . "Outside*")))) (progn (setq enx (entget (ssname sel 0))) (while (setq itm (assoc 10 enx)) (setq lst (cons (list (truezero (cdr itm)) (cdr (assoc 42 enx))) lst) enx (cdr (member itm enx)) ) ) (reverse lst) ) ) )
Nice 'truezero' function gile
I appreciate the defun programs guys. It adds the bulge factor in between the points. I'm going to try and process the items in the list 2 items at a time so I need the bulge factor included with the points as a single item. This is what I came up with earlier today. I know it's not as pretty as the code you guys post on this site but I'm not quite sure how to get it done in the way I need. I appreciate all the help guys! Thanks A Ton Gile!
(setq vertexList (list)) ;;Clear vertexList (if (setq pkt (ssget "x" '((0 . "LWPOLYLINE") (8 . "*CutOut*")))) (foreach p (entget (ssname pkt index1)) (if (= 10 (car p)) (setq vertexList (cons (trueZero (cdr p)) vertexList)) ) ) ) ;-------------------------------------------------------------------- ;----------------Get A List Of the Bulges In First Pocket------------ (setq bulgeList (list)) ;;Clear bulgeList (if (setq pkt (ssget "x" '((0 . "LWPOLYLINE") (8 . "*CutOut*")))) (foreach p (entget (ssname pkt index1)) (if (= 42 (car p)) (setq bulgeList (cons (trueZero (cdr p)) bulgeList)) ) ) ) ;------------Add The List Of the Bulges To The List Of Vertices-------- (setq ptcount (length bulgeList)) (setq pocketList (list)) ;;Clear new list for combining the vertexList and bulgeList (setq index2 0) (repeat ptcount (setq pocketList (append pocketList (list (append (nth index2 vertexList) (list (nth index2 bulgeList))) ;;Add the bulge factor to the vertex ) ;;Close list ) ;;Close append ) ;;Close setq (setq index2 (+ index2 1)) ) ;;End repeat (reverse pocketList)
Hi,
Did you try the routines lee and I posted ?
Both return a list where each item is a sub-list containing the point and the bulge;
(((x1 y1) b1) ((x2 y2) b2) ...)
If you really need to flatten each sublist item, just use (append ...) instead of (list ..) when building each item in the loop.
(defun test (/ out vertexBulgeList) (if (setq out (ssget "x" '((0 . "LWPOLYLINE") (8 . "Outside*")))) (foreach p (entget (ssname out 0)) (if (= 10 (car p)) (setq vertexBulgeList (cons (trueZero (cdr p)) vertexBulgeList)) ) (if (= 42 (car p)) (setq vertexBulgeList (cons (append (car vertexBulgeList) (list (cdr p))) (cdr vertexBulgeList) ) ) ) ) ) (reverse vertexBulgeList) )
Or with Lee's
(defun test ( / enx itm lst sel ) (if (setq sel (ssget "_x" '((0 . "LWPOLYLINE") (8 . "Outside*")))) (progn (setq enx (entget (ssname sel 0))) (while (setq itm (assoc 10 enx)) (setq lst (cons (append (truezero (cdr itm)) (list (cdr (assoc 42 enx)))) lst) enx (cdr (member itm enx)) ) ) (reverse lst) ) ) )
Anyway, even if you prefer build two separated lists and concat their item after, you do not need to select the polyline twice neither lopp through its dXF data list twice.
(defun test (/ out vertexList bulgeList) (if (setq out (ssget "x" '((0 . "LWPOLYLINE") (8 . "Outside*")))) (foreach p (entget (ssname out 0)) (if (= 10 (car p)) (setq vertexList (cons (trueZero (cdr p)) vertexList)) ) (if (= 42 (car p)) (setq bulgeList (cons (cdr p) bulgeList)) ) ) ) (reverse (mapcar '(lambda (p b) (append p (list b))) vertexList bulgeList ) ) )