Jump to content

[LISP] Scaling just the "x" and "y" axis


chiimayred

Recommended Posts

Hey,

 

I am looking to write a lisp routine that, among other things, creates a block and scales it in the x and y but not z (this is a requirement for a coordinate conversion from a client)... I haven't been able to figure it out yet.

 

My thoughts were to add a sort of break in the command where the user can click on the block and change the scales manually, but I don't know how to add such a break. Here's my attempt:

 

(DEFUN C:CC ()
 (COMMAND
   "_.SCALE"
   "_ALL"
   ""
   '(0 0)
   3.28084
   "_BLOCK"
   "1"
   '(0 0)
   "_ALL"
   ""
   (prompt "change x and y scale of block to 1.025")
   break
   "_.explode"
   )
 )

 

Any help would be appreciated.

 

Thanks,

 

CR

Link to comment
Share on other sites

How about something like this?

 

(defun c:cc ( / newscl)
   (setq blk (car (entsel "\nSelect the block to change the X and Y to 1.025 : ")))
       (setq newscl 1.025)

       (entmod
           (subst
               (cons 41 newscl)
               (assoc 41 (entget blk))
               (entget blk)
           )
       )
       (entmod
           (subst
               (cons 42 newscl)
               (assoc 42 (entget blk))
               (entget blk)
           )
       )
           (entupd blk)
 (princ)
)

 

Do you want everything scaled from metric to imperial first, or just the blocks? Either way, I would run this separately.

 

At the break, are you looking to allow the user to manually override the 1.025 default?

Link to comment
Share on other sites

How about something like this?

 

(defun c:cc ( / newscl)
   (setq blk (car (entsel "\nSelect the block to change the X and Y to 1.025 : ")))
       (setq newscl 1.025)

       (entmod
           (subst
               (cons 41 newscl)
               (assoc 41 (entget blk))
               (entget blk)
           )
       )
       (entmod
           (subst
               (cons 42 newscl)
               (assoc 42 (entget blk))
               (entget blk)
           )
       )
           (entupd blk)
 (princ)
)

 

Do you want everything scaled from metric to imperial first, or just the blocks? Either way, I would run this separately.

 

At the break, are you looking to allow the user to manually override the 1.025 default?

 

I would like everything scaled first.

 

I am looking for the user somehow select the block entity created and scaling the x and y axis without scaling the z. the only way i know how to do this currently is to make the contours into a block, scaling the x and y via the properties and exploding the block.

 

Also, if you could go line by as to what each command means and why you're deciding to go this route... extreme beginner here.

 

Thanks!

 

CR

Link to comment
Share on other sites

CheSyn , you can shorten your code to the following besides that , it is a good practice to include if function to check none nil return value

from the first variable . ;)

 

(defun c:Test (/ blk newscl)
 (if (setq blk (car (entsel "\nSelect the block to change the X and Y to 1.025 : ")))
   (entmod (append (entget blk)
                   (list (cons 41 1.025) (cons 42 1.025))
           )))
 (princ)
)

Link to comment
Share on other sites

Thanks for the heads-up Tharwat! I added a prompt for the if function as well.

 

I didn't realize append and list could be used in conjunction with entmod; it looks much cleaner. Is there a time/place where "subst" would be preferred, and if so, why/where?

 

Chiimayred, I included some comments below. I still feel scaling from metric to imperial would best be done in a separate command. The block will now explode upon completion of the command.

 

(defun c:cc ( / blk newscl)
   (if
       (setq blk (car (entsel "\nSelect the block to change : ")))
       (progn
           (setq newscl
               (getreal ; set newscl as a real number
                   (strcat "\nSpecify the scale factor < 1.025 > : "); string prompt
               )
           )
               (if ; if newscl does not have a value associated with it, set the value as 1.025
                   (=
                       nil
                       newscl
                   )
                       (setq newscl 1.025)
               )
               (entmod ; modifies the properties of the entity
                   (append ; combines the list
                       (entget blk); indicates what entity to edit
                       (list ; create a list of properties to change
                           (cons 41 newscl)
                           (cons 42 newscl)
                       )
                   )
               )
                   (entupd blk); updates the block
               (command "_.explode" blk "")
       )
       (prompt "\nNo selection made!")
   )
 (princ)
)

Link to comment
Share on other sites

I think I may have been a bit misunderstood.

 

After I scale the drawing, I am making the whole drawing into a block. As a result I don't need to select the block as the whole drawing is a block. I am looking for a way to just scale the X and Y axis of that block, as the Z can't be scaled at this point in the conversion.

 

I don't quite understand how cons 41 and cons 42 play into this, but that seems to work.

 

I just need to figure out how to select the one block, scale about cons 41 and cons 42 and then explode it and purge the block.

 

Thanks,

 

CR

Link to comment
Share on other sites

Thanks for the heads-up Tharwat! I added a prompt for the if function as well.

 

You're very welcome .

 

 

I didn't realize append and list could be used in conjunction with entmod; it looks much cleaner. Is there a time/place where "subst" would be preferred, and if so, why?

 

Each function has its own performance and I have used the append function since that I have more than one substitute dxf code to

replace otherwise I would go for subst function immediately .

Link to comment
Share on other sites

Tharwat, being somewhat new to LISP, I was apprehensive of using lists. Seeing how useful they are, I will look more into them.

 

Chiimayred, cons 41 & 42 are referring to the DXF codes 41 & 42. DXF 41 refers to X-scale, DXF 42 refers to Y-scale, and DXF 43 refers to Z-scale. I did not include DXF 43 because you did not want it altered.

 

What specifically is missing from the posted LISP that you would like added/altered?

Link to comment
Share on other sites

Tharwat, being somewhat new to LISP, I was apprehensive of using lists. Seeing how useful they are, I will look more into them.

 

Chiimayred, cons 41 & 42 are referring to the DXF codes 41 & 42. DXF 41 refers to X-scale, DXF 42 refers to Y-scale, and DXF 43 refers to Z-scale. I did not include DXF 43 because you did not want it altered.

 

What specifically is missing from the posted LISP that you would like added/altered?

 

Thanks Chesyn, I will have to look into DXF codes.

 

Instead of getting input from the user, just straight up selecting the block created and scaling it.

 

Thanks, both of you for your help so far

 

CR

Link to comment
Share on other sites

Let me know if this is what you are looking for.

 

(defun c:cc ( / sset blk newscl)
   (if
           (setq sset (ssget "_x" (list '(0 . "INSERT") (cons 410 (getvar "ctab")))))
       (progn
    (setq blk (ssname sset 0))
               (entmod ; modifies the properties of the entity
                   (append ; combines the list
                       (entget blk); indicates what entity to edit
                       (list ; create a list of properties to change
                           (cons 41 1.025)
                           (cons 42 1.025)
                       )
                   )
               )
                   (entupd blk); updates the block
               (command "_.explode" blk "")
       )
       (prompt "\nNo blocks in drawing!")
   )
 (princ)
)

Edited by CheSyn
update to use selection set
  • Like 1
Link to comment
Share on other sites

Let me know if this is what you are looking for.

 

(defun c:cc ( / blk newscl)
   (if
       (setq blk (car (entsel "\nSelect the block to change : ")))

       (progn
               (entmod ; modifies the properties of the entity
                   (append ; combines the list
                       (entget blk); indicates what entity to edit
                       (list ; create a list of properties to change
                           (cons 41 1.025)
                           (cons 42 1.025)
                       )
                   )
               )
                   (entupd blk); updates the block
               (command "_.explode" blk "")
       )
       (prompt "\nNo selection made!")
   )
 (princ)
)

 

I'm looking to get rid of the "entsel" portion of it and just have the lisp select the only entity in the drawing without any input from the user.

Link to comment
Share on other sites

Let me know if this is what you are looking for.

 

I think the OP does not want to select any block so you need to go with ssget function with the mode "_X" and iterate into the selection set entity names one by one .

Link to comment
Share on other sites

Chiimayred, I have updated the code I posted on the previous page. I am assuming, based on your description that there will only be one block in the drawing when you use this command.

 

Tharwat, please check my update and let me know if I'm on the right track (time permitting, of course) :)

Link to comment
Share on other sites

Tharwat, please check my update and let me know if I'm on the right track (time permitting, of course) :)

 

Almost well , but please find the new changes on your codes into the following routine .

 

Let's hope that the user have all layers UNLOCKED to avoid the rainy error messages . :D

(defun c:test (/ sset blk newscl n)
 (if (setq sset (ssget "_x" (list '(0 . "INSERT") (cons 410 (getvar "ctab")))))
   (repeat (setq n (sslength sset))
     (setq blk (ssname sset (setq n (1- n))))
     (entmod  (append  (entget blk) (list (cons 41 1.025) (cons 42 1.025))))
     (command "_.explode" blk "")
   )
   (prompt "\nNo blocks in drawing!")
 )
 (princ)
)

Link to comment
Share on other sites

Almost well , but please find the new changes on your codes into the following routine .

 

Let's hope that the user have all layers UNLOCKED to avoid the rainy error messages . :D

 

I see! Just in case more than one block is present, correct?

Link to comment
Share on other sites

I see! Just in case more than one block is present, correct?

 

Correct if you are talking about the changes in the codes , but if you are talking about the second paragraph , so I can tell if any of the selected blocks in on locked layer , the code can not change the scale and nor to explode it .

Link to comment
Share on other sites

Correct if you are talking about the changes in the codes , but if you are talking about the second paragraph , so I can tell if any of the selected blocks in on locked layer , the code can not change the scale and nor to explode it .

 

Yes, I was responding to the first paragraph. But I will keep both points in mind :D

Link to comment
Share on other sites

(defun c:utm2bp (/ blk)
 (command
   "_.scale"
   "_all"
   ""
   '(0 0)
   3.28084
   "_block"
   "1"
   '(0 0)
   "_all"
   ""
   )
 (if (setq sset (ssget "_x" (list '(0 . "INSERT") (cons 410 (getvar "ctab")))))
   (repeat (setq n (sslength sset))
     (setq blk (ssname sset (setq n (1- n))))
     (entmod  (append  (entget blk) (list (cons 41 1.025) (cons 42 1.025))))
     (command "_.explode" blk "")
   )
   (prompt "\nNo blocks in drawing!")
   )
 (princ)
 )

 

here's what it looks like... i keep on getting a "No Blocks in Drawing" prompt when I run this lisp...

Link to comment
Share on other sites

I would suggest the following:

(defun c:utm2bp ( / blk sel )
   (if (= 1 (getvar 'cvport))
       (princ "\nCommand only available in Modelspace.")
       (if (setq sel (ssget "_X" '((410 . "Model"))))
           (progn
               (setq blk 0)
               (while (tblsearch "block" (itoa (setq blk (1+ blk)))))
               (setq blk (itoa blk))
               (command
                   "_.scale" sel "" "_non" '(0 0) 3.28084
                   "_.-block"  blk  "_non" '(0 0) sel ""
                   "_.-insert" blk  "_non" '(0 0) 1.025 1.025 0.0
                   "_.explode" (entlast)
                   "_.-purge" "_b" blk "_N" 
               )
           )
           (princ "\nNo objects found in Modelspace.")
       )
   )
   (princ)
)

Link to comment
Share on other sites

I would suggest the following:

(defun c:utm2bp ( / blk sel )
   (if (= 1 (getvar 'cvport))
       (princ "\nCommand only available in Modelspace.")
       (if (setq sel (ssget "_X" '((410 . "Model"))))
           (progn
               (setq blk 0)
               (while (tblsearch "block" (itoa (setq blk (1+ blk)))))
               (setq blk (itoa blk))
               (command
                   "_.scale" sel "" "_non" '(0 0) 3.28084
                   "_.-block"  blk  "_non" '(0 0) sel ""
                   "_.-insert" blk  "_non" '(0 0) 1.025 1.025 0.0
                   "_.explode" (entlast)
                   "_.-purge" "_b" blk "_N" 
               )
           )
           (princ "\nNo objects found in Modelspace.")
       )
   )
   (princ)
)

 

Hey, I am currently trying it out... could you explain the use of the while command, tblsearch, progn and this little bit of code

 

   (setq blk 0)
               (while (tblsearch "block" (itoa (setq blk (1+ blk)))))
               (setq blk (itoa blk))

Thanks for your time, help and patience.

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