ocs-calculators 0.1.0 → 0.1.2
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.
- package/CHANGELOG.md +45 -4
- package/README.md +47 -5
- package/README_EN.md +11 -5
- package/dist/ampacity/index.cjs +17 -0
- package/dist/ampacity/index.cjs.map +1 -0
- package/dist/ampacity/index.d.cts +68 -0
- package/dist/ampacity/index.d.ts +68 -0
- package/dist/ampacity/index.js +17 -0
- package/dist/ampacity/index.js.map +1 -0
- package/dist/chunk-3ERFRRHZ.cjs +119 -0
- package/dist/chunk-3ERFRRHZ.cjs.map +1 -0
- package/dist/chunk-4UU7WA7N.cjs +107 -0
- package/dist/chunk-4UU7WA7N.cjs.map +1 -0
- package/dist/chunk-5INEDXRY.cjs +69 -0
- package/dist/chunk-5INEDXRY.cjs.map +1 -0
- package/dist/chunk-5Q6IASB2.cjs +101 -0
- package/dist/chunk-5Q6IASB2.cjs.map +1 -0
- package/dist/chunk-746H65EQ.js +91 -0
- package/dist/chunk-746H65EQ.js.map +1 -0
- package/dist/chunk-CVA4EH2K.js +102 -0
- package/dist/chunk-CVA4EH2K.js.map +1 -0
- package/dist/chunk-DGO2DCO5.cjs +19 -0
- package/dist/chunk-DGO2DCO5.cjs.map +1 -0
- package/dist/chunk-FVESJBUD.cjs +95 -0
- package/dist/chunk-FVESJBUD.cjs.map +1 -0
- package/dist/chunk-GN6QNOUL.js +91 -0
- package/dist/chunk-GN6QNOUL.js.map +1 -0
- package/dist/chunk-IFVYGNT3.js +107 -0
- package/dist/chunk-IFVYGNT3.js.map +1 -0
- package/dist/chunk-IUENDAAJ.js +67 -0
- package/dist/chunk-IUENDAAJ.js.map +1 -0
- package/dist/chunk-J2UXRMTU.cjs +126 -0
- package/dist/chunk-J2UXRMTU.cjs.map +1 -0
- package/dist/chunk-KOSC6EA3.js +101 -0
- package/dist/chunk-KOSC6EA3.js.map +1 -0
- package/dist/chunk-LDSV3U4M.js +69 -0
- package/dist/chunk-LDSV3U4M.js.map +1 -0
- package/dist/chunk-MZBQ4546.cjs +102 -0
- package/dist/chunk-MZBQ4546.cjs.map +1 -0
- package/dist/chunk-NBFOB2PI.cjs +91 -0
- package/dist/chunk-NBFOB2PI.cjs.map +1 -0
- package/dist/chunk-NBHEOJ5A.cjs +88 -0
- package/dist/chunk-NBHEOJ5A.cjs.map +1 -0
- package/dist/chunk-P6KUGPHD.cjs +91 -0
- package/dist/chunk-P6KUGPHD.cjs.map +1 -0
- package/dist/chunk-QTPXTDGY.js +119 -0
- package/dist/chunk-QTPXTDGY.js.map +1 -0
- package/dist/chunk-RPKDEFSJ.cjs +78 -0
- package/dist/chunk-RPKDEFSJ.cjs.map +1 -0
- package/dist/chunk-RVG3LEZQ.js +95 -0
- package/dist/chunk-RVG3LEZQ.js.map +1 -0
- package/dist/chunk-RVP3IU2L.cjs +67 -0
- package/dist/chunk-RVP3IU2L.cjs.map +1 -0
- package/dist/chunk-UO2PHBC3.js +126 -0
- package/dist/chunk-UO2PHBC3.js.map +1 -0
- package/dist/chunk-VAHQDIMW.js +88 -0
- package/dist/chunk-VAHQDIMW.js.map +1 -0
- package/dist/chunk-WPMKM6NL.js +78 -0
- package/dist/chunk-WPMKM6NL.js.map +1 -0
- package/dist/chunk-YHDO6XVM.js +19 -0
- package/dist/chunk-YHDO6XVM.js.map +1 -0
- package/dist/copper/index.cjs +12 -0
- package/dist/copper/index.cjs.map +1 -0
- package/dist/copper/index.d.cts +57 -0
- package/dist/copper/index.d.ts +57 -0
- package/dist/copper/index.js +12 -0
- package/dist/copper/index.js.map +1 -0
- package/dist/curve-stagger/index.cjs +17 -0
- package/dist/curve-stagger/index.cjs.map +1 -0
- package/dist/curve-stagger/index.d.cts +77 -0
- package/dist/curve-stagger/index.d.ts +77 -0
- package/dist/curve-stagger/index.js +17 -0
- package/dist/curve-stagger/index.js.map +1 -0
- package/dist/dropper/index.cjs +15 -0
- package/dist/dropper/index.cjs.map +1 -0
- package/dist/dropper/index.d.cts +84 -0
- package/dist/dropper/index.d.ts +84 -0
- package/dist/dropper/index.js +15 -0
- package/dist/dropper/index.js.map +1 -0
- package/dist/force/index.cjs +17 -0
- package/dist/force/index.cjs.map +1 -0
- package/dist/force/index.d.cts +69 -0
- package/dist/force/index.d.ts +69 -0
- package/dist/force/index.js +17 -0
- package/dist/force/index.js.map +1 -0
- package/dist/icing/index.cjs +9 -0
- package/dist/icing/index.cjs.map +1 -0
- package/dist/icing/index.d.cts +43 -0
- package/dist/icing/index.d.ts +43 -0
- package/dist/icing/index.js +9 -0
- package/dist/icing/index.js.map +1 -0
- package/dist/index.cjs +162 -1220
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +47 -775
- package/dist/index.d.ts +47 -775
- package/dist/index.js +108 -1063
- package/dist/index.js.map +1 -1
- package/dist/stroke/index.cjs +19 -0
- package/dist/stroke/index.cjs.map +1 -0
- package/dist/stroke/index.d.cts +63 -0
- package/dist/stroke/index.d.ts +63 -0
- package/dist/stroke/index.js +19 -0
- package/dist/stroke/index.js.map +1 -0
- package/dist/tension/index.cjs +19 -0
- package/dist/tension/index.cjs.map +1 -0
- package/dist/tension/index.d.cts +85 -0
- package/dist/tension/index.d.ts +85 -0
- package/dist/tension/index.js +19 -0
- package/dist/tension/index.js.map +1 -0
- package/dist/types-C2OanO8N.d.cts +33 -0
- package/dist/types-C2OanO8N.d.ts +33 -0
- package/dist/voltage-drop/index.cjs +12 -0
- package/dist/voltage-drop/index.cjs.map +1 -0
- package/dist/voltage-drop/index.d.cts +40 -0
- package/dist/voltage-drop/index.d.ts +40 -0
- package/dist/voltage-drop/index.js +12 -0
- package/dist/voltage-drop/index.js.map +1 -0
- package/dist/wavespeed/index.cjs +17 -0
- package/dist/wavespeed/index.cjs.map +1 -0
- package/dist/wavespeed/index.d.cts +58 -0
- package/dist/wavespeed/index.d.ts +58 -0
- package/dist/wavespeed/index.js +17 -0
- package/dist/wavespeed/index.js.map +1 -0
- package/dist/wear/index.cjs +13 -0
- package/dist/wear/index.cjs.map +1 -0
- package/dist/wear/index.d.cts +55 -0
- package/dist/wear/index.d.ts +55 -0
- package/dist/wear/index.js +13 -0
- package/dist/wear/index.js.map +1 -0
- package/dist/wind/index.cjs +15 -0
- package/dist/wind/index.cjs.map +1 -0
- package/dist/wind/index.d.cts +66 -0
- package/dist/wind/index.d.ts +66 -0
- package/dist/wind/index.js +15 -0
- package/dist/wind/index.js.map +1 -0
- package/package.json +64 -3
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
// src/tension/meta.ts
|
|
2
|
+
var tensionMeta = {
|
|
3
|
+
name: "\u5F20\u529B-\u6E29\u5EA6\u5B89\u88C5\u66F2\u7EBF",
|
|
4
|
+
nameEn: "Tension-Temperature Installation Curve",
|
|
5
|
+
summary: "\u6309\u5F20\u529B-\u6E29\u5EA6\u72B6\u6001\u65B9\u7A0B\u6C42\u89E3\u5404\u6E29\u5EA6\u6863\u7684\u65BD\u5DE5\u5F20\u529B\u4E0E\u5F1B\u5EA6\uFF0C\u751F\u6210\u5B89\u88C5\u66F2\u7EBF\u8868\uFF1B\u652F\u6301\u5F53\u91CF\u8DE8\u8DDD\uFF08\u591A\u8DE8\u951A\u6BB5\uFF09\u4E0E\u8986\u51B0\u5DE5\u51B5\u6821\u6838\u3002",
|
|
6
|
+
formula: [
|
|
7
|
+
"\u72B6\u6001\u65B9\u7A0B\uFF1AT\u2082 \u2212 g\u2082\xB2l\xB2EA/(24T\u2082\xB2) = T\u2081 \u2212 g\u2081\xB2l\xB2EA/(24T\u2081\xB2) \u2212 \u03B1EA(t\u2082 \u2212 t\u2081)",
|
|
8
|
+
"\u8DE8\u4E2D\u5F1B\u5EA6\uFF08\u629B\u7269\u7EBF\u8FD1\u4F3C\uFF09\uFF1Af = gl\xB2/(8T)",
|
|
9
|
+
"\u5F53\u91CF\u8DE8\u8DDD\uFF1Al_D = \u221A(\u03A3l\u1D62\xB3 / \u03A3l\u1D62)",
|
|
10
|
+
"\u8986\u51B0\u8377\u8F7D\uFF08\u51B0\u7B52\u6A21\u578B\uFF09\uFF1Ag_ice = \u03C1_ice \xB7 g\u2080 \xB7 \u03C0 \xB7 b \xB7 (d + b)"
|
|
11
|
+
],
|
|
12
|
+
references: [
|
|
13
|
+
"TB 10009-2016\u300A\u94C1\u8DEF\u7535\u529B\u7275\u5F15\u4F9B\u7535\u8BBE\u8BA1\u89C4\u8303\u300B\u2014\u2014 \u4EC5\u89C4\u5B9A\u63A5\u89E6\u7EBF\u6700\u5C0F\u5F20\u529B\u3001\u5F20\u529B\u786E\u5B9A\u539F\u5219\u4E0E\u5F20\u529B\u5DEE\u9650\u503C\uFF0C\u4E0D\u542B\u5F20\u529B-\u6E29\u5EA6\u72B6\u6001\u65B9\u7A0B\u672C\u8EAB",
|
|
14
|
+
"\u5F20\u529B-\u6E29\u5EA6\u72B6\u6001\u65B9\u7A0B\u4E3A\u901A\u7528\u67D4\u7D22\u72B6\u6001\u65B9\u7A0B\uFF0C\u5177\u4F53\u5F62\u5F0F\u4EE5\u8BBE\u8BA1\u6587\u4EF6\u53CA\u63A5\u89E6\u7F51\u8BBE\u8BA1\u6559\u6750/\u624B\u518C\u4E3A\u51C6",
|
|
15
|
+
"\u7EBF\u6750 E / \u03B1 / \u7EBF\u5BC6\u5EA6\u4E3A\u6807\u79F0\u53C2\u8003\u503C\uFF0C\u5B9E\u9645\u4EE5\u4EA7\u54C1\u6280\u672F\u6761\u4EF6\u4E3A\u51C6"
|
|
16
|
+
],
|
|
17
|
+
scope: [
|
|
18
|
+
"\u5F39\u6027\u6A21\u91CF E\uFF1A50 ~ 200 GPa",
|
|
19
|
+
"\u622A\u9762\u79EF A\uFF1A50 ~ 250 mm\xB2",
|
|
20
|
+
"\u8DE8\u8DDD l\uFF1A20 ~ 90 m",
|
|
21
|
+
"\u5F1B\u5EA6\u91C7\u7528\u629B\u7269\u7EBF\u8FD1\u4F3C\uFF0C\u4E0D\u9002\u7528\u4E8E\u5927\u5F1B\u5EA6\uFF08f/l > 1/10\uFF09\u5DE5\u51B5",
|
|
22
|
+
"\u8986\u51B0\u6A21\u578B\u4E3A\u5747\u5300\u51B0\u7B52\u5047\u8BBE\uFF0C\u4E0D\u8003\u8651\u4E0D\u5747\u5300\u8986\u51B0\u4E0E\u8131\u51B0\u8DF3\u8DC3"
|
|
23
|
+
],
|
|
24
|
+
disclaimer: "\u672C\u5DE5\u5177\u7ED3\u679C\u4EC5\u4F9B\u53C2\u8003\uFF0C\u5DE5\u7A0B\u5E94\u7528\u4EE5\u8BBE\u8BA1\u6587\u4EF6\u4E3A\u51C6\u3002\u8BE6\u89C1 DISCLAIMER.md\u3002",
|
|
25
|
+
online: "https://www.itswe.com/calculator/tension/"
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
// src/tension/index.ts
|
|
29
|
+
function sagM(weightPerLengthNPerM, spanM, tensionN) {
|
|
30
|
+
if (!(tensionN > 0)) {
|
|
31
|
+
throw new RangeError(`\u5F20\u529B\u5FC5\u987B\u4E3A\u6B63\u6570\uFF0C\u6536\u5230 ${tensionN} N`);
|
|
32
|
+
}
|
|
33
|
+
return weightPerLengthNPerM * spanM * spanM / (8 * tensionN);
|
|
34
|
+
}
|
|
35
|
+
function equivalentSpanM(spansM) {
|
|
36
|
+
if (spansM.length === 0) {
|
|
37
|
+
throw new RangeError("\u8DE8\u8DDD\u6570\u7EC4\u4E0D\u80FD\u4E3A\u7A7A");
|
|
38
|
+
}
|
|
39
|
+
let sumCubed = 0;
|
|
40
|
+
let sum = 0;
|
|
41
|
+
for (const s of spansM) {
|
|
42
|
+
if (!(s > 0)) {
|
|
43
|
+
throw new RangeError(`\u8DE8\u8DDD\u5FC5\u987B\u4E3A\u6B63\u6570\uFF0C\u6536\u5230 ${s}`);
|
|
44
|
+
}
|
|
45
|
+
sumCubed += s * s * s;
|
|
46
|
+
sum += s;
|
|
47
|
+
}
|
|
48
|
+
return Math.sqrt(sumCubed / sum);
|
|
49
|
+
}
|
|
50
|
+
function stateCoefficientK(weightPerLengthNPerM, spanM, elasticModulusGPa, crossSectionMM2) {
|
|
51
|
+
const ePa = elasticModulusGPa * 1e9;
|
|
52
|
+
const aM2 = crossSectionMM2 * 1e-6;
|
|
53
|
+
return weightPerLengthNPerM * weightPerLengthNPerM * spanM * spanM * ePa * aM2 / 24;
|
|
54
|
+
}
|
|
55
|
+
function solveTensionN(K, targetN) {
|
|
56
|
+
const hOf = (t) => t - K / (t * t) - targetN;
|
|
57
|
+
let lo = Math.max(targetN, 1e-9);
|
|
58
|
+
let hi = lo + 1;
|
|
59
|
+
let guard = 0;
|
|
60
|
+
while (hOf(hi) < 0 && guard++ < 200) {
|
|
61
|
+
hi = lo + (hi - lo) * 2;
|
|
62
|
+
if (!Number.isFinite(hi)) break;
|
|
63
|
+
}
|
|
64
|
+
let iterations = 0;
|
|
65
|
+
for (let i = 0; i < 200; i++) {
|
|
66
|
+
iterations = i + 1;
|
|
67
|
+
const mid = 0.5 * (lo + hi);
|
|
68
|
+
if (hOf(mid) < 0) {
|
|
69
|
+
lo = mid;
|
|
70
|
+
} else {
|
|
71
|
+
hi = mid;
|
|
72
|
+
}
|
|
73
|
+
if (hi - lo <= 1e-12 * Math.max(1, hi)) break;
|
|
74
|
+
}
|
|
75
|
+
const tensionN = 0.5 * (lo + hi);
|
|
76
|
+
return { tensionN, iterations, residualN: hOf(tensionN) };
|
|
77
|
+
}
|
|
78
|
+
function tensionAt(input) {
|
|
79
|
+
const T1N = input.baseTensionKN * 1e3;
|
|
80
|
+
if (!(T1N > 0)) {
|
|
81
|
+
throw new RangeError(`\u57FA\u51C6\u5F20\u529B\u5FC5\u987B\u4E3A\u6B63\u6570\uFF0C\u6536\u5230 ${input.baseTensionKN} kN`);
|
|
82
|
+
}
|
|
83
|
+
if (!(input.spanM > 0)) {
|
|
84
|
+
throw new RangeError(`\u8DE8\u8DDD\u5FC5\u987B\u4E3A\u6B63\u6570\uFF0C\u6536\u5230 ${input.spanM} m`);
|
|
85
|
+
}
|
|
86
|
+
const K = stateCoefficientK(
|
|
87
|
+
input.weightPerLengthNPerM,
|
|
88
|
+
input.spanM,
|
|
89
|
+
input.elasticModulusGPa,
|
|
90
|
+
input.crossSectionMM2
|
|
91
|
+
);
|
|
92
|
+
const ePa = input.elasticModulusGPa * 1e9;
|
|
93
|
+
const aM2 = input.crossSectionMM2 * 1e-6;
|
|
94
|
+
const alphaEA = input.expansionPerDegC * ePa * aM2;
|
|
95
|
+
const fBase = T1N - K / (T1N * T1N);
|
|
96
|
+
const target = fBase - alphaEA * (input.targetTempDegC - input.baseTempDegC);
|
|
97
|
+
const { tensionN, iterations, residualN } = solveTensionN(K, target);
|
|
98
|
+
return {
|
|
99
|
+
targetTempDegC: input.targetTempDegC,
|
|
100
|
+
tensionKN: tensionN / 1e3,
|
|
101
|
+
sagM: sagM(input.weightPerLengthNPerM, input.spanM, tensionN),
|
|
102
|
+
iterations,
|
|
103
|
+
residualN
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
function tensionCurve(base, tempsDegC) {
|
|
107
|
+
return tempsDegC.map((t) => tensionAt({ ...base, targetTempDegC: t }));
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export {
|
|
111
|
+
tensionMeta,
|
|
112
|
+
sagM,
|
|
113
|
+
equivalentSpanM,
|
|
114
|
+
stateCoefficientK,
|
|
115
|
+
solveTensionN,
|
|
116
|
+
tensionAt,
|
|
117
|
+
tensionCurve
|
|
118
|
+
};
|
|
119
|
+
//# sourceMappingURL=chunk-QTPXTDGY.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/tension/meta.ts","../src/tension/index.ts"],"sourcesContent":["import type { CalculatorMeta } from '../types';\n\nexport const tensionMeta: CalculatorMeta = {\n name: '张力-温度安装曲线',\n nameEn: 'Tension-Temperature Installation Curve',\n summary:\n '按张力-温度状态方程求解各温度档的施工张力与弛度,生成安装曲线表;支持当量跨距(多跨锚段)与覆冰工况校核。',\n formula: [\n '状态方程:T₂ − g₂²l²EA/(24T₂²) = T₁ − g₁²l²EA/(24T₁²) − αEA(t₂ − t₁)',\n '跨中弛度(抛物线近似):f = gl²/(8T)',\n '当量跨距:l_D = √(Σlᵢ³ / Σlᵢ)',\n '覆冰荷载(冰筒模型):g_ice = ρ_ice · g₀ · π · b · (d + b)',\n ],\n references: [\n 'TB 10009-2016《铁路电力牵引供电设计规范》—— 仅规定接触线最小张力、张力确定原则与张力差限值,不含张力-温度状态方程本身',\n '张力-温度状态方程为通用柔索状态方程,具体形式以设计文件及接触网设计教材/手册为准',\n '线材 E / α / 线密度为标称参考值,实际以产品技术条件为准',\n ],\n scope: [\n '弹性模量 E:50 ~ 200 GPa',\n '截面积 A:50 ~ 250 mm²',\n '跨距 l:20 ~ 90 m',\n '弛度采用抛物线近似,不适用于大弛度(f/l > 1/10)工况',\n '覆冰模型为均匀冰筒假设,不考虑不均匀覆冰与脱冰跳跃',\n ],\n disclaimer: '本工具结果仅供参考,工程应用以设计文件为准。详见 DISCLAIMER.md。',\n online: 'https://www.itswe.com/calculator/tension/',\n};\n","export { tensionMeta } from './meta';\n\n/** 单个温度档的输入参数 */\nexport interface TensionPointInput {\n /** 基准工况张力 T₁,kN */\n readonly baseTensionKN: number;\n /** 基准温度 t₁,℃ */\n readonly baseTempDegC: number;\n /** 目标温度 t₂,℃ */\n readonly targetTempDegC: number;\n /** 单位自重荷载 g,N/m(覆冰工况传自重与冰重的组合值) */\n readonly weightPerLengthNPerM: number;\n /** 计算跨距 l,m(多跨锚段传当量跨距 l_D) */\n readonly spanM: number;\n /** 弹性模量 E,GPa */\n readonly elasticModulusGPa: number;\n /** 截面积 A,mm² */\n readonly crossSectionMM2: number;\n /** 线膨胀系数 α,1/℃ */\n readonly expansionPerDegC: number;\n}\n\n/** 安装曲线公共参数(不含目标温度) */\nexport type TensionCurveInput = Omit<TensionPointInput, 'targetTempDegC'>;\n\n/** 单个温度档的计算结果 */\nexport interface TensionResult {\n /** 目标温度 t₂,℃ */\n readonly targetTempDegC: number;\n /** 该温度下的张力 T₂,kN */\n readonly tensionKN: number;\n /** 跨中弛度 f,m(抛物线近似) */\n readonly sagM: number;\n /** 求解迭代次数 */\n readonly iterations: number;\n /** 状态方程残差,N(用于校验收敛,应接近 0) */\n readonly residualN: number;\n}\n\n/**\n * 跨中弛度,抛物线近似:f = gl²/(8T)\n * @param weightPerLengthNPerM 单位自重荷载 g,N/m\n * @param spanM 跨距 l,m\n * @param tensionN 张力 T,N\n * @returns 弛度 f,m\n */\nexport function sagM(\n weightPerLengthNPerM: number,\n spanM: number,\n tensionN: number,\n): number {\n if (!(tensionN > 0)) {\n throw new RangeError(`张力必须为正数,收到 ${tensionN} N`);\n }\n return (weightPerLengthNPerM * spanM * spanM) / (8 * tensionN);\n}\n\n/**\n * 当量跨距(多跨锚段归算):l_D = √(Σlᵢ³ / Σlᵢ)\n * @param spansM 各跨跨距,m\n * @returns 当量跨距 l_D,m\n */\nexport function equivalentSpanM(spansM: readonly number[]): number {\n if (spansM.length === 0) {\n throw new RangeError('跨距数组不能为空');\n }\n let sumCubed = 0;\n let sum = 0;\n for (const s of spansM) {\n if (!(s > 0)) {\n throw new RangeError(`跨距必须为正数,收到 ${s}`);\n }\n sumCubed += s * s * s;\n sum += s;\n }\n return Math.sqrt(sumCubed / sum);\n}\n\n/**\n * 覆冰荷载(均匀冰筒模型)与 icing 模块共用 `src/common/ice.ts`,\n * 由根 index 统一导出,此处不再重复定义。\n */\n\n/**\n * 状态方程系数 K = g²l²EA/24,单位 N³。\n * 使状态方程可写成 F(T) = T − K/T² 的紧凑形式。\n */\nexport function stateCoefficientK(\n weightPerLengthNPerM: number,\n spanM: number,\n elasticModulusGPa: number,\n crossSectionMM2: number,\n): number {\n const ePa = elasticModulusGPa * 1e9;\n const aM2 = crossSectionMM2 * 1e-6;\n return (weightPerLengthNPerM * weightPerLengthNPerM * spanM * spanM * ePa * aM2) / 24;\n}\n\n/**\n * 求解状态方程 T − K/T² = target 的正根。\n *\n * h(T) = T − K/T² − target 在 T > 0 上严格单调递增(h′ = 1 + 2K/T³ > 0),\n * 因此用二分法必定收敛。又由 T = target + K/T² 可知 T > target,\n * 可直接取 target 作为下界,bracket 很紧。\n */\nexport function solveTensionN(\n K: number,\n targetN: number,\n): { tensionN: number; iterations: number; residualN: number } {\n const hOf = (t: number): number => t - K / (t * t) - targetN;\n\n let lo = Math.max(targetN, 1e-9);\n let hi = lo + 1;\n let guard = 0;\n while (hOf(hi) < 0 && guard++ < 200) {\n hi = lo + (hi - lo) * 2;\n if (!Number.isFinite(hi)) break;\n }\n\n let iterations = 0;\n for (let i = 0; i < 200; i++) {\n iterations = i + 1;\n const mid = 0.5 * (lo + hi);\n if (hOf(mid) < 0) {\n lo = mid;\n } else {\n hi = mid;\n }\n if (hi - lo <= 1e-12 * Math.max(1, hi)) break;\n }\n\n const tensionN = 0.5 * (lo + hi);\n return { tensionN, iterations, residualN: hOf(tensionN) };\n}\n\n/**\n * 求某一温度档的张力与弛度。\n *\n * 状态方程:T₂ − g²l²EA/(24T₂²) = T₁ − g²l²EA/(24T₁²) − αEA(t₂ − t₁)\n */\nexport function tensionAt(input: TensionPointInput): TensionResult {\n const T1N = input.baseTensionKN * 1000;\n if (!(T1N > 0)) {\n throw new RangeError(`基准张力必须为正数,收到 ${input.baseTensionKN} kN`);\n }\n if (!(input.spanM > 0)) {\n throw new RangeError(`跨距必须为正数,收到 ${input.spanM} m`);\n }\n\n const K = stateCoefficientK(\n input.weightPerLengthNPerM,\n input.spanM,\n input.elasticModulusGPa,\n input.crossSectionMM2,\n );\n const ePa = input.elasticModulusGPa * 1e9;\n const aM2 = input.crossSectionMM2 * 1e-6;\n const alphaEA = input.expansionPerDegC * ePa * aM2;\n\n const fBase = T1N - K / (T1N * T1N);\n const target = fBase - alphaEA * (input.targetTempDegC - input.baseTempDegC);\n\n const { tensionN, iterations, residualN } = solveTensionN(K, target);\n\n return {\n targetTempDegC: input.targetTempDegC,\n tensionKN: tensionN / 1000,\n sagM: sagM(input.weightPerLengthNPerM, input.spanM, tensionN),\n iterations,\n residualN,\n };\n}\n\n/**\n * 批量求解多个温度档,生成安装曲线表。\n */\nexport function tensionCurve(\n base: TensionCurveInput,\n tempsDegC: readonly number[],\n): TensionResult[] {\n return tempsDegC.map((t) => tensionAt({ ...base, targetTempDegC: t }));\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }// src/force/meta.ts
|
|
2
|
+
var forceMeta = {
|
|
3
|
+
name: "\u5F13\u7F51\u63A5\u89E6\u529B\u7EDF\u8BA1\u8BC4\u4EF7",
|
|
4
|
+
nameEn: "Pantograph-Catenary Contact Force Statistical Assessment",
|
|
5
|
+
summary: "\u6309 EN 50367 \u7EDF\u8BA1\u8BC4\u4EF7\u4F53\u7CFB\uFF0C\u7531\u5E73\u5747\u63A5\u89E6\u529B Fm \u4E0E\u6807\u51C6\u5DEE \u03C3 \u8BA1\u7B97 Fmax=Fm+3\u03C3\u3001Fmin=Fm\u22123\u03C3\uFF0C\u5BF9\u7167\u9A8C\u6536\u9650\u503C\u7ED9\u51FA\u5224\u5B9A\uFF0C\u9002\u7528\u4E8E C1 \u68C0\u6D4B\u6570\u636E\u8BC4\u4EF7\u3002",
|
|
6
|
+
formula: [
|
|
7
|
+
"\u7EDF\u8BA1\u8BC4\u4EF7\uFF1AFmax = Fm + 3\u03C3\uFF0CFmin = Fm \u2212 3\u03C3",
|
|
8
|
+
"\u53C2\u8003\u76EE\u6807\u529B\uFF08AC \u4F53\u7CFB\uFF09\uFF1AFref = 0.00097\xB7v\xB2 + 70\uFF08v \u5355\u4F4D km/h\uFF09",
|
|
9
|
+
"DC 3kV \u4F53\u7CFB\uFF1AFref = 0.00097\xB7v\xB2 + 110",
|
|
10
|
+
"DC 1.5kV \u4F53\u7CFB\uFF1AFref = 0.00097\xB7v\xB2 + 140"
|
|
11
|
+
],
|
|
12
|
+
references: [
|
|
13
|
+
"\u7EDF\u8BA1\u8BC4\u4EF7\u6846\u67B6\u4F9D\u636E EN 50367\uFF1B\u6D4B\u91CF\u65B9\u6CD5\u89C1 EN 50317",
|
|
14
|
+
"AC \u4F53\u7CFB\u5E38\u6570\u5F15\u81EA EN 50367 \u88686\uFF1BDC \u4F53\u7CFB\u5E38\u6570\u5F15\u81EA TSI ENE 2011/274/EU",
|
|
15
|
+
"\u9A8C\u6536\u4E0A\u4E0B\u9650\u987B\u6309\u73B0\u884C\u9A8C\u6536\u5927\u7EB2/\u5408\u540C\u586B\u5199\uFF0C\u672C\u6A21\u5757\u4E0D\u5185\u7F6E\u9650\u503C",
|
|
16
|
+
"v = 200 km/h \u65F6 AC \u4F53\u7CFB Fref = 108.8 N"
|
|
17
|
+
],
|
|
18
|
+
scope: [
|
|
19
|
+
"Fm \u4E0E \u03C3 \u5E94\u53D6\u81EA\u540C\u4E00\u68C0\u6D4B\u533A\u6BB5\u7684\u7EDF\u8BA1\u503C\uFF08C1 \u68C0\u6D4B\u6570\u636E\uFF09",
|
|
20
|
+
"3\u03C3 \u51C6\u5219\u662F\u7EDF\u8BA1\u6781\u503C\u8FD1\u4F3C\uFF0C\u4E0D\u66FF\u4EE3\u9010\u70B9\u8D85\u9650\u7EDF\u8BA1",
|
|
21
|
+
"\u672A\u8003\u8651\u79BB\u7EBF\u7387\u3001\u71C3\u5F27\u7387\u7B49\u5176\u4ED6\u63A5\u89E6\u8D28\u91CF\u6307\u6807",
|
|
22
|
+
"\u5206\u6863\u8868\u503C\u4E0E\u5141\u5DEE\u5E26\u4EE5\u6807\u51C6\u539F\u6587\u4E3A\u51C6"
|
|
23
|
+
],
|
|
24
|
+
disclaimer: "\u672C\u5DE5\u5177\u7ED3\u679C\u4EC5\u4F9B\u53C2\u8003\uFF0C\u5DE5\u7A0B\u5E94\u7528\u4EE5\u8BBE\u8BA1\u6587\u4EF6\u4E3A\u51C6\u3002\u8BE6\u89C1 DISCLAIMER.md\u3002",
|
|
25
|
+
online: "https://www.itswe.com/calculator/force/"
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
// src/force/index.ts
|
|
29
|
+
var REF_TARGET_COEFF = 97e-5;
|
|
30
|
+
var REF_TARGET_OFFSET_N = {
|
|
31
|
+
ac: 70,
|
|
32
|
+
dc3kv: 110,
|
|
33
|
+
dc15kv: 140
|
|
34
|
+
};
|
|
35
|
+
function referenceTargetForceN(speedKmH, system = "ac") {
|
|
36
|
+
if (!(speedKmH >= 0)) {
|
|
37
|
+
throw new RangeError(`\u901F\u5EA6\u4E0D\u80FD\u4E3A\u8D1F\uFF0C\u6536\u5230 ${speedKmH} km/h`);
|
|
38
|
+
}
|
|
39
|
+
return REF_TARGET_COEFF * speedKmH * speedKmH + REF_TARGET_OFFSET_N[system];
|
|
40
|
+
}
|
|
41
|
+
function statisticalForcesN(meanForceN, stdDevN) {
|
|
42
|
+
if (!(meanForceN > 0)) {
|
|
43
|
+
throw new RangeError(`\u5E73\u5747\u63A5\u89E6\u529B\u5FC5\u987B\u4E3A\u6B63\u6570\uFF0C\u6536\u5230 ${meanForceN} N`);
|
|
44
|
+
}
|
|
45
|
+
if (!(stdDevN >= 0)) {
|
|
46
|
+
throw new RangeError(`\u6807\u51C6\u5DEE\u4E0D\u80FD\u4E3A\u8D1F\uFF0C\u6536\u5230 ${stdDevN} N`);
|
|
47
|
+
}
|
|
48
|
+
const threeSigma = 3 * stdDevN;
|
|
49
|
+
return { maxN: meanForceN + threeSigma, minN: meanForceN - threeSigma };
|
|
50
|
+
}
|
|
51
|
+
function assessContactForce(input) {
|
|
52
|
+
const { meanForceN, stdDevN, speedKmH, maxLimitN, minLimitN } = input;
|
|
53
|
+
const { maxN, minN } = statisticalForcesN(meanForceN, stdDevN);
|
|
54
|
+
const referenceTargetN = speedKmH === null ? null : referenceTargetForceN(speedKmH, _nullishCoalesce(input.system, () => ( "ac")));
|
|
55
|
+
const meanDeviationN = referenceTargetN === null ? null : meanForceN - referenceTargetN;
|
|
56
|
+
const maxVerdict = maxLimitN === null ? "not-assessed" : maxN <= maxLimitN ? "pass" : "fail";
|
|
57
|
+
const minVerdict = minLimitN === null ? "not-assessed" : minN >= minLimitN ? "pass" : "fail";
|
|
58
|
+
return {
|
|
59
|
+
meanForceN,
|
|
60
|
+
stdDevN,
|
|
61
|
+
maxForceN: maxN,
|
|
62
|
+
minForceN: minN,
|
|
63
|
+
referenceTargetN,
|
|
64
|
+
meanDeviationN,
|
|
65
|
+
maxVerdict,
|
|
66
|
+
minVerdict
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
exports.forceMeta = forceMeta; exports.REF_TARGET_COEFF = REF_TARGET_COEFF; exports.REF_TARGET_OFFSET_N = REF_TARGET_OFFSET_N; exports.referenceTargetForceN = referenceTargetForceN; exports.statisticalForcesN = statisticalForcesN; exports.assessContactForce = assessContactForce;
|
|
78
|
+
//# sourceMappingURL=chunk-RPKDEFSJ.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/home/runner/work/ocs-calculators/ocs-calculators/dist/chunk-RPKDEFSJ.cjs","../src/force/meta.ts","../src/force/index.ts"],"names":[],"mappings":"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","file":"/home/runner/work/ocs-calculators/ocs-calculators/dist/chunk-RPKDEFSJ.cjs","sourcesContent":[null,"import type { CalculatorMeta } from '../types';\n\nexport const forceMeta: CalculatorMeta = {\n name: '弓网接触力统计评价',\n nameEn: 'Pantograph-Catenary Contact Force Statistical Assessment',\n summary:\n '按 EN 50367 统计评价体系,由平均接触力 Fm 与标准差 σ 计算 Fmax=Fm+3σ、Fmin=Fm−3σ,对照验收限值给出判定,适用于 C1 检测数据评价。',\n formula: [\n '统计评价:Fmax = Fm + 3σ,Fmin = Fm − 3σ',\n '参考目标力(AC 体系):Fref = 0.00097·v² + 70(v 单位 km/h)',\n 'DC 3kV 体系:Fref = 0.00097·v² + 110',\n 'DC 1.5kV 体系:Fref = 0.00097·v² + 140',\n ],\n references: [\n '统计评价框架依据 EN 50367;测量方法见 EN 50317',\n 'AC 体系常数引自 EN 50367 表6;DC 体系常数引自 TSI ENE 2011/274/EU',\n '验收上下限须按现行验收大纲/合同填写,本模块不内置限值',\n 'v = 200 km/h 时 AC 体系 Fref = 108.8 N',\n ],\n scope: [\n 'Fm 与 σ 应取自同一检测区段的统计值(C1 检测数据)',\n '3σ 准则是统计极值近似,不替代逐点超限统计',\n '未考虑离线率、燃弧率等其他接触质量指标',\n '分档表值与允差带以标准原文为准',\n ],\n disclaimer: '本工具结果仅供参考,工程应用以设计文件为准。详见 DISCLAIMER.md。',\n online: 'https://www.itswe.com/calculator/force/',\n};\n","export { forceMeta } from './meta';\n\n/** 供电制式,决定参考目标力 Fref 的常数项 */\nexport type PowerSystem = 'ac' | 'dc3kv' | 'dc15kv';\n\n/** 限值判定结果 */\nexport type LimitVerdict = 'pass' | 'fail' | 'not-assessed';\n\n/** Fref = 0.00097·v² + offset,offset 按供电制式取值 */\nexport const REF_TARGET_COEFF = 0.00097;\n\n/** 参考目标力常数项,N。AC 引自 EN 50367 表6,DC 引自 TSI ENE 2011/274/EU */\nexport const REF_TARGET_OFFSET_N: Record<PowerSystem, number> = {\n ac: 70,\n dc3kv: 110,\n dc15kv: 140,\n};\n\nexport interface ContactForceInput {\n /** 平均接触力 Fm,N(同一 C1 检测区段统计均值) */\n readonly meanForceN: number;\n /** 标准差 σ,N(同一区段统计标准差) */\n readonly stdDevN: number;\n /** 速度 v,km/h。传 null 则不输出参考目标力 */\n readonly speedKmH: number | null;\n /** 验收上限 Fmax,lim,N。传 null 则不判定 */\n readonly maxLimitN: number | null;\n /** 验收下限 Fmin,lim,N。传 null 则不判定 */\n readonly minLimitN: number | null;\n /** 供电制式。缺省为交流 */\n readonly system?: PowerSystem;\n}\n\nexport interface ContactForceResult {\n readonly meanForceN: number;\n readonly stdDevN: number;\n /** 统计最大力 Fmax = Fm + 3σ,N */\n readonly maxForceN: number;\n /** 统计最小力 Fmin = Fm − 3σ,N */\n readonly minForceN: number;\n /** 参考目标力 Fref,N。未提供速度时为 null */\n readonly referenceTargetN: number | null;\n /** 均值对参考目标的偏差 Fm − Fref,N。未提供速度时为 null */\n readonly meanDeviationN: number | null;\n /** 上限判定 */\n readonly maxVerdict: LimitVerdict;\n /** 下限判定 */\n readonly minVerdict: LimitVerdict;\n}\n\n/**\n * 参考目标力 Fref,N。\n *\n * Fref = 0.00097·v² + offset\n *\n * @param speedKmH 速度 v,km/h\n * @param system 供电制式,缺省 'ac'\n * @returns 参考目标力,N\n */\nexport function referenceTargetForceN(\n speedKmH: number,\n system: PowerSystem = 'ac',\n): number {\n if (!(speedKmH >= 0)) {\n throw new RangeError(`速度不能为负,收到 ${speedKmH} km/h`);\n }\n return REF_TARGET_COEFF * speedKmH * speedKmH + REF_TARGET_OFFSET_N[system];\n}\n\n/**\n * 统计极值:Fmax = Fm + 3σ,Fmin = Fm − 3σ。\n *\n * @returns 统计最大力与最小力,N\n */\nexport function statisticalForcesN(\n meanForceN: number,\n stdDevN: number,\n): { readonly maxN: number; readonly minN: number } {\n if (!(meanForceN > 0)) {\n throw new RangeError(`平均接触力必须为正数,收到 ${meanForceN} N`);\n }\n if (!(stdDevN >= 0)) {\n throw new RangeError(`标准差不能为负,收到 ${stdDevN} N`);\n }\n const threeSigma = 3 * stdDevN;\n return { maxN: meanForceN + threeSigma, minN: meanForceN - threeSigma };\n}\n\n/**\n * 弓网接触力统计评价(EN 50367 框架)。\n *\n * 上下限传 null 表示该侧不参与判定,对应判定结果为 'not-assessed'。\n */\nexport function assessContactForce(input: ContactForceInput): ContactForceResult {\n const { meanForceN, stdDevN, speedKmH, maxLimitN, minLimitN } = input;\n\n const { maxN, minN } = statisticalForcesN(meanForceN, stdDevN);\n\n const referenceTargetN = speedKmH === null ? null : referenceTargetForceN(speedKmH, input.system ?? 'ac');\n const meanDeviationN =\n referenceTargetN === null ? null : meanForceN - referenceTargetN;\n\n const maxVerdict: LimitVerdict =\n maxLimitN === null ? 'not-assessed' : maxN <= maxLimitN ? 'pass' : 'fail';\n const minVerdict: LimitVerdict =\n minLimitN === null ? 'not-assessed' : minN >= minLimitN ? 'pass' : 'fail';\n\n return {\n meanForceN,\n stdDevN,\n maxForceN: maxN,\n minForceN: minN,\n referenceTargetN,\n meanDeviationN,\n maxVerdict,\n minVerdict,\n };\n}\n"]}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
// src/wind/meta.ts
|
|
2
|
+
var windMeta = {
|
|
3
|
+
name: "\u98CE\u504F\u9650\u754C\u6821\u9A8C",
|
|
4
|
+
nameEn: "Wind Deflection Clearance Check",
|
|
5
|
+
summary: "\u8BA1\u7B97\u7EBF\u7D22\u5728\u98CE\u8377\u8F7D\u4F5C\u7528\u4E0B\u7684\u8DE8\u4E2D\u504F\u79FB b\uFF0C\u53E0\u52A0\u62C9\u51FA\u503C\u540E\u4E0E\u9650\u754C\u5141\u8BB8\u503C\u6BD4\u8F83\uFF0C\u7ED9\u51FA\u5408\u683C/\u8D85\u9650\u7ED3\u8BBA\u3002",
|
|
6
|
+
formula: [
|
|
7
|
+
"\u5355\u4F4D\u98CE\u8377\u8F7D\uFF1Ap = \xBD\xB7\u03C1\xB7v\xB2\xB7d\xB7\u03B1\xB7sin\xB2\u03B8\uFF08\u03C1 = 1.225 kg/m\xB3\uFF09",
|
|
8
|
+
"\u8DE8\u4E2D\u98CE\u504F\uFF08\u7B80\u652F\u7D22\u629B\u7269\u7EBF\u8FD1\u4F3C\uFF09\uFF1Ab = p\xB7L\xB2 / (8\xB7T)",
|
|
9
|
+
"\u9650\u754C\u6821\u9A8C\uFF1Ab + a \u2264 \u9650\u754C\u5141\u8BB8\u503C\uFF0C\u6EE1\u8DB3\u5224\u4E3A\u5408\u683C"
|
|
10
|
+
],
|
|
11
|
+
references: [
|
|
12
|
+
"\u7B80\u652F\u7D22\u629B\u7269\u7EBF\u8FD1\u4F3C\uFF0C\u9002\u7528\u4E8E f/L \u2264 1/10 \u5DE5\u51B5",
|
|
13
|
+
"\u98CE\u8F7D\u4F53\u578B\u7CFB\u6570 \u03B1\uFF1A\u5706\u67F1\u5F62\u7EBF\u7D22\u5E38\u53D6 1.2",
|
|
14
|
+
"\u9650\u754C\u5141\u8BB8\u503C\u6309\u53D7\u7535\u5F13\u52A8\u6001\u5305\u7EDC\u7EBF\u53D6\u503C"
|
|
15
|
+
],
|
|
16
|
+
scope: [
|
|
17
|
+
"\u98CE\u901F v\uFF1A0 ~ 60 m/s",
|
|
18
|
+
"\u98CE\u5411\u4E0E\u7EBF\u8DEF\u5939\u89D2 \u03B8\uFF1A0 ~ 180\xB0\uFF0C90\xB0 \u4E3A\u5782\u76F4\u4E8E\u7EBF\u8DEF",
|
|
19
|
+
"\u7EBF\u7D22\u76F4\u5F84 d\uFF1A1 ~ 30 mm",
|
|
20
|
+
"\u7EBF\u7D22\u5F20\u529B T\uFF1A1 ~ 40 kN",
|
|
21
|
+
"\u8DE8\u8DDD L\uFF1A5 ~ 80 m",
|
|
22
|
+
"\u98CE\u8F7D\u4F53\u578B\u7CFB\u6570 \u03B1\uFF1A0.5 ~ 2.0",
|
|
23
|
+
"\u62C9\u51FA\u503C a\uFF1A0 ~ 0.6 m",
|
|
24
|
+
"\u9650\u754C\u5141\u8BB8\u503C\uFF1A0.1 ~ 2 m",
|
|
25
|
+
"\u672A\u8BA1\u5165\u7EBF\u7D22\u98CE\u81F4\u632F\u52A8\u3001\u9A70\u632F\u4E0E\u8986\u51B0\u9644\u52A0\u98CE\u8F7D"
|
|
26
|
+
],
|
|
27
|
+
disclaimer: "\u672C\u5DE5\u5177\u7ED3\u679C\u4EC5\u4F9B\u53C2\u8003\uFF0C\u5DE5\u7A0B\u5E94\u7528\u4EE5\u8BBE\u8BA1\u6587\u4EF6\u4E3A\u51C6\u3002\u8BE6\u89C1 DISCLAIMER.md\u3002",
|
|
28
|
+
online: "https://www.itswe.com/calculator/wind/"
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
// src/wind/index.ts
|
|
32
|
+
var AIR_DENSITY_KG_PER_M3 = 1.225;
|
|
33
|
+
function windLoadNPerM(params) {
|
|
34
|
+
const { windSpeedMPerS, windAngleDeg, wireDiameterMM, dragCoefficient, airDensityKgPerM3 } = params;
|
|
35
|
+
if (!(windSpeedMPerS >= 0)) {
|
|
36
|
+
throw new RangeError(`\u98CE\u901F\u4E0D\u80FD\u4E3A\u8D1F\uFF0C\u6536\u5230 ${windSpeedMPerS} m/s`);
|
|
37
|
+
}
|
|
38
|
+
if (!(wireDiameterMM > 0)) {
|
|
39
|
+
throw new RangeError(`\u7EBF\u7D22\u76F4\u5F84\u5FC5\u987B\u4E3A\u6B63\u6570\uFF0C\u6536\u5230 ${wireDiameterMM} mm`);
|
|
40
|
+
}
|
|
41
|
+
if (!(dragCoefficient > 0)) {
|
|
42
|
+
throw new RangeError(`\u98CE\u8F7D\u4F53\u578B\u7CFB\u6570\u5FC5\u987B\u4E3A\u6B63\u6570\uFF0C\u6536\u5230 ${dragCoefficient}`);
|
|
43
|
+
}
|
|
44
|
+
if (!(windAngleDeg >= 0 && windAngleDeg <= 180)) {
|
|
45
|
+
throw new RangeError(`\u98CE\u5411\u4E0E\u7EBF\u8DEF\u5939\u89D2\u5E94\u4E3A 0 ~ 180\xB0\uFF0C\u6536\u5230 ${windAngleDeg}\xB0`);
|
|
46
|
+
}
|
|
47
|
+
const rho = airDensityKgPerM3 ?? AIR_DENSITY_KG_PER_M3;
|
|
48
|
+
if (!(rho > 0)) {
|
|
49
|
+
throw new RangeError(`\u7A7A\u6C14\u5BC6\u5EA6\u5FC5\u987B\u4E3A\u6B63\u6570\uFF0C\u6536\u5230 ${rho} kg/m\xB3`);
|
|
50
|
+
}
|
|
51
|
+
const dM = wireDiameterMM * 1e-3;
|
|
52
|
+
const sinTheta = Math.sin(windAngleDeg * Math.PI / 180);
|
|
53
|
+
return 0.5 * rho * windSpeedMPerS * windSpeedMPerS * dM * dragCoefficient * sinTheta * sinTheta;
|
|
54
|
+
}
|
|
55
|
+
function windDeflectionM(windLoadNPerM2, spanM, tensionKN) {
|
|
56
|
+
if (!(windLoadNPerM2 >= 0)) {
|
|
57
|
+
throw new RangeError(`\u5355\u4F4D\u98CE\u8377\u8F7D\u4E0D\u80FD\u4E3A\u8D1F\uFF0C\u6536\u5230 ${windLoadNPerM2} N/m`);
|
|
58
|
+
}
|
|
59
|
+
if (!(spanM > 0)) {
|
|
60
|
+
throw new RangeError(`\u8DE8\u8DDD\u5FC5\u987B\u4E3A\u6B63\u6570\uFF0C\u6536\u5230 ${spanM} m`);
|
|
61
|
+
}
|
|
62
|
+
if (!(tensionKN > 0)) {
|
|
63
|
+
throw new RangeError(`\u7EBF\u7D22\u5F20\u529B\u5FC5\u987B\u4E3A\u6B63\u6570\uFF0C\u6536\u5230 ${tensionKN} kN`);
|
|
64
|
+
}
|
|
65
|
+
return windLoadNPerM2 * spanM * spanM / (8 * tensionKN * 1e3);
|
|
66
|
+
}
|
|
67
|
+
function windClearanceCheck(input) {
|
|
68
|
+
const { staggerM, clearanceLimitM } = input;
|
|
69
|
+
if (!(staggerM >= 0)) {
|
|
70
|
+
throw new RangeError(`\u62C9\u51FA\u503C\u4E0D\u80FD\u4E3A\u8D1F\uFF0C\u6536\u5230 ${staggerM} m`);
|
|
71
|
+
}
|
|
72
|
+
if (!(clearanceLimitM > 0)) {
|
|
73
|
+
throw new RangeError(`\u9650\u754C\u5141\u8BB8\u503C\u5FC5\u987B\u4E3A\u6B63\u6570\uFF0C\u6536\u5230 ${clearanceLimitM} m`);
|
|
74
|
+
}
|
|
75
|
+
const p = windLoadNPerM(input);
|
|
76
|
+
const b = windDeflectionM(p, input.spanM, input.tensionKN);
|
|
77
|
+
const totalOffsetM = b + staggerM;
|
|
78
|
+
return {
|
|
79
|
+
windLoadNPerM: p,
|
|
80
|
+
deflectionM: b,
|
|
81
|
+
totalOffsetM,
|
|
82
|
+
clearanceLimitM,
|
|
83
|
+
marginM: clearanceLimitM - totalOffsetM,
|
|
84
|
+
passes: totalOffsetM <= clearanceLimitM
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export {
|
|
89
|
+
windMeta,
|
|
90
|
+
AIR_DENSITY_KG_PER_M3,
|
|
91
|
+
windLoadNPerM,
|
|
92
|
+
windDeflectionM,
|
|
93
|
+
windClearanceCheck
|
|
94
|
+
};
|
|
95
|
+
//# sourceMappingURL=chunk-RVG3LEZQ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/wind/meta.ts","../src/wind/index.ts"],"sourcesContent":["import type { CalculatorMeta } from '../types';\n\nexport const windMeta: CalculatorMeta = {\n name: '风偏限界校验',\n nameEn: 'Wind Deflection Clearance Check',\n summary:\n '计算线索在风荷载作用下的跨中偏移 b,叠加拉出值后与限界允许值比较,给出合格/超限结论。',\n formula: [\n '单位风荷载:p = ½·ρ·v²·d·α·sin²θ(ρ = 1.225 kg/m³)',\n '跨中风偏(简支索抛物线近似):b = p·L² / (8·T)',\n '限界校验:b + a ≤ 限界允许值,满足判为合格',\n ],\n references: [\n '简支索抛物线近似,适用于 f/L ≤ 1/10 工况',\n '风载体型系数 α:圆柱形线索常取 1.2',\n '限界允许值按受电弓动态包络线取值',\n ],\n scope: [\n '风速 v:0 ~ 60 m/s',\n '风向与线路夹角 θ:0 ~ 180°,90° 为垂直于线路',\n '线索直径 d:1 ~ 30 mm',\n '线索张力 T:1 ~ 40 kN',\n '跨距 L:5 ~ 80 m',\n '风载体型系数 α:0.5 ~ 2.0',\n '拉出值 a:0 ~ 0.6 m',\n '限界允许值:0.1 ~ 2 m',\n '未计入线索风致振动、驰振与覆冰附加风载',\n ],\n disclaimer: '本工具结果仅供参考,工程应用以设计文件为准。详见 DISCLAIMER.md。',\n online: 'https://www.itswe.com/calculator/wind/',\n};\n","export { windMeta } from './meta';\n\n/** 标准大气空气密度,kg/m³ */\nexport const AIR_DENSITY_KG_PER_M3 = 1.225;\n\n/** 风荷载计算的输入参数 */\nexport interface WindLoadInput {\n /** 风速 v,m/s */\n readonly windSpeedMPerS: number;\n /** 风向与线路夹角 θ,度。90° 表示风垂直于线路 */\n readonly windAngleDeg: number;\n /** 线索直径 d,mm */\n readonly wireDiameterMM: number;\n /** 风载体型系数 α(阻力系数),圆柱形线索常取 1.2 */\n readonly dragCoefficient: number;\n /** 空气密度 ρ,kg/m³。缺省为标准大气 1.225 */\n readonly airDensityKgPerM3?: number;\n}\n\n/**\n * 单位风荷载(Janssen 公式):p = ½·ρ·v²·d·α·sin²θ,N/m。\n * 线索直径按 mm → m 换算(×1e-3)。\n */\nexport function windLoadNPerM(params: WindLoadInput): number {\n const { windSpeedMPerS, windAngleDeg, wireDiameterMM, dragCoefficient, airDensityKgPerM3 } = params;\n\n if (!(windSpeedMPerS >= 0)) {\n throw new RangeError(`风速不能为负,收到 ${windSpeedMPerS} m/s`);\n }\n if (!(wireDiameterMM > 0)) {\n throw new RangeError(`线索直径必须为正数,收到 ${wireDiameterMM} mm`);\n }\n if (!(dragCoefficient > 0)) {\n throw new RangeError(`风载体型系数必须为正数,收到 ${dragCoefficient}`);\n }\n if (!(windAngleDeg >= 0 && windAngleDeg <= 180)) {\n throw new RangeError(`风向与线路夹角应为 0 ~ 180°,收到 ${windAngleDeg}°`);\n }\n const rho = airDensityKgPerM3 ?? AIR_DENSITY_KG_PER_M3;\n if (!(rho > 0)) {\n throw new RangeError(`空气密度必须为正数,收到 ${rho} kg/m³`);\n }\n\n const dM = wireDiameterMM * 1e-3;\n const sinTheta = Math.sin((windAngleDeg * Math.PI) / 180);\n return 0.5 * rho * windSpeedMPerS * windSpeedMPerS * dM * dragCoefficient * sinTheta * sinTheta;\n}\n\n/**\n * 跨中风偏(简支索抛物线近似):b = p·L² / (8·T),m。\n *\n * @param windLoadNPerM 单位风荷载 p,N/m\n * @param spanM 跨距 L,m\n * @param tensionKN 线索张力 T,kN(内部 ×1e3 化 N)\n */\nexport function windDeflectionM(windLoadNPerM: number, spanM: number, tensionKN: number): number {\n if (!(windLoadNPerM >= 0)) {\n throw new RangeError(`单位风荷载不能为负,收到 ${windLoadNPerM} N/m`);\n }\n if (!(spanM > 0)) {\n throw new RangeError(`跨距必须为正数,收到 ${spanM} m`);\n }\n if (!(tensionKN > 0)) {\n throw new RangeError(`线索张力必须为正数,收到 ${tensionKN} kN`);\n }\n return (windLoadNPerM * spanM * spanM) / (8 * tensionKN * 1e3);\n}\n\n/** 风偏限界校验输入:风荷载参数 + 张力/跨距/拉出值/限界允许值 */\nexport interface WindClearanceInput extends WindLoadInput {\n /** 线索张力 T,kN */\n readonly tensionKN: number;\n /** 跨距 L,m */\n readonly spanM: number;\n /** 拉出值 a,m */\n readonly staggerM: number;\n /** 限界允许值,m */\n readonly clearanceLimitM: number;\n}\n\n/** 风偏限界校验结果 */\nexport interface WindClearanceResult {\n /** 单位风荷载 p,N/m */\n readonly windLoadNPerM: number;\n /** 跨中风偏 b,m */\n readonly deflectionM: number;\n /** 风偏 + 拉出值 b + a,m */\n readonly totalOffsetM: number;\n /** 限界允许值,m */\n readonly clearanceLimitM: number;\n /** 富余量 = 限界允许值 − (b + a),m。负值表示超限 */\n readonly marginM: number;\n /** 是否合格 */\n readonly passes: boolean;\n}\n\n/**\n * 风偏限界校验:计算跨中风偏 b,叠加拉出值 a,与限界允许值比较。\n *\n * 判据:b + a ≤ 限界允许值 → 合格。\n */\nexport function windClearanceCheck(input: WindClearanceInput): WindClearanceResult {\n const { staggerM, clearanceLimitM } = input;\n\n if (!(staggerM >= 0)) {\n throw new RangeError(`拉出值不能为负,收到 ${staggerM} m`);\n }\n if (!(clearanceLimitM > 0)) {\n throw new RangeError(`限界允许值必须为正数,收到 ${clearanceLimitM} m`);\n }\n\n const p = windLoadNPerM(input);\n const b = windDeflectionM(p, input.spanM, input.tensionKN);\n const totalOffsetM = b + staggerM;\n\n return {\n windLoadNPerM: p,\n deflectionM: b,\n totalOffsetM,\n clearanceLimitM,\n marginM: clearanceLimitM - totalOffsetM,\n passes: totalOffsetM <= clearanceLimitM,\n };\n}\n"],"mappings":";AAEO,IAAM,WAA2B;AAAA,EACtC,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,SACE;AAAA,EACF,SAAS;AAAA,IACP;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,YAAY;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,OAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,YAAY;AAAA,EACZ,QAAQ;AACV;;;AC3BO,IAAM,wBAAwB;AAoB9B,SAAS,cAAc,QAA+B;AAC3D,QAAM,EAAE,gBAAgB,cAAc,gBAAgB,iBAAiB,kBAAkB,IAAI;AAE7F,MAAI,EAAE,kBAAkB,IAAI;AAC1B,UAAM,IAAI,WAAW,0DAAa,cAAc,MAAM;AAAA,EACxD;AACA,MAAI,EAAE,iBAAiB,IAAI;AACzB,UAAM,IAAI,WAAW,4EAAgB,cAAc,KAAK;AAAA,EAC1D;AACA,MAAI,EAAE,kBAAkB,IAAI;AAC1B,UAAM,IAAI,WAAW,wFAAkB,eAAe,EAAE;AAAA,EAC1D;AACA,MAAI,EAAE,gBAAgB,KAAK,gBAAgB,MAAM;AAC/C,UAAM,IAAI,WAAW,wFAAyB,YAAY,MAAG;AAAA,EAC/D;AACA,QAAM,MAAM,qBAAqB;AACjC,MAAI,EAAE,MAAM,IAAI;AACd,UAAM,IAAI,WAAW,4EAAgB,GAAG,WAAQ;AAAA,EAClD;AAEA,QAAM,KAAK,iBAAiB;AAC5B,QAAM,WAAW,KAAK,IAAK,eAAe,KAAK,KAAM,GAAG;AACxD,SAAO,MAAM,MAAM,iBAAiB,iBAAiB,KAAK,kBAAkB,WAAW;AACzF;AASO,SAAS,gBAAgBA,gBAAuB,OAAe,WAA2B;AAC/F,MAAI,EAAEA,kBAAiB,IAAI;AACzB,UAAM,IAAI,WAAW,4EAAgBA,cAAa,MAAM;AAAA,EAC1D;AACA,MAAI,EAAE,QAAQ,IAAI;AAChB,UAAM,IAAI,WAAW,gEAAc,KAAK,IAAI;AAAA,EAC9C;AACA,MAAI,EAAE,YAAY,IAAI;AACpB,UAAM,IAAI,WAAW,4EAAgB,SAAS,KAAK;AAAA,EACrD;AACA,SAAQA,iBAAgB,QAAQ,SAAU,IAAI,YAAY;AAC5D;AAmCO,SAAS,mBAAmB,OAAgD;AACjF,QAAM,EAAE,UAAU,gBAAgB,IAAI;AAEtC,MAAI,EAAE,YAAY,IAAI;AACpB,UAAM,IAAI,WAAW,gEAAc,QAAQ,IAAI;AAAA,EACjD;AACA,MAAI,EAAE,kBAAkB,IAAI;AAC1B,UAAM,IAAI,WAAW,kFAAiB,eAAe,IAAI;AAAA,EAC3D;AAEA,QAAM,IAAI,cAAc,KAAK;AAC7B,QAAM,IAAI,gBAAgB,GAAG,MAAM,OAAO,MAAM,SAAS;AACzD,QAAM,eAAe,IAAI;AAEzB,SAAO;AAAA,IACL,eAAe;AAAA,IACf,aAAa;AAAA,IACb;AAAA,IACA;AAAA,IACA,SAAS,kBAAkB;AAAA,IAC3B,QAAQ,gBAAgB;AAAA,EAC1B;AACF;","names":["windLoadNPerM"]}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }
|
|
2
|
+
|
|
3
|
+
var _chunkDGO2DCO5cjs = require('./chunk-DGO2DCO5.cjs');
|
|
4
|
+
|
|
5
|
+
// src/voltage-drop/meta.ts
|
|
6
|
+
var voltageDropMeta = {
|
|
7
|
+
name: "\u7535\u538B\u964D\u6821\u6838",
|
|
8
|
+
nameEn: "Voltage Drop Check",
|
|
9
|
+
summary: "\u6309\u6E29\u5EA6\u4FEE\u6B63\u540E\u7684\u5355\u4F4D\u7535\u963B\u8BA1\u7B97\u4F9B\u7535\u81C2\u7535\u538B\u635F\u5931 \u0394U \u4E0E\u672B\u7AEF\u7535\u538B\uFF0C\u7528\u4E8E\u4F9B\u7535\u81C2\u957F\u5EA6\u4E0E\u5BFC\u7EBF\u622A\u9762\u6821\u6838\u3002",
|
|
10
|
+
formula: [
|
|
11
|
+
"\u5355\u4F4D\u7535\u963B\u6E29\u5EA6\u4FEE\u6B63\uFF1Ar_T = r\u2082\u2080\xB7[1 + \u03B1\xB7(T \u2212 20)]\uFF08\u03B1 = 0.00393 /\u2103\uFF09",
|
|
12
|
+
"\u5E76\u8054 n \u8DEF\u65F6\uFF1Ar_T / n",
|
|
13
|
+
"\u7535\u538B\u635F\u5931\uFF1A\u0394U = I \xB7 r_T \xB7 L\uFF08r_T \u5355\u4F4D \u03A9/km\uFF0CL \u5355\u4F4D km\uFF09",
|
|
14
|
+
"\u672B\u7AEF\u7535\u538B\uFF1AU_end = U\u2080 \u2212 \u0394U\uFF1B\u538B\u964D\u7387 = \u0394U / U\u2080"
|
|
15
|
+
],
|
|
16
|
+
references: [
|
|
17
|
+
"\u4F9D\u636E\u672C\u7AD9 \u4F9B\u7535\u8BA1\u7B97 / \u7535\u6C14\u8BBE\u8BA1 \u6761\u76EE",
|
|
18
|
+
"\u672B\u7AEF\u7535\u538B\u9650\u503C\uFF1A25kV \u4F53\u7CFB\u5E38\u6309 20kV \u638C\u63E1\uFF1B\u5B9E\u9645\u9650\u503C\u4EE5\u8BBE\u8BA1\u6587\u4EF6\u4E0E\u4F9B\u7535\u8BA1\u7B97\u4E66\u4E3A\u51C6"
|
|
19
|
+
],
|
|
20
|
+
scope: [
|
|
21
|
+
"\u6BCD\u7EBF\u7535\u538B U\u2080\uFF1A20000 ~ 30000 V",
|
|
22
|
+
"\u6301\u7EED\u7535\u6D41 I\uFF1A10 ~ 3000 A",
|
|
23
|
+
"\u5355\u4F4D\u7535\u963B r\u2082\u2080\uFF1A0.05 ~ 1 \u03A9/km",
|
|
24
|
+
"\u4F9B\u7535\u81C2\u7B49\u6548\u957F\u5EA6 L\uFF1A1 ~ 60 km",
|
|
25
|
+
"\u73AF\u5883\u6E29\u5EA6\uFF1A\u221240 ~ 80 \u2103",
|
|
26
|
+
"\u5355\u56DE\u8DEF\u96C6\u4E2D\u8D1F\u8377\u6A21\u578B\uFF0C\u672A\u8003\u8651\u8D1F\u8377\u6CBF\u4F9B\u7535\u81C2\u5206\u5E03\u4E0E\u518D\u751F\u5236\u52A8"
|
|
27
|
+
],
|
|
28
|
+
disclaimer: "\u672C\u5DE5\u5177\u7ED3\u679C\u4EC5\u4F9B\u53C2\u8003\uFF0C\u5DE5\u7A0B\u5E94\u7528\u4EE5\u8BBE\u8BA1\u6587\u4EF6\u4E3A\u51C6\u3002\u8BE6\u89C1 DISCLAIMER.md\u3002",
|
|
29
|
+
online: "https://www.itswe.com/calculator/voltage-drop/"
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
// src/voltage-drop/index.ts
|
|
33
|
+
var DEFAULT_MIN_END_VOLTAGE_V = 2e4;
|
|
34
|
+
function voltageDropCheck(input) {
|
|
35
|
+
const { busVoltageV, currentA, r20OhmPerKm, feederLengthKm } = input;
|
|
36
|
+
if (!(busVoltageV > 0)) {
|
|
37
|
+
throw new RangeError(`\u6BCD\u7EBF\u7535\u538B\u5FC5\u987B\u4E3A\u6B63\u6570\uFF0C\u6536\u5230 ${busVoltageV} V`);
|
|
38
|
+
}
|
|
39
|
+
if (!(currentA > 0)) {
|
|
40
|
+
throw new RangeError(`\u6301\u7EED\u7535\u6D41\u5FC5\u987B\u4E3A\u6B63\u6570\uFF0C\u6536\u5230 ${currentA} A`);
|
|
41
|
+
}
|
|
42
|
+
if (!(feederLengthKm > 0)) {
|
|
43
|
+
throw new RangeError(`\u4F9B\u7535\u81C2\u957F\u5EA6\u5FC5\u987B\u4E3A\u6B63\u6570\uFF0C\u6536\u5230 ${feederLengthKm} km`);
|
|
44
|
+
}
|
|
45
|
+
const parallelCount = _nullishCoalesce(input.parallelCount, () => ( 1));
|
|
46
|
+
if (!(parallelCount > 0) || !Number.isInteger(parallelCount)) {
|
|
47
|
+
throw new RangeError(`\u5E76\u8054\u5BFC\u7EBF\u6570\u5FC5\u987B\u4E3A\u6B63\u6574\u6570\uFF0C\u6536\u5230 ${parallelCount}`);
|
|
48
|
+
}
|
|
49
|
+
const minEndVoltageV = _nullishCoalesce(input.minEndVoltageV, () => ( DEFAULT_MIN_END_VOLTAGE_V));
|
|
50
|
+
const rT = _chunkDGO2DCO5cjs.resistanceAtTempOhmPerKm.call(void 0, r20OhmPerKm, _nullishCoalesce(input.tempDegC, () => ( 25))) / parallelCount;
|
|
51
|
+
const voltageDropV = currentA * rT * feederLengthKm;
|
|
52
|
+
const endVoltageV = busVoltageV - voltageDropV;
|
|
53
|
+
return {
|
|
54
|
+
rTOhmPerKm: rT,
|
|
55
|
+
voltageDropV,
|
|
56
|
+
endVoltageV,
|
|
57
|
+
dropPercent: voltageDropV / busVoltageV * 100,
|
|
58
|
+
passes: endVoltageV >= minEndVoltageV
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
exports.voltageDropMeta = voltageDropMeta; exports.DEFAULT_MIN_END_VOLTAGE_V = DEFAULT_MIN_END_VOLTAGE_V; exports.voltageDropCheck = voltageDropCheck;
|
|
67
|
+
//# sourceMappingURL=chunk-RVP3IU2L.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/home/runner/work/ocs-calculators/ocs-calculators/dist/chunk-RVP3IU2L.cjs","../src/voltage-drop/meta.ts","../src/voltage-drop/index.ts"],"names":[],"mappings":"AAAA;AACE;AACF,wDAA6B;AAC7B;AACA;ACFO,IAAM,gBAAA,EAAkC;AAAA,EAC7C,IAAA,EAAM,gCAAA;AAAA,EACN,MAAA,EAAQ,oBAAA;AAAA,EACR,OAAA,EACE,iQAAA;AAAA,EACF,OAAA,EAAS;AAAA,IACP,gJAAA;AAAA,IACA,0CAAA;AAAA,IACA,wHAAA;AAAA,IACA;AAAA,EACF,CAAA;AAAA,EACA,UAAA,EAAY;AAAA,IACV,2FAAA;AAAA,IACA;AAAA,EACF,CAAA;AAAA,EACA,KAAA,EAAO;AAAA,IACL,uDAAA;AAAA,IACA,6CAAA;AAAA,IACA,gEAAA;AAAA,IACA,6DAAA;AAAA,IACA,oDAAA;AAAA,IACA;AAAA,EACF,CAAA;AAAA,EACA,UAAA,EAAY,sKAAA;AAAA,EACZ,MAAA,EAAQ;AACV,CAAA;ADGA;AACA;AE5BO,IAAM,0BAAA,EAA4B,GAAA;AAsClC,SAAS,gBAAA,CAAiB,KAAA,EAA4C;AAC3E,EAAA,MAAM,EAAE,WAAA,EAAa,QAAA,EAAU,WAAA,EAAa,eAAe,EAAA,EAAI,KAAA;AAE/D,EAAA,GAAA,CAAI,CAAA,CAAE,YAAA,EAAc,CAAA,CAAA,EAAI;AACtB,IAAA,MAAM,IAAI,UAAA,CAAW,CAAA,yEAAA,EAAgB,WAAW,CAAA,EAAA,CAAI,CAAA;AAAA,EACtD;AACA,EAAA,GAAA,CAAI,CAAA,CAAE,SAAA,EAAW,CAAA,CAAA,EAAI;AACnB,IAAA,MAAM,IAAI,UAAA,CAAW,CAAA,yEAAA,EAAgB,QAAQ,CAAA,EAAA,CAAI,CAAA;AAAA,EACnD;AACA,EAAA,GAAA,CAAI,CAAA,CAAE,eAAA,EAAiB,CAAA,CAAA,EAAI;AACzB,IAAA,MAAM,IAAI,UAAA,CAAW,CAAA,+EAAA,EAAiB,cAAc,CAAA,GAAA,CAAK,CAAA;AAAA,EAC3D;AAEA,EAAA,MAAM,cAAA,mBAAgB,KAAA,CAAM,aAAA,UAAiB,GAAA;AAC7C,EAAA,GAAA,CAAI,CAAA,CAAE,cAAA,EAAgB,CAAA,EAAA,GAAM,CAAC,MAAA,CAAO,SAAA,CAAU,aAAa,CAAA,EAAG;AAC5D,IAAA,MAAM,IAAI,UAAA,CAAW,CAAA,qFAAA,EAAkB,aAAa,CAAA,CAAA;AACtD,EAAA;AAE+C,EAAA;AAGiB,EAAA;AAC3B,EAAA;AACH,EAAA;AAE3B,EAAA;AACO,IAAA;AACZ,IAAA;AACA,IAAA;AAC4C,IAAA;AACrB,IAAA;AACzB,EAAA;AACF;AFb+H;AACA;AACA;AACA;AACA;AACA","file":"/home/runner/work/ocs-calculators/ocs-calculators/dist/chunk-RVP3IU2L.cjs","sourcesContent":[null,"import type { CalculatorMeta } from '../types';\n\nexport const voltageDropMeta: CalculatorMeta = {\n name: '电压降校核',\n nameEn: 'Voltage Drop Check',\n summary:\n '按温度修正后的单位电阻计算供电臂电压损失 ΔU 与末端电压,用于供电臂长度与导线截面校核。',\n formula: [\n '单位电阻温度修正:r_T = r₂₀·[1 + α·(T − 20)](α = 0.00393 /℃)',\n '并联 n 路时:r_T / n',\n '电压损失:ΔU = I · r_T · L(r_T 单位 Ω/km,L 单位 km)',\n '末端电压:U_end = U₀ − ΔU;压降率 = ΔU / U₀',\n ],\n references: [\n '依据本站 供电计算 / 电气设计 条目',\n '末端电压限值:25kV 体系常按 20kV 掌握;实际限值以设计文件与供电计算书为准',\n ],\n scope: [\n '母线电压 U₀:20000 ~ 30000 V',\n '持续电流 I:10 ~ 3000 A',\n '单位电阻 r₂₀:0.05 ~ 1 Ω/km',\n '供电臂等效长度 L:1 ~ 60 km',\n '环境温度:−40 ~ 80 ℃',\n '单回路集中负荷模型,未考虑负荷沿供电臂分布与再生制动',\n ],\n disclaimer: '本工具结果仅供参考,工程应用以设计文件为准。详见 DISCLAIMER.md。',\n online: 'https://www.itswe.com/calculator/voltage-drop/',\n};\n","export { voltageDropMeta } from './meta';\n\n/** 25kV 体系常用的末端电压下限,V */\nexport const DEFAULT_MIN_END_VOLTAGE_V = 20000;\n\n// 电阻温度修正统一来自 src/common/resistance.ts(copper 与 voltage-drop 共用)\nimport { resistanceAtTempOhmPerKm } from '../common/resistance';\n\nexport interface VoltageDropInput {\n /** 变电所母线电压 U₀,V */\n readonly busVoltageV: number;\n /** 持续电流 I,A */\n readonly currentA: number;\n /** 20℃ 单位电阻 r₂₀,Ω/km */\n readonly r20OhmPerKm: number;\n /** 供电臂等效长度 L,km */\n readonly feederLengthKm: number;\n /** 环境温度 T,℃。缺省 25 */\n readonly tempDegC?: number;\n /** 并联导线数。缺省 1 */\n readonly parallelCount?: number;\n /** 末端最低允许电压,V。缺省 20000 */\n readonly minEndVoltageV?: number;\n}\n\nexport interface VoltageDropResult {\n /** 温度修正(并含并联折减)后的单位电阻 r_T,Ω/km */\n readonly rTOhmPerKm: number;\n /** 电压损失 ΔU,V */\n readonly voltageDropV: number;\n /** 末端电压 U_end,V */\n readonly endVoltageV: number;\n /** 压降率,% */\n readonly dropPercent: number;\n /** 末端电压是否满足要求 */\n readonly passes: boolean;\n}\n\n/**\n * 电压降校核:ΔU = I·r_T·L(并联 n 路时 r_T/n),U_end = U₀ − ΔU。\n */\nexport function voltageDropCheck(input: VoltageDropInput): VoltageDropResult {\n const { busVoltageV, currentA, r20OhmPerKm, feederLengthKm } = input;\n\n if (!(busVoltageV > 0)) {\n throw new RangeError(`母线电压必须为正数,收到 ${busVoltageV} V`);\n }\n if (!(currentA > 0)) {\n throw new RangeError(`持续电流必须为正数,收到 ${currentA} A`);\n }\n if (!(feederLengthKm > 0)) {\n throw new RangeError(`供电臂长度必须为正数,收到 ${feederLengthKm} km`);\n }\n\n const parallelCount = input.parallelCount ?? 1;\n if (!(parallelCount > 0) || !Number.isInteger(parallelCount)) {\n throw new RangeError(`并联导线数必须为正整数,收到 ${parallelCount}`);\n }\n\n const minEndVoltageV = input.minEndVoltageV ?? DEFAULT_MIN_END_VOLTAGE_V;\n\n const rT =\n resistanceAtTempOhmPerKm(r20OhmPerKm, input.tempDegC ?? 25) / parallelCount;\n const voltageDropV = currentA * rT * feederLengthKm;\n const endVoltageV = busVoltageV - voltageDropV;\n\n return {\n rTOhmPerKm: rT,\n voltageDropV,\n endVoltageV,\n dropPercent: (voltageDropV / busVoltageV) * 100,\n passes: endVoltageV >= minEndVoltageV,\n };\n}\n"]}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
// src/dropper/meta.ts
|
|
2
|
+
var dropperMeta = {
|
|
3
|
+
name: "\u540A\u5F26\u957F\u5EA6\u8BA1\u7B97",
|
|
4
|
+
nameEn: "Dropper Length Calculator",
|
|
5
|
+
summary: "\u6309\u629B\u7269\u7EBF\u5F1B\u5EA6\u516C\u5F0F\u8BA1\u7B97\u94FE\u5F62\u60AC\u6302\u5404\u540A\u5F26\u957F\u5EA6\uFF0C\u652F\u6301\u7B80\u5355\u94FE\u5F62\u4E0E\u5F39\u6027\u94FE\u5F62\u4E24\u79CD\u60AC\u6302\u7C7B\u578B\u3002",
|
|
6
|
+
formula: [
|
|
7
|
+
"\u63A5\u89E6\u7EBF\u5F1B\u5EA6\uFF08\u629B\u7269\u7EBF\u8FD1\u4F3C\uFF09\uFF1Af_c(x) = q_c\xB7x\xB7(L\u2212x) / (2\xB7T_c)",
|
|
8
|
+
"\u627F\u529B\u7D22\u5F1B\u5EA6\uFF1Af_m(x) = q_m\xB7x\xB7(L\u2212x) / (2\xB7T_m)",
|
|
9
|
+
"\u7B80\u5355\u94FE\u5F62\uFF1Al_i = H \u2212 f_c(x_i)",
|
|
10
|
+
"\u5F39\u6027\u94FE\u5F62\uFF08\u8BA1\u5165\u627F\u529B\u7D22\u5F1B\u5EA6\uFF09\uFF1Al_i = H \u2212 f_c(x_i) + f_m(x_i)",
|
|
11
|
+
"\u8DE8\u4E2D\u6700\u5927\u5F1B\u5EA6\uFF1Af_max = q_c\xB7L\xB2 / (8\xB7T_c)"
|
|
12
|
+
],
|
|
13
|
+
references: [
|
|
14
|
+
"\u629B\u7269\u7EBF\u8FD1\u4F3C\uFF0C\u9002\u7528\u4E8E f/L \u2264 1/10 \u7684\u5C0F\u5F1B\u5EA6\u5DE5\u51B5",
|
|
15
|
+
"\u540A\u5F26\u95F4\u8DDD\u987B\u80FD\u6574\u9664\u8DE8\u8DDD\uFF1B\u5B9E\u9645\u540A\u5F26\u5E03\u7F6E\u4EE5\u8BBE\u8BA1\u6587\u4EF6\u4E3A\u51C6",
|
|
16
|
+
"\u5F39\u6027\u94FE\u5F62\u60AC\u6302\u987B\u540C\u65F6\u63D0\u4F9B\u627F\u529B\u7D22\u5F20\u529B\u4E0E\u5355\u4F4D\u8377\u8F7D"
|
|
17
|
+
],
|
|
18
|
+
scope: [
|
|
19
|
+
"\u8DE8\u8DDD L\uFF1A5 ~ 80 m",
|
|
20
|
+
"\u63A5\u89E6\u7EBF\u5F20\u529B T_c\uFF1A1 ~ 40 kN",
|
|
21
|
+
"\u7ED3\u6784\u9AD8\u5EA6 H\uFF1A0.3 ~ 3 m",
|
|
22
|
+
"\u63A5\u89E6\u7EBF\u5355\u4F4D\u8377\u8F7D q_c\uFF1A0.001 ~ 0.1 kN/m",
|
|
23
|
+
"\u540A\u5F26\u95F4\u8DDD d\uFF1A1 ~ 15 m\uFF0C\u987B\u80FD\u6574\u9664\u8DE8\u8DDD",
|
|
24
|
+
"\u629B\u7269\u7EBF\u8FD1\u4F3C\uFF0C\u5927\u5F1B\u5EA6\u5DE5\u51B5\u8BEF\u5DEE\u589E\u5927",
|
|
25
|
+
"\u672A\u8BA1\u5165\u540A\u5F26\u81EA\u8EAB\u4F38\u957F\u3001\u6E29\u5EA6\u53D8\u5316\u4E0E\u96F6\u90E8\u4EF6\u5236\u9020\u516C\u5DEE"
|
|
26
|
+
],
|
|
27
|
+
disclaimer: "\u672C\u5DE5\u5177\u7ED3\u679C\u4EC5\u4F9B\u53C2\u8003\uFF0C\u5DE5\u7A0B\u5E94\u7528\u4EE5\u8BBE\u8BA1\u6587\u4EF6\u4E3A\u51C6\u3002\u8BE6\u89C1 DISCLAIMER.md\u3002",
|
|
28
|
+
online: "https://www.itswe.com/calculator/dropper/"
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
// src/dropper/index.ts
|
|
32
|
+
function parabolaSagM(xM, spanM, loadKNPerM, tensionKN) {
|
|
33
|
+
if (!(tensionKN > 0)) {
|
|
34
|
+
throw new RangeError(`\u5F20\u529B\u5FC5\u987B\u4E3A\u6B63\u6570\uFF0C\u6536\u5230 ${tensionKN} kN`);
|
|
35
|
+
}
|
|
36
|
+
if (xM < 0 || xM > spanM) {
|
|
37
|
+
throw new RangeError(`\u4F4D\u7F6E x = ${xM} m \u8D85\u51FA\u8DE8\u8DDD 0 ~ ${spanM} m`);
|
|
38
|
+
}
|
|
39
|
+
return loadKNPerM * xM * (spanM - xM) / (2 * tensionKN);
|
|
40
|
+
}
|
|
41
|
+
function maxParabolaSagM(spanM, loadKNPerM, tensionKN) {
|
|
42
|
+
return loadKNPerM * spanM * spanM / (8 * tensionKN);
|
|
43
|
+
}
|
|
44
|
+
function dropperPositionsM(spanM, spacingM) {
|
|
45
|
+
if (!(spanM > 0)) {
|
|
46
|
+
throw new RangeError(`\u8DE8\u8DDD\u5FC5\u987B\u4E3A\u6B63\u6570\uFF0C\u6536\u5230 ${spanM} m`);
|
|
47
|
+
}
|
|
48
|
+
if (!(spacingM > 0)) {
|
|
49
|
+
throw new RangeError(`\u540A\u5F26\u95F4\u8DDD\u5FC5\u987B\u4E3A\u6B63\u6570\uFF0C\u6536\u5230 ${spacingM} m`);
|
|
50
|
+
}
|
|
51
|
+
const intervals = spanM / spacingM;
|
|
52
|
+
const rounded = Math.round(intervals);
|
|
53
|
+
if (Math.abs(intervals - rounded) > 1e-9 || rounded < 1) {
|
|
54
|
+
throw new RangeError(
|
|
55
|
+
`\u540A\u5F26\u95F4\u8DDD ${spacingM} m \u4E0D\u80FD\u6574\u9664\u8DE8\u8DDD ${spanM} m\uFF08\u5F97\u5230 ${intervals} \u6BB5\uFF09`
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
return Array.from({ length: rounded + 1 }, (_, i) => i * spacingM);
|
|
59
|
+
}
|
|
60
|
+
function dropperLengths(input) {
|
|
61
|
+
const {
|
|
62
|
+
suspension,
|
|
63
|
+
spanM,
|
|
64
|
+
contactTensionKN,
|
|
65
|
+
structureHeightM,
|
|
66
|
+
contactLoadKNPerM,
|
|
67
|
+
dropperSpacingM: spacingM
|
|
68
|
+
} = input;
|
|
69
|
+
if (!(contactTensionKN > 0)) {
|
|
70
|
+
throw new RangeError(`\u63A5\u89E6\u7EBF\u5F20\u529B\u5FC5\u987B\u4E3A\u6B63\u6570\uFF0C\u6536\u5230 ${contactTensionKN} kN`);
|
|
71
|
+
}
|
|
72
|
+
if (!(contactLoadKNPerM > 0)) {
|
|
73
|
+
throw new RangeError(`\u63A5\u89E6\u7EBF\u5355\u4F4D\u8377\u8F7D\u5FC5\u987B\u4E3A\u6B63\u6570\uFF0C\u6536\u5230 ${contactLoadKNPerM} kN/m`);
|
|
74
|
+
}
|
|
75
|
+
if (!(structureHeightM > 0)) {
|
|
76
|
+
throw new RangeError(`\u7ED3\u6784\u9AD8\u5EA6\u5FC5\u987B\u4E3A\u6B63\u6570\uFF0C\u6536\u5230 ${structureHeightM} m`);
|
|
77
|
+
}
|
|
78
|
+
if (suspension === "elastic") {
|
|
79
|
+
const m = input.messenger;
|
|
80
|
+
if (!m) {
|
|
81
|
+
throw new RangeError("\u5F39\u6027\u94FE\u5F62\u60AC\u6302\u5FC5\u987B\u63D0\u4F9B\u627F\u529B\u7D22\u53C2\u6570\uFF08messenger\uFF09");
|
|
82
|
+
}
|
|
83
|
+
if (!(m.tensionKN > 0) || !(m.loadKNPerM > 0)) {
|
|
84
|
+
throw new RangeError("\u627F\u529B\u7D22\u5F20\u529B\u4E0E\u5355\u4F4D\u8377\u8F7D\u5FC5\u987B\u4E3A\u6B63\u6570");
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
const positions = dropperPositionsM(spanM, spacingM);
|
|
88
|
+
const messenger = suspension === "elastic" ? input.messenger : null;
|
|
89
|
+
const points = positions.map((xM, index) => {
|
|
90
|
+
const contactSag = parabolaSagM(
|
|
91
|
+
xM,
|
|
92
|
+
spanM,
|
|
93
|
+
contactLoadKNPerM,
|
|
94
|
+
contactTensionKN
|
|
95
|
+
);
|
|
96
|
+
const messengerSag = messenger && messenger !== null ? parabolaSagM(xM, spanM, messenger.loadKNPerM, messenger.tensionKN) : 0;
|
|
97
|
+
const dropperLengthM = structureHeightM - contactSag + messengerSag;
|
|
98
|
+
if (dropperLengthM <= 0) {
|
|
99
|
+
throw new RangeError(
|
|
100
|
+
`x = ${xM} m \u5904\u540A\u5F26\u957F\u5EA6\u975E\u6B63\uFF08${dropperLengthM.toFixed(4)} m\uFF09\uFF1A\u7ED3\u6784\u9AD8\u5EA6 ${structureHeightM} m \u4E0D\u8DB3\uFF0C\u8BF7\u590D\u6838\u8F93\u5165`
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
return { index, positionM: xM, contactSagM: contactSag, messengerSagM: messengerSag, dropperLengthM };
|
|
104
|
+
});
|
|
105
|
+
let maxSagM = 0;
|
|
106
|
+
let shortestDropperM = Number.POSITIVE_INFINITY;
|
|
107
|
+
for (const p of points) {
|
|
108
|
+
if (p.contactSagM > maxSagM) maxSagM = p.contactSagM;
|
|
109
|
+
if (p.dropperLengthM < shortestDropperM) shortestDropperM = p.dropperLengthM;
|
|
110
|
+
}
|
|
111
|
+
return {
|
|
112
|
+
points,
|
|
113
|
+
maxSagM,
|
|
114
|
+
shortestDropperM,
|
|
115
|
+
count: points.length
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export {
|
|
120
|
+
dropperMeta,
|
|
121
|
+
parabolaSagM,
|
|
122
|
+
maxParabolaSagM,
|
|
123
|
+
dropperPositionsM,
|
|
124
|
+
dropperLengths
|
|
125
|
+
};
|
|
126
|
+
//# sourceMappingURL=chunk-UO2PHBC3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/dropper/meta.ts","../src/dropper/index.ts"],"sourcesContent":["import type { CalculatorMeta } from '../types';\n\nexport const dropperMeta: CalculatorMeta = {\n name: '吊弦长度计算',\n nameEn: 'Dropper Length Calculator',\n summary:\n '按抛物线弛度公式计算链形悬挂各吊弦长度,支持简单链形与弹性链形两种悬挂类型。',\n formula: [\n '接触线弛度(抛物线近似):f_c(x) = q_c·x·(L−x) / (2·T_c)',\n '承力索弛度:f_m(x) = q_m·x·(L−x) / (2·T_m)',\n '简单链形:l_i = H − f_c(x_i)',\n '弹性链形(计入承力索弛度):l_i = H − f_c(x_i) + f_m(x_i)',\n '跨中最大弛度:f_max = q_c·L² / (8·T_c)',\n ],\n references: [\n '抛物线近似,适用于 f/L ≤ 1/10 的小弛度工况',\n '吊弦间距须能整除跨距;实际吊弦布置以设计文件为准',\n '弹性链形悬挂须同时提供承力索张力与单位荷载',\n ],\n scope: [\n '跨距 L:5 ~ 80 m',\n '接触线张力 T_c:1 ~ 40 kN',\n '结构高度 H:0.3 ~ 3 m',\n '接触线单位荷载 q_c:0.001 ~ 0.1 kN/m',\n '吊弦间距 d:1 ~ 15 m,须能整除跨距',\n '抛物线近似,大弛度工况误差增大',\n '未计入吊弦自身伸长、温度变化与零部件制造公差',\n ],\n disclaimer: '本工具结果仅供参考,工程应用以设计文件为准。详见 DISCLAIMER.md。',\n online: 'https://www.itswe.com/calculator/dropper/',\n};\n","export { dropperMeta } from './meta';\n\n/** 悬挂类型 */\nexport type SuspensionType = 'simple' | 'elastic';\n\nexport interface DropperInput {\n /** 悬挂类型。弹性链形须同时提供 messenger 参数 */\n readonly suspension: SuspensionType;\n /** 跨距 L,m */\n readonly spanM: number;\n /** 接触线张力 T_c,kN */\n readonly contactTensionKN: number;\n /** 结构高度 H,m */\n readonly structureHeightM: number;\n /** 接触线单位荷载 q_c,kN/m */\n readonly contactLoadKNPerM: number;\n /** 吊弦间距 d,m,须能整除跨距 */\n readonly dropperSpacingM: number;\n /**\n * 承力索参数。弹性链形悬挂('elastic')必填,\n * 简单链形悬挂传 null 或不传。\n */\n readonly messenger?: {\n /** 承力索张力 T_m,kN */\n readonly tensionKN: number;\n /** 承力索单位荷载 q_m,kN/m */\n readonly loadKNPerM: number;\n } | null;\n}\n\n/** 单个吊弦点的计算结果 */\nexport interface DropperPoint {\n /** 序号 i(0 为起始端) */\n readonly index: number;\n /** 距起始端的距离 x,m */\n readonly positionM: number;\n /** 接触线弛度 f_c(x),m */\n readonly contactSagM: number;\n /** 承力索弛度 f_m(x),m(简单链形恒为 0) */\n readonly messengerSagM: number;\n /** 吊弦长度 l,m */\n readonly dropperLengthM: number;\n}\n\nexport interface DropperResult {\n readonly points: readonly DropperPoint[];\n /** 跨中最大弛度 f_max,m */\n readonly maxSagM: number;\n /** 最短吊弦长度,m(位于跨中) */\n readonly shortestDropperM: number;\n /** 吊弦数量(含两端) */\n readonly count: number;\n}\n\n/**\n * 抛物线弛度:f(x) = q·x·(L−x) / (2·T)\n *\n * 对接触线和承力索通用,区别只在传哪一组 q / T。\n *\n * @param xM 距起始端距离,m\n * @param spanM 跨距 L,m\n * @param loadKNPerM 单位荷载 q,kN/m\n * @param tensionKN 张力 T,kN\n * @returns 该点弛度,m\n */\nexport function parabolaSagM(\n xM: number,\n spanM: number,\n loadKNPerM: number,\n tensionKN: number,\n): number {\n if (!(tensionKN > 0)) {\n throw new RangeError(`张力必须为正数,收到 ${tensionKN} kN`);\n }\n if (xM < 0 || xM > spanM) {\n throw new RangeError(`位置 x = ${xM} m 超出跨距 0 ~ ${spanM} m`);\n }\n return (loadKNPerM * xM * (spanM - xM)) / (2 * tensionKN);\n}\n\n/**\n * 跨中最大弛度:f_max = q·L² / (8·T)\n */\nexport function maxParabolaSagM(\n spanM: number,\n loadKNPerM: number,\n tensionKN: number,\n): number {\n return (loadKNPerM * spanM * spanM) / (8 * tensionKN);\n}\n\n/**\n * 生成吊弦点位(含两端)。\n * @param spanM 跨距 L,m\n * @param spacingM 吊弦间距 d,m,须能整除跨距\n * @returns 各点位距起始端的距离,m\n */\nexport function dropperPositionsM(spanM: number, spacingM: number): number[] {\n if (!(spanM > 0)) {\n throw new RangeError(`跨距必须为正数,收到 ${spanM} m`);\n }\n if (!(spacingM > 0)) {\n throw new RangeError(`吊弦间距必须为正数,收到 ${spacingM} m`);\n }\n const intervals = spanM / spacingM;\n const rounded = Math.round(intervals);\n if (Math.abs(intervals - rounded) > 1e-9 || rounded < 1) {\n throw new RangeError(\n `吊弦间距 ${spacingM} m 不能整除跨距 ${spanM} m(得到 ${intervals} 段)`,\n );\n }\n return Array.from({ length: rounded + 1 }, (_, i) => i * spacingM);\n}\n\n/**\n * 计算整跨各吊弦长度。\n *\n * 简单链形:l_i = H − f_c(x_i)\n * 弹性链形:l_i = H − f_c(x_i) + f_m(x_i)\n */\nexport function dropperLengths(input: DropperInput): DropperResult {\n const {\n suspension,\n spanM,\n contactTensionKN,\n structureHeightM,\n contactLoadKNPerM,\n dropperSpacingM: spacingM,\n } = input;\n\n if (!(contactTensionKN > 0)) {\n throw new RangeError(`接触线张力必须为正数,收到 ${contactTensionKN} kN`);\n }\n if (!(contactLoadKNPerM > 0)) {\n throw new RangeError(`接触线单位荷载必须为正数,收到 ${contactLoadKNPerM} kN/m`);\n }\n if (!(structureHeightM > 0)) {\n throw new RangeError(`结构高度必须为正数,收到 ${structureHeightM} m`);\n }\n\n if (suspension === 'elastic') {\n const m = input.messenger;\n if (!m) {\n throw new RangeError('弹性链形悬挂必须提供承力索参数(messenger)');\n }\n if (!(m.tensionKN > 0) || !(m.loadKNPerM > 0)) {\n throw new RangeError('承力索张力与单位荷载必须为正数');\n }\n }\n\n const positions = dropperPositionsM(spanM, spacingM);\n const messenger = suspension === 'elastic' ? input.messenger : null;\n\n const points: DropperPoint[] = positions.map((xM, index) => {\n const contactSag = parabolaSagM(\n xM,\n spanM,\n contactLoadKNPerM,\n contactTensionKN,\n );\n const messengerSag =\n messenger && messenger !== null\n ? parabolaSagM(xM, spanM, messenger.loadKNPerM, messenger.tensionKN)\n : 0;\n\n const dropperLengthM = structureHeightM - contactSag + messengerSag;\n if (dropperLengthM <= 0) {\n throw new RangeError(\n `x = ${xM} m 处吊弦长度非正(${dropperLengthM.toFixed(4)} m):` +\n `结构高度 ${structureHeightM} m 不足,请复核输入`,\n );\n }\n\n return { index, positionM: xM, contactSagM: contactSag, messengerSagM: messengerSag, dropperLengthM };\n });\n\n let maxSagM = 0;\n let shortestDropperM = Number.POSITIVE_INFINITY;\n for (const p of points) {\n if (p.contactSagM > maxSagM) maxSagM = p.contactSagM;\n if (p.dropperLengthM < shortestDropperM) shortestDropperM = p.dropperLengthM;\n }\n\n return {\n points,\n maxSagM,\n shortestDropperM,\n count: points.length,\n };\n}\n"],"mappings":"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","names":[]}
|