;;; ---------------------------------------------------------------------
;;;  CLRIN-bgol.lsp
;;;  Command:  CIN
;;;
;;;  PURPOSE
;;;  Erases every entity located INSIDE a selected closed polyline
;;;  boundary. The inverse of KEEPIN-bgol.lsp (KIN). Useful for clearing
;;;  survey points, text, or clutter that falls inside a building
;;;  footprint or other region before further processing.
;;;
;;;  USAGE
;;;    1. Load this file (APPLOAD or drag-drop onto the drawing window).
;;;    2. Type   CIN   at the command line and press Enter.
;;;    3. Select the closed polyline that defines the boundary to clear.
;;;    4. Every other entity whose reference point falls inside that
;;;       boundary is erased. The boundary polyline itself is untouched.
;;;
;;;  NOTES
;;;    - Uses a standard ray-casting point-in-polygon test against the
;;;      boundary polyline's vertices.
;;;    - This is an original, independently written implementation.
;;;      It is INSPIRED by the general idea of boundary-based selective
;;;      erase utilities common in CAD drafting workflows, but the code,
;;;      command name and file name here are new and are NOT copied
;;;      from, nor identical to, any specific third-party product.
;;;
;;;  ---------------------------------------------------------------------
;;;  Developed and shared for the CAD community by:  BGol Community
;;;  Community website:                              https://bgol.in/
;;;  License:  Open-source & free to use, modify, and share for all.
;;;            Provided "as is", without warranty of any kind.
;;;  ---------------------------------------------------------------------

(vl-load-com)

;; Ray-casting point-in-polygon test. pt = (x y), poly = list of (x y).
(defun BGOL:CIN-PtInPoly (pt poly / n i j xi yi xj yj inside px py)
  (setq px (car pt))
  (setq py (cadr pt))
  (setq n (length poly))
  (setq inside nil)
  (setq i 0)
  (setq j (1- n))
  (while (< i n)
    (setq xi (car (nth i poly)))
    (setq yi (cadr (nth i poly)))
    (setq xj (car (nth j poly)))
    (setq yj (cadr (nth j poly)))
    (if (and (/= (> yi py) (> yj py))
             (< px (+ xi (* (/ (- xj xi) (- yj yi)) (- py yi)))))
      (setq inside (not inside))
    )
    (setq j i)
    (setq i (1+ i))
  )
  inside
)

(defun BGOL:CIN-RefPoint (edata)
  (cdr (assoc 10 edata))
)

(defun BGOL:CIN-PolyVerts (ent / obj coords i verts)
  (setq obj (vlax-ename->vla-object ent))
  (setq verts '())
  (if (vlax-property-available-p obj 'Coordinates)
    (progn
      (setq coords (vlax-safearray->list (vlax-variant-value (vla-get-Coordinates obj))))
      (setq i 0)
      (while (< i (length coords))
        (setq verts (append verts (list (list (nth i coords) (nth (1+ i) coords)))))
        (setq i (+ i 2))
      )
    )
  )
  verts
)

(defun C:CIN ( / boundEnt boundVerts ss n i ent edata refpt erased kept)
  (setq boundEnt (car (entsel "\nSelect boundary polygon (entities INSIDE it will be erased): ")))
  (if boundEnt
    (progn
      (setq boundVerts (BGOL:CIN-PolyVerts boundEnt))
      (if (>= (length boundVerts) 3)
        (progn
          (setq ss (ssget "_X"))
          (if ss
            (progn
              (setq erased 0)
              (setq kept 0)
              (setq n (sslength ss))
              (setq i 0)
              (while (< i n)
                (setq ent (ssname ss i))
                (if (/= ent boundEnt)
                  (progn
                    (setq edata (entget ent))
                    (setq refpt (BGOL:CIN-RefPoint edata))
                    (if (and refpt (BGOL:CIN-PtInPoly refpt boundVerts))
                      (progn
                        (entdel ent)
                        (setq erased (1+ erased))
                      )
                      (setq kept (1+ kept))
                    )
                  )
                )
                (setq i (1+ i))
              )
              (princ (strcat "\nCIN: erased " (itoa erased)
                              " entity(ies) inside the boundary. Kept "
                              (itoa kept) "."))
            )
            (princ "\nNo entities found in drawing.")
          )
        )
        (princ "\nSelected entity is not a valid closed polyline boundary.")
      )
    )
    (princ "\nNo boundary selected.")
  )
  (princ)
)

(princ "\nCLRIN-bgol.lsp loaded. Type CIN to erase entities inside a polyline boundary.")
(princ "\n  -- Free & open-source, courtesy of BGol Community (https://bgol.in/) --")
(princ)
