CFORD Posted November 15, 2022 Posted November 15, 2022 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 Quote
CFORD Posted November 15, 2022 Author Posted November 15, 2022 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? Quote
mhupp Posted November 15, 2022 Posted November 15, 2022 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. 2 Quote
Steven P Posted November 15, 2022 Posted November 15, 2022 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?) 2 Quote
CFORD Posted November 15, 2022 Author Posted November 15, 2022 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 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. Quote
BIGAL Posted November 15, 2022 Posted November 15, 2022 Just maybe another way for boundary, I use bpoly, make a dummy outline and pick point inside it. Quote
CFORD Posted November 15, 2022 Author Posted November 15, 2022 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 Quote
mhupp Posted November 16, 2022 Posted November 16, 2022 (edited) <> is the button up top will pop up another window to input the code so its easier to copy and scoll down as much. 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 November 16, 2022 by mhupp 1 Quote
CFORD Posted November 16, 2022 Author Posted November 16, 2022 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 Quote
CFORD Posted November 16, 2022 Author Posted November 16, 2022 (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 1 Quote
CFORD Posted November 24, 2022 Author Posted November 24, 2022 (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. 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 Quote
CFORD Posted November 24, 2022 Author Posted November 24, 2022 Done a bit more digging and found this https://cadtips.cadalyst.com/linear-objects/draw-a-cap-or-pipe-end?q=linear-objects/draw-a-cap-or-pipe-end which is very near what I want I just need to cap the offset lines but not sure how that would work in the existing code I have Quote
Recommended Posts
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.