;;; ---------------------------------------------------------------------
;;;  VXINTERP-bgol.lsp
;;;  Command:  VIZ
;;;
;;;  PURPOSE
;;;  When only the start and end elevations of a polyline are known,
;;;  this routine calculates the elevation at every intermediate vertex
;;;  by linear interpolation (proportional to distance along the
;;;  polyline) and drops elevation text at each one. Useful for design
;;;  gradelines, formation levels, and simplified breaklines where only
;;;  the two endpoint elevations are defined.
;;;
;;;  USAGE
;;;    1. Load this file (APPLOAD or drag-drop onto the drawing window).
;;;    2. Type   VIZ   at the command line and press Enter.
;;;    3. Select the polyline to interpolate.
;;;    4. Enter the known elevation at the START vertex.
;;;    5. Enter the known elevation at the END vertex.
;;;    6. Elevation text is created at every vertex (including the two
;;;       endpoints for confirmation), interpolated proportionally to
;;;       distance along the polyline, placed on layer "BGOL-VIZ".
;;;
;;;  NOTES
;;;    - This is an original, independently written implementation.
;;;      It is INSPIRED by the general idea of linear-interpolation
;;;      elevation 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-viz-precision* 3)

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

(defun BGOL:VIZ-MakeText (pt elev lname / dxfdata)
  (setq dxfdata (list '(0 . "TEXT")
                       '(100 . "AcDbEntity")
                       (cons 8 lname)
                       '(100 . "AcDbText")
                       (cons 10 (list (car pt) (cadr pt) 0.0))
                       '(40 . 2.0)
                       (cons 1 (rtos elev 2 *bgol-viz-precision*))
                 )
  )
  (entmake dxfdata)
)

;; Return list of 2D vertex points of an LWPOLYLINE, in order
(defun BGOL:VIZ-Vertices (ent / edata pts)
  (setq edata (entget ent))
  (setq pts '())
  (foreach pair edata
    (if (= (car pair) 10)
      (setq pts (append pts (list (cdr pair))))
    )
  )
  pts
)

(defun C:VIZ ( / ent obj pts n i pt0 ptN elevStart elevEnd
                 totalLen cumLen segLen frac elev pt prevpt)
  (BGOL:VIZ-EnsureLayer "BGOL-VIZ")
  (setq ent (car (entsel "\nSelect polyline to interpolate: ")))
  (if ent
    (progn
      (setq pts (BGOL:VIZ-Vertices ent))
      (setq n (length pts))
      (if (< n 2)
        (princ "\nSelected polyline needs at least 2 vertices.")
        (progn
          (setq elevStart (getreal "\nEnter known elevation at START vertex: "))
          (setq elevEnd   (getreal "\nEnter known elevation at END vertex: "))
          (if (and elevStart elevEnd)
            (progn
              ;; total length along the polyline (2D, vertex to vertex)
              (setq totalLen 0.0)
              (setq prevpt (car pts))
              (setq i 1)
              (while (< i n)
                (setq pt (nth i pts))
                (setq totalLen (+ totalLen (distance prevpt pt)))
                (setq prevpt pt)
                (setq i (1+ i))
              )
              (if (< totalLen 1e-9) (setq totalLen 1.0))
              ;; walk vertices again, accumulating distance for interpolation
              (setq cumLen 0.0)
              (setq prevpt (car pts))
              (setq i 0)
              (while (< i n)
                (setq pt (nth i pts))
                (if (> i 0)
                  (setq cumLen (+ cumLen (distance prevpt pt)))
                )
                (setq frac (/ cumLen totalLen))
                (setq elev (+ elevStart (* frac (- elevEnd elevStart))))
                (BGOL:VIZ-MakeText pt elev "BGOL-VIZ")
                (setq prevpt pt)
                (setq i (1+ i))
              )
              (princ (strcat "\nInterpolated elevation text created at " (itoa n) " vertices (BGOL-VIZ)."))
            )
            (princ "\nBoth start and end elevations are required.")
          )
        )
      )
    )
    (princ "\nNo polyline selected.")
  )
  (princ)
)

(princ "\nVXINTERP-bgol.lsp loaded. Type VIZ to interpolate vertex elevations along a polyline.")
(princ "\n  -- Free & open-source, courtesy of BGol Community (https://bgol.in/) --")
(princ)
