From 7216ae49727b375a895bb72092f58bedc7073654 Mon Sep 17 00:00:00 2001 From: guga kakhadze Date: Mon, 29 Dec 2025 17:31:20 +0400 Subject: [PATCH] fixes in the autocad lsp file --- conveyors.csv | 133 ++++++----- generate_csv.lsp | 470 +++++++++++++++++++-------------------- generate_scene.py | 58 +++-- generated_conveyors.tscn | 42 +++- skipped_conveyors.txt | 12 + 5 files changed, 391 insertions(+), 324 deletions(-) create mode 100644 skipped_conveyors.txt diff --git a/conveyors.csv b/conveyors.csv index ed9ad24..23d04f9 100644 --- a/conveyors.csv +++ b/conveyors.csv @@ -1,59 +1,74 @@ -conveyor_key,tpe_count,vfd_count,start_x,start_y,end_x,end_y -PS1_2,2,1,3182.112871,1751.627960,3307.631353,1679.668896 -PS1_4,2,1,3377.926229,1655.901734,3931.089961,1657.733689 -PS1_5,1,1,3931.089961,1657.733689,4262.417377,1656.646266 -PS2_2,2,1,3099.843745,2245.419901,3140.391285,2223.245100 -PS2_3,1,1,3140.391285,2223.245100,3588.721702,1959.931507 -PS2_5,2,1,3660.544200,1941.885284,4197.937505,1938.160461 -PS2_6,1,1,4197.937505,1938.160461,4259.627698,1938.547503 -UL1_3,2,1,547.290786,1846.090315,902.762889,1810.459399 -UL1_4,1,1,902.762889,1810.459399,1731.526555,1810.217430 -UL1_5,1,1,1731.526555,1810.217430,1839.227859,1809.167581 -UL1_6,1,1,1839.227859,1809.167581,1876.642886,1807.970923 -UL1_7,1,1,1876.642886,1807.970923,1912.482307,1808.027116 -UL1_8,1,1,1912.482307,1808.027116,1948.547333,1806.790209 -UL1_9,1,1,1948.547333,1806.790209,1985.172076,1809.772901 -UL1_10,5,1,2020.869443,1811.538199,2641.029923,1810.100198 -UL1_11,1,2,2641.029923,1810.100198,2893.829959,1825.589512 -UL1_12,1,1,2893.829959,1825.589512,2785.705008,1813.203468 -UL1_13,1,1,2785.705008,1813.203468,3018.129340,1821.502800 -UL2_3,2,1,553.975614,2012.630135,903.404869,1978.577931 -UL2_4,1,1,903.404869,1978.577931,1719.423553,1977.802191 -UL2_5,1,1,1719.423553,1977.802191,1822.643168,1978.445929 -UL2_7,2,1,1899.557661,1958.742816,1944.517637,1930.951081 -UL2_8,1,1,1944.517637,1930.951081,1976.150833,1915.448512 -UL2_9,1,1,1976.150833,1915.448512,2008.246923,1897.796075 -UL2_10,1,1,2008.246923,1897.796075,2037.918359,1881.625600 -UL3_1,1,1,633.140086,2120.663545,831.814701,2091.737797 -UL3_2,2,1,878.893221,2098.646563,1861.404040,2089.400325 -UL3_3,1,1,1861.404040,2089.400325,2017.419596,2090.046509 -UL3_5,2,1,2082.236933,2070.328821,2282.772670,1950.214639 -UL3_6,1,1,2282.772670,1950.214639,2315.361086,1932.846138 -UL3_7,1,1,2315.361086,1932.846138,2348.664717,1919.645834 -UL3_8,1,1,2348.664717,1919.645834,2378.129323,1897.913034 -UL3_9,1,1,2378.129323,1897.913034,2408.907201,1881.035163 -UL4_3,2,1,552.788849,2350.626783,905.700382,2315.449436 -UL4_4,1,1,905.700382,2315.449436,1712.101194,2313.812375 -UL4_5,1,1,1712.101194,2313.812375,1819.964891,2317.864418 -UL4_6,1,1,1819.964891,2317.864418,1856.812083,2304.600063 -UL4_7,1,1,1856.812083,2304.600063,1892.551907,2306.435269 -UL4_8,1,1,1892.551907,2306.435269,1928.981908,2306.047462 -UL4_9,1,1,1928.981908,2306.047462,1965.024016,2306.234051 -UL4_10,5,1,2001.418905,2307.809246,2557.362372,2308.264495 -UL4_12,2,1,2718.741165,2320.506810,2815.749256,2323.832156 -UL4_13,1,1,2815.749256,2323.832156,2914.786899,2322.882657 -UL5_3,2,1,546.894209,2453.798891,903.442508,2479.527764 -UL5_4,1,1,903.442508,2479.527764,1691.840905,2484.924653 -UL5_5,1,1,1691.840905,2484.924653,1789.119716,2480.254441 -UL5_7,2,1,1854.915951,2464.288039,1913.811244,2428.171974 -UL5_8,1,1,1913.811244,2428.171974,1946.027358,2411.078652 -UL5_9,1,1,1946.027358,2411.078652,1976.288196,2392.094872 -UL5_10,1,1,1976.288196,2392.094872,2008.055527,2375.211118 -UL6_1,1,1,633.808413,2684.658977,830.713568,2651.384227 -UL6_2,2,1,889.155446,2663.081118,1706.522553,2653.949825 -UL6_3,1,1,1706.522553,2653.949825,1811.247017,2651.041122 -UL6_5,2,1,1876.189950,2633.114258,2190.222142,2447.433453 -UL6_6,1,1,2190.222142,2447.433453,2221.929865,2428.342256 -UL6_7,1,1,2221.929865,2428.342256,2254.419133,2412.811656 -UL6_8,1,1,2254.419133,2412.811656,2285.596047,2394.811656 -UL6_9,1,1,2285.596047,2394.811656,2315.906936,2377.311656 +conveyor_key,sec,included,reason,has_tpe,has_epc,has_vfd,is_last_any,is_last_geom,start_x,start_y,end_x,end_y +PS1_2,2,1,GEOMETRY,1,0,1,0,0,3182.112871,1751.627960,3307.631353,1679.668896 +PS1_4,4,1,GEOMETRY,1,0,1,0,0,3377.926229,1655.901734,3931.089961,1657.733689 +PS1_5,5,1,GEOMETRY,1,1,1,1,1,3931.089961,1657.733689,4262.417377,1656.646266 +PS2_2,2,1,GEOMETRY,1,0,1,0,0,3099.843745,2245.419901,3140.391285,2223.245100 +PS2_3,3,1,GEOMETRY,1,0,1,0,0,3140.391285,2223.245100,3588.721702,1959.931507 +PS2_5,5,1,GEOMETRY,1,0,1,0,0,3660.544200,1941.885284,4197.937505,1938.160461 +PS2_6,6,1,GEOMETRY,1,1,1,1,1,4197.937505,1938.160461,4259.627698,1938.547503 +UL1_3,3,1,GEOMETRY,1,1,1,0,0,547.290786,1846.090315,902.762889,1810.459399 +UL1_4,4,1,GEOMETRY,1,1,1,0,0,902.762889,1810.459399,1731.526555,1810.217430 +UL1_5,5,1,GEOMETRY,1,0,1,0,0,1731.526555,1810.217430,1839.227859,1809.167581 +UL1_6,6,1,GEOMETRY,1,0,1,0,0,1839.227859,1809.167581,1876.642886,1807.970923 +UL1_7,7,1,GEOMETRY,1,0,1,0,0,1876.642886,1807.970923,1912.482307,1808.027116 +UL1_8,8,1,GEOMETRY,1,0,1,0,0,1912.482307,1808.027116,1948.547333,1806.790209 +UL1_9,9,1,GEOMETRY,1,0,1,0,0,1948.547333,1806.790209,1985.172076,1809.772901 +UL1_10,10,1,GEOMETRY,1,1,1,0,0,2020.869443,1811.538199,2641.029923,1810.100198 +UL1_11,11,1,GEOMETRY,1,0,1,0,0,2641.029923,1810.100198,2803.698247,1810.912459 +UL1_12,12,1,GEOMETRY,1,0,1,0,0,2803.698247,1810.912459,2893.829959,1825.589512 +UL1_13,13,1,GEOMETRY,1,0,1,0,0,2893.829959,1825.589512,3018.129340,1821.502800 +UL1_14,14,1,GEOMETRY,1,0,1,1,1,3034.357601,1826.496682,3281.847811,1820.321611 +UL2_3,3,1,GEOMETRY,1,1,1,0,0,553.975614,2012.630135,903.404869,1978.577931 +UL2_4,4,1,GEOMETRY,1,1,1,0,0,903.404869,1978.577931,1719.423553,1977.802191 +UL2_5,5,1,GEOMETRY,1,0,1,0,0,1719.423553,1977.802191,1822.643168,1978.445929 +UL2_7,7,1,GEOMETRY,1,0,1,0,0,1899.557661,1958.742816,1944.517637,1930.951081 +UL2_8,8,1,GEOMETRY,1,0,1,0,0,1944.517637,1930.951081,1976.150833,1915.448512 +UL2_9,9,1,GEOMETRY,1,0,1,0,0,1976.150833,1915.448512,2008.246923,1897.796075 +UL2_10,10,1,GEOMETRY,1,0,1,0,1,2008.246923,1897.796075,2037.918359,1881.625600 +UL3_1,1,1,GEOMETRY,1,1,1,0,0,633.140086,2120.663545,831.814701,2091.737797 +UL3_2,2,1,GEOMETRY,1,1,1,0,0,878.893221,2098.646563,1861.404040,2089.400325 +UL3_3,3,1,GEOMETRY,1,0,1,0,0,1861.404040,2089.400325,2017.419596,2090.046509 +UL3_5,5,1,GEOMETRY,1,0,1,0,0,2082.236933,2070.328821,2282.772670,1950.214639 +UL3_6,6,1,GEOMETRY,1,0,1,0,0,2282.772670,1950.214639,2315.361086,1932.846138 +UL3_7,7,1,GEOMETRY,1,0,1,0,0,2315.361086,1932.846138,2348.664717,1919.645834 +UL3_8,8,1,GEOMETRY,1,0,1,0,0,2348.664717,1919.645834,2378.129323,1897.913034 +UL3_9,9,1,GEOMETRY,1,0,1,0,1,2378.129323,1897.913034,2408.907201,1881.035163 +UL4_3,3,1,GEOMETRY,1,1,1,0,0,552.788849,2350.626783,905.700382,2315.449436 +UL4_4,4,1,GEOMETRY,1,1,1,0,0,905.700382,2315.449436,1712.101194,2313.812375 +UL4_5,5,1,GEOMETRY,1,0,1,0,0,1712.101194,2313.812375,1819.964891,2317.864418 +UL4_6,6,1,GEOMETRY,1,0,1,0,0,1819.964891,2317.864418,1856.812083,2304.600063 +UL4_7,7,1,GEOMETRY,1,0,1,0,0,1856.812083,2304.600063,1892.551907,2306.435269 +UL4_8,8,1,GEOMETRY,1,0,1,0,0,1892.551907,2306.435269,1928.981908,2306.047462 +UL4_9,9,1,GEOMETRY,1,0,1,0,0,1928.981908,2306.047462,1965.024016,2306.234051 +UL4_10,10,1,GEOMETRY,1,1,1,0,0,2001.418905,2307.809246,2557.362372,2308.264495 +UL4_11,11,1,GEOMETRY,1,0,1,0,0,2557.362372,2308.264495,2718.741165,2320.506810 +UL4_12,12,1,GEOMETRY,1,0,1,0,0,2718.741165,2320.506810,2815.749256,2323.832156 +UL4_13,13,1,GEOMETRY,1,0,1,0,0,2815.749256,2323.832156,2914.786899,2322.882657 +UL4_14,14,1,GEOMETRY,1,0,1,1,1,2925.448433,2318.555436,3138.255794,2321.951658 +UL5_3,3,1,GEOMETRY,1,1,1,0,0,546.894209,2453.798891,903.442508,2479.527764 +UL5_4,4,1,GEOMETRY,1,1,1,0,0,903.442508,2479.527764,1691.840905,2484.924653 +UL5_5,5,1,GEOMETRY,1,0,1,0,0,1691.840905,2484.924653,1789.119716,2480.254441 +UL5_7,7,1,GEOMETRY,1,0,1,0,0,1854.915951,2464.288039,1913.811244,2428.171974 +UL5_8,8,1,GEOMETRY,1,0,1,0,0,1913.811244,2428.171974,1946.027358,2411.078652 +UL5_9,9,1,GEOMETRY,1,0,1,0,0,1946.027358,2411.078652,1976.288196,2392.094872 +UL5_10,10,1,GEOMETRY,1,0,1,0,1,1976.288196,2392.094872,2008.055527,2375.211118 +UL6_1,1,1,GEOMETRY,1,1,1,0,0,633.808413,2684.658977,830.713568,2651.384227 +UL6_2,2,1,GEOMETRY,1,1,1,0,0,889.155446,2663.081118,1706.522553,2653.949825 +UL6_3,3,1,GEOMETRY,1,0,1,0,0,1706.522553,2653.949825,1811.247017,2651.041122 +UL6_5,5,1,GEOMETRY,1,0,1,0,0,1876.189950,2633.114258,2190.222142,2447.433453 +UL6_6,6,1,GEOMETRY,1,0,1,0,0,2190.222142,2447.433453,2221.929865,2428.342256 +UL6_7,7,1,GEOMETRY,1,0,1,0,0,2221.929865,2428.342256,2254.419133,2412.811656 +UL6_8,8,1,GEOMETRY,1,0,1,0,0,2254.419133,2412.811656,2285.596047,2394.811656 +UL6_9,9,1,GEOMETRY,1,0,1,0,1,2285.596047,2394.811656,2315.906936,2377.311656 +UL2_6,6,0,VFD_ONLY_BEFORE_GEOM_END,0,0,1,0,0,,,, +UL3_4,4,0,VFD_ONLY_BEFORE_GEOM_END,0,0,1,0,0,,,, +PS1_1,1,0,VFD_ONLY_BEFORE_GEOM_END,0,1,1,0,0,,,, +PS2_4,4,0,VFD_ONLY_BEFORE_GEOM_END,0,0,1,0,0,,,, +PS1_3,3,0,VFD_ONLY_BEFORE_GEOM_END,0,0,1,0,0,,,, +PS2_1,1,0,VFD_ONLY_BEFORE_GEOM_END,0,1,1,0,0,,,, +UL5_6,6,0,VFD_ONLY_BEFORE_GEOM_END,0,0,1,0,0,,,, +UL2_11,11,0,VFD_ONLY_LAST_MAY_MERGE,0,0,1,1,0,,,, +UL3_10,10,0,VFD_ONLY_LAST_MAY_MERGE,0,0,1,1,0,,,, +UL5_11,11,0,VFD_ONLY_LAST_MAY_MERGE,0,0,1,1,0,,,, +UL6_4,4,0,VFD_ONLY_BEFORE_GEOM_END,0,0,1,0,0,,,, +UL6_10,10,0,VFD_ONLY_LAST_MAY_MERGE,0,0,1,1,0,,,, diff --git a/generate_csv.lsp b/generate_csv.lsp index ea8acb1..be3fc27 100644 --- a/generate_csv.lsp +++ b/generate_csv.lsp @@ -1,89 +1,47 @@ ; ============================================================ -; EXPORT_CONVEYORS (v5 - TPE-first geometry + EPC bootstrap only at chain start + VFD count) -; -; Conveyor definition: -; - Source blocks: -; CLX_TPE (photoeye anchors) -; CLX_EPC (EPC blocks - may be chained across multiple conveyors) -; VFD_v2 (drive blocks) -; - Logical name from attribute: P_TAG1 -; e.g. UL5_4_TPE1, UL6_2_EPC2, UL6_3_VFD1 -; - Conveyor key = _
-; - Section change ALWAYS = new conveyor -; -; GEOMETRY (IMPORTANT): -; - TPEs define conveyor boundaries. EPCs DO NOT split conveyors. -; - For each conveyor key: -; * If TPE count >= 2: -; end = last TPE (highest index) -; start = first TPE (lowest index) -; BUT if this is the first conveyor in the prefix chain (no previous section exported) -; and EPC exists on this conveyor, EPC may be used as the START ONLY (bootstrap) if it extends the belt. -; * If TPE count == 1: -; end = that single TPE -; start = previous conveyor end (if exists & within MAX_STITCH_DISTANCE) -; else (ONLY if first conveyor in chain) bootstrap start from EPC farthest from the end TPE -; else start = own TPE -; * If TPE count == 0: -; not exported (out of scope / unreliable geometry) +; EXPORT_CONVEYORS (v7 - TPE-first geometry + EPC bootstrap + VFD inclusion + reasoning columns) ; ; Output: CSV -; conveyor_key,tpe_count,vfd_count,start_x,start_y,end_x,end_y +; conveyor_key,sec,included,reason,has_tpe,has_epc,has_vfd,is_last_any,is_last_geom,start_x,start_y,end_x,end_y +; +; included: +; 1 = geometry exported (TPE-based) +; 0 = no geometry (typically VFD-only) +; +; reasoning columns help Godot decide: +; - "VFD_ONLY_MIDDLE" => likely spur candidate (not last in prefix) +; - "VFD_ONLY_LAST_MAY_MERGE" => last in prefix, could be merge-end triangle conveyor +; - "VFD_ONLY_BEFORE_GEOM_END"=> weird: VFD-only but section <= last geom section (data issue / missing TPE) +; - "NO_GEOM_NO_VFD" => not written (we don’t export these) ; ============================================================ (vl-load-com) -;; ------------------------ -;; Tuning / safety -;; ------------------------ -(setq *MAX_STITCH_DISTANCE* 1000.0) ; inches (normal neighbor stitching) -(setq *MAX_BOOTSTRAP_DISTANCE* 5000.0) ; inches (EPC bootstrap guardrail for FIRST conveyor only) +(setq *MAX_STITCH_DISTANCE* 1000.0) ; inches +(setq *MAX_BOOTSTRAP_DISTANCE* 5000.0) ; inches -;; ------------------------ -;; Attribute helper -;; ------------------------ (defun getAttVal (attList tag) (setq tag (strcase tag)) - (setq a - (vl-some - (function - (lambda (a) - (if (= (strcase (vla-get-tagstring a)) tag) a) - ) - ) - attList - ) - ) + (setq a (vl-some '(lambda (a) + (if (= (strcase (vla-get-tagstring a)) tag) a)) + attList)) (if a (strcase (vl-string-trim " " (vla-get-textstring a))) "" ) ) -;; ------------------------ -;; Simple underscore splitter -;; ------------------------ (defun splitUnderscore (s / parts cur i ch) (setq parts '() cur "" i 1) (while (<= i (strlen s)) (setq ch (substr s i 1)) (if (= ch "_") - (progn - (setq parts (append parts (list cur))) - (setq cur "") - ) - (setq cur (strcat cur ch)) - ) - (setq i (1+ i)) - ) + (progn (setq parts (append parts (list cur))) (setq cur "")) + (setq cur (strcat cur ch))) + (setq i (1+ i))) (append parts (list cur)) ) -;; ------------------------ -;; Parse P_TAG1 like: UL6_3_TPE1 / UL6_3_EPC2 / UL6_3_VFD1 -;; returns: (prefix section kind index) or nil -;; kind is "TPE" / "EPC" / "VFD" -;; ------------------------ (defun parse-ptag1-anchor (ptag / s parts prefix section third kind idx) (setq s (strcase (vl-string-trim " " ptag))) (if (and s (vl-string-search "_" s)) @@ -91,25 +49,30 @@ (setq parts (splitUnderscore s)) (if (= (length parts) 3) (progn - (setq prefix (nth 0 parts)) + (setq prefix (nth 0 parts)) (setq section (atoi (nth 1 parts))) - (setq third (nth 2 parts)) ; TPE#, EPC#, VFD# - + (setq third (nth 2 parts)) (cond - ((wcmatch third "TPE*") - (setq kind "TPE") - (setq idx (atoi (substr third 4)))) - ((wcmatch third "EPC*") - (setq kind "EPC") - (setq idx (atoi (substr third 4)))) - ((wcmatch third "VFD*") - (setq kind "VFD") - (setq idx (atoi (substr third 4)))) - (t - (setq kind nil) - (setq idx 0)) + ((or + (wcmatch third "TPE*") + (wcmatch third "PE*") + (wcmatch third "LPE*") + (wcmatch third "RPE*") + ) + (setq kind "TPE") + (setq idx + (cond + ((wcmatch third "TPE*") (atoi (substr third 4))) + ((wcmatch third "LPE*") (atoi (substr third 4))) + ((wcmatch third "RPE*") (atoi (substr third 4))) + (T (atoi (substr third 3))) ; PE* + ) + ) + ) + ((wcmatch third "EPC*") (setq kind "EPC") (setq idx (atoi (substr third 4)))) + ((wcmatch third "VFD*") (setq kind "VFD") (setq idx (atoi (substr third 4)))) + (t (setq kind nil) (setq idx 0)) ) - (if (and kind prefix (> section 0) (> idx 0)) (list prefix section kind idx) nil @@ -122,9 +85,6 @@ ) ) -;; ------------------------ -;; Helpers: key parsing + distance -;; ------------------------ (defun parse-key (key / parts prefix section) (setq parts (splitUnderscore (strcase key))) (if (= (length parts) 2) @@ -133,11 +93,7 @@ (setq section (atoi (nth 1 parts))) (if (and prefix (> section 0)) (list prefix section) - nil - ) - ) - nil - ) + nil))) ) (defun dist2d (p q / dx dy) @@ -150,80 +106,63 @@ (and p q (<= (dist2d p q) maxd)) ) -;; ------------------------ -;; Find neighbor record in a chain (by prefix + section) -;; Each chain entry: -;; (section key tpeCount tpeSorted firstTPE lastTPE epcPoints) -;; ------------------------ (defun find-by-section (chain targetSec / r) (setq r nil) - (foreach e chain - (if (= (car e) targetSec) (setq r e)) - ) + (foreach e chain (if (= (car e) targetSec) (setq r e))) r ) -;; ------------------------ -;; Pick EPC point farthest from a reference point (usually endTPE) -;; Returns EPC xy or nil -;; ------------------------ (defun farthest-from (pts ref / bestD bestP d) (setq bestD -1.0 bestP nil) (foreach p pts (setq d (dist2d p ref)) - (if (> d bestD) - (progn - (setq bestD d) - (setq bestP p) - ) - ) - ) + (if (> d bestD) (setq bestD d bestP p))) bestP ) -;; ------------------------ -;; Main command -;; ------------------------ +;; prefixStats = ( (prefix . (maxAny maxGeom)) ... ) +(defun stats-get (stats prefix / it) + (setq it (assoc prefix stats)) + (if it (cdr it) (list 0 0)) +) + +(defun stats-set (stats prefix maxAny maxGeom / it) + (setq it (assoc prefix stats)) + (if it + (subst (cons prefix (list maxAny maxGeom)) it stats) + (cons (cons prefix (list maxAny maxGeom)) stats) + ) +) + (defun c:EXPORT_CONVEYORS ( / ss i ent blk effName attList ptag parsed prefix section kind idx insPt xy key - tpeMap epcMap vfdMap entries + tpeMap epcMap vfdPresence outPath fh chainMap kv parsedKey chainKey secNum tpeEntries epcEntries tpeCount epcPoints tpeSorted firstTPE lastTPE - chains rec - prevRec prevEnd - startXY endXY - vfdEntries vfdCount - allKeys - endRef baseLen epcCandidate epcLen) + chains rec prevRec prevEnd + startXY endXY allKeys + endRef baseLen epcCandidate epcLen + included + prefixStats maxAny maxGeom + hasT hasE hasV isLastAny isLastGeom reason) - ;; Maps: - ;; tpeMap = ( (key . ( (idx xy) ... )) ... ) - ;; epcMap = ( (key . ( (idx xy) ... )) ... ) - ;; vfdMap = ( (key . ( "UL6_3_VFD1" ... )) ... ) ; unique P_TAG1 values (setq tpeMap '()) (setq epcMap '()) - (setq vfdMap '()) + (setq vfdPresence '()) (setq ss (ssget "X" '((0 . "INSERT")))) - (if (not ss) + (progn (princ "\nNo INSERT blocks found.") (princ)) (progn - (princ "\nNo INSERT blocks found.") - (princ) - ) - (progn - ;; ------------------------ - ;; 1) Collect TPE + EPC points + VFD unique tags by conveyor key - ;; ------------------------ + ;; --- 1) Collect anchors + VFD presence --- (setq i 0) (while (< i (sslength ss)) (setq ent (ssname ss i)) (setq blk (vlax-ename->vla-object ent)) (setq effName (strcase (vla-get-EffectiveName blk))) - ;; VFD_v2 -> "VFD_V2" (if (or (= effName "CLX_TPE") (= effName "CLX_EPC") (= effName "VFD_V2")) (progn (setq attList (vlax-invoke blk 'GetAttributes)) @@ -232,14 +171,13 @@ (if parsed (progn - (setq prefix (nth 0 parsed)) + (setq prefix (nth 0 parsed)) (setq section (nth 1 parsed)) - (setq kind (nth 2 parsed)) - (setq idx (nth 3 parsed)) + (setq kind (nth 2 parsed)) + (setq idx (nth 3 parsed)) (setq key (strcat prefix "_" (itoa section))) (cond - ;; --- TPE --- ((= kind "TPE") (setq insPt (vlax-get blk 'InsertionPoint)) (setq xy (list (car insPt) (cadr insPt))) @@ -249,12 +187,9 @@ (setq tpeMap (if (assoc key tpeMap) (subst (cons key entries) (assoc key tpeMap) tpeMap) - (cons (cons key entries) tpeMap) - ) + (cons (cons key entries) tpeMap)) ) ) - - ;; --- EPC --- ((= kind "EPC") (setq insPt (vlax-get blk 'InsertionPoint)) (setq xy (list (car insPt) (cadr insPt))) @@ -264,24 +199,12 @@ (setq epcMap (if (assoc key epcMap) (subst (cons key entries) (assoc key epcMap) epcMap) - (cons (cons key entries) epcMap) - ) + (cons (cons key entries) epcMap)) ) ) - - ;; --- VFD (unique by P_TAG1 text) --- ((= kind "VFD") - (setq vfdEntries (cdr (assoc key vfdMap))) - (if (not vfdEntries) (setq vfdEntries '())) - (if (and (/= ptag "") (not (member ptag vfdEntries))) - (setq vfdEntries (cons ptag vfdEntries)) - ) - (setq vfdMap - (if (assoc key vfdMap) - (subst (cons key vfdEntries) (assoc key vfdMap) vfdMap) - (cons (cons key vfdEntries) vfdMap) - ) - ) + (if (not (assoc key vfdPresence)) + (setq vfdPresence (cons (cons key T) vfdPresence))) ) ) ) @@ -292,48 +215,36 @@ (setq i (1+ i)) ) - ;; ------------------------ - ;; 2) Build chainMap by prefix. - ;; Only EXPORT if tpeCount > 0 (TPE-first geometry). - ;; Each record: - ;; (section key tpeCount tpeSorted firstTPE lastTPE epcPoints) - ;; ------------------------ + ;; --- 2) Build chainMap by prefix for conveyors with TPEs --- (setq chainMap '()) - - ;; keys to consider: union of tpeMap and epcMap (so EPCs are available for bootstrap) (setq allKeys '()) + + ;; union keys: tpe keys + epc-only keys (for bootstrap availability) (foreach kv tpeMap (setq allKeys (cons (car kv) allKeys))) (foreach kv epcMap (if (not (assoc (car kv) tpeMap)) - (setq allKeys (cons (car kv) allKeys)) - ) - ) + (setq allKeys (cons (car kv) allKeys)))) (foreach key allKeys (setq parsedKey (parse-key key)) (if parsedKey (progn (setq chainKey (nth 0 parsedKey)) - (setq secNum (nth 1 parsedKey)) + (setq secNum (nth 1 parsedKey)) (setq tpeEntries (cdr (assoc key tpeMap))) (setq epcEntries (cdr (assoc key epcMap))) - (setq tpeCount (if tpeEntries (length tpeEntries) 0)) - ;; EPC points list (xy only) (setq epcPoints '()) (if epcEntries - (foreach it epcEntries (setq epcPoints (cons (cadr it) epcPoints))) - ) + (foreach it epcEntries (setq epcPoints (cons (cadr it) epcPoints)))) - ;; TPE-sorted + endpoints (if (> tpeCount 0) (progn (setq tpeSorted (vl-sort tpeEntries '(lambda (a b) (< (car a) (car b))))) - (setq firstTPE (cadr (car tpeSorted))) - (setq lastTPE (cadr (car (reverse tpeSorted)))) - + (setq firstTPE (cadr (car tpeSorted))) + (setq lastTPE (cadr (car (reverse tpeSorted)))) (setq rec (list secNum key tpeCount tpeSorted firstTPE lastTPE epcPoints)) (setq chains (cdr (assoc chainKey chainMap))) @@ -343,140 +254,215 @@ (setq chainMap (if (assoc chainKey chainMap) (subst (cons chainKey chains) (assoc chainKey chainMap) chainMap) - (cons (cons chainKey chains) chainMap) - ) - ) + (cons (cons chainKey chains) chainMap))) ) ) ) ) ) - ;; sort each chain by section ascending + ;; sort by section (foreach kv chainMap (setq chainKey (car kv)) - (setq chains (cdr kv)) - (setq chains (vl-sort chains '(lambda (a b) (< (car a) (car b))))) + (setq chains (vl-sort (cdr kv) '(lambda (a b) (< (car a) (car b))))) (setq chainMap (subst (cons chainKey chains) kv chainMap)) ) - ;; ------------------------ - ;; 3) Write CSV with: - ;; - TPE-first geometry - ;; - Stitch START from previous conveyor end for single-TPE - ;; - EPC bootstrap START only if first in chain (no prevRec) - ;; - vfd_count - ;; ------------------------ - (setq outPath - (getfiled - "Save conveyors CSV" - (strcat (getvar "DWGPREFIX") "conveyors.csv") - "csv" - 1 + ;; --- 2.5) Build prefixStats: maxAny and maxGeom per prefix --- + (setq prefixStats '()) + + ;; consider ANY keys from: tpeMap, epcMap, vfdPresence + (foreach kv tpeMap + (setq key (car kv)) + (setq parsedKey (parse-key key)) + (if parsedKey + (progn + (setq prefix (nth 0 parsedKey)) + (setq secNum (nth 1 parsedKey)) + (setq it (stats-get prefixStats prefix)) + (setq maxAny (nth 0 it)) + (setq maxGeom (nth 1 it)) + (if (> secNum maxAny) (setq maxAny secNum)) + (if (> secNum maxGeom) (setq maxGeom secNum)) + (setq prefixStats (stats-set prefixStats prefix maxAny maxGeom)) + ) ) ) + (foreach kv epcMap + (setq key (car kv)) + (setq parsedKey (parse-key key)) + (if parsedKey + (progn + (setq prefix (nth 0 parsedKey)) + (setq secNum (nth 1 parsedKey)) + (setq it (stats-get prefixStats prefix)) + (setq maxAny (nth 0 it)) + (setq maxGeom (nth 1 it)) + (if (> secNum maxAny) (setq maxAny secNum)) + ;; maxGeom only updates via TPE (geometry), so leave it + (setq prefixStats (stats-set prefixStats prefix maxAny maxGeom)) + ) + ) + ) + + (foreach kv vfdPresence + (setq key (car kv)) + (setq parsedKey (parse-key key)) + (if parsedKey + (progn + (setq prefix (nth 0 parsedKey)) + (setq secNum (nth 1 parsedKey)) + (setq it (stats-get prefixStats prefix)) + (setq maxAny (nth 0 it)) + (setq maxGeom (nth 1 it)) + (if (> secNum maxAny) (setq maxAny secNum)) + (setq prefixStats (stats-set prefixStats prefix maxAny maxGeom)) + ) + ) + ) + + ;; --- 3) Write CSV --- + (setq outPath (getfiled "Save conveyors CSV" + (strcat (getvar "DWGPREFIX") "conveyors.csv") + "csv" 1)) (if outPath (progn (setq fh (open outPath "w")) - (write-line "conveyor_key,tpe_count,vfd_count,start_x,start_y,end_x,end_y" fh) + (write-line "conveyor_key,sec,included,reason,has_tpe,has_epc,has_vfd,is_last_any,is_last_geom,start_x,start_y,end_x,end_y" fh) + ;; --- 3A) Geometry conveyors (included=1) --- (foreach kv chainMap (setq chainKey (car kv)) - (setq chains (cdr kv)) ; sorted + (setq chains (cdr kv)) + + ;; prefix stats for flags + (setq it (stats-get prefixStats chainKey)) + (setq maxAny (nth 0 it)) + (setq maxGeom (nth 1 it)) (foreach rec chains - (setq secNum (nth 0 rec)) - (setq key (nth 1 rec)) - (setq tpeCount (nth 2 rec)) - (setq firstTPE (nth 4 rec)) - (setq lastTPE (nth 5 rec)) + (setq secNum (nth 0 rec)) + (setq key (nth 1 rec)) + (setq tpeCount (nth 2 rec)) + (setq firstTPE (nth 4 rec)) + (setq lastTPE (nth 5 rec)) (setq epcPoints (nth 6 rec)) - ;; Default: TPE-defined endpoints (setq startXY firstTPE) - (setq endXY lastTPE) - - ;; Neighbor (previous section) record in same prefix chain + (setq endXY lastTPE) (setq prevRec (find-by-section chains (1- secNum))) - ;; ----- If single-TPE, end is that TPE (already), start may stitch from prev end ----- + ;; single-TPE handling (if (= tpeCount 1) (progn - (setq endXY lastTPE) ; the only TPE + (setq endXY lastTPE) (if prevRec (progn - (setq prevEnd (nth 5 prevRec)) ; prev lastTPE + (setq prevEnd (nth 5 prevRec)) (if (within? prevEnd endXY *MAX_STITCH_DISTANCE*) (setq startXY prevEnd) - (setq startXY endXY) - ) - ) - (setq startXY endXY) - ) + (setq startXY endXY))) + (setq startXY endXY)) - ;; EPC bootstrap START only if NO prevRec (first conveyor in chain) + ;; EPC bootstrap only if first in chain (if (and (not prevRec) epcPoints) (progn (setq epcCandidate (farthest-from epcPoints endXY)) (if (and epcCandidate (within? epcCandidate endXY *MAX_BOOTSTRAP_DISTANCE*)) - (setq startXY epcCandidate) - ) - ) - ) + (setq startXY epcCandidate)))) ) ) - ;; ----- If multi-TPE, allow EPC bootstrap only for FIRST conveyor in chain ----- + ;; multi-TPE bootstrap only if first in chain (if (and (>= tpeCount 2) (not prevRec) epcPoints) (progn - ;; Only use EPC as START if it meaningfully extends beyond firstTPE->lastTPE (setq endRef lastTPE) (setq baseLen (dist2d firstTPE endRef)) - (setq epcCandidate (farthest-from epcPoints endRef)) - (if epcCandidate - (progn - (setq epcLen (dist2d epcCandidate endRef)) - (if (and (> epcLen baseLen) - (within? epcCandidate endRef *MAX_BOOTSTRAP_DISTANCE*)) - (setq startXY epcCandidate) - ) - ) - ) - ) + (if (and epcCandidate + (> (dist2d epcCandidate endRef) baseLen) + (within? epcCandidate endRef *MAX_BOOTSTRAP_DISTANCE*)) + (setq startXY epcCandidate))) ) - ;; vfd_count (unique VFD_v2 P_TAG1s) - (setq vfdCount 0) - (if (assoc key vfdMap) - (setq vfdCount (length (cdr (assoc key vfdMap)))) - ) + (setq included 1) + (setq hasT 1) + (setq hasE (if (assoc key epcMap) 1 0)) + (setq hasV (if (assoc key vfdPresence) 1 0)) + (setq isLastAny (if (= secNum maxAny) 1 0)) + (setq isLastGeom (if (= secNum maxGeom) 1 0)) + (setq reason "GEOMETRY") (write-line (strcat - key "," - (itoa tpeCount) "," - (itoa vfdCount) "," + key "," (itoa secNum) "," + (itoa included) "," reason "," + (itoa hasT) "," (itoa hasE) "," (itoa hasV) "," + (itoa isLastAny) "," (itoa isLastGeom) "," (rtos (car startXY) 2 6) "," (rtos (cadr startXY) 2 6) "," - (rtos (car endXY) 2 6) "," (rtos (cadr endXY) 2 6) + (rtos (car endXY) 2 6) "," (rtos (cadr endXY) 2 6) ) fh ) ) ) + ;; --- 3B) VFD-only conveyors (included=0, no geometry) --- + (foreach kv vfdPresence + (setq key (car kv)) + (setq parsedKey (parse-key key)) + + ;; only output if no TPE geometry record exists + (if (and parsedKey (not (assoc key tpeMap))) + (progn + (setq prefix (nth 0 parsedKey)) + (setq secNum (nth 1 parsedKey)) + + (setq it (stats-get prefixStats prefix)) + (setq maxAny (nth 0 it)) + (setq maxGeom (nth 1 it)) + + (setq included 0) + (setq hasT 0) + (setq hasE (if (assoc key epcMap) 1 0)) + (setq hasV 1) + (setq isLastAny (if (= secNum maxAny) 1 0)) + (setq isLastGeom (if (= secNum maxGeom) 1 0)) + + ;; Reasoning: + ;; - If this is last of the prefix (maxAny): could be a merge-end “triangle” conveyor + ;; - If it’s not last: likely a side spur candidate + ;; - If it’s before/at last geom section: likely missing TPEs / drafting inconsistency + (setq reason "VFD_ONLY_MIDDLE") + (if (= isLastAny 1) + (setq reason "VFD_ONLY_LAST_MAY_MERGE") + (if (and (> maxGeom 0) (<= secNum maxGeom)) + (setq reason "VFD_ONLY_BEFORE_GEOM_END") + ) + ) + + (write-line + (strcat + key "," (itoa secNum) "," + (itoa included) "," reason "," + (itoa hasT) "," (itoa hasE) "," (itoa hasV) "," + (itoa isLastAny) "," (itoa isLastGeom) ",,,," + ) + fh + ) + ) + ) + ) + (close fh) (princ (strcat "\nExported conveyors to: " outPath)) - (princ "\nGeometry: TPE-first. EPC used only as START bootstrap for first conveyor in chain when it extends the belt.") - (princ (strcat "\nStitch: single-TPE start may stitch from previous end (MAX_STITCH_DISTANCE=" (rtos *MAX_STITCH_DISTANCE* 2 2) ").")) - (princ (strcat "\nBootstrap: EPC->endTPE guarded by MAX_BOOTSTRAP_DISTANCE=" (rtos *MAX_BOOTSTRAP_DISTANCE* 2 2) ".")) - (princ "\nAdded vfd_count from VFD_v2 (unique P_TAG1 values per conveyor_key).") + (princ "\nIncluded=1 => geometry. Included=0 => VFD-only (no TPE geometry).") + (princ "\nReason + is_last_* columns added to support spur/merge rules in Godot.") ) ) ) ) - (princ) ) diff --git a/generate_scene.py b/generate_scene.py index f5c5470..f36568b 100644 --- a/generate_scene.py +++ b/generate_scene.py @@ -24,7 +24,7 @@ def transform_from_points(x1, y1, x2, y2): angle = math.atan2(dy, dx) mid_x = (x1 + x2) / 2 * SCALE - mid_z = (y1 + y2) / 2 * SCALE + mid_z = (y1 + y2) / 2 * SCALE # if you need flip: mid_z = -(y1 + y2)/2 * SCALE return { "length": length, @@ -46,18 +46,45 @@ def transform3d(rot_y, x, y, z): # READ CSV # ----------------------- conveyors = [] +skipped = [] # (key, reason) + +def is_blank(v): + return v is None or str(v).strip() == "" with open(CSV_PATH, newline="") as f: reader = csv.DictReader(f) for row in reader: - conv = transform_from_points( - float(row["start_x"]), - float(row["start_y"]), - float(row["end_x"]), - float(row["end_y"]), - ) - conv["name"] = row["conveyor_key"] - conveyors.append(conv) + key = (row.get("conveyor_key") or "").strip() + + included = (row.get("included") or "1").strip() + if included == "0": + skipped.append((key, "included=0 (no geometry)")) + continue + + # guard against blank coords + for col in ("start_x", "start_y", "end_x", "end_y"): + if is_blank(row.get(col)): + skipped.append((key, f"blank {col}")) + break + else: + try: + x1 = float(row["start_x"]) + y1 = float(row["start_y"]) + x2 = float(row["end_x"]) + y2 = float(row["end_y"]) + except ValueError as e: + skipped.append((key, f"float parse error: {e}")) + continue + + conv = transform_from_points(x1, y1, x2, y2) + conv["name"] = key + conveyors.append(conv) + +# optional: write a simple report so you can see what spurs are missing +Path("skipped_conveyors.txt").write_text( + "\n".join([f"{k}\t{r}" for k, r in skipped]), + encoding="utf-8" +) # ----------------------- # WRITE TSCN @@ -72,13 +99,11 @@ lines.append('') lines.append('[node name="GeneratedConveyors" type="Node3D"]') lines.append('') -for i, c in enumerate(conveyors, start=1): +for c in conveyors: x, y, z = c["pos"] t = transform3d(c["rot_y"], x, y, z) - lines.append( - f'[node name="{c["name"]}" parent="." instance=ExtResource("{BELT_RESOURCE_ID}")]' - ) + lines.append(f'[node name="{c["name"]}" parent="." instance=ExtResource("{BELT_RESOURCE_ID}")]') lines.append(f"transform = {t}") lines.append("right_side_guards_enabled = false") lines.append("left_side_guards_enabled = false") @@ -86,10 +111,9 @@ for i, c in enumerate(conveyors, start=1): lines.append("tail_end_leg_enabled = false") lines.append("enable_comms = true") lines.append(f'speed_tag_name = "{c["name"]}_OIP"') - lines.append( - f"size = Vector3({c['length']:.6f}, 0.5, 1.524)" - ) + lines.append(f"size = Vector3({c['length']:.6f}, 0.5, 1.524)") lines.append("") -Path(OUT_TSCN).write_text("\n".join(lines)) +Path(OUT_TSCN).write_text("\n".join(lines), encoding="utf-8") print(f"Generated: {OUT_TSCN}") +print(f"Skipped: {len(skipped)} (see skipped_conveyors.txt)") diff --git a/generated_conveyors.tscn b/generated_conveyors.tscn index 0a29fd8..f89ffd5 100644 --- a/generated_conveyors.tscn +++ b/generated_conveyors.tscn @@ -155,34 +155,44 @@ speed_tag_name = "UL1_10_OIP" size = Vector3(15.752119, 0.5, 1.524) [node name="UL1_11" parent="." instance=ExtResource("3_38ygf")] -transform = Transform3D(0.9981282001527524, 0, -0.0611563247737067, 0, 1, 0, 0.0611563247737067, 0, 0.9981282001527524, 70.29272050140001, 2.5, 46.173259317) +transform = Transform3D(0.999987533426502, 0, -0.004993294661893442, 0, 1, 0, 0.004993294661893442, 0, 0.999987533426502, 69.14804775900001, 2.5, 45.9868607439) right_side_guards_enabled = false left_side_guards_enabled = false head_end_leg_enabled = false tail_end_leg_enabled = false enable_comms = true speed_tag_name = "UL1_11_OIP" -size = Vector3(6.433163, 0.5, 1.524) +size = Vector3(4.131827, 0.5, 1.524) [node name="UL1_12" parent="." instance=ExtResource("3_38ygf")] -transform = Transform3D(-0.9935026741492011, 0, 0.11380877144748693, 0, 1, 0, -0.11380877144748693, 0, -0.9935026741492011, 72.1300940809, 2.5, 46.212670846) +transform = Transform3D(0.9869995429660313, 0, -0.1607230605260031, 0, 1, 0, 0.1607230605260031, 0, 0.9869995429660313, 72.3586082162, 2.5, 46.183575031699995) right_side_guards_enabled = false left_side_guards_enabled = false head_end_leg_enabled = false tail_end_leg_enabled = false enable_comms = true speed_tag_name = "UL1_12_OIP" -size = Vector3(2.764335, 0.5, 1.524) +size = Vector3(2.319500, 0.5, 1.524) [node name="UL1_13" parent="." instance=ExtResource("3_38ygf")] -transform = Transform3D(0.9993630900498375, 0, -0.03568493023729351, 0, 1, 0, 0.03568493023729351, 0, 0.9993630900498375, 73.7086962196, 2.5, 46.160769603599995) +transform = Transform3D(0.9994599571489898, 0, 0.03286021995878083, 0, 1, 0, -0.03286021995878083, 0, 0.9994599571489898, 75.0818830973, 2.5, 46.318072362399995) right_side_guards_enabled = false left_side_guards_enabled = false head_end_leg_enabled = false tail_end_leg_enabled = false enable_comms = true speed_tag_name = "UL1_13_OIP" -size = Vector3(5.907340, 0.5, 1.524) +size = Vector3(3.158910, 0.5, 1.524) + +[node name="UL1_14" parent="." instance=ExtResource("3_38ygf")] +transform = Transform3D(0.9996888748277157, 0, 0.02494300594747222, 0, 1, 0, -0.02494300594747222, 0, 0.9996888748277157, 80.2158087324, 2.5, 46.3145923211) +right_side_guards_enabled = false +left_side_guards_enabled = false +head_end_leg_enabled = false +tail_end_leg_enabled = false +enable_comms = true +speed_tag_name = "UL1_14_OIP" +size = Vector3(6.288208, 0.5, 1.524) [node name="UL2_3" parent="." instance=ExtResource("3_38ygf")] transform = Transform3D(0.9952852133168667, 0, 0.09699146432959523, 0, 1, 0, -0.09699146432959523, 0, 0.9952852133168667, 18.508732134099997, 2.5, 50.6883424382) @@ -414,6 +424,16 @@ enable_comms = true speed_tag_name = "UL4_10_OIP" size = Vector3(14.120969, 0.5, 1.524) +[node name="UL4_11" parent="." instance=ExtResource("3_38ygf")] +transform = Transform3D(0.9971349340123079, 0, -0.07564339609159712, 0, 1, 0, 0.07564339609159712, 0, 0.9971349340123079, 67.0065149199, 2.5, 58.7853955735) +right_side_guards_enabled = false +left_side_guards_enabled = false +head_end_leg_enabled = false +tail_end_leg_enabled = false +enable_comms = true +speed_tag_name = "UL4_11_OIP" +size = Vector3(4.110799, 0.5, 1.524) + [node name="UL4_12" parent="." instance=ExtResource("3_38ygf")] transform = Transform3D(0.9994129903588115, 0, -0.03425893609057608, 0, 1, 0, 0.03425893609057608, 0, 0.9994129903588115, 70.2880283467, 2.5, 58.98310486819999) right_side_guards_enabled = false @@ -434,6 +454,16 @@ enable_comms = true speed_tag_name = "UL4_13_OIP" size = Vector3(2.515672, 0.5, 1.524) +[node name="UL4_14" parent="." instance=ExtResource("3_38ygf")] +transform = Transform3D(0.9998726772810103, 0, -0.01595710584362971, 0, 1, 0, 0.01595710584362971, 0, 0.9998726772810103, 77.0090436829, 2.5, 58.934440093800006) +right_side_guards_enabled = false +left_side_guards_enabled = false +head_end_leg_enabled = false +tail_end_leg_enabled = false +enable_comms = true +speed_tag_name = "UL4_14_OIP" +size = Vector3(5.405995, 0.5, 1.524) + [node name="UL5_3" parent="." instance=ExtResource("3_38ygf")] transform = Transform3D(0.9974065210227826, 0, -0.0719738273348684, 0, 1, 0, 0.0719738273348684, 0, 0.9974065210227826, 18.419276305900002, 2.5, 62.65324851849999) right_side_guards_enabled = false diff --git a/skipped_conveyors.txt b/skipped_conveyors.txt new file mode 100644 index 0000000..12d0ec4 --- /dev/null +++ b/skipped_conveyors.txt @@ -0,0 +1,12 @@ +UL2_6 included=0 (no geometry) +UL3_4 included=0 (no geometry) +PS1_1 included=0 (no geometry) +PS2_4 included=0 (no geometry) +PS1_3 included=0 (no geometry) +PS2_1 included=0 (no geometry) +UL5_6 included=0 (no geometry) +UL2_11 included=0 (no geometry) +UL3_10 included=0 (no geometry) +UL5_11 included=0 (no geometry) +UL6_4 included=0 (no geometry) +UL6_10 included=0 (no geometry) \ No newline at end of file