@willcgage/module-schematic 0.56.0 → 0.57.0
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/dist/index.cjs +82 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +43 -1
- package/dist/index.d.ts +43 -1
- package/dist/index.js +80 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1320,6 +1320,85 @@ function samplePartSegments(segments, stepsPerCurve = 16) {
|
|
|
1320
1320
|
return out;
|
|
1321
1321
|
});
|
|
1322
1322
|
}
|
|
1323
|
+
function angleDeltaDeg(a, b) {
|
|
1324
|
+
let d = ((a - b) % 360 + 540) % 360 - 180;
|
|
1325
|
+
if (d === -180) d = 180;
|
|
1326
|
+
return d;
|
|
1327
|
+
}
|
|
1328
|
+
function frogNumberFromName(name) {
|
|
1329
|
+
if (!name) return void 0;
|
|
1330
|
+
const m = name.match(/(?:#|no\.?\s*|number\s+)(\d+(?:\.\d+)?)/i);
|
|
1331
|
+
if (!m) return void 0;
|
|
1332
|
+
const n = Number(m[1]);
|
|
1333
|
+
return Number.isFinite(n) && n > 0 ? n : void 0;
|
|
1334
|
+
}
|
|
1335
|
+
function importedKind(name) {
|
|
1336
|
+
const s = (name ?? "").toLowerCase();
|
|
1337
|
+
if (s.includes("wye")) return "wye";
|
|
1338
|
+
if (s.includes("crossing")) return "crossing";
|
|
1339
|
+
if (s.includes("curved")) return "curved-turnout";
|
|
1340
|
+
return "turnout";
|
|
1341
|
+
}
|
|
1342
|
+
var slug = (s) => s.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
|
|
1343
|
+
function importedPartToTrackPart(part, sourceName = "imported .xtp") {
|
|
1344
|
+
const name = part.name ?? part.title ?? "Imported part";
|
|
1345
|
+
const manufacturer = part.manufacturer ?? "Unknown";
|
|
1346
|
+
const note = `from ${sourceName} \u2014 community CAD data, not a measurement`;
|
|
1347
|
+
const out = {
|
|
1348
|
+
id: `xtp-${slug(manufacturer)}-${slug(part.partNumber || name)}`,
|
|
1349
|
+
manufacturer,
|
|
1350
|
+
name,
|
|
1351
|
+
line: "",
|
|
1352
|
+
scale: "N",
|
|
1353
|
+
kind: importedKind(name),
|
|
1354
|
+
frogNumber: frogNumberFromName(name),
|
|
1355
|
+
segments: part.segments,
|
|
1356
|
+
ends: part.ends,
|
|
1357
|
+
importedFrom: sourceName
|
|
1358
|
+
};
|
|
1359
|
+
if (part.partNumber) out.partNumbers = { single: part.partNumber };
|
|
1360
|
+
const ends = part.ends;
|
|
1361
|
+
if (ends.length >= 2) {
|
|
1362
|
+
const a = ends[0].angleDeg * Math.PI / 180;
|
|
1363
|
+
const ux = Math.sin(a);
|
|
1364
|
+
const uy = Math.cos(a);
|
|
1365
|
+
const proj = ends.map((e) => (e.x - ends[0].x) * ux + (e.y - ends[0].y) * uy);
|
|
1366
|
+
const span = Math.max(...proj) - Math.min(...proj);
|
|
1367
|
+
if (span > 0) out.overallLength = { inches: span, source: "unverified", note };
|
|
1368
|
+
}
|
|
1369
|
+
if (ends.length >= 3) {
|
|
1370
|
+
const rest = ends.slice(1);
|
|
1371
|
+
const opposite = rest.map((e) => ({ e, off: Math.abs(angleDeltaDeg(e.angleDeg, ends[0].angleDeg + 180)) })).sort((p, q) => p.off - q.off);
|
|
1372
|
+
const through = opposite[0].e;
|
|
1373
|
+
const diverging = opposite[opposite.length - 1].e;
|
|
1374
|
+
const deg = Math.abs(angleDeltaDeg(diverging.angleDeg, through.angleDeg));
|
|
1375
|
+
if (deg > 0.01) out.actualAngle = { deg, source: "unverified", note };
|
|
1376
|
+
}
|
|
1377
|
+
return out;
|
|
1378
|
+
}
|
|
1379
|
+
function mergeImportedParts(imported, library = BUILT_IN_TRACK_PARTS, sourceName = "imported .xtp") {
|
|
1380
|
+
const out = library.map((p) => ({ ...p }));
|
|
1381
|
+
const numbersOf = (p) => [p.partNumbers?.left, p.partNumbers?.right, p.partNumbers?.single].filter(Boolean).map((s) => s.trim().toLowerCase());
|
|
1382
|
+
for (const raw of imported) {
|
|
1383
|
+
const conv = importedPartToTrackPart(raw, sourceName);
|
|
1384
|
+
const pn = raw.partNumber?.trim().toLowerCase();
|
|
1385
|
+
const match = (pn ? out.find((p) => numbersOf(p).includes(pn)) : void 0) ?? (conv.frogNumber != null ? out.find(
|
|
1386
|
+
(p) => p.frogNumber === conv.frogNumber && p.kind === conv.kind && p.manufacturer.toLowerCase() === conv.manufacturer.toLowerCase()
|
|
1387
|
+
) : void 0);
|
|
1388
|
+
if (!match) {
|
|
1389
|
+
out.push(conv);
|
|
1390
|
+
continue;
|
|
1391
|
+
}
|
|
1392
|
+
if (!match.segments?.length && conv.segments?.length) match.segments = conv.segments;
|
|
1393
|
+
if (!match.ends?.length && conv.ends?.length) match.ends = conv.ends;
|
|
1394
|
+
if (!match.importedFrom && (conv.segments?.length || conv.ends?.length)) {
|
|
1395
|
+
match.importedFrom = sourceName;
|
|
1396
|
+
}
|
|
1397
|
+
if (!match.overallLength && conv.overallLength) match.overallLength = conv.overallLength;
|
|
1398
|
+
if (!match.actualAngle && conv.actualAngle) match.actualAngle = conv.actualAngle;
|
|
1399
|
+
}
|
|
1400
|
+
return out;
|
|
1401
|
+
}
|
|
1323
1402
|
function turnoutClosure(size, opts = {}) {
|
|
1324
1403
|
const N = size > 0 ? size : 6;
|
|
1325
1404
|
const g = opts.gaugeInches ?? RAIL_GAUGE_INCHES;
|
|
@@ -1882,12 +1961,15 @@ exports.endplateLead = endplateLead;
|
|
|
1882
1961
|
exports.endplateTrackOffsetFor = endplateTrackOffsetFor;
|
|
1883
1962
|
exports.endplateTrackOffsetInches = endplateTrackOffsetInches;
|
|
1884
1963
|
exports.endplateWidthInches = endplateWidthInches;
|
|
1964
|
+
exports.frogNumberFromName = frogNumberFromName;
|
|
1885
1965
|
exports.fromSectionRelative = fromSectionRelative;
|
|
1886
1966
|
exports.geometryTurnDegrees = geometryTurnDegrees;
|
|
1967
|
+
exports.importedPartToTrackPart = importedPartToTrackPart;
|
|
1887
1968
|
exports.inchesToScaleFeet = inchesToScaleFeet;
|
|
1888
1969
|
exports.isLoopDoc = isLoopDoc;
|
|
1889
1970
|
exports.isTransitionTurnout = isTransitionTurnout;
|
|
1890
1971
|
exports.leadInchesForSize = leadInchesForSize;
|
|
1972
|
+
exports.mergeImportedParts = mergeImportedParts;
|
|
1891
1973
|
exports.moduleCenterline = moduleCenterline;
|
|
1892
1974
|
exports.moduleFeatures = moduleFeatures;
|
|
1893
1975
|
exports.moduleFootprint = moduleFootprint;
|