;;; ---------------------------------------------------------------------
;;;  AUTOMV-bgol.lsp
;;;  Command:  AMV
;;;
;;;  PURPOSE
;;;  Moves a selection of entities without requiring the user to
;;;  manually pick a base point first. The routine automatically computes
;;;  the leftmost point of the selection's combined bounding box and uses
;;;  it as the base point, so the user only has to pick the destination.
;;;
;;;  USAGE
;;;    1. Load this file (APPLOAD or drag-drop onto the drawing window).
;;;    2. Type   AMV   at the command line and press Enter.
;;;    3. Select the entities to move; press Enter to confirm selection.
;;;    4. Specify the destination point.
;;;    5. The selection is moved from its own leftmost point to the
;;;       destination point — no manual base-point pick required.
;;;
;;;  NOTES
;;;    - The leftmost point is derived from the combined bounding box of
;;;      every selected entity (the minimum X across all of them).
;;;    - This is an original, independently written implementation.
;;;      It is INSPIRED by the general idea of no-base-point move
;;;      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)

;; Compute the combined bounding box leftmost point (min X, and the Y at
;; that entity's box) across every entity in the selection set.
(defun BGOL:AMV-LeftmostPoint (ss / n i ent obj bbMinV bbMaxV bbMin bbMax
                                     minx miny found result)
  (setq n (sslength ss))
  (setq i 0)
  (setq found nil)
  (while (< i n)
    (setq ent (ssname ss i))
    (setq result (vl-catch-all-apply 'vlax-ename->vla-object (list ent)))
    (if (not (vl-catch-all-error-p result))
      (progn
        (setq obj result)
        (setq result
          (vl-catch-all-apply
            '(lambda ()
               (vla-getboundingbox obj 'bbMinV 'bbMaxV)
               (setq bbMin (vlax-safearray->list bbMinV))
               (setq bbMax (vlax-safearray->list bbMaxV))
            )
            nil
          )
        )
        (if (not (vl-catch-all-error-p result))
          (progn
            (if (or (not found) (< (car bbMin) minx))
              (progn
                (setq minx (car bbMin))
                (setq miny (cadr bbMin))
              )
            )
            (setq found T)
          )
        )
      )
    )
    (setq i (1+ i))
  )
  (if found
    (list minx miny 0.0)
    nil
  )
)

(defun C:AMV ( / ss basept destpt disp)
  (setq ss (ssget))
  (if ss
    (progn
      (setq basept (BGOL:AMV-LeftmostPoint ss))
      (if basept
        (progn
          (setq destpt (getpoint basept "\nSpecify destination point: "))
          (if destpt
            (progn
              (setq disp (mapcar '- destpt basept))
              (command "_.move" ss "" '(0.0 0.0 0.0) disp)
              (princ (strcat "\nAMV: moved " (itoa (sslength ss))
                              " entity(ies) using auto-detected leftmost base point."))
            )
            (princ "\nNo destination point specified — command cancelled.")
          )
        )
        (princ "\nCould not determine a bounding box for the selection.")
      )
    )
    (princ "\nNo entities selected.")
  )
  (princ)
)

(princ "\nAUTOMV-bgol.lsp loaded. Type AMV to move a selection without picking a base point.")
(princ "\n  -- Free & open-source, courtesy of BGol Community (https://bgol.in/) --")
(princ)
