Jump to content

Recommended Posts

Posted

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?

Posted

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

  • Like 1
Posted

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

Posted

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

Posted (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 by pBe
Major Blunder/Fixed
Posted

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.

Posted

FWIW - The MULTIPLE command can also be used for non-VL* code.

Posted (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 by pBe
Posted
FWIW - The MULTIPLE command can also be used for non-VL* code.

 

You are right :o

 

It didnt even cross my mind to use MULTIPLE, good catch Renderman

Posted

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

Posted

Alan - ^^ The comment is hilarious. LoL

 

You are right :o

 

It didnt even cross my mind to use MULTIPLE, good catch Renderman

 

:thumbsup:

Posted
Alan - ^^ The comment is hilarious. LoL

lol

I guess I could have call it offset inward As much As Possible.

Posted
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 :D 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

Posted
lol

I guess I could have call it offset inward As much As Possible.

 

:P.... LoL

Posted

(setq ss (ssget "_:L" '((0 . "LWPOLYLINE") (-4 . "&=") (70 . 1))))....

)

 

That is the filter i was looking for :thumbsup:

 

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" :ouch: modifying these is another matter entirely.

 

Good one BTW Alanjt

Posted (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 :lol:

Swamp

Autodesk

and CADTutor of course

 

and all this for free. ;)

Edited by pBe
Posted

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

Posted (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 by pBe
update code
Posted

I didn't get it, this is a response to alan or my post? :D

whichever it is it hits error: no function definition: VLAX-ENAME->VLA-OBJECT

I'm not much into Vlisp yet to debug it :D

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