;;; ---------------------------------------------------------------------
;;;  PWRZIG-bgol.lsp
;;;  Command:  PWZ
;;;
;;;  PURPOSE
;;;  Converts a selected polyline into a properly scaled power-line
;;;  indicator: periodic zigzag "teeth" clusters drawn along the
;;;  polyline path, with plain segments between clusters, matching the
;;;  standard electrical/power-line cartographic symbol used in survey
;;;  and utility drawings.
;;;
;;;  USAGE
;;;    1. Load this file (APPLOAD or drag-drop onto the drawing window).
;;;    2. Type   PWZ   at the command line and press Enter.
;;;    3. Select the polyline representing the power line route.
;;;    4. Enter the zigzag amplitude, tooth spacing, and cluster
;;;       interval (Enter to accept the sensible defaults shown).
;;;    5. Zigzag clusters are generated along the route at the given
;;;       interval, drawn as short polylines on layer "BGOL-PWZ",
;;;       layered on top of the original route.
;;;
;;;  NOTES
;;;    - The original polyline is left untouched; the zigzag symbology
;;;      is drawn as separate entities on top of it.
;;;    - This is an original, independently written implementation.
;;;      It is INSPIRED by the general idea of scaled power-line symbol
;;;      generation utilities common in survey/utility 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:PWZ-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:PWZ-Polyline (pts lname / dxfdata pt)
  (setq dxfdata (list '(0 . "LWPOLYLINE")
                       '(100 . "AcDbEntity")
                       (cons 8 lname)
                       '(100 . "AcDbPolyline")
                       (cons 90 (length pts))
                       '(70 . 0)
                 )
  )
  (foreach pt pts
    (setq dxfdata (append dxfdata (list (cons 10 pt))))
  )
  (entmake dxfdata)
)

(defun BGOL:PWZ-Cluster (obj centerDist amp step lname / par tang perp base
                                                          i pts npeaks newpt off)
  (setq par (vlax-curve-getParamAtPoint obj (vlax-curve-getPointAtDist obj centerDist)))
  (setq tang (vlax-curve-getFirstDeriv obj par))
  (setq tang (BGOL:PWZ-Normalize tang))
  (setq perp (list (- (cadr tang)) (car tang) 0.0))
  (setq base (vlax-curve-getPointAtDist obj centerDist))
  (setq npeaks 4)
  (setq pts '())
  (setq i (- (/ npeaks 2)))
  (while (<= i (/ npeaks 2))
    (setq off (if (= 0 (rem i 2)) 0.0 amp))
    (setq newpt (list (+ (car base) (* (car tang) (* i step)) (* (car perp) off))
                       (+ (cadr base) (* (cadr tang) (* i step)) (* (cadr perp) off))
                       0.0))
    (setq pts (append pts (list newpt)))
    (setq i (1+ i))
  )
  (BGOL:PWZ-Polyline pts lname)
)

(defun BGOL:PWZ-Normalize (v / m)
  (setq m (sqrt (+ (* (car v) (car v)) (* (cadr v) (cadr v)))))
  (if (> m 0.0)
    (list (/ (car v) m) (/ (cadr v) m) 0.0)
    (list 1.0 0.0 0.0)
  )
)

(defun C:PWZ ( / ent obj total amp step interval d)
  (BGOL:PWZ-EnsureLayer "BGOL-PWZ")
  (setq ent (car (entsel "\nSelect polyline (power line route): ")))
  (if ent
    (progn
      (setq obj (vlax-ename->vla-object ent))
      (setq total (vlax-curve-getDistAtParam obj (vlax-curve-getEndParam obj)))
      (setq amp (getreal "\nZigzag amplitude <0.5>: "))
      (if (not amp) (setq amp 0.5))
      (setq step (getreal "\nTooth spacing <0.6>: "))
      (if (not step) (setq step 0.6))
      (setq interval (getreal "\nCluster interval <10.0>: "))
      (if (not interval) (setq interval 10.0))
      (setq d (/ interval 2.0))
      (while (< d total)
        (BGOL:PWZ-Cluster obj d amp step "BGOL-PWZ")
        (setq d (+ d interval))
      )
      (princ (strcat "\nPWZ: power-line zigzag symbology drawn along route (length " (rtos total 2 2) ")."))
    )
    (princ "\nNo polyline selected.")
  )
  (princ)
)

(princ "\nPWRZIG-bgol.lsp loaded. Type PWZ to draw scaled power-line zigzag symbology along a polyline.")
(princ "\n  -- Free & open-source, courtesy of BGol Community (https://bgol.in/) --")
(princ)
