Jump to content

An offset Marco for CNC Plasma cutting process!


abghrnjd

Recommended Posts

I often have to nest sheet metal parts for an old CNC laser cutter. We need to make an offset toward outside for the part boundary and also an offset toward inside for all the holes and objects inside the part. The final part is in green color. It is a time consuming process for like 100 parts.
I need a macro that can open part files, make the offsets as I explained, save and close the file, going to the next file and does the same till all parts are done.
I'm already using action macros but there are some problems. sometimes my offset lies inside instead of outside and vice versa for the inside objects. I have to open and close the files myself. which is time consuming.
Is there any easier solution before I start learning AutoLisp or VBA and going a long road?

Untitled.jpg

Link to comment
Share on other sites

18 hours ago, mhupp said:

I would check the software you use for cutting for an offset option.

 

Unfortunately, such an option is not available. 😑

Link to comment
Share on other sites

23 hours ago, abghrnjd said:

I'm already using action macros but there are some problems. sometimes my offset lies inside instead of outside and vice versa for the inside objects.

 

I would suggest either using color coding or using different layers for the direction of offset. like the perimeter is blue for offset in. green can be offset out.

  • Like 1
Link to comment
Share on other sites

If all the insides are holes, or circles, then this is easier but I suspect that the holes are not all circular and might be 'odd' shapes.

 

is the boundary always going to be a polyline? and do the holes always go the opposite direction of the boundary (never both in or both out)? Are the drawings only ever for a single part? Are the boundaries for example drawn with a corner at the same coordinate for example 0,0?

 

A couple of ways to go but I would get the basic rules right and then it is a lot easier, set up a LISP passing a variable to it (in or out) and the drawing number - which should be fairly easy - and then go at it with a script routine.

 

Easy or hard road? You are likely to get a fairly complete solution.

 

 

Link to comment
Share on other sites

would look something like this.

 

If the polyline is CCW

+dist is offset out

-dist is offset in

 

(if (setq SS (ssget "_X" '((0 . "*POLYLINE") (70 . 1) (62 . 5))))
  (foreach ent (vl-remove-if 'listp (mapcar 'cadr (ssnamex SS)))
    (setq obj (vlax-ename->vla-object ent))
    (vla-offset obj Distance)
  )
)

 

  • Like 1
Link to comment
Share on other sites

Mhupp I think I got this from PBE.   Note for Bricscad use Pedit Plent R.

 

;; get closed polygon's area

(defun ss-pts2area  (l)
(/ (apply (function +)
            (mapcar (function (lambda (x y)
                                (- (* (car x) (cadr y)) (* (car y) (cadr x)))))
                    (cons (last l) l)
                    l)) 
2.)
)

 ;_force pointset CCW
(setq plent (entsel "\nPick pline"))
(setq co-ord (mapcar 'cdr (vl-remove-if-not '(lambda (x) (= (car x) 10)) (entget (car plent)))))

(if (< (ss-pts2area co-ord) 0)
(command "reverse" plent)
)

 

  • Like 1
Link to comment
Share on other sites

21 hours ago, Steven P said:

If all the insides are holes, or circles, then this is easier but I suspect that the holes are not all circular and might be 'odd' shapes.

 

is the boundary always going to be a polyline? and do the holes always go the opposite direction of the boundary (never both in or both out)? Are the drawings only ever for a single part? Are the boundaries for example drawn with a corner at the same coordinate for example 0,0?

 

A couple of ways to go but I would get the basic rules right and then it is a lot easier, set up a LISP passing a variable to it (in or out) and the drawing number - which should be fairly easy - and then go at it with a script routine.

 

Easy or hard road? You are likely to get a fairly complete solution.

 

 

Inside object can be anything. But everything is a closed joined objects.

I figured this out that the most obvious distinction between inside and the boundary object is their area. The boundary object has the largest area. This way we can identify the correct offset directions. I guess this is key. I just can't write a LISP code yet.

Link to comment
Share on other sites

To tell the machine what you want to do, have to think more step by step. 

 

You may have questions such as: 

Q1. Does 1 dwg contain only 1 part? 

Q2. Doesn't one dwg contain objects that are not parts and have nothing to do with parts?

 

If you YES these 2 questions,

you can add all polylines to the selection set with (ssget "X" '((0 . "LWPOLYLINE"))) 

and then mark the polyline with the largest area as the outside. 

 

Q3. Are there any isolated objects like donuts in your parts?

this case make some headache.. 

If you don't have donuts, you just have to offset them all to the small side. But with donuts, a problem arises.

It may be better to auto-assign the isolate using a hatch.

This is just example, I recently used command HATCH to group objects into a selection set. (BMP3)

https://www.cadtutor.net/forum/topic/75162-bmp-file-to-polyline-mosaic/

 

And when offsetting a closed polyline, 

you need to know whether the polyline is drawn clockwise or counterclockwise to determine the direction of the outer or inner offset. 

This is the correct way. 

but I think below is more understandable, 

1. create inside & outside both polylines

2. determine the outside if the length is long & the inside if the length is short

3. and delete what you don't need.

This Link is example I wrote this way. Lisp that repeatedly offsets the inside of a shape until it is impossible to offset it.

https://www.cadtutor.net/forum/topic/74957-inside-offset-multiple/

This allows you to use the offset in any direction without considering the order of the nodes.

It's not a good way because to create something you don't need and then delete it. But for a beginner like me, this was more intuitive.

 

And, It is generally impossible to use Lisp in multiple drawings,
so i recommend using it with a script. 

However, if you have difficulties with the script, there is a simple way to register Lisp in the startup set, 

make Lisp run automatically when opened, 

then open all DWGs manually, then save and close at once. with CLOSEALL command

Edited by exceed
  • Like 2
Link to comment
Share on other sites

Thank you.

Q1 = Yes, we always just one part in every file. that's why we need to open files , do the offset, then save and close.

Q2 = No, we have just a part and nothing else.

Q3= There is no donuts.

 

Link to comment
Share on other sites

Just to get you going a bit, this should return the entity name of the largest area polyline in your drawing. Command LineArea

 

(defun PolyLineArea ( MyPolyLineEntName / MyArea)
  (setq MyPolyLine (vlax-ename->vla-object MyPolyLineEntName))
  (setq MyArea (vla-get-Area MyPolyLine) )
  MyArea
)

;;https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/find-the-largest-number-in-a-list-of-numbers/td-p/816742
(defun maxinlist (x / next highest)
  (setq next 0)
  (setq highest (nth 0 x)) ; Assumes that the first item in the list is the highest. Then iterates through every number in the list
  (while (< next (1- (length x)))
    (setq highest (max highest (nth (1+ next) x)))
    (setq next (1+ next))
    )
  highest
  )
)
                
                
                
(defun c:LineArea ( / MyPolyLineEntName Acount AreaList)
  (vl-load-com)            ;;Load VL
  (setq AreaList (list))   ;;Blank List
  (setq Acount 0)          ;; Set a counter to 0
  (setq ss (ssget "_A"))   ;;select set, all visible objexts, change A to X for all objects
  (while (< acount (sslength ss)) ;;Loop through selection Set, ss
    (setq MyPolyLineEntName (ssname ss Acount))  ;;nth entity in ss name
    (setq AreaList (append AreaList (list (PolyLineArea MyPolyLineEntName)) )) ;;get object area from PolyLineArea function above
    (setq Acount (+ Acount 1))  ;;increase counter
  )
  (setq largestEntity (ssname ss (vl-position (maxinlist AreaList) AreaList) )) ;; the perimeter entity name using maxinlist function above
)

 

 

and I reckon if you look to MHUPPs above that will let you offset the perimeter and remove that from the selection set list, , then you can offset all that is left in the other direction, add something to save and close the file and job done?

 

Will come back to look at this tomorrow

  • Like 2
Link to comment
Share on other sites

; CNC - 2022.05.31 exceed
; https://www.cadtutor.net/forum/topic/75276-an-offset-marco-for-cnc-plasma-cutting-process/
;
; Works on closed polylines, circles.
; Objects with the largest area are offset outward, others are offset inward.
;
; Command List
; CNC - do offset
; @Q - Save and close all opened drawings. Dialogs do not appear individually when closing each drawing. Appears only once for confirmation.
; 
; The color is designated as number 3 (green). The layer does not change.
;
; Edit 10 in (setq offsetvalue 10) to adjust the offset length
;
; When you add this Lisp to your starter set, it will work automatically every time you open a drawing.
; Open multiple drawings and save and close them all with the @Q command.
; If you want to manually, add ; in front of (c:CNC) to make ;(c:CNC), 
; it will work when manually entering CNC
;
; Note
; If you reopen a drawing that has already been executed and saved, it will be created again. 
; In this part, it seems to be necessary to add a statement that does not execute if there is a green object in the drawing.
; Your green looks different than mine, so I didn't add this code.


(vl-load-com)
(defun c:CNC ( / offsetvalue ss ssl index arealist obj objarea objlist outerloopobj outeroffset otherloop otherlooplen index2 otherloopobj inneroffset )

  (setq offsetvalue 10)
 
  (setq ss (ssget "X" '((0 . "LWPOLYLINE,CIRCLE"))))
  (setq ssl (sslength ss))
  (setq index 0)
  (setq arealist '())
  (repeat ssl
    (setq obj (vlax-ename->vla-object (ssname ss index)))
    (setq objarea (vla-get-area obj))
    (setq objlist (list obj objarea))
    (setq arealist (cons objlist arealist))
    (setq index (+ index 1))
  )
  (setq arealist (vl-sort arealist (function (lambda (x1 x2) (> (cadr x1) (cadr x2)) ) )))
  
  (setq outerloopobj (car (car arealist)))
  (setq outeroffset (ex:offsetout outerloopobj offsetvalue))
  (vlax-put-property outeroffset 'color 3)

  (setq otherloop (cdr arealist))
  (setq otherlooplen (length otherloop))
  (setq index2 0)

  (repeat otherlooplen
    (setq otherloopobj (car (nth index2 otherloop)))
    (setq inneroffset (ex:offsetin otherloopobj offsetvalue))
    (vlax-put-property inneroffset 'color 3)
    (setq index2 (+ index2 1))
  )
  

  (princ)
)
 


(defun ex:offsetin ( obj offdis / subloop1 subloop2 subloop1type subloop2type subloop1length subloop2length objloop)
   (vla-offset obj (* offdis 1))
   (setq subloop1 (vlax-ename->vla-object (entlast)))
   (vla-offset obj (* offdis -1))
   (setq subloop2 (vlax-ename->vla-object (entlast)))
   (setq subloop1type (vlax-get-property subloop1 'entityname))
   (setq subloop2type (vlax-get-property subloop2 'entityname))
   (cond 
     ((= subloop1type "AcDbPolyline")
      (setq subloop1length (vlax-get-property subloop1 'length))
     )
     ((= subloop1type "AcDbCircle")
      (setq subloop1length (vlax-get-property subloop1 'Circumference))
     )
     ((= subloop1type "AcDbArc")
      (setq subloop1length (vlax-get-property subloop1 'Radius))
     )
   );end of cond
   (cond 
     ((= subloop2type "AcDbPolyline")
      (setq subloop2length (vlax-get-property subloop2 'length))
     )
     ((= subloop2type "AcDbCircle")
      (setq subloop2length (vlax-get-property subloop2 'Circumference))
     )
     ((= subloop2type "AcDbArc")
      (setq subloop2length (vlax-get-property subloop2 'Radius))
     )
   );end of cond
   (cond
      ((> subloop1length subloop2length) (progn (vla-delete subloop1) (setq looplength subloop2length) (setq objloop subloop2)))      
      ((< subloop1length subloop2length) (progn (vla-delete subloop2) (setq looplength subloop1length) (setq objloop subloop1)))
      ((= subloop1length subloop2length) (progn (vla-delete subloop2) (setq looplength subloop1length) (setq objloop subloop1)))
   )
   objloop
)

(defun ex:offsetout ( obj offdis / subloop1 subloop2 subloop1type subloop2type subloop1length subloop2length objloop)
   (vla-offset obj (* offdis 1))
   (setq subloop1 (vlax-ename->vla-object (entlast)))
   (vla-offset obj (* offdis -1))
   (setq subloop2 (vlax-ename->vla-object (entlast)))
   (setq subloop1type (vlax-get-property subloop1 'entityname))
   (setq subloop2type (vlax-get-property subloop2 'entityname))
   (cond 
     ((= subloop1type "AcDbPolyline")
      (setq subloop1length (vlax-get-property subloop1 'length))
     )
     ((= subloop1type "AcDbCircle")
      (setq subloop1length (vlax-get-property subloop1 'Circumference))
     )
     ((= subloop1type "AcDbArc")
      (setq subloop1length (vlax-get-property subloop1 'Radius))
     )
   );end of cond
   (cond 
     ((= subloop2type "AcDbPolyline")
      (setq subloop2length (vlax-get-property subloop2 'length))
     )
     ((= subloop2type "AcDbCircle")
      (setq subloop2length (vlax-get-property subloop2 'Circumference))
     )
     ((= subloop2type "AcDbArc")
      (setq subloop2length (vlax-get-property subloop2 'Radius))
     )
   );end of cond
   (cond
      ((< subloop1length subloop2length) (progn (vla-delete subloop1) (setq looplength subloop2length) (setq objloop subloop2)))      
      ((> subloop1length subloop2length) (progn (vla-delete subloop2) (setq looplength subloop1length) (setq objloop subloop1)))
      ((= subloop1length subloop2length) (progn (vla-delete subloop2) (setq looplength subloop1length) (setq objloop subloop1)))
   )
   objloop
)


; close all by Middleton, Cliff 
; https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/early-christmas/m-p/777308/highlight/true#M2966

(defun C:@Q nil
  (cond
    ((= 6 (LM:popup "Close All with Save" "You want close all with save?"  36))
      (@CloseWithSave)
      (command "_close" "n")
    )
    (t (princ "\nCanceled"))
  )
  (princ)
)

(defun @CloseWithSave ( / cnt) 
  (setq cnt (@CloseAllButActive :vlax-True))
  (if (> cnt 0)
    (princ (strcat "\n[ " (itoa cnt) " ] " (if (> cnt 1) "s" "") "are saved and closed"))
    (princ "\nThere's no dwg for closing.")
  )
  (princ)
)

(defun @CloseAllButActive (TrueOrFalse / cnt)
  (setq cnt 0)
  (vlax-for Item (vla-get-Documents (vlax-get-acad-object))
    (if (= (vla-get-Active Item) :vlax-False)
      (progn
        (vla-close Item TrueOrFalse)
        (setq cnt (1+ cnt))
      )
    )
  )
  cnt
)

;; Popup  -  Lee Mac
;; A wrapper for the WSH popup method to display a message box prompting the user.
;; ttl - [str] Text to be displayed in the pop-up title bar
;; msg - [str] Text content of the message box
;; bit - [int] Bit-coded integer indicating icon & button appearance
;; Returns: [int] Integer indicating the button pressed to exit

(defun LM:popup ( ttl msg bit / wsh rtn )
    (if (setq wsh (vlax-create-object "wscript.shell"))
        (progn
            (setq rtn (vl-catch-all-apply 'vlax-invoke-method (list wsh 'popup msg 0 ttl bit)))
            (vlax-release-object wsh)
            (if (not (vl-catch-all-error-p rtn)) rtn)
        )
    )
)


(c:CNC)

cnc.gif

 

Edited by exceed
  • Like 2
Link to comment
Share on other sites

4 hours ago, exceed said:
; CNC - 2022.05.31 exceed
; https://www.cadtutor.net/forum/topic/75276-an-offset-marco-for-cnc-plasma-cutting-process/
;
; Works on closed polylines, circles.
; Objects with the largest area are offset outward, others are offset inward.
;
; Command List
; CNC - do offset
; @Q - Save and close all opened drawings. Dialogs do not appear individually when closing each drawing. Appears only once for confirmation.
; 
; The color is designated as number 3 (green). The layer does not change.
;
; Edit 10 in (setq offsetvalue 10) to adjust the offset length
;
; When you add this Lisp to your starter set, it will work automatically every time you open a drawing.
; Open multiple drawings and save and close them all with the @Q command.
; If you want to manually, add ; in front of (c:CNC) to make ;(c:CNC), 
; it will work when manually entering CNC
;
; Note
; If you reopen a drawing that has already been executed and saved, it will be created again. 
; In this part, it seems to be necessary to add a statement that does not execute if there is a green object in the drawing.
; Your green looks different than mine, so I didn't add this code.


(vl-load-com)
(defun c:CNC ( / offsetvalue ss ssl index arealist obj objarea objlist outerloopobj outeroffset otherloop otherlooplen index2 otherloopobj inneroffset )

  (setq offsetvalue 10)
 
  (setq ss (ssget "X" '((0 . "LWPOLYLINE,CIRCLE"))))
  (setq ssl (sslength ss))
  (setq index 0)
  (setq arealist '())
  (repeat ssl
    (setq obj (vlax-ename->vla-object (ssname ss index)))
    (setq objarea (vla-get-area obj))
    (setq objlist (list obj objarea))
    (setq arealist (cons objlist arealist))
    (setq index (+ index 1))
  )
  (setq arealist (vl-sort arealist (function (lambda (x1 x2) (> (cadr x1) (cadr x2)) ) )))
  
  (setq outerloopobj (car (car arealist)))
  (setq outeroffset (ex:offsetout outerloopobj offsetvalue))
  (vlax-put-property outeroffset 'color 3)

  (setq otherloop (cdr arealist))
  (setq otherlooplen (length otherloop))
  (setq index2 0)

  (repeat otherlooplen
    (setq otherloopobj (car (nth index2 otherloop)))
    (setq inneroffset (ex:offsetin otherloopobj offsetvalue))
    (vlax-put-property inneroffset 'color 3)
    (setq index2 (+ index2 1))
  )
  

  (princ)
)
 


(defun ex:offsetin ( obj offdis / subloop1 subloop2 subloop1type subloop2type subloop1length subloop2length objloop)
   (vla-offset obj (* offdis 1))
   (setq subloop1 (vlax-ename->vla-object (entlast)))
   (vla-offset obj (* offdis -1))
   (setq subloop2 (vlax-ename->vla-object (entlast)))
   (setq subloop1type (vlax-get-property subloop1 'entityname))
   (setq subloop2type (vlax-get-property subloop2 'entityname))
   (cond 
     ((= subloop1type "AcDbPolyline")
      (setq subloop1length (vlax-get-property subloop1 'length))
     )
     ((= subloop1type "AcDbCircle")
      (setq subloop1length (vlax-get-property subloop1 'Circumference))
     )
     ((= subloop1type "AcDbArc")
      (setq subloop1length (vlax-get-property subloop1 'Radius))
     )
   );end of cond
   (cond 
     ((= subloop2type "AcDbPolyline")
      (setq subloop2length (vlax-get-property subloop2 'length))
     )
     ((= subloop2type "AcDbCircle")
      (setq subloop2length (vlax-get-property subloop2 'Circumference))
     )
     ((= subloop2type "AcDbArc")
      (setq subloop2length (vlax-get-property subloop2 'Radius))
     )
   );end of cond
   (cond
      ((> subloop1length subloop2length) (progn (vla-delete subloop1) (setq looplength subloop2length) (setq objloop subloop2)))      
      ((< subloop1length subloop2length) (progn (vla-delete subloop2) (setq looplength subloop1length) (setq objloop subloop1)))
      ((= subloop1length subloop2length) (progn (vla-delete subloop2) (setq looplength subloop1length) (setq objloop subloop1)))
   )
   objloop
)

(defun ex:offsetout ( obj offdis / subloop1 subloop2 subloop1type subloop2type subloop1length subloop2length objloop)
   (vla-offset obj (* offdis 1))
   (setq subloop1 (vlax-ename->vla-object (entlast)))
   (vla-offset obj (* offdis -1))
   (setq subloop2 (vlax-ename->vla-object (entlast)))
   (setq subloop1type (vlax-get-property subloop1 'entityname))
   (setq subloop2type (vlax-get-property subloop2 'entityname))
   (cond 
     ((= subloop1type "AcDbPolyline")
      (setq subloop1length (vlax-get-property subloop1 'length))
     )
     ((= subloop1type "AcDbCircle")
      (setq subloop1length (vlax-get-property subloop1 'Circumference))
     )
     ((= subloop1type "AcDbArc")
      (setq subloop1length (vlax-get-property subloop1 'Radius))
     )
   );end of cond
   (cond 
     ((= subloop2type "AcDbPolyline")
      (setq subloop2length (vlax-get-property subloop2 'length))
     )
     ((= subloop2type "AcDbCircle")
      (setq subloop2length (vlax-get-property subloop2 'Circumference))
     )
     ((= subloop2type "AcDbArc")
      (setq subloop2length (vlax-get-property subloop2 'Radius))
     )
   );end of cond
   (cond
      ((< subloop1length subloop2length) (progn (vla-delete subloop1) (setq looplength subloop2length) (setq objloop subloop2)))      
      ((> subloop1length subloop2length) (progn (vla-delete subloop2) (setq looplength subloop1length) (setq objloop subloop1)))
      ((= subloop1length subloop2length) (progn (vla-delete subloop2) (setq looplength subloop1length) (setq objloop subloop1)))
   )
   objloop
)


; close all by Middleton, Cliff 
; https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/early-christmas/m-p/777308/highlight/true#M2966

(defun C:@Q nil
  (cond
    ((= 6 (LM:popup "Close All with Save" "You want close all with save?"  36))
      (@CloseWithSave)
      (command "_close" "n")
    )
    (t (princ "\nCanceled"))
  )
  (princ)
)

(defun @CloseWithSave ( / cnt) 
  (setq cnt (@CloseAllButActive :vlax-True))
  (if (> cnt 0)
    (princ (strcat "\n[ " (itoa cnt) " ] " (if (> cnt 1) "s" "") "are saved and closed"))
    (princ "\nThere's no dwg for closing.")
  )
  (princ)
)

(defun @CloseAllButActive (TrueOrFalse / cnt)
  (setq cnt 0)
  (vlax-for Item (vla-get-Documents (vlax-get-acad-object))
    (if (= (vla-get-Active Item) :vlax-False)
      (progn
        (vla-close Item TrueOrFalse)
        (setq cnt (1+ cnt))
      )
    )
  )
  cnt
)

;; Popup  -  Lee Mac
;; A wrapper for the WSH popup method to display a message box prompting the user.
;; ttl - [str] Text to be displayed in the pop-up title bar
;; msg - [str] Text content of the message box
;; bit - [int] Bit-coded integer indicating icon & button appearance
;; Returns: [int] Integer indicating the button pressed to exit

(defun LM:popup ( ttl msg bit / wsh rtn )
    (if (setq wsh (vlax-create-object "wscript.shell"))
        (progn
            (setq rtn (vl-catch-all-apply 'vlax-invoke-method (list wsh 'popup msg 0 ttl bit)))
            (vlax-release-object wsh)
            (if (not (vl-catch-all-error-p rtn)) rtn)
        )
    )
)


(c:CNC)

cnc.gif

 

Thank you. 

It works perfectly. the only thing is to get the offset distance from user. just like other AutoCAD commands. that would be incredible! It it possible?

Link to comment
Share on other sites

; CNC - 2022.05.31 exceed
; https://www.cadtutor.net/forum/topic/75276-an-offset-marco-for-cnc-plasma-cutting-process/
;
; Works on closed polylines, circles.
; Objects with the largest area are offset outward, others are offset inward.
;
; Command List
; CNC - do offset
; @Q - Save and close all opened drawings. Dialogs do not appear individually when closing each drawing. Appears only once for confirmation.
; 
; The color is designated as number 3 (green). The layer does not change.
;
; When you add this Lisp to your starter set, it will work automatically every time you open a drawing.
; Open multiple drawings and save and close them all with the @Q command.
; If you want to manually, add ; in front of (c:CNC) to make ;(c:CNC), 
; it will work when manually entering CNC
;
; Note
; If you reopen a drawing that has already been executed and saved, it will be created again. 
; In this part, it seems to be necessary to add a statement that does not execute if there is a green object in the drawing.
; Your green looks different than mine, so I didn't add this code.


(vl-load-com)
(defun c:CNC ( / offsetvalue ss ssl index arealist obj objarea objlist outerloopobj outeroffset otherloop otherlooplen index2 otherloopobj inneroffset )

  ;(setq offsetvalue 10)
  (setq offsetvalue (getreal "\n Input offset value : "))
  (if (= offsetvalue nil) (progn (princ "\n you cancel CNC offset command") (exit)) )
 
  (setq ss (ssget "X" '((0 . "LWPOLYLINE,CIRCLE"))))
  (setq ssl (sslength ss))
  (setq index 0)
  (setq arealist '())
  (repeat ssl
    (setq obj (vlax-ename->vla-object (ssname ss index)))
    (setq objarea (vla-get-area obj))
    (setq objlist (list obj objarea))
    (setq arealist (cons objlist arealist))
    (setq index (+ index 1))
  )
  (setq arealist (vl-sort arealist (function (lambda (x1 x2) (> (cadr x1) (cadr x2)) ) )))
  
  (setq outerloopobj (car (car arealist)))
  (setq outeroffset (ex:offsetout outerloopobj offsetvalue))
  (vlax-put-property outeroffset 'color 3)

  (setq otherloop (cdr arealist))
  (setq otherlooplen (length otherloop))
  (setq index2 0)

  (repeat otherlooplen
    (setq otherloopobj (car (nth index2 otherloop)))
    (setq inneroffset (ex:offsetin otherloopobj offsetvalue))
    (vlax-put-property inneroffset 'color 3)
    (setq index2 (+ index2 1))
  )
  

  (princ)
)
 


(defun ex:offsetin ( obj offdis / subloop1 subloop2 subloop1type subloop2type subloop1length subloop2length objloop)
   (vla-offset obj (* offdis 1))
   (setq subloop1 (vlax-ename->vla-object (entlast)))
   (vla-offset obj (* offdis -1))
   (setq subloop2 (vlax-ename->vla-object (entlast)))
   (setq subloop1type (vlax-get-property subloop1 'entityname))
   (setq subloop2type (vlax-get-property subloop2 'entityname))
   (cond 
     ((= subloop1type "AcDbPolyline")
      (setq subloop1length (vlax-get-property subloop1 'length))
     )
     ((= subloop1type "AcDbCircle")
      (setq subloop1length (vlax-get-property subloop1 'Circumference))
     )
     ((= subloop1type "AcDbArc")
      (setq subloop1length (vlax-get-property subloop1 'Radius))
     )
   );end of cond
   (cond 
     ((= subloop2type "AcDbPolyline")
      (setq subloop2length (vlax-get-property subloop2 'length))
     )
     ((= subloop2type "AcDbCircle")
      (setq subloop2length (vlax-get-property subloop2 'Circumference))
     )
     ((= subloop2type "AcDbArc")
      (setq subloop2length (vlax-get-property subloop2 'Radius))
     )
   );end of cond
   (cond
      ((> subloop1length subloop2length) (progn (vla-delete subloop1) (setq looplength subloop2length) (setq objloop subloop2)))      
      ((< subloop1length subloop2length) (progn (vla-delete subloop2) (setq looplength subloop1length) (setq objloop subloop1)))
      ((= subloop1length subloop2length) (progn (vla-delete subloop2) (setq looplength subloop1length) (setq objloop subloop1)))
   )
   objloop
)

(defun ex:offsetout ( obj offdis / subloop1 subloop2 subloop1type subloop2type subloop1length subloop2length objloop)
   (vla-offset obj (* offdis 1))
   (setq subloop1 (vlax-ename->vla-object (entlast)))
   (vla-offset obj (* offdis -1))
   (setq subloop2 (vlax-ename->vla-object (entlast)))
   (setq subloop1type (vlax-get-property subloop1 'entityname))
   (setq subloop2type (vlax-get-property subloop2 'entityname))
   (cond 
     ((= subloop1type "AcDbPolyline")
      (setq subloop1length (vlax-get-property subloop1 'length))
     )
     ((= subloop1type "AcDbCircle")
      (setq subloop1length (vlax-get-property subloop1 'Circumference))
     )
     ((= subloop1type "AcDbArc")
      (setq subloop1length (vlax-get-property subloop1 'Radius))
     )
   );end of cond
   (cond 
     ((= subloop2type "AcDbPolyline")
      (setq subloop2length (vlax-get-property subloop2 'length))
     )
     ((= subloop2type "AcDbCircle")
      (setq subloop2length (vlax-get-property subloop2 'Circumference))
     )
     ((= subloop2type "AcDbArc")
      (setq subloop2length (vlax-get-property subloop2 'Radius))
     )
   );end of cond
   (cond
      ((< subloop1length subloop2length) (progn (vla-delete subloop1) (setq looplength subloop2length) (setq objloop subloop2)))      
      ((> subloop1length subloop2length) (progn (vla-delete subloop2) (setq looplength subloop1length) (setq objloop subloop1)))
      ((= subloop1length subloop2length) (progn (vla-delete subloop2) (setq looplength subloop1length) (setq objloop subloop1)))
   )
   objloop
)


; close all by Middleton, Cliff 
; https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/early-christmas/m-p/777308/highlight/true#M2966

(defun C:@Q nil
  (cond
    ((= 6 (LM:popup "Close All with Save" "You want close all with save?"  36))
      (@CloseWithSave)
      (command "_close" "n")
    )
    (t (princ "\nCanceled"))
  )
  (princ)
)

(defun @CloseWithSave ( / cnt) 
  (setq cnt (@CloseAllButActive :vlax-True))
  (if (> cnt 0)
    (princ (strcat "\n[ " (itoa cnt) " ] " (if (> cnt 1) "s" "") "are saved and closed"))
    (princ "\nThere's no dwg for closing.")
  )
  (princ)
)

(defun @CloseAllButActive (TrueOrFalse / cnt)
  (setq cnt 0)
  (vlax-for Item (vla-get-Documents (vlax-get-acad-object))
    (if (= (vla-get-Active Item) :vlax-False)
      (progn
        (vla-close Item TrueOrFalse)
        (setq cnt (1+ cnt))
      )
    )
  )
  cnt
)

;; Popup  -  Lee Mac
;; A wrapper for the WSH popup method to display a message box prompting the user.
;; ttl - [str] Text to be displayed in the pop-up title bar
;; msg - [str] Text content of the message box
;; bit - [int] Bit-coded integer indicating icon & button appearance
;; Returns: [int] Integer indicating the button pressed to exit

(defun LM:popup ( ttl msg bit / wsh rtn )
    (if (setq wsh (vlax-create-object "wscript.shell"))
        (progn
            (setq rtn (vl-catch-all-apply 'vlax-invoke-method (list wsh 'popup msg 0 ttl bit)))
            (vlax-release-object wsh)
            (if (not (vl-catch-all-error-p rtn)) rtn)
        )
    )
)


(c:CNC)

 

now you can,

- If you don't enter a value (space bar or esc), doesn't run it. 

- It will work as long as you don't enter too large a value inward. (For example, if you have a circle with a diameter of 10, offset 11 inward.)

 

if you don't want it to run on every open, Remove the last (c:CNC) from notepad

 

But it will ask you every time the drawing is opened. 

This is so the first version to write directly into the code might be better. you can edit this by 

; Edit 10 in (setq offsetvalue 10) to adjust the offset length

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

14 minutes ago, exceed said:
; CNC - 2022.05.31 exceed
; https://www.cadtutor.net/forum/topic/75276-an-offset-marco-for-cnc-plasma-cutting-process/
;
; Works on closed polylines, circles.
; Objects with the largest area are offset outward, others are offset inward.
;
; Command List
; CNC - do offset
; @Q - Save and close all opened drawings. Dialogs do not appear individually when closing each drawing. Appears only once for confirmation.
; 
; The color is designated as number 3 (green). The layer does not change.
;
; Edit 10 in (setq offsetvalue 10) to adjust the offset length
;
; When you add this Lisp to your starter set, it will work automatically every time you open a drawing.
; Open multiple drawings and save and close them all with the @Q command.
; If you want to manually, add ; in front of (c:CNC) to make ;(c:CNC), 
; it will work when manually entering CNC
;
; Note
; If you reopen a drawing that has already been executed and saved, it will be created again. 
; In this part, it seems to be necessary to add a statement that does not execute if there is a green object in the drawing.
; Your green looks different than mine, so I didn't add this code.


(vl-load-com)
(defun c:CNC ( / offsetvalue ss ssl index arealist obj objarea objlist outerloopobj outeroffset otherloop otherlooplen index2 otherloopobj inneroffset )

  ;(setq offsetvalue 10)
  (setq offsetvalue (getreal "\n Input offset value : "))
 
  (setq ss (ssget "X" '((0 . "LWPOLYLINE,CIRCLE"))))
  (setq ssl (sslength ss))
  (setq index 0)
  (setq arealist '())
  (repeat ssl
    (setq obj (vlax-ename->vla-object (ssname ss index)))
    (setq objarea (vla-get-area obj))
    (setq objlist (list obj objarea))
    (setq arealist (cons objlist arealist))
    (setq index (+ index 1))
  )
  (setq arealist (vl-sort arealist (function (lambda (x1 x2) (> (cadr x1) (cadr x2)) ) )))
  
  (setq outerloopobj (car (car arealist)))
  (setq outeroffset (ex:offsetout outerloopobj offsetvalue))
  (vlax-put-property outeroffset 'color 3)

  (setq otherloop (cdr arealist))
  (setq otherlooplen (length otherloop))
  (setq index2 0)

  (repeat otherlooplen
    (setq otherloopobj (car (nth index2 otherloop)))
    (setq inneroffset (ex:offsetin otherloopobj offsetvalue))
    (vlax-put-property inneroffset 'color 3)
    (setq index2 (+ index2 1))
  )
  

  (princ)
)
 


(defun ex:offsetin ( obj offdis / subloop1 subloop2 subloop1type subloop2type subloop1length subloop2length objloop)
   (vla-offset obj (* offdis 1))
   (setq subloop1 (vlax-ename->vla-object (entlast)))
   (vla-offset obj (* offdis -1))
   (setq subloop2 (vlax-ename->vla-object (entlast)))
   (setq subloop1type (vlax-get-property subloop1 'entityname))
   (setq subloop2type (vlax-get-property subloop2 'entityname))
   (cond 
     ((= subloop1type "AcDbPolyline")
      (setq subloop1length (vlax-get-property subloop1 'length))
     )
     ((= subloop1type "AcDbCircle")
      (setq subloop1length (vlax-get-property subloop1 'Circumference))
     )
     ((= subloop1type "AcDbArc")
      (setq subloop1length (vlax-get-property subloop1 'Radius))
     )
   );end of cond
   (cond 
     ((= subloop2type "AcDbPolyline")
      (setq subloop2length (vlax-get-property subloop2 'length))
     )
     ((= subloop2type "AcDbCircle")
      (setq subloop2length (vlax-get-property subloop2 'Circumference))
     )
     ((= subloop2type "AcDbArc")
      (setq subloop2length (vlax-get-property subloop2 'Radius))
     )
   );end of cond
   (cond
      ((> subloop1length subloop2length) (progn (vla-delete subloop1) (setq looplength subloop2length) (setq objloop subloop2)))      
      ((< subloop1length subloop2length) (progn (vla-delete subloop2) (setq looplength subloop1length) (setq objloop subloop1)))
      ((= subloop1length subloop2length) (progn (vla-delete subloop2) (setq looplength subloop1length) (setq objloop subloop1)))
   )
   objloop
)

(defun ex:offsetout ( obj offdis / subloop1 subloop2 subloop1type subloop2type subloop1length subloop2length objloop)
   (vla-offset obj (* offdis 1))
   (setq subloop1 (vlax-ename->vla-object (entlast)))
   (vla-offset obj (* offdis -1))
   (setq subloop2 (vlax-ename->vla-object (entlast)))
   (setq subloop1type (vlax-get-property subloop1 'entityname))
   (setq subloop2type (vlax-get-property subloop2 'entityname))
   (cond 
     ((= subloop1type "AcDbPolyline")
      (setq subloop1length (vlax-get-property subloop1 'length))
     )
     ((= subloop1type "AcDbCircle")
      (setq subloop1length (vlax-get-property subloop1 'Circumference))
     )
     ((= subloop1type "AcDbArc")
      (setq subloop1length (vlax-get-property subloop1 'Radius))
     )
   );end of cond
   (cond 
     ((= subloop2type "AcDbPolyline")
      (setq subloop2length (vlax-get-property subloop2 'length))
     )
     ((= subloop2type "AcDbCircle")
      (setq subloop2length (vlax-get-property subloop2 'Circumference))
     )
     ((= subloop2type "AcDbArc")
      (setq subloop2length (vlax-get-property subloop2 'Radius))
     )
   );end of cond
   (cond
      ((< subloop1length subloop2length) (progn (vla-delete subloop1) (setq looplength subloop2length) (setq objloop subloop2)))      
      ((> subloop1length subloop2length) (progn (vla-delete subloop2) (setq looplength subloop1length) (setq objloop subloop1)))
      ((= subloop1length subloop2length) (progn (vla-delete subloop2) (setq looplength subloop1length) (setq objloop subloop1)))
   )
   objloop
)


; close all by Middleton, Cliff 
; https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/early-christmas/m-p/777308/highlight/true#M2966

(defun C:@Q nil
  (cond
    ((= 6 (LM:popup "Close All with Save" "You want close all with save?"  36))
      (@CloseWithSave)
      (command "_close" "n")
    )
    (t (princ "\nCanceled"))
  )
  (princ)
)

(defun @CloseWithSave ( / cnt) 
  (setq cnt (@CloseAllButActive :vlax-True))
  (if (> cnt 0)
    (princ (strcat "\n[ " (itoa cnt) " ] " (if (> cnt 1) "s" "") "are saved and closed"))
    (princ "\nThere's no dwg for closing.")
  )
  (princ)
)

(defun @CloseAllButActive (TrueOrFalse / cnt)
  (setq cnt 0)
  (vlax-for Item (vla-get-Documents (vlax-get-acad-object))
    (if (= (vla-get-Active Item) :vlax-False)
      (progn
        (vla-close Item TrueOrFalse)
        (setq cnt (1+ cnt))
      )
    )
  )
  cnt
)

;; Popup  -  Lee Mac
;; A wrapper for the WSH popup method to display a message box prompting the user.
;; ttl - [str] Text to be displayed in the pop-up title bar
;; msg - [str] Text content of the message box
;; bit - [int] Bit-coded integer indicating icon & button appearance
;; Returns: [int] Integer indicating the button pressed to exit

(defun LM:popup ( ttl msg bit / wsh rtn )
    (if (setq wsh (vlax-create-object "wscript.shell"))
        (progn
            (setq rtn (vl-catch-all-apply 'vlax-invoke-method (list wsh 'popup msg 0 ttl bit)))
            (vlax-release-object wsh)
            (if (not (vl-catch-all-error-p rtn)) rtn)
        )
    )
)


(c:CNC)

 

It will work as long as you don't enter too large a value inward. (For example, if you have a circle with a diameter of 10, offset 11 inward.)

 

Fantastic!!! How can I add it to my starter set?

Edited by abghrnjd
Link to comment
Share on other sites

2 minutes ago, abghrnjd said:

Fantastic!!! How can I add it to my starter set?

 

http://www.lee-mac.com/runlisp.html

 

Command : APPLOAD

- upside LOAD button is just one time instant load.

- bottom rightside Start Up Suite - Contents... is starter set. add in this

first time you add in start up suite. not loaded, upside load or restart CAD

Link to comment
Share on other sites

1 minute ago, exceed said:

 

http://www.lee-mac.com/runlisp.html

 

Command : APPLOAD

- upside LOAD button is just one time instant load.

- bottom rightside Start Up Suite - Contents... is starter set. add in this

first time you add in start up suite. not loaded, upside load or restart CAD

Can we add => select all ==>join ? this way we can be sure if some objects are not joined. This makes it perfect!

Link to comment
Share on other sites

; CNC - 2022.05.31 exceed
; https://www.cadtutor.net/forum/topic/75276-an-offset-marco-for-cnc-plasma-cutting-process/
;
; Works on closed polylines, circles.
; Objects with the largest area are offset outward, others are offset inward.
;
; Command List
; CNC - do offset
; @Q - Save and close all opened drawings. Dialogs do not appear individually when closing each drawing. Appears only once for confirmation.
; 
; The color is designated as number 3 (green). The layer does not change.
;
; When you add this Lisp to your starter set, it will work automatically every time you open a drawing.
; Open multiple drawings and save and close them all with the @Q command.
; If you want to manually, add ; in front of (c:CNC) to make ;(c:CNC), 
; it will work when manually entering CNC
;
; Note
; If you reopen a drawing that has already been executed and saved, it will be created again. 
; In this part, it seems to be necessary to add a statement that does not execute if there is a green object in the drawing.
; Your green looks different than mine, so I didn't add this code.


(vl-load-com)
(defun c:CNC ( / offsetvalue ss ssl index arealist obj objarea objlist outerloopobj outeroffset otherloop otherlooplen index2 otherloopobj inneroffset )

  ;(setq offsetvalue 10)
  (setq offsetvalue (getreal "\n Input offset value : "))
  (if (= offsetvalue nil) (progn (princ "\n you cancel CNC offset command") (exit)) )
 
  (setvar 'cmdecho 0)
  (command "_Join" "all" "")
  (setvar 'cmdecho 1)

  (setq ss (ssget "X" '((0 . "LWPOLYLINE,CIRCLE"))))
  (setq ssl (sslength ss))
  (setq index 0)
  (setq arealist '())
  (repeat ssl
    (setq obj (vlax-ename->vla-object (ssname ss index)))
    (setq objarea (vla-get-area obj))
    (setq objlist (list obj objarea))
    (setq arealist (cons objlist arealist))
    (setq index (+ index 1))
  )
  (setq arealist (vl-sort arealist (function (lambda (x1 x2) (> (cadr x1) (cadr x2)) ) )))
  
  (setq outerloopobj (car (car arealist)))
  (setq outeroffset (ex:offsetout outerloopobj offsetvalue))
  (vlax-put-property outeroffset 'color 3)

  (setq otherloop (cdr arealist))
  (setq otherlooplen (length otherloop))
  (setq index2 0)

  (repeat otherlooplen
    (setq otherloopobj (car (nth index2 otherloop)))
    (setq inneroffset (ex:offsetin otherloopobj offsetvalue))
    (vlax-put-property inneroffset 'color 3)
    (setq index2 (+ index2 1))
  )
  

  (princ)
)
 


(defun ex:offsetin ( obj offdis / subloop1 subloop2 subloop1type subloop2type subloop1length subloop2length objloop)
   (vla-offset obj (* offdis 1))
   (setq subloop1 (vlax-ename->vla-object (entlast)))
   (vla-offset obj (* offdis -1))
   (setq subloop2 (vlax-ename->vla-object (entlast)))
   (setq subloop1type (vlax-get-property subloop1 'entityname))
   (setq subloop2type (vlax-get-property subloop2 'entityname))
   (cond 
     ((= subloop1type "AcDbPolyline")
      (setq subloop1length (vlax-get-property subloop1 'length))
     )
     ((= subloop1type "AcDbCircle")
      (setq subloop1length (vlax-get-property subloop1 'Circumference))
     )
     ((= subloop1type "AcDbArc")
      (setq subloop1length (vlax-get-property subloop1 'Radius))
     )
   );end of cond
   (cond 
     ((= subloop2type "AcDbPolyline")
      (setq subloop2length (vlax-get-property subloop2 'length))
     )
     ((= subloop2type "AcDbCircle")
      (setq subloop2length (vlax-get-property subloop2 'Circumference))
     )
     ((= subloop2type "AcDbArc")
      (setq subloop2length (vlax-get-property subloop2 'Radius))
     )
   );end of cond
   (cond
      ((> subloop1length subloop2length) (progn (vla-delete subloop1) (setq looplength subloop2length) (setq objloop subloop2)))      
      ((< subloop1length subloop2length) (progn (vla-delete subloop2) (setq looplength subloop1length) (setq objloop subloop1)))
      ((= subloop1length subloop2length) (progn (vla-delete subloop2) (setq looplength subloop1length) (setq objloop subloop1)))
   )
   objloop
)

(defun ex:offsetout ( obj offdis / subloop1 subloop2 subloop1type subloop2type subloop1length subloop2length objloop)
   (vla-offset obj (* offdis 1))
   (setq subloop1 (vlax-ename->vla-object (entlast)))
   (vla-offset obj (* offdis -1))
   (setq subloop2 (vlax-ename->vla-object (entlast)))
   (setq subloop1type (vlax-get-property subloop1 'entityname))
   (setq subloop2type (vlax-get-property subloop2 'entityname))
   (cond 
     ((= subloop1type "AcDbPolyline")
      (setq subloop1length (vlax-get-property subloop1 'length))
     )
     ((= subloop1type "AcDbCircle")
      (setq subloop1length (vlax-get-property subloop1 'Circumference))
     )
     ((= subloop1type "AcDbArc")
      (setq subloop1length (vlax-get-property subloop1 'Radius))
     )
   );end of cond
   (cond 
     ((= subloop2type "AcDbPolyline")
      (setq subloop2length (vlax-get-property subloop2 'length))
     )
     ((= subloop2type "AcDbCircle")
      (setq subloop2length (vlax-get-property subloop2 'Circumference))
     )
     ((= subloop2type "AcDbArc")
      (setq subloop2length (vlax-get-property subloop2 'Radius))
     )
   );end of cond
   (cond
      ((< subloop1length subloop2length) (progn (vla-delete subloop1) (setq looplength subloop2length) (setq objloop subloop2)))      
      ((> subloop1length subloop2length) (progn (vla-delete subloop2) (setq looplength subloop1length) (setq objloop subloop1)))
      ((= subloop1length subloop2length) (progn (vla-delete subloop2) (setq looplength subloop1length) (setq objloop subloop1)))
   )
   objloop
)


; close all by Middleton, Cliff 
; https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/early-christmas/m-p/777308/highlight/true#M2966

(defun C:@Q nil
  (cond
    ((= 6 (LM:popup "Close All with Save" "You want close all with save?"  36))
      (@CloseWithSave)
      (command "_close" "n")
    )
    (t (princ "\nCanceled"))
  )
  (princ)
)

(defun @CloseWithSave ( / cnt) 
  (setq cnt (@CloseAllButActive :vlax-True))
  (if (> cnt 0)
    (princ (strcat "\n[ " (itoa cnt) " ] " (if (> cnt 1) "s" "") "are saved and closed"))
    (princ "\nThere's no dwg for closing.")
  )
  (princ)
)

(defun @CloseAllButActive (TrueOrFalse / cnt)
  (setq cnt 0)
  (vlax-for Item (vla-get-Documents (vlax-get-acad-object))
    (if (= (vla-get-Active Item) :vlax-False)
      (progn
        (vla-close Item TrueOrFalse)
        (setq cnt (1+ cnt))
      )
    )
  )
  cnt
)

;; Popup  -  Lee Mac
;; A wrapper for the WSH popup method to display a message box prompting the user.
;; ttl - [str] Text to be displayed in the pop-up title bar
;; msg - [str] Text content of the message box
;; bit - [int] Bit-coded integer indicating icon & button appearance
;; Returns: [int] Integer indicating the button pressed to exit

(defun LM:popup ( ttl msg bit / wsh rtn )
    (if (setq wsh (vlax-create-object "wscript.shell"))
        (progn
            (setq rtn (vl-catch-all-apply 'vlax-invoke-method (list wsh 'popup msg 0 ttl bit)))
            (vlax-release-object wsh)
            (if (not (vl-catch-all-error-p rtn)) rtn)
        )
    )
)


(c:CNC)

 

 

if you want use basic command in lisp

  (setvar 'cmdecho 0)
  (command "_Join" "all" "")
  (setvar 'cmdecho 1)

like this way.

 

(setvar 'cmdecho 0) is mute. 

(setvar 'cmdecho 1) is unmute.

 

  • Like 1
Link to comment
Share on other sites

Exceed has a good solution for you.

 

Going back to your original post, I think that part offset inside / outside the wrong way around might be to do with how your drew the original polyline, whether you drew it in a clockwise or anticlockwise (counter clockwise) direction - if that makes sense, but you could test that to see yourself.

 

I had another look at this today, and here is another option for you. Command is CNC. I separated the  CNC command from the rest, passing the value of offset to the next LISP, (thinking to your next step which might be to run this as a part of a script, all the drawings at once and this will give you the ability to set the offset according to each drawing).

 

I haven't added anything in here to open, save or close a drawing - thinking that can be done in a script routine, but see he end of Exceed and the '@' defuns for that too

 

 

(defun PolyLineArea ( MyPolyLineEntName / MyArea)
  (setq MyPolyLine (vlax-ename->vla-object MyPolyLineEntName))
  (setq MyArea (vla-get-Area MyPolyLine) )
  MyArea
)
;;;;;;;;;;;;;;;;;;;;;;
;;https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/find-the-largest-number-in-a-list-of-numbers/td-p/816742
(defun maxinlist (x / next highest)
  (setq next 0)
  (setq highest (nth 0 x)) ; Assumes that the first item in the list is the highest. Then iterates through every number in the list
  (while (< next (1- (length x)))
    (setq highest (max highest (nth (1+ next) x)))
    (setq next (1+ next))
  ) ;end while
  highest
)

https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/lisp-offset-many-closed-objects-toward-inside-at-once/td-p/8304010
;;  Function to determine if a polyline is CW or CCW
  ;;  Returns 1 for CCW, or -1 for CW, or nil if not a polyline or only two points
(defun @CCW? (Pline / Param Sum End P1 P2 P3)
  (cond
    ((= (type Pline) 'VLA-OBJECT))
    ((= (type Pline) 'ENAME)(setq Pline (vlax-ename->vla-object Pline)))
    (1 (setq Pline nil))
  )
  (and
    Pline
    (setq Param 0.5
          Sum 0.0
          End (vlax-curve-getendparam Pline)
          P1 (vlax-curve-getstartpoint Pline)
          PType (vlax-get Pline 'ObjectName)
    ) ;end setq
    (or
      (while (not (setq P2 (vlax-curve-getpointatparam Pline Param)))
        (setq Param (+ Param 0.5))
      ) ;end while
      1
    ) ;end or
    (while (and (> End 2)(< Param End))
      (setq Param (+ Param 0.5))
      (while (not (setq P3 (vlax-curve-getpointatparam Pline Param)))
        (setq Param (+ Param 0.5))
      ) ;end while
      (setq Sum (+ Sum (@delta (angle P1 P2)(angle P2 P3)))
            P1 P2 P2 P3
      ) ;end setq
    ) ;end while
  ) ;end and
  (cond
    ((not Sum) nil)
    ((zerop Sum) nil)
    ((> Sum 0) 1)  ;; meaning it's CCW
    ((< Sum 0) -1) ;; meaning it's CW
  )
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun @delta (a1 a2)
  (cond
     ((> a1 (+ a2 pi))
       (- (+ a2 pi pi) a1)
     )
     ((> a2 (+ a1 pi))
       (- a2 (+ a1 pi pi))
     )
     (1 (- a2 a1))
  )
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun c:CNC ( / offset)
  (linearea 2)
  (princ)
)

;;;;;;;;;;;;;;;;;;;;;
(defun LineArea ( offsetdist / MyPolyLineEntName Acount AreaList)
  (vl-load-com)            ;;Load VL
  (setq AreaList (list))   ;;Blank List
  (setq ss (ssget "_A"))   ;;select set, all visible objects, change A to X for all objects

  (command "_pedit" "m" ss "" "c" "") ;Close polylines

  (setq Acount 0)          ;; Set a counter to 0
  (while (< acount (sslength ss)) ;;Loop through selection Set, ss
    (setq MyPolyLineEntName (ssname ss Acount))  ;;nth entity in ss name
    (setq AreaList (append AreaList (list (PolyLineArea MyPolyLineEntName)) )) ;;get object area from PolyLineArea function above
    (setq Acount (+ Acount 1))  ;;increase counter
  )
  (setq largestentpos (- (vl-position (maxinlist AreaList) AreaList) 0 ))
  (setq acount 0)
  (foreach ent (vl-remove-if 'listp (mapcar 'cadr (ssnamex ss)))
    (setq Distance (* -1 (@CCW? ent) offsetdist))
    (if (= acount largestentpos) (setq Distance (* (@CCW? ent) offsetdist)) )
    (setq acount (+ acount 1))
    (setq obj (vlax-ename->vla-object ent))
    (vla-offset obj Distance)
    (command "._CHANGE" (entlast) "" "Properties" "Color" "1" "")
  )

)

 

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