Jump to content
RubberDinero

Learning Lisp "Polyline Width"

Recommended Posts

RubberDinero

No matter what I try, i keep getting an "Invalid Option Keyword". Here is what i have so far. don't know why i can't make it work.

 

(defun c:px2 ( / cmd ent enx ped pw1 pkw )
   (setvar 'errno 0)
   (while (/= 52 (getvar 'errno))
       (setvar 'errno 0)
       (setq ent (car (entsel "\nSelect polyline <exit>: ")))
       (cond
           (   (= 7 (getvar 'errno))
               (prompt "\nMissed, try again.")
           )
           (   (null ent)
               (prompt "\nExit.")
           )
           (   (/= "LWPOLYLINE" (cdr (assoc 0 (setq enx (entget ent)))))
               (prompt "\nSelected object is not an LWPolyline.")
           )
           (   (= 4 (logand 4 (cdr (assoc 70 (tblsearch "layer" (cdr (assoc 8 enx)))))))
               (prompt "\nSelected polyline is on a locked layer.")
           )
           (   (setq cmd (getvar 'cmdecho)
                     ped (getvar 'peditaccept)
               )
               (setvar 'cmdecho 0)
               (setvar 'peditaccept 1)
	[b][color="red"][size="3"](if (= (cdr (assoc 43 enx)) nil)
		(if (= (cdr (assoc 41 enx)) (cdr (assoc 40 enx)))
			(setq pw1 (cdr (assoc 40 enx)))
			((initget "Start End")
			 (setq pkw (getkword "\nMatch Starting or Ending Width? [start/End]: "))
				(cond
					((= pkw "S") (setq pw1 (cdr (assoc 40 enx))))
					((= pkw "E") (setq pw1 (cdr (assoc 41 enx))))
				)
			)
		)
		(setq pw1 (cdr (assoc 43 enx)))
	)[/size][/color][/b]
               (command
                   "_.explode" ent
                   "_.pedit" "_m" "_p" "" "_w" pw1 ""
               )
               (setvar 'peditaccept ped)
               (setvar 'cmdecho cmd)
           )
       )
   )
   (princ)
)

 

I'm able to click on Start or End, but doing so will give me the error. I've also tried typing S s E e Start START End END but i keep getting the error.

I've also tried localizing the strings i.e.

[color="red"][size="3"](initget "Start End _(cdr (assoc 40 enx)) (cdr (assoc 41 enx))")[/size][/color]

but that also doesn't allow any option to be correct. same error no matter what i type.

 

I'm all out of ideas.

Share this post


Link to post
Share on other sites
Grrr

Try the following (modified RED code fragment from your post) :

(if (= (cdr (assoc 43 enx)) nil)
(if (= (cdr (assoc 41 enx)) (cdr (assoc 40 enx)))
	(setq pw1 (cdr (assoc 40 enx)))
	(progn
		(initget "Start End S E")
		(setq pkw (strcase (getkword "\nMatch Starting or Ending Width? [start/End]: ")))
		(cond
			((or (= pkw "START")(= pkw "S")) (setq pw1 (cdr (assoc 40 enx))))
			((or (= pkw "END")(= pkw "E")) (setq pw1 (cdr (assoc 41 enx))))
		)
	); progn
)
(setq pw1 (cdr (assoc 43 enx)))
)

Share this post


Link to post
Share on other sites
Grrr
@ Grrr:

Your use of (initget ...) is not correct.

See:

http://docs.autodesk.com/ACD/2011/ENU/filesALR/WS1a9193826455f5ff1a32d8d10ebc6b7ccc-69da.htm

 

Note that (getkword ...) can also return nil.

 

Thanks, I was sure about that.. so I rely on the (cond) below it. Its not the first time I do this mistake, I'm just lazy to analyse this particular problem.

Share this post


Link to post
Share on other sites
RubberDinero
Try the following (modified RED code fragment from your post)

 

Wow, that worked great! The lisp is now complete!

 

I'll need to study how you did it and learn from it! Thanks

 

To anyone that runs into this thread looking for a fail-proof way to "Unjoin a polyline" "explode a polyline while keeping the width"

 

here is the Lisp

(defun c:px ( / cmd ent enx ped pw1 pkw )
   (setvar 'errno 0)
   (while (/= 52 (getvar 'errno))
       (setvar 'errno 0)
       (setq ent (car (entsel "\nSelect polyline <exit>: ")))
       (cond
           (   (= 7 (getvar 'errno))
               (prompt "\nMissed, try again.")
           )
           (   (null ent)
               (prompt "\nExit.")
           )
           (   (/= "LWPOLYLINE" (cdr (assoc 0 (setq enx (entget ent)))))
               (prompt "\nSelected object is not an LWPolyline.")
           )
           (   (= 4 (logand 4 (cdr (assoc 70 (tblsearch "layer" (cdr (assoc 8 enx)))))))
               (prompt "\nSelected polyline is on a locked layer.")
           )
           (   (setq cmd (getvar 'cmdecho)
                     ped (getvar 'peditaccept)
               )
               (setvar 'cmdecho 0)
               (setvar 'peditaccept 1)
	(if (= (cdr (assoc 43 enx)) nil)
		(if (= (cdr (assoc 41 enx)) (cdr (assoc 40 enx)))
			(setq pw1 (cdr (assoc 40 enx)))
				(progn
					(initget "Start End S E")
					(setq pkw (strcase (getkword "\nMatch Starting or Ending Width? [start/End]: ")))
			(cond
			((or (= pkw "START")(= pkw "S")) (setq pw1 (cdr (assoc 40 enx))))
			((or (= pkw "END")(= pkw "E")) (setq pw1 (cdr (assoc 41 enx))))
		)
	); progn
)
(setq pw1 (cdr (assoc 43 enx)))
)
               (command
                   "_.explode" ent
                   "_.pedit" "_m" "_p" "" "_w" pw1 ""
               )
               (setvar 'peditaccept ped)
               (setvar 'cmdecho cmd)
           )
       )
   )
   (princ)
)

Share this post


Link to post
Share on other sites
Grrr
Wow, that worked great! The lisp is now complete!

 

I'll need to study how you did it and learn from it! Thanks

 

You're wellcome. For a quick/successful start with LISP I would suggest you to read/practice with these functions: if , cond , and , or , not , eq , while , repeat

So later you would know how to properly structure your codes (by using functions for getting user input - like getkword/getstring/getpoint/getreal ...)

... and manipulating it.

Share this post


Link to post
Share on other sites
Roy_043

@ Grrr: you are missing several issues.

For one thing your code cannot cope with a nil return from (getkword). It would crash as (strcase) expects string input. And, contrary to what you say, your (cond) does not have a statement to handle pkw=nil, which would be required since the rest of the code relies on a valid value for pw1.

(progn
 (initget "Start End")
 (if (= "End" (getkword "\nMatch Starting or Ending Width? End/<Start>: "))
   (setq pw1 (cdr (assoc 41 enx))) ; User entered "E", "e", "end", "EN" or ... (no need for strcase).
   (setq pw1 (cdr (assoc 40 enx))) ; User pressed Enter or entered "S", "s", "start", "STA" or ...
 )
)

Share this post


Link to post
Share on other sites
RubberDinero
(progn
 (initget "Start End")
 (if (= "End" (getkword "\nMatch Starting or Ending Width? End/<Start>: "))
   (setq pw1 (cdr (assoc 41 enx))) ; User entered "E", "e", "end", "EN" or ... (no need for strcase).
   (setq pw1 (cdr (assoc 40 enx))) ; User pressed Enter or entered "S", "s", "start", "STA" or ...
 )
)

 

That did work even better! I tried Grrr's code by just pressing "Enter" and it did fail. with your code, I modified the wording a bit, it defaults to Starting by pressing enter.

(defun c:px2 ( / cmd ent enx ped pw1 pkw pwt )
   (setvar 'errno 0)
   (while (/= 52 (getvar 'errno))
       (setvar 'errno 0)
       (setq ent (car (entsel "\nSelect polyline <exit>: ")))
       (cond
           (   (= 7 (getvar 'errno))
               (prompt "\nMissed, try again.")
           )
           (   (null ent)
               (prompt "\nExit.")
           )
           (   (/= "LWPOLYLINE" (cdr (assoc 0 (setq enx (entget ent)))))
               (prompt "\nSelected object is not an LWPolyline.")
           )
           (   (= 4 (logand 4 (cdr (assoc 70 (tblsearch "layer" (cdr (assoc 8 enx)))))))
               (prompt "\nSelected polyline is on a locked layer.")
           )
           (   (setq cmd (getvar 'cmdecho)
                     ped (getvar 'peditaccept)
               )
               (setvar 'cmdecho 0)
               (setvar 'peditaccept 1)
	(if (= (cdr (assoc 43 enx)) nil)
		(if (= (cdr (assoc 41 enx)) (cdr (assoc 40 enx)))
			(setq pw1 (cdr (assoc 40 enx)))
				[b][color="red"](progn
				  (initget "Start End")
				  (if (= "End" (getkword "\nMatch Starting or Ending Width? [start/End]:<Start> "))
				    (setq pw1 (cdr (assoc 41 enx))) ; User entered "E", "e", "end", "EN" or ... (no need for strcase).
				    (setq pw1 (cdr (assoc 40 enx))) ; User pressed Enter or entered "S", "s", "start", "STA" or ...
				  )
				)[/color][/b]
)
(setq pw1 (cdr (assoc 43 enx)))
)
               (command
                   "_.explode" ent
                   "_.pedit" "_m" "_p" "" "_w" pw1 ""
               )
               (setvar 'peditaccept ped)
               (setvar 'cmdecho cmd)
           )
       )
   )
   (princ)
)

Share this post


Link to post
Share on other sites
Grrr
@ Grrr: you are missing several issues.

For one thing your code cannot cope with a nil return from (getkword). It would crash as (strcase) expects string input. And, contrary to what you say, your (cond) does not have a statement to handle pkw=nil, which would be required since the rest of the code relies on a valid value for pw1.

(progn
 (initget "Start End")
 (if (= "End" (getkword "\nMatch Starting or Ending Width? End/<Start>: "))
   (setq pw1 (cdr (assoc 41 enx))) ; User entered "E", "e", "end", "EN" or ... (no need for strcase).
   (setq pw1 (cdr (assoc 40 enx))) ; User pressed Enter or entered "S", "s", "start", "STA" or ...
 )
)

 

Thanks for the constructive criticism Roy,

Perhaps I don't analyse deep enough the solutions I'm posting (usually I use initget with bit 1 to prevent user from pressing ENTER). Your example seems perfect for this case, however I try to avoid using if within initget, and use instead (practice with) cond - just in case we would had more than 2 options:

(defun c:test ( / sUndo cmd ent enx ped pw1 pkw pwt *ans*)
(setq sUndo (vlax-invoke (vla-get-ActiveDocument (vlax-get-acad-object)) 'StartUndoMark))
(setvar 'errno 0)
(while (/= 52 (getvar 'errno))
	(setvar 'errno 0)
	(setq ent (car (entsel "\nSelect polyline <exit>: ")))
	(cond
		(   (= 7 (getvar 'errno))
			(prompt "\nMissed, try again.")
		)
		(   (null ent)
			(prompt "\nExit.")
		)
		(   (/= "LWPOLYLINE" (cdr (assoc 0 (setq enx (entget ent)))))
			(prompt "\nSelected object is not an LWPolyline.")
		)
		(   (= 4 (logand 4 (cdr (assoc 70 (tblsearch "layer" (cdr (assoc 8 enx)))))))
			(prompt "\nSelected polyline is on a locked layer.")
		)
		(   (setq cmd (getvar 'cmdecho)
			ped (getvar 'peditaccept)
		)
		(setvar 'cmdecho 0)
		(setvar 'peditaccept 1)
		[color="red"](if (not (assoc 43 enx))
			(cond
				((= (cdr (assoc 41 enx)) (cdr (assoc 40 enx)))
					(setq pw1 (cdr (assoc 40 enx)))
				)
				(T
					(or *ans* (setq *ans* "Starting")) ; Used http://www.lee-mac.com/promptwithdefault.html Dynamic Default Version2
					(initget "Starting Ending Value") 
					(setq *ans* (cond ((getkword (strcat "\nMatch Starting or Ending Width or specify a Value [start/End/Value] ? <" *ans* ">: "))) ( *ans* )))
					(cond
						((wcmatch *ans* "S*")
							(setq pw1 (cdr (assoc 40 enx)))
						)
						((wcmatch *ans* "E*")
							(setq pw1 (cdr (assoc 41 enx)))
						)
						((wcmatch *ans* "V*")
							(initget (+ 1 4))
							(setq pw1 (getreal "\nSpecify width value: "))
						)
					)
				)
			)
			(setq pw1 (cdr (assoc 43 enx)))
		)[/color]
		(if pw1 
			(command
				"_.explode" ent
				"_.pedit" "_m" "_p" "" "_w" pw1 ""
			)
		)
		(setvar 'peditaccept ped)
		(setvar 'cmdecho cmd)
		)
	)
)
(if sUndo (vlax-invoke (vla-get-ActiveDocument (vlax-get-acad-object)) 'EndUndoMark))
(princ)
)(vl-load-com)(princ)

Lee mac's website always come to the rescue.

Share this post


Link to post
Share on other sites
RubberDinero

Grrr!!! your new code made possible what i had in mind! but i felt i had already overstepped my welcome with request! But thanks to your latest response, i was able to add what i wanted to add but was getting error-ed out.

 

(defun c:px2 ( / sUndo cmd ent enx ped pw1 pkw *ans*)
(setq sUndo (vlax-invoke (vla-get-ActiveDocument (vlax-get-acad-object)) 'StartUndoMark))
(setvar 'errno 0)
(while (/= 52 (getvar 'errno))
	(setvar 'errno 0)
	(setq ent (car (entsel "\nSelect polyline <exit>: ")))
	(cond
		(   (= 7 (getvar 'errno))
			(prompt "\nMissed, try again.")
		)
		(   (null ent)
			(prompt "\nExit.")
		)
		(   (/= "LWPOLYLINE" (cdr (assoc 0 (setq enx (entget ent)))))
			(prompt "\nSelected object is not an LWPolyline.")
		)
		(   (= 4 (logand 4 (cdr (assoc 70 (tblsearch "layer" (cdr (assoc 8 enx)))))))
			(prompt "\nSelected polyline is on a locked layer.")
		)
		(   (setq cmd (getvar 'cmdecho)
			ped (getvar 'peditaccept)
		)
		(setvar 'cmdecho 0)
		(setvar 'peditaccept 1)
		(if (not (assoc 43 enx))
			(cond
				((= (cdr (assoc 41 enx)) (cdr (assoc 40 enx)))
					(setq pw1 (cdr (assoc 40 enx)))
				)
				(T
					(or *ans* (setq *ans* "Starting")) ; Used http://www.lee-mac.com/promptwithdefault.html Dynamic Default Version2
					(initget "Starting Ending Value") 
					(setq *ans* (cond ((getkword
(strcat [color="red"]"\nStarting Width is " (rtos (cdr (assoc 40 enx))) ". Ending Width is " (rtos (cdr (assoc 41 enx)))[/color]". Match Starting or Ending Width or specify a Value [start/End/Value] ? <" *ans* ">: "))) ( *ans* )))
					(cond
						((wcmatch *ans* "S*")
							(setq pw1 (cdr (assoc 40 enx)))
						)
						((wcmatch *ans* "E*")
							(setq pw1 (cdr (assoc 41 enx)))
						)
						((wcmatch *ans* "V*")
							(initget (+ 1 4))
							(setq pw1 (getreal "\nSpecify width value: "))
						)
					)
				)
			)
			(setq pw1 (cdr (assoc 43 enx)))
		)
		(if pw1 
			(command
				"_.explode" ent
				"_.pedit" "_m" "_p" "" "_w" pw1 ""
			)
		)
		(setvar 'peditaccept ped)
		(setvar 'cmdecho cmd)
		)
	)
)
(if sUndo (vlax-invoke (vla-get-ActiveDocument (vlax-get-acad-object)) 'EndUndoMark))
(princ)
)(vl-load-com)(princ)

 

I don't know why when i added the (strcat, the lisp would error out on me no matter where in the code i placed it.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×