mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-31 12:41:20 -06:00 
			
		
		
		
	Merge branch 'master' of https://github.com/prusa3d/PrusaSlicer into et_3dconnexion
This commit is contained in:
		
						commit
						599403ba94
					
				
					 18 changed files with 628 additions and 295 deletions
				
			
		|  | @ -1,109 +1,70 @@ | |||
| <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"/> | ||||
| <svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" width="180.5mm" height="180.6mm" viewBox="0 0 511.7 512"> | ||||
|   <title>MINI_bed_texture</title> | ||||
|   <path d="M510.6,510.9" transform="translate(0.4 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.4 0.4)" style="fill: none;stroke: #fff;stroke-linecap: round;stroke-linejoin: round;stroke-width: 1.5px"/> | ||||
|   <line x1="511" y1="511.3" x2="511" 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.4 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.4 0.4)" style="fill: none;stroke: #fff;stroke-linecap: round;stroke-linejoin: round;stroke-width: 1.5px"/> | ||||
|   <line x1="0.8" y1="0.8" x2="0.8" y2="511.3" style="fill: none;stroke: #fff;stroke-linecap: round;stroke-linejoin: round;stroke-width: 1.5px"/> | ||||
|   <line x1="0.8" y1="511.3" x2="0.8" y2="0.8" style="fill: none;stroke: #fff;stroke-linecap: round;stroke-linejoin: round;stroke-width: 1.5px"/> | ||||
|   <line x1="511" y1="0.8" x2="511" y2="511.3" style="fill: none;stroke: #fff;stroke-linecap: round;stroke-linejoin: round;stroke-width: 1.5px"/> | ||||
|   <line x1="0.8" y1="511.3" x2="511" y2="511.3" style="fill: none;stroke: #fff;stroke-linecap: round;stroke-linejoin: round;stroke-width: 1.5px"/> | ||||
|   <line x1="0.8" y1="0.8" x2="511" 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"/> | ||||
|       <line x1="0.8" y1="383.6" x2="2.9" y2="383.6" style="fill: none;stroke: #fff;stroke-linecap: round;stroke-linejoin: round"/> | ||||
|       <line x1="5" y1="383.6" x2="6.6" y2="383.6" style="fill: none;stroke: #fff;stroke-linecap: round;stroke-linejoin: round;stroke-dasharray: 0.5694814920425415,2.1355555057525635"/> | ||||
|       <line x1="7.7" y1="383.6" x2="507.8" 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="508.9" y1="383.6" x2="511" 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"/> | ||||
|       <line x1="0.8" y1="256" x2="2.9" y2="256" style="fill: none;stroke: #fff;stroke-linecap: round;stroke-linejoin: round"/> | ||||
|       <line x1="5" y1="256" x2="6.6" y2="256" style="fill: none;stroke: #fff;stroke-linecap: round;stroke-linejoin: round;stroke-dasharray: 0.5694814920425415,2.1355555057525635"/> | ||||
|       <line x1="7.7" y1="256" x2="507.8" 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="508.9" y1="256" x2="511" 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"/> | ||||
|       <line x1="511" y1="128.4" x2="508.9" y2="128.4" style="fill: none;stroke: #fff;stroke-linecap: round;stroke-linejoin: round"/> | ||||
|       <line x1="506.7" y1="128.4" x2="505.1" y2="128.4" style="fill: none;stroke: #fff;stroke-linecap: round;stroke-linejoin: round;stroke-dasharray: 0.5694814920425415,2.1355555057525635"/> | ||||
|       <line x1="504" y1="128.4" x2="3.9" 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="2.9" y1="128.4" x2="0.8" 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"/> | ||||
|       <line x1="128.3" y1="511.3" x2="128.3" y2="509.1" style="fill: none;stroke: #fff;stroke-linecap: round;stroke-linejoin: round"/> | ||||
|       <line x1="128.3" y1="507" x2="128.3" y2="505.4" style="fill: none;stroke: #fff;stroke-linecap: round;stroke-linejoin: round;stroke-dasharray: 0.569789707660675,2.1367111206054688"/> | ||||
|       <line x1="128.3" y1="504.3" x2="128.3" 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.3" y1="2.9" x2="128.3" 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"/> | ||||
|       <line x1="255.9" y1="0.8" x2="255.9" y2="2.9" style="fill: none;stroke: #fff;stroke-linecap: round;stroke-linejoin: round"/> | ||||
|       <line x1="255.9" y1="5" x2="255.9" y2="6.7" style="fill: none;stroke: #fff;stroke-linecap: round;stroke-linejoin: round;stroke-dasharray: 0.569789707660675,2.1367111206054688"/> | ||||
|       <line x1="255.9" y1="7.7" x2="255.9" 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="255.9" y1="509.1" x2="255.9" 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"/> | ||||
|       <line x1="383.4" y1="484.8" x2="383.4" y2="482.6" style="fill: none;stroke: #fff;stroke-linecap: round;stroke-linejoin: round"/> | ||||
|       <line x1="383.4" y1="480.5" x2="383.4" y2="478.9" style="fill: none;stroke: #fff;stroke-linecap: round;stroke-linejoin: round;stroke-dasharray: 0.5708136558532715,2.1405510902404785"/> | ||||
|       <line x1="383.4" y1="477.8" x2="383.4" y2="3.9" style="fill: none;stroke: #fff;stroke-linecap: round;stroke-linejoin: round;stroke-dasharray: 4.281102180480957,2.1405510902404785,0.5708136558532715,2.1405510902404785"/> | ||||
|       <line x1="383.4" y1="2.9" x2="383.4" 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"/> | ||||
|     <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.4 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.4 0.4)" style="fill: #fff"/> | ||||
|     <path d="M302,489.3h3.4V505H302Z" transform="translate(0.4 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.4 0.4)" style="fill: #fff"/> | ||||
|     <path d="M325.1,489.3h3.4V505h-3.4Z" transform="translate(0.4 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.4 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.4 0.4)" style="fill: #fff"/> | ||||
|     <path d="M363.4,489.3h3.4v13h6.8V505H363.4Z" transform="translate(0.4 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.4 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.4 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.4 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.4 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.4 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.4 0.4)" style="fill: #fff"/> | ||||
|     <path d="M478.6,489.3H482V505h-3.4Z" transform="translate(0.4 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.4 0.4)" style="fill: #fff"/> | ||||
|     <path d="M501.3,489.3h3.4V505h-3.4Z" transform="translate(0.4 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> | ||||
|  |  | |||
| Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 8.8 KiB | 
|  | @ -184,10 +184,21 @@ extern void stl_mirror_xz(stl_file *stl); | |||
| 
 | ||||
| extern void stl_get_size(stl_file *stl); | ||||
| 
 | ||||
| // the following function is not used
 | ||||
| /*
 | ||||
| template<typename T> | ||||
| extern void stl_transform(stl_file *stl, T *trafo3x4) | ||||
| { | ||||
| 	for (uint32_t i_face = 0; i_face < stl->stats.number_of_facets; ++ i_face) { | ||||
|     Eigen::Matrix<T, 3, 3, Eigen::DontAlign> trafo3x3; | ||||
|     for (int i = 0; i < 3; ++i) | ||||
|     { | ||||
|         for (int j = 0; j < 3; ++j) | ||||
|         { | ||||
|             trafo3x3(i, j) = (i * 4) + j; | ||||
|         } | ||||
|     } | ||||
|     Eigen::Matrix<T, 3, 3, Eigen::DontAlign> r = trafo3x3.inverse().transpose(); | ||||
|     for (uint32_t i_face = 0; i_face < stl->stats.number_of_facets; ++ i_face) { | ||||
| 		stl_facet &face = stl->facet_start[i_face]; | ||||
| 		for (int i_vertex = 0; i_vertex < 3; ++ i_vertex) { | ||||
| 			stl_vertex &v_dst = face.vertex[i_vertex]; | ||||
|  | @ -196,21 +207,18 @@ extern void stl_transform(stl_file *stl, T *trafo3x4) | |||
| 			v_dst(1) = T(trafo3x4[4] * v_src(0) + trafo3x4[5] * v_src(1) + trafo3x4[6]  * v_src(2) + trafo3x4[7]); | ||||
| 			v_dst(2) = T(trafo3x4[8] * v_src(0) + trafo3x4[9] * v_src(1) + trafo3x4[10] * v_src(2) + trafo3x4[11]); | ||||
| 		} | ||||
| 		stl_vertex &v_dst = face.normal; | ||||
| 		stl_vertex  v_src = v_dst; | ||||
| 		v_dst(0) = T(trafo3x4[0] * v_src(0) + trafo3x4[1] * v_src(1) + trafo3x4[2]  * v_src(2)); | ||||
| 		v_dst(1) = T(trafo3x4[4] * v_src(0) + trafo3x4[5] * v_src(1) + trafo3x4[6]  * v_src(2)); | ||||
| 		v_dst(2) = T(trafo3x4[8] * v_src(0) + trafo3x4[9] * v_src(1) + trafo3x4[10] * v_src(2)); | ||||
| 	} | ||||
|         face.normal = (r * face.normal.template cast<T>()).template cast<float>().eval(); | ||||
|     } | ||||
| 
 | ||||
| 	stl_get_size(stl); | ||||
| } | ||||
| */ | ||||
| 
 | ||||
| template<typename T> | ||||
| inline void stl_transform(stl_file *stl, const Eigen::Transform<T, 3, Eigen::Affine, Eigen::DontAlign>& t) | ||||
| { | ||||
| 	const Eigen::Matrix<double, 3, 3, Eigen::DontAlign> r = t.matrix().template block<3, 3>(0, 0); | ||||
| 	for (size_t i = 0; i < stl->stats.number_of_facets; ++ i) { | ||||
|     const Eigen::Matrix<T, 3, 3, Eigen::DontAlign> r = t.matrix().template block<3, 3>(0, 0).inverse().transpose(); | ||||
|     for (size_t i = 0; i < stl->stats.number_of_facets; ++ i) { | ||||
| 		stl_facet &f = stl->facet_start[i]; | ||||
| 		for (size_t j = 0; j < 3; ++j) | ||||
| 			f.vertex[j] = (t * f.vertex[j].template cast<T>()).template cast<float>().eval(); | ||||
|  | @ -223,12 +231,13 @@ inline void stl_transform(stl_file *stl, const Eigen::Transform<T, 3, Eigen::Aff | |||
| template<typename T> | ||||
| inline void stl_transform(stl_file *stl, const Eigen::Matrix<T, 3, 3, Eigen::DontAlign>& m) | ||||
| { | ||||
| 	for (size_t i = 0; i < stl->stats.number_of_facets; ++ i) { | ||||
|     const Eigen::Matrix<T, 3, 3, Eigen::DontAlign> r = m.inverse().transpose(); | ||||
|     for (size_t i = 0; i < stl->stats.number_of_facets; ++ i) { | ||||
| 		stl_facet &f = stl->facet_start[i]; | ||||
| 		for (size_t j = 0; j < 3; ++j) | ||||
| 			f.vertex[j] = (m * f.vertex[j].template cast<T>()).template cast<float>().eval(); | ||||
| 		f.normal = (m * f.normal.template cast<T>()).template cast<float>().eval(); | ||||
| 	} | ||||
|         f.normal = (r * f.normal.template cast<T>()).template cast<float>().eval(); | ||||
|     } | ||||
| 
 | ||||
| 	stl_get_size(stl); | ||||
| } | ||||
|  |  | |||
|  | @ -6,9 +6,6 @@ | |||
| #include "Geometry.hpp" | ||||
| #include "GCode/PrintExtents.hpp" | ||||
| #include "GCode/WipeTower.hpp" | ||||
| #if ENABLE_THUMBNAIL_GENERATOR | ||||
| #include "GCode/ThumbnailData.hpp" | ||||
| #endif // ENABLE_THUMBNAIL_GENERATOR
 | ||||
| #include "ShortestPath.hpp" | ||||
| #include "Utils.hpp" | ||||
| 
 | ||||
|  | @ -695,7 +692,7 @@ std::vector<std::pair<coordf_t, std::vector<GCode::LayerToPrint>>> GCode::collec | |||
| } | ||||
| 
 | ||||
| #if ENABLE_THUMBNAIL_GENERATOR | ||||
| void GCode::do_export(Print* print, const char* path, GCodePreviewData* preview_data, const std::vector<ThumbnailData>* thumbnail_data) | ||||
| void GCode::do_export(Print* print, const char* path, GCodePreviewData* preview_data, ThumbnailsGeneratorCallback thumbnail_cb) | ||||
| #else | ||||
| void GCode::do_export(Print *print, const char *path, GCodePreviewData *preview_data) | ||||
| #endif // ENABLE_THUMBNAIL_GENERATOR
 | ||||
|  | @ -725,7 +722,7 @@ void GCode::do_export(Print *print, const char *path, GCodePreviewData *preview_ | |||
|     try { | ||||
|         m_placeholder_parser_failed_templates.clear(); | ||||
| #if ENABLE_THUMBNAIL_GENERATOR | ||||
|         this->_do_export(*print, file, thumbnail_data); | ||||
|         this->_do_export(*print, file, thumbnail_cb); | ||||
| #else | ||||
|         this->_do_export(*print, file); | ||||
| #endif // ENABLE_THUMBNAIL_GENERATOR
 | ||||
|  | @ -793,9 +790,9 @@ void GCode::do_export(Print *print, const char *path, GCodePreviewData *preview_ | |||
| } | ||||
| 
 | ||||
| #if ENABLE_THUMBNAIL_GENERATOR | ||||
| void GCode::_do_export(Print& print, FILE* file, const std::vector<ThumbnailData>* thumbnail_data) | ||||
| void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thumbnail_cb) | ||||
| #else | ||||
| void GCode::_do_export(Print &print, FILE *file) | ||||
| void GCode::_do_export(Print& print, FILE* file) | ||||
| #endif // ENABLE_THUMBNAIL_GENERATOR
 | ||||
| { | ||||
|     PROFILE_FUNC(); | ||||
|  | @ -812,46 +809,46 @@ void GCode::_do_export(Print &print, FILE *file) | |||
|     // shall be adjusted as well to produce a G-code block compatible with the particular firmware flavor.
 | ||||
|     if (print.config().gcode_flavor.value == gcfMarlin) { | ||||
|         m_normal_time_estimator.set_max_acceleration((float)print.config().machine_max_acceleration_extruding.values[0]); | ||||
| 		m_normal_time_estimator.set_retract_acceleration((float)print.config().machine_max_acceleration_retracting.values[0]); | ||||
| 		m_normal_time_estimator.set_minimum_feedrate((float)print.config().machine_min_extruding_rate.values[0]); | ||||
| 		m_normal_time_estimator.set_minimum_travel_feedrate((float)print.config().machine_min_travel_rate.values[0]); | ||||
| 		m_normal_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::X, (float)print.config().machine_max_acceleration_x.values[0]); | ||||
| 		m_normal_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::Y, (float)print.config().machine_max_acceleration_y.values[0]); | ||||
| 		m_normal_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::Z, (float)print.config().machine_max_acceleration_z.values[0]); | ||||
| 		m_normal_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::E, (float)print.config().machine_max_acceleration_e.values[0]); | ||||
| 		m_normal_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::X, (float)print.config().machine_max_feedrate_x.values[0]); | ||||
| 		m_normal_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::Y, (float)print.config().machine_max_feedrate_y.values[0]); | ||||
| 		m_normal_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::Z, (float)print.config().machine_max_feedrate_z.values[0]); | ||||
| 		m_normal_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::E, (float)print.config().machine_max_feedrate_e.values[0]); | ||||
| 		m_normal_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::X, (float)print.config().machine_max_jerk_x.values[0]); | ||||
| 		m_normal_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::Y, (float)print.config().machine_max_jerk_y.values[0]); | ||||
| 		m_normal_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::Z, (float)print.config().machine_max_jerk_z.values[0]); | ||||
| 		m_normal_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::E, (float)print.config().machine_max_jerk_e.values[0]); | ||||
|         m_normal_time_estimator.set_retract_acceleration((float)print.config().machine_max_acceleration_retracting.values[0]); | ||||
|         m_normal_time_estimator.set_minimum_feedrate((float)print.config().machine_min_extruding_rate.values[0]); | ||||
|         m_normal_time_estimator.set_minimum_travel_feedrate((float)print.config().machine_min_travel_rate.values[0]); | ||||
|         m_normal_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::X, (float)print.config().machine_max_acceleration_x.values[0]); | ||||
|         m_normal_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::Y, (float)print.config().machine_max_acceleration_y.values[0]); | ||||
|         m_normal_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::Z, (float)print.config().machine_max_acceleration_z.values[0]); | ||||
|         m_normal_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::E, (float)print.config().machine_max_acceleration_e.values[0]); | ||||
|         m_normal_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::X, (float)print.config().machine_max_feedrate_x.values[0]); | ||||
|         m_normal_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::Y, (float)print.config().machine_max_feedrate_y.values[0]); | ||||
|         m_normal_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::Z, (float)print.config().machine_max_feedrate_z.values[0]); | ||||
|         m_normal_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::E, (float)print.config().machine_max_feedrate_e.values[0]); | ||||
|         m_normal_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::X, (float)print.config().machine_max_jerk_x.values[0]); | ||||
|         m_normal_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::Y, (float)print.config().machine_max_jerk_y.values[0]); | ||||
|         m_normal_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::Z, (float)print.config().machine_max_jerk_z.values[0]); | ||||
|         m_normal_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::E, (float)print.config().machine_max_jerk_e.values[0]); | ||||
| 
 | ||||
|         if (m_silent_time_estimator_enabled) | ||||
|         { | ||||
|             m_silent_time_estimator.reset(); | ||||
|             m_silent_time_estimator.set_dialect(print.config().gcode_flavor); | ||||
|             /* "Stealth mode" values can be just a copy of "normal mode" values 
 | ||||
|             /* "Stealth mode" values can be just a copy of "normal mode" values
 | ||||
|             * (when they aren't input for a printer preset). | ||||
|             * Thus, use back value from values, instead of second one, which could be absent | ||||
|             */ | ||||
| 			m_silent_time_estimator.set_max_acceleration((float)print.config().machine_max_acceleration_extruding.values.back()); | ||||
| 			m_silent_time_estimator.set_retract_acceleration((float)print.config().machine_max_acceleration_retracting.values.back()); | ||||
| 			m_silent_time_estimator.set_minimum_feedrate((float)print.config().machine_min_extruding_rate.values.back()); | ||||
| 			m_silent_time_estimator.set_minimum_travel_feedrate((float)print.config().machine_min_travel_rate.values.back()); | ||||
| 			m_silent_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::X, (float)print.config().machine_max_acceleration_x.values.back()); | ||||
| 			m_silent_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::Y, (float)print.config().machine_max_acceleration_y.values.back()); | ||||
| 			m_silent_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::Z, (float)print.config().machine_max_acceleration_z.values.back()); | ||||
| 			m_silent_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::E, (float)print.config().machine_max_acceleration_e.values.back()); | ||||
| 			m_silent_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::X, (float)print.config().machine_max_feedrate_x.values.back()); | ||||
| 			m_silent_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::Y, (float)print.config().machine_max_feedrate_y.values.back()); | ||||
| 			m_silent_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::Z, (float)print.config().machine_max_feedrate_z.values.back()); | ||||
| 			m_silent_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::E, (float)print.config().machine_max_feedrate_e.values.back()); | ||||
| 			m_silent_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::X, (float)print.config().machine_max_jerk_x.values.back()); | ||||
| 			m_silent_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::Y, (float)print.config().machine_max_jerk_y.values.back()); | ||||
| 			m_silent_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::Z, (float)print.config().machine_max_jerk_z.values.back()); | ||||
| 			m_silent_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::E, (float)print.config().machine_max_jerk_e.values.back()); | ||||
|             m_silent_time_estimator.set_max_acceleration((float)print.config().machine_max_acceleration_extruding.values.back()); | ||||
|             m_silent_time_estimator.set_retract_acceleration((float)print.config().machine_max_acceleration_retracting.values.back()); | ||||
|             m_silent_time_estimator.set_minimum_feedrate((float)print.config().machine_min_extruding_rate.values.back()); | ||||
|             m_silent_time_estimator.set_minimum_travel_feedrate((float)print.config().machine_min_travel_rate.values.back()); | ||||
|             m_silent_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::X, (float)print.config().machine_max_acceleration_x.values.back()); | ||||
|             m_silent_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::Y, (float)print.config().machine_max_acceleration_y.values.back()); | ||||
|             m_silent_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::Z, (float)print.config().machine_max_acceleration_z.values.back()); | ||||
|             m_silent_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::E, (float)print.config().machine_max_acceleration_e.values.back()); | ||||
|             m_silent_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::X, (float)print.config().machine_max_feedrate_x.values.back()); | ||||
|             m_silent_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::Y, (float)print.config().machine_max_feedrate_y.values.back()); | ||||
|             m_silent_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::Z, (float)print.config().machine_max_feedrate_z.values.back()); | ||||
|             m_silent_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::E, (float)print.config().machine_max_feedrate_e.values.back()); | ||||
|             m_silent_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::X, (float)print.config().machine_max_jerk_x.values.back()); | ||||
|             m_silent_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::Y, (float)print.config().machine_max_jerk_y.values.back()); | ||||
|             m_silent_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::Z, (float)print.config().machine_max_jerk_z.values.back()); | ||||
|             m_silent_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::E, (float)print.config().machine_max_jerk_e.values.back()); | ||||
|             if (print.config().single_extruder_multi_material) { | ||||
|                 // As of now the fields are shown at the UI dialog in the same combo box as the ramming values, so they
 | ||||
|                 // are considered to be active for the single extruder multi-material printers only.
 | ||||
|  | @ -909,7 +906,8 @@ void GCode::_do_export(Print &print, FILE *file) | |||
|             std::sort(zs.begin(), zs.end()); | ||||
|             m_layer_count += (unsigned int)(object->copies().size() * (std::unique(zs.begin(), zs.end()) - zs.begin())); | ||||
|         } | ||||
|     } else { | ||||
|     } | ||||
|     else { | ||||
|         // Print all objects with the same print_z together.
 | ||||
|         std::vector<coordf_t> zs; | ||||
|         for (auto object : print.objects()) { | ||||
|  | @ -927,7 +925,7 @@ void GCode::_do_export(Print &print, FILE *file) | |||
|     m_enable_cooling_markers = true; | ||||
|     this->apply_print_config(print.config()); | ||||
|     this->set_extruders(print.extruders()); | ||||
|      | ||||
| 
 | ||||
|     // Initialize colorprint.
 | ||||
|     m_colorprint_heights = cast<float>(print.config().colorprint_heights.values); | ||||
| 
 | ||||
|  | @ -936,31 +934,31 @@ void GCode::_do_export(Print &print, FILE *file) | |||
|         // get the minimum cross-section used in the print
 | ||||
|         std::vector<double> mm3_per_mm; | ||||
|         for (auto object : print.objects()) { | ||||
|             for (size_t region_id = 0; region_id < object->region_volumes.size(); ++ region_id) { | ||||
|             for (size_t region_id = 0; region_id < object->region_volumes.size(); ++region_id) { | ||||
|                 const PrintRegion* region = print.regions()[region_id]; | ||||
|                 for (auto layer : object->layers()) { | ||||
|                     const LayerRegion* layerm = layer->regions()[region_id]; | ||||
|                     if (region->config().get_abs_value("perimeter_speed"          ) == 0 ||  | ||||
|                         region->config().get_abs_value("small_perimeter_speed"    ) == 0 ||  | ||||
|                         region->config().get_abs_value("external_perimeter_speed" ) == 0 ||  | ||||
|                         region->config().get_abs_value("bridge_speed"             ) == 0) | ||||
|                     if (region->config().get_abs_value("perimeter_speed") == 0 || | ||||
|                         region->config().get_abs_value("small_perimeter_speed") == 0 || | ||||
|                         region->config().get_abs_value("external_perimeter_speed") == 0 || | ||||
|                         region->config().get_abs_value("bridge_speed") == 0) | ||||
|                         mm3_per_mm.push_back(layerm->perimeters.min_mm3_per_mm()); | ||||
|                     if (region->config().get_abs_value("infill_speed"             ) == 0 ||  | ||||
|                         region->config().get_abs_value("solid_infill_speed"       ) == 0 ||  | ||||
|                         region->config().get_abs_value("top_solid_infill_speed"   ) == 0 ||  | ||||
|                         region->config().get_abs_value("bridge_speed"             ) == 0) | ||||
|                     if (region->config().get_abs_value("infill_speed") == 0 || | ||||
|                         region->config().get_abs_value("solid_infill_speed") == 0 || | ||||
|                         region->config().get_abs_value("top_solid_infill_speed") == 0 || | ||||
|                         region->config().get_abs_value("bridge_speed") == 0) | ||||
|                         mm3_per_mm.push_back(layerm->fills.min_mm3_per_mm()); | ||||
|                 } | ||||
|             } | ||||
|             if (object->config().get_abs_value("support_material_speed"           ) == 0 ||  | ||||
|                 object->config().get_abs_value("support_material_interface_speed" ) == 0) | ||||
|             if (object->config().get_abs_value("support_material_speed") == 0 || | ||||
|                 object->config().get_abs_value("support_material_interface_speed") == 0) | ||||
|                 for (auto layer : object->support_layers()) | ||||
|                     mm3_per_mm.push_back(layer->support_fills.min_mm3_per_mm()); | ||||
|         } | ||||
|         print.throw_if_canceled(); | ||||
|         // filter out 0-width segments
 | ||||
|         mm3_per_mm.erase(std::remove_if(mm3_per_mm.begin(), mm3_per_mm.end(), [](double v) { return v < 0.000001; }), mm3_per_mm.end()); | ||||
|         if (! mm3_per_mm.empty()) { | ||||
|         if (!mm3_per_mm.empty()) { | ||||
|             // In order to honor max_print_speed we need to find a target volumetric
 | ||||
|             // speed that we can use throughout the print. So we define this target 
 | ||||
|             // volumetric speed as the volumetric speed produced by printing the 
 | ||||
|  | @ -973,7 +971,7 @@ void GCode::_do_export(Print &print, FILE *file) | |||
|         } | ||||
|     } | ||||
|     print.throw_if_canceled(); | ||||
|      | ||||
| 
 | ||||
|     m_cooling_buffer = make_unique<CoolingBuffer>(*this); | ||||
|     if (print.config().spiral_vase.value) | ||||
|         m_spiral_vase = make_unique<SpiralVase>(print.config()); | ||||
|  | @ -991,11 +989,12 @@ void GCode::_do_export(Print &print, FILE *file) | |||
| 
 | ||||
| #if ENABLE_THUMBNAIL_GENERATOR | ||||
|     // Write thumbnails using base64 encoding
 | ||||
|     if (thumbnail_data != nullptr) | ||||
|     if (thumbnail_cb != nullptr) | ||||
|     { | ||||
|         const size_t max_row_length = 78; | ||||
| 
 | ||||
|         for (const ThumbnailData& data : *thumbnail_data) | ||||
|         ThumbnailsList thumbnails; | ||||
|         thumbnail_cb(thumbnails, print.full_print_config().option<ConfigOptionPoints>("thumbnails")->values, true, true, false); | ||||
|         for (const ThumbnailData& data : thumbnails) | ||||
|         { | ||||
|             if (data.is_valid()) | ||||
|             { | ||||
|  |  | |||
|  | @ -17,6 +17,9 @@ | |||
| #include "GCodeTimeEstimator.hpp" | ||||
| #include "EdgeGrid.hpp" | ||||
| #include "GCode/Analyzer.hpp" | ||||
| #if ENABLE_THUMBNAIL_GENERATOR | ||||
| #include "GCode/ThumbnailData.hpp" | ||||
| #endif // ENABLE_THUMBNAIL_GENERATOR
 | ||||
| 
 | ||||
| #include <memory> | ||||
| #include <string> | ||||
|  | @ -30,9 +33,6 @@ namespace Slic3r { | |||
| // Forward declarations.
 | ||||
| class GCode; | ||||
| class GCodePreviewData; | ||||
| #if ENABLE_THUMBNAIL_GENERATOR | ||||
| struct ThumbnailData; | ||||
| #endif // ENABLE_THUMBNAIL_GENERATOR
 | ||||
| 
 | ||||
| class AvoidCrossingPerimeters { | ||||
| public: | ||||
|  | @ -167,7 +167,7 @@ public: | |||
|     // throws std::runtime_exception on error,
 | ||||
|     // throws CanceledException through print->throw_if_canceled().
 | ||||
| #if ENABLE_THUMBNAIL_GENERATOR | ||||
|     void            do_export(Print* print, const char* path, GCodePreviewData* preview_data = nullptr, const std::vector<ThumbnailData>* thumbnail_data = nullptr); | ||||
|     void            do_export(Print* print, const char* path, GCodePreviewData* preview_data = nullptr, ThumbnailsGeneratorCallback thumbnail_cb = nullptr); | ||||
| #else | ||||
|     void            do_export(Print *print, const char *path, GCodePreviewData *preview_data = nullptr); | ||||
| #endif // ENABLE_THUMBNAIL_GENERATOR
 | ||||
|  | @ -199,7 +199,7 @@ public: | |||
| 
 | ||||
| protected: | ||||
| #if ENABLE_THUMBNAIL_GENERATOR | ||||
|     void            _do_export(Print& print, FILE* file, const std::vector<ThumbnailData>* thumbnail_data); | ||||
|     void            _do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thumbnail_cb); | ||||
| #else | ||||
|     void            _do_export(Print &print, FILE *file); | ||||
| #endif //ENABLE_THUMBNAIL_GENERATOR
 | ||||
|  |  | |||
|  | @ -4,6 +4,7 @@ | |||
| #if ENABLE_THUMBNAIL_GENERATOR | ||||
| 
 | ||||
| #include <vector> | ||||
| #include "libslic3r/Point.hpp" | ||||
| 
 | ||||
| namespace Slic3r { | ||||
| 
 | ||||
|  | @ -20,6 +21,9 @@ struct ThumbnailData | |||
|     bool is_valid() const; | ||||
| }; | ||||
| 
 | ||||
| typedef std::vector<ThumbnailData> ThumbnailsList; | ||||
| typedef std::function<void(ThumbnailsList& thumbnails, const Vec2ds& sizes, bool printable_only, bool parts_only, bool transparent_background)> ThumbnailsGeneratorCallback; | ||||
| 
 | ||||
| } // namespace Slic3r
 | ||||
| 
 | ||||
| #endif // ENABLE_THUMBNAIL_GENERATOR
 | ||||
|  |  | |||
|  | @ -1538,7 +1538,7 @@ void Print::process() | |||
| // write error into the G-code, cannot execute post-processing scripts).
 | ||||
| // It is up to the caller to show an error message.
 | ||||
| #if ENABLE_THUMBNAIL_GENERATOR | ||||
| std::string Print::export_gcode(const std::string& path_template, GCodePreviewData* preview_data, const std::vector<ThumbnailData>* thumbnail_data) | ||||
| std::string Print::export_gcode(const std::string& path_template, GCodePreviewData* preview_data, ThumbnailsGeneratorCallback thumbnail_cb) | ||||
| #else | ||||
| std::string Print::export_gcode(const std::string &path_template, GCodePreviewData *preview_data) | ||||
| #endif // ENABLE_THUMBNAIL_GENERATOR
 | ||||
|  | @ -1559,7 +1559,7 @@ std::string Print::export_gcode(const std::string &path_template, GCodePreviewDa | |||
|     // The following line may die for multiple reasons.
 | ||||
|     GCode gcode; | ||||
| #if ENABLE_THUMBNAIL_GENERATOR | ||||
|     gcode.do_export(this, path.c_str(), preview_data, thumbnail_data); | ||||
|     gcode.do_export(this, path.c_str(), preview_data, thumbnail_cb); | ||||
| #else | ||||
|     gcode.do_export(this, path.c_str(), preview_data); | ||||
| #endif // ENABLE_THUMBNAIL_GENERATOR
 | ||||
|  |  | |||
|  | @ -11,6 +11,9 @@ | |||
| #include "Slicing.hpp" | ||||
| #include "GCode/ToolOrdering.hpp" | ||||
| #include "GCode/WipeTower.hpp" | ||||
| #if ENABLE_THUMBNAIL_GENERATOR | ||||
| #include "GCode/ThumbnailData.hpp" | ||||
| #endif // ENABLE_THUMBNAIL_GENERATOR
 | ||||
| 
 | ||||
| namespace Slic3r { | ||||
| 
 | ||||
|  | @ -19,9 +22,6 @@ class PrintObject; | |||
| class ModelObject; | ||||
| class GCode; | ||||
| class GCodePreviewData; | ||||
| #if ENABLE_THUMBNAIL_GENERATOR | ||||
| struct ThumbnailData; | ||||
| #endif // ENABLE_THUMBNAIL_GENERATOR
 | ||||
| 
 | ||||
| // Print step IDs for keeping track of the print state.
 | ||||
| enum PrintStep { | ||||
|  | @ -311,7 +311,7 @@ public: | |||
|     // Exports G-code into a file name based on the path_template, returns the file path of the generated G-code file.
 | ||||
|     // If preview_data is not null, the preview_data is filled in for the G-code visualization (not used by the command line Slic3r).
 | ||||
| #if ENABLE_THUMBNAIL_GENERATOR | ||||
|     std::string         export_gcode(const std::string& path_template, GCodePreviewData* preview_data, const std::vector<ThumbnailData>* thumbnail_data = nullptr); | ||||
|     std::string         export_gcode(const std::string& path_template, GCodePreviewData* preview_data, ThumbnailsGeneratorCallback thumbnail_cb = nullptr); | ||||
| #else | ||||
|     std::string         export_gcode(const std::string &path_template, GCodePreviewData *preview_data); | ||||
| #endif // ENABLE_THUMBNAIL_GENERATOR
 | ||||
|  |  | |||
|  | @ -1522,9 +1522,9 @@ bool PrintObject::update_layer_height_profile(const ModelObject &model_object, c | |||
|         layer_height_profile.clear(); | ||||
| 
 | ||||
|     if (layer_height_profile.empty()) { | ||||
|             //layer_height_profile = layer_height_profile_adaptive(slicing_parameters, model_object.layer_config_ranges, model_object.volumes);
 | ||||
|             layer_height_profile = layer_height_profile_from_ranges(slicing_parameters, model_object.layer_config_ranges); | ||||
|        	updated = true; | ||||
|         //layer_height_profile = layer_height_profile_adaptive(slicing_parameters, model_object.layer_config_ranges, model_object.volumes);
 | ||||
|         layer_height_profile = layer_height_profile_from_ranges(slicing_parameters, model_object.layer_config_ranges); | ||||
|         updated = true; | ||||
|     } | ||||
|     return updated; | ||||
| } | ||||
|  |  | |||
|  | @ -224,40 +224,59 @@ std::vector<coordf_t> layer_height_profile_from_ranges( | |||
| 
 | ||||
| // Based on the work of @platsch
 | ||||
| // Fill layer_height_profile by heights ensuring a prescribed maximum cusp height.
 | ||||
| #if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE | ||||
| std::vector<double> layer_height_profile_adaptive(const SlicingParameters& slicing_params, | ||||
|     const ModelObject& object, float cusp_value) | ||||
| #else | ||||
| std::vector<coordf_t> layer_height_profile_adaptive( | ||||
|     const SlicingParameters     &slicing_params, | ||||
|     const t_layer_config_ranges & /* layer_config_ranges */, | ||||
|     const ModelVolumePtrs		&volumes) | ||||
| #endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
 | ||||
| { | ||||
| #if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE | ||||
|     // 1) Initialize the SlicingAdaptive class with the object meshes.
 | ||||
|     SlicingAdaptive as; | ||||
|     as.set_slicing_parameters(slicing_params); | ||||
|     for (const ModelVolume *volume : volumes) | ||||
|     as.set_object(object); | ||||
| #else | ||||
|     // 1) Initialize the SlicingAdaptive class with the object meshes.
 | ||||
|     SlicingAdaptive as; | ||||
|     as.set_slicing_parameters(slicing_params); | ||||
|     for (const ModelVolume* volume : volumes) | ||||
|         if (volume->is_model_part()) | ||||
|             as.add_mesh(&volume->mesh()); | ||||
| #endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
 | ||||
| 
 | ||||
|     as.prepare(); | ||||
| 
 | ||||
|     // 2) Generate layers using the algorithm of @platsch 
 | ||||
|     // loop until we have at least one layer and the max slice_z reaches the object height
 | ||||
|     //FIXME make it configurable
 | ||||
|     // Cusp value: A maximum allowed distance from a corner of a rectangular extrusion to a chrodal line, in mm.
 | ||||
|     const coordf_t cusp_value = 0.2; // $self->config->get_value('cusp_value');
 | ||||
| #if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE | ||||
|     double cusp_value = 0.2; | ||||
| #endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
 | ||||
| 
 | ||||
|     std::vector<coordf_t> layer_height_profile; | ||||
|     layer_height_profile.push_back(0.); | ||||
|     std::vector<double> layer_height_profile; | ||||
|     layer_height_profile.push_back(0.0); | ||||
|     layer_height_profile.push_back(slicing_params.first_object_layer_height); | ||||
|     if (slicing_params.first_object_layer_height_fixed()) { | ||||
|         layer_height_profile.push_back(slicing_params.first_object_layer_height); | ||||
|         layer_height_profile.push_back(slicing_params.first_object_layer_height); | ||||
|     } | ||||
|     coordf_t slice_z = slicing_params.first_object_layer_height; | ||||
|     coordf_t height  = slicing_params.first_object_layer_height; | ||||
|     double slice_z = slicing_params.first_object_layer_height; | ||||
|     int current_facet = 0; | ||||
| #if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE | ||||
|     while (slice_z <= slicing_params.object_print_z_height()) { | ||||
|         double height = 999.0; | ||||
| #else | ||||
|     double height = slicing_params.first_object_layer_height; | ||||
|     while ((slice_z - height) <= slicing_params.object_print_z_height()) { | ||||
|         height = 999; | ||||
|         height = 999.0; | ||||
| #endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
 | ||||
|         // Slic3r::debugf "\n Slice layer: %d\n", $id;
 | ||||
|         // determine next layer height
 | ||||
|         coordf_t cusp_height = as.cusp_height(slice_z, cusp_value, current_facet); | ||||
|         double cusp_height = as.cusp_height((float)slice_z, cusp_value, current_facet); | ||||
| 
 | ||||
|         // check for horizontal features and object size
 | ||||
|         /*
 | ||||
|         if($self->config->get_value('match_horizontal_surfaces')) { | ||||
|  | @ -303,19 +322,113 @@ std::vector<coordf_t> layer_height_profile_adaptive( | |||
|         layer_height_profile.push_back(slice_z); | ||||
|         layer_height_profile.push_back(height); | ||||
|         slice_z += height; | ||||
| #if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE | ||||
|         layer_height_profile.push_back(slice_z); | ||||
|         layer_height_profile.push_back(height); | ||||
| #endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
 | ||||
|     } | ||||
| 
 | ||||
|     coordf_t last = std::max(slicing_params.first_object_layer_height, layer_height_profile[layer_height_profile.size() - 2]); | ||||
| #if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE | ||||
|     double z_gap = slicing_params.object_print_z_height() - layer_height_profile[layer_height_profile.size() - 2]; | ||||
|     if (z_gap > 0.0) | ||||
|     { | ||||
|         layer_height_profile.push_back(slicing_params.object_print_z_height()); | ||||
|         layer_height_profile.push_back(clamp(slicing_params.min_layer_height, slicing_params.max_layer_height, z_gap)); | ||||
|     } | ||||
| #else | ||||
|     double last = std::max(slicing_params.first_object_layer_height, layer_height_profile[layer_height_profile.size() - 2]); | ||||
|     layer_height_profile.push_back(last); | ||||
|     layer_height_profile.push_back(slicing_params.first_object_layer_height); | ||||
|     layer_height_profile.push_back(slicing_params.object_print_z_height()); | ||||
|     layer_height_profile.push_back(slicing_params.first_object_layer_height); | ||||
| #endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
 | ||||
| 
 | ||||
|     return layer_height_profile; | ||||
| } | ||||
| 
 | ||||
| std::vector<double> smooth_height_profile(const std::vector<double>& profile, const SlicingParameters& slicing_params, const HeightProfileSmoothingParams& smoothing_params) | ||||
| { | ||||
|     auto gauss_blur = [&slicing_params](const std::vector<double>& profile, const HeightProfileSmoothingParams& smoothing_params) -> std::vector<double> { | ||||
|         auto gauss_kernel = [] (unsigned int radius) -> std::vector<double> { | ||||
|             unsigned int size = 2 * radius + 1; | ||||
|             std::vector<double> ret; | ||||
|             ret.reserve(size); | ||||
| 
 | ||||
|             // Reworked from static inline int getGaussianKernelSize(float sigma) taken from opencv-4.1.2\modules\features2d\src\kaze\AKAZEFeatures.cpp
 | ||||
|             double sigma = 0.3 * (double)(radius - 1) + 0.8; | ||||
|             double two_sq_sigma = 2.0 * sigma * sigma; | ||||
|             double inv_root_two_pi_sq_sigma = 1.0 / ::sqrt(M_PI * two_sq_sigma); | ||||
| 
 | ||||
|             for (unsigned int i = 0; i < size; ++i) | ||||
|             { | ||||
|                 double x = (double)i - (double)radius; | ||||
|                 ret.push_back(inv_root_two_pi_sq_sigma * ::exp(-x * x / two_sq_sigma)); | ||||
|             } | ||||
| 
 | ||||
|             return ret; | ||||
|         }; | ||||
| 
 | ||||
|         // skip first layer ?
 | ||||
|         size_t skip_count = slicing_params.first_object_layer_height_fixed() ? 4 : 0; | ||||
| 
 | ||||
|         // not enough data to smmoth
 | ||||
|         if ((int)profile.size() - (int)skip_count < 6) | ||||
|             return profile; | ||||
|          | ||||
|         unsigned int radius = std::max(smoothing_params.radius, (unsigned int)1); | ||||
|         std::vector<double> kernel = gauss_kernel(radius); | ||||
|         int two_radius = 2 * (int)radius; | ||||
| 
 | ||||
|         std::vector<double> ret; | ||||
|         size_t size = profile.size(); | ||||
|         ret.reserve(size); | ||||
| 
 | ||||
|         // leave first layer untouched
 | ||||
|         for (size_t i = 0; i < skip_count; ++i) | ||||
|         { | ||||
|             ret.push_back(profile[i]); | ||||
|         } | ||||
| 
 | ||||
|         // smooth the rest of the profile by biasing a gaussian blur
 | ||||
|         // the bias moves the smoothed profile closer to the min_layer_height
 | ||||
|         double delta_h = slicing_params.max_layer_height - slicing_params.min_layer_height; | ||||
|         double inv_delta_h = (delta_h != 0.0) ? 1.0 / delta_h : 1.0; | ||||
| 
 | ||||
|         double max_dz_band = (double)radius * slicing_params.layer_height; | ||||
|         for (size_t i = skip_count; i < size; i += 2) | ||||
|         { | ||||
|             double zi = profile[i]; | ||||
|             double hi = profile[i + 1]; | ||||
|             ret.push_back(zi); | ||||
|             ret.push_back(0.0); | ||||
|             double& height = ret.back(); | ||||
|             int begin = std::max((int)i - two_radius, (int)skip_count); | ||||
|             int end = std::min((int)i + two_radius, (int)size - 2); | ||||
|             double weight_total = 0.0; | ||||
|             for (int j = begin; j <= end; j += 2) | ||||
|             { | ||||
|                 int kernel_id = radius + (j - (int)i) / 2; | ||||
|                 double dz = std::abs(zi - profile[j]); | ||||
|                 if (dz * slicing_params.layer_height <= max_dz_band) | ||||
|                 { | ||||
|                     double dh = std::abs(slicing_params.max_layer_height - profile[j + 1]); | ||||
|                     double weight = kernel[kernel_id] * sqrt(dh * inv_delta_h); | ||||
|                     height += weight * profile[j + 1]; | ||||
|                     weight_total += weight; | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             height = clamp(slicing_params.min_layer_height, slicing_params.max_layer_height, (weight_total != 0.0) ? height /= weight_total : hi); | ||||
|             if (smoothing_params.keep_min) | ||||
|                 height = std::min(height, hi); | ||||
|         } | ||||
| 
 | ||||
|         return ret; | ||||
|     }; | ||||
| 
 | ||||
|     return gauss_blur(profile, smoothing_params); | ||||
| } | ||||
| 
 | ||||
| void adjust_layer_height_profile( | ||||
|     const SlicingParameters     &slicing_params, | ||||
|     std::vector<coordf_t> 		&layer_height_profile, | ||||
|  | @ -609,7 +722,11 @@ int generate_layer_height_texture( | |||
|             const Vec3crd &color1 = palette_raw[idx1]; | ||||
|             const Vec3crd &color2 = palette_raw[idx2]; | ||||
|             coordf_t z = cell_to_z * coordf_t(cell); | ||||
| 			assert(z >= lo && z <= hi); | ||||
| #if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE | ||||
|             assert((lo - EPSILON <= z) && (z <= hi + EPSILON)); | ||||
| #else | ||||
|             assert(z >= lo && z <= hi); | ||||
| #endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
 | ||||
|             // Intensity profile to visualize the layers.
 | ||||
|             coordf_t intensity = cos(M_PI * 0.7 * (mid - z) / h); | ||||
|             // Color mapping from layer height to RGB.
 | ||||
|  |  | |||
|  | @ -18,8 +18,12 @@ namespace Slic3r | |||
| 
 | ||||
| class PrintConfig; | ||||
| class PrintObjectConfig; | ||||
| #if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE | ||||
| class ModelObject; | ||||
| #else | ||||
| class ModelVolume; | ||||
| typedef std::vector<ModelVolume*> ModelVolumePtrs; | ||||
| #endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
 | ||||
| 
 | ||||
| // Parameters to guide object slicing and support generation.
 | ||||
| // The slicing parameters account for a raft and whether the 1st object layer is printed with a normal or a bridging flow
 | ||||
|  | @ -138,11 +142,29 @@ extern std::vector<coordf_t> layer_height_profile_from_ranges( | |||
|     const SlicingParameters     &slicing_params, | ||||
|     const t_layer_config_ranges &layer_config_ranges); | ||||
| 
 | ||||
| #if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE | ||||
| extern std::vector<double> layer_height_profile_adaptive( | ||||
|     const SlicingParameters& slicing_params, | ||||
|     const ModelObject& object, float cusp_value); | ||||
| 
 | ||||
| struct HeightProfileSmoothingParams | ||||
| { | ||||
|     unsigned int radius; | ||||
|     bool keep_min; | ||||
| 
 | ||||
|     HeightProfileSmoothingParams() : radius(5), keep_min(false) {} | ||||
|     HeightProfileSmoothingParams(unsigned int radius, bool keep_min) : radius(radius), keep_min(keep_min) {} | ||||
| }; | ||||
| 
 | ||||
| extern std::vector<double> smooth_height_profile( | ||||
|     const std::vector<double>& profile, const SlicingParameters& slicing_params, | ||||
|     const HeightProfileSmoothingParams& smoothing_params); | ||||
| #else | ||||
| extern std::vector<coordf_t> layer_height_profile_adaptive( | ||||
|     const SlicingParameters     &slicing_params, | ||||
|     const t_layer_config_ranges &layer_config_ranges, | ||||
|     const ModelVolumePtrs       &volumes); | ||||
| 
 | ||||
| #endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
 | ||||
| 
 | ||||
| enum LayerHeightEditActionType : unsigned int { | ||||
|     LAYER_HEIGHT_EDIT_ACTION_INCREASE = 0, | ||||
|  |  | |||
|  | @ -1,16 +1,22 @@ | |||
| #include "libslic3r.h" | ||||
| #if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE | ||||
| #include "Model.hpp" | ||||
| #else | ||||
| #include "TriangleMesh.hpp" | ||||
| #endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
 | ||||
| #include "SlicingAdaptive.hpp" | ||||
| 
 | ||||
| namespace Slic3r | ||||
| { | ||||
| 
 | ||||
| #if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE | ||||
| void SlicingAdaptive::clear() | ||||
| { | ||||
| 	m_meshes.clear(); | ||||
|     m_meshes.clear(); | ||||
| 	m_faces.clear(); | ||||
| 	m_face_normal_z.clear(); | ||||
| } | ||||
| #endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
 | ||||
| 
 | ||||
| std::pair<float, float> face_z_span(const stl_facet *f) | ||||
| { | ||||
|  | @ -21,21 +27,42 @@ std::pair<float, float> face_z_span(const stl_facet *f) | |||
| 
 | ||||
| void SlicingAdaptive::prepare() | ||||
| { | ||||
| 	// 1) Collect faces of all meshes.
 | ||||
| 	int nfaces_total = 0; | ||||
| 	for (std::vector<const TriangleMesh*>::const_iterator it_mesh = m_meshes.begin(); it_mesh != m_meshes.end(); ++ it_mesh) | ||||
| #if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE | ||||
|     if (m_object == nullptr) | ||||
|         return; | ||||
| 
 | ||||
|     m_faces.clear(); | ||||
|     m_face_normal_z.clear(); | ||||
| 
 | ||||
|     m_mesh = m_object->raw_mesh(); | ||||
|     const ModelInstance* first_instance = m_object->instances.front(); | ||||
|     m_mesh.transform(first_instance->get_matrix(), first_instance->is_left_handed()); | ||||
|     for (stl_facet& facet : m_mesh.stl.facet_start) | ||||
|     { | ||||
|         facet.normal.normalize(); | ||||
|     } | ||||
| 
 | ||||
|     // 1) Collect faces from mesh.
 | ||||
|     m_faces.reserve(m_mesh.stl.stats.number_of_facets); | ||||
|     for (const stl_facet& face : m_mesh.stl.facet_start) | ||||
|         m_faces.emplace_back(&face); | ||||
| #else | ||||
|     // 1) Collect faces of all meshes.
 | ||||
|     int nfaces_total = 0; | ||||
|     for (std::vector<const TriangleMesh*>::const_iterator it_mesh = m_meshes.begin(); it_mesh != m_meshes.end(); ++ it_mesh) | ||||
| 		nfaces_total += (*it_mesh)->stl.stats.number_of_facets; | ||||
| 	m_faces.reserve(nfaces_total); | ||||
| 	for (std::vector<const TriangleMesh*>::const_iterator it_mesh = m_meshes.begin(); it_mesh != m_meshes.end(); ++ it_mesh) | ||||
| 		for (const stl_facet &face : (*it_mesh)->stl.facet_start) | ||||
| 			m_faces.emplace_back(&face); | ||||
|     m_faces.reserve(nfaces_total); | ||||
|     for (std::vector<const TriangleMesh*>::const_iterator it_mesh = m_meshes.begin(); it_mesh != m_meshes.end(); ++ it_mesh) | ||||
|         for (const stl_facet& face : (*it_mesh)->stl.facet_start) | ||||
|             m_faces.emplace_back(&face); | ||||
| #endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
 | ||||
| 
 | ||||
| 	// 2) Sort faces lexicographically by their Z span.
 | ||||
| 	std::sort(m_faces.begin(), m_faces.end(), [](const stl_facet *f1, const stl_facet *f2) { | ||||
| 		std::pair<float, float> span1 = face_z_span(f1); | ||||
|         std::pair<float, float> span1 = face_z_span(f1); | ||||
| 		std::pair<float, float> span2 = face_z_span(f2); | ||||
| 		return span1 < span2; | ||||
| 	}); | ||||
|         return span1 < span2; | ||||
|     }); | ||||
| 
 | ||||
| 	// 3) Generate Z components of the facet normals.
 | ||||
| 	m_face_normal_z.assign(m_faces.size(), 0.f); | ||||
|  | @ -45,14 +72,14 @@ void SlicingAdaptive::prepare() | |||
| 
 | ||||
| float SlicingAdaptive::cusp_height(float z, float cusp_value, int ¤t_facet) | ||||
| { | ||||
| 	float height = m_slicing_params.max_layer_height; | ||||
| 	float height = (float)m_slicing_params.max_layer_height; | ||||
| 	bool first_hit = false; | ||||
| 	 | ||||
| 	// find all facets intersecting the slice-layer
 | ||||
| 	int ordered_id = current_facet; | ||||
| 	for (; ordered_id < int(m_faces.size()); ++ ordered_id) { | ||||
| 		std::pair<float, float> zspan = face_z_span(m_faces[ordered_id]); | ||||
| 		// facet's minimum is higher than slice_z -> end loop
 | ||||
|         std::pair<float, float> zspan = face_z_span(m_faces[ordered_id]); | ||||
|         // facet's minimum is higher than slice_z -> end loop
 | ||||
| 		if (zspan.first >= z) | ||||
| 			break; | ||||
| 		// facet's maximum is higher than slice_z -> store the first event for next cusp_height call to begin at this point
 | ||||
|  | @ -77,8 +104,8 @@ float SlicingAdaptive::cusp_height(float z, float cusp_value, int ¤t_facet | |||
| 	// check for sloped facets inside the determined layer and correct height if necessary
 | ||||
| 	if (height > m_slicing_params.min_layer_height) { | ||||
| 		for (; ordered_id < int(m_faces.size()); ++ ordered_id) { | ||||
| 			std::pair<float, float> zspan = face_z_span(m_faces[ordered_id]); | ||||
| 			// facet's minimum is higher than slice_z + height -> end loop
 | ||||
|             std::pair<float, float> zspan = face_z_span(m_faces[ordered_id]); | ||||
|             // facet's minimum is higher than slice_z + height -> end loop
 | ||||
| 			if (zspan.first >= z + height) | ||||
| 				break; | ||||
| 
 | ||||
|  | @ -117,24 +144,25 @@ float SlicingAdaptive::cusp_height(float z, float cusp_value, int ¤t_facet | |||
| 	return height;  | ||||
| } | ||||
| 
 | ||||
| #if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE | ||||
| // Returns the distance to the next horizontal facet in Z-dir 
 | ||||
| // to consider horizontal object features in slice thickness
 | ||||
| float SlicingAdaptive::horizontal_facet_distance(float z) | ||||
| { | ||||
| 	for (size_t i = 0; i < m_faces.size(); ++ i) { | ||||
| 		std::pair<float, float> zspan = face_z_span(m_faces[i]); | ||||
| 		// facet's minimum is higher than max forward distance -> end loop
 | ||||
|         std::pair<float, float> zspan = face_z_span(m_faces[i]); | ||||
|         // facet's minimum is higher than max forward distance -> end loop
 | ||||
| 		if (zspan.first > z + m_slicing_params.max_layer_height) | ||||
| 			break; | ||||
| 		// min_z == max_z -> horizontal facet
 | ||||
| 		if (zspan.first > z && zspan.first == zspan.second) | ||||
| 		if ((zspan.first > z) && (zspan.first == zspan.second)) | ||||
| 			return zspan.first - z; | ||||
| 	} | ||||
| 	 | ||||
| 	// objects maximum?
 | ||||
| 	return (z + m_slicing_params.max_layer_height > m_slicing_params.object_print_z_height()) ?  | ||||
| 		std::max<float>(m_slicing_params.object_print_z_height() - z, 0.f) : | ||||
| 		m_slicing_params.max_layer_height; | ||||
| 	return (z + (float)m_slicing_params.max_layer_height > (float)m_slicing_params.object_print_z_height()) ?  | ||||
| 		std::max((float)m_slicing_params.object_print_z_height() - z, 0.f) : (float)m_slicing_params.max_layer_height; | ||||
| } | ||||
| #endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
 | ||||
| 
 | ||||
| }; // namespace Slic3r
 | ||||
|  |  | |||
|  | @ -5,29 +5,49 @@ | |||
| 
 | ||||
| #include "Slicing.hpp" | ||||
| #include "admesh/stl.h" | ||||
| #if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE | ||||
| #include "TriangleMesh.hpp" | ||||
| #endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
 | ||||
| 
 | ||||
| namespace Slic3r | ||||
| { | ||||
| 
 | ||||
| #if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE | ||||
| class ModelVolume; | ||||
| #else | ||||
| class TriangleMesh; | ||||
| #endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
 | ||||
| 
 | ||||
| class SlicingAdaptive | ||||
| { | ||||
| public: | ||||
| 	void clear(); | ||||
| 	void set_slicing_parameters(SlicingParameters params) { m_slicing_params = params; } | ||||
| 	void add_mesh(const TriangleMesh *mesh) { m_meshes.push_back(mesh); } | ||||
| 	void prepare(); | ||||
| #if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE | ||||
|     void clear(); | ||||
| #endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
 | ||||
|     void set_slicing_parameters(SlicingParameters params) { m_slicing_params = params; } | ||||
| #if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE | ||||
|     void set_object(const ModelObject& object) { m_object = &object; } | ||||
| #else | ||||
|     void add_mesh(const TriangleMesh* mesh) { m_meshes.push_back(mesh); } | ||||
| #endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
 | ||||
|     void prepare(); | ||||
| 	float cusp_height(float z, float cusp_value, int ¤t_facet); | ||||
| 	float horizontal_facet_distance(float z); | ||||
| #if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE | ||||
|     float horizontal_facet_distance(float z); | ||||
| #endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
 | ||||
| 
 | ||||
| protected: | ||||
| 	SlicingParameters 					m_slicing_params; | ||||
| 
 | ||||
| 	std::vector<const TriangleMesh*>	m_meshes; | ||||
| 	// Collected faces of all meshes, sorted by raising Z of the bottom most face.
 | ||||
| #if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE | ||||
|     const ModelObject*                  m_object; | ||||
|     TriangleMesh                        m_mesh; | ||||
| #else | ||||
|     std::vector<const TriangleMesh*>	m_meshes; | ||||
| #endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
 | ||||
|     // Collected faces of all meshes, sorted by raising Z of the bottom most face.
 | ||||
| 	std::vector<const stl_facet*>		m_faces; | ||||
| 	// Z component of face normals, normalized.
 | ||||
|     // Z component of face normals, normalized.
 | ||||
| 	std::vector<float>					m_face_normal_z; | ||||
| }; | ||||
| 
 | ||||
|  |  | |||
|  | @ -42,4 +42,7 @@ | |||
| #define ENABLE_THUMBNAIL_GENERATOR_DEBUG (0 && ENABLE_THUMBNAIL_GENERATOR) | ||||
| #define ENABLE_THUMBNAIL_GENERATOR_PNG_TO_GCODE (1 && ENABLE_THUMBNAIL_GENERATOR) | ||||
| 
 | ||||
| // Enable adaptive layer height profile
 | ||||
| #define ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE (1 && ENABLE_2_2_0_ALPHA1) | ||||
| 
 | ||||
| #endif // _technologies_h_
 | ||||
|  |  | |||
|  | @ -20,9 +20,6 @@ | |||
| #include "libslic3r/Utils.hpp" | ||||
| #include "libslic3r/GCode/PostProcessor.hpp" | ||||
| #include "libslic3r/GCode/PreviewData.hpp" | ||||
| #if ENABLE_THUMBNAIL_GENERATOR | ||||
| #include "libslic3r/GCode/ThumbnailData.hpp" | ||||
| #endif // ENABLE_THUMBNAIL_GENERATOR
 | ||||
| #include "libslic3r/libslic3r.h" | ||||
| 
 | ||||
| #include <cassert> | ||||
|  | @ -91,7 +88,7 @@ void BackgroundSlicingProcess::process_fff() | |||
|     m_print->process(); | ||||
| 	wxQueueEvent(GUI::wxGetApp().mainframe->m_plater, new wxCommandEvent(m_event_slicing_completed_id)); | ||||
| #if ENABLE_THUMBNAIL_GENERATOR | ||||
|     m_fff_print->export_gcode(m_temp_output_path, m_gcode_preview_data, m_thumbnail_data); | ||||
|     m_fff_print->export_gcode(m_temp_output_path, m_gcode_preview_data, m_thumbnail_cb); | ||||
| #else | ||||
|     m_fff_print->export_gcode(m_temp_output_path, m_gcode_preview_data); | ||||
| #endif // ENABLE_THUMBNAIL_GENERATOR
 | ||||
|  | @ -139,9 +136,12 @@ void BackgroundSlicingProcess::process_sla() | |||
|             m_sla_print->export_raster(zipper); | ||||
| 
 | ||||
| #if ENABLE_THUMBNAIL_GENERATOR | ||||
|             if (m_thumbnail_data != nullptr) | ||||
|             if (m_thumbnail_cb != nullptr) | ||||
|             { | ||||
|                 for (const ThumbnailData& data : *m_thumbnail_data) | ||||
|                 ThumbnailsList thumbnails; | ||||
|                 m_thumbnail_cb(thumbnails, current_print()->full_print_config().option<ConfigOptionPoints>("thumbnails")->values, true, true, false); | ||||
| //                m_thumbnail_cb(thumbnails, current_print()->full_print_config().option<ConfigOptionPoints>("thumbnails")->values, true, false, false); // renders also supports and pad
 | ||||
|                 for (const ThumbnailData& data : thumbnails) | ||||
|                 { | ||||
|                     if (data.is_valid()) | ||||
|                         write_thumbnail(zipper, data); | ||||
|  | @ -461,9 +461,12 @@ void BackgroundSlicingProcess::prepare_upload() | |||
|         Zipper zipper{source_path.string()}; | ||||
|         m_sla_print->export_raster(zipper, m_upload_job.upload_data.upload_path.string()); | ||||
| #if ENABLE_THUMBNAIL_GENERATOR | ||||
|         if (m_thumbnail_data != nullptr) | ||||
|         if (m_thumbnail_cb != nullptr) | ||||
|         { | ||||
|             for (const ThumbnailData& data : *m_thumbnail_data) | ||||
|             ThumbnailsList thumbnails; | ||||
|             m_thumbnail_cb(thumbnails, current_print()->full_print_config().option<ConfigOptionPoints>("thumbnails")->values, true, true, false); | ||||
| //            m_thumbnail_cb(thumbnails, current_print()->full_print_config().option<ConfigOptionPoints>("thumbnails")->values, true, false, false); // renders also supports and pad
 | ||||
|             for (const ThumbnailData& data : thumbnails) | ||||
|             { | ||||
|                 if (data.is_valid()) | ||||
|                     write_thumbnail(zipper, data); | ||||
|  |  | |||
|  | @ -17,9 +17,6 @@ namespace Slic3r { | |||
| 
 | ||||
| class DynamicPrintConfig; | ||||
| class GCodePreviewData; | ||||
| #if ENABLE_THUMBNAIL_GENERATOR | ||||
| struct ThumbnailData; | ||||
| #endif // ENABLE_THUMBNAIL_GENERATOR
 | ||||
| class Model; | ||||
| class SLAPrint; | ||||
| 
 | ||||
|  | @ -53,7 +50,7 @@ public: | |||
| 	void set_sla_print(SLAPrint *print) { m_sla_print = print; } | ||||
| 	void set_gcode_preview_data(GCodePreviewData *gpd) { m_gcode_preview_data = gpd; } | ||||
| #if ENABLE_THUMBNAIL_GENERATOR | ||||
|     void set_thumbnail_data(const std::vector<ThumbnailData>* data) { m_thumbnail_data = data; } | ||||
|     void set_thumbnail_cb(ThumbnailsGeneratorCallback cb) { m_thumbnail_cb = cb; } | ||||
| #endif // ENABLE_THUMBNAIL_GENERATOR
 | ||||
| 
 | ||||
| 	// The following wxCommandEvent will be sent to the UI thread / Platter window, when the slicing is finished
 | ||||
|  | @ -159,8 +156,8 @@ private: | |||
| 	// Data structure, to which the G-code export writes its annotations.
 | ||||
| 	GCodePreviewData 		   *m_gcode_preview_data = nullptr; | ||||
| #if ENABLE_THUMBNAIL_GENERATOR | ||||
|     // Data structures, used to write thumbnails into gcode.
 | ||||
|     const std::vector<ThumbnailData>* m_thumbnail_data = nullptr; | ||||
|     // Callback function, used to write thumbnails into gcode.
 | ||||
|     ThumbnailsGeneratorCallback m_thumbnail_cb = nullptr; | ||||
| #endif // ENABLE_THUMBNAIL_GENERATOR
 | ||||
| 	// Temporary G-code, there is one defined for the BackgroundSlicingProcess, differentiated from the other processes by a process ID.
 | ||||
| 	std::string 				m_temp_output_path; | ||||
|  |  | |||
|  | @ -131,6 +131,9 @@ GLCanvas3D::LayersEditing::LayersEditing() | |||
|     , m_object_max_z(0.f) | ||||
|     , m_slicing_parameters(nullptr) | ||||
|     , m_layer_height_profile_modified(false) | ||||
| #if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE | ||||
|     , m_adaptive_cusp(0.2f) | ||||
| #endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
 | ||||
|     , state(Unknown) | ||||
|     , band_width(2.0f) | ||||
|     , strength(0.005f) | ||||
|  | @ -151,7 +154,9 @@ GLCanvas3D::LayersEditing::~LayersEditing() | |||
| } | ||||
| 
 | ||||
| const float GLCanvas3D::LayersEditing::THICKNESS_BAR_WIDTH = 70.0f; | ||||
| #if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE | ||||
| const float GLCanvas3D::LayersEditing::THICKNESS_RESET_BUTTON_HEIGHT = 22.0f; | ||||
| #endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
 | ||||
| 
 | ||||
| bool GLCanvas3D::LayersEditing::init(const std::string& vertex_shader_filename, const std::string& fragment_shader_filename) | ||||
| { | ||||
|  | @ -218,13 +223,103 @@ void GLCanvas3D::LayersEditing::render_overlay(const GLCanvas3D& canvas) const | |||
|     if (!m_enabled) | ||||
|         return; | ||||
| 
 | ||||
| #if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE | ||||
|     static const ImVec4 orange(0.757f, 0.404f, 0.216f, 1.0f); | ||||
| 
 | ||||
|     const Size& cnv_size = canvas.get_canvas_size(); | ||||
|     float canvas_w = (float)cnv_size.get_width(); | ||||
|     float canvas_h = (float)cnv_size.get_height(); | ||||
| 
 | ||||
|     ImGuiWrapper& imgui = *wxGetApp().imgui(); | ||||
|     imgui.set_next_window_pos(canvas_w - imgui.get_style_scaling() * THICKNESS_BAR_WIDTH, canvas_h, ImGuiCond_Always, 1.0f, 1.0f); | ||||
|     imgui.set_next_window_bg_alpha(0.5f); | ||||
| 
 | ||||
|     ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f); | ||||
| 
 | ||||
|     imgui.begin(_(L("Layer height profile")), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse); | ||||
| 
 | ||||
|     ImGui::PushStyleColor(ImGuiCol_Text, orange); | ||||
|     imgui.text(_(L("Left mouse button:"))); | ||||
|     ImGui::PopStyleColor(); | ||||
|     ImGui::SameLine(); | ||||
|     imgui.text(_(L("Add detail"))); | ||||
| 
 | ||||
|     ImGui::PushStyleColor(ImGuiCol_Text, orange); | ||||
|     imgui.text(_(L("Right mouse button:"))); | ||||
|     ImGui::PopStyleColor(); | ||||
|     ImGui::SameLine(); | ||||
|     imgui.text(_(L("Remove detail"))); | ||||
| 
 | ||||
|     ImGui::PushStyleColor(ImGuiCol_Text, orange); | ||||
|     imgui.text(_(L("Shift + Left mouse button:"))); | ||||
|     ImGui::PopStyleColor(); | ||||
|     ImGui::SameLine(); | ||||
|     imgui.text(_(L("Reset to base"))); | ||||
| 
 | ||||
|     ImGui::PushStyleColor(ImGuiCol_Text, orange); | ||||
|     imgui.text(_(L("Shift + Right mouse button:"))); | ||||
|     ImGui::PopStyleColor(); | ||||
|     ImGui::SameLine(); | ||||
|     imgui.text(_(L("Smoothing"))); | ||||
| 
 | ||||
|     ImGui::PushStyleColor(ImGuiCol_Text, orange); | ||||
|     imgui.text(_(L("Mouse wheel:"))); | ||||
|     ImGui::PopStyleColor(); | ||||
|     ImGui::SameLine(); | ||||
|     imgui.text(_(L("Increase/decrease edit area"))); | ||||
|      | ||||
|     ImGui::Separator(); | ||||
|     if (imgui.button(_(L("Adaptive")))) | ||||
|         wxPostEvent((wxEvtHandler*)canvas.get_wxglcanvas(), Event<float>(EVT_GLCANVAS_ADAPTIVE_LAYER_HEIGHT_PROFILE, m_adaptive_cusp)); | ||||
| 
 | ||||
|     ImGui::SameLine(); | ||||
|     float text_align = ImGui::GetCursorPosX(); | ||||
|     imgui.text(_(L("Cusp (mm)"))); | ||||
|     ImGui::SameLine(); | ||||
|     float widget_align = ImGui::GetCursorPosX(); | ||||
|     ImGui::PushItemWidth(120.0f); | ||||
|     m_adaptive_cusp = std::min(m_adaptive_cusp, (float)m_slicing_parameters->max_layer_height); | ||||
|     ImGui::SliderFloat("", &m_adaptive_cusp, 0.0f, (float)m_slicing_parameters->max_layer_height, "%.2f"); | ||||
| 
 | ||||
|     ImGui::Separator(); | ||||
|     if (imgui.button(_(L("Smooth")))) | ||||
|         wxPostEvent((wxEvtHandler*)canvas.get_wxglcanvas(), HeightProfileSmoothEvent(EVT_GLCANVAS_SMOOTH_LAYER_HEIGHT_PROFILE, m_smooth_params )); | ||||
| 
 | ||||
|     ImGui::SameLine(); | ||||
|     ImGui::SetCursorPosX(text_align); | ||||
|     imgui.text(_(L("Radius"))); | ||||
|     ImGui::SameLine(); | ||||
|     ImGui::PushItemWidth(120.0f); | ||||
|     ImGui::SetCursorPosX(widget_align); | ||||
|     int radius = (int)m_smooth_params.radius; | ||||
|     if (ImGui::SliderInt("##1", &radius, 1, 10)) | ||||
|         m_smooth_params.radius = (unsigned int)radius; | ||||
| 
 | ||||
|     ImGui::SetCursorPosX(text_align); | ||||
|     imgui.text(_(L("Keep min"))); | ||||
|     ImGui::SameLine(); | ||||
|     ImGui::PushItemWidth(120.0f); | ||||
|     ImGui::SetCursorPosX(widget_align); | ||||
|     imgui.checkbox("##2", m_smooth_params.keep_min); | ||||
| 
 | ||||
|     ImGui::Separator(); | ||||
|     if (imgui.button(_(L("Reset")))) | ||||
|         wxPostEvent((wxEvtHandler*)canvas.get_wxglcanvas(), SimpleEvent(EVT_GLCANVAS_RESET_LAYER_HEIGHT_PROFILE)); | ||||
| 
 | ||||
|     imgui.end(); | ||||
| 
 | ||||
|     ImGui::PopStyleVar(); | ||||
| 
 | ||||
|     const Rect& bar_rect = get_bar_rect_viewport(canvas); | ||||
| #else | ||||
|     const Rect& bar_rect = get_bar_rect_viewport(canvas); | ||||
|     const Rect& reset_rect = get_reset_rect_viewport(canvas); | ||||
| 
 | ||||
|     _render_tooltip_texture(canvas, bar_rect, reset_rect); | ||||
|     _render_reset_texture(reset_rect); | ||||
|     _render_active_object_annotations(canvas, bar_rect); | ||||
|     _render_profile(bar_rect); | ||||
| #endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
 | ||||
|     render_active_object_annotations(canvas, bar_rect); | ||||
|     render_profile(bar_rect); | ||||
| } | ||||
| 
 | ||||
| float GLCanvas3D::LayersEditing::get_cursor_z_relative(const GLCanvas3D& canvas) | ||||
|  | @ -249,11 +344,13 @@ bool GLCanvas3D::LayersEditing::bar_rect_contains(const GLCanvas3D& canvas, floa | |||
|     return (rect.get_left() <= x) && (x <= rect.get_right()) && (rect.get_top() <= y) && (y <= rect.get_bottom()); | ||||
| } | ||||
| 
 | ||||
| #if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE | ||||
| bool GLCanvas3D::LayersEditing::reset_rect_contains(const GLCanvas3D& canvas, float x, float y) | ||||
| { | ||||
|     const Rect& rect = get_reset_rect_screen(canvas); | ||||
|     return (rect.get_left() <= x) && (x <= rect.get_right()) && (rect.get_top() <= y) && (y <= rect.get_bottom()); | ||||
| } | ||||
| #endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
 | ||||
| 
 | ||||
| Rect GLCanvas3D::LayersEditing::get_bar_rect_screen(const GLCanvas3D& canvas) | ||||
| { | ||||
|  | @ -261,9 +358,14 @@ Rect GLCanvas3D::LayersEditing::get_bar_rect_screen(const GLCanvas3D& canvas) | |||
|     float w = (float)cnv_size.get_width(); | ||||
|     float h = (float)cnv_size.get_height(); | ||||
| 
 | ||||
| #if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE | ||||
|     return Rect(w - thickness_bar_width(canvas), 0.0f, w, h); | ||||
| #else | ||||
|     return Rect(w - thickness_bar_width(canvas), 0.0f, w, h - reset_button_height(canvas)); | ||||
| #endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
 | ||||
| } | ||||
| 
 | ||||
| #if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE | ||||
| Rect GLCanvas3D::LayersEditing::get_reset_rect_screen(const GLCanvas3D& canvas) | ||||
| { | ||||
|     const Size& cnv_size = canvas.get_canvas_size(); | ||||
|  | @ -272,6 +374,7 @@ Rect GLCanvas3D::LayersEditing::get_reset_rect_screen(const GLCanvas3D& canvas) | |||
| 
 | ||||
|     return Rect(w - thickness_bar_width(canvas), h - reset_button_height(canvas), w, h); | ||||
| } | ||||
| #endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
 | ||||
| 
 | ||||
| Rect GLCanvas3D::LayersEditing::get_bar_rect_viewport(const GLCanvas3D& canvas) | ||||
| { | ||||
|  | @ -282,9 +385,14 @@ Rect GLCanvas3D::LayersEditing::get_bar_rect_viewport(const GLCanvas3D& canvas) | |||
|     float zoom = (float)canvas.get_camera().get_zoom(); | ||||
|     float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f; | ||||
| 
 | ||||
| #if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE | ||||
|     return Rect((half_w - thickness_bar_width(canvas)) * inv_zoom, half_h * inv_zoom, half_w * inv_zoom, -half_h * inv_zoom); | ||||
| #else | ||||
|     return Rect((half_w - thickness_bar_width(canvas)) * inv_zoom, half_h * inv_zoom, half_w * inv_zoom, (-half_h + reset_button_height(canvas)) * inv_zoom); | ||||
| #endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
 | ||||
| } | ||||
| 
 | ||||
| #if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE | ||||
| Rect GLCanvas3D::LayersEditing::get_reset_rect_viewport(const GLCanvas3D& canvas) | ||||
| { | ||||
|     const Size& cnv_size = canvas.get_canvas_size(); | ||||
|  | @ -296,13 +404,14 @@ Rect GLCanvas3D::LayersEditing::get_reset_rect_viewport(const GLCanvas3D& canvas | |||
| 
 | ||||
|     return Rect((half_w - thickness_bar_width(canvas)) * inv_zoom, (-half_h + reset_button_height(canvas)) * inv_zoom, half_w * inv_zoom, -half_h * inv_zoom); | ||||
| } | ||||
| #endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
 | ||||
| 
 | ||||
| 
 | ||||
| bool GLCanvas3D::LayersEditing::_is_initialized() const | ||||
| bool GLCanvas3D::LayersEditing::is_initialized() const | ||||
| { | ||||
|     return m_shader.is_initialized(); | ||||
| } | ||||
| 
 | ||||
| #if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE | ||||
| void GLCanvas3D::LayersEditing::_render_tooltip_texture(const GLCanvas3D& canvas, const Rect& bar_rect, const Rect& reset_rect) const | ||||
| { | ||||
|     // TODO: do this with ImGui
 | ||||
|  | @ -348,8 +457,9 @@ void GLCanvas3D::LayersEditing::_render_reset_texture(const Rect& reset_rect) co | |||
| 
 | ||||
|     GLTexture::render_texture(m_reset_texture.get_id(), reset_rect.get_left(), reset_rect.get_right(), reset_rect.get_bottom(), reset_rect.get_top()); | ||||
| } | ||||
| #endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
 | ||||
| 
 | ||||
| void GLCanvas3D::LayersEditing::_render_active_object_annotations(const GLCanvas3D& canvas, const Rect& bar_rect) const | ||||
| void GLCanvas3D::LayersEditing::render_active_object_annotations(const GLCanvas3D& canvas, const Rect& bar_rect) const | ||||
| { | ||||
|     m_shader.start_using(); | ||||
| 
 | ||||
|  | @ -380,7 +490,7 @@ void GLCanvas3D::LayersEditing::_render_active_object_annotations(const GLCanvas | |||
|     m_shader.stop_using(); | ||||
| } | ||||
| 
 | ||||
| void GLCanvas3D::LayersEditing::_render_profile(const Rect& bar_rect) const | ||||
| void GLCanvas3D::LayersEditing::render_profile(const Rect& bar_rect) const | ||||
| { | ||||
|     //FIXME show some kind of legend.
 | ||||
| 
 | ||||
|  | @ -497,6 +607,24 @@ void GLCanvas3D::LayersEditing::reset_layer_height_profile(GLCanvas3D& canvas) | |||
|     canvas.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS)); | ||||
| } | ||||
| 
 | ||||
| #if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE | ||||
| void GLCanvas3D::LayersEditing::adaptive_layer_height_profile(GLCanvas3D& canvas, float cusp) | ||||
| { | ||||
|     m_layer_height_profile = layer_height_profile_adaptive(*m_slicing_parameters, *m_model_object, cusp); | ||||
|     const_cast<ModelObject*>(m_model_object)->layer_height_profile = m_layer_height_profile; | ||||
|     m_layers_texture.valid = false; | ||||
|     canvas.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS)); | ||||
| } | ||||
| 
 | ||||
| void GLCanvas3D::LayersEditing::smooth_layer_height_profile(GLCanvas3D& canvas, const HeightProfileSmoothingParams& smoothing_params) | ||||
| { | ||||
|     m_layer_height_profile = smooth_height_profile(m_layer_height_profile, *m_slicing_parameters, smoothing_params); | ||||
|     const_cast<ModelObject*>(m_model_object)->layer_height_profile = m_layer_height_profile; | ||||
|     m_layers_texture.valid = false; | ||||
|     canvas.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS)); | ||||
| } | ||||
| #endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
 | ||||
| 
 | ||||
| void GLCanvas3D::LayersEditing::generate_layer_height_texture() | ||||
| { | ||||
| 	this->update_slicing_parameters(); | ||||
|  | @ -558,6 +686,7 @@ float GLCanvas3D::LayersEditing::thickness_bar_width(const GLCanvas3D &canvas) | |||
|          * THICKNESS_BAR_WIDTH; | ||||
| } | ||||
| 
 | ||||
| #if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE | ||||
| float GLCanvas3D::LayersEditing::reset_button_height(const GLCanvas3D &canvas) | ||||
| { | ||||
|     return | ||||
|  | @ -568,6 +697,7 @@ float GLCanvas3D::LayersEditing::reset_button_height(const GLCanvas3D &canvas) | |||
| #endif | ||||
|          * THICKNESS_RESET_BUTTON_HEIGHT; | ||||
| } | ||||
| #endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
 | ||||
| 
 | ||||
| 
 | ||||
| const Point GLCanvas3D::Mouse::Drag::Invalid_2D_Point(INT_MAX, INT_MAX); | ||||
|  | @ -1119,6 +1249,11 @@ wxDEFINE_EVENT(EVT_GLCANVAS_MOVE_DOUBLE_SLIDER, wxKeyEvent); | |||
| wxDEFINE_EVENT(EVT_GLCANVAS_EDIT_COLOR_CHANGE, wxKeyEvent); | ||||
| wxDEFINE_EVENT(EVT_GLCANVAS_UNDO, SimpleEvent); | ||||
| wxDEFINE_EVENT(EVT_GLCANVAS_REDO, SimpleEvent); | ||||
| #if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE | ||||
| wxDEFINE_EVENT(EVT_GLCANVAS_RESET_LAYER_HEIGHT_PROFILE, SimpleEvent); | ||||
| wxDEFINE_EVENT(EVT_GLCANVAS_ADAPTIVE_LAYER_HEIGHT_PROFILE, Event<float>); | ||||
| wxDEFINE_EVENT(EVT_GLCANVAS_SMOOTH_LAYER_HEIGHT_PROFILE, HeightProfileSmoothEvent); | ||||
| #endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
 | ||||
| 
 | ||||
| #if ENABLE_THUMBNAIL_GENERATOR | ||||
| const double GLCanvas3D::DefaultCameraZoomToBoxMarginFactor = 1.25; | ||||
|  | @ -1421,6 +1556,29 @@ bool GLCanvas3D::is_layers_editing_allowed() const | |||
|     return m_layers_editing.is_allowed(); | ||||
| } | ||||
| 
 | ||||
| #if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE | ||||
| void GLCanvas3D::reset_layer_height_profile() | ||||
| { | ||||
|     m_layers_editing.reset_layer_height_profile(*this); | ||||
|     m_layers_editing.state = LayersEditing::Completed; | ||||
|     m_dirty = true; | ||||
| } | ||||
| 
 | ||||
| void GLCanvas3D::adaptive_layer_height_profile(float cusp) | ||||
| { | ||||
|     m_layers_editing.adaptive_layer_height_profile(*this, cusp); | ||||
|     m_layers_editing.state = LayersEditing::Completed; | ||||
|     m_dirty = true; | ||||
| } | ||||
| 
 | ||||
| void GLCanvas3D::smooth_layer_height_profile(const HeightProfileSmoothingParams& smoothing_params) | ||||
| { | ||||
|     m_layers_editing.smooth_layer_height_profile(*this, smoothing_params); | ||||
|     m_layers_editing.state = LayersEditing::Completed; | ||||
|     m_dirty = true; | ||||
| } | ||||
| #endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
 | ||||
| 
 | ||||
| bool GLCanvas3D::is_reload_delayed() const | ||||
| { | ||||
|     return m_reload_delayed; | ||||
|  | @ -2830,6 +2988,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) | |||
|             m_layers_editing.state = LayersEditing::Editing; | ||||
|             _perform_layer_editing_action(&evt); | ||||
|         } | ||||
| #if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE | ||||
|         else if ((layer_editing_object_idx != -1) && m_layers_editing.reset_rect_contains(*this, pos(0), pos(1))) | ||||
|         { | ||||
|             if (evt.LeftDown()) | ||||
|  | @ -2842,6 +3001,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) | |||
|                 m_dirty = true; | ||||
|             } | ||||
|         } | ||||
| #endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
 | ||||
|         else if (evt.LeftDown() && (evt.ShiftDown() || evt.AltDown()) && m_picking_enabled) | ||||
|         { | ||||
|             if (m_gizmos.get_current_type() != GLGizmosManager::SlaSupports) | ||||
|  |  | |||
|  | @ -81,6 +81,8 @@ template <size_t N> using Vec2dsEvent = ArrayEvent<Vec2d, N>; | |||
| using Vec3dEvent = Event<Vec3d>; | ||||
| template <size_t N> using Vec3dsEvent = ArrayEvent<Vec3d, N>; | ||||
| 
 | ||||
| using HeightProfileSmoothEvent = Event<HeightProfileSmoothingParams>; | ||||
| 
 | ||||
| wxDECLARE_EVENT(EVT_GLCANVAS_INIT, SimpleEvent); | ||||
| wxDECLARE_EVENT(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS, SimpleEvent); | ||||
| wxDECLARE_EVENT(EVT_GLCANVAS_RIGHT_CLICK, RBtnEvent); | ||||
|  | @ -104,6 +106,11 @@ wxDECLARE_EVENT(EVT_GLCANVAS_MOVE_DOUBLE_SLIDER, wxKeyEvent); | |||
| wxDECLARE_EVENT(EVT_GLCANVAS_EDIT_COLOR_CHANGE, wxKeyEvent); | ||||
| wxDECLARE_EVENT(EVT_GLCANVAS_UNDO, SimpleEvent); | ||||
| wxDECLARE_EVENT(EVT_GLCANVAS_REDO, SimpleEvent); | ||||
| #if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE | ||||
| wxDECLARE_EVENT(EVT_GLCANVAS_RESET_LAYER_HEIGHT_PROFILE, SimpleEvent); | ||||
| wxDECLARE_EVENT(EVT_GLCANVAS_ADAPTIVE_LAYER_HEIGHT_PROFILE, Event<float>); | ||||
| wxDECLARE_EVENT(EVT_GLCANVAS_SMOOTH_LAYER_HEIGHT_PROFILE, HeightProfileSmoothEvent); | ||||
| #endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
 | ||||
| 
 | ||||
| class GLCanvas3D | ||||
| { | ||||
|  | @ -153,13 +160,17 @@ private: | |||
| 
 | ||||
|     private: | ||||
|         static const float THICKNESS_BAR_WIDTH; | ||||
| #if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE | ||||
|         static const float THICKNESS_RESET_BUTTON_HEIGHT; | ||||
| #endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
 | ||||
| 
 | ||||
|         bool                        m_enabled; | ||||
|         Shader                      m_shader; | ||||
|         unsigned int                m_z_texture_id; | ||||
| #if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE | ||||
|         mutable GLTexture           m_tooltip_texture; | ||||
|         mutable GLTexture           m_reset_texture; | ||||
| #endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
 | ||||
|         // Not owned by LayersEditing.
 | ||||
|         const DynamicPrintConfig   *m_config; | ||||
|         // ModelObject for the currently selected object (Model::objects[last_object_id]).
 | ||||
|  | @ -171,6 +182,11 @@ private: | |||
|         std::vector<coordf_t>       m_layer_height_profile; | ||||
|         bool                        m_layer_height_profile_modified; | ||||
| 
 | ||||
| #if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE | ||||
|         mutable float               m_adaptive_cusp; | ||||
|         mutable HeightProfileSmoothingParams m_smooth_params; | ||||
| #endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
 | ||||
| 
 | ||||
|         class LayersTexture | ||||
|         { | ||||
|         public: | ||||
|  | @ -217,28 +233,42 @@ private: | |||
| 		void adjust_layer_height_profile(); | ||||
| 		void accept_changes(GLCanvas3D& canvas); | ||||
|         void reset_layer_height_profile(GLCanvas3D& canvas); | ||||
| #if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE | ||||
|         void adaptive_layer_height_profile(GLCanvas3D& canvas, float cusp); | ||||
|         void smooth_layer_height_profile(GLCanvas3D& canvas, const HeightProfileSmoothingParams& smoothing_paramsn); | ||||
| #endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
 | ||||
| 
 | ||||
|         static float get_cursor_z_relative(const GLCanvas3D& canvas); | ||||
|         static bool bar_rect_contains(const GLCanvas3D& canvas, float x, float y); | ||||
| #if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE | ||||
|         static bool reset_rect_contains(const GLCanvas3D& canvas, float x, float y); | ||||
| #endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
 | ||||
|         static Rect get_bar_rect_screen(const GLCanvas3D& canvas); | ||||
| #if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE | ||||
|         static Rect get_reset_rect_screen(const GLCanvas3D& canvas); | ||||
| #endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
 | ||||
|         static Rect get_bar_rect_viewport(const GLCanvas3D& canvas); | ||||
| #if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE | ||||
|         static Rect get_reset_rect_viewport(const GLCanvas3D& canvas); | ||||
| #endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
 | ||||
| 
 | ||||
|         float object_max_z() const { return m_object_max_z; } | ||||
| 
 | ||||
|     private: | ||||
|         bool _is_initialized() const; | ||||
|         bool is_initialized() const; | ||||
|         void generate_layer_height_texture(); | ||||
| #if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE | ||||
|         void _render_tooltip_texture(const GLCanvas3D& canvas, const Rect& bar_rect, const Rect& reset_rect) const; | ||||
|         void _render_reset_texture(const Rect& reset_rect) const; | ||||
|         void _render_active_object_annotations(const GLCanvas3D& canvas, const Rect& bar_rect) const; | ||||
|         void _render_profile(const Rect& bar_rect) const; | ||||
| #endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
 | ||||
|         void render_active_object_annotations(const GLCanvas3D& canvas, const Rect& bar_rect) const; | ||||
|         void render_profile(const Rect& bar_rect) const; | ||||
|         void update_slicing_parameters(); | ||||
| 
 | ||||
|         static float thickness_bar_width(const GLCanvas3D &canvas); | ||||
| #if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE | ||||
|         static float reset_button_height(const GLCanvas3D &canvas); | ||||
| #endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
 | ||||
|     }; | ||||
| 
 | ||||
|     struct Mouse | ||||
|  | @ -501,6 +531,12 @@ public: | |||
|     bool is_layers_editing_enabled() const; | ||||
|     bool is_layers_editing_allowed() const; | ||||
| 
 | ||||
| #if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE | ||||
|     void reset_layer_height_profile(); | ||||
|     void adaptive_layer_height_profile(float cusp); | ||||
|     void smooth_layer_height_profile(const HeightProfileSmoothingParams& smoothing_params); | ||||
| #endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
 | ||||
| 
 | ||||
|     bool is_reload_delayed() const; | ||||
| 
 | ||||
|     void enable_layers_editing(bool enable); | ||||
|  |  | |||
|  | @ -1388,9 +1388,6 @@ struct Plater::priv | |||
|     Slic3r::Model               model; | ||||
|     PrinterTechnology           printer_technology = ptFFF; | ||||
|     Slic3r::GCodePreviewData    gcode_preview_data; | ||||
| #if ENABLE_THUMBNAIL_GENERATOR | ||||
|     std::vector<Slic3r::ThumbnailData> thumbnail_data; | ||||
| #endif // ENABLE_THUMBNAIL_GENERATOR
 | ||||
| 
 | ||||
|     // GUI elements
 | ||||
|     wxSizer* panel_sizer{ nullptr }; | ||||
|  | @ -1948,6 +1945,7 @@ struct Plater::priv | |||
| 
 | ||||
| #if ENABLE_THUMBNAIL_GENERATOR | ||||
|     void generate_thumbnail(ThumbnailData& data, unsigned int w, unsigned int h, bool printable_only, bool parts_only, bool transparent_background); | ||||
|     void generate_thumbnails(ThumbnailsList& thumbnails, const Vec2ds& sizes, bool printable_only, bool parts_only, bool transparent_background); | ||||
| #endif // ENABLE_THUMBNAIL_GENERATOR
 | ||||
| 
 | ||||
|     void msw_rescale_object_menu(); | ||||
|  | @ -2018,7 +2016,15 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) | |||
|     background_process.set_sla_print(&sla_print); | ||||
|     background_process.set_gcode_preview_data(&gcode_preview_data); | ||||
| #if ENABLE_THUMBNAIL_GENERATOR | ||||
|     background_process.set_thumbnail_data(&thumbnail_data); | ||||
|     background_process.set_thumbnail_cb([this](ThumbnailsList& thumbnails, const Vec2ds& sizes, bool printable_only, bool parts_only, bool transparent_background) | ||||
|         { | ||||
|             std::packaged_task<void(ThumbnailsList&, const Vec2ds&, bool, bool, bool)> task([this](ThumbnailsList& thumbnails, const Vec2ds& sizes, bool printable_only, bool parts_only, bool transparent_background) { | ||||
|                 generate_thumbnails(thumbnails, sizes, printable_only, parts_only, transparent_background); | ||||
|                 }); | ||||
|             std::future<void> result = task.get_future(); | ||||
|             wxTheApp->CallAfter([&]() { task(thumbnails, sizes, printable_only, parts_only, transparent_background); }); | ||||
|             result.wait(); | ||||
|         }); | ||||
| #endif // ENABLE_THUMBNAIL_GENERATOR
 | ||||
|     background_process.set_slicing_completed_event(EVT_SLICING_COMPLETED); | ||||
|     background_process.set_finished_event(EVT_PROCESS_COMPLETED); | ||||
|  | @ -2089,6 +2095,11 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) | |||
|     view3D_canvas->Bind(EVT_GLCANVAS_RESETGIZMOS, [this](SimpleEvent&) { reset_all_gizmos(); }); | ||||
|     view3D_canvas->Bind(EVT_GLCANVAS_UNDO, [this](SimpleEvent&) { this->undo(); }); | ||||
|     view3D_canvas->Bind(EVT_GLCANVAS_REDO, [this](SimpleEvent&) { this->redo(); }); | ||||
| #if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE | ||||
|     view3D_canvas->Bind(EVT_GLCANVAS_RESET_LAYER_HEIGHT_PROFILE, [this](SimpleEvent&) { this->view3D->get_canvas3d()->reset_layer_height_profile(); }); | ||||
|     view3D_canvas->Bind(EVT_GLCANVAS_ADAPTIVE_LAYER_HEIGHT_PROFILE, [this](Event<float>& evt) { this->view3D->get_canvas3d()->adaptive_layer_height_profile(evt.data); }); | ||||
|     view3D_canvas->Bind(EVT_GLCANVAS_SMOOTH_LAYER_HEIGHT_PROFILE, [this](HeightProfileSmoothEvent& evt) { this->view3D->get_canvas3d()->smooth_layer_height_profile(evt.data); }); | ||||
| #endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
 | ||||
| 
 | ||||
|     // 3DScene/Toolbar:
 | ||||
|     view3D_canvas->Bind(EVT_GLTOOLBAR_ADD, &priv::on_action_add, this); | ||||
|  | @ -3068,37 +3079,6 @@ bool Plater::priv::restart_background_process(unsigned int state) | |||
|          ( ((state & UPDATE_BACKGROUND_PROCESS_FORCE_RESTART) != 0 && ! this->background_process.finished()) || | ||||
|            (state & UPDATE_BACKGROUND_PROCESS_FORCE_EXPORT) != 0 || | ||||
|            (state & UPDATE_BACKGROUND_PROCESS_RESTART) != 0 ) ) { | ||||
| #if ENABLE_THUMBNAIL_GENERATOR | ||||
|         if (((state & UPDATE_BACKGROUND_PROCESS_FORCE_EXPORT) == 0) && | ||||
|              (this->background_process.state() != BackgroundSlicingProcess::STATE_RUNNING)) | ||||
|         { | ||||
|             // update thumbnail data
 | ||||
|             const std::vector<Vec2d> &thumbnail_sizes = this->background_process.current_print()->full_print_config().option<ConfigOptionPoints>("thumbnails")->values; | ||||
|             if (this->printer_technology == ptFFF) | ||||
|             { | ||||
|                 // for ptFFF we need to generate the thumbnails before the export of gcode starts
 | ||||
|                 this->thumbnail_data.clear(); | ||||
|                 for (const Vec2d &sized : thumbnail_sizes) | ||||
|                 { | ||||
|                     this->thumbnail_data.push_back(ThumbnailData()); | ||||
| 					Point size(sized); // round to ints
 | ||||
|                     generate_thumbnail(this->thumbnail_data.back(), size.x(), size.y(), true, true, false); | ||||
|                 } | ||||
|             } | ||||
|             else if (this->printer_technology == ptSLA) | ||||
|             { | ||||
|                 // for ptSLA generate thumbnails without supports and pad (not yet calculated)
 | ||||
|                 // to render also supports and pad see on_slicing_update()
 | ||||
|                 this->thumbnail_data.clear(); | ||||
|                 for (const Vec2d &sized : thumbnail_sizes) | ||||
|                 { | ||||
|                     this->thumbnail_data.push_back(ThumbnailData()); | ||||
| 					Point size(sized); // round to ints
 | ||||
| 					generate_thumbnail(this->thumbnail_data.back(), size.x(), size.y(), true, true, false); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| #endif // ENABLE_THUMBNAIL_GENERATOR
 | ||||
|         // The print is valid and it can be started.
 | ||||
|         if (this->background_process.start()) { | ||||
|             this->statusbar()->set_cancel_callback([this]() { | ||||
|  | @ -3438,25 +3418,6 @@ void Plater::priv::on_slicing_update(SlicingStatusEvent &evt) | |||
|     } else if (evt.status.flags & PrintBase::SlicingStatus::RELOAD_SLA_PREVIEW) { | ||||
|         // Update the SLA preview. Only called if not RELOAD_SLA_SUPPORT_POINTS, as the block above will refresh the preview anyways.
 | ||||
|         this->preview->reload_print(); | ||||
| 
 | ||||
|         // uncomment the following lines if you want to render into the thumbnail also supports and pad for SLA printer
 | ||||
| /*
 | ||||
| #if ENABLE_THUMBNAIL_GENERATOR | ||||
|         // update thumbnail data
 | ||||
|         // for ptSLA generate the thumbnail after supports and pad have been calculated to have them rendered
 | ||||
|         if ((this->printer_technology == ptSLA) && (evt.status.percent == -3)) | ||||
|         { | ||||
|             const std::vector<Vec2d>& thumbnail_sizes = this->background_process.current_print()->full_print_config().option<ConfigOptionPoints>("thumbnails")->values; | ||||
|             this->thumbnail_data.clear(); | ||||
|             for (const Vec2d &sized : thumbnail_sizes) | ||||
|             { | ||||
|                 this->thumbnail_data.push_back(ThumbnailData()); | ||||
|                 Point size(sized); // round to ints
 | ||||
|                 generate_thumbnail(this->thumbnail_data.back(), size.x(), size.y(), true, false, false); | ||||
|             } | ||||
|         } | ||||
| #endif // ENABLE_THUMBNAIL_GENERATOR
 | ||||
| */ | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | @ -3687,6 +3648,19 @@ void Plater::priv::generate_thumbnail(ThumbnailData& data, unsigned int w, unsig | |||
| { | ||||
|     view3D->get_canvas3d()->render_thumbnail(data, w, h, printable_only, parts_only, transparent_background); | ||||
| } | ||||
| 
 | ||||
| void Plater::priv::generate_thumbnails(ThumbnailsList& thumbnails, const Vec2ds& sizes, bool printable_only, bool parts_only, bool transparent_background) | ||||
| { | ||||
|     thumbnails.clear(); | ||||
|     for (const Vec2d& size : sizes) | ||||
|     { | ||||
|         thumbnails.push_back(ThumbnailData()); | ||||
|         Point isize(size); // round to ints
 | ||||
|         generate_thumbnail(thumbnails.back(), isize.x(), isize.y(), printable_only, parts_only, transparent_background); | ||||
|         if (!thumbnails.back().is_valid()) | ||||
|             thumbnails.pop_back(); | ||||
|     } | ||||
| } | ||||
| #endif // ENABLE_THUMBNAIL_GENERATOR
 | ||||
| 
 | ||||
| void Plater::priv::msw_rescale_object_menu() | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Enrico Turri
						Enrico Turri