TheSwamp

Code Red => AutoLISP (Vanilla / Visual) => Topic started by: Dave M on June 14, 2012, 10:25:45 PM

Title: Thoughts on a better ERASE command
Post by: Dave M on June 14, 2012, 10:25:45 PM
Allow me to throw down the gauntlet, and see if any skillful swampers have a routine that would work like I'm about to describe. 

A polyline is created, and when you invoke the erase command (or any command that allows crossing polygon or window polygon), you have the ability to use the polyline you just created as either a window polygon, or a crossing polygon for selection.

Your reward?  My undying appreciation  ;-)
Title: Re: Thoughts on a better ERASE command
Post by: ronjonp on June 14, 2012, 10:48:42 PM
Grab the polyline coordinates then use ssget and wp?
Title: Re: Thoughts on a better ERASE command
Post by: danallen on June 14, 2012, 11:08:22 PM
Here is code for selecting:

Code: [Select]
;;;From: Joe Burke (joburke@hawaii.rr.com)
;;;Subject: Re: Polygon Selection Boundary
;;;Newsgroups: autodesk.autocad.customization
;;;Date: 2002-04-17 04:38:49 PST
;;;
;;;returns list of points in a pline
(defun-q C:SelectByPline (/ pline ptlist prev count)
 (princ "\nCrossing or Window selection?<C,W>")
 (setq typ (strcase (getstring)))
 (cond
  ((= typ "W")
   (prompt "\nPick polyline to define Window selection set:")
  )
  ((= typ "C")
   (prompt "\nPick polyline to define Crossing selection set:")
  )
 )
 (setq pline (car (entsel))
       ptlist (massoc 10 (entget pline))
 )
 (cond
  ((= typ "W")
   (setq prev (ssget "WP" ptlist))
   (setq count (sslength prev))
   (princ "\nThe Selection Set consists of ")
   (princ count)
   (princ " entities inside the Window Polygon.")
  )
  ((= typ "C")
   (setq prev (ssget "CP" ptlist))
   (ssdel pline prev) ;remove pline from crossing ss
   (setq count (sslength prev))
   (princ "\nThe Selection Set consists of ")
   (princ count)
   (princ " entities inside the Crossing Polygon.")
  )
 )
 (sssetfirst nil prev) ;select
 (princ)
);end defun

;;;=========================================================================
;;; massoc
;;;
;;; get multiple items from an association list (instead of just 1st one)
;;;
;;; From: Tony Tanzillo (tony.tanzillo@worldnet.att.net)
;;; Subject: Re: extracting multiple assoc from list
;;; Newsgroups: autodesk.autocad.customization
;;; Date: 1999/09/29
;;;=========================================================================
(defun-q massoc (key alist / x nlist)
  (foreach x alist
    (if (eq key (car x))
      (setq nlist (cons (cdr x) nlist))
    )
  )
  (reverse nlist)
) ;end defun

Title: Re: Thoughts on a better ERASE command
Post by: irneb on June 15, 2012, 04:13:33 AM
Slightly more concise:
Code - Auto/Visual Lisp: [Select]
  1.  
  2. (defun massoc (key lst /)
  3.   (mapcar 'cdr (vl-remove-if-not '(lambda (item) (equal key (car item))) lst)))
  4.  
  5. (defun c:EraseByPoly  (/ pEname pDxf ss)
  6.   (or *W/C* (setq *W/C* "CP"))
  7.   (while (progn (initget "CP WP F Undo")
  8.                 (setq pEname (entsel (strcat "\nSelect polyline border [WP/CP/F/Undo] <" *W/C* ">: "))))
  9.     (cond ((eq (type pEname) 'Str)
  10.            (if (eq pEname "Undo")
  11.              (command "_.Undo" "1")
  12.              (setq *W/C* pEname)))
  13.           ((and (eq (type pEname) 'List)
  14.                 (eq (type (setq pEname (car pEname))) 'EName)
  15.                 (eq (cdr (assoc 0 (setq pDxf (entget pEname)))) "LWPOLYLINE"))
  16.            (if (setq ss (ssget *W/C* (massoc 10 pDxf)))
  17.              (command "_.ERASE" (ssdel pEname ss) "")
  18.              (prompt "\nThere's no objects to erase.")))
  19.           (t (prompt "\nThat's not a polyline, please try again."))))
  20.   (princ))
Though for some reason I'm finding nothing selected through WP. Works fine for CP/F selection though.
Title: Re: Thoughts on a better ERASE command
Post by: Lee Mac on June 15, 2012, 08:05:44 AM
My version:

Code - Auto/Visual Lisp: [Select]
  1. (defun c:perase ( / e s )
  2.     (while
  3.         (progn (setvar 'errno 0) (setq e (car (entsel)))
  4.             (cond
  5.                 (   (= 7 (getvar 'errno))
  6.                     (princ "\nMissed, try again.")
  7.                 )
  8.                 (   (eq 'ename (type e))
  9.                     (if (not (eq "LWPOLYLINE" (cdr (assoc 0 (entget e)))))
  10.                         (princ "\nSelected Object is not an LWPolyline.")
  11.                     )
  12.                 )
  13.             )
  14.         )
  15.     )
  16.     (if
  17.         (and e
  18.             (progn
  19.                 (initget "Window Crossing")
  20.                 (setq s
  21.                     (ssget
  22.                         (cond
  23.                             (   (eq "Window" (getkword "\nSpecify Selection Type [Window/Crossing] <Crossing>: "))
  24.                                 "_WP"
  25.                             )
  26.                             (   "_CP"   )
  27.                         )
  28.                         (apply 'append (mapcar '(lambda ( x ) (if (= 10 (car x)) (list (cdr x)))) (entget e)))
  29.                     )
  30.                 )
  31.                 (if s (ssdel e s))
  32.                 (< 0 (sslength s))
  33.             )
  34.         )
  35.         (command "_.erase" s "")
  36.     )
  37.     (princ)
  38. )

@Irné, hint: if pEname is not a member of ss, ssdel returns nil :wink:
Title: Re: Thoughts on a better ERASE command
Post by: irneb on June 15, 2012, 08:50:59 AM
@Irné, hint: if pEname is not a member of ss, ssdel returns nil ;)
Ah!  :-[ ... thanks for turning on the light! And for reminding me I don't need the vl-remove-* functions to get rid of nils: append does the same thing.

Now this works!
Code - Auto/Visual Lisp: [Select]
  1. (defun massoc  (key lst /)
  2.   (apply 'append (mapcar '(lambda (item) (if (equal key (car item)) (list (cdr item)))) lst)))
  3.  
  4. (defun c:EraseByPoly  (/ pEname pDxf ss)
  5.   (or *W/C* (setq *W/C* "CP"))
  6.   (while (progn (initget "CP WP F Undo")
  7.                 (setq pEname (entsel (strcat "\nSelect polyline to [WP/CP/F/Undo] <" *W/C* ">: "))))
  8.     (cond ((eq (type pEname) 'Str)
  9.            (if (eq pEname "Undo")
  10.              (command "_.Undo" "1")
  11.              (setq *W/C* pEname)))
  12.           ((and (eq (type pEname) 'List)
  13.                 (eq (type (setq pEname (car pEname))) 'EName)
  14.                 (eq (cdr (assoc 0 (setq pDxf (entget pEname)))) "LWPOLYLINE"))
  15.            (if (and (setq ss (ssget *W/C* (massoc 10 pDxf)))
  16.                     (progn (ssdel pEname ss)
  17.                       (> (sslength ss) 0)))
  18.              (command "_.ERASE" ss "")
  19.              (prompt "\nThere's no objects to erase.")))
  20.           (t (prompt "\nThat's not a polyline, please try again."))))
  21.   (princ))
Title: Re: Thoughts on a better ERASE command
Post by: Dave M on June 18, 2012, 11:43:58 AM
Lee,

Thanks, this works perfectly!

Dave
Title: Re: Thoughts on a better ERASE command
Post by: Lee Mac on June 18, 2012, 11:51:02 AM
You're very welcome Dave, I hope the code is comprehensible  :-)
Title: Re: Thoughts on a better ERASE command
Post by: huiz on June 18, 2012, 03:24:13 PM
I've seen a CookieCutter lisp somewhere which also erases everything inside or outside a polyline, and cut every line and block. Very usefull kind-of-an-erase tool. Actually, erase is an option but not required.

Another maybe great idea for a better erase command is to put elements in a recycle bin or something like that. If you open that drawing recycle bin, you see a drawing with everything you've erased and the possibility to restore the element.
Title: Re: Thoughts on a better ERASE command
Post by: CAB on June 18, 2012, 03:48:14 PM
http://www.theswamp.org/index.php?topic=24646.0  Trim with objects [CookieCutter] by Joe Burke
Title: Re: Thoughts on a better ERASE command
Post by: dgorsman on June 18, 2012, 04:50:50 PM
Another maybe great idea for a better erase command is to put elements in a recycle bin or something like that. If you open that drawing recycle bin, you see a drawing with everything you've erased and the possibility to restore the element.

Like something that wblocks out the chunks (or even individual entities) as they are erased?
Title: Re: Thoughts on a better ERASE command
Post by: huiz on June 19, 2012, 03:45:48 AM
Another maybe great idea for a better erase command is to put elements in a recycle bin or something like that. If you open that drawing recycle bin, you see a drawing with everything you've erased and the possibility to restore the element.

Like something that wblocks out the chunks (or even individual entities) as they are erased?

Conceptual thinking, it would be very cool to have a recycle bin inside the drawing. Colleagues are able to undo erase actions, but customers shouldn't see the deleted items. So I think keeping the erased stuff inside the drawing is not a very good idea.

Maybe WBLOCK is an option. But your disk will be filled with garbage and it is hard to chain the erased elements to the original drawing.

I just think of another method, still conceptual (and I'm not sure if I will create this, but maybe I once will do ;-) ) what if there is an application which uses a Layout as a recycle bin. It redefines the ERASE command or using a reactor so the erased elements are moved to the Layout. The elements can keep the layer, color and linetype information. So all the elements are easily accessible to be restored, and it is also very easy to remove the Recycle Bin layout before sending the drawing to the customer.
Title: Re: Thoughts on a better ERASE command
Post by: irneb on June 19, 2012, 04:22:32 AM
You could always "send" the erased objects to a non-referenced block definition inside the DWG. That way the "trashbin" is not displayed in the DWG but easily restored by simply inserting that block @ 0,0,0 and exploding it. You could then wblock that block if you so want, or to clear it do a purge.
Title: Re: Thoughts on a better ERASE command
Post by: huiz on June 19, 2012, 04:26:21 AM
That is also a neat solution.
Title: Re: Thoughts on a better ERASE command
Post by: dgorsman on June 19, 2012, 10:18:30 AM
You could always "send" the erased objects to a non-referenced block definition inside the DWG. That way the "trashbin" is not displayed in the DWG but easily restored by simply inserting that block @ 0,0,0 and exploding it. You could then wblock that block if you so want, or to clear it do a purge.

Slick.  Or something along the lines of the autosave cleaner which (under normal circumstances) cleans up after itself if the drawing is closed normally.
Title: Re: Thoughts on a better ERASE command
Post by: irneb on June 19, 2012, 10:53:03 AM
Or work similar to a normal Trash-Bin. I.e. have a setting to specify a maximum amount of entities to keep (could be as a percentage of the entire DWG). That way only keep the latest entities and delete the older ones - it should be sorted by time of deletion in any case (if you simply keep adding them to the block def).
Title: Re: Thoughts on a better ERASE command
Post by: danallen on June 19, 2012, 12:49:08 PM
Or try making them invisible:
http://www.theswamp.org/index.php?topic=5007.msg60596#msg60596 (http://www.theswamp.org/index.php?topic=5007.msg60596#msg60596)
Title: Re: Thoughts on a better ERASE command
Post by: Lee Mac on June 19, 2012, 02:18:57 PM
Another maybe great idea for a better erase command is to put elements in a recycle bin or something like that. If you open that drawing recycle bin, you see a drawing with everything you've erased and the possibility to restore the element.

You could always "send" the erased objects to a non-referenced block definition inside the DWG.

That's a great idea Irné!  8-)

Attached is my first draft of a possible program which implements this proposed method to give us all something to work with.

The 'recycle' command will move a selection of objects to the 'drawing recycle bin', and the 'restore' command will restore objects that were previously recycled. The recycle bin can be 'emptied' by simply purging the block collection.

Feel free to add comments and suggestions  :-)
Title: Re: Thoughts on a better ERASE command
Post by: huiz on June 19, 2012, 04:43:34 PM
It is really great Lee Mac!  8) Great to see ideas come to life!

Maybe, if it is not asked too much, a preview of the selected restore item? In big red lines? :-)
Title: Re: Thoughts on a better ERASE command
Post by: Lee Mac on June 19, 2012, 04:51:09 PM
It is really great Lee Mac!  8) Great to see ideas come to life!

Thank you huiz  :-)

Maybe, if it is not asked too much, a preview of the selected restore item? In big red lines? :-)

This would certainly be possible by inserting the 'recycled' block into the drawing and perhaps drawing a box around it using grvecs / grdraw to make it easily distinguishable from surrounding objects, but since standard DCL only permits modal dialogs, the dialog would need to be suppressed and then reloaded if the user cancels the preview (similar to the preview option of the Array command).
Title: Re: Thoughts on a better ERASE command
Post by: ScottMC on August 03, 2020, 11:56:26 PM
Actually better than cut with basepoint as it allows both, multiple separate erased and saved with file! Anyway the restore could ask/allow an alternate or original point/location to restore to?
Title: Re: Thoughts on a better ERASE command
Post by: Lee Mac on August 05, 2020, 02:07:41 PM
Actually better than cut with basepoint as it allows both, multiple separate erased and saved with file! Anyway the restore could ask/allow an alternate or original point/location to restore to?

Yes - change this:
Code - Auto/Visual Lisp: [Select]
  1.                 (foreach bn (LM:ListBox "Select Items to Restore" (vl-sort lst '>) t)
  2.                     (setq bo (vlax-invoke as 'insertblock '(0.0 0.0 0.0) bn 1.0 1.0 1.0 0.0))
  3.                     (vla-explode bo)
  4.                     (vla-delete  bo)
  5.                     (vl-catch-all-apply 'vla-delete (list (vla-item bc bn)))
  6.                 )

To:
Code - Auto/Visual Lisp: [Select]
  1.                 (foreach bn (LM:ListBox "Select Items to Restore" (vl-sort lst '>) t)
  2.                     (if (setq ip (getpoint "\nSpecify insertion point: "))
  3.                         (progn
  4.                             (setq bo (vlax-invoke as 'insertblock (trans ip 1 0) bn 1.0 1.0 1.0 0.0))
  5.                             (vla-explode bo)
  6.                             (vla-delete  bo)
  7.                             (vl-catch-all-apply 'vla-delete (list (vla-item bc bn)))
  8.                         )
  9.                     )
  10.                 )

Note that the base point is always relative to the drawing origin however.
Title: Re: Thoughts on a better ERASE command
Post by: ScottMC on May 03, 2021, 05:49:01 PM
Lee.. anyway you could help me rework this to acquire the insert cut point upon picking object(s) instead of the (0.0 0.0 0.0) as in your "DrawingRecycleBin" Please?  :idea:

                    (vla-get-blocks ad)
                   'add
                    '(0.0 0.0 0.0) << would help! Wish to understand how to get
                                               a coord (getpoint..) to work.
      Thanks so much!
Title: Re: Thoughts on a better ERASE command
Post by: cmwade77 on May 11, 2021, 06:50:55 PM
Wow, I get engrossed in doing what I need to fix up and this is what I come back to find! There is some incredible stuff here.