Command to offset with options specific layer and line type

Command to offset with options specific layer and line type

werner.bianca
Contributor Contributor
1,370 Views
7 Replies
Message 1 of 8

Command to offset with options specific layer and line type

werner.bianca
Contributor
Contributor

Good morning!
I've been putting together lisps by researching here, mashing things together/trial and error until I'm able to get it to work as I want. But I've been struggling to get this one going (and another one that I'll make a different post for).


This one is about the Offset into a specific layer and linetype. Below is what I have to far.
The idea is to run the command and select which option to go with 1/5.
4 of them go to the same layer but different linetypes. The last one goes into a different layer and linetype by layer.


However I'm having issues with it changing into the linetype I want. Please help

;;;;;;;;;;;;;;;;;;;;;;;;;;;; OFFSET-WIRE to Layer/ LT ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun c:WIRE ()
(setvar "cmdecho" 0)
(command "attdia" "1")
(setq offDist 10) ;(getstring "enter offest distance"))
(setq oldlayer(getvar "clayer")) ;Determine current Layer;
      (setq client
              (getint
                "What Line Offset do you need? [1] 1/W IN, [2] 2/W IN, [3] 3/W IN, [4] 4/W IN, [5] RM"
              )
              )
              (IF (= CLIENT 1)
                  (command "layer" "s" "INSTALL" "")
                  (setq linety "1WIRE")
              )
              (IF (= CLIENT 2)
                  (command "layer" "s" "INSTALL" "")
                  (setq linety "2WIRE")
              )
              (IF (= CLIENT 3)
                  (command "layer" "s" "INSTALL" "")
                  (setq linety "3WIRE")
              )
              (IF (= CLIENT 4)
                  (command "layer" "s" "INSTALL" "")
                  (setq linety "4WIRE")
              )
              (IF (= CLIENT 5)
                  (command "layer" "s" "REMOVE" "")
                  (setq linety "bylayer")
               )
      (print "select line to offset")
      (command "offset" offDist pause pause "")
      (command "chprop" "last" "" "lt" linety "")
(command "layer" "s" oldlayer "") ;Layer back to previous;
(princ)
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;; END OFFSET-WIRE to Layer/ LT ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
0 Likes
Accepted solutions (1)
1,371 Views
7 Replies
Replies (7)
Message 2 of 8

Kent1Cooper
Consultant
Consultant

Your use of (if) is incorrect.  You have 'then' and 'else' expressions where you really want a single 'then' expression to incorporate the two things you want to do into one.  They way to do that is to "wrap" them together into a (progn) function, for example:

(IF (= CLIENT 1)
  (progn
    (command "layer" "s" "INSTALL" "")
    (setq linety "1WIRE")
  ); progn
); if

But the better way is not with a series of (if) functions that it needs to step through even after it's already found the one to work with, but rather with a (cond) function with those tests as separate conditions, in which once it finds a condition satisfied, it does what's asked for and then doesn't even bother to look at the rest of the conditions:

(cond
  ((= CLIENT 1)
    (command "layer" "s" "INSTALL" "")
    (setq linety "1WIRE")
  ); 1 condition
  ((= CLIENT 2)
    (command "layer" "s" "INSTALL" "")
    (setq linety "2WIRE")
  ); 2 condition
  ((= CLIENT 3)
    (command "layer" "s" "INSTALL" "")
    (setq linety "3WIRE")
  ); 3 condition
  ((= CLIENT 4)
    (command "layer" "s" "INSTALL" "")
    (setq linety "4WIRE")
  ); 4 condition
  ((= CLIENT 5)
    (command "layer" "s" "REMOVE" "")
    (setq linety "bylayer")
  ); 5 condition
); cond

[In that method, the two things you want to do in each condition are not 'then' and 'else' opposites, so they don't need the (progn) wrappers.]

 

But that whole part of the thing could be streamlined much more, with a different approach....

(setvar 'clayer (if (= CLIENT 5) "REMOVE" "INSTALL"))
(setq linety (if (= CLIENT 5) "bylayer" (strcat (itoa CLIENT) "WIRE")))

 

Kent Cooper, AIA
0 Likes
Message 3 of 8

werner.bianca
Contributor
Contributor
Accepted solution

OMG thank you so much!
I was struggling using (IF), all the lisps I've used were simple block insertion for most part.
I had to make a couple other changes because the offset wasn't going into the layer set as current. So it ended up like this:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;       OFFSET-WIRE  to Layer/ LT      ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun c:WIRE ()
(setvar "cmdecho" 1)
(command "attdia" "1")
(setq offDist 10)			;(getstring "enter offest distance"))
(setq oldlayer(getvar "clayer")) ;Determine current Layer;
		(setq client
			(getint
			"What Line Offset do you need? [1] 1/C IN, [2] 2/C IN, [3] 3/C IN, [4] 4/C IN, [5] EX/RM"
			)
		)
		(COND
			((= CLIENT 1)
				(progn
					(setq offlayer "INSTALL")
					(setq linety "1WIRE")
				)
			) ;Condition 1
			((= CLIENT 2)
				(progn
					(setq offlayer "INSTALL")
					(setq linety "2WIRE")
				)
			) ;Condition 2
			((= CLIENT 3)
				(progn
					(setq offlayer "INSTALL")
					(setq linety "3WIRE")
				)
			) ;Condition 3
			((= CLIENT 4)
				(progn
					(setq offlayer "INSTALL")
					(setq linety "4WIRE")
				)
			) ;Condition 4
			((= CLIENT 5)
				(progn
					(setq offlayer "REMOVE")
					(setq linety "bylayer")
				)
			) ;Condition 5
		)
	(print "select line to offset")
	(command "offset" offDist pause pause "")
	(command "chprop" "last" "" "lt" linety "")
	(command "chprop" "last" "" "la" offlayer "")
(command "layer" "s" oldlayer "") ;Layer back to previous;
(princ)
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;     END OFFSET-WIRE  to Layer/ LT    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
0 Likes
Message 4 of 8

Kent1Cooper
Consultant
Consultant

A few quickie comments:

 

No need to deal with ATTDIA when no Block insertions are involved.

A better way to get the Offset distance [if you go back to asking for it rather than setting a fixed value] is with (getdist) rather than (getreal) or [not a good idea] your (getstring).  It will accept a typed distance input, or picking two points on-screen.  And in typed input, it will take any valid format, so if you're in Imperial Architectural units you can type in 1'6-3/4" if you like, whereas with (getreal) that would not be accepted but only 18.75.  And whether by (getreal) or (getdist), you could use (setvar 'offsetdist) with it, and just have the Offset command accept the current distance setting with "", rather than use the offDist variable.

No need for the oldlayer variable or the Layer command returning the current Layer to it, since the current approach doesn't change the current Layer.

Again, you don't need the (progn) "wrappers" in the conditions in a (cond) function the way you do with the 'then' argument in an (if) function.

No need for the prompt about selecting the Line to Offset -- Offset will provide its own.

You can change more than one Property in one CHPROP command, so you don't need separate ones for the Linetype and Layer.

 

BEyond those:  It could be enhanced to require appropriate input [and avoid potential errors for inappropriate answers], for example:

  (while
    (not
      (<
        0
        (setq client
          (getint
            "What Line Offset do you need? [1] 1/C IN, [2] 2/C IN, [3] 3/C IN, [4] 4/C IN, [5] EX/RM"
          )
        )
        6
      ); <
    ); not
    (prompt "\nNot within 1-to-5 range.")
  ); while

That could also be controlled with the (initget)/(getkword) approach, which should take less code but make the 'CLIENT' variable a text string instead of an integer.  But that would make my earlier suggestion of setting the Linetype easier, since the value wouldn't need to be converted to use in a (strcat)ed Linetype name.

 

Kent Cooper, AIA
0 Likes
Message 5 of 8

werner.bianca
Contributor
Contributor

Funny that you mentioned that. I initially wanted the offset distance to vary depending on the ltscale.
We do our drawings on 30 and or 60 ltscale.
In case of the drawing being on 30 I want the offset to be 5 and for the 60 scale, offset 10.
That's when I started trying to use the "IF", but unsuccessfully :S

 

Corrected code:

(defun c:WIRE ()
(setvar "cmdecho" 1)
(setq offDist 10)
		(setq client
			(getint
			"What Line Offset do you need? [1] 1/C IN, [2] 2/C IN, [3] 3/C IN, [4] 4/C IN, [5] EX/RM"
			)
		)
		(COND
			((= CLIENT 1)
				(progn
					(setq offlayer "INSTALL")
					(setq linety "1WIRE")
				)
			) ;Condition 1
			((= CLIENT 2)
				(progn
					(setq offlayer "INSTALL")
					(setq linety "2WIRE")
				)
			) ;Condition 2
			((= CLIENT 3)
				(progn
					(setq offlayer "INSTALL")
					(setq linety "3WIRE")
				)
			) ;Condition 3
			((= CLIENT 4)
				(progn
					(setq offlayer "INSTALL")
					(setq linety "4WIRE")
				)
			) ;Condition 4
			((= CLIENT 5)
				(progn
					(setq offlayer "REMOVE")
					(setq linety "bylayer")
				)
			) ;Condition 5
		)
	(command "offset" offDist pause pause "")
	(command "chprop" "last" "" "lt" linety "la" offlayer "")
(princ)
)

 

0 Likes
Message 6 of 8

Sea-Haven
Mentor
Mentor

For what its worth    3,layer 1,23

 

3 is offset, layer 1 should be obvious, 23 is color.

 

input

3,layer 1,23

-2,layer 1,23

5,layer 5,5

-5,layer 5,5

Just uses a simple csv method to pull apart offset supports a -ve offset value. If you want some code will find.

 

Based on multiple offset as many as required 3,-3,5,-5,5.45,-5.45,6,7,8

0 Likes
Message 7 of 8

Sea-Haven
Mentor
Mentor

Here is a replacement for initget

 

(if (not AH:Butts)(load "Multi Radio buttons.lsp"))
(if (= but nil)(setq but 1))
(setq ans (ah:butts but "V"  '("Choose clientt" "Client1" "Client2 " "Client3" "client4"))) ; ans holds the button picked value
Message 8 of 8

ВeekeeCZ
Consultant
Consultant

Just for the record. Cond does not require progn

Also, a setq can handle more variables than one.

 

(COND ((= CLIENT 1)
       (setq offlayer "INSTALL")
       (setq linety "1WIRE"))

      ((= CLIENT 2)
       (setq offlayer "INSTALL"
	     linety "2WIRE"))
      ) ; cond