Jump to content

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


chiimayred

Recommended Posts

could you explain the use of the while command, tblsearch, progn and this little bit of code...

 

Here is a heavily commented version:

([color=BLUE]defun[/color] c:utm2bp ( [color=BLUE]/[/color] blk sel )
   [color=GREEN];; Define function, declare local variable symbols[/color]
   [color=GREEN];; To understand why variable declaration is an important[/color]
   [color=GREEN];; practice, see [url]http://lee-mac.com/localising.html[/url][/color]
   ([color=BLUE]if[/color] [color=GREEN];; If the following expression returns a non-nil value[/color]
       ([color=BLUE]=[/color] 1 ([color=BLUE]getvar[/color] 'cvport))
       [color=GREEN];; The CVPORT system variable will equal 1 when the[/color]
       [color=GREEN];; user is in paperspace.[/color]
       ([color=BLUE]princ[/color] [color=MAROON]"\nCommand only available in Modelspace."[/color])
       [color=GREEN];; If so, inform the user that the command is only[/color]
       [color=GREEN];; available for use in Modelspace.[/color]
       ([color=BLUE]if[/color] [color=GREEN];; If the following expression returns a non-nil value[/color]
           ([color=BLUE]setq[/color] sel ([color=BLUE]ssget[/color] [color=MAROON]"_X"[/color] '((410 . [color=MAROON]"Model"[/color]))))
           [color=GREEN];; Retrieve a selection set of all graphical entities[/color]
           [color=GREEN];; residing in Modelspace (the Model layout).[/color]
           ([color=BLUE]progn[/color]
               [color=GREEN];; Evaluate the following expressions and return the result[/color]
               [color=GREEN];; of the last expression evaluated. PROGN is used as a[/color]
               [color=GREEN];; wrapper function so that we can pass multiple expressions[/color]
               [color=GREEN];; to the IF function as a single argument constituting the[/color]
               [color=GREEN];; 'then' parameter.[/color]
               ([color=BLUE]setq[/color] blk 0)
               [color=GREEN];; Initialise the 'blk' variable to 0[/color]
               [color=GREEN];; (this will become the temporary block name)[/color]

               [color=GREEN];; While the temporary block name already exists...[/color]
               ([color=BLUE]while[/color] [color=GREEN];; while the following expression returns a non-nil value[/color]
                   ([color=BLUE]tblsearch[/color] [color=MAROON]"block"[/color] [color=GREEN];; Query the block table for the following symbol[/color]
                       ([color=BLUE]itoa[/color] [color=GREEN];; Convert the following integer value to a string[/color]
                           ([color=BLUE]setq[/color] blk ([color=BLUE]1+[/color] blk)) [color=GREEN];; Increment the 'blk' variable by one[/color]
                       ) [color=GREEN];; end ITOA[/color]
                   ) [color=GREEN];; end TBLSEARCH[/color]
               ) [color=GREEN];; end WHILE[/color]
               ([color=BLUE]setq[/color] blk ([color=BLUE]itoa[/color] blk))
               [color=GREEN];; Assign the string representation of integer value of the 'blk' variable[/color]
               [color=GREEN];; to the 'blk' symbol (overwriting the existing value)[/color]
               ([color=BLUE]command[/color] [color=GREEN];; Evaluate the following arguments at the command-line:[/color]
                   [color=MAROON]"_.scale"[/color] sel [color=MAROON]""[/color] [color=MAROON]"_non"[/color] '(0 0) 3.28084
                   [color=GREEN];; Scale all entities in the selection set[/color]
                   [color=GREEN];; Base point at 0,0 and scale factor 3.28084[/color]
                   [color=MAROON]"_.-block"[/color]  blk  [color=MAROON]"_non"[/color] '(0 0) sel [color=MAROON]""[/color]
                   [color=GREEN];; Create a temporary block definition with name equal to the value of the 'blk' variable[/color]
                   [color=GREEN];; Base point at 0,0 containing all entities in the set (i.e. all entities in Modelspace)[/color]
                   [color=MAROON]"_.-insert"[/color] blk  [color=MAROON]"_non"[/color] '(0 0) 1.025 1.025 0.0
                   [color=GREEN];; Insert the new block at the origin with scale 1.025 in the X&Y axes[/color]
                   [color=MAROON]"_.explode"[/color] ([color=BLUE]entlast[/color])
                   [color=GREEN];; Explode the last entity added to the drawing database (i.e. the block reference)[/color]
                   [color=GREEN];; More error-trapping is potentially required here to ensure that the last entity[/color]
                   [color=GREEN];; added to the drawing database is indeed the block reference to be exploded;[/color]
                   [color=GREEN];; setting the undocumented QAFLAGS system variable to zero should also be[/color]
                   [color=GREEN];; considered since a value containing bit-code 1 will cause the EXPLODE command[/color]
                   [color=GREEN];; to accept selection sets when called through AutoLISP.[/color]
                   [color=MAROON]"_.-purge"[/color] [color=MAROON]"_b"[/color] blk [color=MAROON]"_N"[/color]
                   [color=GREEN];; Purge the temporary block definition from the block table[/color]
               ) [color=GREEN];; end COMMAND[/color]
           ) [color=GREEN];; end PROGN[/color]
           ([color=BLUE]princ[/color] [color=MAROON]"\nNo objects found in Modelspace."[/color])
           [color=GREEN];; Else 'sel' is null and no entities were found in the Modelspace drawing layout.[/color]
       ) [color=GREEN];; end IF[/color]
   ) [color=GREEN];; end IF[/color]
   ([color=BLUE]princ[/color]) [color=GREEN];; Suppress the return of the last evaluated expression[/color]
) [color=GREEN];; end DEFUN[/color]

I would ask that you please repay the time I that have invested by studying my comments carefully.

 

To understand the purpose of any function that you do not understand, I would recommend that you first consult the documentation.

Link to comment
Share on other sites

Here is a heavily commented version:

([color=BLUE]defun[/color] c:utm2bp ( [color=BLUE]/[/color] blk sel )
   [color=GREEN];; Define function, declare local variable symbols[/color]
   [color=GREEN];; To understand why variable declaration is an important[/color]
   [color=GREEN];; practice, see [url]http://lee-mac.com/localising.html[/url][/color]
   ([color=BLUE]if[/color] [color=GREEN];; If the following expression returns a non-nil value[/color]
       ([color=BLUE]=[/color] 1 ([color=BLUE]getvar[/color] 'cvport))
       [color=GREEN];; The CVPORT system variable will equal 1 when the[/color]
       [color=GREEN];; user is in paperspace.[/color]
       ([color=BLUE]princ[/color] [color=MAROON]"\nCommand only available in Modelspace."[/color])
       [color=GREEN];; If so, inform the user that the command is only[/color]
       [color=GREEN];; available for use in Modelspace.[/color]
       ([color=BLUE]if[/color] [color=GREEN];; If the following expression returns a non-nil value[/color]
           ([color=BLUE]setq[/color] sel ([color=BLUE]ssget[/color] [color=MAROON]"_X"[/color] '((410 . [color=MAROON]"Model"[/color]))))
           [color=GREEN];; Retrieve a selection set of all graphical entities[/color]
           [color=GREEN];; residing in Modelspace (the Model layout).[/color]
           ([color=BLUE]progn[/color]
               [color=GREEN];; Evaluate the following expressions and return the result[/color]
               [color=GREEN];; of the last expression evaluated. PROGN is used as a[/color]
               [color=GREEN];; wrapper function so that we can pass multiple expressions[/color]
               [color=GREEN];; to the IF function as a single argument constituting the[/color]
               [color=GREEN];; 'then' parameter.[/color]
               ([color=BLUE]setq[/color] blk 0)
               [color=GREEN];; Initialise the 'blk' variable to 0[/color]
               [color=GREEN];; (this will become the temporary block name)[/color]

               [color=GREEN];; While the temporary block name already exists...[/color]
               ([color=BLUE]while[/color] [color=GREEN];; while the following expression returns a non-nil value[/color]
                   ([color=BLUE]tblsearch[/color] [color=MAROON]"block"[/color] [color=GREEN];; Query the block table for the following symbol[/color]
                       ([color=BLUE]itoa[/color] [color=GREEN];; Convert the following integer value to a string[/color]
                           ([color=BLUE]setq[/color] blk ([color=BLUE]1+[/color] blk)) [color=GREEN];; Increment the 'blk' variable by one[/color]
                       ) [color=GREEN];; end ITOA[/color]
                   ) [color=GREEN];; end TBLSEARCH[/color]
               ) [color=GREEN];; end WHILE[/color]
               ([color=BLUE]setq[/color] blk ([color=BLUE]itoa[/color] blk))
               [color=GREEN];; Assign the string representation of integer value of the 'blk' variable[/color]
               [color=GREEN];; to the 'blk' symbol (overwriting the existing value)[/color]
               ([color=BLUE]command[/color] [color=GREEN];; Evaluate the following arguments at the command-line:[/color]
                   [color=MAROON]"_.scale"[/color] sel [color=MAROON]""[/color] [color=MAROON]"_non"[/color] '(0 0) 3.28084
                   [color=GREEN];; Scale all entities in the selection set[/color]
                   [color=GREEN];; Base point at 0,0 and scale factor 3.28084[/color]
                   [color=MAROON]"_.-block"[/color]  blk  [color=MAROON]"_non"[/color] '(0 0) sel [color=MAROON]""[/color]
                   [color=GREEN];; Create a temporary block definition with name equal to the value of the 'blk' variable[/color]
                   [color=GREEN];; Base point at 0,0 containing all entities in the set (i.e. all entities in Modelspace)[/color]
                   [color=MAROON]"_.-insert"[/color] blk  [color=MAROON]"_non"[/color] '(0 0) 1.025 1.025 0.0
                   [color=GREEN];; Insert the new block at the origin with scale 1.025 in the X&Y axes[/color]
                   [color=MAROON]"_.explode"[/color] ([color=BLUE]entlast[/color])
                   [color=GREEN];; Explode the last entity added to the drawing database (i.e. the block reference)[/color]
                   [color=GREEN];; More error-trapping is potentially required here to ensure that the last entity[/color]
                   [color=GREEN];; added to the drawing database is indeed the block reference to be exploded;[/color]
                   [color=GREEN];; setting the undocumented QAFLAGS system variable to zero should also be[/color]
                   [color=GREEN];; considered since a value containing bit-code 1 will cause the EXPLODE command[/color]
                   [color=GREEN];; to accept selection sets when called through AutoLISP.[/color]
                   [color=MAROON]"_.-purge"[/color] [color=MAROON]"_b"[/color] blk [color=MAROON]"_N"[/color]
                   [color=GREEN];; Purge the temporary block definition from the block table[/color]
               ) [color=GREEN];; end COMMAND[/color]
           ) [color=GREEN];; end PROGN[/color]
           ([color=BLUE]princ[/color] [color=MAROON]"\nNo objects found in Modelspace."[/color])
           [color=GREEN];; Else 'sel' is null and no entities were found in the Modelspace drawing layout.[/color]
       ) [color=GREEN];; end IF[/color]
   ) [color=GREEN];; end IF[/color]
   ([color=BLUE]princ[/color]) [color=GREEN];; Suppress the return of the last evaluated expression[/color]
) [color=GREEN];; end DEFUN[/color]

I would ask that you please repay the time I that have invested by studying my comments carefully.

 

To understand the purpose of any function that you do not understand, I would recommend that you first consult the documentation.

 

Thanks, that's exactly what I needed... I'm going to print it off for reference. I have been consulting the help in my AutoCAD program with some avail.

Link to comment
Share on other sites

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

 

I would ask that you please repay the time I that have invested by studying my comments carefully.

 

Nice coding, Lee. I might have asked the same question the OP did. The thing is, you did a very professional job; whereas, most times, most users will not need to be so careful, as they can almost certainly come up with a Block Name unique to whatever they might be handling. And if they don't the first time, they will probably be able to fix that very quickly, e.g., it's very doubtful there is a block named after themselves, unless they created it themselves. So, if you are handling the code personally in-house, no need for the fancy tablesearch while loop, just set the Block Name and proceed. But if you are providing the code for a client, then the professional approach is the ticket. This is the sort of thing that may not be clear simply by studying documentation. Over to you, Lee.

 

BTW, I'm not sure what happened, but it looked like the others got confused about there only being the one self-created block to handle.

Link to comment
Share on other sites

Thank you neophoible, though my code is hardly a professional job, just a quick hack to provide the OP with an example to study.

 

If I were to write the program for a client, I would include far more error trapping than is currently present, including conditionals to check for locked layers and other possible eventualities. I would most likely also port the entire program to Visual LISP, and use the ActiveX copyobjects method to transfer the necessary objects to a block definition, before inserting the block reference, exploding & removing the block definition all using relevant ActiveX methods, since such methods are not only faster than using in-built AutoCAD commands, but far more predictable to work with programmatically and the program has more control over the methods.

 

I disagree with your point about the redundancy of the check for an existing block name - when writing a program, I hold the opinion that one should attempt to account for every eventuality, hence, if there is a chance that an identical block name already exists and we have the means to avoid the program crashing, this should certainly be implemented, regardless of the likelyhood of this occurring.

Link to comment
Share on other sites

Thank you neophoible, though my code is hardly a professional job, just a quick hack to provide the OP with an example to study.

 

If I were to write the program for a client, I would include far more error trapping than is currently present, including conditionals to check for locked layers and other possible eventualities. I would most likely also port the entire program to Visual LISP, and use the ActiveX copyobjects method to transfer the necessary objects to a block definition, before inserting the block reference, exploding & removing the block definition all using relevant ActiveX methods, since such methods are not only faster than using in-built AutoCAD commands, but far more predictable to work with programmatically and the program has more control over the methods.

 

I disagree with your point about the redundancy of the check for an existing block name - when writing a program, I hold the opinion that one should attempt to account for every eventuality, hence, if there is a chance that an identical block name already exists and we have the means to avoid the program crashing, this should certainly be implemented, regardless of the likelyhood of this occurring.

Point taken about level of professionalism, Lee. And I would say that it rather agrees with my point about the block name. Also, I'm looking at it more from a less experienced coder's side. It's hardly necessary to be so thorough with the block name, if I'm the one handling it, especially if it means I don't have to mess with the table searching. Just put the Block Name in and go. It's good to know how to do the table searching, and I would certainly encourage one to learn about it. But if I'm handling the program to fix some drawings, I don't really have to worry about it as much, since I'm there to control it.

 

But to each his own. If you want to be particularly thorough at that one particular point, have at it! And I do like the tblsearch loop personally. In any case, I'm well aware of your prowess to do an extremely thorough job, would expect your best for a client, and would not want to diminish this in any way.:thumbsup:

Link to comment
Share on other sites

+1 Neophoible, I was confused and did not understand the original request (working with only one, self created block).

 

Lee, I have only written LISP for personal use, so I have never needed much error handling. However, I can appreciate its importance and will try using it more in the future.

 

My only question to you is in regard to 'cvport vs 'tilemode. Why warn the user the command is only available in model space when the command can just change on its own? I am just curious why you made this choice/when one is preferred over the other.

Link to comment
Share on other sites

My only question to you is in regard to 'cvport vs 'tilemode. Why warn the user the command is only available in model space when the command can just change on its own? I am just curious why you made this choice/when one is preferred over the other.

 

I test the value of CVPORT over TILEMODE to account for the case in which the user is viewing Modelspace through a Paperspace viewport. The reason that I do not automatically switch to Modelspace is to adhere to standard AutoCAD behaviour which will inform the user that the command is unavailable rather than unexpectedly altering AutoCAD settings - e.g. what if the user was zoomed to a specific point in the drawing in Paperspace etc.

Link to comment
Share on other sites

I test the value of CVPORT over TILEMODE to account for the case in which the user is viewing Modelspace through a Paperspace viewport. The reason that I do not automatically switch to Modelspace is to adhere to standard AutoCAD behaviour which will inform the user that the command is unavailable rather than unexpectedly altering AutoCAD settings - e.g. what if the user was zoomed to a specific point in the drawing in Paperspace etc.

 

Understood, thank you! :thumbsup:

Link to comment
Share on other sites

  • 2 years later...

Hi everyone, I have a similar problem to the original post, but with a slight variation, I've tried a number of scripts and lisps but no luck.

Basically I have a project that is on a Local Project Grid, based on UK National Grid. The Local Grid has a scale and move translation on the x and y axis with no change on the z axis.

I have to translate data in each direction multiple times so I would like to automate the translation to reduce the chance of error.

In simple terms the translations are as follows;

 

National to Local grid - all data is scaled by a factor of 1.000260681848316 using x=0 and y=0 as the basepoint, followed by moving the data from a basepoint of x=260000 and y=800000 to x=0 and y=0.

 

Local to National grid – all data is moved from a basepoint of x=0 and y=0 to x=260000 and y=800000, followed by scaling data by a scale factor of 0.999739386089 using x=260000 and y=800000 as the basepoint.

Seems simple enough right?

 

My latest attempt at a script is as follows;

;;start

SELECT

ALL

-BLOCK

align

260000,800000

(command "_.-insert" "align" "_none" pause "xyz" 1.000260681848316 1.000260681848316 1. "0")

260000,800000

MOVE

ALL

260000,800000

0,0

ZOOM

EXTENTS

EXPLODE

ALL

 

;;end

 

I can copy this text and paste it into the command line and it works as expected, however if I run it as a script, it does the scale and move, but the final position is slightly incorrect, and I cannot work out why.

 

Can anyone check my script and help me troubleshoot the problem?

 

Thanks

Link to comment
Share on other sites

Make all numbers a real maybe 260000,800000 260000.0,800000.0

 

Thanks for the reply BIGAL, I tried that but still no luck

Link to comment
Share on other sites

I have a working solution to this problem now, involving a list of commands in a text file that can be pasted into the command line, not a script as such... because for some reason when I run as a script the translation is slightly incorrect.

Link to comment
Share on other sites

  • 1 year later...

I am attempting to do something similar and just found this thread. I want to be able to select all blocks with the name "ELEVATION MARKER" and change the XYZ scales to 1. they are dynamic blocks. For some reason, this code will not select anything, or make any changes. Does anyone know what I need to change?

 

(defun c:cc ( / blk sset)
   (if
           (setq sset (ssget "_X" (list '(0 . "INSERT") '(2 . "ELEVATION MARKER"))))
       (progn
    (setq blk (ssname sset 0))
               (entmod ; modifies the properties of the entity
                   (append ; combines the list
                       (entget sset); indicates what entity to edit
                       (list ; create a list of properties to change
                           (cons 41 1.0)
                           (cons 42 1.0)
                       )
                   )
               )
                   (entupd sset); updates the block
       )
   )
 (princ)
)

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