Visual LISP, AutoLISP and General Customization
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Converting scientific numbers to decimal in AutoLisp

14 REPLIES 14
SOLVED
Reply
Message 1 of 15
cncah
1582 Views, 14 Replies

Converting scientific numbers to decimal in AutoLisp

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
		       )
		      )
		     )
		    )
		   )
	          )

 

14 REPLIES 14
Message 2 of 15
hgasty1001
in reply to: cncah

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

Message 3 of 15
_gile
in reply to: hgasty1001

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))



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 4 of 15
cncah
in reply to: _gile

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.

Message 5 of 15
Kent1Cooper
in reply to: hgasty1001


@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)

Kent Cooper, AIA
Message 6 of 15
Kent1Cooper
in reply to: _gile

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)

Kent Cooper, AIA
Message 7 of 15
cncah
in reply to: Kent1Cooper

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
                             )
                            )
                           )
                          )

 

 

 

 

Message 8 of 15
cncah
in reply to: cncah

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!

Message 9 of 15
_gile
in reply to: cncah

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)
)

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 10 of 15
cncah
in reply to: _gile

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?

Message 11 of 15
_gile
in reply to: cncah

(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)
)

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 12 of 15
Lee_Mac
in reply to: _gile

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 Smiley Happy

Message 13 of 15
cncah
in reply to: Lee_Mac

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)

 

Message 14 of 15
_gile
in reply to: cncah

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
    )
  )
)

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 15 of 15
cncah
in reply to: _gile

Thanks for the tip on using append instead of list. I really appreciate all the help!

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report

”Boost