Merge branch 'master' of https://github.com/prusa3d/PrusaSlicer into et_adaptive_layer_height
This commit is contained in:
commit
3baf11f694
29 changed files with 2228 additions and 360 deletions
47
resources/icons/bed/ender3.svg
Normal file
47
resources/icons/bed/ender3.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 17 KiB |
109
resources/icons/bed/mini.svg
Normal file
109
resources/icons/bed/mini.svg
Normal file
|
@ -0,0 +1,109 @@
|
|||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" width="180.7mm" height="180.6mm" viewBox="0 0 512.1 512">
|
||||
<title>bed_texture_denser</title>
|
||||
<path d="M510.6,510.9" transform="translate(0.7 0.4)" style="fill: none;stroke: #fff;stroke-linecap: round;stroke-linejoin: round;stroke-width: 1.5px"/>
|
||||
<path d="M.4,510.9" transform="translate(0.7 0.4)" style="fill: none;stroke: #fff;stroke-linecap: round;stroke-linejoin: round;stroke-width: 1.5px"/>
|
||||
<line x1="511.3" y1="511.3" x2="511.3" y2="0.8" style="fill: none;stroke: #fff;stroke-linecap: round;stroke-linejoin: round;stroke-width: 1.5px"/>
|
||||
<path d="M.4.4" transform="translate(0.7 0.4)" style="fill: none;stroke: #fff;stroke-linecap: round;stroke-linejoin: round;stroke-width: 1.5px"/>
|
||||
<path d="M510.6.4" transform="translate(0.7 0.4)" style="fill: none;stroke: #fff;stroke-linecap: round;stroke-linejoin: round;stroke-width: 1.5px"/>
|
||||
<line x1="1.1" y1="0.8" x2="1.1" y2="511.3" style="fill: none;stroke: #fff;stroke-linecap: round;stroke-linejoin: round;stroke-width: 1.5px"/>
|
||||
<line x1="1.1" y1="511.3" x2="1.1" y2="0.8" style="fill: none;stroke: #fff;stroke-linecap: round;stroke-linejoin: round;stroke-width: 1.5px"/>
|
||||
<line x1="511.3" y1="0.8" x2="511.3" y2="511.3" style="fill: none;stroke: #fff;stroke-linecap: round;stroke-linejoin: round;stroke-width: 1.5px"/>
|
||||
<line x1="1.1" y1="511.3" x2="511.3" y2="511.3" style="fill: none;stroke: #fff;stroke-linecap: round;stroke-linejoin: round;stroke-width: 1.5px"/>
|
||||
<line x1="1.1" y1="0.8" x2="511.3" y2="0.8" style="fill: none;stroke: #fff;stroke-linecap: round;stroke-linejoin: round;stroke-width: 1.5px"/>
|
||||
<g>
|
||||
<g>
|
||||
<line x1="1.1" y1="383.6" x2="3.2" y2="383.6" style="fill: none;stroke: #fff;stroke-linecap: round;stroke-linejoin: round"/>
|
||||
<line x1="5.4" y1="383.6" x2="7" y2="383.6" style="fill: none;stroke: #fff;stroke-linecap: round;stroke-linejoin: round;stroke-dasharray: 0.5694814920425415,2.1355555057525635"/>
|
||||
<line x1="8.1" y1="383.6" x2="508.1" y2="383.6" style="fill: none;stroke: #fff;stroke-linecap: round;stroke-linejoin: round;stroke-dasharray: 4.271111011505127,2.1355555057525635,0.5694814920425415,2.1355555057525635"/>
|
||||
<line x1="509.2" y1="383.6" x2="511.3" y2="383.6" style="fill: none;stroke: #fff;stroke-linecap: round;stroke-linejoin: round"/>
|
||||
</g>
|
||||
<g>
|
||||
<line x1="1.1" y1="256" x2="3.2" y2="256" style="fill: none;stroke: #fff;stroke-linecap: round;stroke-linejoin: round"/>
|
||||
<line x1="5.4" y1="256" x2="7" y2="256" style="fill: none;stroke: #fff;stroke-linecap: round;stroke-linejoin: round;stroke-dasharray: 0.5694814920425415,2.1355555057525635"/>
|
||||
<line x1="8.1" y1="256" x2="508.1" y2="256" style="fill: none;stroke: #fff;stroke-linecap: round;stroke-linejoin: round;stroke-dasharray: 4.271111011505127,2.1355555057525635,0.5694814920425415,2.1355555057525635"/>
|
||||
<line x1="509.2" y1="256" x2="511.3" y2="256" style="fill: none;stroke: #fff;stroke-linecap: round;stroke-linejoin: round"/>
|
||||
</g>
|
||||
<g>
|
||||
<line x1="511.3" y1="128.4" x2="509.2" y2="128.4" style="fill: none;stroke: #fff;stroke-linecap: round;stroke-linejoin: round"/>
|
||||
<line x1="507.1" y1="128.4" x2="505.4" y2="128.4" style="fill: none;stroke: #fff;stroke-linecap: round;stroke-linejoin: round;stroke-dasharray: 0.5694814920425415,2.1355555057525635"/>
|
||||
<line x1="504.4" y1="128.4" x2="4.3" y2="128.4" style="fill: none;stroke: #fff;stroke-linecap: round;stroke-linejoin: round;stroke-dasharray: 4.271111011505127,2.1355555057525635,0.5694814920425415,2.1355555057525635"/>
|
||||
<line x1="3.2" y1="128.4" x2="1.1" y2="128.4" style="fill: none;stroke: #fff;stroke-linecap: round;stroke-linejoin: round"/>
|
||||
</g>
|
||||
<g>
|
||||
<line x1="128.7" y1="511.3" x2="128.7" y2="509.1" style="fill: none;stroke: #fff;stroke-linecap: round;stroke-linejoin: round"/>
|
||||
<line x1="128.7" y1="507" x2="128.7" y2="505.4" style="fill: none;stroke: #fff;stroke-linecap: round;stroke-linejoin: round;stroke-dasharray: 0.569789707660675,2.1367111206054688"/>
|
||||
<line x1="128.7" y1="504.3" x2="128.7" y2="3.9" style="fill: none;stroke: #fff;stroke-linecap: round;stroke-linejoin: round;stroke-dasharray: 4.2734222412109375,2.1367111206054688,0.569789707660675,2.1367111206054688"/>
|
||||
<line x1="128.7" y1="2.9" x2="128.7" y2="0.8" style="fill: none;stroke: #fff;stroke-linecap: round;stroke-linejoin: round"/>
|
||||
</g>
|
||||
<g>
|
||||
<line x1="256.2" y1="0.8" x2="256.2" y2="2.9" style="fill: none;stroke: #fff;stroke-linecap: round;stroke-linejoin: round"/>
|
||||
<line x1="256.2" y1="5" x2="256.2" y2="6.7" style="fill: none;stroke: #fff;stroke-linecap: round;stroke-linejoin: round;stroke-dasharray: 0.569789707660675,2.1367111206054688"/>
|
||||
<line x1="256.2" y1="7.7" x2="256.2" y2="508.1" style="fill: none;stroke: #fff;stroke-linecap: round;stroke-linejoin: round;stroke-dasharray: 4.2734222412109375,2.1367111206054688,0.569789707660675,2.1367111206054688"/>
|
||||
<line x1="256.2" y1="509.1" x2="256.2" y2="511.3" style="fill: none;stroke: #fff;stroke-linecap: round;stroke-linejoin: round"/>
|
||||
</g>
|
||||
<g>
|
||||
<line x1="383.8" y1="482.3" x2="383.8" y2="480.2" style="fill: none;stroke: #fff;stroke-linecap: round;stroke-linejoin: round"/>
|
||||
<line x1="383.8" y1="478" x2="383.8" y2="476.4" style="fill: none;stroke: #fff;stroke-linecap: round;stroke-linejoin: round;stroke-dasharray: 0.5678567290306091,2.129462480545044"/>
|
||||
<line x1="383.8" y1="475.3" x2="383.8" y2="3.9" style="fill: none;stroke: #fff;stroke-linecap: round;stroke-linejoin: round;stroke-dasharray: 4.258924961090088,2.129462480545044,0.5678567290306091,2.129462480545044"/>
|
||||
<line x1="383.8" y1="2.9" x2="383.8" y2="0.8" style="fill: none;stroke: #fff;stroke-linecap: round;stroke-linejoin: round"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<path d="M277.3,489.1c4.6,0,7.4,2.8,7.4,8.1s-2.9,8.1-7.4,8.1-7.4-2.9-7.4-8.1S272.9,489.1,277.3,489.1Zm3.7,8.1c0-3.8-1.5-5.7-3.7-5.7s-3.8,1.9-3.8,5.7,1.3,5.6,3.8,5.6S281,500.9,281,497.2Z" transform="translate(0.7 0.4)" style="fill: #fff"/>
|
||||
<path d="M293.1,499h-2.5v6h-3.3V489.3h6.1a7.3,7.3,0,0,1,3.2.6,4.1,4.1,0,0,1,2.6,4,4.4,4.4,0,0,1-3.1,4.3h0l3.5,6.8H296Zm-.1-2.4c1.5,0,2.7-.7,2.7-2.5a2.4,2.4,0,0,0-2.7-2.5h-2.4v5Z" transform="translate(0.7 0.4)" style="fill: #fff"/>
|
||||
<path d="M302,489.3h3.4V505H302Z" transform="translate(0.7 0.4)" style="fill: #fff"/>
|
||||
<path d="M311.6,497.2c0,4,1.4,5.6,3.8,5.6s3.4-1.3,3.6-3.5V499h-3.7v-2.4h6.8V505h-2.6v-2.2h-.1a5,5,0,0,1-4.6,2.5c-4.4,0-6.8-3.1-6.8-7.9s3-8.3,7.4-8.3,6.1,1.7,6.4,4.9h-3.4a2.8,2.8,0,0,0-3-2.5C313,491.5,311.6,493.5,311.6,497.2Z" transform="translate(0.7 0.4)" style="fill: #fff"/>
|
||||
<path d="M325.1,489.3h3.4V505h-3.4Z" transform="translate(0.7 0.4)" style="fill: #fff"/>
|
||||
<path d="M331.7,489.3h3.7l5,8.5a16.8,16.8,0,0,1,1.2,2.3h0V489.3h3.1V505h-3.5l-5.3-8.7a12.8,12.8,0,0,1-1.1-2.4h-.1V505h-3Z" transform="translate(0.7 0.4)" style="fill: #fff"/>
|
||||
<path d="M356.8,501.5H351l-1.1,3.5h-3.2l5.4-15.7h3.8l5.6,15.7h-3.6Zm-3.5-7.1-1.5,4.6H356l-1.5-4.5c-.4-1.4-.6-2.3-.6-2.3h0A15.3,15.3,0,0,1,353.3,494.4Z" transform="translate(0.7 0.4)" style="fill: #fff"/>
|
||||
<path d="M363.4,489.3h3.4v13h6.8V505H363.4Z" transform="translate(0.7 0.4)" style="fill: #fff"/>
|
||||
<path d="M384,499.6V505h-3.4V489.3h5.5c3.4,0,6,1.4,6,5s-2.8,5.3-6.3,5.3Zm2-2.5a2.5,2.5,0,0,0,2.8-2.7c0-1.9-1.1-2.7-2.8-2.7h-2v5.4Z" transform="translate(0.7 0.4)" style="fill: #fff"/>
|
||||
<path d="M400.1,499h-2.4v6h-3.4V489.3h6.1a7.3,7.3,0,0,1,3.2.6,3.9,3.9,0,0,1,2.6,4,4.5,4.5,0,0,1-3,4.3h0l3.5,6.8H403Zm-.1-2.4c1.5,0,2.8-.7,2.8-2.5a2.4,2.4,0,0,0-2.7-2.5h-2.4v5Z" transform="translate(0.7 0.4)" style="fill: #fff"/>
|
||||
<path d="M408.7,489.3H412v9.1a5.6,5.6,0,0,0,.6,3.2,3.6,3.6,0,0,0,5,0c.6-.8.5-2.1.5-3.2v-9.1h3.3v10.2c0,3.9-2.5,5.8-6.4,5.8s-6.3-1.8-6.3-5.8Z" transform="translate(0.7 0.4)" style="fill: #fff"/>
|
||||
<path d="M432.4,493.5a2,2,0,0,0-2.3-2c-1.5,0-2.4.8-2.4,1.9s.6,1.7,2.1,1.9l2.4.5c2.8.5,4.1,2,4.1,4.3s-2.3,5.2-6.3,5.2-6.1-1.9-6.2-4.8h3.5a2.5,2.5,0,0,0,2.8,2.3c1.9,0,2.7-.9,2.7-2.1s-.5-1.7-2.2-2l-2.3-.4c-2.4-.5-4.1-1.9-4.1-4.4s2.2-4.8,5.9-4.8,5.7,2,5.8,4.4Z" transform="translate(0.7 0.4)" style="fill: #fff"/>
|
||||
<path d="M447.4,501.5h-5.7l-1.2,3.5h-3.2l5.5-15.7h3.7l5.6,15.7h-3.5Zm-3.5-7.1-1.4,4.6h4.1l-1.4-4.5a11.3,11.3,0,0,1-.6-2.3h-.1A15.3,15.3,0,0,1,443.9,494.4Z" transform="translate(0.7 0.4)" style="fill: #fff"/>
|
||||
<path d="M458.7,489.3h4.9l2.8,8.4a15.7,15.7,0,0,1,.7,2.3h0l.7-2.3,2.8-8.4h4.9V505h-3.3V492.7h-.1a26.9,26.9,0,0,1-1,3.3l-2.9,9h-2.5l-2.9-9a26.9,26.9,0,0,1-1-3.3h0V505h-3.1Z" transform="translate(0.7 0.4)" style="fill: #fff"/>
|
||||
<path d="M478.6,489.3H482V505h-3.4Z" transform="translate(0.7 0.4)" style="fill: #fff"/>
|
||||
<path d="M485.2,489.3h3.7l5,8.5a16.8,16.8,0,0,1,1.2,2.3h0V489.3h3.1V505h-3.5l-5.3-8.7a12.8,12.8,0,0,1-1.1-2.4h-.1V505h-3Z" transform="translate(0.7 0.4)" style="fill: #fff"/>
|
||||
<path d="M501.3,489.3h3.4V505h-3.4Z" transform="translate(0.7 0.4)" style="fill: #fff"/>
|
||||
</g>
|
||||
<line x1="0.4" y1="28.7" x2="511" y2="28.7" style="fill: none;stroke: #fff;stroke-miterlimit: 10;stroke-width: 0.25px"/>
|
||||
<line x1="0.4" y1="57.1" x2="511" y2="57.1" style="fill: none;stroke: #fff;stroke-miterlimit: 10;stroke-width: 0.25px"/>
|
||||
<line x1="0.4" y1="28.7" x2="511" y2="28.7" style="fill: none;stroke: #fff;stroke-miterlimit: 10;stroke-width: 0.25px"/>
|
||||
<line x1="0.1" y1="85.4" x2="510.7" y2="85.4" style="fill: none;stroke: #fff;stroke-miterlimit: 10;stroke-width: 0.25px"/>
|
||||
<line x1="0.1" y1="113.8" x2="510.7" y2="113.8" style="fill: none;stroke: #fff;stroke-miterlimit: 10;stroke-width: 0.25px"/>
|
||||
<line x1="0.9" y1="142.1" x2="511.5" y2="142.1" style="fill: none;stroke: #fff;stroke-miterlimit: 10;stroke-width: 0.25px"/>
|
||||
<path d="M509.9,141.7" transform="translate(0.7 0.4)" style="fill: none;stroke: #fff;stroke-miterlimit: 10;stroke-width: 0.25px"/>
|
||||
<path d="M-.7,141.7" transform="translate(0.7 0.4)" style="fill: none;stroke: #fff;stroke-miterlimit: 10;stroke-width: 0.25px"/>
|
||||
<line x1="1.5" y1="198.8" x2="512.1" y2="198.8" style="fill: none;stroke: #fff;stroke-miterlimit: 10;stroke-width: 0.25px"/>
|
||||
<line y1="170.5" x2="510.6" y2="170.5" style="fill: none;stroke: #fff;stroke-miterlimit: 10;stroke-width: 0.25px"/>
|
||||
<line x1="0.5" y1="227.2" x2="511.1" y2="227.2" style="fill: none;stroke: #fff;stroke-miterlimit: 10;stroke-width: 0.25px"/>
|
||||
<line x1="0.6" y1="283.9" x2="511.2" y2="283.9" style="fill: none;stroke: #fff;stroke-miterlimit: 10;stroke-width: 0.25px"/>
|
||||
<line x1="0.5" y1="28.7" x2="511.1" y2="28.7" style="fill: none;stroke: #fff;stroke-miterlimit: 10;stroke-width: 0.25px"/>
|
||||
<line x1="0.6" y1="312.2" x2="511.2" y2="312.2" style="fill: none;stroke: #fff;stroke-miterlimit: 10;stroke-width: 0.25px"/>
|
||||
<line x1="0.6" y1="340.6" x2="511.2" y2="340.6" style="fill: none;stroke: #fff;stroke-miterlimit: 10;stroke-width: 0.25px"/>
|
||||
<line x1="0.6" y1="368.9" x2="511.2" y2="368.9" style="fill: none;stroke: #fff;stroke-miterlimit: 10;stroke-width: 0.25px"/>
|
||||
<line x1="0.6" y1="397.2" x2="511.2" y2="397.2" style="fill: none;stroke: #fff;stroke-miterlimit: 10;stroke-width: 0.25px"/>
|
||||
<line x1="0.6" y1="425.6" x2="511.2" y2="425.6" style="fill: none;stroke: #fff;stroke-miterlimit: 10;stroke-width: 0.25px"/>
|
||||
<line x1="0.6" y1="453.9" x2="511.2" y2="453.9" style="fill: none;stroke: #fff;stroke-miterlimit: 10;stroke-width: 0.25px"/>
|
||||
<line x1="0.6" y1="482.3" x2="511.2" y2="482.3" style="fill: none;stroke: #fff;stroke-miterlimit: 10;stroke-width: 0.25px"/>
|
||||
<path d="M481.9,511.4" transform="translate(0.7 0.4)" style="fill: none;stroke: #fff;stroke-miterlimit: 10;stroke-width: 0.25px"/>
|
||||
<path d="M481.9.8" transform="translate(0.7 0.4)" style="fill: none;stroke: #fff;stroke-miterlimit: 10;stroke-width: 0.25px"/>
|
||||
<line x1="454.3" y1="1.2" x2="454.3" y2="482.3" style="fill: none;stroke: #fff;stroke-miterlimit: 10;stroke-width: 0.25px"/>
|
||||
<line x1="482.6" y1="1.2" x2="482.6" y2="482.3" style="fill: none;stroke: #fff;stroke-miterlimit: 10;stroke-width: 0.25px"/>
|
||||
<line x1="425.9" y1="0.8" x2="425.9" y2="482.3" style="fill: none;stroke: #fff;stroke-miterlimit: 10;stroke-width: 0.25px"/>
|
||||
<line x1="397.6" y1="0.8" x2="397.6" y2="482.3" style="fill: none;stroke: #fff;stroke-miterlimit: 10;stroke-width: 0.25px"/>
|
||||
<line x1="369.2" y1="1.7" x2="369.2" y2="482.3" style="fill: none;stroke: #fff;stroke-miterlimit: 10;stroke-width: 0.25px"/>
|
||||
<line x1="312.6" y1="2.2" x2="312.6" y2="482.3" style="fill: none;stroke: #fff;stroke-miterlimit: 10;stroke-width: 0.25px"/>
|
||||
<line x1="340.9" y1="0.8" x2="340.9" y2="482.3" style="fill: none;stroke: #fff;stroke-miterlimit: 10;stroke-width: 0.25px"/>
|
||||
<line x1="284.2" y1="1.3" x2="284.2" y2="482.3" style="fill: none;stroke: #fff;stroke-miterlimit: 10;stroke-width: 0.25px"/>
|
||||
<line x1="227.5" y1="1.3" x2="227.5" y2="511.9" style="fill: none;stroke: #fff;stroke-miterlimit: 10;stroke-width: 0.25px"/>
|
||||
<line x1="482.6" y1="1.3" x2="482.6" y2="482.3" style="fill: none;stroke: #fff;stroke-miterlimit: 10;stroke-width: 0.25px"/>
|
||||
<line x1="199.2" y1="1.3" x2="199.2" y2="511.9" style="fill: none;stroke: #fff;stroke-miterlimit: 10;stroke-width: 0.25px"/>
|
||||
<line x1="170.8" y1="1.3" x2="170.8" y2="511.9" style="fill: none;stroke: #fff;stroke-miterlimit: 10;stroke-width: 0.25px"/>
|
||||
<line x1="142.5" y1="1.3" x2="142.5" y2="511.9" style="fill: none;stroke: #fff;stroke-miterlimit: 10;stroke-width: 0.25px"/>
|
||||
<line x1="114.1" y1="1.3" x2="114.1" y2="511.9" style="fill: none;stroke: #fff;stroke-miterlimit: 10;stroke-width: 0.25px"/>
|
||||
<line x1="85.8" y1="1.3" x2="85.8" y2="511.9" style="fill: none;stroke: #fff;stroke-miterlimit: 10;stroke-width: 0.25px"/>
|
||||
<line x1="57.4" y1="1.3" x2="57.4" y2="511.9" style="fill: none;stroke: #fff;stroke-miterlimit: 10;stroke-width: 0.25px"/>
|
||||
<line x1="29.1" y1="1.3" x2="29.1" y2="511.9" style="fill: none;stroke: #fff;stroke-miterlimit: 10;stroke-width: 0.25px"/>
|
||||
</svg>
|
After Width: | Height: | Size: 14 KiB |
BIN
resources/icons/printers/Creality_Ender3.png
Normal file
BIN
resources/icons/printers/Creality_Ender3.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 61 KiB |
BIN
resources/icons/printers/PrusaResearch_MINI.png
Normal file
BIN
resources/icons/printers/PrusaResearch_MINI.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 58 KiB |
BIN
resources/models/ender3_bed.stl
Normal file
BIN
resources/models/ender3_bed.stl
Normal file
Binary file not shown.
BIN
resources/models/mini_bed.stl
Normal file
BIN
resources/models/mini_bed.stl
Normal file
Binary file not shown.
415
resources/profiles/Creality.ini
Normal file
415
resources/profiles/Creality.ini
Normal file
|
@ -0,0 +1,415 @@
|
|||
# Print profiles for the Creality printers.
|
||||
|
||||
[vendor]
|
||||
# Vendor name will be shown by the Config Wizard.
|
||||
name = Creality
|
||||
# Configuration version of this file. Config file will only be installed, if the config_version differs.
|
||||
# This means, the server may force the PrusaSlicer configuration to be downgraded.
|
||||
config_version = 0.0.1
|
||||
# Where to get the updates from?
|
||||
config_update_url = http://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/Creality/
|
||||
# changelog_url = http://files.prusa3d.com/?latest=slicer-profiles&lng=%1%
|
||||
|
||||
# The printer models will be shown by the Configuration Wizard in this order,
|
||||
# also the first model installed & the first nozzle installed will be activated after install.
|
||||
# Printer model name will be shown by the installation wizard.
|
||||
|
||||
[printer_model:ENDER3]
|
||||
name = Creality Ender-3
|
||||
variants = 0.4
|
||||
technology = FFF
|
||||
|
||||
# All presets starting with asterisk, for example *common*, are intermediate and they will
|
||||
# not make it into the user interface.
|
||||
|
||||
# Common print preset
|
||||
[print:*common*]
|
||||
avoid_crossing_perimeters = 0
|
||||
bridge_angle = 0
|
||||
bridge_flow_ratio = 0.95
|
||||
bridge_speed = 25
|
||||
brim_width = 0
|
||||
clip_multipart_objects = 1
|
||||
compatible_printers =
|
||||
complete_objects = 0
|
||||
dont_support_bridges = 1
|
||||
elefant_foot_compensation = 0
|
||||
ensure_vertical_shell_thickness = 1
|
||||
external_fill_pattern = rectilinear
|
||||
external_perimeters_first = 0
|
||||
external_perimeter_extrusion_width = 0.45
|
||||
extra_perimeters = 0
|
||||
extruder_clearance_height = 25
|
||||
extruder_clearance_radius = 45
|
||||
extrusion_width = 0.45
|
||||
fill_angle = 45
|
||||
fill_density = 20%
|
||||
fill_pattern = grid
|
||||
first_layer_extrusion_width = 0.42
|
||||
first_layer_height = 0.2
|
||||
first_layer_speed = 20
|
||||
gap_fill_speed = 30
|
||||
gcode_comments = 0
|
||||
infill_every_layers = 1
|
||||
infill_extruder = 1
|
||||
infill_extrusion_width = 0.45
|
||||
infill_first = 0
|
||||
infill_only_where_needed = 0
|
||||
infill_overlap = 25%
|
||||
interface_shells = 0
|
||||
max_print_speed = 100
|
||||
max_volumetric_extrusion_rate_slope_negative = 0
|
||||
max_volumetric_extrusion_rate_slope_positive = 0
|
||||
max_volumetric_speed = 0
|
||||
min_skirt_length = 4
|
||||
notes =
|
||||
overhangs = 0
|
||||
only_retract_when_crossing_perimeters = 0
|
||||
ooze_prevention = 0
|
||||
output_filename_format = {input_filename_base}_{layer_height}mm_{filament_type[0]}_{printer_model}_{print_time}.gcode
|
||||
perimeters = 2
|
||||
perimeter_extruder = 1
|
||||
perimeter_extrusion_width = 0.45
|
||||
post_process =
|
||||
print_settings_id =
|
||||
raft_layers = 0
|
||||
resolution = 0
|
||||
seam_position = nearest
|
||||
single_extruder_multi_material_priming = 1
|
||||
skirts = 1
|
||||
skirt_distance = 2
|
||||
skirt_height = 2
|
||||
small_perimeter_speed = 25
|
||||
solid_infill_below_area = 0
|
||||
solid_infill_every_layers = 0
|
||||
solid_infill_extruder = 1
|
||||
solid_infill_extrusion_width = 0.45
|
||||
spiral_vase = 0
|
||||
standby_temperature_delta = -5
|
||||
support_material = 0
|
||||
support_material_extruder = 0
|
||||
support_material_extrusion_width = 0.4
|
||||
support_material_interface_extruder = 0
|
||||
support_material_angle = 0
|
||||
support_material_buildplate_only = 0
|
||||
support_material_enforce_layers = 0
|
||||
support_material_contact_distance = 0.15
|
||||
support_material_interface_contact_loops = 0
|
||||
support_material_interface_layers = 2
|
||||
support_material_interface_spacing = 0.2
|
||||
support_material_interface_speed = 100%
|
||||
support_material_pattern = rectilinear
|
||||
support_material_spacing = 2
|
||||
support_material_speed = 40
|
||||
support_material_synchronize_layers = 0
|
||||
support_material_threshold = 45
|
||||
support_material_with_sheath = 0
|
||||
support_material_xy_spacing = 60%
|
||||
thin_walls = 0
|
||||
top_infill_extrusion_width = 0.45
|
||||
top_solid_infill_speed = 40
|
||||
travel_speed = 100
|
||||
wipe_tower = 0
|
||||
wipe_tower_bridging = 10
|
||||
wipe_tower_rotation_angle = 0
|
||||
wipe_tower_width = 60
|
||||
wipe_tower_x = 170
|
||||
wipe_tower_y = 140
|
||||
xy_size_compensation = 0
|
||||
|
||||
[print:*0.12mm*]
|
||||
inherits = *common*
|
||||
perimeter_speed = 40
|
||||
external_perimeter_speed = 25
|
||||
infill_speed = 50
|
||||
solid_infill_speed = 40
|
||||
layer_height = 0.12
|
||||
perimeters = 3
|
||||
top_infill_extrusion_width = 0.4
|
||||
bottom_solid_layers = 6
|
||||
top_solid_layers = 7
|
||||
|
||||
[print:*0.20mm*]
|
||||
inherits = *common*
|
||||
perimeter_speed = 40
|
||||
external_perimeter_speed = 25
|
||||
infill_speed = 50
|
||||
solid_infill_speed = 40
|
||||
layer_height = 0.20
|
||||
top_infill_extrusion_width = 0.4
|
||||
bottom_solid_layers = 4
|
||||
top_solid_layers = 5
|
||||
|
||||
[print:*0.24mm*]
|
||||
inherits = *common*
|
||||
perimeter_speed = 40
|
||||
external_perimeter_speed = 25
|
||||
infill_speed = 50
|
||||
solid_infill_speed = 40
|
||||
layer_height = 0.24
|
||||
top_infill_extrusion_width = 0.45
|
||||
bottom_solid_layers = 3
|
||||
top_solid_layers = 4
|
||||
|
||||
[print:0.12mm DETAIL ENDER3]
|
||||
inherits = *0.12mm*
|
||||
alias=0.12mm DETAIL
|
||||
travel_speed = 150
|
||||
infill_speed = 50
|
||||
solid_infill_speed = 40
|
||||
top_solid_infill_speed = 30
|
||||
support_material_extrusion_width = 0.38
|
||||
compatible_printers_condition = printer_model=="ENDER3" and nozzle_diameter[0]==0.4
|
||||
|
||||
[print:0.20mm NORMAL ENDER3]
|
||||
inherits = *0.20mm*
|
||||
alias=0.20mm NORMAL
|
||||
travel_speed = 150
|
||||
infill_speed = 50
|
||||
solid_infill_speed = 40
|
||||
top_solid_infill_speed = 30
|
||||
support_material_extrusion_width = 0.38
|
||||
compatible_printers_condition = printer_model=="ENDER3" and nozzle_diameter[0]==0.4
|
||||
|
||||
[print:0.24mm DRAFT ENDER3]
|
||||
inherits = *0.24mm*
|
||||
alias=0.24mm DRAFT
|
||||
travel_speed = 150
|
||||
infill_speed = 50
|
||||
solid_infill_speed = 40
|
||||
top_solid_infill_speed = 30
|
||||
support_material_extrusion_width = 0.38
|
||||
compatible_printers_condition = printer_model=="ENDER3" and nozzle_diameter[0]==0.4
|
||||
|
||||
# Common filament preset
|
||||
[filament:*common*]
|
||||
cooling = 0
|
||||
compatible_printers =
|
||||
compatible_printers_condition =
|
||||
extrusion_multiplier = 1
|
||||
filament_cost = 0
|
||||
filament_density = 0
|
||||
filament_diameter = 1.75
|
||||
filament_notes = ""
|
||||
filament_settings_id = ""
|
||||
filament_soluble = 0
|
||||
min_print_speed = 15
|
||||
slowdown_below_layer_time = 20
|
||||
|
||||
[filament:*PLA*]
|
||||
inherits = *common*
|
||||
bed_temperature = 40
|
||||
fan_below_layer_time = 100
|
||||
filament_colour = #FF3232
|
||||
filament_max_volumetric_speed = 15
|
||||
filament_type = PLA
|
||||
filament_density = 1.24
|
||||
filament_cost = 20
|
||||
first_layer_bed_temperature = 40
|
||||
first_layer_temperature = 215
|
||||
fan_always_on = 1
|
||||
cooling = 1
|
||||
max_fan_speed = 100
|
||||
min_fan_speed = 100
|
||||
bridge_fan_speed = 100
|
||||
disable_fan_first_layers = 1
|
||||
temperature = 210
|
||||
|
||||
[filament:*PET*]
|
||||
inherits = *common*
|
||||
bed_temperature = 70
|
||||
cooling = 1
|
||||
disable_fan_first_layers = 3
|
||||
fan_below_layer_time = 20
|
||||
filament_colour = #FF8000
|
||||
filament_max_volumetric_speed = 8
|
||||
filament_type = PETG
|
||||
filament_density = 1.27
|
||||
filament_cost = 30
|
||||
first_layer_bed_temperature =70
|
||||
first_layer_temperature = 240
|
||||
fan_always_on = 1
|
||||
max_fan_speed = 50
|
||||
min_fan_speed = 20
|
||||
bridge_fan_speed = 100
|
||||
temperature = 240
|
||||
|
||||
[filament:*ABS*]
|
||||
inherits = *common*
|
||||
bed_temperature = 100
|
||||
cooling = 0
|
||||
disable_fan_first_layers = 3
|
||||
fan_below_layer_time = 20
|
||||
filament_colour = #3A80CA
|
||||
filament_max_volumetric_speed = 11
|
||||
filament_type = PLA
|
||||
filament_density = 1.04
|
||||
filament_cost = 20
|
||||
first_layer_bed_temperature = 100
|
||||
first_layer_temperature = 245
|
||||
fan_always_on = 0
|
||||
max_fan_speed = 0
|
||||
min_fan_speed = 0
|
||||
bridge_fan_speed = 30
|
||||
top_fan_speed = 0
|
||||
temperature = 245
|
||||
|
||||
[filament:Generic PLA ENDER3]
|
||||
inherits = *PLA*
|
||||
alias=Generic PLA
|
||||
|
||||
[filament:Generic PET ENDER3]
|
||||
inherits = *PET*
|
||||
alias=Generic PET
|
||||
|
||||
[filament:Generic ABS ENDER3]
|
||||
inherits = *ABS*
|
||||
alias=Generic ABS
|
||||
first_layer_bed_temperature = 90
|
||||
bed_temperature = 90
|
||||
|
||||
[filament:Creality PLA ENDER3]
|
||||
inherits = *PLA*
|
||||
alias=Creality PLA
|
||||
temperature = 205
|
||||
bed_temperature = 40
|
||||
first_layer_temperature = 210
|
||||
first_layer_bed_temperature =40
|
||||
|
||||
[filament:Creality PET ENDER3]
|
||||
inherits = *PET*
|
||||
alias=Creality PET
|
||||
temperature = 240
|
||||
bed_temperature = 70
|
||||
first_layer_temperature = 240
|
||||
first_layer_bed_temperature =70
|
||||
max_fan_speed = 40
|
||||
min_fan_speed = 20
|
||||
|
||||
[filament:Creality ABS ENDER3]
|
||||
inherits = *ABS*
|
||||
alias=Creality ABS
|
||||
temperature = 240
|
||||
bed_temperature = 90
|
||||
first_layer_temperature = 240
|
||||
first_layer_bed_temperature =90
|
||||
|
||||
[filament:Prusament PLA ENDER3]
|
||||
inherits = *PLA*
|
||||
alias=Prusament PLA
|
||||
temperature = 215
|
||||
bed_temperature = 40
|
||||
first_layer_temperature = 215
|
||||
first_layer_bed_temperature =40
|
||||
filament_cost = 24.99
|
||||
filament_density = 1.24
|
||||
|
||||
[filament:Prusament PETG ENDER3]
|
||||
inherits = *PET*
|
||||
alias=Prusament PETG
|
||||
temperature = 245
|
||||
bed_temperature = 70
|
||||
first_layer_temperature = 245
|
||||
first_layer_bed_temperature =70
|
||||
filament_cost = 24.99
|
||||
filament_density = 1.27
|
||||
|
||||
# Common printer preset
|
||||
[printer:*common*]
|
||||
printer_technology = FFF
|
||||
bed_shape = 0x0,200x0,200x200,0x200
|
||||
before_layer_gcode = ;BEFORE_LAYER_CHANGE\n;[layer_z]\n\n
|
||||
between_objects_gcode =
|
||||
deretract_speed = 0
|
||||
extruder_colour = #FFFF00
|
||||
extruder_offset = 0x0
|
||||
gcode_flavor = marlin
|
||||
silent_mode = 0
|
||||
remaining_times = 0
|
||||
machine_max_acceleration_e = 10000
|
||||
machine_max_acceleration_extruding = 2000
|
||||
machine_max_acceleration_retracting = 1500
|
||||
machine_max_acceleration_x = 3000
|
||||
machine_max_acceleration_y = 3000
|
||||
machine_max_acceleration_z = 500
|
||||
machine_max_feedrate_e = 120
|
||||
machine_max_feedrate_x = 500
|
||||
machine_max_feedrate_y = 500
|
||||
machine_max_feedrate_z = 12
|
||||
machine_max_jerk_e = 2.5
|
||||
machine_max_jerk_x = 20
|
||||
machine_max_jerk_y = 20
|
||||
machine_max_jerk_z = 0.4
|
||||
machine_min_extruding_rate = 0
|
||||
machine_min_travel_rate = 0
|
||||
layer_gcode = ;AFTER_LAYER_CHANGE\n;[layer_z]
|
||||
max_layer_height = 0.3
|
||||
min_layer_height = 0.07
|
||||
max_print_height = 200
|
||||
nozzle_diameter = 0.4
|
||||
octoprint_apikey =
|
||||
octoprint_host =
|
||||
printer_notes =
|
||||
printer_settings_id =
|
||||
retract_before_travel = 1
|
||||
retract_before_wipe = 0%
|
||||
retract_layer_change = 1
|
||||
retract_length = 1
|
||||
retract_length_toolchange = 1
|
||||
retract_lift = 0
|
||||
retract_lift_above = 0
|
||||
retract_lift_below = 0
|
||||
retract_restart_extra = 0
|
||||
retract_restart_extra_toolchange = 0
|
||||
retract_speed = 35
|
||||
serial_port =
|
||||
serial_speed = 250000
|
||||
single_extruder_multi_material = 0
|
||||
start_gcode = G90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 ; home all\nG92 E0.0\nG1 Z0.15 F240\nG1 X60.0 E9.0 F800.0 ; intro line\nG1 X100.0 E12.5 F800 ; intro line\nG92 E0.0
|
||||
end_gcode = M104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n{if layer_z < max_print_height}G1 Z{z_offset+min(layer_z+30, max_print_height)}{endif} ; Move print head up\nG1 X0 F3000 ; home X axis\nM84 ; disable motors
|
||||
toolchange_gcode =
|
||||
use_firmware_retraction = 0
|
||||
use_relative_e_distances = 1
|
||||
use_volumetric_e = 0
|
||||
variable_layer_height = 1
|
||||
wipe = 1
|
||||
z_offset = 0
|
||||
printer_model =
|
||||
default_print_profile =
|
||||
default_filament_profile =
|
||||
|
||||
[printer:Creality ENDER-3]
|
||||
inherits = *common*
|
||||
printer_model = ENDER3
|
||||
printer_variant = 0.4
|
||||
max_layer_height = 0.25
|
||||
min_layer_height = 0.1
|
||||
bed_shape = 0x0,220x0,220x220,0x220
|
||||
max_print_height = 250
|
||||
machine_max_acceleration_e = 5000
|
||||
machine_max_acceleration_extruding = 500
|
||||
machine_max_acceleration_retracting = 1000
|
||||
machine_max_acceleration_x = 500
|
||||
machine_max_acceleration_y = 500
|
||||
machine_max_acceleration_z = 100
|
||||
machine_max_feedrate_e = 60
|
||||
machine_max_feedrate_x = 500
|
||||
machine_max_feedrate_y = 500
|
||||
machine_max_feedrate_z = 10
|
||||
machine_max_jerk_e = 5
|
||||
machine_max_jerk_x = 8
|
||||
machine_max_jerk_y = 8
|
||||
machine_max_jerk_z = 0.4
|
||||
machine_min_extruding_rate = 0
|
||||
machine_min_travel_rate = 0
|
||||
printer_notes =
|
||||
nozzle_diameter = 0.4
|
||||
retract_before_travel = 2
|
||||
retract_length = 5
|
||||
retract_speed = 60
|
||||
deretract_speed = 40
|
||||
retract_before_wipe = 70%
|
||||
default_print_profile = 0.20mm NORMAL
|
||||
default_filament_profile = Creality PLA
|
||||
start_gcode = G90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 ; home all\nG1 Z2 F240\nG1 X2 Y10 F3000\nG1 Z0.28 F240\nG92 E0.0\nG1 Y190 E15.0 F1500.0 ; intro line\nG1 X2.3 F5000\nG1 Y10 E30 F1200.0 ; intro line\nG92 E0.0
|
||||
end_gcode = M104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n{if layer_z < max_print_height}G1 Z{z_offset+min(layer_z+10, max_print_height)} F600{endif} ; Move print head up\nG1 X0 Y200 F3000 ; present print\nM84 X Y E ; disable motors
|
File diff suppressed because it is too large
Load diff
|
@ -1205,7 +1205,7 @@ ExPolygons variable_offset_inner_ex(const ExPolygon &expoly, const std::vector<s
|
|||
{
|
||||
#ifndef NDEBUG
|
||||
// Verify that the deltas are all non positive.
|
||||
for (const std::vector<float>& ds : deltas)
|
||||
for (const std::vector<float>& ds : deltas)
|
||||
for (float delta : ds)
|
||||
assert(delta <= 0.);
|
||||
assert(expoly.holes.size() + 1 == deltas.size());
|
||||
|
|
|
@ -60,9 +60,9 @@ std::vector<float> contour_distance(const EdgeGrid::Grid &grid, const size_t idx
|
|||
for (size_t axis = 0; axis < 2; ++ axis) {
|
||||
double dx = std::abs(dir(axis));
|
||||
if (dx >= EPSILON) {
|
||||
double tedge = (dir(axis) > 0) ? (double(bbox.max(axis)) - EPSILON - this->pt(axis)) : (this->pt(axis) - double(bbox.min(axis)) - EPSILON);
|
||||
double tedge = (dir(axis) > 0) ? (double(bbox.max(axis)) - SCALED_EPSILON - this->pt(axis)) : (this->pt(axis) - double(bbox.min(axis)) - SCALED_EPSILON);
|
||||
if (tedge < dx)
|
||||
t = tedge / dx;
|
||||
t = std::min(t, tedge / dx);
|
||||
}
|
||||
}
|
||||
this->dir = dir;
|
||||
|
@ -70,6 +70,7 @@ std::vector<float> contour_distance(const EdgeGrid::Grid &grid, const size_t idx
|
|||
dir *= t;
|
||||
this->pt_end = (this->pt + dir).cast<coord_t>();
|
||||
this->t_min = 1.;
|
||||
assert(this->grid.bbox().contains(this->pt_start) && this->grid.bbox().contains(this->pt_end));
|
||||
}
|
||||
|
||||
bool operator()(coord_t iy, coord_t ix) {
|
||||
|
@ -361,7 +362,7 @@ static inline void smooth_compensation_banded(const Points &contour, float band,
|
|||
}
|
||||
|
||||
ExPolygon elephant_foot_compensation(const ExPolygon &input_expoly, const Flow &external_perimeter_flow, const double compensation)
|
||||
{
|
||||
{
|
||||
// The contour shall be wide enough to apply the external perimeter plus compensation on both sides.
|
||||
double min_contour_width = double(external_perimeter_flow.scaled_width() + external_perimeter_flow.scaled_spacing());
|
||||
double scaled_compensation = scale_(compensation);
|
||||
|
@ -369,39 +370,59 @@ ExPolygon elephant_foot_compensation(const ExPolygon &input_expoly, const Flow &
|
|||
// Make the search radius a bit larger for the averaging in contour_distance over a fan of rays to work.
|
||||
double search_radius = min_contour_width_compensated + min_contour_width * 0.5;
|
||||
|
||||
EdgeGrid::Grid grid;
|
||||
ExPolygon simplified = input_expoly.simplify(SCALED_EPSILON).front();
|
||||
BoundingBox bbox = get_extents(simplified.contour);
|
||||
bbox.offset(SCALED_EPSILON);
|
||||
grid.set_bbox(bbox);
|
||||
grid.create(simplified, coord_t(0.7 * search_radius));
|
||||
std::vector<std::vector<float>> deltas;
|
||||
deltas.reserve(simplified.holes.size() + 1);
|
||||
ExPolygon resampled(simplified);
|
||||
double resample_interval = scale_(0.5);
|
||||
for (size_t idx_contour = 0; idx_contour <= simplified.holes.size(); ++ idx_contour) {
|
||||
Polygon &poly = (idx_contour == 0) ? resampled.contour : resampled.holes[idx_contour - 1];
|
||||
std::vector<ResampledPoint> resampled_point_parameters;
|
||||
poly.points = resample_polygon(poly.points, resample_interval, resampled_point_parameters);
|
||||
std::vector<float> dists = contour_distance(grid, idx_contour, poly.points, resampled_point_parameters, search_radius);
|
||||
for (float &d : dists) {
|
||||
// printf("Point %d, Distance: %lf\n", int(&d - dists.data()), unscale<double>(d));
|
||||
// Convert contour width to available compensation distance.
|
||||
if (d < min_contour_width)
|
||||
d = 0.f;
|
||||
else if (d > min_contour_width_compensated)
|
||||
d = - float(scaled_compensation);
|
||||
else
|
||||
d = - (d - float(min_contour_width)) / 2.f;
|
||||
assert(d >= - float(scaled_compensation) && d <= 0.f);
|
||||
BoundingBox bbox = get_extents(input_expoly.contour);
|
||||
Point bbox_size = bbox.size();
|
||||
ExPolygon out;
|
||||
if (bbox_size.x() < min_contour_width_compensated + SCALED_EPSILON ||
|
||||
bbox_size.y() < min_contour_width_compensated + SCALED_EPSILON ||
|
||||
input_expoly.area() < min_contour_width_compensated * min_contour_width_compensated * 5.)
|
||||
{
|
||||
// The contour is tiny. Don't correct it.
|
||||
out = input_expoly;
|
||||
}
|
||||
else
|
||||
{
|
||||
EdgeGrid::Grid grid;
|
||||
ExPolygon simplified = input_expoly.simplify(SCALED_EPSILON).front();
|
||||
BoundingBox bbox = get_extents(simplified.contour);
|
||||
bbox.offset(SCALED_EPSILON);
|
||||
grid.set_bbox(bbox);
|
||||
grid.create(simplified, coord_t(0.7 * search_radius));
|
||||
std::vector<std::vector<float>> deltas;
|
||||
deltas.reserve(simplified.holes.size() + 1);
|
||||
ExPolygon resampled(simplified);
|
||||
double resample_interval = scale_(0.5);
|
||||
for (size_t idx_contour = 0; idx_contour <= simplified.holes.size(); ++ idx_contour) {
|
||||
Polygon &poly = (idx_contour == 0) ? resampled.contour : resampled.holes[idx_contour - 1];
|
||||
std::vector<ResampledPoint> resampled_point_parameters;
|
||||
poly.points = resample_polygon(poly.points, resample_interval, resampled_point_parameters);
|
||||
std::vector<float> dists = contour_distance(grid, idx_contour, poly.points, resampled_point_parameters, search_radius);
|
||||
for (float &d : dists) {
|
||||
// printf("Point %d, Distance: %lf\n", int(&d - dists.data()), unscale<double>(d));
|
||||
// Convert contour width to available compensation distance.
|
||||
if (d < min_contour_width)
|
||||
d = 0.f;
|
||||
else if (d > min_contour_width_compensated)
|
||||
d = - float(scaled_compensation);
|
||||
else
|
||||
d = - (d - float(min_contour_width)) / 2.f;
|
||||
assert(d >= - float(scaled_compensation) && d <= 0.f);
|
||||
}
|
||||
// smooth_compensation(dists, 0.4f, 10);
|
||||
smooth_compensation_banded(poly.points, float(0.8 * resample_interval), dists, 0.3f, 3);
|
||||
deltas.emplace_back(dists);
|
||||
}
|
||||
// smooth_compensation(dists, 0.4f, 10);
|
||||
smooth_compensation_banded(poly.points, float(0.8 * resample_interval), dists, 0.3f, 3);
|
||||
deltas.emplace_back(dists);
|
||||
|
||||
ExPolygons out_vec = variable_offset_inner_ex(resampled, deltas, 2.);
|
||||
assert(out_vec.size() == 1);
|
||||
if (out_vec.size() == 1)
|
||||
out = std::move(out_vec.front());
|
||||
else
|
||||
// Something went wrong, don't compensate.
|
||||
out = input_expoly;
|
||||
}
|
||||
|
||||
ExPolygons out = variable_offset_inner_ex(resampled, deltas, 2.);
|
||||
return out.front();
|
||||
return out;
|
||||
}
|
||||
|
||||
ExPolygons elephant_foot_compensation(const ExPolygons &input, const Flow &external_perimeter_flow, const double compensation)
|
||||
|
|
|
@ -267,6 +267,15 @@ public:
|
|||
|
||||
//static inline std::string role_to_string(ExtrusionLoopRole role);
|
||||
|
||||
#ifndef NDEBUG
|
||||
bool validate() const {
|
||||
assert(this->first_point() == this->paths.back().polyline.points.back());
|
||||
for (size_t i = 1; i < paths.size(); ++ i)
|
||||
assert(this->paths[i - 1].polyline.points.back() == this->paths[i].polyline.points.front());
|
||||
return true;
|
||||
}
|
||||
#endif /* NDEBUG */
|
||||
|
||||
private:
|
||||
ExtrusionLoopRole m_loop_role;
|
||||
};
|
||||
|
|
|
@ -534,7 +534,8 @@ struct ContourPointData {
|
|||
// Verify whether the contour from point idx_start to point idx_end could be taken (whether all segments along the contour were not yet extruded).
|
||||
static bool could_take(const std::vector<ContourPointData> &contour_data, size_t idx_start, size_t idx_end)
|
||||
{
|
||||
for (size_t i = idx_start; i < idx_end; ) {
|
||||
assert(idx_start != idx_end);
|
||||
for (size_t i = idx_start; i != idx_end; ) {
|
||||
if (contour_data[i].segment_consumed || contour_data[i].point_consumed)
|
||||
return false;
|
||||
if (++ i == contour_data.size())
|
||||
|
@ -899,63 +900,86 @@ void Fill::connect_infill(Polylines &&infill_ordered, const ExPolygon &boundary_
|
|||
|
||||
// Mark the points and segments of split boundary as consumed if they are very close to some of the infill line.
|
||||
{
|
||||
const double clip_distance = scale_(this->spacing);
|
||||
//const double clip_distance = scale_(this->spacing);
|
||||
const double clip_distance = 3. * scale_(this->spacing);
|
||||
const double distance_colliding = scale_(this->spacing);
|
||||
mark_boundary_segments_touching_infill(boundary, boundary_data, bbox, infill_ordered, clip_distance, distance_colliding);
|
||||
}
|
||||
|
||||
// Chain infill_ordered.
|
||||
//FIXME run the following loop through a heap sorted by the shortest perimeter edge that could be taken.
|
||||
//length between two lines
|
||||
// Connection from end of one infill line to the start of another infill line.
|
||||
//const float length_max = scale_(this->spacing);
|
||||
const float length_max = scale_((2. / params.density) * this->spacing);
|
||||
size_t idx_chain_last = 0;
|
||||
// const float length_max = scale_((2. / params.density) * this->spacing);
|
||||
const float length_max = scale_((1000. / params.density) * this->spacing);
|
||||
std::vector<size_t> merged_with(infill_ordered.size());
|
||||
for (size_t i = 0; i < merged_with.size(); ++ i)
|
||||
merged_with[i] = i;
|
||||
struct ConnectionCost {
|
||||
ConnectionCost(size_t idx_first, double cost, bool reversed) : idx_first(idx_first), cost(cost), reversed(reversed) {}
|
||||
size_t idx_first;
|
||||
double cost;
|
||||
bool reversed;
|
||||
};
|
||||
std::vector<ConnectionCost> connections_sorted;
|
||||
connections_sorted.reserve(infill_ordered.size() * 2 - 2);
|
||||
for (size_t idx_chain = 1; idx_chain < infill_ordered.size(); ++ idx_chain) {
|
||||
Polyline &pl1 = infill_ordered[idx_chain_last];
|
||||
Polyline &pl2 = infill_ordered[idx_chain];
|
||||
const Polyline &pl1 = infill_ordered[idx_chain - 1];
|
||||
const Polyline &pl2 = infill_ordered[idx_chain];
|
||||
const std::pair<size_t, size_t> *cp1 = &map_infill_end_point_to_boundary[(idx_chain - 1) * 2 + 1];
|
||||
const std::pair<size_t, size_t> *cp2 = &map_infill_end_point_to_boundary[idx_chain * 2];
|
||||
const Points &contour = boundary[cp1->first];
|
||||
std::vector<ContourPointData> &contour_data = boundary_data[cp1->first];
|
||||
bool valid = false;
|
||||
bool reversed = false;
|
||||
const std::vector<ContourPointData> &contour_data = boundary_data[cp1->first];
|
||||
if (cp1->first == cp2->first) {
|
||||
// End points on the same contour. Try to connect them.
|
||||
float param_lo = (cp1->second == 0) ? 0.f : contour_data[cp1->second].param;
|
||||
float param_hi = (cp2->second == 0) ? 0.f : contour_data[cp2->second].param;
|
||||
float param_lo = (cp1->second == 0) ? 0.f : contour_data[cp1->second].param;
|
||||
float param_hi = (cp2->second == 0) ? 0.f : contour_data[cp2->second].param;
|
||||
float param_end = contour_data.front().param;
|
||||
bool reversed = false;
|
||||
if (param_lo > param_hi) {
|
||||
std::swap(param_lo, param_hi);
|
||||
std::swap(cp1, cp2);
|
||||
reversed = true;
|
||||
}
|
||||
assert(param_lo >= 0.f && param_lo <= param_end);
|
||||
assert(param_hi >= 0.f && param_hi <= param_end);
|
||||
float dist1 = param_hi - param_lo;
|
||||
float dist2 = param_lo + param_end - param_hi;
|
||||
if (dist1 > dist2) {
|
||||
std::swap(dist1, dist2);
|
||||
std::swap(cp1, cp2);
|
||||
reversed = ! reversed;
|
||||
}
|
||||
if (dist1 < length_max) {
|
||||
// Try to connect the shorter path.
|
||||
valid = could_take(contour_data, cp1->second, cp2->second);
|
||||
// Try to connect the longer path.
|
||||
if (! valid && dist2 < length_max) {
|
||||
std::swap(cp1, cp2);
|
||||
reversed = ! reversed;
|
||||
valid = could_take(contour_data, cp1->second, cp2->second);
|
||||
}
|
||||
}
|
||||
double len = param_hi - param_lo;
|
||||
if (len < length_max)
|
||||
connections_sorted.emplace_back(idx_chain - 1, len, reversed);
|
||||
len = param_lo + param_end - param_hi;
|
||||
if (len < length_max)
|
||||
connections_sorted.emplace_back(idx_chain - 1, len, ! reversed);
|
||||
}
|
||||
if (valid)
|
||||
take(pl1, std::move(pl2), contour, contour_data, cp1->second, cp2->second, reversed);
|
||||
else if (++ idx_chain_last < idx_chain)
|
||||
infill_ordered[idx_chain_last] = std::move(pl2);
|
||||
}
|
||||
infill_ordered.erase(infill_ordered.begin() + idx_chain_last + 1, infill_ordered.end());
|
||||
append(polylines_out, std::move(infill_ordered));
|
||||
std::sort(connections_sorted.begin(), connections_sorted.end(), [](const ConnectionCost& l, const ConnectionCost& r) { return l.cost < r.cost; });
|
||||
|
||||
size_t idx_chain_last = 0;
|
||||
for (ConnectionCost &connection_cost : connections_sorted) {
|
||||
const std::pair<size_t, size_t> *cp1 = &map_infill_end_point_to_boundary[connection_cost.idx_first * 2 + 1];
|
||||
const std::pair<size_t, size_t> *cp2 = &map_infill_end_point_to_boundary[(connection_cost.idx_first + 1) * 2];
|
||||
assert(cp1->first == cp2->first);
|
||||
std::vector<ContourPointData> &contour_data = boundary_data[cp1->first];
|
||||
if (connection_cost.reversed)
|
||||
std::swap(cp1, cp2);
|
||||
if (could_take(contour_data, cp1->second, cp2->second)) {
|
||||
// Indices of the polygons to be connected.
|
||||
size_t idx_first = connection_cost.idx_first;
|
||||
size_t idx_second = idx_first + 1;
|
||||
for (size_t last = idx_first;;) {
|
||||
size_t lower = merged_with[last];
|
||||
if (lower == last) {
|
||||
merged_with[idx_first] = lower;
|
||||
idx_first = lower;
|
||||
break;
|
||||
}
|
||||
last = lower;
|
||||
}
|
||||
// Connect the two polygons using the boundary contour.
|
||||
take(infill_ordered[idx_first], std::move(infill_ordered[idx_second]), boundary[cp1->first], contour_data, cp1->second, cp2->second, connection_cost.reversed);
|
||||
// Mark the second polygon as merged with the first one.
|
||||
merged_with[idx_second] = merged_with[idx_first];
|
||||
}
|
||||
}
|
||||
polylines_out.reserve(polylines_out.size() + std::count_if(infill_ordered.begin(), infill_ordered.end(), [](const Polyline &pl) { return ! pl.empty(); }));
|
||||
for (Polyline &pl : infill_ordered)
|
||||
if (! pl.empty())
|
||||
polylines_out.emplace_back(std::move(pl));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -169,7 +169,7 @@ void FillGyroid::_fill_surface_single(
|
|||
bb.merge(_align_to_grid(bb.min, Point(2*M_PI*distance, 2*M_PI*distance)));
|
||||
|
||||
// generate pattern
|
||||
Polylines polylines_square = make_gyroid_waves(
|
||||
Polylines polylines = make_gyroid_waves(
|
||||
scale_(this->z),
|
||||
density_adjusted,
|
||||
this->spacing,
|
||||
|
@ -177,22 +177,25 @@ void FillGyroid::_fill_surface_single(
|
|||
ceil(bb.size()(1) / distance) + 1.);
|
||||
|
||||
// shift the polyline to the grid origin
|
||||
for (Polyline &pl : polylines_square)
|
||||
for (Polyline &pl : polylines)
|
||||
pl.translate(bb.min);
|
||||
|
||||
Polylines polylines_chained = chain_polylines(intersection_pl(polylines_square, to_polygons(expolygon)));
|
||||
polylines = intersection_pl(polylines, to_polygons(expolygon));
|
||||
|
||||
size_t polylines_out_first_idx = polylines_out.size();
|
||||
if (! polylines_chained.empty()) {
|
||||
// connect lines
|
||||
if (! polylines.empty())
|
||||
// remove too small bits (larger than longer)
|
||||
polylines.erase(
|
||||
std::remove_if(polylines.begin(), polylines.end(), [this](const Polyline &pl) { return pl.length() < scale_(this->spacing * 3); }),
|
||||
polylines.end());
|
||||
|
||||
if (! polylines.empty()) {
|
||||
polylines = chain_polylines(polylines);
|
||||
// connect lines
|
||||
size_t polylines_out_first_idx = polylines_out.size();
|
||||
if (params.dont_connect)
|
||||
append(polylines_out, std::move(polylines_chained));
|
||||
append(polylines_out, std::move(polylines));
|
||||
else
|
||||
this->connect_infill(std::move(polylines_chained), expolygon, polylines_out, params);
|
||||
// remove too small bits (larger than longer)
|
||||
polylines_out.erase(
|
||||
std::remove_if(polylines_out.begin() + polylines_out_first_idx, polylines_out.end(), [this](const Polyline &pl){ return pl.length() < scale_(this->spacing * 3); }),
|
||||
polylines_out.end());
|
||||
this->connect_infill(std::move(polylines), expolygon, polylines_out, params);
|
||||
// new paths must be rotated back
|
||||
if (abs(infill_angle) >= EPSILON) {
|
||||
for (auto it = polylines_out.begin() + polylines_out_first_idx; it != polylines_out.end(); ++ it)
|
||||
|
|
|
@ -285,7 +285,7 @@ static inline Point wipe_tower_point_to_object_point(GCode &gcodegen, const Vec2
|
|||
return Point(scale_(wipe_tower_pt.x() - gcodegen.origin()(0)), scale_(wipe_tower_pt.y() - gcodegen.origin()(1)));
|
||||
}
|
||||
|
||||
std::string WipeTowerIntegration::append_tcr(GCode &gcodegen, const WipeTower::ToolChangeResult &tcr, int new_extruder_id) const
|
||||
std::string WipeTowerIntegration::append_tcr(GCode &gcodegen, const WipeTower::ToolChangeResult &tcr, int new_extruder_id, double z) const
|
||||
{
|
||||
if (new_extruder_id != -1 && new_extruder_id != tcr.new_tool)
|
||||
throw std::invalid_argument("Error: WipeTowerIntegration::append_tcr was asked to do a toolchange it didn't expect.");
|
||||
|
@ -321,6 +321,15 @@ std::string WipeTowerIntegration::append_tcr(GCode &gcodegen, const WipeTower::T
|
|||
gcode += gcodegen.unretract();
|
||||
}
|
||||
|
||||
double current_z = gcodegen.writer().get_position().z();
|
||||
if (z == -1.) // in case no specific z was provided, print at current_z pos
|
||||
z = current_z;
|
||||
if (! is_approx(z, current_z)) {
|
||||
gcode += gcodegen.writer().retract();
|
||||
gcode += gcodegen.writer().travel_to_z(z, "Travel down to the last wipe tower layer.");
|
||||
gcode += gcodegen.writer().unretract();
|
||||
}
|
||||
|
||||
|
||||
// Process the end filament gcode.
|
||||
std::string end_filament_gcode_str;
|
||||
|
@ -387,16 +396,23 @@ std::string WipeTowerIntegration::append_tcr(GCode &gcodegen, const WipeTower::T
|
|||
// A phony move to the end position at the wipe tower.
|
||||
gcodegen.writer().travel_to_xy(end_pos.cast<double>());
|
||||
gcodegen.set_last_pos(wipe_tower_point_to_object_point(gcodegen, end_pos));
|
||||
if (! is_approx(z, current_z)) {
|
||||
gcode += gcodegen.writer().retract();
|
||||
gcode += gcodegen.writer().travel_to_z(current_z, "Travel back up to the topmost object layer.");
|
||||
gcode += gcodegen.writer().unretract();
|
||||
}
|
||||
|
||||
// Prepare a future wipe.
|
||||
gcodegen.m_wipe.path.points.clear();
|
||||
if (new_extruder_id >= 0) {
|
||||
// Start the wipe at the current position.
|
||||
gcodegen.m_wipe.path.points.emplace_back(wipe_tower_point_to_object_point(gcodegen, end_pos));
|
||||
// Wipe end point: Wipe direction away from the closer tower edge to the further tower edge.
|
||||
gcodegen.m_wipe.path.points.emplace_back(wipe_tower_point_to_object_point(gcodegen,
|
||||
Vec2f((std::abs(m_left - end_pos.x()) < std::abs(m_right - end_pos.x())) ? m_right : m_left,
|
||||
end_pos.y())));
|
||||
else {
|
||||
// Prepare a future wipe.
|
||||
gcodegen.m_wipe.path.points.clear();
|
||||
if (new_extruder_id >= 0) {
|
||||
// Start the wipe at the current position.
|
||||
gcodegen.m_wipe.path.points.emplace_back(wipe_tower_point_to_object_point(gcodegen, end_pos));
|
||||
// Wipe end point: Wipe direction away from the closer tower edge to the further tower edge.
|
||||
gcodegen.m_wipe.path.points.emplace_back(wipe_tower_point_to_object_point(gcodegen,
|
||||
Vec2f((std::abs(m_left - end_pos.x()) < std::abs(m_right - end_pos.x())) ? m_right : m_left,
|
||||
end_pos.y())));
|
||||
}
|
||||
}
|
||||
|
||||
// Let the planner know we are traveling between objects.
|
||||
|
@ -522,7 +538,23 @@ std::string WipeTowerIntegration::tool_change(GCode &gcodegen, int extruder_id,
|
|||
if (m_layer_idx < (int)m_tool_changes.size()) {
|
||||
if (! (size_t(m_tool_change_idx) < m_tool_changes[m_layer_idx].size()))
|
||||
throw std::runtime_error("Wipe tower generation failed, possibly due to empty first layer.");
|
||||
gcode += append_tcr(gcodegen, m_tool_changes[m_layer_idx][m_tool_change_idx++], extruder_id);
|
||||
|
||||
|
||||
// Calculate where the wipe tower layer will be printed. -1 means that print z will not change,
|
||||
// resulting in a wipe tower with sparse layers.
|
||||
double wipe_tower_z = -1;
|
||||
bool ignore_sparse = false;
|
||||
if (gcodegen.config().wipe_tower_no_sparse_layers.value) {
|
||||
wipe_tower_z = m_last_wipe_tower_print_z;
|
||||
ignore_sparse = (m_brim_done && m_tool_changes[m_layer_idx].size() == 1 && m_tool_changes[m_layer_idx].front().initial_tool == m_tool_changes[m_layer_idx].front().new_tool);
|
||||
if (m_tool_change_idx == 0 && ! ignore_sparse)
|
||||
wipe_tower_z = m_last_wipe_tower_print_z + m_tool_changes[m_layer_idx].front().layer_height;
|
||||
}
|
||||
|
||||
if (! ignore_sparse) {
|
||||
gcode += append_tcr(gcodegen, m_tool_changes[m_layer_idx][m_tool_change_idx++], extruder_id, wipe_tower_z);
|
||||
m_last_wipe_tower_print_z = wipe_tower_z;
|
||||
}
|
||||
}
|
||||
m_brim_done = true;
|
||||
}
|
||||
|
|
|
@ -113,7 +113,7 @@ public:
|
|||
|
||||
private:
|
||||
WipeTowerIntegration& operator=(const WipeTowerIntegration&);
|
||||
std::string append_tcr(GCode &gcodegen, const WipeTower::ToolChangeResult &tcr, int new_extruder_id) const;
|
||||
std::string append_tcr(GCode &gcodegen, const WipeTower::ToolChangeResult &tcr, int new_extruder_id, double z = -1.) const;
|
||||
|
||||
// Postprocesses gcode: rotates and moves G1 extrusions and returns result
|
||||
std::string post_process_wipe_tower_moves(const WipeTower::ToolChangeResult& tcr, const Vec2f& translation, float angle) const;
|
||||
|
@ -134,6 +134,7 @@ private:
|
|||
int m_tool_change_idx;
|
||||
bool m_brim_done;
|
||||
bool i_have_brim = false;
|
||||
double m_last_wipe_tower_print_z = 0.f;
|
||||
};
|
||||
|
||||
class GCode {
|
||||
|
|
|
@ -474,6 +474,7 @@ WipeTower::WipeTower(const PrintConfig& config, const std::vector<std::vector<fl
|
|||
m_z_pos(0.f),
|
||||
m_is_first_layer(false),
|
||||
m_bridging(float(config.wipe_tower_bridging)),
|
||||
m_no_sparse_layers(config.wipe_tower_no_sparse_layers),
|
||||
m_gcode_flavor(config.gcode_flavor),
|
||||
m_current_tool(initial_tool),
|
||||
wipe_volumes(wiping_matrix)
|
||||
|
@ -1145,9 +1146,10 @@ WipeTower::ToolChangeResult WipeTower::finish_layer()
|
|||
writer.set_initial_position((m_left_to_right ? fill_box.ru : fill_box.lu), // so there is never a diagonal travel
|
||||
m_wipe_tower_width, m_wipe_tower_depth, m_internal_rotation);
|
||||
|
||||
bool toolchanges_on_layer = m_layer_info->toolchanges_depth() > WT_EPSILON;
|
||||
box_coordinates box = fill_box;
|
||||
for (int i=0;i<2;++i) {
|
||||
if (m_layer_info->toolchanges_depth() < WT_EPSILON) { // there were no toolchanges on this layer
|
||||
if (! toolchanges_on_layer) {
|
||||
if (i==0) box.expand(m_perimeter_width);
|
||||
else box.expand(-m_perimeter_width);
|
||||
}
|
||||
|
@ -1201,9 +1203,12 @@ WipeTower::ToolChangeResult WipeTower::finish_layer()
|
|||
|
||||
m_depth_traversed = m_wipe_tower_depth-m_perimeter_width;
|
||||
|
||||
// Ask our writer about how much material was consumed:
|
||||
if (m_current_tool < m_used_filament_length.size())
|
||||
m_used_filament_length[m_current_tool] += writer.get_and_reset_used_filament_length();
|
||||
|
||||
// Ask our writer about how much material was consumed.
|
||||
// Skip this in case the layer is sparse and config option to not print sparse layers is enabled.
|
||||
if (! m_no_sparse_layers || toolchanges_on_layer)
|
||||
if (m_current_tool < m_used_filament_length.size())
|
||||
m_used_filament_length[m_current_tool] += writer.get_and_reset_used_filament_length();
|
||||
|
||||
ToolChangeResult result;
|
||||
result.priming = false;
|
||||
|
|
|
@ -220,6 +220,7 @@ private:
|
|||
float m_parking_pos_retraction = 0.f;
|
||||
float m_extra_loading_move = 0.f;
|
||||
float m_bridging = 0.f;
|
||||
bool m_no_sparse_layers = false;
|
||||
bool m_set_extruder_trimpot = false;
|
||||
bool m_adhesion = true;
|
||||
GCodeFlavor m_gcode_flavor;
|
||||
|
|
|
@ -46,9 +46,9 @@ public:
|
|||
if (indices.empty())
|
||||
clear();
|
||||
else {
|
||||
// Allocate a next highest power of 2 nodes, because the incomplete binary tree will not have the leaves filled strictly from the left.
|
||||
// Allocate enough memory for a full binary tree.
|
||||
m_nodes.assign(next_highest_power_of_2(indices.size() + 1), npos);
|
||||
build_recursive(indices, 0, 0, 0, (int)(indices.size() - 1));
|
||||
build_recursive(indices, 0, 0, 0, indices.size() - 1);
|
||||
}
|
||||
indices.clear();
|
||||
}
|
||||
|
@ -81,7 +81,7 @@ public:
|
|||
|
||||
private:
|
||||
// Build a balanced tree by splitting the input sequence by an axis aligned plane at a dimension.
|
||||
void build_recursive(std::vector<size_t> &input, size_t node, int dimension, int left, int right)
|
||||
void build_recursive(std::vector<size_t> &input, size_t node, const size_t dimension, const size_t left, const size_t right)
|
||||
{
|
||||
if (left > right)
|
||||
return;
|
||||
|
@ -94,54 +94,56 @@ private:
|
|||
return;
|
||||
}
|
||||
|
||||
// Partition the input sequence to two equal halves.
|
||||
int center = (left + right) >> 1;
|
||||
// Partition the input to left / right pieces of the same length to produce a balanced tree.
|
||||
size_t center = (left + right) / 2;
|
||||
partition_input(input, dimension, left, right, center);
|
||||
// Insert a node into the tree.
|
||||
m_nodes[node] = input[center];
|
||||
// Partition the left and right subtrees.
|
||||
size_t next_dimension = (++ dimension == NumDimensions) ? 0 : dimension;
|
||||
build_recursive(input, (node << 1) + 1, next_dimension, left, center - 1);
|
||||
build_recursive(input, (node << 1) + 2, next_dimension, center + 1, right);
|
||||
// Build up the left / right subtrees.
|
||||
size_t next_dimension = dimension;
|
||||
if (++ next_dimension == NumDimensions)
|
||||
next_dimension = 0;
|
||||
if (center > left)
|
||||
build_recursive(input, node * 2 + 1, next_dimension, left, center - 1);
|
||||
build_recursive(input, node * 2 + 2, next_dimension, center + 1, right);
|
||||
}
|
||||
|
||||
// Partition the input m_nodes <left, right> at k using QuickSelect method.
|
||||
// Partition the input m_nodes <left, right> at "k" and "dimension" using the QuickSelect method:
|
||||
// https://en.wikipedia.org/wiki/Quickselect
|
||||
void partition_input(std::vector<size_t> &input, int dimension, int left, int right, int k) const
|
||||
// Items left of the k'th item are lower than the k'th item in the "dimension",
|
||||
// items right of the k'th item are higher than the k'th item in the "dimension",
|
||||
void partition_input(std::vector<size_t> &input, const size_t dimension, size_t left, size_t right, const size_t k) const
|
||||
{
|
||||
while (left < right) {
|
||||
// Guess the k'th element.
|
||||
// Pick the pivot as a median of first, center and last value.
|
||||
// Sort first, center and last values.
|
||||
int center = (left + right) >> 1;
|
||||
auto left_value = this->coordinate(input[left], dimension);
|
||||
auto center_value = this->coordinate(input[center], dimension);
|
||||
auto right_value = this->coordinate(input[right], dimension);
|
||||
if (center_value < left_value) {
|
||||
std::swap(input[left], input[center]);
|
||||
std::swap(left_value, center_value);
|
||||
size_t center = (left + right) / 2;
|
||||
CoordType pivot;
|
||||
{
|
||||
// Bubble sort the input[left], input[center], input[right], so that a median of the three values
|
||||
// will end up in input[center].
|
||||
CoordType left_value = this->coordinate(input[left], dimension);
|
||||
CoordType center_value = this->coordinate(input[center], dimension);
|
||||
CoordType right_value = this->coordinate(input[right], dimension);
|
||||
if (left_value > center_value) {
|
||||
std::swap(input[left], input[center]);
|
||||
std::swap(left_value, center_value);
|
||||
}
|
||||
if (left_value > right_value) {
|
||||
std::swap(input[left], input[right]);
|
||||
right_value = left_value;
|
||||
}
|
||||
if (center_value > right_value) {
|
||||
std::swap(input[center], input[right]);
|
||||
center_value = right_value;
|
||||
}
|
||||
pivot = center_value;
|
||||
}
|
||||
if (right_value < left_value) {
|
||||
std::swap(input[left], input[right]);
|
||||
std::swap(left_value, right_value);
|
||||
}
|
||||
if (right_value < center_value) {
|
||||
std::swap(input[center], input[right]);
|
||||
// No need to do that, result is not used.
|
||||
// std::swap(center_value, right_value);
|
||||
}
|
||||
// Only two or three values are left and those are sorted already.
|
||||
if (left + 3 > right)
|
||||
if (right <= left + 2)
|
||||
// The <left, right> interval is already sorted.
|
||||
break;
|
||||
// left and right items are already at their correct positions.
|
||||
// input[left].point[dimension] <= input[center].point[dimension] <= input[right].point[dimension]
|
||||
// Move the pivot to the (right - 1) position.
|
||||
std::swap(input[center], input[right - 1]);
|
||||
// Pivot value.
|
||||
double pivot = this->coordinate(input[right - 1], dimension);
|
||||
size_t i = left;
|
||||
size_t j = right - 1;
|
||||
std::swap(input[center], input[j]);
|
||||
// Partition the set based on the pivot.
|
||||
int i = left;
|
||||
int j = right - 1;
|
||||
for (;;) {
|
||||
// Skip left points that are already at correct positions.
|
||||
// Search will certainly stop at position (right - 1), which stores the pivot.
|
||||
|
@ -153,7 +155,7 @@ private:
|
|||
std::swap(input[i], input[j]);
|
||||
}
|
||||
// Restore pivot to the center of the sequence.
|
||||
std::swap(input[i], input[right]);
|
||||
std::swap(input[i], input[right - 1]);
|
||||
// Which side the kth element is in?
|
||||
if (k < i)
|
||||
right = i - 1;
|
||||
|
@ -173,7 +175,7 @@ private:
|
|||
return;
|
||||
|
||||
// Left / right child node index.
|
||||
size_t left = (node << 1) + 1;
|
||||
size_t left = node * 2 + 1;
|
||||
size_t right = left + 1;
|
||||
unsigned int mask = visitor(m_nodes[node], dimension);
|
||||
if ((mask & (unsigned int)VisitorReturnMask::STOP) == 0) {
|
||||
|
|
|
@ -201,6 +201,7 @@ bool Print::invalidate_state_by_config_options(const std::vector<t_config_option
|
|||
|| opt_key == "wipe_tower"
|
||||
|| opt_key == "wipe_tower_width"
|
||||
|| opt_key == "wipe_tower_bridging"
|
||||
|| opt_key == "wipe_tower_no_sparse_layers"
|
||||
|| opt_key == "wiping_volumes_matrix"
|
||||
|| opt_key == "parking_pos_retraction"
|
||||
|| opt_key == "cooling_tube_retraction"
|
||||
|
|
|
@ -1837,6 +1837,14 @@ void PrintConfigDef::init_fff_params()
|
|||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionBool(true));
|
||||
|
||||
def = this->add("wipe_tower_no_sparse_layers", coBool);
|
||||
def->label = L("No sparse layers (EXPERIMENTAL)");
|
||||
def->tooltip = L("If enabled, the wipe tower will not be printed on layers with no toolchanges. "
|
||||
"On layers with a toolchange, extruder will travel downward to print the wipe tower. "
|
||||
"User is responsible for ensuring there is no collision with the print.");
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
|
||||
def = this->add("support_material", coBool);
|
||||
def->label = L("Generate support material");
|
||||
def->category = L("Support material");
|
||||
|
|
|
@ -669,6 +669,7 @@ public:
|
|||
ConfigOptionStrings start_filament_gcode;
|
||||
ConfigOptionBool single_extruder_multi_material;
|
||||
ConfigOptionBool single_extruder_multi_material_priming;
|
||||
ConfigOptionBool wipe_tower_no_sparse_layers;
|
||||
ConfigOptionString toolchange_gcode;
|
||||
ConfigOptionFloat travel_speed;
|
||||
ConfigOptionBool use_firmware_retraction;
|
||||
|
@ -739,6 +740,7 @@ protected:
|
|||
OPT_PTR(retract_speed);
|
||||
OPT_PTR(single_extruder_multi_material);
|
||||
OPT_PTR(single_extruder_multi_material_priming);
|
||||
OPT_PTR(wipe_tower_no_sparse_layers);
|
||||
OPT_PTR(start_gcode);
|
||||
OPT_PTR(start_filament_gcode);
|
||||
OPT_PTR(toolchange_gcode);
|
||||
|
|
|
@ -237,11 +237,19 @@ std::vector<std::pair<size_t, bool>> chain_segments_greedy_constrained_reversals
|
|||
|
||||
// Chain the end points: find (num_segments - 1) shortest links not forming bifurcations or loops.
|
||||
assert(num_segments >= 2);
|
||||
#ifndef NDEBUG
|
||||
double distance_taken_last = 0.;
|
||||
#endif /* NDEBUG */
|
||||
for (int iter = int(num_segments) - 2;; -- iter) {
|
||||
assert(validate_graph_and_queue());
|
||||
// Take the first end point, for which the link points to the currently closest valid neighbor.
|
||||
EndPoint &end_point1 = *queue.top();
|
||||
assert(end_point1.edge_out != nullptr);
|
||||
#ifndef NDEBUG
|
||||
// Each edge added shall be longer than the previous one taken.
|
||||
assert(end_point1.distance_out > distance_taken_last - SCALED_EPSILON);
|
||||
distance_taken_last = end_point1.distance_out;
|
||||
#endif /* NDEBUG */
|
||||
assert(end_point1.edge_out != nullptr);
|
||||
// No point on the queue may be connected yet.
|
||||
assert(end_point1.chain_id == 0);
|
||||
// Take the closest end point to the first end point,
|
||||
|
@ -313,6 +321,10 @@ std::vector<std::pair<size_t, bool>> chain_segments_greedy_constrained_reversals
|
|||
assert(next_idx < end_points.size());
|
||||
end_point1.edge_out = &end_points[next_idx];
|
||||
end_point1.distance_out = (end_points[next_idx].pos - end_point1.pos).squaredNorm();
|
||||
#ifndef NDEBUG
|
||||
// Each edge shall be longer than the last one removed from the queue.
|
||||
assert(end_point1.distance_out > distance_taken_last - SCALED_EPSILON);
|
||||
#endif /* NDEBUG */
|
||||
// Update position of this end point in the queue based on the distance calculated at the line above.
|
||||
queue.update(end_point1.heap_idx);
|
||||
//FIXME Remove the other end point from the KD tree.
|
||||
|
@ -460,18 +472,206 @@ std::vector<size_t> chain_points(const Points &points, Point *start_near)
|
|||
return out;
|
||||
}
|
||||
|
||||
// Flip the sequences of polylines to lower the total length of connecting lines.
|
||||
// #define DEBUG_SVG_OUTPUT
|
||||
static inline void improve_ordering_by_segment_flipping(Polylines &polylines, bool fixed_start)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
auto cost = [&polylines]() {
|
||||
double sum = 0.;
|
||||
for (size_t i = 1; i < polylines.size(); ++i)
|
||||
sum += (polylines[i].first_point() - polylines[i - 1].last_point()).cast<double>().norm();
|
||||
return sum;
|
||||
};
|
||||
double cost_initial = cost();
|
||||
|
||||
static int iRun = 0;
|
||||
++ iRun;
|
||||
BoundingBox bbox = get_extents(polylines);
|
||||
#ifdef DEBUG_SVG_OUTPUT
|
||||
{
|
||||
SVG svg(debug_out_path("improve_ordering_by_segment_flipping-initial-%d.svg", iRun).c_str(), bbox);
|
||||
svg.draw(polylines);
|
||||
for (size_t i = 1; i < polylines.size(); ++ i)
|
||||
svg.draw(Line(polylines[i - 1].last_point(), polylines[i].first_point()), "red");
|
||||
}
|
||||
#endif /* DEBUG_SVG_OUTPUT */
|
||||
#endif /* NDEBUG */
|
||||
|
||||
struct Connection {
|
||||
Connection(size_t heap_idx = std::numeric_limits<size_t>::max(), bool flipped = false) : heap_idx(heap_idx), flipped(flipped) {}
|
||||
// Position of this object on MutablePriorityHeap.
|
||||
size_t heap_idx;
|
||||
// Is segment_idx flipped?
|
||||
bool flipped;
|
||||
|
||||
double squaredNorm(const Polylines &polylines, const std::vector<Connection> &connections) const
|
||||
{ return ((this + 1)->start_point(polylines, connections) - this->end_point(polylines, connections)).squaredNorm(); }
|
||||
double norm(const Polylines &polylines, const std::vector<Connection> &connections) const
|
||||
{ return sqrt(this->squaredNorm(polylines, connections)); }
|
||||
double squaredNorm(const Polylines &polylines, const std::vector<Connection> &connections, bool try_flip1, bool try_flip2) const
|
||||
{ return ((this + 1)->start_point(polylines, connections, try_flip2) - this->end_point(polylines, connections, try_flip1)).squaredNorm(); }
|
||||
double norm(const Polylines &polylines, const std::vector<Connection> &connections, bool try_flip1, bool try_flip2) const
|
||||
{ return sqrt(this->squaredNorm(polylines, connections, try_flip1, try_flip2)); }
|
||||
Vec2d start_point(const Polylines &polylines, const std::vector<Connection> &connections, bool flip = false) const
|
||||
{ const Polyline &pl = polylines[this - connections.data()]; return ((this->flipped == flip) ? pl.points.front() : pl.points.back()).cast<double>(); }
|
||||
Vec2d end_point(const Polylines &polylines, const std::vector<Connection> &connections, bool flip = false) const
|
||||
{ const Polyline &pl = polylines[this - connections.data()]; return ((this->flipped == flip) ? pl.points.back() : pl.points.front()).cast<double>(); }
|
||||
|
||||
bool in_queue() const { return this->heap_idx != std::numeric_limits<size_t>::max(); }
|
||||
void flip() { this->flipped = ! this->flipped; }
|
||||
};
|
||||
std::vector<Connection> connections(polylines.size());
|
||||
|
||||
#ifndef NDEBUG
|
||||
auto cost_flipped = [fixed_start, &polylines, &connections]() {
|
||||
assert(! fixed_start || ! connections.front().flipped);
|
||||
double sum = 0.;
|
||||
for (size_t i = 1; i < polylines.size(); ++ i)
|
||||
sum += connections[i - 1].norm(polylines, connections);
|
||||
return sum;
|
||||
};
|
||||
double cost_prev = cost_flipped();
|
||||
assert(std::abs(cost_initial - cost_prev) < SCALED_EPSILON);
|
||||
|
||||
auto print_statistics = [&polylines, &connections]() {
|
||||
#if 0
|
||||
for (size_t i = 1; i < polylines.size(); ++ i)
|
||||
printf("Connecting %d with %d: Current length %lf flip(%d, %d), left flipped: %lf, right flipped: %lf, both flipped: %lf, \n",
|
||||
int(i - 1), int(i),
|
||||
unscale<double>(connections[i - 1].norm(polylines, connections)),
|
||||
int(connections[i - 1].flipped), int(connections[i].flipped),
|
||||
unscale<double>(connections[i - 1].norm(polylines, connections, true, false)),
|
||||
unscale<double>(connections[i - 1].norm(polylines, connections, false, true)),
|
||||
unscale<double>(connections[i - 1].norm(polylines, connections, true, true)));
|
||||
#endif
|
||||
};
|
||||
print_statistics();
|
||||
#endif /* NDEBUG */
|
||||
|
||||
// Initialize a MutablePriorityHeap of connections between polylines.
|
||||
auto queue = make_mutable_priority_queue<Connection*>(
|
||||
[](Connection *connection, size_t idx){ connection->heap_idx = idx; },
|
||||
// Sort by decreasing connection distance.
|
||||
[&polylines, &connections](Connection *l, Connection *r){ return l->squaredNorm(polylines, connections) > r->squaredNorm(polylines, connections); });
|
||||
queue.reserve(polylines.size() - 1);
|
||||
for (size_t i = 0; i + 1 < polylines.size(); ++ i)
|
||||
queue.push(&connections[i]);
|
||||
|
||||
static constexpr size_t itercnt = 100;
|
||||
size_t iter = 0;
|
||||
for (; ! queue.empty() && iter < itercnt; ++ iter) {
|
||||
Connection &connection = *queue.top();
|
||||
queue.pop();
|
||||
connection.heap_idx = std::numeric_limits<size_t>::max();
|
||||
size_t idx_first = &connection - connections.data();
|
||||
// Try to flip segments starting with idx_first + 1 to the end.
|
||||
// Calculate the last segment to be flipped to improve the total path length.
|
||||
double length_current = connection.norm(polylines, connections);
|
||||
double length_flipped = connection.norm(polylines, connections, false, true);
|
||||
int best_idx_forward = int(idx_first);
|
||||
double best_improvement_forward = 0.;
|
||||
for (size_t i = idx_first + 1; i + 1 < connections.size(); ++ i) {
|
||||
length_current += connections[i].norm(polylines, connections);
|
||||
double this_improvement = length_current - length_flipped - connections[i].norm(polylines, connections, true, false);
|
||||
length_flipped += connections[i].norm(polylines, connections, true, true);
|
||||
if (this_improvement > best_improvement_forward) {
|
||||
best_improvement_forward = this_improvement;
|
||||
best_idx_forward = int(i);
|
||||
}
|
||||
// if (length_flipped > 1.5 * length_current)
|
||||
// break;
|
||||
}
|
||||
if (length_current - length_flipped > best_improvement_forward)
|
||||
// Best improvement by flipping up to the end.
|
||||
best_idx_forward = int(connections.size()) - 1;
|
||||
// Try to flip segments starting with idx_first - 1 to the start.
|
||||
// Calculate the last segment to be flipped to improve the total path length.
|
||||
length_current = connection.norm(polylines, connections);
|
||||
length_flipped = connection.norm(polylines, connections, true, false);
|
||||
int best_idx_backwards = int(idx_first);
|
||||
double best_improvement_backwards = 0.;
|
||||
for (int i = int(idx_first) - 1; i >= 0; -- i) {
|
||||
length_current += connections[i].norm(polylines, connections);
|
||||
double this_improvement = length_current - length_flipped - connections[i].norm(polylines, connections, false, true);
|
||||
length_flipped += connections[i].norm(polylines, connections, true, true);
|
||||
if (this_improvement > best_improvement_backwards) {
|
||||
best_improvement_backwards = this_improvement;
|
||||
best_idx_backwards = int(i);
|
||||
}
|
||||
// if (length_flipped > 1.5 * length_current)
|
||||
// break;
|
||||
}
|
||||
if (! fixed_start && length_current - length_flipped > best_improvement_backwards)
|
||||
// Best improvement by flipping up to the start including the first polyline.
|
||||
best_idx_backwards = -1;
|
||||
int update_begin = int(idx_first);
|
||||
int update_end = best_idx_forward;
|
||||
if (best_improvement_backwards > 0. && best_improvement_backwards > best_improvement_forward) {
|
||||
// Flip the sequence of polylines from idx_first to best_improvement_forward + 1.
|
||||
update_begin = best_idx_backwards;
|
||||
update_end = int(idx_first);
|
||||
}
|
||||
assert(update_begin <= update_end);
|
||||
if (update_begin == update_end)
|
||||
continue;
|
||||
for (int i = update_begin + 1; i <= update_end; ++ i)
|
||||
connections[i].flip();
|
||||
|
||||
#ifndef NDEBUG
|
||||
double cost = cost_flipped();
|
||||
assert(cost < cost_prev);
|
||||
cost_prev = cost;
|
||||
print_statistics();
|
||||
#endif /* NDEBUG */
|
||||
|
||||
update_end = std::min(update_end + 1, int(connections.size()) - 1);
|
||||
for (int i = std::max(0, update_begin); i < update_end; ++ i) {
|
||||
Connection &c = connections[i];
|
||||
if (c.in_queue())
|
||||
queue.update(c.heap_idx);
|
||||
else
|
||||
queue.push(&c);
|
||||
}
|
||||
}
|
||||
|
||||
// Flip the segments based on the flip flag.
|
||||
for (Polyline &pl : polylines)
|
||||
if (connections[&pl - polylines.data()].flipped)
|
||||
pl.reverse();
|
||||
|
||||
#ifndef NDEBUG
|
||||
double cost_final = cost();
|
||||
#ifdef DEBUG_SVG_OUTPUT
|
||||
{
|
||||
SVG svg(debug_out_path("improve_ordering_by_segment_flipping-final-%d.svg", iRun).c_str(), bbox);
|
||||
svg.draw(polylines);
|
||||
for (size_t i = 1; i < polylines.size(); ++ i)
|
||||
svg.draw(Line(polylines[i - 1].last_point(), polylines[i].first_point()), "red");
|
||||
}
|
||||
#endif /* DEBUG_SVG_OUTPUT */
|
||||
#endif /* NDEBUG */
|
||||
|
||||
assert(cost_final <= cost_prev);
|
||||
assert(cost_final <= cost_initial);
|
||||
}
|
||||
|
||||
Polylines chain_polylines(Polylines &&polylines, const Point *start_near)
|
||||
{
|
||||
auto segment_end_point = [&polylines](size_t idx, bool first_point) -> const Point& { return first_point ? polylines[idx].first_point() : polylines[idx].last_point(); };
|
||||
std::vector<std::pair<size_t, bool>> ordered = chain_segments_greedy<Point, decltype(segment_end_point)>(segment_end_point, polylines.size(), start_near);
|
||||
Polylines out;
|
||||
out.reserve(polylines.size());
|
||||
for (auto &segment_and_reversal : ordered) {
|
||||
out.emplace_back(std::move(polylines[segment_and_reversal.first]));
|
||||
if (segment_and_reversal.second)
|
||||
out.back().reverse();
|
||||
if (! polylines.empty()) {
|
||||
auto segment_end_point = [&polylines](size_t idx, bool first_point) -> const Point& { return first_point ? polylines[idx].first_point() : polylines[idx].last_point(); };
|
||||
std::vector<std::pair<size_t, bool>> ordered = chain_segments_greedy<Point, decltype(segment_end_point)>(segment_end_point, polylines.size(), start_near);
|
||||
out.reserve(polylines.size());
|
||||
for (auto &segment_and_reversal : ordered) {
|
||||
out.emplace_back(std::move(polylines[segment_and_reversal.first]));
|
||||
if (segment_and_reversal.second)
|
||||
out.back().reverse();
|
||||
}
|
||||
if (out.size() > 1)
|
||||
improve_ordering_by_segment_flipping(out, start_near != nullptr);
|
||||
}
|
||||
return out;
|
||||
return out;
|
||||
}
|
||||
|
||||
template<class T> static inline T chain_path_items(const Points &points, const T &items)
|
||||
|
|
|
@ -272,27 +272,13 @@ void Bed3D::render(GLCanvas3D& canvas, float theta, float scale_factor) const
|
|||
|
||||
switch (m_type)
|
||||
{
|
||||
case MK2:
|
||||
{
|
||||
render_prusa(canvas, "mk2", theta > 90.0f);
|
||||
break;
|
||||
}
|
||||
case MK3:
|
||||
{
|
||||
render_prusa(canvas, "mk3", theta > 90.0f);
|
||||
break;
|
||||
}
|
||||
case SL1:
|
||||
{
|
||||
render_prusa(canvas, "sl1", theta > 90.0f);
|
||||
break;
|
||||
}
|
||||
case MK2: { render_prusa(canvas, "mk2", theta > 90.0f); break; }
|
||||
case MK3: { render_prusa(canvas, "mk3", theta > 90.0f); break; }
|
||||
case SL1: { render_prusa(canvas, "sl1", theta > 90.0f); break; }
|
||||
case MINI: { render_prusa(canvas, "mini", theta > 90.0f); break; }
|
||||
case ENDER3: { render_prusa(canvas, "ender3", theta > 90.0f); break; }
|
||||
default:
|
||||
case Custom:
|
||||
{
|
||||
render_custom(canvas, theta > 90.0f);
|
||||
break;
|
||||
}
|
||||
case Custom: { render_custom(canvas, theta > 90.0f); break; }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -364,22 +350,38 @@ Bed3D::EType Bed3D::detect_type(const Pointfs& shape) const
|
|||
{
|
||||
if (curr->config.has("bed_shape"))
|
||||
{
|
||||
if ((curr->vendor != nullptr) && (curr->vendor->name == "Prusa Research") && (shape == dynamic_cast<const ConfigOptionPoints*>(curr->config.option("bed_shape"))->values))
|
||||
if (curr->vendor != nullptr)
|
||||
{
|
||||
if (boost::contains(curr->name, "SL1"))
|
||||
if ((curr->vendor->name == "Prusa Research") && (shape == dynamic_cast<const ConfigOptionPoints*>(curr->config.option("bed_shape"))->values))
|
||||
{
|
||||
type = SL1;
|
||||
break;
|
||||
if (boost::contains(curr->name, "SL1"))
|
||||
{
|
||||
type = SL1;
|
||||
break;
|
||||
}
|
||||
else if (boost::contains(curr->name, "MK3") || boost::contains(curr->name, "MK2.5"))
|
||||
{
|
||||
type = MK3;
|
||||
break;
|
||||
}
|
||||
else if (boost::contains(curr->name, "MK2"))
|
||||
{
|
||||
type = MK2;
|
||||
break;
|
||||
}
|
||||
else if (boost::contains(curr->name, "MINI"))
|
||||
{
|
||||
type = MINI;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (boost::contains(curr->name, "MK3") || boost::contains(curr->name, "MK2.5"))
|
||||
else if ((curr->vendor->name == "Creality") && (shape == dynamic_cast<const ConfigOptionPoints*>(curr->config.option("bed_shape"))->values))
|
||||
{
|
||||
type = MK3;
|
||||
break;
|
||||
}
|
||||
else if (boost::contains(curr->name, "MK2"))
|
||||
{
|
||||
type = MK2;
|
||||
break;
|
||||
if (boost::contains(curr->name, "ENDER-3"))
|
||||
{
|
||||
type = ENDER3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,6 +67,8 @@ public:
|
|||
MK2,
|
||||
MK3,
|
||||
SL1,
|
||||
MINI,
|
||||
ENDER3,
|
||||
Custom,
|
||||
Num_Types
|
||||
};
|
||||
|
|
|
@ -166,6 +166,8 @@ PrinterPicker::PrinterPicker(wxWindow *parent, const VendorProfile &vendor, wxSt
|
|||
int max_row_width = 0;
|
||||
int current_row_width = 0;
|
||||
|
||||
bool is_variants = false;
|
||||
|
||||
for (const auto &model : models) {
|
||||
if (! filter(model)) { continue; }
|
||||
|
||||
|
@ -220,6 +222,7 @@ PrinterPicker::PrinterPicker(wxWindow *parent, const VendorProfile &vendor, wxSt
|
|||
auto *alt_label = new wxStaticText(variants_panel, wxID_ANY, _(L("Alternate nozzles:")));
|
||||
alt_label->SetFont(font_alt_nozzle);
|
||||
variants_sizer->Add(alt_label, 0, wxBOTTOM, 3);
|
||||
is_variants = true;
|
||||
}
|
||||
|
||||
auto *cbox = new Checkbox(variants_panel, label, model_id, variant.name);
|
||||
|
@ -280,10 +283,10 @@ PrinterPicker::PrinterPicker(wxWindow *parent, const VendorProfile &vendor, wxSt
|
|||
}
|
||||
title_sizer->AddStretchSpacer();
|
||||
|
||||
if (titles.size() > 1) {
|
||||
if (/*titles.size() > 1*/is_variants) {
|
||||
// It only makes sense to add the All / None buttons if there's multiple printers
|
||||
|
||||
auto *sel_all_std = new wxButton(this, wxID_ANY, _(L("All standard")));
|
||||
auto *sel_all_std = new wxButton(this, wxID_ANY, titles.size() > 1 ? _(L("All standard")) : _(L("Standard")));
|
||||
auto *sel_all = new wxButton(this, wxID_ANY, _(L("All")));
|
||||
auto *sel_none = new wxButton(this, wxID_ANY, _(L("None")));
|
||||
sel_all_std->Bind(wxEVT_BUTTON, [this](const wxCommandEvent &event) { this->select_all(true, false); });
|
||||
|
|
|
@ -403,7 +403,7 @@ const std::vector<std::string>& Preset::print_options()
|
|||
"top_infill_extrusion_width", "support_material_extrusion_width", "infill_overlap", "bridge_flow_ratio", "clip_multipart_objects",
|
||||
"elefant_foot_compensation", "xy_size_compensation", "threads", "resolution", "wipe_tower", "wipe_tower_x", "wipe_tower_y",
|
||||
"wipe_tower_width", "wipe_tower_rotation_angle", "wipe_tower_bridging", "single_extruder_multi_material_priming",
|
||||
"compatible_printers", "compatible_printers_condition", "inherits"
|
||||
"wipe_tower_no_sparse_layers", "compatible_printers", "compatible_printers_condition", "inherits"
|
||||
};
|
||||
return s_opts;
|
||||
}
|
||||
|
|
|
@ -1170,6 +1170,7 @@ void TabPrint::build()
|
|||
optgroup->append_single_option_line("wipe_tower_width");
|
||||
optgroup->append_single_option_line("wipe_tower_rotation_angle");
|
||||
optgroup->append_single_option_line("wipe_tower_bridging");
|
||||
optgroup->append_single_option_line("wipe_tower_no_sparse_layers");
|
||||
optgroup->append_single_option_line("single_extruder_multi_material_priming");
|
||||
|
||||
optgroup = page->new_optgroup(_(L("Advanced")));
|
||||
|
|
|
@ -222,6 +222,21 @@ static ExPolygon vase_with_fins()
|
|||
|
||||
SCENARIO("Elephant foot compensation", "[ElephantFoot]") {
|
||||
|
||||
GIVEN("Tiny contour") {
|
||||
ExPolygon expoly({ { 133382606, 94912473 }, { 134232493, 95001115 }, { 133783926, 95159440 }, { 133441897, 95180666 }, { 133408242, 95191984 }, { 133339012, 95166830 }, { 132991642, 95011087 }, { 133206549, 94908304 } });
|
||||
WHEN("Compensated") {
|
||||
ExPolygon expoly_compensated = elephant_foot_compensation(expoly, Flow(0.419999987f, 0.2f, 0.4f, false), 0.2f);
|
||||
#ifdef TESTS_EXPORT_SVGS
|
||||
SVG::export_expolygons(debug_out_path("elephant_foot_compensation_tiny.svg").c_str(),
|
||||
{ { { expoly }, { "gray", "black", "blue", coord_t(scale_(0.02)), 0.5f, "black", coord_t(scale_(0.05)) } },
|
||||
{ { expoly_compensated }, { "gray", "black", "blue", coord_t(scale_(0.02)), 0.5f, "black", coord_t(scale_(0.05)) } } });
|
||||
#endif /* TESTS_EXPORT_SVGS */
|
||||
THEN("Tiny contour is not compensated") {
|
||||
REQUIRE(expoly_compensated == expoly);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GIVEN("Large box") {
|
||||
ExPolygon expoly( { {50000000, 50000000 }, { 0, 50000000 }, { 0, 0 }, { 50000000, 0 } } );
|
||||
WHEN("Compensated") {
|
||||
|
|
|
@ -252,15 +252,39 @@ SCENARIO("Circle Fit, TaubinFit with Newton's method", "[Geometry]") {
|
|||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Chained path working correctly", "[Geometry]"){
|
||||
// if chained_path() works correctly, these points should be joined with no diagonal paths
|
||||
// (thus 26 units long)
|
||||
std::vector<Point> points = {Point(26,26),Point(52,26),Point(0,26),Point(26,52),Point(26,0),Point(0,52),Point(52,52),Point(52,0)};
|
||||
std::vector<Points::size_type> indices = chain_points(points);
|
||||
for (Points::size_type i = 0; i + 1 < indices.size(); ++ i) {
|
||||
double dist = (points.at(indices.at(i)).cast<double>() - points.at(indices.at(i+1)).cast<double>()).norm();
|
||||
REQUIRE(std::abs(dist-26) <= EPSILON);
|
||||
}
|
||||
SCENARIO("Path chaining", "[Geometry]") {
|
||||
GIVEN("A path") {
|
||||
std::vector<Point> points = { Point(26,26),Point(52,26),Point(0,26),Point(26,52),Point(26,0),Point(0,52),Point(52,52),Point(52,0) };
|
||||
THEN("Chained with no diagonals (thus 26 units long)") {
|
||||
std::vector<Points::size_type> indices = chain_points(points);
|
||||
for (Points::size_type i = 0; i + 1 < indices.size(); ++ i) {
|
||||
double dist = (points.at(indices.at(i)).cast<double>() - points.at(indices.at(i+1)).cast<double>()).norm();
|
||||
REQUIRE(std::abs(dist-26) <= EPSILON);
|
||||
}
|
||||
}
|
||||
}
|
||||
GIVEN("Loop pieces") {
|
||||
Point a { 2185796, 19058485 };
|
||||
Point b { 3957902, 18149382 };
|
||||
Point c { 2912841, 18790564 };
|
||||
Point d { 2831848, 18832390 };
|
||||
Point e { 3179601, 18627769 };
|
||||
Point f { 3137952, 18653370 };
|
||||
Polylines polylines = { { a, b },
|
||||
{ c, d },
|
||||
{ e, f },
|
||||
{ d, a },
|
||||
{ f, c },
|
||||
{ b, e } };
|
||||
Polylines chained = chain_polylines(polylines, &a);
|
||||
THEN("Connected without a gap") {
|
||||
for (size_t i = 0; i < chained.size(); ++i) {
|
||||
const Polyline &pl1 = (i == 0) ? chained.back() : chained[i - 1];
|
||||
const Polyline &pl2 = chained[i];
|
||||
REQUIRE(pl1.points.back() == pl2.points.front());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SCENARIO("Line distances", "[Geometry]"){
|
||||
|
|
Loading…
Reference in a new issue