裙片排版小程序

来源:互联网 发布:三维凸包算法 编辑:程序博客网 时间:2024/06/11 17:00

sublime text editor
需求:
你有一块布,布的长度和门幅确定,问怎么对裙片进行排版,可以使得用料最省?
裙片是一个扇环。

需要用到三角函数,勾股定理。

输入参数:
布匹长度: len
布匹门幅(宽度): width
裙片的内圆半径(一般是13厘米左右): r2
裙片的外圆半径: r1
裙片的角的大小(一般是180度到45度,角度制): angle
是否从半片开始(堆叠裁剪,工厂裁剪都是从半片开始):startWithHalf

输出
布匹的最大利用率:unitUsage
布匹的实际利用率:usagePercent

工厂一般采用堆叠裁剪,先把布匹Z型堆叠,然后从半片开始裁剪,追求布匹的最大利用率。
裙子长度 = 裙片的外圆半径 - 裙片的内圆半径

其他参数说明:
裙片排版宽度的一半:eLen
裙片排版高度:singePartHeight

裙片的拼接方式主要有两种:
1. 圆弧拼接 arcMatching()
2. 半径拼接 radiusMatching()

最经济的拼接方式应该是圆弧拼接,当r1 == width, 裙片的角为180度时,最大利用率unitUsage = 0.8948967025354823

当裙片的角为30度时,进行半径拼接,最大利用率虽然可以达到0.96,但是裙片变小变多,需要进行更多的缝纫,另外太多的缝和,使得成品不够美观,档次被拉低了

<!DOCTYPE html><html><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><head></head><body style="font-family:'lucida grande', tahoma, verdana, arial, sans-serif;background-color: #f7f7f7;color: #333;"><img id="spacebg" src="http://my.csdn.net/uploads/201207/02/1341222679_9916.jpg" style="display:none" /><canvas id="canvas" width="660" height="510" style="border:1px dotted;float:left"></canvas><br><form action="action_page.php">inner radius (cm):<br><input type="text" id="innerR" value="13"><br>outer radius (cm):<br><input type="text" id="outerR" value="113"><br>skirt part angle (degree):<br><input type="text" id="angleInput" value="90"><br>cloth width (cm):<br><input type="text" id="widthInput" value="140"><br>cloth length (cm):<br><input type="text" id="lengthInput" value="500"><br>start with half part:<input type="checkbox" name="startWithHalfCb" checked="checked" id="cb1"><br><br><span>Total usage:</span> <span id="usage">0</span><br> <span>Unit usage:</span> <span id="unitUsage">0</span> <br> <span>Half parts:</span> <span id="halfParts">0</span> <br><br><br><!-- <input type="submit" value="Submit" onclick="start()"> --></form> <input type="button" value="start" onclick="start()" id="startBtn" /><script>var r1 = 90;var r2 = 20;var angle = 180;var width = 140;var len = 500;var angleBeta = (180 - angle) / 2;var d1, d2, stepLen, eLen;var skirtPartArea;var startWithHalf = true;var halfCount = 0;function drawSkirtPart(ctx, x, y, startRadian, endRadian) {    ctx.beginPath();    ctx.moveTo(x, y);    ctx.arc(x, y, r1, startRadian, endRadian, false);    ctx.fillStyle="#009900";     ctx.closePath();    ctx.fill();    ctx.beginPath();    ctx.moveTo(x, y);    ctx.arc(x, y, r2, startRadian, endRadian, false);    ctx.fillStyle="white";     ctx.closePath();    ctx.fill();}function initParams () {    r1 = parseInt(document.getElementById("outerR").value);    r2 = parseInt(document.getElementById("innerR").value);    angle = parseInt(document.getElementById("angleInput").value);    width = parseInt(document.getElementById("widthInput").value);    len = parseInt(document.getElementById("lengthInput").value);    var cbs = document.getElementsByName('startWithHalfCb');     for(var i=0;i<cbs.length;i++){        startWithHalf = cbs[i].checked;    }    angleBeta = (180 - angle) / 2;}function draw() {    var canvas = document.getElementById("canvas");    if (canvas == null) {     return;    }    var ctx = canvas.getContext("2d");    ctx.clearRect(0, 0, 600, 600);    ctx.strokeRect(0, 0, len, width);    if (halfCount == 0) {        return;    }    var start1 = degreeToRadian(angleBeta);    var end1 = degreeToRadian(angleBeta + angle);    var count = halfCount;    if (startWithHalf) {        drawSkirtPart(ctx, 0, -d1, start1, Math.PI / 2);        count--;        var drawDown = true;        for (var i=1; count > 0; count -= 2) {            if (count > 1) {                if (drawDown) {                    drawSkirtPart(ctx, stepLen * i, width + d1, start1 + Math.PI, end1 + Math.PI);                } else {                    drawSkirtPart(ctx, stepLen * i, -d1, start1, end1);                }            } else {                if (drawDown) {                    drawSkirtPart(ctx, stepLen * i, width + d1, start1 + Math.PI, Math.PI * 1.5);                } else {                    drawSkirtPart(ctx, stepLen * i, -d1, Math.PI / 2, end1);                }            }            drawDown = !drawDown;            i++;        }    } else {        if (halfCount > 1) {            drawSkirtPart(ctx, eLen, -d1, start1, end1);            count -= 2;        } else {            drawSkirtPart(ctx, eLen, -d1, Math.PI / 2, end1);            count--;        }        var drawDown = true;        for (var i=1; count > 0; count -= 2) {            if (count > 1) {                if (drawDown) {                    drawSkirtPart(ctx, stepLen * i + eLen, width + d1, start1 + Math.PI, end1 + Math.PI);                } else {                    drawSkirtPart(ctx, stepLen * i + eLen, -d1, start1, end1);                }            } else {                if (drawDown) {                    drawSkirtPart(ctx, stepLen * i + eLen, width + d1, start1 + Math.PI, Math.PI * 1.5);                } else {                    drawSkirtPart(ctx, stepLen * i + eLen, -d1, Math.PI / 2, end1);                }            }            drawDown = !drawDown;            i++;        }    }}function draw2() {    var canvas = document.getElementById("canvas");    if (canvas == null) {     return;    }    var ctx = canvas.getContext("2d");    ctx.clearRect(0, 0, 600, 600);    ctx.strokeRect(0, 0, len, width);    if (halfCount == 0) {        return;    }    var start1 = degreeToRadian(angleBeta) + Math.PI;    var end1 = start1 + degreeToRadian(angle);    var count = halfCount;    if (startWithHalf) {        drawSkirtPart(ctx, 0, r1, Math.PI*1.5, end1);        count--;        var drawDown = true;        for (var i=1; count > 0; count -= 2) {            if (count > 1) {                if (drawDown) {                    drawSkirtPart(ctx, stepLen * i, extraH, start1 - Math.PI, end1 - Math.PI);                } else {                    drawSkirtPart(ctx, stepLen * i, r1, start1, end1);                }            } else {                if (drawDown) {                    drawSkirtPart(ctx, stepLen * i, extraH, Math.PI / 2, end1 - Math.PI);                } else {                    drawSkirtPart(ctx, stepLen * i, r1, start1, Math.PI * 1.5);                }            }            drawDown = !drawDown;            i++;        }    } else {        if (halfCount > 1) {            drawSkirtPart(ctx, eLen, r1, start1, end1);            count -= 2;        } else {            drawSkirtPart(ctx, eLen, r1, start1, Math.PI * 1.5);            count--;        }        var drawDown = true;        for (var i=1; count > 0; count -= 2) {            if (count > 1) {                if (drawDown) {                    drawSkirtPart(ctx, stepLen * i + eLen, extraH, start1 - Math.PI, end1 - Math.PI);                } else {                    drawSkirtPart(ctx, stepLen * i + eLen, r1, start1, end1);                }            } else {                if (drawDown) {                    drawSkirtPart(ctx, stepLen * i + eLen, extraH, Math.PI / 2, end1 - Math.PI);                } else {                    drawSkirtPart(ctx, stepLen * i + eLen, r1, start1, Math.PI * 1.5);                }            }            drawDown = !drawDown;            i++;        }    }}var isLineMatching;function start() {    initParams ();    eLen = r1 * Math.sin(degreeToRadian( angle/2 ));    var totalArea = width * len;    var singePartHeight = r1 - r2 * Math.sin(degreeToRadian(angleBeta));    if (singePartHeight > width) {        alert("cloth not support such long skirt part!");    }    var stepLenRadius = radiusMatching();    var stepLenArc = arcMatching();    if (stepLenRadius <= stepLenArc) {        stepLen = stepLenRadius;        isLineMatching = true;    } else {        stepLen = stepLenArc;        isLineMatching = false;    }    skirtPartArea = Math.PI * (r1 * r1 - r2 * r2) * (angle / 360);    // alert("stepLen: " + stepLen + ", eLen: " + eLen);    if (startWithHalf) {        halfCount = getHalfPartsCount(len, stepLen, eLen);    } else {        halfCount = getHalfPartsCount(len - eLen, stepLen, eLen);        halfCount ++;    }    var usagePercent = (skirtPartArea * halfCount / 2) / totalArea;    var unitUsage = skirtPartArea / (width * stepLen);    // alert("unitUsage: " + unitUsage + ", usagePercent: " + usagePercent + ", halfCount: " + halfCount);    document.getElementById("unitUsage").innerHTML = unitUsage;    document.getElementById("usage").innerHTML = usagePercent;    document.getElementById("halfParts").innerHTML = halfCount;    if (isLineMatching) {        draw2();    } else {        draw();    }}var extraH;function radiusMatching() {    var stepLength;    extraH = r1 - r1 * Math.sin(degreeToRadian(angleBeta));    var h2 = r1 + extraH;    if (h2 <= width) {        stepLength = r1 * Math.cos(degreeToRadian(angleBeta));    } else {        var len2 = width / Math.sin(degreeToRadian(angleBeta));        var ret1 = (len2 + 2 * r2) * Math.cos(degreeToRadian(angleBeta));        var dh = width - r1;        var h2 = width - 2 * dh;        var ret2 = h2 / Math.tan(degreeToRadian(angleBeta));        if (ret1 <= ret2) {            stepLength = ret1;        } else {            stepLength = ret2;            extraH = dh;        }    }    return stepLength;}function arcMatching() {    d1 = r2 * Math.sin(degreeToRadian(angleBeta));    var d2 = width + 2 * d1;    var hypotenuse = 2 * r1;    var stepLength = Math.sqrt(hypotenuse*hypotenuse - d2 * d2);    var minStepLen = r1 * Math.cos(angleBeta);    if (stepLength < minStepLen) {        stepLength = minStepLen;    }    return stepLength;}function degreeToRadian(degree) {    return (degree / 180) * Math.PI;}function getHalfPartsCount(length, stepLength, halfPartWidth) {    // if (stepLength < halfPartWidth) {    //  return 0;    // }    var c = parseInt(length / stepLength);    var remain = length - c * stepLength;    var halfCount = c * 2;    if (remain >= halfPartWidth) {        halfCount ++;    }    return halfCount;}// window.onload=init;</script></body></html>
0 0