anishtain4 Posted December 14, 2011 Posted December 14, 2011 Hi, I want to repeat an offset a certain of times lets assume the amount will be returned by the (numoff) I tried this but it's not working: (command "._offset" offdis entoff "m" (repeat (numoff) offto) nil) offdis is the distance of offset, entoff is the entity I wanna offset offto is the point where I want offset be on that side I also tried to put a list instead of the (repeat) but that doesn't work either, what should I do? Quote
Tharwat Posted December 14, 2011 Posted December 14, 2011 Hope this work for you and as per your needs . (defun c:TesT (/ s i d p v) ;;; Tharwat 14. Dec. 2011 ;;; (if (and (setq s (car (entsel "\n Select entity :"))) (member (cdr (assoc 0 (entget s))) '("*LINE" "CIRCLE" "ARC" "ELLIPSE")) (setq i (getint "\n number of offset times :")) (setq d (getdist "\n Distance of offset :")) (setq p (getpoint "\n Specify point on side to offset :")) (setq v d) ) (repeat i (command "_.offset" d s p "") (setq d (+ d v))) (princ) ) (princ) ) 1 Quote
anishtain4 Posted December 14, 2011 Author Posted December 14, 2011 actually I have written something like that: (if (= offnum "Five") ; offset five time for near out walls (repeat 5 (command "._offset" offdis e "m" polycenter nil) (setq e (entlast)) ) ; Offset as much as possible (while (not (eq e emother)) (command "._offset" offdis e "m" polycenter nil) (setq emother e) (setq e (entlast)) ) ) but I wanted to see if there is anyway to repeat the entity inside the command for commands that can get infinite inputs. thanks anyway Quote
anishtain4 Posted December 15, 2011 Author Posted December 15, 2011 Thanks pBe but that is now what I want to do, that lisp acts like the regular offset just saves you type multiple and can dimension that. I want something that automatically do my thing, I used the MacLee's routine for finding the center of gravity to automatically set the side which offset should be done, however there is a possibility I wanna offset a line which in that case offset side should be set manually. I have two cases, in one you should offset five time and in another offset should be continued as long it can. This is the lisp I came to, but sometimes when I wanna use it, it just keeps creating new offsets without finishing, when I try to debug it, it just works!!!! I'm getting a little confused of what's going on here? here is my lisp: (defun c:oi ( / e ) (if (setq e (ssget "_+.:S:E" '((0 . "LWPOLYLINE")))) (progn ;;; Offset distance (if (or (= offdis nil) (= offdis 1.0)) (setq offdis 0.1)) (setq oldoffdis offdis) (setq offdis (getreal (strcat "\nEnter offset distance: <" (rtos offdis) ">"))) (if (= offdis nil) (setq offdis oldoffdis)) ;;; Number of offsets (if (= offnum nil) (setq offnum "Infinite")) (setq oldoffnum offnum) (initget "Five Infinite") (setq offnum (getkword (strcat "\nNumber of repetition? (Five or Infinite): <" oldoffnum ">"))) (if (= offnum nil) (setq offnum oldoffnum)) ;;; Offset toward centroid(auto) or one side (initget "Auto Manual") (setq cogtype (getkword "\nWhere to offset? (Auto or Manual): <Auto>")) (if (= cogtype nil) (setq cogtype "Auto")) (if (= cogtype "Auto") (setq polycenter (LM:PolyCentroid (ssname e 0))) (setq polycenter (getpoint)) ) (setq emother nil) ;;; Plotings offsets (if (= offnum "Five") ; offset five time for near out walls (repeat 5 (command "._offset" offdis e polycenter nil) (setq e (entlast)) ) ; Offset as much as possible (while (not (eq e emother)) (command "._offset" offdis e polycenter nil) (setq emother e) (setq e (entlast)) (if (= cogtype "Auto") (setq polycenter (LM:PolyCentroid e ))) ) ) ) ) (princ) ) ;; Polygon Centroid - Lee Mac ;; Returns the centroid of an LWPolyline Polygon (defun LM:PolyCentroid ( e / l ) (foreach x (setq e (entget e)) (if (= 10 (car x)) (setq l (cons (cdr x) l))) ) ( (lambda ( a ) (trans (mapcar '/ (apply 'mapcar (cons '+ (mapcar (function (lambda ( a b ) ( (lambda ( m ) (mapcar (function (lambda ( c d ) (* (+ c d) m)) ) a b ) ) (- (* (car a) (cadr b)) (* (car b) (cadr a))) ) ) ) l (cons (last l) l) ) ) ) (list a a) ) (cdr (assoc 210 e)) 0 ) ) (* 3.0 (apply '+ (mapcar (function (lambda ( a b ) (- (* (car a) (cadr b)) (* (car b) (cadr a))) ) ) l (cons (last l) l) ) ) ) ) ) Quote
pBe Posted December 15, 2011 Posted December 15, 2011 (edited) I would suggest using vla-offset, where a positive number offset outwards and a negative number inwards (defun c:oi (/ e) [color=blue](vl-load-com) (defun lwcl (LW / LST MAXP MINP) ;;; ElpanovEvgeniy ;;; (vla-GetBoundingBox lw 'MinP 'MaxP) (setq minp (vlax-safearray->list minp) MaxP (vlax-safearray->list MaxP) lst (mapcar (function (lambda (x) (vlax-curve-getParamAtPoint lw (vlax-curve-getClosestPointTo lw x) ) ;_ vlax-curve-getParamAtPoint ) ;_ lambda ) ;_ function (list minp (list (car minp) (cadr MaxP)) MaxP (list (car MaxP) (cadr minp)) ) ;_ list ) ;_ mapcar ) ;_ setq (if (or (<= (car lst) (cadr lst) (caddr lst) (cadddr lst)) (<= (cadr lst) (caddr lst) (cadddr lst) (car lst)) (<= (caddr lst) (cadddr lst) (car lst) (cadr lst)) (<= (cadddr lst) (car lst) (cadr lst) (caddr lst)) ) ;_ or t ) ;_ if ) ;_ defun [/color] (if (setq e (ssget "_+.:S:E" '((0 . "LWPOLYLINE")))) (progn ;;; Offset distance ;;; (if (or (= offdis nil) (= offdis 1.0)) (setq offdis 0.1) ) (setq oldoffdis [color=blue](abs offdis)) [/color] (setq offdis (getreal (strcat "\nEnter offset distance: <" [color=blue](rtos [color=blue]oldoffdis[/color])[/color] ">") ) ) (if (= offdis nil) (setq offdis oldoffdis) ) ;;; Number of offsets (if (= offnum nil) (setq offnum "Infinite") ) (setq oldoffnum offnum) (initget "Five Infinite") (setq offnum (getkword (strcat "\nNumber of repetition? (Five or Infinite): <" oldoffnum ">" ) ) ) (if (= offnum nil) (setq offnum oldoffnum) ) [color=blue](setq e (ssname e 0) flg (lwcl (vlax-ename->vla-object e)))[/color] ;;; Modified ;;; [color=blue](initget "I O") [/color] (setq cogtype (getkword "\nWhere to offset [inside/Outside]: <Inside>" ) ) (if (= cogtype nil) (setq cogtype "I") ) [color=blue](cond ((eq cogtype "I") (setq offdis (if flg offdis (* offdis -1.0)))) ((eq cogtype "O") (setq offdis (if flg (* offdis -1.0) offdis )))) [/color] ;; Modified ;;; (if (= offnum "Five") ; offset five time for near out walls (repeat 5 [color=blue](vl-catch-all-error-p (vl-catch-all-apply 'vla-offset (list (vlax-ename->vla-object e) offdis) ) ) [/color] (setq e (entlast)) ) ; Offset as much as possible [color=blue](while (not (vl-catch-all-error-p (vl-catch-all-apply 'vla-offset (list (vlax-ename->vla-object e) offdis) ) ) [/color] ) (setq e (entlast)) ) ) ) ) (princ) ) HTH EDIT/WARNING: during testing phase I found out that it all depends on the direction of the polyline. I'll update the code later Code UPDATED: Edited December 15, 2011 by pBe Major Blunder/Fixed Quote
anishtain4 Posted December 17, 2011 Author Posted December 17, 2011 Thanks a lot, can you just do two other things for me to make me more grateful? 1. I never offset outside, it's always inside (because of the infinite) just there are cases where I wanna offset a line, then user does not know which side is inside and where is outside? then s/he should adjust it with get point. 2. what is the best source for learning lisp? I've read some tutorials and introductions but the vlax which I see most of the experienced users use a lot is strange to me. Quote
BlackBox Posted December 17, 2011 Posted December 17, 2011 FWIW - The MULTIPLE command can also be used for non-VL* code. Quote
pBe Posted December 17, 2011 Posted December 17, 2011 (edited) Thanks a lot, can you just do two other things for me to make me more grateful? 1. I never offset outside, it's always inside (because of the infinite)... It can be done, BUT i will code it to work only with closed polylines. I believe you know what will happen if its not specially with a 2 vertices polyline. there are cases where I wanna offset a line, then user does not know which side is inside and where is outside? then s/he should adjust it with get point. Your orignal code shows exclusive selection for ""LWPOLYLINE" BUT we can manage that. (defun c:oi (/ e etyp pto) (vl-load-com) ;;; Lee Mac ;;; (defun LM:ListClockwise-p (lst) (minusp (apply '+ (mapcar (function (lambda (a b) (- (* (car b) (cadr a)) (* (car a) (cadr b))) ) ) lst (cons (last lst) lst) ) ) ) ) (if (setq e (ssget "_+.:S:E" '((0 . "*LINE")))) (progn (if (not dist) (setq dist 1.00) ) (setq dist (cond ((getreal (strcat "\nEnter Distance <" (rtos (abs dist) 2 2) ">: " ) ) ) ((abs dist)) ) ) (setq e (ssname e 0) etyp (cdr (assoc 0 (entget e))) ) (cond ((and (eq etyp "LWPOLYLINE") (> (cdr (assoc 90 (entget e))) 2) ) (vla-put-closed (vlax-ename->vla-object e) :vlax-true) (setq dist (if (LM:ListClockwise-p (mapcar 'cdr (vl-remove-if-not '(lambda (x) (= (car x) 10) ) (entget e) ) ) ) dist (* dist -1.0) ) ) (while (not (vl-catch-all-error-p (vl-catch-all-apply 'vla-offset (list (vlax-ename->vla-object e) dist) ) ) ) (setq e (entlast)) ) ) ((eq etyp "LINE") (if (not rep) (setq rep 1) ) (initget 6) (setq d dist rep (cond ((getint (strcat "\nNumber of Offset <" (itoa rep) ">: " ) ) ) (rep) ) pto (getpoint "\nGetpoint Side to offset:") ) (repeat rep (command "._offset" d e pto nil) (setq d (+ d dist)) ) ) ) ) )(princ) ) 2. what is the best source for learning lisp? For one thing , you're on it Edited December 17, 2011 by pBe Quote
pBe Posted December 17, 2011 Posted December 17, 2011 FWIW - The MULTIPLE command can also be used for non-VL* code. You are right It didnt even cross my mind to use MULTIPLE, good catch Renderman Quote
alanjt Posted December 17, 2011 Posted December 17, 2011 For fun... (defun c:IOI (/ AT:TriangleArea ss i ent obj dst off) ;; Infinite Offset Inward (well, not infinite, but as much as possible, given the offset increment ;; Alan J. Thompson, 12.17.11 (defun AT:TriangleArea (a b c) ;; Returns area of three provided points ;; If returned value is negative, last point (c) exists on right side of a-b vector ;; Alan J. Thompson, 06.09.10 (/ (- (* (- (car b) (car a)) (- (cadr c) (cadr a))) (* (- (cadr b) (cadr a)) (- (car c) (car a))) ) 2. ) ) (initget 6) (if (and (setq *IOI:Inc* (cond ((getdist (strcat "\nSpecify inward offset increment" (if (numberp *IOI:Inc*) (strcat " <" (rtos *IOI:Inc*) ">: ") ": " ) ) ) ) (*IOI:Inc*) ) ) (setq ss (ssget "_:L" '((0 . "LWPOLYLINE") (-4 . "&=") (70 . 1)))) ) (repeat (setq i (sslength ss)) (setq ent (ssname ss (setq i (1- i))) obj (vlax-ename->vla-object ent) dst (if (minusp (AT:TriangleArea (vlax-curve-getPointAtParam ent 0) (vlax-curve-getPointAtParam ent 1) (vlax-curve-getPointAtParam ent 2) ) ) *IOI:Inc* (- *IOI:Inc*) ) ) (while (not (vl-catch-all-error-p (setq off (vl-catch-all-apply 'vlax-invoke (list obj 'Offset dst)))) ) (setq obj (car off)) ) ) ) (princ) ) Quote
BlackBox Posted December 17, 2011 Posted December 17, 2011 Alan - ^^ The comment is hilarious. LoL You are right It didnt even cross my mind to use MULTIPLE, good catch Renderman Quote
alanjt Posted December 17, 2011 Posted December 17, 2011 Alan - ^^ The comment is hilarious. LoL lol I guess I could have call it offset inward As much As Possible. Quote
anishtain4 Posted December 17, 2011 Author Posted December 17, 2011 It can be done, BUT i will code it to work only with closed polylines. I believe you know what will happen if its not specially with a 2 vertices polyline. Your orignal code shows exclusive selection for ""LWPOLYLINE" BUT we can manage that. Guess I just miss leaded you, the previous was great, you know I want this for Under floor heating drawings, pipe spacing is constant and pipes will be from the near wall all toward the inside of the area. but near the outer walls of the building pipe density always should have 5 rows of 0.1 spacing. So when the room has no outer wall the polyline will be closed, else it will be of two part, one near outer wall, and another for the rest of room. closed polylines would not always be beneficial when I said line I meant in geometry not entity since the code is using centroid and in that case it will be on the object itself and there is no geometrical clue which side is inside? Guess I know what you mean by not closed, it get's into a dead lock, well I simply add a condition that if the new polyline that has been created after the offset is longer than the original then stop and delete the last entity. here, if the user is able to select the side manually can probe a point which is inside the area (visually, not centroid) which will do the job. and by reference I meant a book, or something, you know, because I'm just wandering in this way Thank you a lot for your time Quote
BlackBox Posted December 18, 2011 Posted December 18, 2011 lolI guess I could have call it offset inward As much As Possible. .... LoL Quote
pBe Posted December 18, 2011 Posted December 18, 2011 (setq ss (ssget "_:L" '((0 . "LWPOLYLINE") (-4 . "&=") (70 . 1)))).... ) That is the filter i was looking for Initially I intended to use: (setq ss (ssget "_:L" '((-4 . "<OR") (0 . "LINE")(-4 . "<AND") (0 . "LWPOLYLINE")(70 . 1)(-4 . "AND>") (-4 . "OR>")) )) But it doesnt work with flg 129 (plinegen on) , besides i also need to select a "seemingly closed" polyline i.e. closed by osnap pick and not "C" where the flg is 0/128 . Your filter works 129, but when i try to include "LINE" (setq ss (ssget "_:L" '((0 . "LWPOLYLINE,LINE") (-4 . "&=") (70 . 1)))) No joy So. (setq ss (ssget "_:L" '((-4 . "<OR") (0 . "LINE") (-4 . "<AND")(0 . "LWPOLYLINE") [color=blue](-4 . "&=")[/color](70 . 1)(-4 . "AND>") (-4 . "OR>") ) )) But still it wont include the polylines i described above. I ended up with (setq e (ssget "_+.:S:E" '((0 . "*LINE")))) There's also "self intersecting polylines" modifying these is another matter entirely. Good one BTW Alanjt Quote
pBe Posted December 18, 2011 Posted December 18, 2011 (edited) and by reference I meant a book, or something, you know, because I'm just wandering in this way Thank you a lot for your time You're welcome anishtain4 you want it to work for not "just" lines but polyliens with two vetices as well? or exclusively polyines? Can you handle the modification you describe by yourself? Reference AFRALISP LMP And IMO the best way to learn is picking the brains of those who has done it all Swamp Autodesk and CADTutor of course and all this for free. Edited December 18, 2011 by pBe Quote
anishtain4 Posted December 18, 2011 Author Posted December 18, 2011 haha, I made you completely confused right? I use ONLY polylines, but they are not closed and centroid is not always extractable. I'm currently using the lisp of yours which had inside/outside (post #6). just a little modification of that will do it all, instead of outside put pick point!!, That's all. Well guess I managed the picking the brain part I first read jeffery panderson's but I rather books, you know they are organized. I got the book "The Visual LISP Developers Bible", one of the people here introduced that, guess it was renderman who is laughing up here, this book is great, brief and comprehensive. Thanks a thousands times for your help Quote
pBe Posted December 18, 2011 Posted December 18, 2011 (edited) In that case: (defun c:IOI (/ AT:TriangleArea ss i ent obj dst off) (vl-load-com) ;; Infinite Offset Inward (well, not infinite, but as much as possible, given the offset increment ;; Alan J. Thompson, 12.17.11 (defun AT:TriangleArea (a b c) ;; Returns area of three provided points ;; If returned value is negative, last point (c) exists on right side of a-b vector ;; Alan J. Thompson, 06.09.10 (/ (- (* (- (car b) (car a)) (- (cadr c) (cadr a))) (* (- (cadr b) (cadr a)) (- (car c) (car a))) ) 2. ) ) (initget 6) (if (and (setq *IOI:Inc* (cond ((getdist (strcat "\nSpecify inward offset increment" (if (numberp *IOI:Inc*) (strcat " <" (rtos *IOI:Inc*) ">: ") ": " ) ) ) ) (*IOI:Inc*) ) ) (setq ss (ssget "_:L" '[color=blue]((0 . "LWPOLYLINE"))[/color])) ) (repeat (setq i (sslength ss)) (setq ent (ssname ss (setq i (1- i))) obj (vlax-ename->vla-object ent) dst (if (minusp [color=blue](if (= (cdr (assoc 90 (entget ent))) 2)[/color] [color=blue] (progn (redraw ent 3)[/color] [color=blue] (AT:TriangleArea[/color] [color=blue] (vlax-curve-getEndPoint obj)[/color] [color=blue] (getpoint "\nPick Side to Offset:")[/color] [color=blue] (vlax-curve-getStartPoint obj)[/color] [color=blue] )[/color] [color=blue] )[/color] (AT:TriangleArea (vlax-curve-getPointAtParam ent 0) (vlax-curve-getPointAtParam ent 1) (vlax-curve-getPointAtParam ent 2) ) [color=blue] )[/color] ) *IOI:Inc* (- *IOI:Inc*) ) ) (if [color=sienna](or[/color] (= (cdr (assoc 70 (entget ent))) 1) [color=sienna] (equal (vlax-curve-getEndPoint obj)[/color] [color=sienna] (vlax-curve-getStartPoint obj)[/color] [color=sienna] )[/color] [color=sienna] )[/color] (while (not (vl-catch-all-error-p (setq off (vl-catch-all-apply 'vlax-invoke (list obj 'Offset dst) ) ) ) ) (setq obj (car off)) ) [color=blue](progn[/color] [color=blue] (redraw ent 4)[/color] [color=blue] (repeat 5[/color] [color=blue] (vl-catch-all-error-p[/color] [color=blue] (setq off (vl-catch-all-apply[/color] [color=blue] 'vlax-invoke[/color] [color=blue] (list obj 'Offset dst)[/color] [color=blue] )[/color] [color=blue] )[/color] [color=blue] )[/color] [color=blue] (setq obj (car off))[/color] [color=blue] )[/color] [color=blue] )[/color] ) ) )(princ) ) More fun Kudos to Alanjt CODE UPDATED: Edited December 19, 2011 by pBe update code Quote
anishtain4 Posted December 18, 2011 Author Posted December 18, 2011 I didn't get it, this is a response to alan or my post? whichever it is it hits error: no function definition: VLAX-ENAME->VLA-OBJECT I'm not much into Vlisp yet to debug it 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.