Jump to content

Delete A Previous Action In The LISP Command


CFORD

Recommended Posts

Hello,

 

I am working on a Autolisp code whereby the following commands happen 

 

Step 1

Select all objects in Layer ....

Offset distance = pause ""

Select all objects in Layer ....

Offset distance = pause ""

Select all objects in Layer ....

Offset distance = pause ""

Select all objects in Layer ....

Offset distance = pause ""

Select all objects in Layer ....

Offset distance = pause ""

"" to move onto the next set of commands

 

Step 2

Offsets are done left and right of every layer that is selected at the required offset distance.

 

Step 3

-Boundary command and select multiple boundaries 

 

Step 4

when exiting the command the offsets that were produced are deleted the only thing to remain is the boundary lines

 

I don't know how to do step 4 and wondering if anyone know of a way of doing that?

 

OFFSETBOUNDARY.txt

Link to comment
Share on other sites

Apologies that was my notes from other peoples coding. Here is the code that I have managed to mash together from that.

 

(defun c:APV ()
       (while
        (setq TargEnt (car (entsel "\nSelect object on layer to select: ")))
        (setq TargLayer (assoc 8 (entget TargEnt)))
        (sssetfirst nil (ssget "_X" (list TargLayer)))
        (defun *error* ( msg )
           (and undo (vla-EndUndomark doc))
           (or (wcmatch (strcase msg) "*BREAK,*CANCEL*,*EXIT*")
              (princ (strcat "\n** Error: " msg " **")))
           (princ)
          )
    (if (and (ssget '((0 . "ARC,CIRCLE,ELLIPSE,*LINE")))
          (setq of (getdist "\nSpecify Offset Distance: ")))
   (progn
     (setq undo
       (not
         (vla-StartUndomark
           (setq doc
             (vla-get-ActiveDocument
               (vlax-get-acad-object)
             )
           )
         )
       )
     )
     
     (vlax-for obj (setq ss (vla-get-ActiveSelectionSet doc))
       (mapcar
         (function
           (lambda ( o )
             (vl-catch-all-apply
               (function vla-offset) (list obj o)
             )
           )
         )
         (list of (- of))
       )
     )
     (vla-delete ss)
    (setq undo (vla-EndUndoMark doc))
   )
 )
    )
     (while (setq pt (getpoint "\nPick internal point: "))
   (command "_.-boundary" "_a" "_i" "_n" "" "" "_non" pt "")
 )
(princ)
)

 

My problem is just deleting those temporary offset layers. 

Let me know if you can provide any insight?

Link to comment
Share on other sites

Use <> when posting code so it looks like this.

 

Using  (entlast) to group up offset entity's so they can be deleted later.

(defun c:APV (/ doc SS1 TargLayer SS of undo obj pt)
  (defun *error* (msg)
    (and undo (vla-EndUndomark doc))
    (or (wcmatch (strcase msg) "*BREAK,*CANCEL*,*EXIT*")
        (princ (strcat "\n** Error: " msg " **"))
    )
    (princ)
  )
  (setq doc (vla-get-ActiveDocument (vlax-get-acad-object)))
  (vla-StartUndomark doc)
  (setq SS1 (ssadd))  ;add empty selection set to add entity's too
  (setq LastEnt (entlast))           ;set last entity before creating objects
  (while (setq TargEnt (car (entsel "\nSelect Object(s): ")))
    (setq TargLayer (cdr (assoc 8 (entget TargEnt))))
    (if (and (setq ss (ssget "_X" (list '(0 . "ARC,CIRCLE,ELLIPSE,*LINE") (cons 8 TargLayer))))
             (setq of (getdist "\nSpecify Offset Distance: "))
        )
        (foreach ent (vl-remove-if 'listp (mapcar 'cadr (ssnamex SS)))
          (vla-offset (setq obj (vlax-ename->vla-object ent)) of)
          (vla-offset obj (- of))
          (vla-delete obj)
        )
    )
    (if (setq en (entnext LastEnt))  ;adds all offsets to SS1
      (while en
        (ssadd en SS1)
        (setq en (entnext en))
      )
    )
  )
  (while (setq pt (getpoint "\nPick internal point: "))
    ;(vl-cmdf "_.Boundary" "_non" pt "")
    (command "_.Boundary" "_A" "_I" "_N" "" "" "_non" pt "") ;doesn't work with BircsCAD
  )
  (foreach ent (vl-remove-if 'listp (mapcar 'cadr (ssnamex SS1)))
    (entdel ent)                   ;Deletes all offset entity's
  )
  ;(command "_.Erase" SS "") ;another way to do it all at once.
  (vla-EndUndoMark doc)
  (princ)
)

 

Don't really like this lisp because its selecting alot of things based on a entsel's layer and deleting them. Has a great potential of deleting things you want to keep and/or things on a different tab.

Should really only select the things you want to offset to create the boundary.

  • Like 2
Link to comment
Share on other sites

Working through what you have made up and with a similar idea to MHUPP, above, create a selection set from the temporary lines and delete these. I did my version with a loop to create each temporary line and add them to the set as you go, MHUPP did all the lines and then creates the selection set - same result though. I suspect mine will be slower if there are a lot of lines (but only by fractions of a second).

 

 

;;https://www.cadtutor.net/forum/topic/21484-i-search-for-offset-with-same-value-and-opposite-direction/#comment-175406
(defun c:APV ( / TargEnt TargLayer MySS of MyOffSS)
;;Errors
  (defun *error* ( msg )
    (and undo (vla-EndUndomark doc))
    (or
      (wcmatch (strcase msg) "*BREAK,*CANCEL*,*EXIT*")
      (princ (strcat "\n** Error: " msg " **"))
    )
    (princ)
  )

;; Set variables
  (setq MyOffSS (ssadd))

;; Loop layers selection
  (while ; while a
;;Select Layer
    (setq TargEnt (car (entsel "\nSelect object on layer to select: ")))
    (setq TargLayer (assoc 8 (entget TargEnt)))
    (setq MySS (ssget "_X" (list TargLayer (cons 0 "ARC,CIRCLE,ELLIPSE,*LINE") ) ))

;;Get Offset
    (setq of (getdist "\nSpecify Offset Distance: "))

;; Do Offset
;;https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/vla-offset-directions/td-p/1705849
    (setq acount 0)
    (while (< acount (sslength MySS)) ; while b
      (setq VlaOb (vlax-ename->vla-object (ssname MySS acount)))
      (vla-offset VlaOb of ) ;; offset line 1
      (setq MyOffSS (ssadd (entlast) MyOffSS)) ;; add offset to selection set
      (vla-offset VlaOb (* of -1) ) ;; offset line 2
      (setq MyOffSS (ssadd (entlast) MyOffSS)) ;; add offset to selection set
      (setq acount (+ acount 1)) 
    ) ; end while b
  ) ; end while a

  (while (setq pt (getpoint "\nPick internal point: ")) ; while c
    (command "_.-boundary" "_a" "_i" "_n" "" "" "_non" pt "")
  ) ; end while c

;; Delete temporary Lines
  (command "_.erase" MyOffSS "")  ;; Delete selection set

;;Finish
  (setq undo (vla-EndUndoMark doc))
  (princ)
)

 

 

I have added a couple of links to the code above just to give credit where it is due (I think your code was mostly copied from the link at the top?)

  • Like 2
Link to comment
Share on other sites

Wow thank you! That was very quick and very useful.

 

When I tested it out for some reason it would only do one offset and not get to the boundary command or onto the next set of offsets.

So I tested it on a small file with a small of amount of lines and it worked so thank you. There were a couple things I am not sure about what is causing a slight problem. Below I have selected the white objects and offset 15 clicked enter and got an error and in doing so left the command. Any ideas on how to resolve this? also see how the line moved not sure why that is either

image.thumb.png.c97d640b8df1125224ae20c1ef65e40a.png

image.thumb.png.aaa3cbd00fbfc32760cc2ed5dbcfd8de.png

 

Command: APV
Select Object(s):
Specify Offset Distance: 15
** Error: Automation Error. Invalid input **

 

 

So for context I am dealing with a very large project which has a lot of vertices. If I go down the route of only offsetting what I need the design takes weeks and then gets changed or amended a couple week or months down the line. So trying with your guys help to speed up that process. 

 

Thank you for the help so far by the way it is really appreciated.

 

Link to comment
Share on other sites

3 hours ago, mhupp said:

Use <> when posting code so it looks like this.

 

Using  (entlast) to group up offset entity's so they can be deleted later.

(defun c:APV (/ doc SS1 TargLayer SS of undo obj pt)
  (defun *error* (msg)
    (and undo (vla-EndUndomark doc))
    (or (wcmatch (strcase msg) "*BREAK,*CANCEL*,*EXIT*")
        (princ (strcat "\n** Error: " msg " **"))
    )
    (princ)
  )
  (setq doc (vla-get-ActiveDocument (vlax-get-acad-object)))
  (vla-StartUndomark doc)
  (setq SS1 (ssadd))  ;add empty selection set to add entity's too
  (setq LastEnt (entlast))           ;set last entity before creating objects
  (while (setq TargEnt (car (entsel "\nSelect Object(s): ")))
    (setq TargLayer (cdr (assoc 8 (entget TargEnt))))
    (if (and (setq ss (ssget "_X" (list '(0 . "ARC,CIRCLE,ELLIPSE,*LINE") (cons 8 TargLayer))))
             (setq of (getdist "\nSpecify Offset Distance: "))
        )
        (foreach ent (vl-remove-if 'listp (mapcar 'cadr (ssnamex SS)))
          (vla-offset (setq obj (vlax-ename->vla-object ent)) of)
          (vla-offset obj (- of))
          (vla-delete obj)
        )
    )
    (if (setq en (entnext LastEnt))  ;adds all offsets to SS1
      (while en
        (ssadd en SS1)
        (setq en (entnext en))
      )
    )
  )
  (while (setq pt (getpoint "\nPick internal point: "))
    ;(vl-cmdf "_.Boundary" "_non" pt "")
    (command "_.Boundary" "_A" "_I" "_N" "" "" "_non" pt "") ;doesn't work with BircsCAD
  )
  (foreach ent (vl-remove-if 'listp (mapcar 'cadr (ssnamex SS1)))
    (entdel ent)                   ;Deletes all offset entity's
  )
  ;(command "_.Erase" SS "") ;another way to do it all at once.
  (vla-EndUndoMark doc)
  (princ)
)

 

Don't really like this lisp because its selecting alot of things based on a entsel's layer and deleting them. Has a great potential of deleting things you want to keep and/or things on a different tab.

Should really only select the things you want to offset to create the boundary.

I used bits of your code with the code I gathered from other people to make this code below.

<

(defun c:APV ()
       (while
        (setq TargEnt (car (entsel "\nSelect object on layer to select: ")))
        (setq TargLayer (assoc 8 (entget TargEnt)))
        (sssetfirst nil (ssget "_X" (list TargLayer)))
        (defun *error* ( msg )
           (and undo (vla-EndUndomark doc))
           (or (wcmatch (strcase msg) "*BREAK,*CANCEL*,*EXIT*")
              (princ (strcat "\n** Error: " msg " **")))
           (princ)
          )
    (setq SS1 (ssadd))
    (setq LastEnt (entlast))
    (if (and (ssget '((0 . "ARC,CIRCLE,ELLIPSE,*LINE")))
          (setq of (getdist "\nSpecify Offset Distance: ")))
   (progn
     (setq undo
       (not
         (vla-StartUndomark
           (setq doc
             (vla-get-ActiveDocument
               (vlax-get-acad-object)
             )
           )
         )
       )
     )
     
     (vlax-for obj (setq ss (vla-get-ActiveSelectionSet doc))
       (mapcar
         (function
           (lambda ( o )
             (vl-catch-all-apply
               (function vla-offset) (list obj o)
             )
           )
         )
         (list of (- of))
       )
     )
     (vla-delete ss)
    (setq undo (vla-EndUndoMark doc))
   )
 )
)
(if (setq en (entnext LastEnt))  ;adds all offsets to SS1
      (while en
        (ssadd en SS1)
        (setq en (entnext en))))

     (while (setq pt (getpoint "\nPick internal point: "))
   (command "_.-boundary" "_a" "_i" "_n" "" "" "_non" pt "")

  (foreach ent (vl-remove-if 'listp (mapcar 'cadr (ssnamex SS1)))
    (entdel ent) 
)                
(princ)
)
>

It seems to be a bit more stable on the offsets but I was wondering if you could tell me why it only deletes the first offset that I do not all the offsets?

 

Many thanks MHUPP, Steven and Bigal

Link to comment
Share on other sites

<> is the button up top will pop up another window to input the code so its easier to copy and scoll down as much.

 

image.png.99e18bbdb521566852a1abfafdad2117.png

 

50 minutes ago, CFORD said:

It seems to be a bit more stable on the offsets but I was wondering if you could tell me why it only deletes the first offset that I do not all the offsets?

 

You have to have ss1 and Lastent outside of the while. they keeps getting reset every loop. so it will only pick up the entity's after that point.

(defun c:APV (/ ss1 Lastent TargEnt TargLayer undo obj ss of en pt ent) ;also always declare your variables
  (setq SS1 (ssadd))
  (setq LastEnt (entlast))
  (while (setq TargEnt (car (entsel "\nSelect object on layer to select: "))) 
    (setq TargLayer (assoc 8 (entget TargEnt)))
    (sssetfirst nil (ssget "_X" (list TargLayer)))
    (defun *error* (msg)

 

As for ** Error: Automation Error. Invalid input **

I think its the circle trying to offset in but I'm going to guess the radius is smaller than 15 so radius would be negative and error.

 

try using

(vlax-for obj (setq ss (vla-get-ActiveSelectionSet doc))
          (mapcar
            (function
              (lambda (o)
                      (vl-catch-all-error-message ;won't display error messages of offset
                        (function vla-offset) (list obj o)
                      )
              )
            )
            (list of (- of))
          )
        )

 

 

 

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

13 hours ago, mhupp said:

Use <> when posting code so it looks like this.

 

Using  (entlast) to group up offset entity's so they can be deleted later.

(defun c:APV (/ doc SS1 TargLayer SS of undo obj pt)
  (defun *error* (msg)
    (and undo (vla-EndUndomark doc))
    (or (wcmatch (strcase msg) "*BREAK,*CANCEL*,*EXIT*")
        (princ (strcat "\n** Error: " msg " **"))
    )
    (princ)
  )
  (setq doc (vla-get-ActiveDocument (vlax-get-acad-object)))
  (vla-StartUndomark doc)
  (setq SS1 (ssadd))  ;add empty selection set to add entity's too
  (setq LastEnt (entlast))           ;set last entity before creating objects
  (while (setq TargEnt (car (entsel "\nSelect Object(s): ")))
    (setq TargLayer (cdr (assoc 8 (entget TargEnt))))
    (if (and (setq ss (ssget "_X" (list '(0 . "ARC,CIRCLE,ELLIPSE,*LINE") (cons 8 TargLayer))))
             (setq of (getdist "\nSpecify Offset Distance: "))
        )
        (foreach ent (vl-remove-if 'listp (mapcar 'cadr (ssnamex SS)))
          (vla-offset (setq obj (vlax-ename->vla-object ent)) of)
          (vla-offset obj (- of))
          (vla-delete obj)
        )
    )
    (if (setq en (entnext LastEnt))  ;adds all offsets to SS1
      (while en
        (ssadd en SS1)
        (setq en (entnext en))
      )
    )
  )
  (while (setq pt (getpoint "\nPick internal point: "))
    ;(vl-cmdf "_.Boundary" "_non" pt "")
    (command "_.Boundary" "_A" "_I" "_N" "" "" "_non" pt "") ;doesn't work with BircsCAD
  )
  (foreach ent (vl-remove-if 'listp (mapcar 'cadr (ssnamex SS1)))
    (entdel ent)                   ;Deletes all offset entity's
  )
  ;(command "_.Erase" SS "") ;another way to do it all at once.
  (vla-EndUndoMark doc)
  (princ)
)

 

Don't really like this lisp because its selecting alot of things based on a entsel's layer and deleting them. Has a great potential of deleting things you want to keep and/or things on a different tab.

Should really only select the things you want to offset to create the boundary.

Brilliant thank you it works perfectly now!! cheers for your help I am obviously new to this so thank you for your patience  

Link to comment
Share on other sites

(defun c:APV (/ ss1 Lastent TargEnt TargLayer undo obj ss of en pt ent) ;also always declare your variables
 		(setq SS1 (ssadd))
 		(setq LastEnt (entlast))
		(while (setq TargEnt (car (entsel "\nSelect object on layer to select: "))) 
  		(setq TargLayer (assoc 8 (entget TargEnt)))
  		(sssetfirst nil (ssget "_X" (list TargLayer)))
   		(defun *error* (msg)
   		(or (wcmatch (strcase msg) "*BREAK,*CANCEL*,*EXIT*")
      		(princ (strcat "\n** Error: " msg " **")))
   		(princ)
  		)

	(if (and (ssget '((0 . "ARC,CIRCLE,ELLIPSE,*LINE")))
          (setq of (getdist "\nSpecify Offset Distance: ")))
   (progn
     (setq undo
       (not
         (vla-StartUndomark
           (setq doc
             (vla-get-ActiveDocument
               (vlax-get-acad-object)
             )
           )
         )
       )
     )
     
     (vlax-for obj (setq ss (vla-get-ActiveSelectionSet doc))
       (mapcar
         (function
           (lambda ( o )
             (vl-catch-all-apply
               (function vla-offset) (list obj o)
             )
           )
         )
         (list of (- of))
       )
     )
     (vla-delete ss)
	(setq undo (vla-EndUndoMark doc))
   )
 )
)
(if (setq en (entnext LastEnt))  ;adds all offsets to SS1
      (while en
        (ssadd en SS1)
        (setq en (entnext en))))

	 (while (setq pt (getpoint "\nPick internal point: "))
   (command "_.-boundary" "_a" "_i" "_n" "" "" "_non" pt "")
) 
  (foreach ent (vl-remove-if 'listp (mapcar 'cadr (ssnamex SS1)))
    (entdel ent) 
)                
(princ)
)

This is the Code that I am left with for anyone facing the same problem. Works well for me any further comments let me know 

  • Like 1
Link to comment
Share on other sites

  • 2 weeks later...
(defun c:APV (/ ss1 Lastent TargEnt TargLayer undo obj ss of en pt ent) ;also always declare your variables
 		(setq SS1 (ssadd))
 		(setq LastEnt (entlast))
		(while (setq TargEnt (car (entsel "\nSelect object on layer to select: "))) 
  		(setq TargLayer (assoc 8 (entget TargEnt)))
  		(sssetfirst nil (ssget "_X" (list TargLayer)))
   		(defun *error* (msg)
   		(or (wcmatch (strcase msg) "*BREAK,*CANCEL*,*EXIT*")
      		(princ (strcat "\n** Error: " msg " **")))
   		(princ)
  		)

	(if (and (ssget '((0 . "ARC,CIRCLE,ELLIPSE,*LINE")))
          (setq of (getdist "\nSpecify Offset Distance: ")))
   (progn
     (setq undo
       (not
         (vla-StartUndomark
           (setq doc
             (vla-get-ActiveDocument
               (vlax-get-acad-object)
             )
           )
         )
       )
     )
     
     (vlax-for obj (setq ss (vla-get-ActiveSelectionSet doc))
       (mapcar
         (function
           (lambda ( o )
             (vl-catch-all-apply
               (function vla-offset) (list obj o)
             )
           )
         )
         (list of (- of))
       )
     )
     (vla-delete ss)
	(setq undo (vla-EndUndoMark doc))
   )
 )
)
(if (setq en (entnext LastEnt))  ;adds all offsets to SS1
      (while en
        (ssadd en SS1)
        (setq en (entnext en))))

	 (while (setq pt (getpoint "\nPick internal point: "))
   (command "_.-boundary" "_a" "_i" "_n" "" "" "_non" pt "")
) 
  (foreach ent (vl-remove-if 'listp (mapcar 'cadr (ssnamex SS1)))
    (entdel ent) 
)                
(princ)
)

Right this code has done me very well so far there would be just one slight change that I would make.

I think the polylines that aren't a closed object should be closed. ie I have a shape I want to use the APV command be be distanced away from the red line as shown below. 

image.png.2be38e627c3f7dff44ed1e82625c2984.pngimage.png.d7901967d8b88c5d2591254beadb4410.pngimage.png.6b5e496dc6a3f61b866a9ef9d0966c1a.png

As you can see If I use the boundary command here now it would not include this offset from the red line because it was not closed. So if anyone can help me with a bit of code within this code to close off those parallel lines, that would be amazing.

 

I have done some googling and found this but not sure how that can be incorporated into the code I am using

https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/creating-multiple-closed-polygons-in-selected-closed-boundaries/td-p/8426623

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