Nikon Posted Sunday at 06:06 PM Posted Sunday at 06:06 PM (edited) Good day everyone! *** Happy New Year 2026! *** I wish you good health and creative success! I'm asking for help in changing the code. I want to select several rectangles and execute the command "Offset" OUTWARD by a specified distance. But the command performs an inward Offset. thanks (defun c:RectOffBatch (/ selset dist i ent pts maxpt offsetpt) (prompt "\nSelect rectangles (polylines): ") (setq selset (ssget '((0 . "LWPOLYLINE")))) (if selset (progn (initget 7) (setq dist (getdist "\nEnter the offset distance: ")) (setq i 0) (repeat (sslength selset) (setq ent (ssname selset i)) (setq pts (mapcar 'cdr (vl-remove-if-not '(lambda (x) (= (car x) 10)) (entget ent)))) (setq maxpt (list (apply 'max (mapcar 'car pts)) (apply 'max (mapcar 'cadr pts)))) (setq offsetpt (list (+ (car maxpt) dist) (+ (cadr maxpt) dist))) (command "_.OFFSET" dist ent offsetpt "") (setq i (1+ i)) ) ) ) (princ) ) Edited yesterday at 05:42 AM by Nikon Quote
Steven P Posted Sunday at 07:56 PM Posted Sunday at 07:56 PM I would maybe use: (vla-Offset (vlax-ename->vla-object ent) dist) where dist can be positive to go one direction, negative to go the other. This direction might also depend on the direction that the rectangle was drawn - clockwise or anticlockwise. Could do them both directions and just delete the shorter line - a few more lines of code to add though, some thinking for the first full week of work in 2026, always a quiet week. I might also suggest a couple more filters to the selection set, if all rectangles are closed polylines (test: 70 is 1 or 128 - use bitand (search for this Lee Mac uses this often to test both at the same time)), or number of vertices being 3 (closed polyline) or 4 (open polyline) (test: 90 is 3 or 4) 1 Quote
BIGAL Posted Sunday at 09:18 PM Posted Sunday at 09:18 PM A couple of answers, as suggested, check is closed pline ie a rectang drawn CW or CCW then vla-offset will always go out for a CCW pline. You can do a check and reverse the pline if required. Or the simpler is (setq offsetpt (getvar 'extmax)) 1 Quote
Lee Mac Posted Sunday at 09:23 PM Posted Sunday at 09:23 PM Use this and simply switch: *dist* (- *dist*) To: (- *dist*) *dist* 3 Quote
Nikon Posted yesterday at 06:09 AM Author Posted yesterday at 06:09 AM (edited) 9 hours ago, Lee Mac said: Use this and simply switch: *dist* (- *dist*) To: (- *dist*) *dist* @Lee Mac thank you, that's great! Is it possible to add a check for closing polylines to the code, and if they are not closed, close them? Is it possible to combine the two codes: OffInside.lsp и CloseLwPl.lsp? (defun c:CloseLwPl (/ ss i ent edata elist obj) (prompt "Select LWPOLYLINE: ") (setq ss (ssget '((0 . "LWPOLYLINE")))) (if ss (progn (setq i 0) (repeat (sslength ss) (setq ent (ssname ss i)) (setq edata (entget ent)) (setq elist (assoc 70 edata)) (if (not (and elist (= (logand (cdr elist) 1) 1))) (progn (entmod (subst (cons 70 (logior (cdr elist) 1)) elist edata)) (entupd ent) ) ) (setq i (1+ i)) ) ) ) (princ) ) Edited yesterday at 06:25 AM by Nikon Quote
Saxlle Posted yesterday at 10:00 AM Posted yesterday at 10:00 AM (edited) Anything can be done, but it would be helpful if you could post an example drawing so we can see those rectangles. You can use Lee's code to perform that making a two solutions, one for inside (as it is in the example from Lee's post, and one to performe outside offset as Lee suggested). Edited yesterday at 10:04 AM by Saxlle Quote
Nikon Posted yesterday at 10:14 AM Author Posted yesterday at 10:14 AM 14 minutes ago, Saxlle said: Anything can be done, but it would be helpful if you could post an example drawing so we can see those rectangles. Now we are talking not only about rectangles, but also polygons from LWPOLYLINE, POLYLINE. The problem is that the polygons from the LWPOLYLINE, POLYLINE must be closed. Lee Mac's OffInside.lsp code also allows offsets for CIRCLE, ARC, ELLIPSE, and SPLINE. Quote
GLAVCVS Posted yesterday at 03:17 PM Posted yesterday at 03:17 PM If the polygons aren't too irregular, using your own code, maybe this... (defun c:RectOffBatch (/ selset dist i ent pts maxpt offsetpt a70 es l le p1 p2 a) (prompt "\nSelect rectangles (polylines): ") (setq selset (ssget '((0 . "*POLYLINE")))) (vl-cmdf "_.CONVERTPOLY" "_Light" selset "") (if selset (progn (setq dist (getreal "\nEnter the offset distance or ENTER to indicate on screen: ")) (setq p1 (getpoint "\nPick on/near one of the rectangles to be offset...")) (if (and (setq es (car (nentselp p1))) (= (wcmatch (cdr (assoc 0 (entget es))) "LWP*"))) (progn (setq p2 (getpoint p1 "\nPoint to get direction (or distance) to offset: ")) (if (not dist) (setq dist (distance p1 p2))) (setq l (mapcar 'cdr (vl-remove-if-not '(lambda (x) (= (car x) 10)) (entget es)))) (setq midP (mapcar '(lambda(v) (/ v (length l))) (apply 'mapcar (cons '+ l)))) (setq a (if (> (distance p1 midP) (distance p2 midP)) 0 PI) i 0 ) (repeat (sslength selset) (setq ent (ssname selset i)) (setq pts (mapcar 'cdr (vl-remove-if-not '(lambda (x) (= (car x) 10)) (setq le (entget ent))))) (if (= (rem (cdr (setq a70 (assoc 70 le))) 2) 0) (entmod (subst (cons 70 (+ (cdr a70) 1)) a70 le))) (setq maxpt (list (apply 'max (mapcar 'car pts)) (apply 'max (mapcar 'cadr pts)))) (setq midP (mapcar '(lambda(v) (/ v (length pts))) (apply 'mapcar (cons '+ pts)))) (setq offsetpt (polar (car pts) (+ a (angle (car pts) midP)) 0.01)) (command "_.OFFSET" dist ent offsetpt "") (setq i (1+ i)) ) ) ) ) ) (princ) ) 1 Quote
GLAVCVS Posted yesterday at 03:23 PM Posted yesterday at 03:23 PM PS: 2D polylines do not support offset, so they need to be converted first. I haven't tested it extensively, but it should work for what you need. 1 Quote
Nikon Posted yesterday at 04:29 PM Author Posted yesterday at 04:29 PM (edited) 1 hour ago, GLAVCVS said: If the polygons aren't too irregular, using your own code, maybe this... (defun c:RectOffBatch (/ selset dist i ent pts maxpt offsetpt a70 es l le p1 p2 a) (prompt "\nSelect rectangles (polylines): ") (setq selset (ssget '((0 . "*POLYLINE")))) @GLAVCVS Thank The displacement occurs, but incorrectly, some rectangles (polygons) are shifted inside, some outside. I would like not to specify the offset point, but to have the offset performed automatically - Outside. The polygons are not too irregular... Some rectangles (polygons) from polylines are not closed, so the offset does not work for them. Lee Mac's code performs the offset automatically, but does not work with unclosed rectangles (polygons). Edited yesterday at 04:32 PM by Nikon Quote
GLAVCVS Posted yesterday at 04:36 PM Posted yesterday at 04:36 PM As @Saxlle says, if you post an example drawing, everything will be easier. Quote
Nikon Posted yesterday at 05:10 PM Author Posted yesterday at 05:10 PM (edited) 1 hour ago, GLAVCVS said: As @Saxlle says, if you post an example drawing, everything will be easier. I don't think an example drawing is needed. If you draw a rectangle using the Rectangle command, it is always closed. If you draw a rectangle (or polygon) using the Polyline command, it can be closed or open. Manually checking each rectangle (or polygon) is not very convenient... Therefore, I just wanted to add a check of polylines to the code, and if they are not closed, then close them. Сlosed-Not closed.dwg Edited yesterday at 06:02 PM by Nikon Quote
Steven P Posted yesterday at 06:31 PM Posted yesterday at 06:31 PM (70 . 1) or (70 . 128) will filter a selection set for closed polyline - (70 . 1) is usually enough 1 Quote
GLAVCVS Posted yesterday at 10:03 PM Posted yesterday at 10:03 PM 4 hours ago, Nikon said: I don't think an example drawing is needed. If you draw a rectangle using the Rectangle command, it is always closed. If you draw a rectangle (or polygon) using the Polyline command, it can be closed or open. Manually checking each rectangle (or polygon) is not very convenient... Therefore, I just wanted to add a check of polylines to the code, and if they are not closed, then close them. Сlosed-Not closed.dwg 36.39 kB · 5 downloads I tested the code on your drawing and it works correctly. Perhaps you didn't use it correctly. Nikon1.mp4 2 Quote
BIGAL Posted yesterday at 10:06 PM Posted yesterday at 10:06 PM (edited) As I said I did some testing about method, just get your closed plines, then check there CW or CCW direction and change if needed. Then use (getvar 'extmax) as offset point.In code below I use pedit "R" as the Reverse command is not available in Bricscad. CCW is offset out for a positive value using VLA-Offset. ; Checking if pline is CW or CCW and set to CCW ; Orignal idea by Kent Cooper, 1 August 2018 Offsetinorout.lsp ; By Alan H July 2020 (defun AH:chkcwccw (ent / objnew area1 area2 obj minpoint maxpoint) (setq obj (vlax-ename->vla-object ent)) (vla-GetBoundingBox obj 'minpoint 'maxpoint) (setq pointmin (vlax-safearray->list minpoint)) (setq pointmax (vlax-safearray->list maxpoint)) (setq dist (/ (distance pointmin pointmax) 20.0)) (vla-offset obj dist) (setq objnew (vlax-ename->vla-object (entlast))) (setq area1 (vlax-get objnew 'Area)) (vla-delete objnew) (vla-offset obj (- dist)) (setq objnew (vlax-ename->vla-object (entlast))) (setq area2 (vlax-get objnew 'Area)) (vla-delete objnew) (if (> area1 area2) (command "Pedit" ent "R" "") ) (princ) ) Edited yesterday at 10:07 PM by BIGAL 1 Quote
GLAVCVS Posted yesterday at 10:07 PM Posted yesterday at 10:07 PM (edited) Quote So that it only offsets outwards, for example, like this (defun c:RectOffBatch (/ selset dist i ent pts offsetpt a70 es l le p1 p2 a midP) (prompt "\nSelect rectangles (polylines): ") (setq selset (ssget '((0 . "*POLYLINE")))) (vl-cmdf "_.CONVERTPOLY" "_Light" selset "") (if selset (progn (setq dist (getdist "\nEnter the offset distance: ") i 0) (repeat (sslength selset) (setq ent (ssname selset i)) (setq pts (mapcar 'cdr (vl-remove-if-not '(lambda (x) (= (car x) 10)) (setq le (entget ent))))) (if (= (rem (cdr (setq a70 (assoc 70 le))) 2) 0) (entmod (subst (cons 70 (+ (cdr a70) 1)) a70 le))) (setq midP (mapcar '(lambda(v) (/ v (length pts))) (apply 'mapcar (cons '+ pts)))) (setq offsetpt (polar (car pts) (angle midP (car pts)) 0.01)) (command "_.OFFSET" dist ent offsetpt "") (setq i (1+ i)) ) ) ) (princ) ) Edited yesterday at 10:17 PM by GLAVCVS 1 Quote
Nikon Posted 16 hours ago Author Posted 16 hours ago (edited) @GLAVCVS "So that it only offsets outwards, for example, like this" I figured out what the problem was. Both codes are not working correctly with my bindings (osmode 183). With bindings disabled (osmode 0), the codes work perfectly. Thanks! (defun c:RectOffBatchOsm0-out (/ selset dist i ent pts offsetpt a70 es l le p1 p2 a midP osmode-prev) (prompt " Select rectangles (polylines): ") (setq selset (ssget '((0 . "*POLYLINE")))) (vl-cmdf "_.CONVERTPOLY" "_Light" selset "") (if selset (progn (setq osmode-prev (getvar "OSMODE")) (setvar "OSMODE" 0) (setq dist (getdist " Enter the offset distance: ") i 0) (repeat (sslength selset) (setq ent (ssname selset i)) (setq pts (mapcar 'cdr (vl-remove-if-not '(lambda (x) (= (car x) 10)) (setq le (entget ent))))) (if (= (rem (cdr (setq a70 (assoc 70 le))) 2) 0) (entmod (subst (cons 70 (+ (cdr a70) 1)) a70 le))) (setq midP (mapcar '(lambda(v) (/ v (length pts))) (apply 'mapcar (cons '+ pts)))) (setq offsetpt (polar (car pts) (angle midP (car pts)) 0.01)) (command "_.OFFSET" dist ent offsetpt "") (setq i (1+ i)) ) (setvar "OSMODE" osmode-prev) ) ) (princ) ) Edited 15 hours ago by Nikon Quote
GLAVCVS Posted 11 hours ago Posted 11 hours ago This version should work in all cases, regardless of the complexity of the polygons ;******************* p o r d e s i a r g o ******************** ;************************ G L A V C V S ************************* ;************************** F E C I T *************************** (defun c:RectOffBatch (/ selset dist i ent pts offsetpt a70 es l le p1 p2 o sDir) (defun sDir (le i? / p1 p2 p ar ang ab dir tl) (foreach l le (if (and (= (car l) 10) (setq p (cdr l))) (progn (if p2 (if p1 (setq dir (cond ((< (abs (setq ang (- (setq ar (angle p1 p2)) (setq ab (angle p2 p))))) PI) ang) (T (if (<= ar PI) (+ ar (- (* 2 PI) ab)) (- (- ar (* 2 PI)) ab))) ) ) ) ) (if dir (setq tl (+ (if tl tl 0) dir))) (setq p1 p2 p2 p dir nil) ) ) ) (if (minusp tl) (if i? + -) (if i? - +)) ) (prompt "\nSelect rectangles (polylines): ") (setq selset (ssget '((0 . "*POLYLINE")))) (vl-cmdf "_.CONVERTPOLY" "_Light" selset "") (if selset (if (setq i -1 dist (getdist "\nEnter the offset distance: ")) (repeat (sslength selset) (setq ent (ssname selset (setq i (1+ i)))) (setq o (sDir (setq le (entget ent)) nil)); <-- CHANGE 'nil' TO 'T' FOR OFFSET INWARD TOWARD INTERIOR OF THE POLYGONS (if (= (rem (cdr (setq a70 (assoc 70 le))) 2) 0) (entmod (subst (cons 70 (+ (cdr a70) 1)) a70 le))) (setq pr (vlax-curve-getPointAtParam ent 0.5)) (setq offsetpt (polar pr (o (angle (vlax-curve-getPointAtParam ent 0) pr) (/ PI 2.)) 0.1)) (command "_.OFFSET" dist ent offsetpt "") ) ) ) (princ) ) 2 Quote
GLAVCVS Posted 11 hours ago Posted 11 hours ago (edited) If you want to change the offset direction, you just need to change the 'i?' parameter used to call 'sDir' from 'nil' to 'T' (as indicated in the code comment). Nikon2.mp4 PS: The video shows the execution of the code with 'i?' set to 'T'. Edited 10 hours ago by GLAVCVS 1 Quote
Nikon Posted 10 hours ago Author Posted 10 hours ago 1 hour ago, GLAVCVS said: This version should work in all cases, regardless of the complexity of the polygons ;******************* p o r d e s i a r g o ******************** ;************************ G L A V C V S ************************* ;************************** F E C I T *************************** (defun c:RectOffBatch (/ selset dist i ent pts offsetpt a70 es l le p1 p2 o sDir) @GLAVCVS Thanks so much, I really appreciate your help! You offer many options, one is better than the other! I do not know about your drawing, but my bindings interfere with the correct execution of the code. Need to set OSMODE to 0. I use offset OUTSIDE more often, but we don't know what the future holds! 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.