;;; ---------------------------------------------------------------------
;;;  XPTMARK-bgol.lsp
;;;  Command:  XPM
;;;
;;;  PURPOSE
;;;  Finds every point where selected LINE, ARC and/or LWPOLYLINE
;;;  entities intersect one another and marks each intersection point
;;;  with a visible circle. Handles mixed entity types (including arcs)
;;;  in a single command, using the ActiveX IntersectWith method rather
;;;  than separate per-type geometric formulas.
;;;
;;;  USAGE
;;;    1. Load this file (APPLOAD or drag-drop onto the drawing window).
;;;    2. Type   XPM   at the command line and press Enter.
;;;    3. Select multiple LINE / ARC / LWPOLYLINE entities.
;;;    4. Every intersection point among the selected entities is marked
;;;       with a small circle on layer "BGOL-XPM". The selected entities
;;;       are left untouched.
;;;
;;;  NOTES
;;;    - This is an original, independently written implementation.
;;;      It is INSPIRED by the general idea of intersection-marking
;;;      utilities common in CAD/survey 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)

(setq *bgol-xpm-radius* 1.5)

(defun BGOL:XPM-EnsureLayer (lname / )
  (if (not (tblsearch "LAYER" lname))
    (entmake (list '(0 . "LAYER")
                   '(100 . "AcDbSymbolTableRecord")
                   '(100 . "AcDbLayerTableRecord")
                   (cons 2 lname)
                   '(70 . 0)
                   '(62 . 6)          ; magenta
                   '(6 . "Continuous")))
  )
)

(defun BGOL:XPM-MakeMarker (pt radius lname / dxfdata)
  (setq dxfdata (list '(0 . "CIRCLE")
                       '(100 . "AcDbEntity")
                       (cons 8 lname)
                       '(100 . "AcDbCircle")
                       (cons 10 pt)
                       (cons 40 radius)
                 )
  )
  (entmakex dxfdata)
)

;; Return T if pt is not already present (within tol) in ptlist
(defun BGOL:XPM-NewPointP (pt ptlist tol / found p)
  (setq found nil)
  (foreach p ptlist
    (if (< (distance pt p) tol) (setq found T))
  )
  (not found)
)

(defun C:XPM ( / ss n i j obj1 obj2 pts pt found allpts marks)
  (BGOL:XPM-EnsureLayer "BGOL-XPM")
  (princ "\nSelect LINE / ARC / LWPOLYLINE entities to check for intersections: ")
  (setq ss (ssget '((-4 . "<OR") (0 . "LINE") (0 . "ARC") (0 . "LWPOLYLINE") (-4 . "OR>"))))
  (if (and ss (>= (sslength ss) 2))
    (progn
      (setq n (sslength ss))
      (setq allpts '())
      (setq marks 0)
      (setq i 0)
      (while (< i n)
        (setq j (1+ i))
        (while (< j n)
          (setq obj1 (vlax-ename->vla-object (ssname ss i)))
          (setq obj2 (vlax-ename->vla-object (ssname ss j)))
          (setq pts (vl-catch-all-apply 'vlax-invoke (list obj1 'IntersectWith obj2 acExtendNone)))
          (if (not (vl-catch-all-error-p pts))
            (while pts
              (setq pt (list (car pts) (cadr pts) (caddr pts)))
              (if (BGOL:XPM-NewPointP pt allpts 1e-4)
                (progn
                  (setq allpts (append allpts (list pt)))
                  (BGOL:XPM-MakeMarker pt *bgol-xpm-radius* "BGOL-XPM")
                  (setq marks (1+ marks))
                )
              )
              (setq pts (cdddr pts))
            )
          )
          (setq j (1+ j))
        )
        (setq i (1+ i))
      )
      (princ (strcat "\nXPM: " (itoa marks) " intersection point(s) marked (layer BGOL-XPM)."))
    )
    (princ "\nSelect at least two entities to check for intersections.")
  )
  (princ)
)

(princ "\nXPTMARK-bgol.lsp loaded. Type XPM to find and mark all intersections among selected entities.")
(princ "\n  -- Free & open-source, courtesy of BGol Community (https://bgol.in/) --")
(princ)
