Jump to content

Offset to a specific layer


Dahzee

Recommended Posts

Does anyone have an Offset routine that will offset to one side only and to a specific layer?

 

I have found various routines that are similar but none that do just the above.

 

I have to offset to a specific layer that is already in my template, so I don't need to check that the layer exists and I don't need to select an existing entity in my drawing as there won't be any entities on this layer before I start the routine. So I would like the layer name included in the lisp file.

 

I know this might sound a trivial request (not the code, but the requirement) but I will only use this offset layer for a few entities in my drawing so there is no need to have this layer current at any other time.

 

Many thanks in advance.

Link to comment
Share on other sites

Hi,

Something like this one?

(defun c:Test (/ n c s p o e)
  ;; Tharwat - Date: 5.Jun.2020		;;
  (setq	n "Layer" ;; Target layer name.	;;
	c 232	  ;; Colour of Layer.	;;
  )
  (or *off* (setq *off* 1.0))
  (and (or (tblsearch "LAYER" n)
	   (entmake (list '(0 . "LAYER")
			  '(100 . "AcDbSymbolTableRecord")
			  '(100 . "AcDbLayerTableRecord")
			  (cons 2 n)
			  (cons 62 c)
			  '(70 . 0)
		    )
	   )
       )
       (setq *off* (cond ((getdist (strcat "\nSpecify offset distance < "
					   (rtos *off* 2 2)
					   " > :"
				   )
			  )
			 )
			 (*off*)
		   )
       )
       (setq s (ssget "_:S:E:L" '((0 . "*LINE,ARC,CIRCLE"))))
       (setq p (getpoint "\nSpecify offset side : "))
       (setq o (entlast))
       (vl-cmdf "_.OFFSET" *off* (ssname s 0) "_none" p "")
       (and (not (= o (setq o (entlast))))
	    (entmod (subst (cons 8 n) (assoc 8 (setq e (entget o))) e))
       )
  )
  (princ)
)

 

Link to comment
Share on other sites

Another single click way is is using VLA-OFFSET as it supports positive or negative input for objects like arc and circle. The *line is done 1 click by picking near an end this implies the direction so goes either left or right. It does require more code though for the *line check compared to pick a point direction.

 

Edited by BIGAL
Link to comment
Share on other sites

@Tharwat,

 

Thanks for this it works exactly how I needed, but....

 

It doesn't automatically stay in the offset command as the internal command does.

I know I can add an asterisk if I assign this to a button, but I use the keyboard for most of my lisps so it would be good if I could have this as part of the routine.

 

Once again thank you for the routine and sorry if I am being picky with the way it works 🙂

 

@Bigal, thanks for the reply, I know very little about creating lisps so I didn't really understand your comment, but thanks for replying anyway.

Link to comment
Share on other sites

You're welcome Dahzee. :) 

 

Please try the following updated codes based on your request and let me know if that meets your needs or may require further mods.

(defun c:Test (/ n c s p o e)
  ;; Tharwat - Date: 8.Jun.2020		;;
  (setq n "Layer";; Target layer name.	;;
        c 232    ;; Colour of Layer.	;;
  )
  (or *off* (setq *off* 1.0))
  (and
    (or (tblsearch "LAYER" n)
        (entmake (list '(0 . "LAYER")
                       '(100 . "AcDbSymbolTableRecord")
                       '(100 . "AcDbLayerTableRecord")
                       (cons 2 n)
                       (cons 62 c)
                       '(70 . 0)
                 )
        )
    )
    (or (initget 6)
        (setq
          *off* (cond ((getdist (strcat "\nSpecify offset distance < "
                                        (rtos *off* 2 2)
                                        " > : "
                                )
                       )
                      )
                      (*off*)
                )
        )
    )
    (while
      (and
        (princ
          "\nPick Line,Polyline,Arc,Circle to offset <Enter to exit safely> : "
        )
        (setq s (ssget "_+.:S:E:L" '((0 . "*LINE,ARC,CIRCLE"))))
        (setq p (getpoint "\nSpecify offset side : "))
        (setq o (entlast))
      )
       (vl-cmdf "_.OFFSET" *off* (ssname s 0) "_none" p "")
       (and (not (= o (setq o (entlast))))
            (entmod (subst (cons 8 n) (assoc 8 (setq e (entget o))) e))
       )
    )
  )
  (princ)
)

 

Link to comment
Share on other sites

Dahzee the vla-offset only asks for an offset value not a direction, so for an arc or circle entering a -ve value makes the radius less +ve bigger. For lines +ve implies go right -ve go left. The issue is that it depends on the direction of how the original line was drawn, but there are ways of checking this.

Link to comment
Share on other sites

Thanks BIGAL for the reply,

 

I will read up on these commands, to get an understanding of how they work in relation to the standard autocad commands.

Link to comment
Share on other sites

  • 3 years later...
On 6/8/2020 at 10:07 AM, Tharwat said:

You're welcome Dahzee. :) 

 

Please try the following updated codes based on your request and let me know if that meets your needs or may require further mods.

(defun c:Test (/ n c s p o e)
  ;; Tharwat - Date: 8.Jun.2020		;;
  (setq n "Layer";; Target layer name.	;;
        c 232    ;; Colour of Layer.	;;
  )
  (or *off* (setq *off* 1.0))
  (and
    (or (tblsearch "LAYER" n)
        (entmake (list '(0 . "LAYER")
                       '(100 . "AcDbSymbolTableRecord")
                       '(100 . "AcDbLayerTableRecord")
                       (cons 2 n)
                       (cons 62 c)
                       '(70 . 0)
                 )
        )
    )
    (or (initget 6)
        (setq
          *off* (cond ((getdist (strcat "\nSpecify offset distance < "
                                        (rtos *off* 2 2)
                                        " > : "
                                )
                       )
                      )
                      (*off*)
                )
        )
    )
    (while
      (and
        (princ
          "\nPick Line,Polyline,Arc,Circle to offset <Enter to exit safely> : "
        )
        (setq s (ssget "_+.:S:E:L" '((0 . "*LINE,ARC,CIRCLE"))))
        (setq p (getpoint "\nSpecify offset side : "))
        (setq o (entlast))
      )
       (vl-cmdf "_.OFFSET" *off* (ssname s 0) "_none" p "")
       (and (not (= o (setq o (entlast))))
            (entmod (subst (cons 8 n) (assoc 8 (setq e (entget o))) e))
       )
    )
  )
  (princ)
)

 

 

Hello @Tharwat

 

Can you please provide some modifications on this code?

I need the code to always do the offset automatically on the inside without manual input.

Also want the code to be applied on all lines on the drawing, instead of selecting the ones I want manually.

 

Thanks in advance for your help and support.

Link to comment
Share on other sites

5 hours ago, Trap3d said:

I need the code to always do the offset automatically on the inside without manual input.

 

Referring you to BigAls comment above, how is the LISP to determine which side of a line is 'inside' and which is 'outside' (for example draw a line left to right and another right to left, 'inside will be on opposite sides because the lines were drawn in opposite directions). There might be some additional coding needed to work out or correct a line direction depends on the rules you want to follow.

 

Ultimately to replace

 

(vl-cmdf "_.OFFSET" *off* (ssname s 0) "_none" p "")

 

with

 

(vla-offset .....

 

 

If you look at Lee Macs website, ssget functions that will give you the details to change Tharwats code to select all from select a single entity, looking to replace

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

 

with

 

... (ssget "_X" ...

 

 where 'X' refers to everything, or leave it out for user selection.

 

... (ssget ...

 

Edited by Steven P
  • Like 1
Link to comment
Share on other sites

5 hours ago, Trap3d said:

 

Hello @Tharwat

 

Can you please provide some modifications on this code?

I need the code to always do the offset automatically on the inside without manual input.

Also want the code to be applied on all lines on the drawing, instead of selecting the ones I want manually.

 

Thanks in advance for your help and support.

Hi,

Try this untested codes and I excluded line objects due to unknown of the internal side as for Arcs & Circles.

(defun c:Test (/ n c f i s e o)
  ;;----------------------------------------------------;;
  ;;	Author : Tharwat Al Choufi			;;
  ;; website: https://autolispprograms.wordpress.com	;;
  ;;----------------------------------------------------;;
  (setq n "Layer" ;; Target layer name.	;;
        c 232     ;; Colour of Layer.	;;
        f 1.0     ;; Offset distance.	;;
  )
  (and
    (or (tblsearch "LAYER" n)
        (entmake (list '(0 . "LAYER")
                       '(100 . "AcDbSymbolTableRecord")
                       '(100 . "AcDbLayerTableRecord")
                       (cons 2 n)
                       (cons 62 c)
                       '(70 . 0)
                 )
        )
    )
    (setq i -1
          s (ssget "_X"
                   (list (cons 410 (getvar 'CTAB)) '(0 . "ARC,CIRCLE"))
            )
    )
    (while (setq i (1+ i) e (ssname s i))
      (and (setq o (entlast))
           (vlax-write-enabled-p (vlax-ename->vla-object e))
           (vl-cmdf "_.OFFSET"
                    f
                    e
                    "_none"
                    (cdr (assoc 10 (entget e)))
                    ""
           )
           (not (= o (setq o (entlast))))
           (entmod (subst (cons 8 n) (assoc 8 (setq e (entget o))) e))
      )
    )
  )
  (princ)
) (vl-load-com)

 

Link to comment
Share on other sites

1 hour ago, Tharwat said:

Hi,

Try this untested codes and I excluded line objects due to unknown of the internal side as for Arcs & Circles.

(defun c:Test (/ n c f i s e o)
  ;;----------------------------------------------------;;
  ;;	Author : Tharwat Al Choufi			;;
  ;; website: https://autolispprograms.wordpress.com	;;
  ;;----------------------------------------------------;;
  (setq n "Layer" ;; Target layer name.	;;
        c 232     ;; Colour of Layer.	;;
        f 1.0     ;; Offset distance.	;;
  )
  (and
    (or (tblsearch "LAYER" n)
        (entmake (list '(0 . "LAYER")
                       '(100 . "AcDbSymbolTableRecord")
                       '(100 . "AcDbLayerTableRecord")
                       (cons 2 n)
                       (cons 62 c)
                       '(70 . 0)
                 )
        )
    )
    (setq i -1
          s (ssget "_X"
                   (list (cons 410 (getvar 'CTAB)) '(0 . "ARC,CIRCLE"))
            )
    )
    (while (setq i (1+ i) e (ssname s i))
      (and (setq o (entlast))
           (vlax-write-enabled-p (vlax-ename->vla-object e))
           (vl-cmdf "_.OFFSET"
                    f
                    e
                    "_none"
                    (cdr (assoc 10 (entget e)))
                    ""
           )
           (not (= o (setq o (entlast))))
           (entmod (subst (cons 8 n) (assoc 8 (setq e (entget o))) e))
      )
    )
  )
  (princ)
) (vl-load-com)

 

 

Thanks for your fast response @Tharwat. The code does not work. I only have polylines in my case.

I attached one dxf file with the input and with the pretended output of the code. Maybe the approach can be to fix the offset value to a negative one, so it's always on the inside of the closed polyline (I used -0.8mm). The offset value also must be fixed, so i don't have to specify it for each polygon to offset.

 

 

 

Link to comment
Share on other sites

1 hour ago, Steven P said:

 

Referring you to BigAls comment above, how is the LISP to determine which side of a line is 'inside' and which is 'outside' (for example draw a line left to right and another right to left, 'inside will be on opposite sides because the lines were drawn in opposite directions). There might be some additional coding needed to work out or correct a line direction depends on the rules you want to follow.

 

Ultimately to replace

 

(vl-cmdf "_.OFFSET" *off* (ssname s 0) "_none" p "")

 

with

 

(vla-offset .....

 

 

If you look at Lee Macs website, ssget functions that will give you the details to change Tharwats code to select all from select a single entity, looking to replace

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

 

with

 

... (ssget "_X" ...

 

 where 'X' refers to everything, or leave it out for user selection.

 

... (ssget ...

 

 

Thank you for your tips @Steven P. The objects that i have are always closed polylines. The approach should be to fix the offset value with a negative one, so it's always on the inside of the closed polyline. You can see the file attached to understand better what I pretend the code to do.

example_offset.dwg

Link to comment
Share on other sites

15 minutes ago, Trap3d said:

 

Thanks for your fast response @Tharwat. The code does not work. I only have polylines in my case.

I attached one dxf file with the input and with the pretended output of the code. Maybe the approach can be to fix the offset value to a negative one, so it's always on the inside of the closed polyline (I used -0.8mm). The offset value also must be fixed, so i don't have to specify it for each polygon to offset.

 

 

 

Apparently you did not read what I did write against polylines & lines and just ran the program blindly. ! nor the offset part as well.

Would you like any fries with the codes on delivery ?

Link to comment
Share on other sites

5 minutes ago, Tharwat said:

Apparently you did not read what I did write against polylines & lines and just ran the program blindly. ! nor the offset part as well.

Would you like any fries with the codes on delivery ?

 

Of course I read what you wrote. I was saying that I only will need to work with polylines. I added the "LINE" filter hoping that it would work.

It was not my intention to neither offend or disrespect you 😅

Thanks anyway for your help and time.

(PS: I started learning lisp in autocad a few days ago...)

Link to comment
Share on other sites

No worries, try it and let me know. :) 

(defun c:Test (/ n c f i s e o)
  ;;----------------------------------------------------;;
  ;;	Author : Tharwat Al Choufi			;;
  ;; website: https://autolispprograms.wordpress.com	;;
  ;;----------------------------------------------------;;
  (setq n "Layer" ;; Target layer name.	;;
        c 232     ;; Colour of Layer.	;;
        f 0.8     ;; Offset distance.	;;
  )
  (and
    (or (tblsearch "LAYER" n)
        (entmake (list '(0 . "LAYER")
                       '(100 . "AcDbSymbolTableRecord")
                       '(100 . "AcDbLayerTableRecord")
                       (cons 2 n)
                       (cons 62 c)
                       '(70 . 0)
                 )
        )
    )
    (setq i -1
          s (ssget "_X"
              (list (cons 410 (getvar 'CTAB))
                    '(0 . "LWPOLYLINE")
                    '(-4 . "&=")
                    '(70 . 1)
              )
            )
    )
    (while (setq i (1+ i)
                 e (ssname s i)
           )
      (and (setq g (entget e)
                 o (entlast)
           )
           (vlax-write-enabled-p (vlax-ename->vla-object e))
           (vl-cmdf "_.OFFSET"
                    f
                    e
                    "_none"
                    (mapcar (function (lambda (j k) (* (+ j k) 0.5)))
                            (vlax-curve-getstartpoint e)
                            (vlax-curve-getpointatparam e 2)
                    )
                    ""
           )
           (not (= o (setq o (entlast))))
           (entmod (subst (cons 8 n) (assoc 8 (setq e (entget o))) e))
      )
    )
  )
  (princ)
) (vl-load-com)

 

  • Like 3
Link to comment
Share on other sites

Look into CW and CCW direction of plines, then an offset to inside is controlled by this direction, using say, vla-offset obj 1, will go in or out depending on pline direction, simple for closed plines.

  • Like 1
  • Dislike 1
Link to comment
Share on other sites

Just been following this in the background a little

 

BigAl - for direction, 'inside' and 'outside' I assume that inside is a shorter line than outside - no need to work out points and angles like CW / CCW so in this case I think this works and using this for the line length

 

(setq Ent_Len (vla-get-length (vlax-Ename->Vla-Object EntName) ))

 

 

For Tharwat, I'd be tempted to look at 'closed' polylines also being polylines where the first and last point coincide (with or without a 'fuzz factor') just in case they arn't true closed polylines, something like:

 

(setq MySS (ssget "_X" (list '(0 . "LWPOLYLINE"))))
(while loop.....
(setq MyEnt (entget (ssname MySS n) ))
(if
  (or
    (equal (assoc 10 MyEnt) (assoc 10 (reverse MyEnt)) (/ Offset 100) ) ;; fuzz factor, 1/100 offset distance
    (= 1 (cdr (assoc 70 MyEnt)))
  ) ; end or
(progn.....

 

 

 

Quickly putting that together, copy and pasted from other stuff, an no nice stuff added, something like this:

 

 

(defun c:test ( / MyOffset MyLayer MySS EntName acount MyEnt obj Orig_Len New_Len )
  (setq MyOffset 0.8) ; offset distance - user to define this
;;  (setq Myoffset (getreal "Enter Offset Distance")) ; user to enter distance if required
  (setq MyLayer "0")  ; Layer to copy to
;;  (setq MyLayer (getstring "Enter Layer Name" T)) ; or user enters this


;;Do some checks here that the layer is valid


  (setq MySS (ssget "_X" (list '(0 . "LWPOLYLINE")))) ; Get Polylines ;; OR next line, not both
;;  (setq MySS (ssget (list '(0 . "LWPOLYLINE")))) ; Get Polylines ;; User selects polylines

  (setq acount 0) ; just a counter
  (while (< acount (sslength MySS)) ;; loop through polylines in drawing
    (setq EntName  (ssname MySS acount)) ;; get the entity to assess
    (setq MyEnt    (entget EntName)) ;; entity descriptiob
    (if ;; if to offset 'closed' polylines or those that appear closed
      (or
        (equal (assoc 10 MyEnt) (assoc 10 (reverse MyEnt)) (/ MyOffset 100) ) ;; fuzz factor, 1/100 offset distance
        (= 1 (cdr (assoc 70 MyEnt)))
      ) ; end or
      (progn ; if closed polylines
        (setq obj (vlax-Ename->Vla-Object EntName)) ;; get entity object name
        (setq Orig_Len (vla-get-length obj)) ; get entity line length
        (vla-Offset (vlax-ename->vla-object EntName) MyOffset) ; offset the polyline
        (setq obj (vlax-Ename->Vla-Object (entlast))) ; get new offset entity name
        (setq New_Len (vla-get-length obj)) ; get new offset entity length

        (if (< Orig_Len New_Len) ; if offset line is longer than original, reverse offset
          (progn
            (entdel (entlast))
            (vla-Offset (vlax-ename->vla-object EntName) (* -1 MyOffset)) ;; negative offset
          )
        )
        (vla-put-layer (vlax-EName->vla-Object (entlast)) MyLayer) ;; change layer
      ) ; end progn
    ) ; end if
    (setq acount (+ acount 1))
  ) ; end while
  (princ)
); end defun

 

Edited by Steven P
  • Like 1
Link to comment
Share on other sites

41 minutes ago, Steven P said:

For Tharwat, I'd be tempted to look at 'closed' polylines also being polylines where the first and last point coincide (with or without a 'fuzz factor') just in case they arn't true closed polylines, something like:

Although that I decided not to reply to any of your replies / comments due to your unwillingness in learning and being confident in copying & pasting codes from all around forums which means that you are wasting your free time here, and your question confirms what I am alluding to.

If you knew what my codes do, then you would not have asked your question with that irrelevant narrative explanations.

 

  • Thanks 1
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...