sheetfold
Version:
a library for metal sheet construction
992 lines (991 loc) • 32.6 kB
JavaScript
// src/facet.ts
import { Contour, SegEnum, isSeg } from "geometrix";
var tJDir = /* @__PURE__ */ ((tJDir2) => {
tJDir2[tJDir2["eA"] = 0] = "eA";
tJDir2[tJDir2["eB"] = 1] = "eB";
return tJDir2;
})(tJDir || {});
var tJSide = /* @__PURE__ */ ((tJSide2) => {
tJSide2[tJSide2["eABRight"] = 0] = "eABRight";
tJSide2[tJSide2["eABLeft"] = 1] = "eABLeft";
return tJSide2;
})(tJSide || {});
function invertJDir(iJDir) {
let rJDir = 0 /* eA */;
if (iJDir === rJDir) {
rJDir = 1 /* eB */;
}
return rJDir;
}
var ContourJ = class _ContourJ extends Contour {
/** @internal */
pJuncs = [];
lastPosition = -1;
facetIdx = -1;
ctrIdx = -1;
used = 0;
startJunction(jName, aNb, abSide) {
for (const iJunc of this.pJuncs) {
if (iJunc.jName === jName) {
throw `err209: jName ${jName} already used`;
}
}
const newPosition = this.segments.length - 1;
if (newPosition === this.lastPosition) {
throw `err210: jName ${jName} overwrites previous position ${newPosition}`;
}
this.lastPosition = newPosition;
this.pJuncs.push({
jName,
jDir: aNb,
jSide: abSide,
jPosition: newPosition
});
return this;
}
findIdx(jName) {
let rIdx = -1;
for (const [idx, iJunc] of this.pJuncs.entries()) {
if (jName === iJunc.jName) {
rIdx = idx;
}
}
return rIdx;
}
cloneJ(iCtr) {
const rctrJ = new _ContourJ(iCtr.segments[0].px, iCtr.segments[0].py);
for (const seg of iCtr.segments) {
const nseg = seg.clone();
if (nseg.sType !== SegEnum.eStart) {
rctrJ.addSeg(nseg);
if (isSeg(nseg.sType)) {
rctrJ.setLastPoint(nseg.px, nseg.py);
}
}
}
for (const iJunc of this.pJuncs) {
rctrJ.pJuncs.push({
jName: iJunc.jName,
jDir: iJunc.jDir,
jSide: iJunc.jSide,
jPosition: iJunc.jPosition
});
}
rctrJ.lastPosition = this.lastPosition;
return rctrJ;
}
generateRevertOrientation() {
const ctrA = super.generateRevertOrientation();
const rctrJ = new _ContourJ(ctrA.segments[0].px, ctrA.segments[0].py);
for (const seg of ctrA.segments) {
const nseg = seg.clone();
if (nseg.sType !== SegEnum.eStart) {
rctrJ.addSeg(nseg);
if (isSeg(nseg.sType)) {
rctrJ.setLastPoint(nseg.px, nseg.py);
}
}
}
const jnb = this.pJuncs.length;
for (let idx = 0; idx < jnb; idx++) {
const iJunc = this.pJuncs[jnb - idx - 1];
const lastPos = this.segments.length - 2 - iJunc.jPosition;
if (lastPos < 0) {
throw `err110: revert ctrJ len ${this.segments.length} has lastPos ${lastPos} negative`;
}
rctrJ.pJuncs.push({
jName: iJunc.jName,
jDir: invertJDir(iJunc.jDir),
jSide: iJunc.jSide,
jPosition: lastPos
});
rctrJ.lastPosition = lastPos;
}
return rctrJ;
}
translate(ix, iy) {
const ctrA = super.translate(ix, iy);
const rCtrJ = this.cloneJ(ctrA);
return rCtrJ;
}
translatePolar(ia, il) {
return this.translate(il * Math.cos(ia), il * Math.sin(ia));
}
rotate(ix, iy, ia) {
const ctrA = super.rotate(ix, iy, ia);
const rCtrJ = this.cloneJ(ctrA);
return rCtrJ;
}
setIdx(iFacetIdx, iCtrIdx) {
this.facetIdx = iFacetIdx;
this.ctrIdx = iCtrIdx;
this.used = 0;
}
compareIdx(iFacetIdx, iCtrIdx) {
let rCompare = false;
if (iFacetIdx === this.facetIdx && iCtrIdx === this.ctrIdx) {
rCompare = true;
}
return rCompare;
}
incrementUsed() {
this.used += 1;
}
normOrientation(iOuterInner) {
const orientation1 = super.getEnvelop().orientation;
if (orientation1 !== iOuterInner) {
return this.generateRevertOrientation();
} else {
return this;
}
}
};
var Facet = class {
/** @internal */
attached = false;
ax = 0;
ay = 0;
aa = 0;
juncIdx = 0;
outerInner = [];
constructor(iOuterInner) {
for (const iCtr of iOuterInner) {
this.outerInner.push(iCtr);
}
}
place(tm2) {
const az2 = tm2.getRotation();
const [xx2, yy2] = tm2.getTranslation();
const ctrsJ = [];
for (const iCtr of this.outerInner) {
ctrsJ.push(iCtr.rotate(0, 0, az2).translate(xx2, yy2));
}
const rFacet = facet(ctrsJ);
rFacet.attached = this.attached;
rFacet.ax = this.ax;
rFacet.ay = this.ay;
rFacet.aa = this.aa;
rFacet.juncIdx = this.juncIdx;
return rFacet;
}
getContourPure() {
const ctrsPure = [];
for (const iCtr of this.outerInner) {
if (!(iCtr instanceof ContourJ)) {
ctrsPure.push(iCtr);
}
}
return ctrsPure;
}
getContourJ(iFacetIdx) {
const ctrsJ = [];
for (const [iCtrIdx, iCtr] of this.outerInner.entries()) {
if (iCtr instanceof ContourJ) {
const ctrN = iCtr.normOrientation(iCtrIdx === 0);
ctrN.setIdx(iFacetIdx, iCtrIdx);
ctrsJ.push(ctrN);
}
}
return ctrsJ;
}
getContourAll() {
const ctrsAll = [];
for (const iCtr of this.outerInner) {
ctrsAll.push(contourJ2contour(iCtr));
}
return ctrsAll;
}
};
function contourJ(ix, iy, icolor = "") {
return new ContourJ(ix, iy, icolor);
}
function facet(iOuterInner) {
return new Facet(iOuterInner);
}
function contourJ2contour(iContoutJ) {
return iContoutJ.clone();
}
// src/sheetfold.ts
import {
contour,
ctrRectangle,
ctrRectRot,
Contour as Contour2,
figure,
envelop,
ffix,
SegEnum as SegEnum2,
isActiveCorner,
withinPiPi,
point,
transform2d,
transform3d,
EExtrude,
EBVolume
} from "geometrix";
var cPrecision = 10 ** -5;
var SheetFold = class {
/** @internal */
pThickness = 0;
pPartName = "";
pSFMark = "";
pFacets = [];
pJuncs = [];
pProfiles = [];
constructor(iFacets, iJuncs, iProfiles, iThickness, iPartName, iSFMark) {
this.pThickness = iThickness;
this.pPartName = iPartName;
this.pSFMark = iSFMark;
const jNames2 = Object.keys(iJuncs);
for (const [iFacetIdx, iFacet] of iFacets.entries()) {
let backward = 0;
for (const [iCtrIdx, iCtr] of iFacet.outerInner.entries()) {
if (iCtr instanceof ContourJ) {
for (const iJunc of iCtr.pJuncs) {
const iJuncName = iJunc.jName;
const jNames = this.pJuncs.map((item) => item.jName);
if (jNames.includes(iJuncName)) {
const jIdx = jNames.findIndex((item) => item === iJuncName);
if (1 === this.pJuncs[jIdx].associated) {
const facetIdx1 = this.pJuncs[jIdx].a1FacetIdx;
if (iFacetIdx <= facetIdx1) {
throw `err390: junction ${jIdx} connects facets ${facetIdx1} and ${iFacetIdx}. Must be higher!`;
}
this.pJuncs[jIdx].associated = 2;
this.pJuncs[jIdx].a2FacetIdx = iFacetIdx;
this.pJuncs[jIdx].a2ContIdx = iCtrIdx;
this.pJuncs[jIdx].a2SegIdx = iJunc.jPosition;
this.pJuncs[jIdx].a2Dir = iJunc.jDir;
this.pJuncs[jIdx].a2Side = iJunc.jSide;
if (0 === backward) {
backward = 1;
} else {
throw `err628: jName ${iJuncName} is the second backward junction of facet-idx ${iFacetIdx}`;
}
} else {
throw `err125: jName ${iJuncName} used a third time in facet-idx ${iFacetIdx}`;
}
} else {
if (jNames2.includes(iJuncName)) {
this.pJuncs.push({
jName: iJuncName,
angle: iJuncs[iJuncName].angle,
radius: iJuncs[iJuncName].radius,
neutral: iJuncs[iJuncName].neutral,
mark: iJuncs[iJuncName].mark,
associated: 1,
a1FacetIdx: iFacetIdx,
a1ContIdx: iCtrIdx,
a1SegIdx: iJunc.jPosition,
a1Dir: iJunc.jDir,
a1Side: iJunc.jSide,
a1x: 0,
a1y: 0,
a1Teta: 0,
a2FacetIdx: -1,
a2ContIdx: -1,
a2SegIdx: -1,
a2Dir: 0 /* eA */,
a2Side: 0 /* eABRight */,
a2x: 0,
a2y: 0,
a2Teta: 0,
jLength: 0,
jx: 0,
jy: 0
});
} else {
throw `err129: jName ${iJuncName} not defined in junction-list`;
}
}
}
}
}
if (0 === backward && iFacetIdx > 0) {
throw `err738: iFacetIdx ${iFacetIdx} has no backward connection`;
}
this.pFacets.push(iFacet);
}
this.computeLength();
this.checkFacet();
for (const oneProfile of iProfiles) {
if (oneProfile.l1 <= 0) {
throw `err292: profile l1 ${oneProfile.l1} is negative or null`;
}
for (const [idx, halfP] of oneProfile.ante.entries()) {
if (0 === idx % 2) {
if ("string" !== typeof halfP) {
throw `err234: even element of ante is not a string`;
}
if (!jNames2.includes(halfP)) {
throw `err242: even element string ${halfP} of ante is not a declared junctions`;
}
} else {
if ("number" !== typeof halfP) {
throw `err239: odd element of ante is not a number`;
}
if (halfP <= 0) {
throw `err242: odd element number ${halfP} of ante is negative or null`;
}
}
}
for (const [idx, halfP] of oneProfile.post.entries()) {
if (0 === idx % 2) {
if ("string" !== typeof halfP) {
throw `err234: even element of post is not a string`;
}
if (!jNames2.includes(halfP)) {
throw `err242: even element string ${halfP} of post is not a declared junctions`;
}
} else {
if ("number" !== typeof halfP) {
throw `err239: odd element of post is not a number`;
}
if (halfP <= 0) {
throw `err242: odd element number ${halfP} of post is negative or null`;
}
}
}
this.pProfiles.push(oneProfile);
}
}
/** @internal */
printJuncs() {
for (const iJunc of this.pJuncs) {
const fa1 = iJunc.a1FacetIdx;
const co1 = iJunc.a1ContIdx;
const seg1 = iJunc.a1SegIdx;
const fa2 = iJunc.a2FacetIdx;
const co2 = iJunc.a2ContIdx;
const seg2 = iJunc.a2SegIdx;
console.log(`dbg527: ${iJunc.jName} : ${fa1} ${co1} ${seg1} : ${fa2} ${co2} ${seg2}`);
}
}
/** @internal */
oneTetaLength(faIdx, coIdx, segIdx) {
const ctr = this.pFacets[faIdx].outerInner[coIdx];
if (!(ctr instanceof Contour2)) {
throw `err234: faIdx ${faIdx}, coIdx ${coIdx} is not a Contour but a ContourCircle`;
}
const maxLen = ctr.segments.length;
const segA = ctr.segments[segIdx];
const segB = ctr.segments[(segIdx + 1) % maxLen];
const segC = ctr.segments[(segIdx + 2) % maxLen];
if (isActiveCorner(segA.sType)) {
throw `err101: junction ${faIdx} ${coIdx} ${segIdx} starts with an active corner`;
}
if (SegEnum2.eStroke !== segB.sType) {
throw `err102: junction ${faIdx} ${coIdx} ${segIdx} is not a stroke`;
}
if (isActiveCorner(segC.sType)) {
throw `err103: junction ${faIdx} ${coIdx} ${segIdx} ends with an active corner`;
}
const rLength = Math.sqrt((segB.px - segA.px) ** 2 + (segB.py - segA.py) ** 2);
const rTeta = Math.atan2(segB.py - segA.py, segB.px - segA.px);
const rLog = `Ax ${ffix(segA.px)} Ay ${ffix(segA.py)} Bx ${ffix(segB.px)} By ${ffix(segB.py)}`;
return [segA.px, segA.py, rTeta, rLength, rLog];
}
/** @internal */
computeLength() {
for (const [iJuncIdx, iJunc] of this.pJuncs.entries()) {
for (let idx = 0; idx < iJunc.associated; idx++) {
let faIdx = iJunc.a1FacetIdx;
let coIdx = iJunc.a1ContIdx;
let segIdx = iJunc.a1SegIdx;
let jDir = iJunc.a1Dir;
if (1 === idx) {
faIdx = iJunc.a2FacetIdx;
coIdx = iJunc.a2ContIdx;
segIdx = iJunc.a2SegIdx;
jDir = iJunc.a2Dir;
}
const [Ax, Ay, aAB, lAB, ABLog] = this.oneTetaLength(faIdx, coIdx, segIdx);
let jTeta = aAB;
let xx = Ax;
let yy = Ay;
if (1 /* eB */ === jDir) {
const pA = point(Ax, Ay).translatePolar(aAB, lAB);
xx = pA.cx;
yy = pA.cy;
jTeta = withinPiPi(aAB + Math.PI);
}
if (1 === idx) {
const absDiffL = Math.abs(lAB - iJunc.jLength);
if (absDiffL > cPrecision) {
const ABLog2 = `jName ${iJunc.jName} ${ABLog}`;
throw `err908: junction ${iJuncIdx} jLength ${ffix(iJunc.jLength)} ${ffix(lAB)} differs of ${absDiffL}
${ABLog2}`;
}
if (iJunc.a1Side === iJunc.a2Side) {
throw `err905: jSide ${iJunc.a1Side} ${iJunc.a2Side} must be opposite`;
}
iJunc.a2x = xx;
iJunc.a2y = yy;
iJunc.a2Teta = jTeta;
if (this.pFacets[faIdx].attached === false) {
this.pFacets[faIdx].attached = true;
this.pFacets[faIdx].ax = xx;
this.pFacets[faIdx].ay = yy;
this.pFacets[faIdx].aa = jTeta;
this.pFacets[faIdx].juncIdx = iJuncIdx;
} else {
throw `err545: pFacet ${faIdx} is already attached`;
}
} else {
iJunc.jLength = lAB;
iJunc.a1Teta = jTeta;
iJunc.a1x = xx;
iJunc.a1y = yy;
}
}
}
}
checkFacet() {
for (const [iFacetIdx, iFacet] of this.pFacets.entries()) {
if (iFacetIdx > 0 && iFacet.attached === false) {
throw `err464: pFacet ${iFacetIdx} ax is not set`;
}
}
}
// end of constructor sub-functions
/** @internal */
getJuncIdx(jName) {
let rIdx = -1;
for (const [idx, iJunc] of this.pJuncs.entries()) {
if (jName === iJunc.jName) {
rIdx = idx;
}
}
if (rIdx < 0) {
throw `err801: jName ${jName} not found`;
}
return rIdx;
}
/** @internal */
fromJunctionToAttach(iJunc) {
let ra = iJunc.a1Teta;
let rx = iJunc.a1x;
let ry = iJunc.a1y;
const faIdx = iJunc.a1FacetIdx;
if (faIdx > 0) {
const facette = this.pFacets[faIdx];
ra = ra - facette.aa;
const tx2 = rx - facette.ax;
const ty2 = ry - facette.ay;
const tl2 = Math.sqrt(tx2 ** 2 + ty2 ** 2);
const ta2 = Math.atan2(ty2, tx2);
const ta3 = ta2 - facette.aa;
rx = tl2 * Math.cos(ta3);
ry = tl2 * Math.sin(ta3);
}
return [ra, rx, ry];
}
positionF(iTm, iFacetIdx) {
let rTm = iTm;
if (iFacetIdx > 0) {
const jIdx = this.pFacets[iFacetIdx].juncIdx;
const junc = this.pJuncs[jIdx];
if (1 /* eABLeft */ === junc.a1Side) {
rTm = rTm.addRotation(-junc.angle, 0, 0).addTranslation(0, -junc.jx, junc.jy);
} else {
rTm = rTm.addRotation(junc.angle, 0, 0).addTranslation(0, junc.jx, junc.jy);
}
rTm = this.positionJ(rTm, jIdx);
}
return rTm;
}
positionJ(iTm, jIdx) {
const junc = this.pJuncs[jIdx];
const [ta, tx, ty] = this.fromJunctionToAttach(junc);
let rTm = iTm.addRotation(0, 0, ta).addTranslation(tx, ty, 0);
const faIdx = junc.a1FacetIdx;
if (faIdx > 0) {
rTm = this.positionF(rTm, faIdx);
}
return rTm;
}
positionJ2d(iFacetIdx) {
const rTm1 = transform2d();
let facIdx = iFacetIdx;
if (this.pFacets[iFacetIdx].attached) {
while (facIdx > 0) {
const jIdx = this.pFacets[facIdx].juncIdx;
const junc = this.pJuncs[jIdx];
const tJangle = Math.abs(junc.angle);
const tJWidth = tJangle === 0 ? junc.radius : tJangle * junc.radius;
const tSign = 1 /* eABLeft */ === junc.a1Side ? -1 : 1;
rTm1.addTranslation(0, tSign * tJWidth);
const [ta, tx, ty] = this.fromJunctionToAttach(junc);
rTm1.addRotation(ta);
rTm1.addTranslation(tx, ty);
facIdx = junc.a1FacetIdx;
}
} else {
throw `err491: iFacetIdx ${iFacetIdx} is not attached!`;
}
return rTm1;
}
positionF2d(iFacetIdx) {
const tm1 = this.positionJ2d(iFacetIdx);
const az1 = tm1.getRotation();
const [xx1, yy1] = tm1.getTranslation();
const iFacet = this.pFacets[iFacetIdx];
const rTm2d = transform2d().addTranslation(-iFacet.ax, -iFacet.ay).addRotation(-iFacet.aa + az1).addTranslation(xx1, yy1);
return rTm2d;
}
findCtrJ(iCtrsJ, iFacetIdx, iCtrIdx) {
let rCtrJ = iCtrsJ[0];
let found = false;
for (const ctrJ of iCtrsJ) {
if (ctrJ.compareIdx(iFacetIdx, iCtrIdx)) {
rCtrJ = ctrJ;
found = true;
}
}
if (!found) {
throw `err612: not found ctrJ with iFacetIdx ${iFacetIdx} and iCtrIdx ${iCtrIdx}`;
}
return rCtrJ;
}
generateJunc3List(iCtrJ) {
const rJ3List = [];
for (const iJunc of iCtrJ.pJuncs) {
const j3 = {
jName: iJunc.jName,
segPosition: iJunc.jPosition,
jDir: iJunc.jDir
};
rJ3List.push(j3);
}
return rJ3List;
}
calcJuncList(iCtrJ, jName) {
const startIdx = iCtrJ.findIdx(jName);
if (startIdx < 0) {
throw `err324: junction ${jName} not found`;
}
const origList = this.generateJunc3List(iCtrJ);
const rJuncList = [...origList.slice(startIdx), ...origList.slice(0, startIdx)];
return rJuncList;
}
incrSegIdx(idx, delta, maxIdx) {
let rIdx = idx + delta;
if (rIdx >= maxIdx) {
rIdx = 0;
} else if (rIdx < 0) {
rIdx = maxIdx + rIdx;
}
return rIdx;
}
addSeg(iCtr, iSeg) {
if (iSeg.sType !== SegEnum2.eStart) {
iCtr.addSeg(iSeg);
iCtr.setLastPoint(iSeg.px, iSeg.py);
}
}
makePartialCtr(iCtrJ, iJuncList, first, iCtrsJ) {
let startIdx = iJuncList[0].segPosition;
let endIdx = this.incrSegIdx(startIdx, 0, iCtrJ.segments.length);
if (!first) {
startIdx = this.incrSegIdx(iJuncList[0].segPosition, 1, iCtrJ.segments.length);
endIdx = this.incrSegIdx(startIdx, 0, iCtrJ.segments.length);
}
const rCtr = contour(iCtrJ.segments[startIdx].px, iCtrJ.segments[startIdx].py);
let segIdx = this.incrSegIdx(startIdx, 0, iCtrJ.segments.length);
for (let i1 = 1; i1 < iJuncList.length; i1++) {
iCtrJ.incrementUsed();
while (segIdx !== iJuncList[i1].segPosition) {
segIdx = this.incrSegIdx(segIdx, 1, iCtrJ.segments.length);
this.addSeg(rCtr, iCtrJ.segments[segIdx].clone());
}
const junc = this.pJuncs[this.getJuncIdx(iJuncList[i1].jName)];
if (junc.a2FacetIdx === -1) {
const Ax = iCtrJ.segments[segIdx].px;
const Ay = iCtrJ.segments[segIdx].py;
segIdx = this.incrSegIdx(segIdx, 1, iCtrJ.segments.length);
const Bx = iCtrJ.segments[segIdx].px;
const By = iCtrJ.segments[segIdx].py;
const vABx = Bx - Ax;
const vABy = By - Ay;
const lAB = Math.sqrt(vABx ** 2 + vABy ** 2);
const aAB = Math.atan2(vABy, vABx);
let a90plus = 0;
if (1 /* eB */ === iJuncList[i1].jDir) {
a90plus = Math.PI;
}
const jLen = junc.angle === 0 ? junc.radius : Math.abs(junc.angle) * junc.radius;
const a90 = junc.a1Side === 1 /* eABLeft */ ? -Math.PI / 2 : Math.PI / 2;
rCtr.addSegStrokeRP(aAB + a90 + a90plus, jLen);
rCtr.addSegStrokeRP(aAB, lAB);
rCtr.addSegStrokeA(Bx, By);
} else {
const ctrJ2 = this.findCtrJ(iCtrsJ, junc.a2FacetIdx, junc.a2ContIdx);
const juncList2 = this.calcJuncList(ctrJ2, junc.jName);
const partialCtr = this.makePartialCtr(ctrJ2, juncList2, false, iCtrsJ);
rCtr.addSegStrokeA(partialCtr.segments[0].px, partialCtr.segments[0].py);
for (const seg of partialCtr.segments) {
this.addSeg(rCtr, seg.clone());
}
segIdx = this.incrSegIdx(segIdx, 1, iCtrJ.segments.length);
rCtr.addSegStrokeA(iCtrJ.segments[segIdx].px, iCtrJ.segments[segIdx].py);
}
}
iCtrJ.incrementUsed();
segIdx = this.incrSegIdx(segIdx, 1, iCtrJ.segments.length);
while (segIdx !== endIdx) {
this.addSeg(rCtr, iCtrJ.segments[segIdx].clone());
segIdx = this.incrSegIdx(segIdx, 1, iCtrJ.segments.length);
}
return rCtr;
}
generateNewContours(iCtrsJ) {
const rCtrsNew = [];
for (const iCtrJ of iCtrsJ) {
if (iCtrJ.used === 0) {
const j0 = { jName: "", segPosition: 0, jDir: 0 /* eA */ };
const juncList1 = [j0, ...this.generateJunc3List(iCtrJ)];
const ctrN = this.makePartialCtr(iCtrJ, juncList1, true, iCtrsJ);
rCtrsNew.push(ctrN);
}
}
return rCtrsNew;
}
generateOneMarker(iJunc) {
const jLen = iJunc.angle === 0 ? iJunc.radius : Math.abs(iJunc.angle) * iJunc.radius;
if (jLen < 2 * iJunc.mark) {
const ctrM = ctrRectangle(-iJunc.mark, 0, 2 * iJunc.mark, jLen);
return ctrM;
} else {
const ctrM = contour(-iJunc.mark, iJunc.mark).addPointA(0, 0).addPointA(iJunc.mark, iJunc.mark).addSegArc2().addSegStrokeA(iJunc.mark, jLen - iJunc.mark).addPointA(0, jLen).addPointA(-iJunc.mark, jLen - iJunc.mark).addSegArc2().closeSegStroke();
return ctrM;
}
}
generateMarkers() {
const rMarkers = [];
for (const iJunc of this.pJuncs) {
if (iJunc.associated === 0) {
throw `err509: junction ${iJunc.jName} is not associated`;
}
if (iJunc.mark > 0) {
const facetIdx = iJunc.a1FacetIdx;
const tJangle = Math.abs(iJunc.angle);
const tJWidth = tJangle === 0 ? iJunc.radius : tJangle * iJunc.radius;
const tSign = 1 /* eABLeft */ === iJunc.a1Side ? -1 : 0;
const tm1 = transform2d().addTranslation(iJunc.jLength / 2, tSign * tJWidth);
if (facetIdx > 0) {
const [ta, tx, ty] = this.fromJunctionToAttach(iJunc);
tm1.addRotation(ta).addTranslation(tx, ty);
const tm2 = this.positionJ2d(facetIdx);
tm1.addRotation(tm2.getRotation()).addTranslation(...tm2.getTranslation());
} else {
tm1.addRotation(iJunc.a1Teta).addTranslation(iJunc.a1x, iJunc.a1y);
}
const ctrM = this.generateOneMarker(iJunc).rotate(0, 0, tm1.getRotation()).translate(...tm1.getTranslation());
rMarkers.push(ctrM);
}
}
return rMarkers;
}
// external API
makePatternFigure(iCheck) {
const facetPlaced = [];
for (const [iFacetIdx, iFacet] of this.pFacets.entries()) {
if (iFacetIdx > 0) {
const tm2 = this.positionF2d(iFacetIdx);
facetPlaced.push(iFacet.place(tm2));
} else {
if (iFacet.attached) {
throw `err490: iFacetIdx ${iFacetIdx} is attached!`;
}
const tm0 = transform2d();
facetPlaced.push(iFacet.place(tm0));
}
}
const ctrsAll = [];
const ctrsPure = [];
const ctrsJ = [];
for (const [iFacetIdx, iFacet] of facetPlaced.entries()) {
ctrsAll.push(...iFacet.getContourAll());
ctrsPure.push(...iFacet.getContourPure());
ctrsJ.push(...iFacet.getContourJ(iFacetIdx));
}
const rfig = figure();
for (const iCtr of ctrsAll) {
rfig.addSecond(iCtr);
}
const ctrsNew = this.generateNewContours(ctrsJ);
const ctrsMaker = this.generateMarkers();
const ctrsAll2 = [...ctrsNew, ...ctrsPure, ...ctrsMaker];
const ctrsRest2 = [];
let ctrOuter = ctrsAll2[0];
const envTracker = envelop(ctrOuter.getEnvelop());
for (const iCtr of ctrsAll2) {
if (envTracker.add(iCtr.getEnvelop())) {
ctrsRest2.push(ctrOuter);
ctrOuter = iCtr;
} else {
ctrsRest2.push(iCtr);
}
}
if (iCheck) {
if (!envTracker.check(ctrOuter.getEnvelop())) {
throw `err782: the outer-contour does not envelop all contours`;
}
}
rfig.addMainOI([ctrOuter, ...ctrsRest2]);
return rfig;
}
/** @internal */
nameFacePattern() {
const rStr = `${this.pSFMark}_pattern`;
return rStr;
}
/** @internal */
nameFace(idx) {
const rStr = `${this.pSFMark}_f${idx.toString().padStart(2, "0")}`;
return rStr;
}
/** @internal */
nameFaceJ(idx) {
const rStr = `${this.pSFMark}_fj${idx.toString().padStart(2, "0")}`;
return rStr;
}
/** @internal */
nameFaceProfiles() {
const rStr = `${this.pSFMark}_profiles`;
return rStr;
}
/** @internal */
makeFacetFig(iFacetIdx, iFacet) {
const rFig = figure();
const outerInner = [];
for (const iCtr of iFacet.outerInner) {
let ctr1 = contourJ2contour(iCtr);
if (iFacetIdx > 0) {
ctr1 = ctr1.translate(-iFacet.ax, -iFacet.ay).rotate(0, 0, Math.PI / 2 - iFacet.aa);
}
outerInner.push(ctr1);
}
rFig.addMainOI(outerInner);
return rFig;
}
/** @internal */
drawJuncPositive(rE, rI, angle) {
const pC = point(0, rE);
const pE2 = pC.translatePolar(-Math.PI / 2 + angle / 2, rE);
const pE1 = pC.translatePolar(-Math.PI / 2 + angle, rE);
const pI1 = pC.translatePolar(-Math.PI / 2 + angle, rI);
const pI2 = pC.translatePolar(-Math.PI / 2 + angle / 2, rI);
const rCtrBendP = contour(0, 0).addPointA(pE2.cx, pE2.cy).addPointA(pE1.cx, pE1.cy).addSegArc2().addSegStrokeA(pI1.cx, pI1.cy).addPointA(pI2.cx, pI2.cy).addPointA(0, this.pThickness).addSegArc2().closeSegStroke();
return [rCtrBendP, pE1.cx, pE1.cy];
}
/** @internal */
drawJuncNegative(rE, rI, angle) {
const pC = point(0, -rI);
const pE2 = pC.translatePolar(Math.PI / 2 + angle / 2, rE);
const pE1 = pC.translatePolar(Math.PI / 2 + angle, rE);
const pI1 = pC.translatePolar(Math.PI / 2 + angle, rI);
const pI2 = pC.translatePolar(Math.PI / 2 + angle / 2, rI);
const rCtrBendN = contour(0, 0).addPointA(pI2.cx, pI2.cy).addPointA(pI1.cx, pI1.cy).addSegArc2().addSegStrokeA(pE1.cx, pE1.cy).addPointA(pE2.cx, pE2.cy).addPointA(0, this.pThickness).addSegArc2().closeSegStroke();
return [rCtrBendN, pI1.cx, pI1.cy];
}
/** @internal */
makeJuncCtr(jName, jAngle, jRadius, jNeutral) {
let rCtr = ctrRectangle(0, 0, jRadius, this.pThickness);
if (jNeutral < 0 || jNeutral > 1) {
throw `err329: junction ${jName} with neutral ${jNeutral} not within 0..1`;
}
if (jRadius < 0) {
throw `err328: junction ${jName} with negative radius ${jRadius}`;
}
const rI = jRadius - this.pThickness * jNeutral;
const rE = jRadius + this.pThickness * (1 - jNeutral);
if (rI <= 0) {
throw `err901: junction ${jName} with negative rI ${rI}, radius ${jRadius}, neutral ${jNeutral}, thickness ${this.pThickness}`;
}
let rjx = 0;
let rjy = 0;
if (0 === jAngle) {
rjx = jRadius;
rjy = 0;
} else if (jAngle > 0) {
const [ctrBendP, tjx, tjy] = this.drawJuncPositive(rE, rI, jAngle);
rCtr = ctrBendP;
rjx = tjx;
rjy = tjy;
} else {
const [ctrBendN, tjx, tjy] = this.drawJuncNegative(rE, rI, jAngle);
rCtr = ctrBendN;
rjx = tjx;
rjy = tjy;
}
return [rCtr, rjx, rjy];
}
/** @internal */
makeProfileFig() {
const rfig = figure();
for (const oneP of this.pProfiles) {
let tx = oneP.x1;
let ty = oneP.y1;
let ta = oneP.a1;
rfig.addMainO(ctrRectRot(tx, ty, oneP.l1, this.pThickness, ta));
const p1 = point(tx, ty).translatePolar(ta, oneP.l1);
tx = p1.cx;
ty = p1.cy;
for (const half of oneP.post) {
if ("number" === typeof half) {
rfig.addMainO(ctrRectRot(tx, ty, half, this.pThickness, ta));
const p2 = point(tx, ty).translatePolar(ta, half);
tx = p2.cx;
ty = p2.cy;
} else {
const tJunc = this.pJuncs[this.getJuncIdx(half)];
const [ctr, tjx, tjy] = this.makeJuncCtr(
tJunc.jName,
tJunc.angle,
tJunc.radius,
tJunc.neutral
);
rfig.addMainO(ctr.rotate(0, 0, ta).translate(tx, ty));
const p3 = point(tjx, tjy).rotate(point(0, 0), ta);
tx += p3.cx;
ty += p3.cy;
ta += tJunc.angle;
}
}
tx = oneP.x1;
ty = oneP.y1;
ta = oneP.a1 + Math.PI;
const p4 = point(tx, ty).translatePolar(ta - Math.PI / 2, this.pThickness);
tx = p4.cx;
ty = p4.cy;
for (const half of oneP.ante) {
if ("number" === typeof half) {
rfig.addMainO(ctrRectRot(tx, ty, half, this.pThickness, ta));
const p5 = point(tx, ty).translatePolar(ta, half);
tx = p5.cx;
ty = p5.cy;
} else {
const tJunc = this.pJuncs[this.getJuncIdx(half)];
const [ctr, tjx, tjy] = this.makeJuncCtr(
tJunc.jName,
-tJunc.angle,
tJunc.radius,
tJunc.neutral
);
rfig.addMainO(ctr.rotate(0, 0, ta).translate(tx, ty));
const p6 = point(tjx, tjy).rotate(point(0, 0), ta);
tx += p6.cx;
ty += p6.cy;
ta -= tJunc.angle;
}
}
}
return rfig;
}
makeFigures(iCheck = true) {
const rfigs = {};
if (this.pThickness <= 0) {
throw `err822: thickness ${this.pThickness} is negative`;
}
rfigs[this.nameFacePattern()] = this.makePatternFigure(iCheck);
if (this.pProfiles.length > 0) {
const faceName = this.nameFaceProfiles();
rfigs[faceName] = this.makeProfileFig();
}
for (const [iFacetIdx, iFacet] of this.pFacets.entries()) {
const faceName = this.nameFace(iFacetIdx);
rfigs[faceName] = this.makeFacetFig(iFacetIdx, iFacet);
}
for (const [iJuncIdx, iJunc] of this.pJuncs.entries()) {
const faceName = this.nameFaceJ(iJuncIdx);
const [ctr, tjx, tjy] = this.makeJuncCtr(
iJunc.jName,
iJunc.angle,
iJunc.radius,
iJunc.neutral
);
const fig = figure();
fig.addMainO(ctr);
rfigs[faceName] = fig;
iJunc.jx = tjx;
iJunc.jy = tjy;
}
return rfigs;
}
makeVolume() {
const extrudeList = [];
for (const iFacetIdx of this.pFacets.keys()) {
const tm0 = transform3d();
let tm2 = tm0;
if (iFacetIdx > 0) {
const tm1 = tm0.addRotation(0, 0, -Math.PI / 2);
tm2 = this.positionF(tm1, iFacetIdx);
}
const subM = {
outName: `subpax_${this.pPartName}_${this.nameFace(iFacetIdx)}`,
face: `${this.pPartName}_${this.nameFace(iFacetIdx)}`,
extrudeMethod: EExtrude.eLinearOrtho,
length: this.pThickness,
rotate: tm2.getRotation(),
translate: tm2.getTranslation()
};
extrudeList.push(subM);
}
for (const [iJuncIdx, iJunc] of this.pJuncs.entries()) {
let tm1 = transform3d();
if (1 /* eABLeft */ === iJunc.a1Side) {
tm1 = tm1.addRotation(Math.PI / 2, 0, 0).addTranslation(0, iJunc.jLength, 0).addRotation(0, 0, -Math.PI / 2);
} else {
tm1 = tm1.addRotation(Math.PI / 2, 0, 0).addRotation(0, 0, Math.PI / 2);
}
const tm2 = this.positionJ(tm1, iJuncIdx);
const subM = {
outName: `subpax_${this.pPartName}_${this.nameFaceJ(iJuncIdx)}`,
face: `${this.pPartName}_${this.nameFaceJ(iJuncIdx)}`,
extrudeMethod: EExtrude.eLinearOrtho,
length: iJunc.jLength,
rotate: tm2.getRotation(),
translate: tm2.getTranslation()
};
extrudeList.push(subM);
}
const subN = extrudeList.map((item) => item.outName);
const volumeList = [];
const vol1 = {
outName: `pax_${this.pPartName}`,
boolMethod: EBVolume.eUnion,
inList: subN
};
volumeList.push(vol1);
return { extrudes: extrudeList, volumes: volumeList };
}
};
function sheetFold(iFacets, iJuncs, iProfiles, iThickness, iPartName, iSFMark = "SFG") {
return new SheetFold(iFacets, iJuncs, iProfiles, iThickness, iPartName, iSFMark);
}
function facet2figure(iFacet) {
const rfig = figure();
const outerInner = [];
for (const iCtr of iFacet.outerInner) {
if (iCtr instanceof ContourJ) {
outerInner.push(contourJ2contour(iCtr));
} else {
outerInner.push(iCtr);
}
}
rfig.addMainOI(outerInner);
return rfig;
}
export {
ContourJ,
Facet,
contourJ,
contourJ2contour,
facet,
facet2figure,
sheetFold,
tJDir,
tJSide
};
//# sourceMappingURL=index.js.map