;;; ---------------------------------------------------------------------
;;;  VXTXT-bgol.lsp
;;;  Command:  VXTX
;;;
;;;  PURPOSE
;;;  Builds a brand-new LWPOLYLINE that passes through the insertion
;;;  points of a set of selected TEXT/MTEXT entities (e.g., elevation
;;;  labels placed along an existing polyline). The result is a new
;;;  polyline with a vertex located exactly at each selected text's
;;;  position, ordered by nearest-neighbour walking from a chosen start
;;;  point. The original polyline (if any) is left completely untouched.
;;;
;;;  USAGE
;;;    1. Load this file (APPLOAD or drag-drop onto the drawing window).
;;;    2. Type   VXTX   at the command line and press Enter.
;;;    3. Select the TEXT/MTEXT entities marking where new vertices
;;;       should be (e.g., elevation labels sitting on a polyline).
;;;    4. A new LWPOLYLINE is created on layer "BGOL-VXTX", passing
;;;       through every selected text's insertion point in order.
;;;
;;;  NOTES
;;;    - Text entities are ordered by walking a nearest-neighbour chain
;;;      starting from the text closest to the first-selected point,
;;;      so selection order does not need to already be sequential.
;;;    - This is an original, independently written implementation.
;;;      It is INSPIRED by the general idea of building vertex-marked
;;;      polylines from existing text label positions, a technique
;;;      common in survey/civil 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)

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

(defun BGOL:VXTX-MakePolyline (pointlist lname / dxfdata pt)
  (setq dxfdata (list '(0 . "LWPOLYLINE")
                       '(100 . "AcDbEntity")
                       (cons 8 lname)
                       '(100 . "AcDbPolyline")
                       (cons 90 (length pointlist))
                       '(70 . 0)
                 )
  )
  (foreach pt pointlist
    (setq dxfdata (append dxfdata (list (cons 10 (list (car pt) (cadr pt))))))
  )
  (entmake dxfdata)
)

;; Pop the point in ptlist nearest to fromPt, return (nearpt . remaininglist)
(defun BGOL:VXTX-PopNearest (fromPt ptlist / best bestd d pt rest)
  (setq best (car ptlist))
  (setq bestd (distance fromPt best))
  (foreach pt ptlist
    (setq d (distance fromPt pt))
    (if (< d bestd) (progn (setq best pt) (setq bestd d)))
  )
  (setq rest '())
  (foreach pt ptlist
    (if (not (equal pt best 1e-8)) (setq rest (append rest (list pt))))
  )
  (list best rest)
)

(defun C:VXTX ( / ss n i ent pt pts ordered cur result)
  (BGOL:VXTX-EnsureLayer "BGOL-VXTX")
  (setq ss (ssget '((0 . "TEXT,MTEXT"))))
  (if (and ss (>= (sslength ss) 2))
    (progn
      (setq pts '())
      (setq n (sslength ss))
      (setq i 0)
      (while (< i n)
        (setq ent (ssname ss i))
        (setq pt (cdr (assoc 10 (entget ent))))
        (setq pts (append pts (list pt)))
        (setq i (1+ i))
      )
      ;; order points by nearest-neighbour chain starting at the first one
      (setq ordered (list (car pts)))
      (setq pts (cdr pts))
      (setq cur (car ordered))
      (while pts
        (setq result (BGOL:VXTX-PopNearest cur pts))
        (setq cur (car result))
        (setq pts (cadr result))
        (setq ordered (append ordered (list cur)))
      )
      (BGOL:VXTX-MakePolyline ordered "BGOL-VXTX")
      (princ (strcat "\nNew polyline created through " (itoa (length ordered)) " text-marked vertex position(s) (BGOL-VXTX)."))
    )
    (princ "\nSelect at least 2 TEXT/MTEXT entities marking vertex positions.")
  )
  (princ)
)

(princ "\nVXTXT-bgol.lsp loaded. Type VXTX to build a polyline through selected text positions.")
(princ "\n  -- Free & open-source, courtesy of BGol Community (https://bgol.in/) --")
(princ)
