Jump to content

Learning Lisp "Polyline Width"


RubberDinero

Recommended Posts

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.

Link to comment
Share on other sites

  • Replies 29
  • Created
  • Last Reply

Top Posters In This Topic

  • RubberDinero

    14

  • Grrr

    8

  • Lee Mac

    4

  • Roy_043

    2

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

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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)

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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

Link to comment
Share on other sites

(/= (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! :)

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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!

Link to comment
Share on other sites

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.
Link to comment
Share on other sites

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

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...