;;; ------------------------------------------------------------
;;; AutoCATS ¸®½À ÀÚ·á½Ç
;; ¸í·É: LINE2PL
;; ±â´É: ºñºÐ±â LINE ¹× ARC Ã¼ÀÎ°ú Æú¸®¼±ÀÇ »óÈ£ º¯È¯
;; ÃâÃ³: https://www.autocats.co.kr/lisp/line-to-polyline
;; ¹öÀü: 1.0 (2026-07-27)
;; ¶óÀÌ¼±½º: ÀÚÀ¯ »ç¿ë¡¤¼öÁ¤, Àç¹èÆ÷ ½Ã ÃâÃ³(autocats.co.kr) Ç¥±â
;; ¾ÈÀü: *error* ÇÚµé·¯ + UNDO ±×·ì, ºÐ±â ¹× 3D Ã¼ÀÎ º¯°æ ¹æÁö
;;; ------------------------------------------------------------

(vl-load-com)

(defun autocats-line2pl-locked-p (ent / row)
  (setq row (tblsearch "LAYER" (cdr (assoc 8 (entget ent)))))
  (and row (= 4 (logand 4 (cdr (assoc 70 row))))))

(defun autocats-line2pl-arc-point (center radius angle)
  (list
    (+ (car center) (* radius (cos angle)))
    (+ (cadr center) (* radius (sin angle)))
    (if (caddr center) (caddr center) 0.0)))

(defun autocats-line2pl-endpoints (ent / data kind center radius)
  (setq data (entget ent)
        kind (cdr (assoc 0 data)))
  (cond
    ((= kind "LINE")
     (list (cdr (assoc 10 data)) (cdr (assoc 11 data))))
    ((= kind "ARC")
     (setq center (cdr (assoc 10 data))
           radius (cdr (assoc 40 data)))
     (list
       (autocats-line2pl-arc-point center radius (cdr (assoc 50 data)))
       (autocats-line2pl-arc-point center radius (cdr (assoc 51 data)))))
    (T nil)))

(defun autocats-line2pl-near-count (point points tolerance / count)
  (setq count 0)
  (foreach other points
    (if (<= (distance point other) tolerance)
      (setq count (1+ count))))
  count)

(defun autocats-line2pl-valid-p (ss tolerance / idx endpoints pair base-z valid)
  (setq idx 0 endpoints nil valid T)
  (while (and valid (< idx (sslength ss)))
    (setq pair (autocats-line2pl-endpoints (ssname ss idx)))
    (if (or (null pair) (<= (distance (car pair) (cadr pair)) tolerance))
      (setq valid nil)
      (setq endpoints (append endpoints pair)))
    (setq idx (1+ idx)))
  (if endpoints (setq base-z (caddr (car endpoints))))
  (foreach point endpoints
    (if (or (> (abs (- (caddr point) base-z)) tolerance)
            (> (autocats-line2pl-near-count point endpoints tolerance) 2))
      (setq valid nil)))
  valid)

(defun autocats-line2pl-editable-set (ss / idx ent result)
  (setq idx 0 result (ssadd))
  (while (< idx (sslength ss))
    (setq ent (ssname ss idx))
    (if (not (autocats-line2pl-locked-p ent))
      (ssadd ent result))
    (setq idx (1+ idx)))
  result)

(defun autocats-line2pl-join (ss tolerance / old-accept result)
  (setq old-accept (getvar "PEDITACCEPT"))
  (setvar "PEDITACCEPT" 0)
  (setq result
        (vl-catch-all-apply
          '(lambda ()
             (command "_.PEDIT" "_Multiple" ss "" "_Yes" "_Join" tolerance "")
             T)))
  (setvar "PEDITACCEPT" old-accept)
  (if (vl-catch-all-error-p result) nil result))

(defun autocats-line2pl-explode (ss / result)
  (setq result
        (vl-catch-all-apply
          '(lambda ()
             (command "_.EXPLODE" ss "")
             T)))
  (if (vl-catch-all-error-p result) nil result))

(defun c:LINE2PL (/ *error* doc undo-open mode tolerance raw editable old-accept result)
  (defun *error* (msg)
    (if old-accept (setvar "PEDITACCEPT" old-accept))
    (if undo-open
      (progn (vla-EndUndoMark doc) (setq undo-open nil)))
    (if (and msg (not (wcmatch (strcase msg) "*CANCEL*,*QUIT*,*EXIT*,*Ãë¼Ò*")))
      (princ (strcat "\n[LINE2PL] Áß´Ü: " msg)))
    (princ))

  (initget "Join Explode")
  (setq mode (getkword "\n[LINE2PL] º¯È¯ [Join/Explode] <Join>: "))
  (if (null mode) (setq mode "Join"))
  (if (= mode "Join")
    (progn
      (princ "\n[LINE2PL] °áÇÕÇÒ LINE ¹× ARC¸¦ ¼±ÅÃÇÏ¼¼¿ä.")
      (setq raw (ssget '((0 . "LINE,ARC"))))
      (if raw
        (progn
          (initget 6)
          (setq tolerance (getdist "\n[LINE2PL] ¿¬°á Çã¿ë¿ÀÂ÷ <0.01>: "))
          (if (null tolerance) (setq tolerance 0.01))
          (setq editable (autocats-line2pl-editable-set raw))
          (if (or (= 0 (sslength editable))
                  (not (autocats-line2pl-valid-p editable tolerance)))
            (princ "\n[LINE2PL] µ¿ÀÏ Æò¸éÀÇ ºñºÐ±â ¿¬°á Ã¼ÀÎ¸¸ °áÇÕÇÒ ¼ö ÀÖ½À´Ï´Ù.")
            (progn
              (setq doc (vla-get-ActiveDocument (vlax-get-acad-object))
                    old-accept (getvar "PEDITACCEPT"))
              (vla-StartUndoMark doc)
              (setq undo-open T
                    result (autocats-line2pl-join editable tolerance))
              (vla-EndUndoMark doc)
              (setq undo-open nil old-accept nil)
              (if result
                (princ (strcat "\n[LINE2PL] ¿Ï·á: " (itoa (sslength editable))
                               "°³ ¼±¡¤È£¸¦ Æú¸®¼±À¸·Î º¯È¯Çß½À´Ï´Ù."))
                (princ "\n[LINE2PL] °áÇÕÇÏÁö ¸øÇÑ °´Ã¼°¡ ÀÖ½À´Ï´Ù.")))))
        (princ "\n[LINE2PL] ¼±ÅÃµÈ ¼± ¶Ç´Â È£°¡ ¾ø½À´Ï´Ù.")))
    (progn
      (princ "\n[LINE2PL] ºÐÇØÇÒ Æú¸®¼±À» ¼±ÅÃÇÏ¼¼¿ä.")
      (setq raw (ssget '((0 . "LWPOLYLINE,POLYLINE"))))
      (if raw
        (progn
          (setq editable (autocats-line2pl-editable-set raw))
          (if (= 0 (sslength editable))
            (princ "\n[LINE2PL] ÆíÁý °¡´ÉÇÑ Æú¸®¼±ÀÌ ¾ø½À´Ï´Ù.")
            (progn
              (setq doc (vla-get-ActiveDocument (vlax-get-acad-object)))
              (vla-StartUndoMark doc)
              (setq undo-open T
                    result (autocats-line2pl-explode editable))
              (vla-EndUndoMark doc)
              (setq undo-open nil)
              (if result
                (princ (strcat "\n[LINE2PL] ¿Ï·á: " (itoa (sslength editable))
                               "°³ Æú¸®¼±À» ºÐÇØÇß½À´Ï´Ù."))
                (princ "\n[LINE2PL] Æú¸®¼±À» ºÐÇØÇÏÁö ¸øÇß½À´Ï´Ù.")))))
        (princ "\n[LINE2PL] ¼±ÅÃµÈ Æú¸®¼±ÀÌ ¾ø½À´Ï´Ù."))))
  (princ))

(princ "\n[AutoCATS] LINE2PL ·Îµå ¿Ï·á - ¸í·ÉÇà¿¡ LINE2PL ¸¦ ÀÔ·ÂÇÏ¼¼¿ä.")
(princ)
