@yumiai/chat-widget 0.1.2 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. package/CHANGELOG.md +100 -0
  2. package/README.md +119 -22
  3. package/dist/ExcelCore-DJOIVQMI.js +11 -0
  4. package/dist/ExcelCore-DJOIVQMI.js.map +1 -0
  5. package/dist/ExcelViewer-3YLLYYIQ.js +65 -0
  6. package/dist/ExcelViewer-3YLLYYIQ.js.map +1 -0
  7. package/dist/GerberViewerA2UI-7CNT7HX4.css +693 -0
  8. package/dist/GerberViewerA2UI-7CNT7HX4.css.map +1 -0
  9. package/dist/GerberViewerA2UI-X5FWAD5M.js +57 -0
  10. package/dist/GerberViewerA2UI-X5FWAD5M.js.map +1 -0
  11. package/dist/GraphStatsLegend-D5bPeXB_.d.cts +607 -0
  12. package/dist/GraphStatsLegend-D5bPeXB_.d.ts +607 -0
  13. package/dist/JsonRenderStandalone-EIZM62JU.js +18 -0
  14. package/dist/JsonRenderStandalone-EIZM62JU.js.map +1 -0
  15. package/dist/JsonRenderStandalone-POB4Q3N3.css +2384 -0
  16. package/dist/JsonRenderStandalone-POB4Q3N3.css.map +1 -0
  17. package/dist/JsonRenderStandalone-UsTcST4G.d.cts +23 -0
  18. package/dist/JsonRenderStandalone-UsTcST4G.d.ts +23 -0
  19. package/dist/KicadViewer-GV6ZC4AQ.js +124 -0
  20. package/dist/KicadViewer-GV6ZC4AQ.js.map +1 -0
  21. package/dist/KicadViewerCore-U7BWZHKJ.js +11 -0
  22. package/dist/KicadViewerCore-U7BWZHKJ.js.map +1 -0
  23. package/dist/PdfViewer-CHPDRK46.js +51 -0
  24. package/dist/PdfViewer-CHPDRK46.js.map +1 -0
  25. package/dist/PdfViewer-LPYGQETK.css +1899 -0
  26. package/dist/PdfViewer-LPYGQETK.css.map +1 -0
  27. package/dist/PdfViewerCore-HJPEHSRA.js +364 -0
  28. package/dist/PdfViewerCore-HJPEHSRA.js.map +1 -0
  29. package/dist/PowerPointCore-FPDR2BL4.js +11 -0
  30. package/dist/PowerPointCore-FPDR2BL4.js.map +1 -0
  31. package/dist/PowerPointViewer-LQTO6UCU.js +61 -0
  32. package/dist/PowerPointViewer-LQTO6UCU.js.map +1 -0
  33. package/dist/StepViewerCore-7W3L3R4E.js +285 -0
  34. package/dist/StepViewerCore-7W3L3R4E.js.map +1 -0
  35. package/dist/ThreeViewerCore-N3QJD5QI.js +161 -0
  36. package/dist/ThreeViewerCore-N3QJD5QI.js.map +1 -0
  37. package/dist/WordCore-JKSXK2XD.js +11 -0
  38. package/dist/WordCore-JKSXK2XD.js.map +1 -0
  39. package/dist/WordViewer-ZHCQMHOH.js +61 -0
  40. package/dist/WordViewer-ZHCQMHOH.js.map +1 -0
  41. package/dist/chunk-2SKA3F5U.js +88 -0
  42. package/dist/chunk-2SKA3F5U.js.map +1 -0
  43. package/dist/chunk-2UC7YLVX.js +318 -0
  44. package/dist/chunk-2UC7YLVX.js.map +1 -0
  45. package/dist/chunk-3R6T3LBR.js +24 -0
  46. package/dist/chunk-3R6T3LBR.js.map +1 -0
  47. package/dist/chunk-56WRZM3R.js +398 -0
  48. package/dist/chunk-56WRZM3R.js.map +1 -0
  49. package/dist/chunk-7A4FY6FK.js +10226 -0
  50. package/dist/chunk-7A4FY6FK.js.map +1 -0
  51. package/dist/chunk-7D4SUZUM.js +38 -0
  52. package/dist/chunk-7D4SUZUM.js.map +1 -0
  53. package/dist/chunk-7S67DOHQ.js +436 -0
  54. package/dist/chunk-7S67DOHQ.js.map +1 -0
  55. package/dist/chunk-CFKGNAJM.js +14013 -0
  56. package/dist/chunk-CFKGNAJM.js.map +1 -0
  57. package/dist/chunk-GAMA3VA7.js +99 -0
  58. package/dist/chunk-GAMA3VA7.js.map +1 -0
  59. package/dist/chunk-GYXTSY22.js +639 -0
  60. package/dist/chunk-GYXTSY22.js.map +1 -0
  61. package/dist/chunk-K4KGNVL5.js +77 -0
  62. package/dist/chunk-K4KGNVL5.js.map +1 -0
  63. package/dist/chunk-KQV7IKET.js +1621 -0
  64. package/dist/chunk-KQV7IKET.js.map +1 -0
  65. package/dist/chunk-O3NXUM6C.js +1871 -0
  66. package/dist/chunk-O3NXUM6C.js.map +1 -0
  67. package/dist/chunk-PZXSASDY.js +83 -0
  68. package/dist/chunk-PZXSASDY.js.map +1 -0
  69. package/dist/chunk-QLVPIM6R.js +595 -0
  70. package/dist/chunk-QLVPIM6R.js.map +1 -0
  71. package/dist/chunk-VXJWGLZ7.js +21 -0
  72. package/dist/chunk-VXJWGLZ7.js.map +1 -0
  73. package/dist/chunk-XQ562W7I.js +116 -0
  74. package/dist/chunk-XQ562W7I.js.map +1 -0
  75. package/dist/components/JsonRender/standalone.cjs +39368 -0
  76. package/dist/components/JsonRender/standalone.cjs.map +1 -0
  77. package/dist/components/JsonRender/standalone.css +2384 -0
  78. package/dist/components/JsonRender/standalone.css.map +1 -0
  79. package/dist/components/JsonRender/standalone.d.cts +16 -0
  80. package/dist/components/JsonRender/standalone.d.ts +16 -0
  81. package/dist/components/JsonRender/standalone.js +38 -0
  82. package/dist/components/JsonRender/standalone.js.map +1 -0
  83. package/dist/gerber-2d-entry-OQ4SQRBY.js +3950 -0
  84. package/dist/gerber-2d-entry-OQ4SQRBY.js.map +1 -0
  85. package/dist/gerber-3d-entry-DEHDBOO2.js +3679 -0
  86. package/dist/gerber-3d-entry-DEHDBOO2.js.map +1 -0
  87. package/dist/gerber-simulation-entry-EBDX72XE.js +1801 -0
  88. package/dist/gerber-simulation-entry-EBDX72XE.js.map +1 -0
  89. package/dist/index.cjs +60113 -2970
  90. package/dist/index.cjs.map +1 -1
  91. package/dist/index.css +11342 -1708
  92. package/dist/index.css.map +1 -1
  93. package/dist/index.d.cts +3275 -77
  94. package/dist/index.d.ts +3275 -77
  95. package/dist/index.js +18078 -2540
  96. package/dist/index.js.map +1 -1
  97. package/dist/provenance/index.cjs +2248 -0
  98. package/dist/provenance/index.cjs.map +1 -0
  99. package/dist/provenance/index.css +52 -0
  100. package/dist/provenance/index.css.map +1 -0
  101. package/dist/provenance/index.d.cts +12 -0
  102. package/dist/provenance/index.d.ts +12 -0
  103. package/dist/provenance/index.js +27 -0
  104. package/dist/provenance/index.js.map +1 -0
  105. package/dist/resolveToArrayBuffer-AQIDZHSQ.js +23 -0
  106. package/dist/resolveToArrayBuffer-AQIDZHSQ.js.map +1 -0
  107. package/package.json +98 -17
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/jetPaveGerberViewer/src/viewer-src/3dPage/js/gerber-parser.js"],"sourcesContent":["/**\n * Gerber 文件解析器\n * 将 Gerber 文件解析为 WebGL 可用的数据格式\n */\n\nimport { parse, plot, renderSVG } from 'web-gerber'\n\n// 调试模式开关 - 设为 false 可禁用所有调试日志,提升性能\nconst DEBUG_MODE = true;\nconst debugLog = DEBUG_MODE ? console.log.bind(console) : () => {};\n\nexport class GerberParser {\n // 存储从Gerber文件中提取的格式信息,供钻孔文件使用\n static gerberFormatInfo = null\n\n /**\n * 读取文件为文本\n */\n static async readFileAsText(file) {\n return new Promise((resolve, reject) => {\n const reader = new FileReader()\n reader.onload = (event) => resolve(event.target.result)\n reader.onerror = (error) => reject(new Error('读取文件失败: ' + error.message))\n reader.readAsText(file)\n })\n }\n\n /**\n * 解析 Gerber 文件\n * @param {File} file - Gerber 文件\n * @param {string} color - 图层颜色\n * @returns {Promise<{data: Object, bounds: Object}>} - 解析后的数据\n */\n /**\n * 检查文件扩展名是否是 TX/TX+数字 格式(如 .txt, .tx1, .tx2 等)\n */\n static isTxFileExtension(extension) {\n return extension === '.txt' || /^\\.tx\\d+$/i.test(extension)\n }\n\n static async parseFile(file, color) {\n // 重置调试计数器\n GerberParser._debugPathCount = 0\n \n // 提取文件名(去掉路径,只保留文件名部分)\n // 处理 Windows 路径 (\\) 和 Unix 路径 (/)\n const fileNameOnly = file.name.split(/[/\\\\]/).pop()\n const fileNameUpper = fileNameOnly.toUpperCase()\n \n // 检查文件名是否有扩展名\n const lastDotIndex = fileNameOnly.lastIndexOf('.')\n let fileExtension = ''\n if (lastDotIndex > 0 && lastDotIndex < fileNameOnly.length - 1) {\n // 有扩展名\n fileExtension = '.' + fileNameOnly.substring(lastDotIndex + 1).toLowerCase()\n } else {\n // 没有扩展名,检查是否是特殊格式(如 _INT1, _INT2 等)\n if (/.*_INT\\d+$/i.test(fileNameUpper)) {\n // 文件名包含 _INT+数字,但没有扩展名,当作 Gerber 文件处理\n fileExtension = ''\n } else {\n // 没有扩展名且不是特殊格式,使用整个文件名作为扩展名(向后兼容)\n fileExtension = '.' + fileNameOnly.toLowerCase()\n }\n }\n \n // 读取文件内容\n let gerberStr\n let isDrillFile = fileExtension === '.drl' || fileExtension === '.d' // .d 也是 DRL 文件\n let detectedFormat = null // 在外部定义,以便在整个函数中访问\n \n // 检查是否是 DRL 或 TX/TX+数字 文件(在函数作用域内定义,确保整个函数可用)\n const isTxFile = this.isTxFileExtension(fileExtension)\n // .txt扩展名且含有M48也是钻孔文件\n const isTxtDrillFile = fileExtension === '.txt'\n if (fileExtension === '.drl' || fileExtension === '.d' || isTxFile || isTxtDrillFile) {\n // DRL、TXT 或 TX+数字 文件特殊处理\n try {\n gerberStr = await this.readFileAsText(file)\n \n // 检查 TX/TX+数字 文件、.d 文件或 .txt 文件是否是 Excellon 钻孔文件\n // 关键修复:Excellon 文件可能首行是 M72/M71(单位指令),M48 在第二行或更靠后\n // 需要扫描前 N 行,而不是只检查首行\n if (isTxFile || fileExtension === '.d' || isTxtDrillFile) {\n const trimmedContent = gerberStr.trim()\n // 扫描前 20 行,检查是否包含 M48 或 M72/M71+Txx(典型 Excellon 特征)\n const headerLines = trimmedContent\n .split(/\\r?\\n/)\n .slice(0, 20)\n .map(line => line.trim())\n .filter(Boolean)\n const hasM48InHeader = headerLines.some(line => /^M48$/i.test(line))\n const hasM71M72InHeader = headerLines.some(line => /^M7[12]$/i.test(line))\n const hasToolDefInHeader = headerLines.some(line => /^T\\d+/i.test(line))\n // Excellon 钻孔文件特征:有 M48,或同时有 M71/M72 和工具定义\n const isExcellonFile = hasM48InHeader || (hasM71M72InHeader && hasToolDefInHeader)\n \n if ((isTxFile && isExcellonFile) || fileExtension === '.d' || fileExtension === '.drl' || (isTxtDrillFile && isExcellonFile)) {\n if (isTxFile || isTxtDrillFile) {\n const fileTypeName = fileExtension.toUpperCase()\n console.log(`[钻孔识别] ${file.name} 是 Excellon 钻孔文件 (M48=${hasM48InHeader}, M71/M72=${hasM71M72InHeader})`)\n } else if (fileExtension === '.drl') {\n debugLog(`检测到 .drl 文件 ${file.name} 是钻孔文件`)\n } else {\n debugLog(`检测到 .d 文件 ${file.name} 是钻孔文件`)\n }\n isDrillFile = true\n \n // 提取格式信息\n const lines = gerberStr.split('\\n').map(line => line.trim())\n let hasFileFormat = false\n \n for (const line of lines) {\n // 检测坐标格式:FILE_FORMAT=X:Y (X位整数,Y位小数)\n const formatMatch = line.match(/FILE_FORMAT[=:](\\d+)[:.](\\d+)/i)\n if (formatMatch) {\n hasFileFormat = true\n detectedFormat = detectedFormat || {}\n const integerPlaces = parseInt(formatMatch[1])\n const decimalPlaces = parseInt(formatMatch[2])\n const totalPlaces = integerPlaces + decimalPlaces\n detectedFormat.places = [integerPlaces, decimalPlaces]\n detectedFormat.integerPlaces = integerPlaces\n detectedFormat.decimalPlaces = decimalPlaces\n detectedFormat.totalPlaces = totalPlaces\n debugLog(`检测到坐标格式: ${integerPlaces}:${decimalPlaces} (${integerPlaces}位整数, ${decimalPlaces}位小数, 总共${totalPlaces}位)`)\n \n // 如果检测到FILE_FORMAT,才使用文件中的单位和零格式\n // 检测单位:INCH 或 METRIC\n if (line.includes('INCH')) {\n detectedFormat.unit = 'inch'\n debugLog('检测到单位: INCH')\n } else if (line.includes('METRIC')) {\n detectedFormat.unit = 'metric'\n debugLog('检测到单位: METRIC')\n }\n \n // 检测零格式:TZ (Trailing Zeros) 或 LZ (Leading Zeros)\n if (line.includes(',TZ') || line.includes('TZ,')) {\n detectedFormat.zero = 'T'\n debugLog('检测到零格式: TZ (Trailing Zeros)')\n } else if (line.includes(',LZ') || line.includes('LZ,')) {\n detectedFormat.zero = 'L'\n debugLog('检测到零格式: LZ (Leading Zeros)')\n }\n }\n }\n \n // 如果没有检测到FILE_FORMAT,尝试从 FMAT 和单位/零格式信息推断\n if (!hasFileFormat) {\n // 检查是否有 FMAT,2 和 INCH,TZ 等格式信息\n let hasFmat2 = false\n let hasInchTz = false\n let hasMetricLz = false\n \n for (const line of lines) {\n if (line.match(/FMAT\\s*,?\\s*2/i)) {\n hasFmat2 = true\n }\n if (line.match(/INCH\\s*,\\s*TZ/i) || line.match(/TZ\\s*,\\s*INCH/i)) {\n hasInchTz = true\n }\n if (line.match(/METRIC\\s*,\\s*LZ/i) || line.match(/LZ\\s*,\\s*METRIC/i)) {\n hasMetricLz = true\n }\n // 单独检测单位和零格式\n if (line.match(/^INCH/i) || line.includes('INCH,') || line.includes(',INCH')) {\n detectedFormat = detectedFormat || {}\n detectedFormat.unit = 'inch'\n }\n if (line.match(/^METRIC/i) || line.includes('METRIC,') || line.includes(',METRIC')) {\n detectedFormat = detectedFormat || {}\n detectedFormat.unit = 'metric'\n }\n // 关键修复:M72 = 英寸单位,M71 = 毫米单位(Excellon 常见首行指令)\n if (line.match(/^M72$/i)) {\n detectedFormat = detectedFormat || {}\n detectedFormat.unit = 'inch'\n }\n if (line.match(/^M71$/i)) {\n detectedFormat = detectedFormat || {}\n detectedFormat.unit = 'metric'\n }\n if (line.includes(',TZ') || line.includes('TZ,') || line.match(/^TZ$/i)) {\n detectedFormat = detectedFormat || {}\n detectedFormat.zero = 'T'\n }\n if (line.includes(',LZ') || line.includes('LZ,') || line.match(/^LZ$/i)) {\n detectedFormat = detectedFormat || {}\n detectedFormat.zero = 'L'\n }\n }\n \n // 优先使用 Gerber 文件的格式(如果可用且合理)\n if (GerberParser.gerberFormatInfo && GerberParser.gerberFormatInfo.places) {\n detectedFormat = detectedFormat || {}\n detectedFormat.places = GerberParser.gerberFormatInfo.places\n detectedFormat.integerPlaces = GerberParser.gerberFormatInfo.integerPlaces\n detectedFormat.decimalPlaces = GerberParser.gerberFormatInfo.decimalPlaces\n detectedFormat.totalPlaces = GerberParser.gerberFormatInfo.totalPlaces\n detectedFormat.unit = detectedFormat.unit || GerberParser.gerberFormatInfo.unit || 'inch'\n // 关键修复:零抑制默认值改为 LZ(与 2dPage 一致),优先继承 Gerber 的设置\n detectedFormat.zero = detectedFormat.zero || GerberParser.gerberFormatInfo.zero || 'L'\n console.log(`[格式继承] ${file.name}: 继承 Gerber 格式 ${detectedFormat.integerPlaces}:${detectedFormat.decimalPlaces}, 单位=${detectedFormat.unit}, 零格式=${detectedFormat.zero === 'L' ? 'LZ' : 'TZ'}`)\n } else if (hasFmat2 || hasInchTz) {\n detectedFormat = detectedFormat || {}\n // 使用 2:4 格式作为默认(常见的 Excellon INCH 格式)\n detectedFormat.places = [2, 4]\n detectedFormat.integerPlaces = 2\n detectedFormat.decimalPlaces = 4\n detectedFormat.totalPlaces = 6\n detectedFormat.unit = detectedFormat.unit || 'inch'\n // 如果明确检测到 INCH,TZ 则用 TZ,否则默认 LZ\n detectedFormat.zero = detectedFormat.zero || (hasInchTz ? 'T' : 'L')\n console.log(`[格式推断] ${file.name}: FMAT,2/INCH 格式 2:4, 单位=${detectedFormat.unit}, 零格式=${detectedFormat.zero === 'L' ? 'LZ' : 'TZ'}`)\n } else if (hasMetricLz) {\n detectedFormat = detectedFormat || {}\n // 使用 3:3 格式作为默认(常见的 Excellon METRIC 格式)\n detectedFormat.places = [3, 3]\n detectedFormat.integerPlaces = 3\n detectedFormat.decimalPlaces = 3\n detectedFormat.totalPlaces = 6\n detectedFormat.unit = 'metric'\n detectedFormat.zero = 'L'\n debugLog(`[FMAT格式] 检测到 METRIC,LZ,使用默认 3:3 格式 (6位)`)\n } else if (GerberParser.gerberFormatInfo) {\n detectedFormat = detectedFormat || {}\n detectedFormat.places = GerberParser.gerberFormatInfo.places\n detectedFormat.integerPlaces = GerberParser.gerberFormatInfo.integerPlaces\n detectedFormat.decimalPlaces = GerberParser.gerberFormatInfo.decimalPlaces\n detectedFormat.totalPlaces = GerberParser.gerberFormatInfo.totalPlaces\n // 完全使用Gerber文件的零格式,默认 LZ(与 2dPage 一致)\n detectedFormat.zero = detectedFormat.zero || GerberParser.gerberFormatInfo.zero || 'L'\n // 完全使用Gerber文件的单位\n detectedFormat.unit = detectedFormat.unit || GerberParser.gerberFormatInfo.unit || 'inch'\n console.log(`[格式继承] ${file.name}: 无FILE_FORMAT,继承 Gerber 格式 ${detectedFormat.integerPlaces}:${detectedFormat.decimalPlaces}, 单位=${detectedFormat.unit}, 零格式=${detectedFormat.zero === 'L' ? 'LZ' : 'TZ'}`)\n } else {\n console.warn(`[格式警告] ${file.name}: 没有FILE_FORMAT,且没有可用的Gerber格式信息`)\n }\n }\n }\n }\n \n // 检查是否是二进制文件\n const printableChars = gerberStr.split('').filter(char => {\n const code = char.charCodeAt(0)\n return (code >= 32 && code <= 126) || code === 10 || code === 13 || code === 9\n }).length\n const printableRatio = printableChars / gerberStr.length\n \n if (printableRatio < 0.5) {\n // 尝试使用 ArrayBuffer 读取\n const arrayBuffer = await file.arrayBuffer()\n try {\n const decoder = new TextDecoder('utf-8', { fatal: false, ignoreBOM: true })\n gerberStr = decoder.decode(arrayBuffer)\n } catch (e) {\n const decoder = new TextDecoder('latin1', { fatal: false })\n gerberStr = decoder.decode(arrayBuffer)\n }\n }\n } catch (e) {\n gerberStr = await this.readFileAsText(file)\n }\n } else {\n gerberStr = await this.readFileAsText(file)\n }\n \n if (!gerberStr || gerberStr.trim().length === 0) {\n throw new Error(`文件 ${file.name} 内容为空`)\n }\n \n // 对于非钻孔文件(Gerber文件),提取格式信息(FSLAX25Y25)并保存\n // 供钻孔文件在没有FILE_FORMAT时使用\n if (!isDrillFile) {\n const fslaMatch = gerberStr.match(/%FSLAX(\\d+)(\\d+)Y(\\d+)(\\d+)\\*%/i)\n if (fslaMatch) {\n const xIntegerPlaces = parseInt(fslaMatch[1])\n const xDecimalPlaces = parseInt(fslaMatch[2])\n const yIntegerPlaces = parseInt(fslaMatch[3])\n const yDecimalPlaces = parseInt(fslaMatch[4])\n \n // 通常X和Y的格式相同,使用X的格式\n const formatInfo = {\n integerPlaces: xIntegerPlaces,\n decimalPlaces: xDecimalPlaces,\n totalPlaces: xIntegerPlaces + xDecimalPlaces,\n places: [xIntegerPlaces, xDecimalPlaces],\n unit: gerberStr.includes('%MOIN*%') ? 'inch' : 'metric',\n zero: gerberStr.includes('%FSLAX') ? 'L' : 'T' // FSLA表示前导零省略(LZ),FSLT表示尾部零省略(TZ)\n }\n \n // 保存格式信息:1. 供后续钻孔文件使用 2. 供当前文件使用\n GerberParser.gerberFormatInfo = formatInfo\n // 同时保存到临时变量,供当前文件的解析使用\n GerberParser.currentFileFormatInfo = formatInfo\n \n debugLog(`[格式提取] 从Gerber文件 ${file.name} 提取格式信息: ${xIntegerPlaces}位整数, ${xDecimalPlaces}位小数`)\n }\n }\n \n // 对于 LZ 格式,尝试两种方式:\n // 方式1: 不补0,直接让web-gerber库处理LZ格式(推荐,让库自己处理)\n // 方式2: 补0到总位数,然后使用TZ格式解析\n // 我们先保存原始内容,然后尝试方式1,如果失败再尝试方式2\n const originalGerberStr = gerberStr // 保存原始内容\n let hasPadded = false // 记录是否进行了补0预处理\n let paddedGerberStr = null // 保存补0后的内容\n \n if (isDrillFile && detectedFormat && detectedFormat.totalPlaces && detectedFormat.zero === 'L') {\n const totalPlaces = detectedFormat.totalPlaces\n debugLog(`[DRL调试] 检测到LZ格式,FILE_FORMAT=${detectedFormat.integerPlaces}:${detectedFormat.decimalPlaces}`)\n debugLog(`[DRL调试] 检测到的格式:`, {\n integerPlaces: detectedFormat.integerPlaces,\n decimalPlaces: detectedFormat.decimalPlaces,\n totalPlaces: detectedFormat.totalPlaces,\n zero: detectedFormat.zero,\n unit: detectedFormat.unit\n })\n \n // 统计处理前的坐标数量\n const coordMatchesBefore = gerberStr.match(/([XY])(\\d+)/g) || []\n debugLog(`[DRL调试] 处理前找到 ${coordMatchesBefore.length} 个坐标值`)\n if (coordMatchesBefore.length > 0 && coordMatchesBefore.length <= 10) {\n debugLog(`[DRL调试] 前几个坐标值:`, coordMatchesBefore.slice(0, 5))\n }\n \n // 准备补0后的内容(但不立即使用,先尝试不补0的方式)\n let replaceCount = 0\n paddedGerberStr = gerberStr.replace(/([XY])(\\d+)/g, (match, coord, num) => {\n // 如果数字位数不足总位数,前面补0\n if (num.length < totalPlaces) {\n const paddedNum = num.padStart(totalPlaces, '0')\n if (replaceCount < 5) {\n debugLog(`[DRL调试] 坐标值 ${coord}${num} -> ${coord}${paddedNum} (前补0到${totalPlaces}位)`)\n }\n replaceCount++\n return `${coord}${paddedNum}`\n }\n return match\n })\n \n debugLog(`[DRL调试] 坐标值预处理完成,共处理 ${replaceCount} 个坐标值`)\n if (replaceCount > 0) {\n hasPadded = true\n // 统计处理后的坐标数量\n const coordMatchesAfter = paddedGerberStr.match(/([XY])(\\d+)/g) || []\n debugLog(`[DRL调试] 补0后找到 ${coordMatchesAfter.length} 个坐标值`)\n if (coordMatchesAfter.length > 0 && coordMatchesAfter.length <= 10) {\n debugLog(`[DRL调试] 前几个补0后的坐标值:`, coordMatchesAfter.slice(0, 5))\n }\n }\n } else if (isDrillFile && detectedFormat) {\n debugLog(`[DRL调试] 检测到的格式信息:`, {\n integerPlaces: detectedFormat.integerPlaces,\n decimalPlaces: detectedFormat.decimalPlaces,\n totalPlaces: detectedFormat.totalPlaces,\n zero: detectedFormat.zero,\n unit: detectedFormat.unit\n })\n if (detectedFormat.zero !== 'L') {\n debugLog(`[DRL调试] 非 LZ 格式,不进行坐标预处理`)\n }\n }\n \n // 解析 Gerber 文件\n let parseResult\n let lastError = null\n if (isDrillFile) {\n // DRL/TX/TX+数字 钻孔文件尝试多种解析方式\n const fileTypeLabel = isTxFile ? `${fileExtension.toUpperCase()} (Excellon)` : 'DRL'\n debugLog(`尝试解析 ${fileTypeLabel} 文件 ${file.name}...`)\n debugLog(`文件内容预览(前200字符):`, gerberStr.substring(0, 200))\n \n // 【动态格式检测】对钻孔文件也应用同样的逻辑\n if (detectedFormat && detectedFormat.integerPlaces && detectedFormat.decimalPlaces) {\n const coordMatches = gerberStr.match(/[XY](-?\\d+)/g)\n if (coordMatches) {\n let maxDigits = 0\n for (const coord of coordMatches) {\n const digits = coord.substring(1).replace(/-/g, '').length\n maxDigits = Math.max(maxDigits, digits)\n }\n \n const definedDigits = detectedFormat.integerPlaces + detectedFormat.decimalPlaces\n debugLog(`[DRL格式检测] ${file.name} 定义格式: [${detectedFormat.integerPlaces}, ${detectedFormat.decimalPlaces}] (${definedDigits}位)`)\n debugLog(`[DRL格式检测] ${file.name} 实际最长坐标: ${maxDigits}位`)\n \n // 如果实际坐标位数超过定义位数,动态增加整数位\n if (maxDigits > definedDigits) {\n const extraDigits = maxDigits - definedDigits\n detectedFormat.integerPlaces += extraDigits\n detectedFormat.totalPlaces = detectedFormat.integerPlaces + detectedFormat.decimalPlaces\n detectedFormat.places = [detectedFormat.integerPlaces, detectedFormat.decimalPlaces]\n debugLog(`[DRL格式修正] ✓ 动态调整格式为: [${detectedFormat.integerPlaces}, ${detectedFormat.decimalPlaces}] (${maxDigits}位)`)\n \n // 修改文件内容中的 FILE_FORMAT 定义\n const oldFormatPattern = /FILE_FORMAT[=:]\\d+[:.]\\d+/i\n const newFormatStr = `FILE_FORMAT=${detectedFormat.integerPlaces}:${detectedFormat.decimalPlaces}`\n \n if (oldFormatPattern.test(gerberStr)) {\n gerberStr = gerberStr.replace(oldFormatPattern, newFormatStr)\n debugLog(`[DRL格式修正] ✓ 已修改文件格式定义 → ${newFormatStr}`)\n // 同时更新 paddedGerberStr(如果存在)\n if (paddedGerberStr) {\n paddedGerberStr = paddedGerberStr.replace(oldFormatPattern, newFormatStr)\n }\n }\n }\n }\n }\n \n // 尝试 1: 如果检测到格式信息,直接使用格式参数解析\n if (isTxFile && detectedFormat && detectedFormat.places) {\n // 尝试多种解析方式,按优先级排序\n const parseAttempts = []\n \n // 方式1: 不补0,直接使用LZ格式让库处理(推荐,让库自己处理LZ格式)\n parseAttempts.push({\n gerberStr: originalGerberStr, // 使用原始内容\n format: {\n places: detectedFormat.places,\n zero: detectedFormat.zero || 'T' // 使用原始检测到的格式(LZ)\n },\n description: '不补0,直接使用LZ格式'\n })\n \n // 方式2: 如果已补0,尝试使用TZ格式(补0后的坐标值已经是完整格式)\n if (hasPadded && paddedGerberStr) {\n parseAttempts.push({\n gerberStr: paddedGerberStr, // 使用补0后的内容\n format: {\n places: detectedFormat.places,\n zero: 'T' // 补0后使用TZ格式\n },\n description: '补0后使用TZ格式'\n })\n }\n \n // 方式3: 如果已补0,尝试不使用zero参数(让库自动处理)\n if (hasPadded && paddedGerberStr) {\n parseAttempts.push({\n gerberStr: paddedGerberStr, // 使用补0后的内容\n format: {\n places: detectedFormat.places\n // 不指定zero参数\n },\n description: '补0后不指定zero参数'\n })\n }\n \n // 方式4: 不补0,尝试不使用zero参数\n parseAttempts.push({\n gerberStr: originalGerberStr, // 使用原始内容\n format: {\n places: detectedFormat.places\n // 不指定zero参数\n },\n description: '不补0,不指定zero参数'\n })\n \n for (const attempt of parseAttempts) {\n try {\n const formatOptions = {\n type: 'drill',\n format: attempt.format\n }\n debugLog(`[DRL调试] 尝试解析方式: ${attempt.description}`, formatOptions.format)\n parseResult = parse(attempt.gerberStr, formatOptions)\n debugLog(`[DRL调试] ${fileTypeLabel} 文件使用 ${attempt.description} 解析成功`)\n debugLog(`[DRL调试] parseResult 类型:`, parseResult?.type)\n debugLog(`[DRL调试] parseResult 工具数量:`, parseResult?.tools ? Object.keys(parseResult.tools).length : 0)\n \n // 检查解析结果中是否有工具和孔\n if (parseResult?.tools && Object.keys(parseResult.tools).length > 0) {\n let totalHoles = 0\n for (const tool of Object.values(parseResult.tools)) {\n if (tool.holes) {\n totalHoles += tool.holes.length\n }\n }\n debugLog(`[DRL调试] 解析出的孔总数: ${totalHoles}`)\n }\n \n break // 解析成功,跳出循环\n } catch (e0) {\n lastError = e0\n debugLog(`[DRL调试] ${fileTypeLabel} 文件使用 ${attempt.description} 解析失败: ${e0.message}`)\n // 继续尝试下一种方式\n }\n }\n }\n \n // 如果上面的尝试失败或没有格式信息,尝试其他方法\n if (!parseResult) {\n // 尝试 1: 直接解析\n try {\n parseResult = parse(gerberStr)\n debugLog(`[DRL调试] ${fileTypeLabel} 文件直接解析成功`)\n debugLog(`[DRL调试] parseResult 类型:`, parseResult?.type)\n debugLog(`[DRL调试] parseResult 工具数量:`, parseResult?.tools ? Object.keys(parseResult.tools).length : 0)\n } catch (e1) {\n lastError = e1\n debugLog(`[DRL调试] ${fileTypeLabel} 文件直接解析失败: ${e1.message}`)\n \n // 尝试 2: 使用 drill 类型\n try {\n parseResult = parse(gerberStr, { type: 'drill' })\n debugLog(`${fileTypeLabel} 文件使用 drill 类型解析成功`)\n } catch (e2) {\n lastError = e2\n debugLog(`${fileTypeLabel} 文件使用 drill 类型解析失败: ${e2.message}`)\n \n // 尝试 2.5: 尝试不同的格式选项\n try {\n parseResult = parse(gerberStr, { \n type: 'drill',\n format: { \n places: [4, 5], // 常见的小数位数\n zero: 'L' // Leading zeros\n }\n })\n debugLog(`${fileTypeLabel} 文件使用格式参数解析成功`)\n } catch (e2_5) {\n lastError = e2_5\n debugLog(`${fileTypeLabel} 文件使用格式参数解析失败: ${e2_5.message}`)\n \n // 尝试 2.6: 对于 TX/TX+数字 文件,使用检测到的格式信息\n if (isTxFile && detectedFormat) {\n // 尝试多种格式组合\n const formatAttempts = []\n \n if (detectedFormat.places) {\n // 格式1: [整数位数, 小数位数] - 例如 [2, 5] 对于 FILE_FORMAT=2:5\n // 这是正确的格式,web-gerber 库期望的是 [整数位数, 小数位数]\n formatAttempts.push({\n places: detectedFormat.places,\n zero: detectedFormat.zero || 'T',\n description: `[整数位数${detectedFormat.integerPlaces}, 小数位数${detectedFormat.decimalPlaces}]`\n })\n \n debugLog(`[DRL调试] 将尝试使用格式: places=[${detectedFormat.places[0]}, ${detectedFormat.places[1]}], zero=${detectedFormat.zero || 'T'}`)\n }\n \n // 如果没有检测到格式,使用默认值\n if (formatAttempts.length === 0) {\n formatAttempts.push({\n places: [4, 5],\n zero: detectedFormat.zero || 'T',\n description: '默认格式[4, 5]'\n })\n debugLog(`[DRL调试] 未检测到格式,使用默认格式`)\n }\n \n let parsed = false\n for (const formatOption of formatAttempts) {\n try {\n const formatOptions = {\n type: 'drill',\n format: {\n places: formatOption.places,\n zero: formatOption.zero\n }\n }\n parseResult = parse(gerberStr, formatOptions)\n debugLog(`${fileTypeLabel} 文件使用格式 ${formatOption.description} 解析成功:`, formatOptions.format)\n parsed = true\n break\n } catch (e) {\n lastError = e\n debugLog(`${fileTypeLabel} 文件使用格式 ${formatOption.description} 解析失败: ${e.message}`)\n }\n }\n \n if (!parsed) {\n // 如果所有格式都失败,尝试默认的 TZ 格式\n try {\n parseResult = parse(gerberStr, { \n type: 'drill',\n format: { \n places: [4, 5],\n zero: 'T' // Trailing zeros\n }\n })\n debugLog(`${fileTypeLabel} 文件使用默认 TZ 格式解析成功`)\n parsed = true\n } catch (e2_6_default) {\n lastError = e2_6_default\n debugLog(`${fileTypeLabel} 文件使用默认 TZ 格式解析失败: ${e2_6_default.message}`)\n }\n }\n \n if (!parsed) {\n // 继续尝试其他方法\n // 尝试 3: 清理文件内容后解析(移除可能的控制字符)\n try {\n const cleanedStr = gerberStr.split('').filter(char => {\n const code = char.charCodeAt(0)\n return (code >= 32 && code <= 126) || code === 10 || code === 13 || code === 9\n }).join('')\n \n if (cleanedStr.length > 0) {\n parseResult = parse(cleanedStr, { type: 'drill' })\n debugLog(`${fileTypeLabel} 文件清理后解析成功`)\n } else {\n throw new Error('清理后文件内容为空')\n }\n } catch (e3) {\n lastError = e3\n debugLog(`${fileTypeLabel} 文件清理后解析失败: ${e3.message}`)\n \n // 尝试 4: 尝试提取可能的文本内容(更激进的清理)\n try {\n const aggressiveCleaned = gerberStr.split('').map(char => {\n const code = char.charCodeAt(0)\n if ((code >= 32 && code <= 126) || code === 10 || code === 13 || code === 9) {\n return char\n }\n return ' '\n }).join('').replace(/\\s+/g, ' ').trim()\n \n if (aggressiveCleaned.length > 10) {\n parseResult = parse(aggressiveCleaned, { type: 'drill' })\n debugLog(`${fileTypeLabel} 文件激进清理后解析成功`)\n } else {\n throw new Error('激进清理后内容不足')\n }\n } catch (e4) {\n lastError = e4\n debugLog(`${fileTypeLabel} 文件激进清理后解析失败: ${e4.message}`)\n \n // 尝试 5: 使用其他可能的类型\n const possibleTypes = ['outline', 'top', 'bottom', 'unknown']\n let parsed2 = false\n \n for (const type of possibleTypes) {\n try {\n parseResult = parse(gerberStr, { type: type })\n debugLog(`${fileTypeLabel} 文件使用 ${type} 类型解析成功`)\n parsed2 = true\n break\n } catch (e) {\n lastError = e\n }\n }\n \n if (!parsed2) {\n console.warn(`${fileTypeLabel} 文件 ${file.name} 无法被 web-gerber 解析`)\n throw new Error(`无法解析 ${fileTypeLabel} 文件 ${file.name}。文件可能是二进制格式(Excellon),web-gerber 仅支持文本格式的 Gerber 文件。已尝试多种方式,最后错误: ${lastError?.message || '未知错误'}`)\n }\n }\n }\n }\n } else {\n // 对于非 TXT 的 DRL 文件,继续原有逻辑\n // 尝试 3: 清理文件内容后解析(移除可能的控制字符)\n try {\n const cleanedStr = gerberStr.split('').filter(char => {\n const code = char.charCodeAt(0)\n return (code >= 32 && code <= 126) || code === 10 || code === 13 || code === 9\n }).join('')\n \n if (cleanedStr.length > 0) {\n parseResult = parse(cleanedStr)\n debugLog(`${fileTypeLabel} 文件清理后解析成功`)\n } else {\n throw new Error('清理后文件内容为空')\n }\n } catch (e3) {\n lastError = e3\n debugLog(`${fileTypeLabel} 文件清理后解析失败: ${e3.message}`)\n \n // 尝试 4: 尝试提取可能的文本内容(更激进的清理)\n try {\n const aggressiveCleaned = gerberStr.split('').map(char => {\n const code = char.charCodeAt(0)\n if ((code >= 32 && code <= 126) || code === 10 || code === 13 || code === 9) {\n return char\n }\n return ' '\n }).join('').replace(/\\s+/g, ' ').trim()\n \n if (aggressiveCleaned.length > 10) {\n parseResult = parse(aggressiveCleaned)\n debugLog(`${fileTypeLabel} 文件激进清理后解析成功`)\n } else {\n throw new Error('激进清理后内容不足')\n }\n } catch (e4) {\n lastError = e4\n debugLog(`${fileTypeLabel} 文件激进清理后解析失败: ${e4.message}`)\n \n // 尝试 5: 使用其他可能的类型\n const possibleTypes = ['outline', 'top', 'bottom', 'unknown']\n let parsed = false\n \n for (const type of possibleTypes) {\n try {\n parseResult = parse(gerberStr, { type: type })\n debugLog(`${fileTypeLabel} 文件使用 ${type} 类型解析成功`)\n parsed = true\n break\n } catch (e) {\n lastError = e\n }\n }\n \n if (!parsed) {\n console.warn(`${fileTypeLabel} 文件 ${file.name} 无法被 web-gerber 解析,可能是二进制格式`)\n throw new Error(`无法解析 ${fileTypeLabel} 文件 ${file.name}。文件可能是二进制格式(Excellon),web-gerber 仅支持文本格式的 Gerber 文件。已尝试多种方式,最后错误: ${lastError?.message || '未知错误'}`)\n }\n }\n }\n }\n }\n }\n }\n }\n } else {\n // 非 DRL 文件\n try {\n debugLog(`[解析调试] 文件 ${file.name}, currentFileFormatInfo存在: ${!!GerberParser.currentFileFormatInfo}`)\n \n // 【动态格式检测】检测文件中实际的坐标位数,动态调整格式定义\n if (GerberParser.currentFileFormatInfo) {\n let integerPlaces = GerberParser.currentFileFormatInfo.integerPlaces\n let decimalPlaces = GerberParser.currentFileFormatInfo.decimalPlaces\n \n // 检测文件中最长的坐标位数\n const coordMatches = gerberStr.match(/[XY](-?\\d+)/g)\n if (coordMatches) {\n let maxDigits = 0\n for (const coord of coordMatches) {\n const digits = coord.substring(1).replace(/-/g, '').length // 去掉 X/Y 和负号\n maxDigits = Math.max(maxDigits, digits)\n }\n \n const definedDigits = integerPlaces + decimalPlaces\n debugLog(`[格式检测] ${file.name} 定义格式: [${integerPlaces}, ${decimalPlaces}] (${definedDigits}位)`)\n debugLog(`[格式检测] ${file.name} 实际最长坐标: ${maxDigits}位`)\n \n // 如果实际坐标位数超过定义位数,动态增加整数位\n if (maxDigits > definedDigits) {\n const extraDigits = maxDigits - definedDigits\n integerPlaces += extraDigits\n debugLog(`[格式修正] ✓ 动态调整格式为: [${integerPlaces}, ${decimalPlaces}] (${maxDigits}位)`)\n debugLog(`[格式修正] 这样8位坐标 X10405403 会被解析为 ${(10405403 / Math.pow(10, decimalPlaces)).toFixed(decimalPlaces)}\"`)\n \n // 【关键修复】web-gerber 会优先使用文件中的格式定义,而不是我们传递的参数\n // 所以需要直接修改文件内容中的格式定义\n const oldFormat = `%FSLAX${GerberParser.currentFileFormatInfo.integerPlaces}${decimalPlaces}Y${GerberParser.currentFileFormatInfo.integerPlaces}${decimalPlaces}*%`\n const newFormat = `%FSLAX${integerPlaces}${decimalPlaces}Y${integerPlaces}${decimalPlaces}*%`\n \n if (gerberStr.includes(oldFormat)) {\n gerberStr = gerberStr.replace(oldFormat, newFormat)\n debugLog(`[格式修正] ✓ 已修改文件格式定义: ${oldFormat} → ${newFormat}`)\n } else {\n debugLog(`[格式修正] ⚠️ 未找到格式定义字符串,尝试通用替换`)\n // 通用替换:%FSLAX25Y25*% → %FSLAX35Y35*%\n gerberStr = gerberStr.replace(/%FSLAX\\d+\\d+Y\\d+\\d+\\*%/i, newFormat)\n }\n }\n }\n \n const formatOptions = {\n format: {\n places: [integerPlaces, decimalPlaces],\n zero: GerberParser.currentFileFormatInfo.zero\n }\n }\n debugLog(`[Gerber解析] ${file.name} 最终使用格式: places=[${integerPlaces}, ${decimalPlaces}], zero=${GerberParser.currentFileFormatInfo.zero}`)\n parseResult = parse(gerberStr, formatOptions)\n } else {\n parseResult = parse(gerberStr)\n }\n } catch (parseError) {\n // 尝试指定文件类型\n const fileTypeMap = {\n '.gtl': 'top',\n '.gbl': 'bottom',\n '.gts': 'topsolder',\n '.gbs': 'bottomsolder',\n '.gto': 'topsilkscreen',\n '.gbo': 'bottomsilkscreen',\n '.gtp': 'toppaste',\n '.gbp': 'bottompaste',\n '.gm1': 'outline',\n '.gko': 'outline',\n '.gdl': 'outline',\n '.gdd': 'outline',\n '.gm': 'outline',\n '.gd1': 'outline',\n '.gg1': 'outline',\n '.gpb': 'bottompaste',\n '.gpt': 'toppaste'\n }\n \n let fileType = fileTypeMap[fileExtension]\n if (!fileType && /^\\.gm\\d+$/i.test(fileExtension)) {\n fileType = 'outline'\n }\n // INT+数字 文件(扩展名格式)作为内部层处理,尝试使用 'top' 类型\n if (!fileType && /^\\.int\\d+$/i.test(fileExtension)) {\n fileType = 'top'\n }\n // INT+数字 文件(文件名格式,无扩展名)作为内部层处理,尝试使用 'top' 类型\n if (!fileType && fileExtension === '' && /.*_INT\\d+$/i.test(fileNameUpper)) {\n fileType = 'top'\n }\n fileType = fileType || 'unknown'\n \n try {\n parseResult = parse(gerberStr, { type: fileType })\n } catch (typeError) {\n // 如果指定类型失败,对于 INT 文件或其他未知类型,尝试不指定类型让库自动识别\n if (fileType === 'unknown' || /^\\.int\\d+$/i.test(fileExtension) || (fileExtension === '' && /.*_INT\\d+$/i.test(fileNameUpper))) {\n try {\n parseResult = parse(gerberStr)\n } catch (finalError) {\n throw new Error(`无法解析文件 ${file.name}。错误: ${parseError.message || typeError.message || finalError.message}`)\n }\n } else {\n throw new Error(`无法解析文件 ${file.name}。错误: ${parseError.message || typeError.message}`)\n }\n }\n }\n }\n \n // 生成可视化结果\n const plotResult = plot(parseResult)\n debugLog(`[DRL调试] 文件 ${file.name} 解析成功,plotResult:`, plotResult)\n \n // 调试:检查 plotResult 中的工具(光圈)定义(只对GTL文件输出)\n if (!isDrillFile && plotResult.tools && Object.keys(plotResult.tools).length > 0 && file.name.toUpperCase().includes('GTL')) {\n debugLog(`[光圈调试] 文件 ${file.name} 包含 ${Object.keys(plotResult.tools).length} 个工具定义:`)\n const toolEntries = Object.entries(plotResult.tools).slice(0, 5)\n toolEntries.forEach(([id, tool]) => {\n debugLog(` 工具 ${id}:`, JSON.stringify(tool, null, 2))\n })\n \n // 调试:检查 children 的结构,按类型分组统计\n if (plotResult.children && plotResult.children.length > 0) {\n const typeCount = {}\n const polarityCount = { dark: 0, clear: 0 }\n plotResult.children.forEach(child => {\n typeCount[child.type] = (typeCount[child.type] || 0) + 1\n if (child.polarity) {\n polarityCount[child.polarity] = (polarityCount[child.polarity] || 0) + 1\n }\n })\n debugLog(`[Children统计] GTL文件 ${plotResult.children.length} 个 children:`)\n debugLog(` 类型统计:`, typeCount)\n debugLog(` 极性统计:`, polarityCount)\n \n // 找出不同类型的示例\n const types = Object.keys(typeCount)\n types.forEach(type => {\n const example = plotResult.children.find(c => c.type === type)\n if (example) {\n debugLog(` ${type} 示例:`, JSON.stringify({\n type: example.type,\n tool: example.tool,\n dcode: example.dcode,\n polarity: example.polarity,\n segmentsCount: example.segments?.length,\n keys: Object.keys(example)\n }, null, 2))\n }\n })\n }\n }\n \n // 对于 DRL 文件,输出更详细的信息\n if (isDrillFile && plotResult) {\n debugLog(`[DRL调试] plotResult 详细信息:`)\n debugLog(` - type: ${plotResult.type}`)\n debugLog(` - units: ${plotResult.units}`)\n debugLog(` - size:`, plotResult.size)\n debugLog(` - tools:`, plotResult.tools ? Object.keys(plotResult.tools).length + ' 个工具' : '无')\n if (plotResult.tools) {\n const toolKeys = Object.keys(plotResult.tools).slice(0, 5)\n toolKeys.forEach(key => {\n debugLog(` - T${key}: 直径 ${plotResult.tools[key]?.diameter || '未知'}`)\n })\n }\n debugLog(` - children数量: ${plotResult.children?.length || 0}`)\n }\n \n // 生成 SVG 树\n const svgTree = renderSVG(plotResult)\n debugLog(`[DRL调试] 文件 ${file.name} SVG树生成成功,children数量:`, svgTree?.children?.length || 0)\n \n // 对于 DRL 文件,统计圆形元素数量\n if (isDrillFile && svgTree?.children) {\n let circleCount = 0\n const countCircles = (element) => {\n if (!element) return\n if (element.tagName?.toLowerCase() === 'circle') {\n circleCount++\n }\n if (element.children) {\n element.children.forEach(child => countCircles(child))\n }\n }\n svgTree.children.forEach(child => countCircles(child))\n debugLog(`[DRL调试] SVG树中圆形元素(孔)数量: ${circleCount}`)\n \n // 输出前几个孔的坐标\n if (circleCount > 0) {\n const circles = []\n const extractCircles = (element) => {\n if (!element) return\n if (element.tagName?.toLowerCase() === 'circle') {\n const cx = parseFloat(element.properties?.cx || element.attributes?.cx || 0)\n const cy = parseFloat(element.properties?.cy || element.attributes?.cy || 0)\n const r = parseFloat(element.properties?.r || element.attributes?.r || 0)\n circles.push({ cx, cy, r })\n }\n if (element.children) {\n element.children.forEach(child => extractCircles(child))\n }\n }\n svgTree.children.forEach(child => extractCircles(child))\n debugLog(`[DRL调试] 前5个孔的坐标:`)\n circles.slice(0, 5).forEach((circle, idx) => {\n debugLog(` ${idx + 1}. 中心: (${circle.cx.toFixed(6)}, ${circle.cy.toFixed(6)}), 半径: ${circle.r.toFixed(6)}`)\n })\n \n // ==================== coordPosScaleFix 机制(与 2dPage 一致)====================\n // 检测并修正 10^n 坐标缩放错误:用首个 XY 坐标按 detectedFormat 推导期望值,\n // 再与解析后的 circle.cx/cy 对比,如果差距是 10^n 则修正所有圆心(不修正半径)\n if (detectedFormat && detectedFormat.totalPlaces && circles.length > 0) {\n try {\n // 从原始文件提取第一个 XY 坐标\n const xyMatch = gerberStr.match(/X(-?\\d+)\\s*Y(-?\\d+)/i)\n console.log(`[钻孔坐标检查] ${file.name}: 首个XY=${xyMatch ? xyMatch[0] : '未找到'}, circles[0]=(${circles[0]?.cx?.toFixed(4)}, ${circles[0]?.cy?.toFixed(4)})`)\n if (xyMatch && circles[0]) {\n const actX = circles[0].cx\n const actY = circles[0].cy\n \n // 解析期望坐标的辅助函数\n const parseFixedCoord = (rawDigits, fmt, zeroMode) => {\n if (!fmt || rawDigits == null) return null\n const s = String(rawDigits).trim()\n const sign = s.startsWith('-') ? -1 : 1\n let digits = s.replace(/[^0-9]/g, '')\n if (!digits) return null\n const need = fmt.totalPlaces\n if (need && digits.length < need) {\n // LZ: 前导零省略 → 左侧补零; TZ: 尾部零省略 → 右侧补零\n if ((zeroMode || '').toUpperCase() === 'L' || zeroMode === 'LZ') {\n digits = digits.padStart(need, '0')\n } else {\n digits = digits.padEnd(need, '0')\n }\n }\n const denom = Math.pow(10, fmt.decimalPlaces || 0)\n const n = parseInt(digits, 10)\n if (!Number.isFinite(n) || denom === 0) return null\n return sign * (n / denom)\n }\n \n // 确定单位\n const plotUnits = plotResult && plotResult.units === 'in' ? 'in' : 'mm'\n const srcUnits = detectedFormat.unit === 'inch' ? 'in' : (detectedFormat.unit === 'metric' ? 'mm' : plotUnits)\n \n // 尝试两种零抑制模式,选择更匹配的\n const evalZeroMode = (zeroMode) => {\n let expX = parseFixedCoord(xyMatch[1], detectedFormat, zeroMode)\n let expY = parseFixedCoord(xyMatch[2], detectedFormat, zeroMode)\n if (expX != null && expY != null) {\n if (srcUnits === 'in' && plotUnits === 'mm') { expX *= 25.4; expY *= 25.4 }\n if (srcUnits === 'mm' && plotUnits === 'in') { expX /= 25.4; expY /= 25.4 }\n }\n const ratios = []\n // 关键修复:web-gerber 可能翻转 Y 坐标,计算 ratio 时使用绝对值\n if (Number.isFinite(expX) && Math.abs(actX) > 0.0001) ratios.push(Math.abs(expX) / Math.abs(actX))\n if (Number.isFinite(expY) && Math.abs(actY) > 0.0001) ratios.push(Math.abs(expY) / Math.abs(actY))\n if (ratios.length === 0) return null\n const avg = ratios.reduce((s, v) => s + v, 0) / ratios.length\n const max = Math.max(...ratios)\n const min = Math.min(...ratios)\n const spread = (avg !== 0) ? Math.abs(max - min) / Math.abs(avg) : 999\n return { zeroMode, expX, expY, avg, spread }\n }\n \n const primaryZero = detectedFormat.zero === 'T' ? 'TZ' : 'LZ'\n const altZero = primaryZero === 'TZ' ? 'LZ' : 'TZ'\n const primary = evalZeroMode(primaryZero)\n const alt = evalZeroMode(altZero)\n \n // 输出详细诊断日志\n console.log(`[钻孔坐标检查] ${file.name}: 格式=${detectedFormat.integerPlaces}:${detectedFormat.decimalPlaces}, 实际=(${actX.toFixed(4)}, ${actY.toFixed(4)}), plotUnits=${plotUnits}, srcUnits=${srcUnits}`)\n if (primary) console.log(`[钻孔坐标检查] ${file.name}: ${primaryZero}模式 期望=(${primary.expX?.toFixed(4)}, ${primary.expY?.toFixed(4)}), ratio=${primary.avg?.toFixed(4)}, spread=${primary.spread?.toFixed(4)}`)\n if (alt) console.log(`[钻孔坐标检查] ${file.name}: ${altZero}模式 期望=(${alt.expX?.toFixed(4)}, ${alt.expY?.toFixed(4)}), ratio=${alt.avg?.toFixed(4)}, spread=${alt.spread?.toFixed(4)}`)\n \n const near1 = (r) => r && Number.isFinite(r.avg) && r.spread < 0.05 && Math.abs(r.avg - 1) <= 0.05\n \n // 如果两种模式都不接近1,才认为存在整体倍率错误\n if (!near1(primary) && !near1(alt)) {\n const chosen = primary && alt ? (primary.spread <= alt.spread ? primary : alt) : (primary || alt)\n if (chosen && Number.isFinite(chosen.avg) && chosen.spread < 0.05 && Math.abs(chosen.avg - 1) > 0.05) {\n const absAvg = Math.abs(chosen.avg)\n const pow10 = Math.pow(10, Math.round(Math.log10(absAvg)))\n const snapped = (Math.abs(absAvg - pow10) / pow10) < 0.15 ? pow10 : absAvg\n \n if (snapped >= 0.01 && snapped <= 10000 && Math.abs(snapped - 1) > 0.05) {\n console.warn(`[钻孔坐标修正] ${file.name}: 检测到 ${snapped.toFixed(2)}x 缩放偏差,修正圆心坐标 (plotUnits=${plotUnits}, srcUnits=${srcUnits}, zero=${chosen.zeroMode})`)\n \n // 修正所有 circle/ellipse 的圆心位置(不修正半径)\n const applyFix = (node) => {\n if (!node) return\n const tag = node.tagName?.toLowerCase()\n if (tag === 'circle' || tag === 'ellipse') {\n const p = node.properties || (node.properties = {})\n const cx = parseFloat(p.cx ?? node.attributes?.cx ?? 0)\n const cy = parseFloat(p.cy ?? node.attributes?.cy ?? 0)\n if (Number.isFinite(cx)) p.cx = String(cx * snapped)\n if (Number.isFinite(cy)) p.cy = String(cy * snapped)\n }\n if (node.children) node.children.forEach(applyFix)\n }\n svgTree.children.forEach(child => applyFix(child))\n }\n }\n } else if (near1(alt) && !near1(primary)) {\n console.warn(`[钻孔坐标检查] ${file.name}: 零抑制声明为 ${primaryZero},但坐标更符合 ${altZero}(无需修正)`)\n } else if (near1(primary)) {\n console.log(`[钻孔坐标检查] ${file.name}: ✓ ${primaryZero}模式匹配良好 (ratio≈1),无需修正`)\n } else {\n console.log(`[钻孔坐标检查] ${file.name}: 未触发修正 (near1(primary)=${near1(primary)}, near1(alt)=${near1(alt)})`)\n }\n }\n } catch (e) {\n console.warn(`[钻孔坐标修正] ${file.name}: posScaleFix 计算失败:`, e?.message || e)\n }\n } else {\n console.log(`[钻孔坐标检查] ${file.name}: 跳过检查 (detectedFormat=${!!detectedFormat}, totalPlaces=${detectedFormat?.totalPlaces}, circles=${circles.length})`)\n }\n \n // 验证坐标解析:从原始文件中提取前几个坐标值,手动计算应该的值\n if (detectedFormat && detectedFormat.totalPlaces && detectedFormat.zero === 'L') {\n debugLog(`[DRL调试] 开始验证坐标解析...`)\n \n // 从原始文件内容中提取前几个坐标值(在补0之前)\n const originalContent = await this.readFileAsText(file)\n const originalCoords = originalContent.match(/([XY])(\\d+)/g) || []\n \n if (originalCoords.length > 0) {\n debugLog(`[DRL调试] 从原始文件中提取的前5个坐标值:`)\n const sampleCoords = originalCoords.slice(0, 10) // 取前10个(5对X,Y)\n \n for (let i = 0; i < Math.min(5, Math.floor(sampleCoords.length / 2)); i++) {\n const xCoord = sampleCoords[i * 2]\n const yCoord = sampleCoords[i * 2 + 1]\n \n if (xCoord && yCoord) {\n const xMatch = xCoord.match(/X(\\d+)/)\n const yMatch = yCoord.match(/Y(\\d+)/)\n \n if (xMatch && yMatch) {\n const xRaw = xMatch[1]\n const yRaw = yMatch[1]\n \n // 手动计算应该的值\n // FILE_FORMAT=2:5, LZ 格式\n // 例如:X034745(6位)补0到 X0034745(7位),解析为 00.34745 = 0.34745 英寸\n const xPadded = xRaw.padStart(detectedFormat.totalPlaces, '0')\n const yPadded = yRaw.padStart(detectedFormat.totalPlaces, '0')\n \n // 解析:前2位是整数,后5位是小数\n const xInteger = parseInt(xPadded.substring(0, detectedFormat.integerPlaces))\n const xDecimal = parseInt(xPadded.substring(detectedFormat.integerPlaces)) / Math.pow(10, detectedFormat.decimalPlaces)\n const xExpected = xInteger + xDecimal\n \n const yInteger = parseInt(yPadded.substring(0, detectedFormat.integerPlaces))\n const yDecimal = parseInt(yPadded.substring(detectedFormat.integerPlaces)) / Math.pow(10, detectedFormat.decimalPlaces)\n const yExpected = yInteger + yDecimal\n \n // 找到对应的解析后的坐标\n const parsedCircle = circles[i]\n \n debugLog(` ${i + 1}. 原始: ${xCoord}${yCoord}`)\n debugLog(` 补0后: X${xPadded}Y${yPadded}`)\n debugLog(` 应该解析为: (${xExpected.toFixed(6)}, ${yExpected.toFixed(6)})`)\n if (parsedCircle) {\n debugLog(` 实际解析为: (${parsedCircle.cx.toFixed(6)}, ${parsedCircle.cy.toFixed(6)})`)\n const xDiff = Math.abs(parsedCircle.cx - xExpected)\n const yDiff = Math.abs(parsedCircle.cy - yExpected)\n if (xDiff > 0.001 || yDiff > 0.001) {\n debugLog(` ⚠️ 坐标不匹配!X差异: ${(xDiff * 25.4).toFixed(3)} mm, Y差异: ${(yDiff * 25.4).toFixed(3)} mm`)\n } else {\n debugLog(` ✓ 坐标匹配`)\n }\n }\n }\n }\n }\n }\n }\n }\n }\n \n // 提取坐标范围\n let bounds = null\n if (parseResult && typeof parseResult === 'object') {\n if (parseResult.bounds) {\n bounds = parseResult.bounds\n } else if (parseResult.format && parseResult.format.bounds) {\n bounds = parseResult.format.bounds\n } else if (parseResult.minX !== undefined && parseResult.minY !== undefined) {\n bounds = {\n minX: parseResult.minX,\n minY: parseResult.minY,\n maxX: parseResult.maxX,\n maxY: parseResult.maxY\n }\n }\n }\n \n if (plotResult && typeof plotResult === 'object') {\n if (plotResult.bounds) {\n bounds = plotResult.bounds\n } else if (plotResult.minX !== undefined && plotResult.minY !== undefined) {\n bounds = {\n minX: plotResult.minX,\n minY: plotResult.minY,\n maxX: plotResult.maxX,\n maxY: plotResult.maxY\n }\n }\n }\n \n // 将 SVG 树转换为 WebGL 数据,传入 plotResult 以保留 polarity 信息\n const webglData = this.svgTreeToWebGL(svgTree, color, bounds, plotResult)\n \n // 如果没有 bounds,从 WebGL 数据中计算\n if (!bounds && webglData.bounds) {\n bounds = webglData.bounds\n }\n \n return {\n data: webglData,\n bounds: bounds || { minX: 0, minY: 0, maxX: 100, maxY: 100 },\n isDrillFile: isDrillFile, // 标记是否是钻孔文件,供main.js使用\n units: plotResult ? plotResult.units : 'mm',\n plotResult: plotResult // 🎯 保留原始 plotResult,包含 polarity 信息\n }\n }\n\n /**\n * 将 SVG 树转换为 WebGL 数据\n * @param {Object} svgTree - SVG 树(hast 格式)\n * @param {string} color - 颜色\n * @param {Object} bounds - 坐标范围(可选)\n * @returns {Object} - WebGL 数据\n */\n static svgTreeToWebGL(svgTree, color, bounds = null) {\n const vertices = []\n const colors = []\n const indices = []\n const lineStrips = []\n let calculatedBounds = { minX: Infinity, minY: Infinity, maxX: -Infinity, maxY: -Infinity }\n \n // 解析颜色\n const rgb = this.hexToRgb(color)\n \n /**\n * 添加顶点\n */\n function addVertex(x, y) {\n vertices.push(x, y, 0)\n colors.push(rgb.r, rgb.g, rgb.b)\n \n // 更新边界\n calculatedBounds.minX = Math.min(calculatedBounds.minX, x)\n calculatedBounds.minY = Math.min(calculatedBounds.minY, y)\n calculatedBounds.maxX = Math.max(calculatedBounds.maxX, x)\n calculatedBounds.maxY = Math.max(calculatedBounds.maxY, y)\n }\n \n /**\n * 获取当前顶点偏移\n */\n const getVertexOffset = () => vertices.length / 3\n \n /**\n * 处理 SVG 元素\n */\n const getPaintInfo = (element) => {\n const fillRaw =\n element?.properties?.fill ??\n element?.attributes?.fill ??\n element?.properties?.style?.fill ??\n element?.attributes?.style?.fill\n const strokeRaw =\n element?.properties?.stroke ??\n element?.attributes?.stroke ??\n element?.properties?.style?.stroke ??\n element?.attributes?.style?.stroke\n\n const fill = (fillRaw == null ? '' : String(fillRaw)).trim().toLowerCase()\n const stroke = (strokeRaw == null ? '' : String(strokeRaw)).trim().toLowerCase()\n\n // SVG 默认 fill 为 black;web-gerber 常会显式填 fill/stroke\n const hasFill = fill === '' ? true : (fill !== 'none')\n const hasStroke = stroke !== '' && stroke !== 'none'\n\n // 优先根据 fill/stroke 做分类\n // - fill-only 或 fill+stroke:按 fill 处理(通常是 flash/region)\n // - stroke-only:按 stroke 处理(通常是丝印描边)\n const kind = hasFill ? 'fill' : (hasStroke ? 'stroke' : 'unknown')\n return { kind, hasFill, hasStroke }\n }\n\n const processElement = (element) => {\n if (!element || !element.tagName) return\n \n const tagName = element.tagName.toLowerCase()\n const paint = getPaintInfo(element)\n \n switch (tagName) {\n case 'path':\n GerberParser.processPath(element, addVertex, lineStrips, getVertexOffset, paint)\n break\n case 'circle':\n GerberParser.processCircle(element, addVertex, lineStrips, getVertexOffset, paint)\n break\n case 'ellipse':\n GerberParser.processEllipse(element, addVertex, lineStrips, getVertexOffset, paint)\n break\n case 'rect':\n GerberParser.processRect(element, addVertex, lineStrips, getVertexOffset, paint)\n break\n case 'line':\n GerberParser.processLine(element, addVertex, indices, getVertexOffset)\n break\n case 'polyline':\n GerberParser.processPolyline(element, addVertex, lineStrips, getVertexOffset, paint)\n break\n case 'polygon':\n GerberParser.processPolygon(element, addVertex, lineStrips, getVertexOffset, paint)\n break\n case 'g':\n // 处理组内的所有子元素\n if (element.children) {\n element.children.forEach(child => processElement(child))\n }\n break\n }\n }\n \n // 处理根元素\n if (svgTree.children) {\n debugLog(`处理 ${svgTree.children.length} 个子元素`)\n svgTree.children.forEach(child => processElement(child))\n } else {\n console.warn(`SVG树没有子元素,可能文件只包含定义(如%ADD)而没有绘图命令`)\n }\n \n // 如果没有计算到边界,使用传入的 bounds\n if (calculatedBounds.minX === Infinity && bounds) {\n calculatedBounds = bounds\n }\n \n const vertexCount = vertices.length / 3\n debugLog(`WebGL转换完成: ${vertexCount} 个顶点, ${lineStrips.length} 条线, ${indices.length} 个索引`)\n \n return {\n vertices: new Float32Array(vertices),\n colors: new Float32Array(colors),\n indices: new Uint16Array(indices),\n lineStrips: lineStrips,\n vertexCount: vertexCount,\n bounds: calculatedBounds\n }\n }\n\n /**\n * 处理 path 元素\n * 支持 stroke-width 属性,将开放路径扩展为有宽度的闭合多边形\n */\n static processPath(element, addVertex, lineStrips, getVertexOffset, paint = null) {\n const d = element.properties?.d || element.attributes?.d || ''\n if (!d) return\n \n const points = this.parsePathData(d)\n \n if (points.length < 2) {\n return\n }\n \n // 提取 stroke-width(线宽)- 检查多个可能的位置\n let strokeWidth = parseFloat(\n element.properties?.['stroke-width'] || \n element.attributes?.['stroke-width'] || \n element.properties?.strokeWidth ||\n element.attributes?.strokeWidth ||\n 0\n )\n \n // 检查 style 属性中的 stroke-width\n if (strokeWidth === 0) {\n const style = element.properties?.style || element.attributes?.style || ''\n if (typeof style === 'string') {\n const match = style.match(/stroke-width\\s*:\\s*([0-9.]+)/i)\n if (match) {\n strokeWidth = parseFloat(match[1])\n }\n } else if (typeof style === 'object') {\n strokeWidth = parseFloat(style['stroke-width'] || style.strokeWidth || 0)\n }\n }\n \n // 调试:打印前几个元素的属性\n if (!GerberParser._debugPathCount) {\n GerberParser._debugPathCount = 0\n }\n if (GerberParser._debugPathCount < 3) {\n GerberParser._debugPathCount++\n debugLog(`[调试] Path 元素 #${GerberParser._debugPathCount}:`, {\n properties: element.properties,\n attributes: element.attributes,\n strokeWidth: strokeWidth,\n pointsCount: points.length,\n isClosed: Math.sqrt(Math.pow(points[0].x - points[points.length-1].x, 2) + Math.pow(points[0].y - points[points.length-1].y, 2)) < 0.001\n })\n }\n \n // 检查路径是否闭合(首尾点距离小于阈值)\n const first = points[0]\n const last = points[points.length - 1]\n const closeDist = Math.sqrt(Math.pow(first.x - last.x, 2) + Math.pow(first.y - last.y, 2))\n const isClosed = closeDist < 0.001\n \n // 如果有线宽且路径不闭合,将路径扩展为有宽度的闭合多边形\n if (strokeWidth > 0 && !isClosed) {\n const expandedPoints = this.expandPathToPolygon(points, strokeWidth)\n if (expandedPoints.length >= 3) {\n const stripStart = getVertexOffset()\n expandedPoints.forEach(point => {\n addVertex(point.x, point.y)\n })\n // 闭合多边形\n addVertex(expandedPoints[0].x, expandedPoints[0].y)\n \n // 这是“描边扩展后的面积”,可按 fill 渲染(避免把它当成中心线再做 ribbon)\n lineStrips.push({\n start: stripStart,\n count: expandedPoints.length + 1,\n kind: 'fill'\n })\n return\n }\n }\n \n // 原有逻辑:直接添加点\n const stripStart = getVertexOffset()\n points.forEach(point => {\n addVertex(point.x, point.y)\n })\n \n // 没有做“宽度扩展”的 path:根据 SVG paint 判定 fill vs stroke\n lineStrips.push({\n start: stripStart,\n count: points.length,\n kind: paint?.kind || 'unknown'\n })\n }\n\n /**\n * 将开放路径扩展为有宽度的闭合多边形\n * @param {Array} points - 路径点数组 [{x, y}, ...]\n * @param {number} strokeWidth - 线宽\n * @returns {Array} - 扩展后的多边形点数组\n */\n static expandPathToPolygon(points, strokeWidth) {\n if (points.length < 2) return []\n \n const halfWidth = strokeWidth / 2\n const leftSide = [] // 左侧边界点\n const rightSide = [] // 右侧边界点\n \n for (let i = 0; i < points.length; i++) {\n const curr = points[i]\n const prev = points[i - 1]\n const next = points[i + 1]\n \n let dx, dy, len, perpX, perpY\n \n if (i === 0) {\n // 起点:使用与下一点的方向\n dx = next.x - curr.x\n dy = next.y - curr.y\n len = Math.sqrt(dx * dx + dy * dy)\n if (len < 1e-9) {\n perpX = 0\n perpY = halfWidth\n } else {\n perpX = -dy / len * halfWidth\n perpY = dx / len * halfWidth\n }\n } else if (i === points.length - 1) {\n // 终点:使用与上一点的方向\n dx = curr.x - prev.x\n dy = curr.y - prev.y\n len = Math.sqrt(dx * dx + dy * dy)\n if (len < 1e-9) {\n perpX = 0\n perpY = halfWidth\n } else {\n perpX = -dy / len * halfWidth\n perpY = dx / len * halfWidth\n }\n } else {\n // 中间点:使用前后两段的平均方向\n const dx1 = curr.x - prev.x\n const dy1 = curr.y - prev.y\n const len1 = Math.sqrt(dx1 * dx1 + dy1 * dy1)\n \n const dx2 = next.x - curr.x\n const dy2 = next.y - curr.y\n const len2 = Math.sqrt(dx2 * dx2 + dy2 * dy2)\n \n if (len1 < 1e-9 && len2 < 1e-9) {\n perpX = 0\n perpY = halfWidth\n } else if (len1 < 1e-9) {\n perpX = -dy2 / len2 * halfWidth\n perpY = dx2 / len2 * halfWidth\n } else if (len2 < 1e-9) {\n perpX = -dy1 / len1 * halfWidth\n perpY = dx1 / len1 * halfWidth\n } else {\n // 计算两段的平均法向量\n const perpX1 = -dy1 / len1\n const perpY1 = dx1 / len1\n const perpX2 = -dy2 / len2\n const perpY2 = dx2 / len2\n \n // 平均法向量\n let avgPerpX = (perpX1 + perpX2) / 2\n let avgPerpY = (perpY1 + perpY2) / 2\n const avgLen = Math.sqrt(avgPerpX * avgPerpX + avgPerpY * avgPerpY)\n \n if (avgLen < 1e-9) {\n perpX = perpX1 * halfWidth\n perpY = perpY1 * halfWidth\n } else {\n // 计算斜接因子(miter factor)来保持正确的宽度\n const dot = perpX1 * perpX2 + perpY1 * perpY2\n const miterLen = halfWidth / Math.max(0.5, Math.sqrt((1 + dot) / 2))\n perpX = avgPerpX / avgLen * miterLen\n perpY = avgPerpY / avgLen * miterLen\n }\n }\n }\n \n // 左侧点(法向量方向)\n leftSide.push({\n x: curr.x + perpX,\n y: curr.y + perpY\n })\n \n // 右侧点(法向量反方向)\n rightSide.push({\n x: curr.x - perpX,\n y: curr.y - perpY\n })\n }\n \n // 组合成闭合多边形:左侧正向 + 右侧反向\n const polygon = [...leftSide, ...rightSide.reverse()]\n \n return polygon\n }\n\n /**\n * 处理 circle 元素\n */\n static processCircle(element, addVertex, lineStrips, getVertexOffset, paint = null) {\n const cx = parseFloat(element.properties?.cx || element.attributes?.cx || 0)\n const cy = parseFloat(element.properties?.cy || element.attributes?.cy || 0)\n const r = parseFloat(element.properties?.r || element.attributes?.r || 0)\n \n if (r <= 0) return\n \n // 生成圆形顶点(使用足够的分段数)\n const segments = Math.max(32, Math.ceil(r * 0.5))\n const points = []\n \n for (let i = 0; i <= segments; i++) {\n const angle = (i / segments) * Math.PI * 2\n points.push({\n x: cx + Math.cos(angle) * r,\n y: cy + Math.sin(angle) * r\n })\n }\n \n const stripStart = getVertexOffset()\n points.forEach(point => {\n addVertex(point.x, point.y)\n })\n \n lineStrips.push({\n start: stripStart,\n count: points.length,\n kind: paint?.kind || 'unknown'\n })\n }\n\n /**\n * 处理 ellipse 元素\n */\n static processEllipse(element, addVertex, lineStrips, getVertexOffset, paint = null) {\n const cx = parseFloat(element.properties?.cx || element.attributes?.cx || 0)\n const cy = parseFloat(element.properties?.cy || element.attributes?.cy || 0)\n const rx = parseFloat(element.properties?.rx || element.attributes?.rx || 0)\n const ry = parseFloat(element.properties?.ry || element.attributes?.ry || 0)\n \n if (rx <= 0 || ry <= 0) return\n \n // 生成椭圆顶点\n const segments = Math.max(32, Math.ceil(Math.max(rx, ry) * 0.5))\n const points = []\n \n for (let i = 0; i <= segments; i++) {\n const angle = (i / segments) * Math.PI * 2\n points.push({\n x: cx + Math.cos(angle) * rx,\n y: cy + Math.sin(angle) * ry\n })\n }\n \n const stripStart = getVertexOffset()\n points.forEach(point => {\n addVertex(point.x, point.y)\n })\n \n lineStrips.push({\n start: stripStart,\n count: points.length,\n kind: paint?.kind || 'unknown'\n })\n }\n\n /**\n * 处理 rect 元素(支持圆角矩形)\n */\n static processRect(element, addVertex, lineStrips, getVertexOffset, paint = null) {\n const x = parseFloat(element.properties?.x || element.attributes?.x || 0)\n const y = parseFloat(element.properties?.y || element.attributes?.y || 0)\n const width = parseFloat(element.properties?.width || element.attributes?.width || 0)\n const height = parseFloat(element.properties?.height || element.attributes?.height || 0)\n const rx = parseFloat(element.properties?.rx || element.attributes?.rx || 0)\n const ry = parseFloat(element.properties?.ry || element.attributes?.ry || rx || 0)\n \n if (width <= 0 || height <= 0) return\n \n const stripStart = getVertexOffset()\n \n // 如果有圆角,使用圆弧绘制\n if (rx > 0 && ry > 0) {\n const maxRx = Math.min(rx, width / 2)\n const maxRy = Math.min(ry, height / 2)\n \n // 圆角矩形的路径:从左上角开始,顺时针\n // 左上角\n addVertex(x + maxRx, y)\n // 右上角圆弧\n const topRightArc = this.approximateArc(\n x + width - maxRx, y,\n maxRx, maxRy, 0, 0, 1,\n x + width, y + maxRy\n )\n for (let i = 1; i < topRightArc.length; i++) {\n addVertex(topRightArc[i].x, topRightArc[i].y)\n }\n // 右下角圆弧\n const bottomRightArc = this.approximateArc(\n x + width, y + height - maxRy,\n maxRx, maxRy, 0, 0, 1,\n x + width - maxRx, y + height\n )\n for (let i = 1; i < bottomRightArc.length; i++) {\n addVertex(bottomRightArc[i].x, bottomRightArc[i].y)\n }\n // 左下角圆弧\n const bottomLeftArc = this.approximateArc(\n x + maxRx, y + height,\n maxRx, maxRy, 0, 0, 1,\n x, y + height - maxRy\n )\n for (let i = 1; i < bottomLeftArc.length; i++) {\n addVertex(bottomLeftArc[i].x, bottomLeftArc[i].y)\n }\n // 左上角圆弧\n const topLeftArc = this.approximateArc(\n x, y + maxRy,\n maxRx, maxRy, 0, 0, 1,\n x + maxRx, y\n )\n for (let i = 1; i < topLeftArc.length; i++) {\n addVertex(topLeftArc[i].x, topLeftArc[i].y)\n }\n } else {\n // 普通矩形:四个顶点\n addVertex(x, y)\n addVertex(x + width, y)\n addVertex(x + width, y + height)\n addVertex(x, y + height)\n // 闭合\n addVertex(x, y)\n }\n \n lineStrips.push({\n start: stripStart,\n count: getVertexOffset() - stripStart,\n kind: paint?.kind || 'unknown'\n })\n }\n\n /**\n * 处理 line 元素\n */\n static processLine(element, addVertex, indices, getVertexOffset) {\n const x1 = parseFloat(element.properties?.x1 || element.attributes?.x1 || 0)\n const y1 = parseFloat(element.properties?.y1 || element.attributes?.y1 || 0)\n const x2 = parseFloat(element.properties?.x2 || element.attributes?.x2 || 0)\n const y2 = parseFloat(element.properties?.y2 || element.attributes?.y2 || 0)\n \n const v0 = getVertexOffset()\n addVertex(x1, y1)\n const v1 = getVertexOffset()\n addVertex(x2, y2)\n \n indices.push(v0, v1)\n }\n\n /**\n * 处理 polyline 元素\n */\n static processPolyline(element, addVertex, lineStrips, getVertexOffset, paint = null) {\n const points = element.properties?.points || element.attributes?.points || ''\n if (!points) return\n \n const coords = this.parsePoints(points)\n if (coords.length < 2) return\n \n const stripStart = getVertexOffset()\n coords.forEach(coord => {\n addVertex(coord.x, coord.y)\n })\n \n lineStrips.push({\n start: stripStart,\n count: coords.length,\n kind: paint?.kind || 'unknown'\n })\n }\n\n /**\n * 处理 polygon 元素\n */\n static processPolygon(element, addVertex, lineStrips, getVertexOffset, paint = null) {\n const points = element.properties?.points || element.attributes?.points || ''\n if (!points) return\n \n const coords = this.parsePoints(points)\n if (coords.length < 2) return\n \n // 多边形需要闭合\n const stripStart = getVertexOffset()\n coords.forEach(coord => {\n addVertex(coord.x, coord.y)\n })\n // 添加第一个点以闭合\n addVertex(coords[0].x, coords[0].y)\n \n lineStrips.push({\n start: stripStart,\n count: coords.length + 1,\n kind: paint?.kind || 'unknown'\n })\n }\n\n /**\n * 解析 SVG path 数据\n * 支持 M, L, H, V, Z, A 命令(绝对和相对坐标)\n * A 命令用于绘制圆弧(圆角矩形等)\n */\n static parsePathData(d) {\n if (!d || typeof d !== 'string') return []\n \n const points = []\n let currentX = 0\n let currentY = 0\n let startX = 0\n let startY = 0\n \n // Token 化:分割命令和数字(包括 A 和 a 命令)\n const tokens = d.match(/[MLHVZACQSTmlhvzacqst]|-?[\\d.]+(?:[eE][+-]?\\d+)?/g)\n if (!tokens || tokens.length === 0) return []\n \n let i = 0\n while (i < tokens.length) {\n const token = tokens[i]\n const upperToken = token.toUpperCase()\n const isRelative = token === token.toLowerCase()\n \n if (upperToken === 'M') {\n // MoveTo\n if (i + 2 < tokens.length) {\n const x = parseFloat(tokens[i + 1])\n const y = parseFloat(tokens[i + 2])\n if (!isNaN(x) && !isNaN(y)) {\n if (isRelative) {\n currentX += x\n currentY += y\n } else {\n currentX = x\n currentY = y\n }\n startX = currentX\n startY = currentY\n points.push({ x: currentX, y: currentY })\n i += 3\n \n // 处理隐式 LineTo(只处理数字对,不处理命令)\n while (i + 1 < tokens.length && !/^[MLHVZACQSTmlhvzacqst]$/.test(tokens[i])) {\n const nextX = parseFloat(tokens[i])\n const nextY = parseFloat(tokens[i + 1])\n if (!isNaN(nextX) && !isNaN(nextY)) {\n if (isRelative) {\n currentX += nextX\n currentY += nextY\n } else {\n currentX = nextX\n currentY = nextY\n }\n points.push({ x: currentX, y: currentY })\n i += 2\n } else {\n break\n }\n }\n } else {\n i++\n }\n } else {\n i++\n }\n } else if (upperToken === 'L') {\n // LineTo\n if (i + 2 < tokens.length) {\n const x = parseFloat(tokens[i + 1])\n const y = parseFloat(tokens[i + 2])\n if (!isNaN(x) && !isNaN(y)) {\n if (isRelative) {\n currentX += x\n currentY += y\n } else {\n currentX = x\n currentY = y\n }\n points.push({ x: currentX, y: currentY })\n i += 3\n \n // 处理隐式 LineTo\n while (i + 1 < tokens.length && !/^[MLHVZACQSTmlhvzacqst]$/.test(tokens[i])) {\n const nextX = parseFloat(tokens[i])\n const nextY = parseFloat(tokens[i + 1])\n if (!isNaN(nextX) && !isNaN(nextY)) {\n if (isRelative) {\n currentX += nextX\n currentY += nextY\n } else {\n currentX = nextX\n currentY = nextY\n }\n points.push({ x: currentX, y: currentY })\n i += 2\n } else {\n break\n }\n }\n } else {\n i++\n }\n } else {\n i++\n }\n } else if (upperToken === 'A') {\n // Arc 命令:绘制圆弧(用于圆角矩形等)\n // A rx ry x-axis-rotation large-arc-flag sweep-flag x y\n if (i + 7 < tokens.length) {\n const rx = parseFloat(tokens[i + 1])\n const ry = parseFloat(tokens[i + 2])\n const xAxisRotation = parseFloat(tokens[i + 3])\n const largeArcFlag = parseFloat(tokens[i + 4])\n const sweepFlag = parseFloat(tokens[i + 5])\n const x = parseFloat(tokens[i + 6])\n const y = parseFloat(tokens[i + 7])\n \n if (!isNaN(rx) && !isNaN(ry) && !isNaN(x) && !isNaN(y)) {\n const endX = isRelative ? currentX + x : x\n const endY = isRelative ? currentY + y : y\n \n // 生成圆弧的近似点(使用足够的分段)\n const arcPoints = this.approximateArc(\n currentX, currentY,\n rx, ry, xAxisRotation,\n largeArcFlag, sweepFlag,\n endX, endY\n )\n \n // 添加圆弧点(跳过第一个点,因为它是当前点)\n for (let j = 1; j < arcPoints.length; j++) {\n points.push(arcPoints[j])\n }\n \n currentX = endX\n currentY = endY\n i += 8\n \n // 处理连续的 A 命令(隐式)\n while (i + 6 < tokens.length && !/^[MLHVZACQSTmlhvzacqst]$/.test(tokens[i])) {\n const nextRx = parseFloat(tokens[i])\n const nextRy = parseFloat(tokens[i + 1])\n const nextXAxisRotation = parseFloat(tokens[i + 2])\n const nextLargeArcFlag = parseFloat(tokens[i + 3])\n const nextSweepFlag = parseFloat(tokens[i + 4])\n const nextX = parseFloat(tokens[i + 5])\n const nextY = parseFloat(tokens[i + 6])\n \n if (!isNaN(nextRx) && !isNaN(nextRy) && !isNaN(nextX) && !isNaN(nextY)) {\n const nextEndX = isRelative ? currentX + nextX : nextX\n const nextEndY = isRelative ? currentY + nextY : nextY\n \n const nextArcPoints = this.approximateArc(\n currentX, currentY,\n nextRx, nextRy, nextXAxisRotation,\n nextLargeArcFlag, nextSweepFlag,\n nextEndX, nextEndY\n )\n \n for (let j = 1; j < nextArcPoints.length; j++) {\n points.push(nextArcPoints[j])\n }\n \n currentX = nextEndX\n currentY = nextEndY\n i += 7\n } else {\n break\n }\n }\n } else {\n i++\n }\n } else {\n i++\n }\n } else if (upperToken === 'H') {\n // Horizontal LineTo\n if (i + 1 < tokens.length) {\n const x = parseFloat(tokens[i + 1])\n if (!isNaN(x)) {\n if (isRelative) {\n currentX += x\n } else {\n currentX = x\n }\n points.push({ x: currentX, y: currentY })\n i += 2\n } else {\n i++\n }\n } else {\n i++\n }\n } else if (upperToken === 'V') {\n // Vertical LineTo\n if (i + 1 < tokens.length) {\n const y = parseFloat(tokens[i + 1])\n if (!isNaN(y)) {\n if (isRelative) {\n currentY += y\n } else {\n currentY = y\n }\n points.push({ x: currentX, y: currentY })\n i += 2\n } else {\n i++\n }\n } else {\n i++\n }\n } else if (upperToken === 'Z') {\n // ClosePath\n if (points.length > 0 && (currentX !== startX || currentY !== startY)) {\n points.push({ x: startX, y: startY })\n }\n currentX = startX\n currentY = startY\n i++\n } else if (upperToken === 'C' || upperToken === 'S' || upperToken === 'Q' || upperToken === 'T') {\n // 贝塞尔曲线命令(C, S, Q, T)\n // 对于这些命令,我们暂时跳过,因为它们通常用于复杂曲线\n // 如果遇到这些命令,跳过相应的参数\n i++\n // 跳过参数(C: 6个, S: 4个, Q: 4个, T: 2个)\n const paramCount = upperToken === 'C' ? 6 : (upperToken === 'S' ? 4 : (upperToken === 'Q' ? 4 : 2))\n let skipped = 0\n while (i < tokens.length && skipped < paramCount) {\n const num = parseFloat(tokens[i])\n if (!isNaN(num)) {\n skipped++\n if (skipped === paramCount - 1) {\n // 最后一个参数是终点 Y\n const endY = isRelative ? currentY + num : num\n currentY = endY\n } else if (skipped === paramCount - 2) {\n // 倒数第二个参数是终点 X\n const endX = isRelative ? currentX + num : num\n currentX = endX\n }\n }\n i++\n }\n // 添加终点\n if (skipped === paramCount) {\n points.push({ x: currentX, y: currentY })\n }\n } else {\n // 未知命令或格式错误,跳过\n console.warn(`路径解析:遇到未知命令或格式错误: ${token},位置: ${i}`)\n i++\n }\n }\n \n return points\n }\n\n /**\n * 近似圆弧为线段\n * @param {number} x1 - 起始点 X\n * @param {number} y1 - 起始点 Y\n * @param {number} rx - X 轴半径\n * @param {number} ry - Y 轴半径\n * @param {number} xAxisRotation - X 轴旋转角度(度)\n * @param {number} largeArcFlag - 大弧标志(0 或 1)\n * @param {number} sweepFlag - 扫描标志(0 或 1)\n * @param {number} x2 - 终点 X\n * @param {number} y2 - 终点 Y\n * @returns {Array} - 近似点数组\n */\n static approximateArc(x1, y1, rx, ry, xAxisRotation, largeArcFlag, sweepFlag, x2, y2) {\n const points = []\n \n // 如果半径太小,直接返回直线\n if (rx < 0.001 || ry < 0.001) {\n points.push({ x: x1, y: y1 })\n points.push({ x: x2, y: y2 })\n return points\n }\n \n // 计算中心点和角度\n const dx = (x1 - x2) / 2\n const dy = (y1 - y2) / 2\n const cosPhi = Math.cos(xAxisRotation * Math.PI / 180)\n const sinPhi = Math.sin(xAxisRotation * Math.PI / 180)\n \n // 旋转到局部坐标系\n const x1p = cosPhi * dx + sinPhi * dy\n const y1p = -sinPhi * dx + cosPhi * dy\n \n // 确保半径足够大\n const lambda = (x1p * x1p) / (rx * rx) + (y1p * y1p) / (ry * ry)\n if (lambda > 1) {\n rx *= Math.sqrt(lambda)\n ry *= Math.sqrt(lambda)\n }\n \n // 计算中心点\n const sign = largeArcFlag === sweepFlag ? -1 : 1\n const num = Math.max(0, (rx * rx * ry * ry - rx * rx * y1p * y1p - ry * ry * x1p * x1p) / (rx * rx * y1p * y1p + ry * ry * x1p * x1p))\n const co = sign * Math.sqrt(num)\n const cxp = (co * rx * y1p) / ry\n const cyp = -(co * ry * x1p) / rx\n \n // 旋转回全局坐标系\n const cx = cosPhi * cxp - sinPhi * cyp + (x1 + x2) / 2\n const cy = sinPhi * cxp + cosPhi * cyp + (y1 + y2) / 2\n \n // 计算起始和结束角度\n const ux = (x1p - cxp) / rx\n const uy = (y1p - cyp) / ry\n const vx = (-x1p - cxp) / rx\n const vy = (-y1p - cyp) / ry\n \n let startAngle = Math.atan2(uy, ux)\n let sweepAngle = Math.atan2(ux * vy - uy * vx, ux * vx + uy * vy)\n \n if (sweepFlag === 0 && sweepAngle > 0) {\n sweepAngle -= 2 * Math.PI\n } else if (sweepFlag === 1 && sweepAngle < 0) {\n sweepAngle += 2 * Math.PI\n }\n \n // 生成近似点\n // 对于完整圆(360度),使用至少32段;对于其他圆弧,也使用至少32段以保证平滑度\n const isFullCircle = Math.abs(Math.abs(sweepAngle) - 2 * Math.PI) < 0.001\n const minSegments = 64\n const segments = Math.max(minSegments, Math.ceil(Math.abs(sweepAngle) * Math.max(rx, ry) / 2))\n points.push({ x: x1, y: y1 })\n \n for (let i = 1; i <= segments; i++) {\n const angle = startAngle + (sweepAngle * i) / segments\n const px = cx + rx * Math.cos(angle) * cosPhi - ry * Math.sin(angle) * sinPhi\n const py = cy + rx * Math.cos(angle) * sinPhi + ry * Math.sin(angle) * cosPhi\n points.push({ x: px, y: py })\n }\n \n return points\n }\n\n /**\n * 解析 points 属性(polyline/polygon)\n */\n static parsePoints(pointsStr) {\n if (!pointsStr || typeof pointsStr !== 'string') return []\n \n const coords = []\n const numbers = pointsStr.match(/-?[\\d.]+(?:[eE][+-]?\\d+)?/g)\n \n if (!numbers || numbers.length < 2) return []\n \n for (let i = 0; i < numbers.length - 1; i += 2) {\n const x = parseFloat(numbers[i])\n const y = parseFloat(numbers[i + 1])\n if (!isNaN(x) && !isNaN(y)) {\n coords.push({ x, y })\n }\n }\n \n return coords\n }\n\n /**\n * 将十六进制颜色转换为 RGB\n */\n static hexToRgb(hex) {\n const result = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(hex)\n return result ? {\n r: parseInt(result[1], 16) / 255,\n g: parseInt(result[2], 16) / 255,\n b: parseInt(result[3], 16) / 255\n } : { r: 1, g: 0, b: 0 }\n }\n\n /**\n * 从 SVG 树中提取钻孔坐标(圆形元素的中心点)\n * 用于 DRL 文件\n * @param {Object} svgTree - SVG 树\n * @returns {Array<{x: number, y: number, r: number}>} - 钻孔坐标数组\n */\n static extractHoles(svgTree) {\n const holes = []\n \n if (!svgTree || !svgTree.children) return holes\n \n const extractFromElement = (element) => {\n if (!element || !element.tagName) return\n \n const tagName = element.tagName.toLowerCase()\n \n if (tagName === 'circle') {\n const cx = parseFloat(element.properties?.cx || element.attributes?.cx || 0)\n const cy = parseFloat(element.properties?.cy || element.attributes?.cy || 0)\n const r = parseFloat(element.properties?.r || element.attributes?.r || 0)\n \n if (r > 0 && !isNaN(cx) && !isNaN(cy)) {\n holes.push({ x: cx, y: cy, r: r })\n }\n } else if (tagName === 'g') {\n // 递归处理组内的子元素\n if (element.children) {\n element.children.forEach(child => extractFromElement(child))\n }\n }\n }\n \n svgTree.children.forEach(child => extractFromElement(child))\n \n return holes\n }\n\n /**\n * 从 SVG 树中提取特征点(圆形、矩形等元素的中心点)\n * 用于 Gerber 文件,提取焊盘、过孔等特征点\n * @param {Object} svgTree - SVG 树\n * @returns {Array<{x: number, y: number, r?: number, type: string}>} - 特征点坐标数组\n */\n static extractFeaturePoints(svgTree) {\n const points = []\n \n if (!svgTree || !svgTree.children) return points\n \n const extractFromElement = (element) => {\n if (!element || !element.tagName) return\n \n const tagName = element.tagName.toLowerCase()\n \n if (tagName === 'circle') {\n const cx = parseFloat(element.properties?.cx || element.attributes?.cx || 0)\n const cy = parseFloat(element.properties?.cy || element.attributes?.cy || 0)\n const r = parseFloat(element.properties?.r || element.attributes?.r || 0)\n \n if (r > 0 && !isNaN(cx) && !isNaN(cy)) {\n points.push({ x: cx, y: cy, r: r, type: 'circle' })\n }\n } else if (tagName === 'rect') {\n const x = parseFloat(element.properties?.x || element.attributes?.x || 0)\n const y = parseFloat(element.properties?.y || element.attributes?.y || 0)\n const width = parseFloat(element.properties?.width || element.attributes?.width || 0)\n const height = parseFloat(element.properties?.height || element.attributes?.height || 0)\n \n if (width > 0 && height > 0 && !isNaN(x) && !isNaN(y)) {\n // 矩形中心点\n const cx = x + width / 2\n const cy = y + height / 2\n // 使用对角线的一半作为\"半径\"(用于距离计算)\n const r = Math.sqrt(width * width + height * height) / 2\n points.push({ x: cx, y: cy, r: r, type: 'rect', width: width, height: height })\n }\n } else if (tagName === 'ellipse') {\n const cx = parseFloat(element.properties?.cx || element.attributes?.cx || 0)\n const cy = parseFloat(element.properties?.cy || element.attributes?.cy || 0)\n const rx = parseFloat(element.properties?.rx || element.attributes?.rx || 0)\n const ry = parseFloat(element.properties?.ry || element.attributes?.ry || 0)\n \n if (rx > 0 && ry > 0 && !isNaN(cx) && !isNaN(cy)) {\n // 如果 rx === ry,则是一个圆形,使用 'circle' 类型\n // 否则是椭圆,使用 'ellipse' 类型\n const isCircle = Math.abs(rx - ry) < 0.0001 // 允许小的浮点误差\n const r = isCircle ? rx : Math.max(rx, ry) // 圆形使用半径,椭圆使用较大的半径\n points.push({ \n x: cx, \n y: cy, \n r: r, \n type: isCircle ? 'circle' : 'ellipse', \n rx: rx, \n ry: ry \n })\n }\n } else if (tagName === 'polygon') {\n // 提取多边形的中心点\n const pointsStr = element.properties?.points || element.attributes?.points || ''\n if (pointsStr) {\n const polygonPoints = this.parsePoints(pointsStr)\n if (polygonPoints.length >= 3) {\n // 计算多边形的中心点(质心)\n let sumX = 0\n let sumY = 0\n let minX = Infinity\n let minY = Infinity\n let maxX = -Infinity\n let maxY = -Infinity\n \n for (const point of polygonPoints) {\n sumX += point.x\n sumY += point.y\n minX = Math.min(minX, point.x)\n minY = Math.min(minY, point.y)\n maxX = Math.max(maxX, point.x)\n maxY = Math.max(maxY, point.y)\n }\n \n // 使用质心作为中心点\n const cx = sumX / polygonPoints.length\n const cy = sumY / polygonPoints.length\n // 使用边界框对角线的一半作为\"半径\"\n const r = Math.sqrt(\n Math.pow(maxX - minX, 2) + Math.pow(maxY - minY, 2)\n ) / 2\n \n if (r > 0.001) {\n points.push({ x: cx, y: cy, r: r, type: 'polygon', pointCount: polygonPoints.length })\n }\n }\n }\n } else if (tagName === 'polyline') {\n // 提取折线的中心点\n const pointsStr = element.properties?.points || element.attributes?.points || ''\n if (pointsStr) {\n const polylinePoints = this.parsePoints(pointsStr)\n if (polylinePoints.length >= 2) {\n // 计算折线的中心点(质心)\n let sumX = 0\n let sumY = 0\n let minX = Infinity\n let minY = Infinity\n let maxX = -Infinity\n let maxY = -Infinity\n \n for (const point of polylinePoints) {\n sumX += point.x\n sumY += point.y\n minX = Math.min(minX, point.x)\n minY = Math.min(minY, point.y)\n maxX = Math.max(maxX, point.x)\n maxY = Math.max(maxY, point.y)\n }\n \n // 使用质心作为中心点\n const cx = sumX / polylinePoints.length\n const cy = sumY / polylinePoints.length\n // 使用边界框对角线的一半作为\"半径\"\n const r = Math.sqrt(\n Math.pow(maxX - minX, 2) + Math.pow(maxY - minY, 2)\n ) / 2\n \n if (r > 0.001) {\n points.push({ x: cx, y: cy, r: r, type: 'polyline', pointCount: polylinePoints.length })\n }\n }\n }\n } else if (tagName === 'path') {\n // 提取路径的特征点\n const d = element.properties?.d || element.attributes?.d || ''\n if (d) {\n const pathPoints = this.parsePathData(d)\n if (pathPoints.length >= 2) {\n // 检查路径是否是一个圆形(闭合路径,所有点到中心的距离大致相等)\n // 计算所有点的中心点\n let sumX = 0\n let sumY = 0\n for (const point of pathPoints) {\n sumX += point.x\n sumY += point.y\n }\n const centerX = sumX / pathPoints.length\n const centerY = sumY / pathPoints.length\n \n // 计算所有点到中心的距离\n const distances = pathPoints.map(p => \n Math.sqrt(Math.pow(p.x - centerX, 2) + Math.pow(p.y - centerY, 2))\n )\n \n // 计算平均距离和标准差\n const avgDistance = distances.reduce((a, b) => a + b, 0) / distances.length\n const variance = distances.reduce((sum, d) => sum + Math.pow(d - avgDistance, 2), 0) / distances.length\n const stdDev = Math.sqrt(variance)\n \n // 如果标准差相对于平均距离很小(小于5%),且路径是闭合的(起点和终点接近),则认为是圆形\n const isClosed = pathPoints.length > 2 && \n Math.sqrt(\n Math.pow(pathPoints[0].x - pathPoints[pathPoints.length - 1].x, 2) +\n Math.pow(pathPoints[0].y - pathPoints[pathPoints.length - 1].y, 2)\n ) < 0.001\n \n const isCircle = isClosed && avgDistance > 0.001 && (stdDev / avgDistance) < 0.05\n \n if (isCircle) {\n // 这是一个圆形路径,提取中心点和半径\n points.push({ \n x: centerX, \n y: centerY, \n r: avgDistance, \n type: 'circle',\n source: 'path'\n })\n } else {\n // 不是圆形,使用路径的起点和终点作为特征点\n const start = pathPoints[0]\n const end = pathPoints[pathPoints.length - 1]\n // 使用路径长度的一半作为\"半径\"\n const pathLength = Math.sqrt(\n Math.pow(end.x - start.x, 2) + Math.pow(end.y - start.y, 2)\n )\n if (pathLength > 0.001) { // 只添加有意义的路径点\n points.push({ x: start.x, y: start.y, r: pathLength / 2, type: 'path-start' })\n points.push({ x: end.x, y: end.y, r: pathLength / 2, type: 'path-end' })\n }\n }\n }\n }\n } else if (tagName === 'g') {\n // 递归处理组内的子元素\n if (element.children) {\n element.children.forEach(child => extractFromElement(child))\n }\n }\n }\n \n svgTree.children.forEach(child => extractFromElement(child))\n \n return points\n }\n}\n\n"],"mappings":"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","names":["stripStart","d"]}
@@ -0,0 +1,83 @@
1
+ import {
2
+ useRevokeBlobUrl
3
+ } from "./chunk-VXJWGLZ7.js";
4
+
5
+ // src/components/ViewerCore/PowerPointCore.tsx
6
+ import { useEffect, useState, useRef } from "react";
7
+ import { jsx, jsxs } from "react/jsx-runtime";
8
+ var PowerPointCore = ({
9
+ src,
10
+ className,
11
+ loadingLabel
12
+ }) => {
13
+ const [error, setError] = useState();
14
+ const [loading, setLoading] = useState(true);
15
+ const containerRef = useRef(null);
16
+ const previewerRef = useRef(null);
17
+ useRevokeBlobUrl(src);
18
+ useEffect(() => {
19
+ if (!src || !containerRef.current) return;
20
+ let cancelled = false;
21
+ (async () => {
22
+ try {
23
+ setLoading(true);
24
+ setError(void 0);
25
+ const { resolveToArrayBuffer } = await import("./resolveToArrayBuffer-AQIDZHSQ.js");
26
+ const buf = await resolveToArrayBuffer(src);
27
+ if (cancelled) return;
28
+ const { init } = await import("pptx-preview");
29
+ const el = containerRef.current;
30
+ el.innerHTML = "";
31
+ const containerWidth = el.clientWidth || 600;
32
+ const width = containerWidth;
33
+ const height = Math.round(width * 0.75);
34
+ const previewer = init(el, { width, height, mode: "slide" });
35
+ previewerRef.current = previewer;
36
+ await previewer.preview(buf);
37
+ if (cancelled) {
38
+ previewer.destroy();
39
+ return;
40
+ }
41
+ const wrapper = el.firstElementChild;
42
+ if (wrapper) {
43
+ const renderedW = wrapper.scrollWidth;
44
+ if (renderedW > containerWidth) {
45
+ const scale = containerWidth / renderedW;
46
+ wrapper.style.transform = `scale(${scale})`;
47
+ wrapper.style.transformOrigin = "top left";
48
+ wrapper.style.width = `${renderedW}px`;
49
+ el.style.height = `${Math.round(wrapper.scrollHeight * scale)}px`;
50
+ }
51
+ }
52
+ } catch (err) {
53
+ if (!cancelled) setError(String(err?.message ?? err));
54
+ } finally {
55
+ if (!cancelled) setLoading(false);
56
+ }
57
+ })();
58
+ return () => {
59
+ cancelled = true;
60
+ if (previewerRef.current) {
61
+ try {
62
+ previewerRef.current.destroy();
63
+ } catch {
64
+ }
65
+ previewerRef.current = null;
66
+ }
67
+ };
68
+ }, [src]);
69
+ if (error) {
70
+ return /* @__PURE__ */ jsx("div", { className: `ycw-ppt-viewer ${className || ""}`, children: /* @__PURE__ */ jsx("div", { className: "ycw-viewer-error", children: error }) });
71
+ }
72
+ return /* @__PURE__ */ jsxs("div", { className: `ycw-ppt-viewer ${className || ""}`, children: [
73
+ loading && /* @__PURE__ */ jsx("div", { className: "ycw-viewer-loading", children: loadingLabel || "Loading\u2026" }),
74
+ /* @__PURE__ */ jsx("div", { ref: containerRef, className: "ycw-ppt-stage" })
75
+ ] });
76
+ };
77
+ var PowerPointCore_default = PowerPointCore;
78
+
79
+ export {
80
+ PowerPointCore,
81
+ PowerPointCore_default
82
+ };
83
+ //# sourceMappingURL=chunk-PZXSASDY.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/ViewerCore/PowerPointCore.tsx"],"sourcesContent":["import React, { useEffect, useState, useRef, useCallback } from 'react'\nimport { useRevokeBlobUrl } from './hooks/useRevokeBlobUrl.js'\n\nexport interface PowerPointCoreProps {\n src?: string\n className?: string\n onLinkClick?: (url: string) => void\n loadingLabel?: string\n prevLabel?: string\n nextLabel?: string\n slideLabel?: string\n thumbnailsLabel?: string\n}\n\nexport const PowerPointCore: React.FC<PowerPointCoreProps> = ({\n src, className, loadingLabel,\n}) => {\n const [error, setError] = useState<string>()\n const [loading, setLoading] = useState(true)\n const containerRef = useRef<HTMLDivElement>(null)\n const previewerRef = useRef<any>(null)\n\n useRevokeBlobUrl(src)\n\n useEffect(() => {\n if (!src || !containerRef.current) return\n let cancelled = false\n\n ;(async () => {\n try {\n setLoading(true)\n setError(undefined)\n\n const { resolveToArrayBuffer } = await import('./utils/resolveToArrayBuffer.js')\n const buf = await resolveToArrayBuffer(src)\n if (cancelled) return\n\n const { init } = await import('pptx-preview')\n const el = containerRef.current!\n el.innerHTML = ''\n\n const containerWidth = el.clientWidth || 600\n const width = containerWidth\n const height = Math.round(width * 0.75)\n\n const previewer = init(el, { width, height, mode: 'slide' })\n previewerRef.current = previewer\n\n await previewer.preview(buf)\n if (cancelled) { previewer.destroy(); return }\n\n // Scale rendered content to fit container if it overflows\n const wrapper = el.firstElementChild as HTMLElement | null\n if (wrapper) {\n const renderedW = wrapper.scrollWidth\n if (renderedW > containerWidth) {\n const scale = containerWidth / renderedW\n wrapper.style.transform = `scale(${scale})`\n wrapper.style.transformOrigin = 'top left'\n wrapper.style.width = `${renderedW}px`\n el.style.height = `${Math.round(wrapper.scrollHeight * scale)}px`\n }\n }\n } catch (err) {\n if (!cancelled) setError(String((err as Error)?.message ?? err))\n } finally {\n if (!cancelled) setLoading(false)\n }\n })()\n\n return () => {\n cancelled = true\n if (previewerRef.current) {\n try { previewerRef.current.destroy() } catch {}\n previewerRef.current = null\n }\n }\n }, [src])\n\n if (error) {\n return <div className={`ycw-ppt-viewer ${className || ''}`}>\n <div className=\"ycw-viewer-error\">{error}</div>\n </div>\n }\n\n return (\n <div className={`ycw-ppt-viewer ${className || ''}`}>\n {loading && <div className=\"ycw-viewer-loading\">{loadingLabel || 'Loading…'}</div>}\n <div ref={containerRef} className=\"ycw-ppt-stage\" />\n </div>\n )\n}\n\nexport default PowerPointCore\n"],"mappings":";;;;;AAAA,SAAgB,WAAW,UAAU,cAA2B;AAiF1D,cAKF,YALE;AAnEC,IAAM,iBAAgD,CAAC;AAAA,EAC5D;AAAA,EAAK;AAAA,EAAW;AAClB,MAAM;AACJ,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAiB;AAC3C,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,IAAI;AAC3C,QAAM,eAAe,OAAuB,IAAI;AAChD,QAAM,eAAe,OAAY,IAAI;AAErC,mBAAiB,GAAG;AAEpB,YAAU,MAAM;AACd,QAAI,CAAC,OAAO,CAAC,aAAa,QAAS;AACnC,QAAI,YAAY;AAEf,KAAC,YAAY;AACZ,UAAI;AACF,mBAAW,IAAI;AACf,iBAAS,MAAS;AAElB,cAAM,EAAE,qBAAqB,IAAI,MAAM,OAAO,oCAAiC;AAC/E,cAAM,MAAM,MAAM,qBAAqB,GAAG;AAC1C,YAAI,UAAW;AAEf,cAAM,EAAE,KAAK,IAAI,MAAM,OAAO,cAAc;AAC5C,cAAM,KAAK,aAAa;AACxB,WAAG,YAAY;AAEf,cAAM,iBAAiB,GAAG,eAAe;AACzC,cAAM,QAAQ;AACd,cAAM,SAAS,KAAK,MAAM,QAAQ,IAAI;AAEtC,cAAM,YAAY,KAAK,IAAI,EAAE,OAAO,QAAQ,MAAM,QAAQ,CAAC;AAC3D,qBAAa,UAAU;AAEvB,cAAM,UAAU,QAAQ,GAAG;AAC3B,YAAI,WAAW;AAAE,oBAAU,QAAQ;AAAG;AAAA,QAAO;AAG7C,cAAM,UAAU,GAAG;AACnB,YAAI,SAAS;AACX,gBAAM,YAAY,QAAQ;AAC1B,cAAI,YAAY,gBAAgB;AAC9B,kBAAM,QAAQ,iBAAiB;AAC/B,oBAAQ,MAAM,YAAY,SAAS,KAAK;AACxC,oBAAQ,MAAM,kBAAkB;AAChC,oBAAQ,MAAM,QAAQ,GAAG,SAAS;AAClC,eAAG,MAAM,SAAS,GAAG,KAAK,MAAM,QAAQ,eAAe,KAAK,CAAC;AAAA,UAC/D;AAAA,QACF;AAAA,MACF,SAAS,KAAK;AACZ,YAAI,CAAC,UAAW,UAAS,OAAQ,KAAe,WAAW,GAAG,CAAC;AAAA,MACjE,UAAE;AACA,YAAI,CAAC,UAAW,YAAW,KAAK;AAAA,MAClC;AAAA,IACF,GAAG;AAEH,WAAO,MAAM;AACX,kBAAY;AACZ,UAAI,aAAa,SAAS;AACxB,YAAI;AAAE,uBAAa,QAAQ,QAAQ;AAAA,QAAE,QAAQ;AAAA,QAAC;AAC9C,qBAAa,UAAU;AAAA,MACzB;AAAA,IACF;AAAA,EACF,GAAG,CAAC,GAAG,CAAC;AAER,MAAI,OAAO;AACT,WAAO,oBAAC,SAAI,WAAW,kBAAkB,aAAa,EAAE,IACtD,8BAAC,SAAI,WAAU,oBAAoB,iBAAM,GAC3C;AAAA,EACF;AAEA,SACE,qBAAC,SAAI,WAAW,kBAAkB,aAAa,EAAE,IAC9C;AAAA,eAAW,oBAAC,SAAI,WAAU,sBAAsB,0BAAgB,iBAAW;AAAA,IAC5E,oBAAC,SAAI,KAAK,cAAc,WAAU,iBAAgB;AAAA,KACpD;AAEJ;AAEA,IAAO,yBAAQ;","names":[]}