;;; ---------------------------------------------------------------------
;;;  VTXTABLE-bgol.lsp
;;;  Command:  VTAB
;;;
;;;  PURPOSE
;;;  Reads every vertex of a selected 2D or 3D polyline and generates an
;;;  in-drawing coordinate table listing Sl. No., Easting (X),
;;;  Northing (Y) and, for 3D polylines, Elevation (Z) - using standard
;;;  survey terminology.
;;;
;;;  USAGE
;;;    1. Load this file (APPLOAD or drag-drop onto the drawing window).
;;;    2. Type   VTAB   at the command line and press Enter.
;;;    3. Select the source polyline (2D LWPOLYLINE or legacy 3D
;;;       POLYLINE).
;;;    4. Pick a point in the drawing for the coordinate table.
;;;    5. A row-by-row text table of Sl./Easting/Northing[/Elevation] is
;;;       created on layer "BGOL-VTAB".
;;;
;;;  NOTES
;;;    - This is an original, independently written implementation.
;;;      It is INSPIRED by the general idea of vertex-to-coordinate-
;;;      table 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)

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

(defun BGOL:VTAB-MakeText (pt str ht lname / dxfdata)
  (setq dxfdata (list '(0 . "TEXT")
                       '(100 . "AcDbEntity")
                       (cons 8 lname)
                       '(100 . "AcDbText")
                       (cons 10 pt)
                       (cons 40 ht)
                       (cons 1 str)
                 )
  )
  (entmakex dxfdata)
)

;; Gather vertex list as (x y z) for LWPOLYLINE (2D + constant elevation)
;; or legacy 3D POLYLINE (true per-vertex Z).
(defun BGOL:VTAB-GetVerts (ename / edata etype obj coords n i pt elev verts vent vdata)
  (setq edata (entget ename))
  (setq etype (cdr (assoc 0 edata)))
  (setq verts '())
  (cond
    ((= etype "LWPOLYLINE")
     (setq obj (vlax-ename->vla-object ename))
     (setq coords (vlax-get obj 'Coordinates))
     (setq elev (vl-catch-all-apply 'vlax-get (list obj 'Elevation)))
     (if (vl-catch-all-error-p elev) (setq elev 0.0))
     (setq n (/ (length coords) 2))
     (setq i 0)
     (while (< i n)
       (setq pt (list (nth (* 2 i) coords) (nth (1+ (* 2 i)) coords) elev))
       (setq verts (append verts (list pt)))
       (setq i (1+ i))
     )
     (list verts nil)
    )
    ((= etype "POLYLINE")
     (setq vent (entnext ename))
     (while (and vent (= (cdr (assoc 0 (entget vent))) "VERTEX"))
       (setq vdata (entget vent))
       (setq pt (cdr (assoc 10 vdata)))
       (setq verts (append verts (list pt)))
       (setq vent (entnext vent))
     )
     (list verts T)
    )
    (t (list nil nil))
  )
)

(defun C:VTAB ( / ent verts is3d pt th rowht row sl v hdr)
  (BGOL:VTAB-EnsureLayer "BGOL-VTAB")
  (setq ent (car (entsel "\nSelect polyline for coordinate table: ")))
  (if ent
    (progn
      (setq v (BGOL:VTAB-GetVerts ent))
      (setq verts (car v))
      (setq is3d (cadr v))
      (if verts
        (progn
          (setq pt (getpoint "\nSpecify point for coordinate table: "))
          (if pt
            (progn
              (setq th 2.2)
              (setq rowht (* th 1.8))
              (setq row (list (car pt) (cadr pt) (caddr pt)))
              (BGOL:VTAB-MakeText row "COORDINATE TABLE (VTAB)" th "BGOL-VTAB")
              (setq row (list (car row) (- (cadr row) rowht) (caddr row)))
              (setq hdr (if is3d "Sl.No   Easting        Northing       Elevation"
                                 "Sl.No   Easting        Northing"))
              (BGOL:VTAB-MakeText row hdr th "BGOL-VTAB")
              (setq sl 1)
              (foreach pt3 verts
                (setq row (list (car row) (- (cadr row) rowht) (caddr row)))
                (BGOL:VTAB-MakeText row
                  (strcat (itoa sl) "      "
                          (rtos (car pt3) 2 3) "     "
                          (rtos (cadr pt3) 2 3)
                          (if is3d (strcat "     " (rtos (caddr pt3) 2 3)) ""))
                  th "BGOL-VTAB")
                (setq sl (1+ sl))
              )
              (princ (strcat "\nVTAB: coordinate table with " (itoa (length verts))
                              " row(s) placed in drawing."))
            )
            (princ "\nNo point specified; table not placed.")
          )
        )
        (princ "\nSelected entity has no readable vertices (must be LWPOLYLINE or POLYLINE).")
      )
    )
    (princ "\nNo entity selected.")
  )
  (princ)
)

(princ "\nVTXTABLE-bgol.lsp loaded. Type VTAB to build a coordinate table from a polyline's vertices.")
(princ "\n  -- Free & open-source, courtesy of BGol Community (https://bgol.in/) --")
(princ)
