Jump to content
RubberDinero

Learning Lisp "Polyline Width"

Recommended Posts

RubberDinero

I'm still learning Lisps and am in the need of a function. I'm not going to say what i need it for, i want to try and write the lisp from the input of this forum.

 

I need to know how to store the polyline width of a user selected polyline. for example, if i select a polyline and i run my lisp, or vice versa, the lisp will store the global width of the selected polyline into memory.

 

(setq PW (ssget "polyline width")

 

After i get this info, i will post my lisp and what it does. After you guys can share how you would have done it instead. and it will probably be better then my way.

 

thanks ahead of time.

Share this post


Link to post
Share on other sites
Lee Mac

Assuming you are referring to the global (constant) width of an LWPolyline, the width value is associated with DXF group 43:

(defun c:test ( / ent enx )
   (if (setq ent (car (entsel)))
       (if (= "LWPOLYLINE" (cdr (assoc 0 (setq enx (entget ent)))))
           (princ (strcat "\nThe polyline width is " (rtos (cdr (assoc 43 enx)))))
           (princ "\nThe selected object is not a polyline.")
       )
       (princ "\nNo object selected.")
   )
   (princ)
)

Share this post


Link to post
Share on other sites
RubberDinero
(defun c:test ( / ent enx )

(if (setq ent (car (entsel)))

(if (= "LWPOLYLINE" (cdr (assoc 0 (setq enx (entget ent)))))

(princ (strcat "\nThe polyline width is " (rtos (cdr (assoc 43 enx)))))

(princ "\nThe selected object is not a polyline.")

)

(princ "\nNo object selected.")

)

(princ)

)

this is kind of what i'm looking for, and maybe i can take it from here.

instead of String output, i want to put the value into memory to use within another command.

let me take a shot at it, and if i can't figure it out, i'll reach out for more help. Thanks!

Share this post


Link to post
Share on other sites
RubberDinero
Assuming you are referring to the global (constant) width of an LWPolyline, the width value is associated with DXF group 43:[/code]

 

Thanks to YOU! I did it!!! probably not as good as you would have done it, but i did it!

 

(defun c:px nil
   (if (setq ent (car (entsel)))
       (if (= "LWPOLYLINE" (cdr (assoc 0 (setq enx (entget ent)))))
           (setq pw (rtos (cdr (assoc 43 enx)))))
   )
(command "explode" ent)
(command "pedit" "m" "p" "" "w" pw"")
   (princ)
)

 

This lisp xplodes the polyline while keeping the width.

Technically, it gets the width, stores it in memory, explodes the LWPOLYLINE, converts the lines to LWPOLYLINE then adds the width of "pw"

 

it just clicked that i may need to add a "peditaccept" just incase most people have it set to 0.

 

I am curious as to how the better approach would be.

Share this post


Link to post
Share on other sites
BIGAL

Rather than calling it save in memory which is correct, you are saving a "Global" variable for further use in the same dwg session. The only problem may be if you write another program that uses pw. You can save variables within the dwg such as USERI1-5 5 integers, USERR1-5 5 reals

But again they can be overridden. If saving global variables maybe use a prefix GLBpw and keep a list somewhere of what you have used with a description.

 

(setvar "userr1" 0.25) ; sets userr1 value

(getvar "userr1") ; retrieves the value

 

(defun c:px ( / ent) ; implies ent is a local variable and will not be saved at end of defun

just me added a space after pw 
(command "pedit" "m" "p" "" "w" [color=red]pw ""[color=red])[/color]
[/color]

 

Almost forgot if your wanting to save a lot of variables and use them across drawings then save to a simple txt file and just read as required. Make it a library defun in acaddoc.lsp then can use when ever.

Share this post


Link to post
Share on other sites
RubberDinero
Rather than calling it save in memory which is correct, you are saving a "Global" variable for further use in the same dwg session.

 

Thanks.

I'm still learning Lisp and kind of understand the memory within the lisp. i used nil, because i wasn't 100% confident. i do understand the importance of it, so i'll add it just in case other lisps end up using "pw" as a variable.

 

Thanks everyone.

Share this post


Link to post
Share on other sites
Lee Mac
Thanks to YOU! I did it!!! probably not as good as you would have done it, but i did it!

 

Well done!

 

I am curious as to how the better approach would be.

 

There are numerous ways in which the code could be developed further in order to account for and mitigate against every possibility of an error - an initial improvement would be to account for a null or invalid selection, e.g.:

(defun c:px ( / cmd ent enx ped )
   (if (setq ent (car (entsel)))
       (if (= "LWPOLYLINE" (cdr (assoc 0 (setq enx (entget ent)))))
           (progn
               (setq cmd (getvar 'cmdecho)
                     ped (getvar 'peditaccept)
               )
               (setvar 'cmdecho 0)
               (setvar 'peditaccept 1)
               (command
                   "_.explode" ent
                   "_.pedit" "_m" "_p" "" "_w" (cdr (assoc 43 enx)) ""
               )
               (setvar 'peditaccept ped)
               (setvar 'cmdecho cmd)
           )
           (princ "\nThe selected object is not an LWPolyline.")
       )
       (princ "\nNo object selected.")
   )
   (princ)
)

But one could go further to account for locked layers, with checks to ensure that valid objects were generated following the call to the EXPLODE command prior to invoking the PEDIT command.

Share this post


Link to post
Share on other sites
Grrr
But one could go further to account for locked layers, with checks to ensure that valid objects were generated following the call to the EXPLODE command prior to invoking the PEDIT command.

Hi Lee,

I was curious would it be possible to account for locked layer with the entsel/nentsel approach, without using the:

(ssget "_+.:E:S:L")

I thought that the only way would be acessing entity's layer definition and retrieve from there if its status is locked. So the above line shows how much this issue is simplified. Another way I could think of is something like:

(setq s (ssadd))
(ssadd (car (entsel "\nSelect entity: ")) s)
(sssetfirst nil s)
(/= 0 (sslength (ssget "_.+:I:L"))); here we can check if the selected entity is on locked layer
(sssetfirst nil nil)

Share this post


Link to post
Share on other sites
Lee Mac

Here is an example:

(defun c:px ( / cmd ent enx ped )
   (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)
               (command
                   "_.explode" ent
                   "_.pedit" "_m" "_p" "" "_w" (cdr (assoc 43 enx)) ""
               )
               (setvar 'peditaccept ped)
               (setvar 'cmdecho cmd)
           )
       )
   )
   (princ)
)

Share this post


Link to post
Share on other sites
Grrr

Thank you, Lee

I've just wrote something similar:

(defun C:test ( / e enx )
(while 
	(not
		(and
			(setq e (car (entsel "\nSelect LWpolyline on non-locked layer: ")))
			(eq (cdr (assoc 0 (setq enx (entget e)))) "LWPOLYLINE")
			(/= (cdr (assoc 70 (entget (tblobjname "LAYER" (cdr (assoc 8 enx)))))) 4)
		)
	)
	e
)

(print enx); if successful
(princ)
)

I might need to study deeper this logand function as its not the first time I see its in use.

I think I'm done writing codes for today.

Share this post


Link to post
Share on other sites
RubberDinero
Here is an example:
(defun c:px ( / cmd ent enx ped )
   (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)
               (command
                   "_.explode" ent
                   "_.pedit" "_m" "_p" "" "_w" (cdr (assoc 43 enx)) ""
               )
               (setvar 'peditaccept ped)
               (setvar 'cmdecho cmd)
           )
       )
   )
   (princ)
)

 

WOW!!! Now that is the right way to do it!!!

on a side note, i keep re-writing and re-writing my code cuz i kept getting an error. turns out the global was not set and i kept getting an error.

 

after i ran yours and it also didn't work, i knew something was wrong. never did i think to check if the global width was set.

 

maybe there could be a variable to select either starting width or ending width if global is not set.

Share this post


Link to post
Share on other sites
RubberDinero
(command

"_.explode" ent

"_.pedit" "_m" "_p" "" "_w" (cdr (assoc 43 enx)) ""

)

 

I learn more from your code then from the book I'm reading.

I see now that I don't need to setq pw for assoc 43, i can simply invoke assoc 43 when i need that number.

 

I'm still a caveman in coding, but i'm trying to make that fire burn. that should be my CADTutor motto. lol.

Share this post


Link to post
Share on other sites
Lee Mac
(/= (cdr (assoc 70 (entget (tblobjname "LAYER" (cdr (assoc 8 enx)))))) 4)

I might need to study deeper this logand function as its not the first time I see its in use.

 

Indeed - DXF group 70 is typically bit-coded and therefore may not be equal to 4 if locked with other properties set (for example, test your code with an object residing on a locked layer which is frozen in new viewports).

 

I learn more from your code then from the book I'm reading.

 

That's great to hear! :)

Share this post


Link to post
Share on other sites
RubberDinero
(command

"_.explode" ent

"_.pedit" "_m" "_p" "" "_w" (cdr (assoc 43 enx)) ""

)

 

Where the following code is

(cdr (assoc 43 enx))

would it be possible to make that a variable and add an (if parameter stating that if the Constant width is null and (cdr (assoc 40)) is equal to (cdr (assoc 41) then width would be set to starting width.

If different, ask user input to choose either start or end

i.e. (initget "Start End"

where start is (cdr (assoc 40)) and end is (cdr (assoc 41))

 

i think that would wrap up this lisp of all errors.

Share this post


Link to post
Share on other sites
Grrr
Indeed - DXF group 70 is typically bit-coded and therefore may not be equal to 4 if locked with other properties set (for example, test your code with an object residing on a locked layer which is frozen in new viewports).

That was exactly my thought, I wasn't sure how to structure your answer as a question in my previous post, but you answered already. (english is not my first langugage).

Thank you for elaborating!

Share this post


Link to post
Share on other sites
broncos15
Where the following code is

(cdr (assoc 43 enx))

would it be possible to make that a variable and add an (if parameter stating that if the Constant width is null and (cdr (assoc 40)) is equal to (cdr (assoc 41) then width would be set to starting width.

If different, ask user input to choose either start or end

i.e. (initget "Start End"

where start is (cdr (assoc 40)) and end is (cdr (assoc 41))

 

i think that would wrap up this lisp of all errors.

Hint, look at dxf group codes 40 and 41 to find the starting and ending widths. Just need to put in a conditional statement where if dxf group code 43 is null, then move onto the 40 or 41 depending on your preference.

Share this post


Link to post
Share on other sites
RubberDinero

(defun c:px2 ( / cmd ent enx ped pw1 )
   (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)
[size="2"]	[b][color="red"]	(if (= (cdr (assoc 43 enx)) nil)
		(if (= (cdr (assoc 41 enx)) (cdr (assoc 40 enx)))
			(setq pw1 (cdr (assoc 40 enx)))
			(initget "Start End (cdr (assoc 40 enx)) (cdr (assoc 41 enx)))
			(setq pw1 (getkword "\nEnter an Option (Start/End): "))
		)
		(setq pw1 (cdr (assoc 43 enx)))
	)
               (command
                   "_.explode" ent
                   "_.pedit" "_m" "_p" "" "_w" pw1 ""
               )[/color][/b][/size]
               (setvar 'peditaccept ped)
               (setvar 'cmdecho cmd)
           )
       )
   )
   (princ)
)

 

I tried my caveman coding, but is it not possible to have an "IF" statement within an "IF" statement? or did I write the "(=" statement wrong?

Share this post


Link to post
Share on other sites
RubberDinero

(defun c:px2 ( / cmd ent enx ped pw1 )
   (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)))
			((initget "Start End (cdr (assoc 40 enx)) (cdr (assoc 41 enx))") (setq pw1 (getkword "\nEnter an Option (Start/End): ")))
		)
		(setq pw1 (cdr (assoc 43 enx)))
	)
               (command
                   "_.explode" ent
                   "_.pedit" "_m" "_p" "" "_w" pw1 ""
               )
               (setvar 'peditaccept ped)
               (setvar 'cmdecho cmd)
           )
       )
   )
   (princ)
)

 

HAD FORGOT TO PUT A END QUOTE!!! LOL!

But now when i do getkword it doesn't accept Start or End, it says invalid.

Share this post


Link to post
Share on other sites
RubberDinero
But now when i do getkword it doesn't accept Start or End, it says invalid.

 

i know see that initget are the acceptable keywords. now i need to set up the if statements.

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

×