function getQuarterPanelsPatternWidth(innerRadius, outerRadius, fabricWidth, repetitions) { const twoR = outerRadius * 2; const trapezoidWidth = Math.sqrt(twoR * twoR - fabricWidth * fabricWidth); const arcToArcWidth = 2 * outerRadius - fabricWidth; const bellyOverlap = 2 * outerRadius - trapezoidWidth; const waistHoleWidth = innerRadius * (Math.SQRT2/2); const singlePanelWidth = outerRadius - waistHoleWidth; const overlap = arcToArcWidth - bellyOverlap >= singlePanelWidth ? bellyOverlap : arcToArcWidth - singlePanelWidth; return repetitions * arcToArcWidth - (repetitions - 1) * overlap; } const quarterPanelInstructions = "Am besten machst du dir ein Schnittmuster auf Papier: Zeichne eine gerade Linie und eine weitere Linie in einem 45-Grad-Winkel zur Ersten, sodass die zwei Linien sich etwa in der Ecke deines Papierbogens kreuzen. Der Kreuzungspunkt wird der Mittelpunkt deiner Kreise. Zeichne den Taillenradius und den vollen Radius jeweils von diesem Mittelpunkt aus ein, um ein Kreissegment zu erhalten. Füge auf den Seiten des Segments jeweils eine Nahtzugabe hinzu, und schneide das ganze aus. Verwende dieses Schnittmuster um alle Teile aus deinem Stoff auszuschneiden (siehe Diagramm)." const halfSkirtFullFit = { calculateYardage: function (innerRadius, outerRadius, fabricWidth) { return outerRadius; }, hasBiasSeams: false, imagePath: "assets/half-fit.svg", instructions: "Dein Kreismittelpunkt ist in der Ecke des gefalteten Stoffs; auf dem Stoffbruch, aber etwa eine Nahtzugabe weit entfernt von der Stoffkante. Zeichne deinen Taillenradius und den vollen Radius von diesem Punkt aus ein, sodass du einen Viertelkreis erhältst.", } const threeqSkirtFullFit = { calculateYardage: function (innerRadius, outerRadius, fabricWidth) { return outerRadius + outerRadius * (Math.SQRT2/2); }, hasBiasSeams: true, imagePath: "assets/threeq-fit.svg", instructions: "Dein Kreismittelpunkt ist auf dem Stoffbruch, einen vollen Radius von der Stoffkante entfernt. Zeichne deinen Taillenradius und den vollen Radius von diesem Punkt aus ein. Dann zeichne eine 45-Grad-Linie vom selben Punkt aus, um die Kante deines Rockteils zu finden. Füge zu dieser Kante eine Nahtzugabe hinzu.", } const fullSkirtFullFit = { calculateYardage: function (innerRadius, outerRadius, fabricWidth) { return outerRadius * 2; }, hasBiasSeams: false, imagePath: "assets/full-fit.svg", instructions: "Falte den Stoff doppelt. Der Kreismittelpunkt ist in der Ecke des gefalteten Stoffs. Markiere deinen Taillenradius und den vollen Radius von diesem Punkt aus.", } const fullSkirtFullFitThrifty = { // maybe I'll use this later, scoped out for now calculateYardage: function (innerRadius, outerRadius, fabricWidth) { const w = fabricWidth / 2; const twoR = outerRadius * 2; return Math.sqrt(twoR * twoR - w * w) }, hasBiasSeams: false, imagePath: "assets/full-fit.svg", } const halfSkirtHalfFit = { calculateYardage: function (innerRadius, outerRadius, fabricWidth) { return outerRadius * 2; }, hasBiasSeams: false, imagePath: "assets/half-half.svg", instructions: "Dein Kreismittelpunkt ist an der Webkante deines offen gelegten Stoffs, eine Nahtzugaben-Breite von der Webkante entfernt und einen vollen Radius von der Schnittkante entfernt. Zeichne deinen Taillenradius und den vollen Radius ein.", } const threeqSkirtHalfFit = { calculateYardage: function (innerRadius, outerRadius, fabricWidth) { const twoR = outerRadius * 2; const overlap = Math.sqrt(twoR * twoR - fabricWidth * fabricWidth) return outerRadius + overlap; }, hasBiasSeams: false, imagePath: "assets/threeq-half.svg", instructions: "Der erste Kreismittelpunkt ist bei der Webkante des offengelegten Stoffs, eine Nahtzugaben-Breite von der Webkante entfernt und einen vollen Radius von der Schnittkante entfernt. Zeichne deinen Taillenradius und den vollen Radius ein. Dann kannst du den zweiten Kreismittelpunkt bestimmen: Dieser ist diagonal gegenüber vom ersten, an der anderen Webkante. Platziere das zweite Stück so nah wie möglich am Ersten, um Stoff zu sparen. Platziere den Kreismittelpunkt wieder eine Nahtzugaben-Breite von der Webkante entfernt.", } const fullSkirtHalfFit = { calculateYardage:function (innerRadius, outerRadius, fabricWidth) { const twoR = outerRadius * 2; const overlap = Math.sqrt(twoR * twoR - fabricWidth * fabricWidth) return outerRadius * 2 + overlap; }, hasBiasSeams: false, imagePath: "assets/full-half.svg", instructions: "Der erste Kreismittelpunkt ist bei der Webkante des offengelegten Stoffs, eine Nahtzugaben-Breite von der Webkante entfernt und einen vollen Radius von der Schnittkante entfernt. Zeichne deinen Taillenradius und den vollen Radius ein. Dann kannst du den zweiten Kreismittelpunkt bestimmen: Dieser ist diagonal gegenüber vom ersten, an der anderen Webkante. Platziere das zweite Stück so nah wie möglich am Ersten, um Stoff zu sparen. Platziere den Kreismittelpunkt wieder eine Nahtzugaben-Breite von der Webkante entfernt.", } const halfSkirtNoFit = { calculateYardage: function (innerRadius, outerRadius, fabricWidth) { return getQuarterPanelsPatternWidth(innerRadius, outerRadius, fabricWidth, 2); }, hasBiasSeams: true, imagePath: "assets/half-no.svg", instructions: quarterPanelInstructions, } const threeqSkirtNoFit = { calculateYardage: function (innerRadius, outerRadius, fabricWidth) { return getQuarterPanelsPatternWidth(innerRadius, outerRadius, fabricWidth, 3); }, hasBiasSeams: true, imagePath: "assets/threeq-no.svg", instructions: quarterPanelInstructions, } const fullSkirtNoFit = { calculateYardage: function (innerRadius, outerRadius, fabricWidth) { return getQuarterPanelsPatternWidth(innerRadius, outerRadius, fabricWidth, 4); }, hasBiasSeams: true, imagePath: "assets/full-no.svg", instructions: quarterPanelInstructions, } const errorState = { hasBiasSeams: false, imagePath: "assets/emptystate.svg", yardage: "error", instructions: "Dein Rock ist so gross, wir haben leider keine Anleitung für dich finden können. Wir sind uns auch nicht ganz sicher, wieviel Stoff du brauchen wirst. Aber die berechneten Radii stimmen trotzdem. Viel Glück!", } const finder = { full: { fit: fullSkirtFullFit, half: fullSkirtHalfFit, no: fullSkirtNoFit, }, threeq: { fit: threeqSkirtFullFit, half: threeqSkirtHalfFit, no: threeqSkirtNoFit, }, half: { fit: halfSkirtFullFit, half: halfSkirtHalfFit, no: halfSkirtNoFit, } } const centimeterDefaults = { seamAllowance: 1.5, hemAllowance: 3, fabricWidth: 140, } const inchDefaults = { seamAllowance: 0.625, hemAllowance: 2, fabricWidth: 54, } function calculatePatternSize(waist, length, seamAllowance, hemAllowance, skirtType) { const waistRadius = waist / (Math.PI * 2); console.log(skirtType); const normalizedWaistRadius = skirtType === "half" ? waistRadius*2 : skirtType === "threeq" ? waistRadius*4/3 : waistRadius; console.log(normalizedWaistRadius); const hemRadius = normalizedWaistRadius + length; const innerRadius = normalizedWaistRadius - seamAllowance; const outerRadius = hemRadius + hemAllowance; return { innerRadius: innerRadius, outerRadius: outerRadius, }; } function calculateYardage(innerRadius, outerRadius, skirtType, fabricWidth) { const variant = _getVariant(outerRadius, skirtType, fabricWidth); if (variant === "error") return errorState; return { hasBiasSeams: variant.hasBiasSeams, imagePath: variant.imagePath, yardage: variant.calculateYardage(innerRadius, outerRadius, fabricWidth) * 1.07, instructions: variant.instructions, }; } function _getVariant(outerRadius, skirtType, fabricWidth) { const fitVariant = _getFitVariant(outerRadius, fabricWidth); if (!(skirtType in finder)) return "error"; if (!(fitVariant in finder[skirtType])) return "error"; return finder[skirtType][fitVariant]; } function _getFitVariant(outerRadius, fabricWidth) { if (outerRadius * 2 < fabricWidth) return "fit"; if (outerRadius < fabricWidth) return "half"; if (outerRadius * (Math.SQRT2/2) < fabricWidth) return "no"; return "doesnotcompute"; }