Compare commits
116 Commits
V1.1.3
...
Version_1.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
53b881144c | ||
|
|
ecff478fd4 | ||
|
|
43fc6f262a | ||
|
|
18a0c7bd80 | ||
|
|
007578e041 | ||
|
|
e6b82214e5 | ||
|
|
5ed1560c59 | ||
|
|
a6ed4e65cb | ||
|
|
ca82d85cc2 | ||
|
|
f69a71d1f5 | ||
|
|
e61c252aee | ||
|
|
146a4a15ed | ||
|
|
4bdb7b76df | ||
|
|
9509b4ffab | ||
|
|
8413db6570 | ||
|
|
bebee387c5 | ||
|
|
7e1ce117f7 | ||
|
|
a23a37cbca | ||
|
|
df89ee4f35 | ||
|
|
141752edf2 | ||
|
|
7a86f18bac | ||
|
|
61424985ac | ||
|
|
ad0b449ad4 | ||
|
|
6e8f38f01a | ||
|
|
24cff06406 | ||
|
|
4277d8118c | ||
|
|
7de8f0817f | ||
|
|
4e223315f8 | ||
|
|
db53ba056c | ||
|
|
5005a1df1b | ||
|
|
2b8deba938 | ||
|
|
6cf7a38bb9 | ||
|
|
be65279049 | ||
|
|
aca63cc7e0 | ||
|
|
90f64f7151 | ||
|
|
84312d4cb8 | ||
|
|
df194b11c8 | ||
|
|
8e9d4777f4 | ||
|
|
5d9df179dd | ||
|
|
8912079f62 | ||
|
|
e505af5cc7 | ||
|
|
11bda61bc8 | ||
|
|
4c9bbc53a3 | ||
|
|
e9146c950a | ||
|
|
3d288f47b1 | ||
|
|
69126621fc | ||
|
|
b7e961c443 | ||
|
|
5b5ff0a1eb | ||
|
|
e033b37e75 | ||
|
|
f25014959b | ||
|
|
78513b7b86 | ||
|
|
0fe9657904 | ||
|
|
f0c70857ae | ||
|
|
e21feab522 | ||
|
|
5b7a66b64c | ||
|
|
c2d1c70e10 | ||
|
|
a1c4285ffc | ||
|
|
ad0215fa2f | ||
|
|
8ef53eceee | ||
|
|
9e5911b2c3 | ||
|
|
4e0134d651 | ||
|
|
783b825007 | ||
|
|
201cb4a2fd | ||
|
|
125abfca57 | ||
|
|
e77259c80b | ||
|
|
0b00c61781 | ||
|
|
13d99fd843 | ||
|
|
f743590509 | ||
|
|
323538586d | ||
|
|
cb05d9d4a0 | ||
|
|
01cbd4c5d4 | ||
|
|
25062b9f99 | ||
|
|
d4f6c80a43 | ||
|
|
ee237cfc16 | ||
|
|
a9889b297e | ||
|
|
508ba0444c | ||
|
|
090eebdabc | ||
|
|
5368acee65 | ||
|
|
c2b5393b82 | ||
|
|
4404fdc03c | ||
|
|
8c0b581581 | ||
|
|
96b64539e2 | ||
|
|
e768b990a8 | ||
|
|
a2ddbe8eb4 | ||
|
|
a3e0809506 | ||
|
|
b13c47456b | ||
|
|
6121002516 | ||
|
|
8fa61058d4 | ||
|
|
0053429d72 | ||
|
|
da44f549e1 | ||
|
|
04ad174e91 | ||
|
|
9c52fb3733 | ||
|
|
128a023c41 | ||
|
|
b9452a91a2 | ||
|
|
cc68470ac8 | ||
|
|
0de9767ff0 | ||
|
|
3217389d20 | ||
|
|
05d820c13d | ||
|
|
68553eba55 | ||
|
|
6e4ada127d | ||
|
|
4d2d510050 | ||
|
|
825c980cef | ||
|
|
2a46a2f415 | ||
|
|
ea3407798b | ||
|
|
9917cfeb69 | ||
|
|
d06a7dfa89 | ||
|
|
ecde3d5864 | ||
|
|
446c2c4e75 | ||
|
|
2466489049 | ||
|
|
b9997e7ee2 | ||
|
|
b6d7c8a367 | ||
|
|
05e2b540ab | ||
|
|
0491f84149 | ||
|
|
88c9efa548 | ||
|
|
e6a64eb5cb | ||
|
|
a630648563 |
2
.gitignore
vendored
@@ -21,3 +21,5 @@ deps/build-linux/*
|
|||||||
**/.idea/
|
**/.idea/
|
||||||
.pkg_cache
|
.pkg_cache
|
||||||
CMakeUserPresets.json
|
CMakeUserPresets.json
|
||||||
|
/resources/profiles
|
||||||
|
/src/slic3r/QIDI
|
||||||
|
|||||||
BIN
resources/icon.icns
Normal file
|
Before Width: | Height: | Size: 114 KiB After Width: | Height: | Size: 112 KiB |
|
Before Width: | Height: | Size: 8.9 KiB After Width: | Height: | Size: 7.1 KiB |
@@ -1,56 +1,20 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<!-- Generator: Adobe Illustrator 25.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
<!-- Generator: Adobe Illustrator 25.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
<svg version="1.1" id="图层_2" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
viewBox="0 0 256 256" enable-background="new 0 0 256 256" xml:space="preserve">
|
viewBox="0 0 256 256" enable-background="new 0 0 256 256" xml:space="preserve">
|
||||||
<g>
|
<g>
|
||||||
<path fill="#4479FB" d="M196,256H60c-33.1,0-60-26.9-60-60V60C0,26.9,26.9,0,60,0h136c33.1,0,60,26.9,60,60v136
|
<path fill="#FFFFFF" d="M60,252c-30.9,0-56-25.1-56-56V60C4,29.1,29.1,4,60,4h136c30.9,0,56,25.1,56,56v136c0,30.9-25.1,56-56,56
|
||||||
C256,229.1,229.1,256,196,256z"/>
|
H60z"/>
|
||||||
</g>
|
<g>
|
||||||
<g>
|
<path fill="#303AB2" d="M196,8c28.7,0,52,23.3,52,52v136c0,28.7-23.3,52-52,52H60c-28.7,0-52-23.3-52-52V60C8,31.3,31.3,8,60,8
|
||||||
<path fill="#FFFFFF" d="M194.5,188.5c-7.6-3.5-15-7.5-22.2-11.8c-6.8-4.2-13.1-8.5-18.7-12.9c17.1-13.5,23.2-36.1,13.2-56.7
|
H196 M196,0H60C26.9,0,0,26.9,0,60v136c0,33.1,26.9,60,60,60h136c33.1,0,60-26.9,60-60V60C256,26.9,229.1,0,196,0L196,0z"/>
|
||||||
c-12.7-26.1-46.3-39.2-75.2-29.1c-31.6,11-41,43-25.8,68.7c-48.2-53.1,7.3-123.8,85-99.8c26.2,8.1,48.9,25.8,60.8,50.2
|
</g>
|
||||||
C227.4,129.7,219.5,165.3,194.5,188.5z"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<path fill="#FFFFFF" d="M34.7,158.5c17.6,36.2,59,57.6,100.3,54.8c-16.2-6.1-32-16-45-29c-7.8-7.8-13.8-16-18.2-24.2
|
|
||||||
c-9.1-6.3-16.9-14.3-23-23.6C37.5,118.9,34.6,99.6,39,82C24.6,104.1,21.9,132.2,34.7,158.5L34.7,158.5z"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<path fill="#FFFFFF" d="M234.5,206.6c-28.2,6.1-68-4.1-97.8-26.7c-35.1-26.6-43.5-60.9-19.9-78.1c-8,18.8,7,47.1,40.6,71.4
|
|
||||||
C181.1,190.4,209.2,202,234.5,206.6z"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<path fill="#FFFFFF" d="M187.4,212.9c-29.6,5.2-68.1-7.9-94.8-34.2c-33-32.6-35.5-73.3-5.5-90.8c12-7,27.4-9.2,43.6-7.3
|
|
||||||
c-4.7,1.3-9.2,3.1-13.2,5.4c-30,17.5-26.8,58.9,7.2,92.4C142.6,196.1,165.4,208.1,187.4,212.9L187.4,212.9z"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
</g>
|
||||||
|
<path fill="#303AB2" d="M145,177.9v-13.2v-21.3c0-2.3,1.2-4.5,3.2-5.6l28.3-16.3l13-7.5V93c0-4.6-2.5-8.9-6.5-11.2l-57.8-33.4
|
||||||
|
c-4-2.3-8.9-2.3-13,0L54.5,81.8c-4,2.3-6.5,6.6-6.5,11.2v66.7c0,4.6,2.5,8.9,6.5,11.2l57.8,33.4c4,2.3,8.9,2.3,13,0l19.7-11.4l0,0
|
||||||
|
V177.9z M125.2,115.2c-4,2.3-6.5,6.6-6.5,11.2v55.4c0,5-5.4,8.1-9.7,5.6l-44.8-25.9c-2-1.2-3.2-3.3-3.2-5.6V96.7
|
||||||
|
c0-2.3,1.2-4.5,3.2-5.6l51.3-29.6c2-1.2,4.5-1.2,6.5,0l38.3,22.1c4.3,2.5,4.3,8.7,0,11.2L125.2,115.2z"/>
|
||||||
|
<path fill="#303AB2" d="M198.3,108.9l-8.8,5.1v18.2v1.8v22.1v7.5c0,2.3-1.2,4.4-3.2,5.5l0,0l-0.7,0.4l-0.9,0.5l-8.1,4.7l-5.2,3
|
||||||
|
L145,192.9l0,0v6.4v3.1v0.1c0,0,0,0,0,0v0.4c0.1,4.8,5.2,7.9,9.5,5.7l0.2-0.1l5.2-3l44.9-26c2-1.2,3.2-3.3,3.2-5.6v-59.4
|
||||||
|
C208,109.5,202.6,106.4,198.3,108.9z"/>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 7.5 KiB After Width: | Height: | Size: 6.0 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 9.1 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 7.5 KiB After Width: | Height: | Size: 6.0 KiB |
|
Before Width: | Height: | Size: 114 KiB After Width: | Height: | Size: 112 KiB |
|
Before Width: | Height: | Size: 8.9 KiB After Width: | Height: | Size: 7.1 KiB |
@@ -1,56 +1,20 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<!-- Generator: Adobe Illustrator 25.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
<!-- Generator: Adobe Illustrator 25.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
<svg version="1.1" id="图层_2" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
viewBox="0 0 256 256" enable-background="new 0 0 256 256" xml:space="preserve">
|
viewBox="0 0 256 256" enable-background="new 0 0 256 256" xml:space="preserve">
|
||||||
<g>
|
<g>
|
||||||
<path fill="#4479FB" d="M196,256H60c-33.1,0-60-26.9-60-60V60C0,26.9,26.9,0,60,0h136c33.1,0,60,26.9,60,60v136
|
<path fill="#FFFFFF" d="M60,252c-30.9,0-56-25.1-56-56V60C4,29.1,29.1,4,60,4h136c30.9,0,56,25.1,56,56v136c0,30.9-25.1,56-56,56
|
||||||
C256,229.1,229.1,256,196,256z"/>
|
H60z"/>
|
||||||
</g>
|
<g>
|
||||||
<g>
|
<path fill="#303AB2" d="M196,8c28.7,0,52,23.3,52,52v136c0,28.7-23.3,52-52,52H60c-28.7,0-52-23.3-52-52V60C8,31.3,31.3,8,60,8
|
||||||
<path fill="#FFFFFF" d="M194.5,188.5c-7.6-3.5-15-7.5-22.2-11.8c-6.8-4.2-13.1-8.5-18.7-12.9c17.1-13.5,23.2-36.1,13.2-56.7
|
H196 M196,0H60C26.9,0,0,26.9,0,60v136c0,33.1,26.9,60,60,60h136c33.1,0,60-26.9,60-60V60C256,26.9,229.1,0,196,0L196,0z"/>
|
||||||
c-12.7-26.1-46.3-39.2-75.2-29.1c-31.6,11-41,43-25.8,68.7c-48.2-53.1,7.3-123.8,85-99.8c26.2,8.1,48.9,25.8,60.8,50.2
|
</g>
|
||||||
C227.4,129.7,219.5,165.3,194.5,188.5z"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<path fill="#FFFFFF" d="M34.7,158.5c17.6,36.2,59,57.6,100.3,54.8c-16.2-6.1-32-16-45-29c-7.8-7.8-13.8-16-18.2-24.2
|
|
||||||
c-9.1-6.3-16.9-14.3-23-23.6C37.5,118.9,34.6,99.6,39,82C24.6,104.1,21.9,132.2,34.7,158.5L34.7,158.5z"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<path fill="#FFFFFF" d="M234.5,206.6c-28.2,6.1-68-4.1-97.8-26.7c-35.1-26.6-43.5-60.9-19.9-78.1c-8,18.8,7,47.1,40.6,71.4
|
|
||||||
C181.1,190.4,209.2,202,234.5,206.6z"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<path fill="#FFFFFF" d="M187.4,212.9c-29.6,5.2-68.1-7.9-94.8-34.2c-33-32.6-35.5-73.3-5.5-90.8c12-7,27.4-9.2,43.6-7.3
|
|
||||||
c-4.7,1.3-9.2,3.1-13.2,5.4c-30,17.5-26.8,58.9,7.2,92.4C142.6,196.1,165.4,208.1,187.4,212.9L187.4,212.9z"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
</g>
|
||||||
|
<path fill="#303AB2" d="M145,177.9v-13.2v-21.3c0-2.3,1.2-4.5,3.2-5.6l28.3-16.3l13-7.5V93c0-4.6-2.5-8.9-6.5-11.2l-57.8-33.4
|
||||||
|
c-4-2.3-8.9-2.3-13,0L54.5,81.8c-4,2.3-6.5,6.6-6.5,11.2v66.7c0,4.6,2.5,8.9,6.5,11.2l57.8,33.4c4,2.3,8.9,2.3,13,0l19.7-11.4l0,0
|
||||||
|
V177.9z M125.2,115.2c-4,2.3-6.5,6.6-6.5,11.2v55.4c0,5-5.4,8.1-9.7,5.6l-44.8-25.9c-2-1.2-3.2-3.3-3.2-5.6V96.7
|
||||||
|
c0-2.3,1.2-4.5,3.2-5.6l51.3-29.6c2-1.2,4.5-1.2,6.5,0l38.3,22.1c4.3,2.5,4.3,8.7,0,11.2L125.2,115.2z"/>
|
||||||
|
<path fill="#303AB2" d="M198.3,108.9l-8.8,5.1v18.2v1.8v22.1v7.5c0,2.3-1.2,4.4-3.2,5.5l0,0l-0.7,0.4l-0.9,0.5l-8.1,4.7l-5.2,3
|
||||||
|
L145,192.9l0,0v6.4v3.1v0.1c0,0,0,0,0,0v0.4c0.1,4.8,5.2,7.9,9.5,5.7l0.2-0.1l5.2-3l44.9-26c2-1.2,3.2-3.3,3.2-5.6v-59.4
|
||||||
|
C208,109.5,202.6,106.4,198.3,108.9z"/>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 7.5 KiB After Width: | Height: | Size: 6.0 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 9.1 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 9.1 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 9.1 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 5.7 KiB |
BIN
resources/icons/X-Plus 4_thumbnail.png
Normal file
|
After Width: | Height: | Size: 9.5 KiB |
|
Before Width: | Height: | Size: 437 B After Width: | Height: | Size: 437 B |
6
resources/icons/add_machine_list_disable.svg
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 25.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
width="24px" height="24px" viewBox="0 0 24 24" enable-background="new 0 0 24 24" xml:space="preserve">
|
||||||
|
<path fill="#ADADAF" d="M11,11V5h2v6h6v2h-6v6h-2v-6H5v-2H11z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 437 B |
|
Before Width: | Height: | Size: 417 B After Width: | Height: | Size: 417 B |
6
resources/icons/delete_machine_list_disable.svg
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 25.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
width="24px" height="24px" viewBox="0 0 24 24" enable-background="new 0 0 24 24" xml:space="preserve">
|
||||||
|
<path fill="#ADADAF" d="M5,13v-2h14v2H5z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 417 B |
7
resources/icons/edit_machine_list_able.svg
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 25.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
width="24px" height="24px" viewBox="0 0 24 24" enable-background="new 0 0 24 24" xml:space="preserve">
|
||||||
|
<path fill="#4479fb" d="M16.8,3l-2,2H5v14h14V9.2l2-2V20c0,0.6-0.4,1-1,1H4c-0.6,0-1-0.4-1-1V4c0-0.6,0.4-1,1-1H16.8z M20.5,2.1
|
||||||
|
l1.4,1.4l-9.2,9.2l-1.4,0l0-1.4L20.5,2.1z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 543 B |
|
Before Width: | Height: | Size: 543 B After Width: | Height: | Size: 543 B |
155
resources/icons/param_cross hatch.svg
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 25.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
width="10px" height="10px" viewBox="0 0 10 10" enable-background="new 0 0 10 10" xml:space="preserve">
|
||||||
|
<defs>
|
||||||
|
<filter id="Adobe_OpacityMaskFilter" filterUnits="userSpaceOnUse" x="0.7" y="0.6" width="3.7" height="3.7">
|
||||||
|
<feColorMatrix type="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0"/>
|
||||||
|
</filter>
|
||||||
|
</defs>
|
||||||
|
<mask maskUnits="userSpaceOnUse" x="0.7" y="0.6" width="3.7" height="3.7" id="mask1_7_73_2_">
|
||||||
|
<path id="path3_2_" fill="#FFFFFF" filter="url(#Adobe_OpacityMaskFilter)" d="M10,0.1H0v10h10V0.1z"/>
|
||||||
|
</mask>
|
||||||
|
<g id="g5" transform="translate(-0.13363557,-0.18774744)" mask="url(#mask1_7_73_2_)">
|
||||||
|
<path id="path4" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M2.7,4.3l1.6-1.6L2.7,1L1,2.7L2.7,4.3z"/>
|
||||||
|
<path id="path5" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M2.7,3.5l0.8-0.8L2.7,1.8L1.8,2.7L2.7,3.5z"/>
|
||||||
|
<path id="path31" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M2.7,4.3l1.6-1.6L2.7,1L1,2.7L2.7,4.3z"/>
|
||||||
|
<path id="path32" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M2.7,3.5l0.8-0.8L2.7,1.8L1.8,2.7L2.7,3.5z"/>
|
||||||
|
<path id="path50" fill="none" stroke="#999999" stroke-width="0.3" d="M2.7,4.3l1.6-1.6L2.7,1L1,2.7L2.7,4.3z"/>
|
||||||
|
<path id="path51" fill="none" stroke="#999999" stroke-width="0.3" d="M2.7,3.5l0.8-0.8L2.7,1.8L1.8,2.7L2.7,3.5z"/>
|
||||||
|
</g>
|
||||||
|
<defs>
|
||||||
|
<filter id="Adobe_OpacityMaskFilter_1_" filterUnits="userSpaceOnUse" x="4" y="0.6" width="3.7" height="3.7">
|
||||||
|
<feColorMatrix type="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0"/>
|
||||||
|
</filter>
|
||||||
|
</defs>
|
||||||
|
<mask maskUnits="userSpaceOnUse" x="4" y="0.6" width="3.7" height="3.7" id="mask2_7_73_2_">
|
||||||
|
<path id="path6_2_" fill="#FFFFFF" filter="url(#Adobe_OpacityMaskFilter_1_)" d="M10,0.1H0v10h10V0.1z"/>
|
||||||
|
</mask>
|
||||||
|
<g id="g8" transform="translate(-0.13363557,-0.18774744)" mask="url(#mask2_7_73_2_)">
|
||||||
|
<path id="path7" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M6,4.3l1.6-1.6L6,1L4.4,2.7L6,4.3z"/>
|
||||||
|
<path id="path8" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M6,3.5l0.8-0.8L6,1.8L5.1,2.7L6,3.5z"/>
|
||||||
|
<path id="path33" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M6,4.3l1.6-1.6L6,1L4.4,2.7L6,4.3z"/>
|
||||||
|
<path id="path34" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M6,3.5l0.8-0.8L6,1.8L5.1,2.7L6,3.5z"/>
|
||||||
|
<path id="path52" fill="none" stroke="#999999" stroke-width="0.3" d="M6,4.3l1.6-1.6L6,1L4.4,2.7L6,4.3z"/>
|
||||||
|
<path id="path53" fill="none" stroke="#999999" stroke-width="0.3" d="M6,3.5l0.8-0.8L6,1.8L5.1,2.7L6,3.5z"/>
|
||||||
|
</g>
|
||||||
|
<defs>
|
||||||
|
<filter id="Adobe_OpacityMaskFilter_2_" filterUnits="userSpaceOnUse" x="7.3" y="0.7" width="2.1" height="3.5">
|
||||||
|
<feColorMatrix type="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0"/>
|
||||||
|
</filter>
|
||||||
|
</defs>
|
||||||
|
<mask maskUnits="userSpaceOnUse" x="7.3" y="0.7" width="2.1" height="3.5" id="mask3_7_73_2_">
|
||||||
|
<path id="path9_2_" fill="#FFFFFF" filter="url(#Adobe_OpacityMaskFilter_2_)" d="M10,0.1H0v10h10V0.1z"/>
|
||||||
|
</mask>
|
||||||
|
<g id="g11" transform="translate(-0.13363557,-0.18774744)" mask="url(#mask3_7_73_2_)">
|
||||||
|
<path id="path10" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M9.2,4.2L7.6,2.6l1.6-1.7"/>
|
||||||
|
<path id="path11" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M9.2,3.4L8.4,2.6l0.8-0.8"/>
|
||||||
|
<path id="path35" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M9.2,4.2L7.6,2.6l1.6-1.7"/>
|
||||||
|
<path id="path36" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M9.2,3.4L8.4,2.6l0.8-0.8"/>
|
||||||
|
<path id="path54" fill="none" stroke="#999999" stroke-width="0.3" d="M9.2,4.2L7.6,2.6l1.6-1.7"/>
|
||||||
|
<path id="path55" fill="none" stroke="#999999" stroke-width="0.3" d="M9.5,3.7l-1-1l1-1"/>
|
||||||
|
</g>
|
||||||
|
<defs>
|
||||||
|
<filter id="Adobe_OpacityMaskFilter_3_" filterUnits="userSpaceOnUse" x="0.7" y="4" width="3.7" height="3.7">
|
||||||
|
<feColorMatrix type="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0"/>
|
||||||
|
</filter>
|
||||||
|
</defs>
|
||||||
|
<mask maskUnits="userSpaceOnUse" x="0.7" y="4" width="3.7" height="3.7" id="mask4_7_73_2_">
|
||||||
|
<path id="path12_2_" fill="#FFFFFF" filter="url(#Adobe_OpacityMaskFilter_3_)" d="M10,0.1H0v10h10V0.1z"/>
|
||||||
|
</mask>
|
||||||
|
<g id="g14" transform="translate(-0.13363557,-0.18774744)" mask="url(#mask4_7_73_2_)">
|
||||||
|
<path id="path13" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M2.7,7.6L4.3,6L2.7,4.4L1.1,6L2.7,7.6z"/>
|
||||||
|
<path id="path14" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M2.7,6.9L3.5,6L2.7,5.2L1.8,6L2.7,6.9z"/>
|
||||||
|
<path id="path37" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M2.7,7.6L4.3,6L2.7,4.4L1.1,6L2.7,7.6z"/>
|
||||||
|
<path id="path38" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M2.7,6.9L3.5,6L2.7,5.2L1.8,6L2.7,6.9z"/>
|
||||||
|
<path id="path56" fill="none" stroke="#999999" stroke-width="0.3" d="M2.7,7.6L4.3,6L2.7,4.4L1.1,6L2.7,7.6z"/>
|
||||||
|
<path id="path57" fill="none" stroke="#999999" stroke-width="0.3" d="M2.7,6.9L3.5,6L2.7,5.2L1.8,6L2.7,6.9z"/>
|
||||||
|
</g>
|
||||||
|
<defs>
|
||||||
|
<filter id="Adobe_OpacityMaskFilter_4_" filterUnits="userSpaceOnUse" x="4" y="4" width="3.7" height="3.7">
|
||||||
|
<feColorMatrix type="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0"/>
|
||||||
|
</filter>
|
||||||
|
</defs>
|
||||||
|
<mask maskUnits="userSpaceOnUse" x="4" y="4" width="3.7" height="3.7" id="mask5_7_73_2_">
|
||||||
|
<path id="path15_2_" fill="#FFFFFF" filter="url(#Adobe_OpacityMaskFilter_4_)" d="M10,0.1H0v10h10V0.1z"/>
|
||||||
|
</mask>
|
||||||
|
<g id="g17" transform="translate(-0.13363557,-0.18774744)" mask="url(#mask5_7_73_2_)">
|
||||||
|
<path id="path16" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M6,7.6L7.6,6L6,4.4L4.4,6L6,7.6z"/>
|
||||||
|
<path id="path17" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M6,6.9L6.9,6L6,5.2L5.2,6L6,6.9z"/>
|
||||||
|
<path id="path39" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M6,7.6L7.6,6L6,4.4L4.4,6L6,7.6z"/>
|
||||||
|
<path id="path40" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M6,6.9L6.9,6L6,5.2L5.2,6L6,6.9z"/>
|
||||||
|
<path id="path58" fill="none" stroke="#999999" stroke-width="0.3" d="M6,7.6L7.6,6L6,4.4L4.4,6L6,7.6z"/>
|
||||||
|
<path id="path59" fill="none" stroke="#999999" stroke-width="0.3" d="M6,6.9L6.9,6L6,5.2L5.2,6L6,6.9z"/>
|
||||||
|
</g>
|
||||||
|
<defs>
|
||||||
|
<filter id="Adobe_OpacityMaskFilter_5_" filterUnits="userSpaceOnUse" x="7.3" y="4" width="2.1" height="3.5">
|
||||||
|
<feColorMatrix type="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0"/>
|
||||||
|
</filter>
|
||||||
|
</defs>
|
||||||
|
<mask maskUnits="userSpaceOnUse" x="7.3" y="4" width="2.1" height="3.5" id="mask6_7_73_2_">
|
||||||
|
<path id="path18_2_" fill="#FFFFFF" filter="url(#Adobe_OpacityMaskFilter_5_)" d="M10,0.1H0v10h10V0.1z"/>
|
||||||
|
</mask>
|
||||||
|
<g id="g20" transform="translate(-0.13363557,-0.18774744)" mask="url(#mask6_7_73_2_)">
|
||||||
|
<path id="path19" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M9.2,7.6L7.6,5.9l1.6-1.6"/>
|
||||||
|
<path id="path20" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M9.2,6.7L8.4,5.9l0.8-0.8"/>
|
||||||
|
<path id="path41" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M9.2,7.6L7.6,5.9l1.6-1.6"/>
|
||||||
|
<path id="path42" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M9.2,6.7L8.4,5.9l0.8-0.8"/>
|
||||||
|
<path id="path60" fill="none" stroke="#999999" stroke-width="0.3" d="M9.2,7.6L7.6,5.9l1.6-1.6"/>
|
||||||
|
<path id="path61" fill="none" stroke="#999999" stroke-width="0.3" d="M9.4,7l-1-1l1-1"/>
|
||||||
|
</g>
|
||||||
|
<defs>
|
||||||
|
<filter id="Adobe_OpacityMaskFilter_6_" filterUnits="userSpaceOnUse" x="0.7" y="7.2" width="3.6" height="2.2">
|
||||||
|
<feColorMatrix type="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0"/>
|
||||||
|
</filter>
|
||||||
|
</defs>
|
||||||
|
<mask maskUnits="userSpaceOnUse" x="0.7" y="7.2" width="3.6" height="2.2" id="mask7_7_73_2_">
|
||||||
|
<path id="path21_2_" fill="#FFFFFF" filter="url(#Adobe_OpacityMaskFilter_6_)" d="M10,0.1H0v10h10V0.1z"/>
|
||||||
|
</mask>
|
||||||
|
<g id="g23" transform="translate(-0.13363557,-0.18774744)" mask="url(#mask7_7_73_2_)">
|
||||||
|
<path id="path22" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M0.9,9.3l1.7-1.7l1.7,1.7"/>
|
||||||
|
<path id="path23" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M1.8,9.3l0.8-0.9l0.8,0.9"/>
|
||||||
|
<path id="path43" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M0.9,9.3l1.7-1.7l1.7,1.7"/>
|
||||||
|
<path id="path44" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M1.8,9.3l0.8-0.9l0.8,0.9"/>
|
||||||
|
<path id="path62" fill="none" stroke="#999999" stroke-width="0.3" d="M0.9,9.3l1.7-1.7l1.7,1.7"/>
|
||||||
|
<path id="path63" fill="none" stroke="#999999" stroke-width="0.3" d="M1.8,9.4l0.9-1l0.9,1.1"/>
|
||||||
|
</g>
|
||||||
|
<defs>
|
||||||
|
<filter id="Adobe_OpacityMaskFilter_7_" filterUnits="userSpaceOnUse" x="4.1" y="7.3" width="3.5" height="2">
|
||||||
|
<feColorMatrix type="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0"/>
|
||||||
|
</filter>
|
||||||
|
</defs>
|
||||||
|
<mask maskUnits="userSpaceOnUse" x="4.1" y="7.3" width="3.5" height="2" id="mask8_7_73_2_">
|
||||||
|
<path id="path24_2_" fill="#FFFFFF" filter="url(#Adobe_OpacityMaskFilter_7_)" d="M10,0.1H0v10h10V0.1z"/>
|
||||||
|
</mask>
|
||||||
|
<g id="g26" transform="translate(-0.06473357,-0.11884544)" mask="url(#mask8_7_73_2_)">
|
||||||
|
<path id="path25" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M4.3,9.3l1.6-1.7l1.7,1.7"/>
|
||||||
|
<path id="path26" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M5.1,9.3l0.8-0.9l0.8,0.9"/>
|
||||||
|
<path id="path45" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M4.3,9.3l1.6-1.7l1.7,1.7"/>
|
||||||
|
<path id="path46" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M5.1,9.3l0.8-0.9l0.8,0.9"/>
|
||||||
|
<path id="path64" fill="none" stroke="#999999" stroke-width="0.3" d="M4.3,9.3l1.6-1.7l1.7,1.7"/>
|
||||||
|
<path id="path65" fill="none" stroke="#999999" stroke-width="0.3" d="M5.1,9.3l0.8-0.9l0.8,0.9"/>
|
||||||
|
</g>
|
||||||
|
<defs>
|
||||||
|
<filter id="Adobe_OpacityMaskFilter_8_" filterUnits="userSpaceOnUse" x="7.3" y="7.3" width="2.1" height="2">
|
||||||
|
<feColorMatrix type="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0"/>
|
||||||
|
</filter>
|
||||||
|
</defs>
|
||||||
|
<mask maskUnits="userSpaceOnUse" x="7.3" y="7.3" width="2.1" height="2" id="mask9_7_73_2_">
|
||||||
|
<path id="path27_2_" fill="#FFFFFF" filter="url(#Adobe_OpacityMaskFilter_8_)" d="M10,0.1H0v10h10V0.1z"/>
|
||||||
|
</mask>
|
||||||
|
<g id="g29" transform="translate(-0.13363557,-0.18774744)" mask="url(#mask9_7_73_2_)">
|
||||||
|
<path id="path28" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M7.5,9.3l1.7-1.7"/>
|
||||||
|
<path id="path29" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M8.4,9.3l0.8-0.9"/>
|
||||||
|
<path id="path47" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M7.5,9.3l1.7-1.7"/>
|
||||||
|
<path id="path48" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M8.4,9.3l0.8-0.9"/>
|
||||||
|
<path id="path66" fill="none" stroke="#999999" stroke-width="0.3" d="M7.5,9.3l1.7-1.7"/>
|
||||||
|
<path id="path67" fill="none" stroke="#999999" stroke-width="0.3" d="M8.3,9.5l1.1-1.3"/>
|
||||||
|
</g>
|
||||||
|
<path id="path68" fill="none" stroke="#4479FB" stroke-width="0.478" d="M2.4,0.7l6.9,6.9"/>
|
||||||
|
<path id="path68-8" fill="none" stroke="#4479FB" stroke-width="0.4997" d="M0.7,2.2l6.9,7.1"/>
|
||||||
|
<path id="path69" fill="none" stroke="#4479FB" stroke-width="0.478" d="M0.7,5.6l3.6,3.7"/>
|
||||||
|
<path id="path70" fill="none" stroke="#4479FB" stroke-width="0.5048" d="M5.7,0.7l3.6,3.5"/>
|
||||||
|
<path id="rect1" fill="none" stroke="#4479FB" stroke-width="0.406" stroke-linejoin="round" stroke-miterlimit="3.9" d="M1.5,0.7h7
|
||||||
|
c0.5,0,0.9,0.4,0.9,0.9v6.9c0,0.5-0.4,0.9-0.9,0.9h-7C1,9.3,0.7,8.9,0.7,8.5V1.5C0.7,1.1,1,0.7,1.5,0.7z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 11 KiB |
8
resources/icons/refresh_machine_list_able.svg
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 25.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
width="24px" height="24px" viewBox="0 0 24 24" enable-background="new 0 0 24 24" xml:space="preserve">
|
||||||
|
<path fill="#4479fb" d="M5.5,4.4C7.2,2.9,9.5,2,12,2c5.5,0,10,4.5,10,10c0,2.1-0.7,4.1-1.8,5.7L17,12h3c0-4.4-3.6-8-8-8
|
||||||
|
C9.8,4,7.9,4.8,6.5,6.2L5.5,4.4z M18.5,19.6c-1.8,1.5-4,2.4-6.5,2.4C6.5,22,2,17.5,2,12c0-2.1,0.7-4.1,1.8-5.7L7,12H4
|
||||||
|
c0,4.4,3.6,8,8,8c2.2,0,4.1-0.8,5.5-2.2L18.5,19.6z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 659 B |
|
Before Width: | Height: | Size: 659 B After Width: | Height: | Size: 659 B |
|
Before Width: | Height: | Size: 141 KiB After Width: | Height: | Size: 119 KiB |
|
Before Width: | Height: | Size: 141 KiB After Width: | Height: | Size: 119 KiB |
BIN
resources/icons/user_dark.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
@@ -1,3 +1,9 @@
|
|||||||
|
min_slic3r_version = 1.1.6
|
||||||
|
1.1.6 Optimize parameters
|
||||||
|
min_slic3r_version = 1.1.5
|
||||||
|
1.1.5 Optimize parameters
|
||||||
|
min_slic3r_version = 1.1.4
|
||||||
|
1.1.4 Optimize parameters
|
||||||
min_slic3r_version = 1.1.3
|
min_slic3r_version = 1.1.3
|
||||||
1.1.3 Optimize parameters
|
1.1.3 Optimize parameters
|
||||||
min_slic3r_version = 1.1.2
|
min_slic3r_version = 1.1.2
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 36 KiB |
@@ -1,60 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Generator: Adobe Illustrator 25.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
|
||||||
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
|
||||||
width="694.5px" height="694.5px" viewBox="0 0 694.5 694.5" enable-background="new 0 0 694.5 694.5" xml:space="preserve">
|
|
||||||
<rect fill="#FFFFFF" width="1.4" height="694.5"/>
|
|
||||||
<rect x="693.1" y="15.7" fill="#FFFFFF" width="1.4" height="678.8"/>
|
|
||||||
<rect x="0" y="693.1" fill="#FFFFFF" width="694.5" height="1.4"/>
|
|
||||||
<rect x="559.1" fill="#FFFFFF" width="1.4" height="694.5"/>
|
|
||||||
<rect x="417.4" fill="#FFFFFF" width="1.4" height="694.5"/>
|
|
||||||
<rect x="275.7" y="15.7" fill="#FFFFFF" width="1.4" height="678.8"/>
|
|
||||||
<rect x="133.9" y="14.2" fill="#FFFFFF" width="1.4" height="680.3"/>
|
|
||||||
<rect x="21.1" y="0" fill="#FFFFFF" width="0.4" height="694.5"/>
|
|
||||||
<rect x="49.4" y="0" fill="#FFFFFF" width="0.4" height="694.5"/>
|
|
||||||
<rect x="77.8" y="14.2" fill="#FFFFFF" width="0.4" height="680.3"/>
|
|
||||||
<rect x="106.1" y="14.2" fill="#FFFFFF" width="0.4" height="680.3"/>
|
|
||||||
<rect x="162.8" y="15.7" fill="#FFFFFF" width="0.4" height="678.8"/>
|
|
||||||
<rect x="191.1" y="15.7" fill="#FFFFFF" width="0.4" height="678.8"/>
|
|
||||||
<rect x="219.5" y="15.7" fill="#FFFFFF" width="0.4" height="678.8"/>
|
|
||||||
<rect x="247.8" y="15.7" fill="#FFFFFF" width="0.4" height="678.8"/>
|
|
||||||
<rect x="304.5" y="15.7" fill="#FFFFFF" width="0.4" height="678.8"/>
|
|
||||||
<rect x="332.9" y="0" fill="#FFFFFF" width="0.4" height="694.5"/>
|
|
||||||
<rect x="361.2" y="0" fill="#FFFFFF" width="0.4" height="694.5"/>
|
|
||||||
<rect x="389.6" y="0" fill="#FFFFFF" width="0.4" height="694.5"/>
|
|
||||||
<rect x="446.3" y="0" fill="#FFFFFF" width="0.4" height="694.5"/>
|
|
||||||
<rect x="474.6" y="0" fill="#FFFFFF" width="0.4" height="694.5"/>
|
|
||||||
<rect x="502.9" y="0" fill="#FFFFFF" width="0.4" height="694.5"/>
|
|
||||||
<rect x="531.3" y="0" fill="#FFFFFF" width="0.4" height="694.5"/>
|
|
||||||
<rect x="588" y="0" fill="#FFFFFF" width="0.4" height="694.5"/>
|
|
||||||
<rect x="616.3" y="15.7" fill="#FFFFFF" width="0.4" height="678.8"/>
|
|
||||||
<rect x="644.7" y="15.7" fill="#FFFFFF" width="0.4" height="678.8"/>
|
|
||||||
<rect x="673" y="15.7" fill="#FFFFFF" width="0.4" height="678.8"/>
|
|
||||||
<rect x="0" y="559.1" fill="#FFFFFF" width="694.5" height="1.4"/>
|
|
||||||
<rect x="0" y="417.4" fill="#FFFFFF" width="694.5" height="1.4"/>
|
|
||||||
<rect x="0" y="275.7" fill="#FFFFFF" width="694.5" height="1.4"/>
|
|
||||||
<rect x="0" y="133.9" fill="#FFFFFF" width="694.5" height="1.4"/>
|
|
||||||
<rect x="0" y="21.1" fill="#FFFFFF" width="694.5" height="0.4"/>
|
|
||||||
<rect x="0" y="49.4" fill="#FFFFFF" width="694.5" height="0.4"/>
|
|
||||||
<rect x="0" y="77.8" fill="#FFFFFF" width="694.5" height="0.4"/>
|
|
||||||
<rect x="0" y="106.1" fill="#FFFFFF" width="694.5" height="0.4"/>
|
|
||||||
<rect x="0" y="162.8" fill="#FFFFFF" width="694.5" height="0.4"/>
|
|
||||||
<rect x="0" y="191.1" fill="#FFFFFF" width="694.5" height="0.4"/>
|
|
||||||
<rect x="0" y="219.5" fill="#FFFFFF" width="694.5" height="0.4"/>
|
|
||||||
<rect x="0" y="247.8" fill="#FFFFFF" width="694.5" height="0.4"/>
|
|
||||||
<rect x="0" y="304.5" fill="#FFFFFF" width="694.5" height="0.4"/>
|
|
||||||
<rect x="0" y="332.9" fill="#FFFFFF" width="694.5" height="0.4"/>
|
|
||||||
<rect x="0" y="361.2" fill="#FFFFFF" width="694.5" height="0.4"/>
|
|
||||||
<rect x="0" y="389.6" fill="#FFFFFF" width="694.5" height="0.4"/>
|
|
||||||
<rect x="0" y="446.3" fill="#FFFFFF" width="694.5" height="0.4"/>
|
|
||||||
<rect x="0" y="474.6" fill="#FFFFFF" width="694.5" height="0.4"/>
|
|
||||||
<rect x="0" y="502.9" fill="#FFFFFF" width="694.5" height="0.4"/>
|
|
||||||
<rect x="0" y="531.3" fill="#FFFFFF" width="694.5" height="0.4"/>
|
|
||||||
<rect x="0" y="588" fill="#FFFFFF" width="694.5" height="0.4"/>
|
|
||||||
<rect x="0" y="616.3" fill="#FFFFFF" width="694.5" height="0.4"/>
|
|
||||||
<rect x="0" y="644.7" fill="#FFFFFF" width="694.5" height="0.4"/>
|
|
||||||
<rect x="0" y="673" fill="#FFFFFF" width="694.5" height="0.4"/>
|
|
||||||
<polygon fill="#FFFFFF" points="694.5,15.7 588.1,15.7 588.1,0 589.6,0 589.6,14 694.5,14 "/>
|
|
||||||
<polygon fill="#FFFFFF" points="327.5,15.7 69.4,15.7 69.4,0 70.9,0 70.9,14 326,14 326,0 327.5,0 "/>
|
|
||||||
<rect x="327.5" y="0" fill="#FFFFFF" width="260.9" height="1.4"/>
|
|
||||||
<rect x="0" y="0" fill="#FFFFFF" width="69.4" height="1.4"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 4.0 KiB |
|
Before Width: | Height: | Size: 36 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 7.6 KiB |
@@ -66,6 +66,7 @@ var LangText={
|
|||||||
"l44": "Different filaments have different maximum volume speed.",
|
"l44": "Different filaments have different maximum volume speed.",
|
||||||
"l45": "Nozzle material, caliber, printing temperature, etc., will affect the maximum volume speed.",
|
"l45": "Nozzle material, caliber, printing temperature, etc., will affect the maximum volume speed.",
|
||||||
"l46": "During the test, the printing speed will increase layer by layer. When there is a hole or missing wire on the surface of the model, it indicates that the layer has reached the maximum volume speed, and the maximum volume speed is calculated according to the ratio of height.",
|
"l46": "During the test, the printing speed will increase layer by layer. When there is a hole or missing wire on the surface of the model, it indicates that the layer has reached the maximum volume speed, and the maximum volume speed is calculated according to the ratio of height.",
|
||||||
|
"l47": "Or you can find a solution through WIKI.",
|
||||||
},
|
},
|
||||||
"zh_CN": {
|
"zh_CN": {
|
||||||
"t1": "用户指南",
|
"t1": "用户指南",
|
||||||
@@ -134,6 +135,7 @@ var LangText={
|
|||||||
"l44": "不同线材的最大体积速度各不相同。",
|
"l44": "不同线材的最大体积速度各不相同。",
|
||||||
"l45": "喷嘴材质、口径、打印温度、等都会影响最大体积速度。",
|
"l45": "喷嘴材质、口径、打印温度、等都会影响最大体积速度。",
|
||||||
"l46": "测试时打印速度会逐层增加,当模型表面出现空洞或缺丝时,说明该层已达到最大体积速度,根据高度比例算出最大体积速度。",
|
"l46": "测试时打印速度会逐层增加,当模型表面出现空洞或缺丝时,说明该层已达到最大体积速度,根据高度比例算出最大体积速度。",
|
||||||
|
"l47": "或者你可以通过WIKI来找到解决方案。",
|
||||||
},
|
},
|
||||||
"ja": {
|
"ja": {
|
||||||
"t1": "ユーザーガイド",
|
"t1": "ユーザーガイド",
|
||||||
@@ -202,6 +204,7 @@ var LangText={
|
|||||||
"l44": "最大体積速度は線材によって異なります。",
|
"l44": "最大体積速度は線材によって異なります。",
|
||||||
"l45": "ノズルの材質、口径、印刷温度などが最大体積速度に影響します。",
|
"l45": "ノズルの材質、口径、印刷温度などが最大体積速度に影響します。",
|
||||||
"l46": "テスト時の印刷速度は層ごとに増加します。模型の表面に穴ができたり、糸が欠けたりした場合、その層が最大体積速度に達したことを示し、高さの割合から最大体積速度を算出します。",
|
"l46": "テスト時の印刷速度は層ごとに増加します。模型の表面に穴ができたり、糸が欠けたりした場合、その層が最大体積速度に達したことを示し、高さの割合から最大体積速度を算出します。",
|
||||||
|
"l47": "WIKIで解決策を見つけることもできます.",
|
||||||
},
|
},
|
||||||
"fr": {
|
"fr": {
|
||||||
"t1": "Guide de l'utilisateur",
|
"t1": "Guide de l'utilisateur",
|
||||||
@@ -270,6 +273,7 @@ var LangText={
|
|||||||
"l44": "Différents filaments ont une vitesse de volume maximale différente.",
|
"l44": "Différents filaments ont une vitesse de volume maximale différente.",
|
||||||
"l45": "Le matériau de la buse, le calibre, la température d’impression, etc., affecteront la vitesse de volume maximum.",
|
"l45": "Le matériau de la buse, le calibre, la température d’impression, etc., affecteront la vitesse de volume maximum.",
|
||||||
"l46": "Pendant l’essai, la vitesse d’impression augmentera couche par couche. Quand il y a un trou ou un fil manquant sur la surface du modèle, cela indique que la couche a atteint la vitesse volumique maximale, et la vitesse volumique maximale est calculée selon le rapport de la hauteur.",
|
"l46": "Pendant l’essai, la vitesse d’impression augmentera couche par couche. Quand il y a un trou ou un fil manquant sur la surface du modèle, cela indique que la couche a atteint la vitesse volumique maximale, et la vitesse volumique maximale est calculée selon le rapport de la hauteur.",
|
||||||
|
"l47": "Ou vous pouvez trouver une solution via WIKI.",
|
||||||
},
|
},
|
||||||
"de": {
|
"de": {
|
||||||
"t1": "Benutzerhandbuch",
|
"t1": "Benutzerhandbuch",
|
||||||
@@ -338,6 +342,7 @@ var LangText={
|
|||||||
"l44": "Es gibt eine vielzahl Von lichtern mit maximale geschwindigkeit.",
|
"l44": "Es gibt eine vielzahl Von lichtern mit maximale geschwindigkeit.",
|
||||||
"l45": "Die düsen, der durchmesser, die drucktemperatur all das beeinflusst die maximale geschwindigkeit.",
|
"l45": "Die düsen, der durchmesser, die drucktemperatur all das beeinflusst die maximale geschwindigkeit.",
|
||||||
"l46": "Bei den tests wird die druckgeschwindigkeit etage für etage erhöht Wenn eine öffnung Oder keine linie in der oberfläche eines modells angezeigt wird, zeigt sie an, dass sie die höchstgeschwindigkeit erreicht hat und dass die höchste geschwindigkeit nach höhe angegeben wird.",
|
"l46": "Bei den tests wird die druckgeschwindigkeit etage für etage erhöht Wenn eine öffnung Oder keine linie in der oberfläche eines modells angezeigt wird, zeigt sie an, dass sie die höchstgeschwindigkeit erreicht hat und dass die höchste geschwindigkeit nach höhe angegeben wird.",
|
||||||
|
"l47": "Oder Sie finden eine Lösung über WIKI.",
|
||||||
},
|
},
|
||||||
"be": {
|
"be": {
|
||||||
"t1": "Кіраўніцтва карыстальніка",
|
"t1": "Кіраўніцтва карыстальніка",
|
||||||
@@ -406,6 +411,7 @@ var LangText={
|
|||||||
"l44": "Различные нити накала имеют разную максимальную объемную скорость.",
|
"l44": "Различные нити накала имеют разную максимальную объемную скорость.",
|
||||||
"l45": "Материал сопла, калибр, температура печати и т.д., повлияет на максимальную объемную скорость.",
|
"l45": "Материал сопла, калибр, температура печати и т.д., повлияет на максимальную объемную скорость.",
|
||||||
"l46": "Во время теста скорость печати будет увеличиваться слой за слоем. Если на поверхности модели имеется отверстие или недостающая проволока, это указывает на то, что слой достиг максимальной объемной скорости, а максимальная объемная скорость рассчитывается в соответствии с отношением высоты.",
|
"l46": "Во время теста скорость печати будет увеличиваться слой за слоем. Если на поверхности модели имеется отверстие или недостающая проволока, это указывает на то, что слой достиг максимальной объемной скорости, а максимальная объемная скорость рассчитывается в соответствии с отношением высоты.",
|
||||||
|
"l47": "Или вы можете найти решение через WIKI.",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ li {
|
|||||||
}
|
}
|
||||||
.accordion > li ol {
|
.accordion > li ol {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background-color: #333;
|
background-color: #333333;
|
||||||
}
|
}
|
||||||
.accordion > li ol li {
|
.accordion > li ol li {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|||||||
BIN
resources/web/guide/img/QIDILink.png
Normal file
|
After Width: | Height: | Size: 502 KiB |
BIN
resources/web/guide/img/X-Plus 4.png
Normal file
|
After Width: | Height: | Size: 84 KiB |
BIN
resources/web/guide/img/X-Plus4Poster.png
Normal file
|
After Width: | Height: | Size: 1.3 MiB |
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
@@ -61,6 +61,10 @@
|
|||||||
<div class="MenuBtnIcon"><img src="img/MenuBtnIcon.svg"/></div>
|
<div class="MenuBtnIcon"><img src="img/MenuBtnIcon.svg"/></div>
|
||||||
<div class="trans" tid="t18"></div>
|
<div class="trans" tid="t18"></div>
|
||||||
</li>
|
</li>
|
||||||
|
<li menu="QIDILink" class="MenuBtn" onClick="GotoMenu('QIDILink')">
|
||||||
|
<div class="MenuBtnIcon"><img src="img/MenuBtnIcon.svg"/></div>
|
||||||
|
<div>QIDI Link</div>
|
||||||
|
</li>
|
||||||
<li menu="ModelDownload" class="MenuBtn" onClick="GotoMenu('ModelDownload')">
|
<li menu="ModelDownload" class="MenuBtn" onClick="GotoMenu('ModelDownload')">
|
||||||
<div class="MenuBtnIcon"><img src="img/MenuBtnIcon.svg"/></div>
|
<div class="MenuBtnIcon"><img src="img/MenuBtnIcon.svg"/></div>
|
||||||
<div class="trans" tid="t13"></div>
|
<div class="trans" tid="t13"></div>
|
||||||
@@ -97,6 +101,10 @@
|
|||||||
<i class="fa fa-caret-right"></i>
|
<i class="fa fa-caret-right"></i>
|
||||||
</label>
|
</label>
|
||||||
<ol>
|
<ol>
|
||||||
|
<li menu="X-Plus 4" class="MenuBtn" onClick="GotoMenu('X-Plus 4')">
|
||||||
|
<div class="MenuBtnIcon"><img src="img/MenuBtnIcon.svg"/></div>
|
||||||
|
<div>X-Plus 4</div>
|
||||||
|
</li>
|
||||||
<li menu="Q1 Pro" class="MenuBtn" onClick="GotoMenu('Q1 Pro')">
|
<li menu="Q1 Pro" class="MenuBtn" onClick="GotoMenu('Q1 Pro')">
|
||||||
<div class="MenuBtnIcon"><img src="img/MenuBtnIcon.svg"/></div>
|
<div class="MenuBtnIcon"><img src="img/MenuBtnIcon.svg"/></div>
|
||||||
<div>Q1 Pro</div>
|
<div>Q1 Pro</div>
|
||||||
@@ -170,6 +178,10 @@
|
|||||||
<div class="AutozoomImage"><img src="img/ExcludeObjects.gif"/></div>
|
<div class="AutozoomImage"><img src="img/ExcludeObjects.gif"/></div>
|
||||||
<div class="ThumbnailTitle trans" tid="t18"></div>
|
<div class="ThumbnailTitle trans" tid="t18"></div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="Thumbnail" onClick="GotoMenu('QIDILink')">
|
||||||
|
<div class="AutozoomImage"><img src="img/QIDILink.png"/></div>
|
||||||
|
<div class="ThumbnailTitle">QIDI Link</div>
|
||||||
|
</div>
|
||||||
<div class="Thumbnail" onClick="GotoMenu('ModelDownload')">
|
<div class="Thumbnail" onClick="GotoMenu('ModelDownload')">
|
||||||
<div class="AutozoomImage"><img src="img/DownloadModel.png"/></div>
|
<div class="AutozoomImage"><img src="img/DownloadModel.png"/></div>
|
||||||
<div class="ThumbnailTitle trans" tid="t13"></div>
|
<div class="ThumbnailTitle trans" tid="t13"></div>
|
||||||
@@ -244,6 +256,11 @@
|
|||||||
<div class="AutozoomImage"><img src="img/ExcludeObjects.gif"/></div>
|
<div class="AutozoomImage"><img src="img/ExcludeObjects.gif"/></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="IntroduceBoard" board="QIDILink">
|
||||||
|
<div class="IntroduceTitle">QIDI Link</div>
|
||||||
|
<div class="AutozoomImage"><img src="img/QIDILink.png"/></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="IntroduceBoard" board="ModelDownload">
|
<div class="IntroduceBoard" board="ModelDownload">
|
||||||
<div class="IntroduceTitle trans" tid="t13"></div>
|
<div class="IntroduceTitle trans" tid="t13"></div>
|
||||||
<div class="IntroduceTextBold trans" tid="l1"></div>
|
<div class="IntroduceTextBold trans" tid="l1"></div>
|
||||||
@@ -314,10 +331,16 @@
|
|||||||
<div class="IntroduceText trans" tid="l46"></div>
|
<div class="IntroduceText trans" tid="l46"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="IntroduceBoard" board="X-Plus 4">
|
||||||
|
<div class="AutozoomImage"><img src="img/X-Plus4Poster.png"/></div>
|
||||||
|
<div class="IntroduceTextBold trans" tid="l0"></div>
|
||||||
|
<div class="IntroduceText">https://qidi3d.com/products/qidi-x-plus-4</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="IntroduceBoard" board="Q1 Pro">
|
<div class="IntroduceBoard" board="Q1 Pro">
|
||||||
<div class="AutozoomImage"><img src="img/Q1 ProPoster.png"/></div>
|
<div class="AutozoomImage"><img src="img/Q1 ProPoster.png"/></div>
|
||||||
<div class="IntroduceTextBold trans" tid="l0"></div>
|
<div class="IntroduceTextBold trans" tid="l0"></div>
|
||||||
<div class="IntroduceText">https://qidi3d.com</div>
|
<div class="IntroduceText">https://qidi3d.com/products/q1-pro-3d-printer</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="IntroduceBoard" board="X-MAX 3">
|
<div class="IntroduceBoard" board="X-MAX 3">
|
||||||
@@ -595,7 +618,18 @@
|
|||||||
<div class="IntroduceTitle trans" tid="t6"></div>
|
<div class="IntroduceTitle trans" tid="t6"></div>
|
||||||
<div class="IntroduceText trans" tid="l2"></div>
|
<div class="IntroduceText trans" tid="l2"></div>
|
||||||
<div class="IntroduceText trans" tid="l3"></div>
|
<div class="IntroduceText trans" tid="l3"></div>
|
||||||
|
<div><br></div>
|
||||||
|
<div class="IntroduceText trans" tid="l47"></div>
|
||||||
|
<div class="IntroduceText">https://wiki.qidi3d.com</div>
|
||||||
<div class="EmailBlock">
|
<div class="EmailBlock">
|
||||||
|
<div class="PrinterBlock">
|
||||||
|
<div class="CenterImage"><img src="img/X-Plus 4.png"/></div>
|
||||||
|
<div class="ThumbnailTitle">X-Plus 4</div>
|
||||||
|
<div class="IntroduceText">
|
||||||
|
<b>E-mail:</b><br/>Plus4support@qidi3d.com<br>Plus4Ams@qidi3d.com<br/><br>
|
||||||
|
<b>Skype:</b><br/>Plus4support@qidi3d.com
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="PrinterBlock">
|
<div class="PrinterBlock">
|
||||||
<div class="CenterImage"><img src="img/Q1 Pro.png"/></div>
|
<div class="CenterImage"><img src="img/Q1 Pro.png"/></div>
|
||||||
<div class="ThumbnailTitle">Q1 Pro</div>
|
<div class="ThumbnailTitle">Q1 Pro</div>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ body {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
/* <20><>ҳ<EFBFBD><D2B3>ռ<EFBFBD><D5BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĸ߶<C4B8> */
|
/* <20><>ҳ<EFBFBD><D2B3>ռ<EFBFBD><D5BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĸ߶<C4B8> */
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
|
background: #EEEEEE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#GifBoard {
|
#GifBoard {
|
||||||
|
|||||||
BIN
resources/web/qidi/link_connection.png
Normal file
|
After Width: | Height: | Size: 502 KiB |
28
resources/web/qidi/link_missing_connection.html
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Printer Connection Required</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="css/home.css" />
|
||||||
|
<script type="text/javascript" src="../data/text.js"></script>
|
||||||
|
<script type="text/javascript" src="../guide/js/jquery-3.6.0.min.js"></script>
|
||||||
|
<script type="text/javascript" src="../guide/js/json2.js"></script>
|
||||||
|
<script type="text/javascript" src="../guide/js/globalapi.js"></script>
|
||||||
|
<script type="text/javascript" src="../guide/js/home.js"></script>
|
||||||
|
</head>
|
||||||
|
<body onLoad="OnInit()">
|
||||||
|
<div id="GifBoard">
|
||||||
|
<div class="GifBlock">
|
||||||
|
<div class="UG_TITLE trans" tid="t4"></div>
|
||||||
|
<div class="UG_DESC trans" tid="wk2">
|
||||||
|
Please set up your printer connection to view the device.
|
||||||
|
</div>
|
||||||
|
<div class="UG_IMG"><img src="link_connection.png" /></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!--<h1 class="trans" tid="t4">Printer Connection</h1>
|
||||||
|
<p class="trans">Please set up your printer connection to view the device.</p>
|
||||||
|
<img src="setup_connection.gif" alt="Printer connection setup demonstration" style="max-width: 100%; height: auto; display: block;"/>-->
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 1.7 MiB |
@@ -26,6 +26,8 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
//B64
|
||||||
|
#include "nlohmann/json.hpp"
|
||||||
#include <boost/algorithm/string/predicate.hpp>
|
#include <boost/algorithm/string/predicate.hpp>
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
#include <boost/nowide/args.hpp>
|
#include <boost/nowide/args.hpp>
|
||||||
|
|||||||
@@ -211,11 +211,33 @@ void AppConfig::set_defaults()
|
|||||||
|
|
||||||
if (get("sys_menu_enabled").empty())
|
if (get("sys_menu_enabled").empty())
|
||||||
set("sys_menu_enabled", "1");
|
set("sys_menu_enabled", "1");
|
||||||
//B45
|
|
||||||
|
#endif // _WIN32
|
||||||
|
// B45
|
||||||
if (get("machine_list_minification").empty())
|
if (get("machine_list_minification").empty())
|
||||||
set("machine_list_minification", "1");
|
set("machine_list_minification", "1");
|
||||||
#endif // _WIN32
|
|
||||||
|
|
||||||
|
//B64
|
||||||
|
if (get("user_token").empty())
|
||||||
|
set("user_token", "");
|
||||||
|
|
||||||
|
//y5
|
||||||
|
if(get("user_head_url").empty())
|
||||||
|
set("user_head_url", "");
|
||||||
|
|
||||||
|
if(get("user_head_name").empty())
|
||||||
|
set("user_head_name", "");
|
||||||
|
|
||||||
|
if (get("sending_interval").empty()) {
|
||||||
|
set("sending_interval", "5");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (get("max_send").empty()) {
|
||||||
|
set("max_send", "3");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (get("machine_list_net").empty())
|
||||||
|
set("machine_list_net", "0");
|
||||||
// Remove legacy window positions/sizes
|
// Remove legacy window positions/sizes
|
||||||
erase("", "main_frame_maximized");
|
erase("", "main_frame_maximized");
|
||||||
erase("", "main_frame_pos");
|
erase("", "main_frame_pos");
|
||||||
|
|||||||
@@ -41,8 +41,8 @@ BeadingStrategyPtr BeadingStrategyFactory::makeStrategy(const coord_t preferred_
|
|||||||
BOOST_LOG_TRIVIAL(trace) << "Applying the Widening Beading meta-strategy with minimum input width " << min_feature_size << " and minimum output width " << min_bead_width << ".";
|
BOOST_LOG_TRIVIAL(trace) << "Applying the Widening Beading meta-strategy with minimum input width " << min_feature_size << " and minimum output width " << min_bead_width << ".";
|
||||||
ret = std::make_unique<WideningBeadingStrategy>(std::move(ret), min_feature_size, min_bead_width);
|
ret = std::make_unique<WideningBeadingStrategy>(std::move(ret), min_feature_size, min_bead_width);
|
||||||
}
|
}
|
||||||
|
//w39
|
||||||
if (outer_wall_offset > 0) {
|
if (outer_wall_offset != 0){//if (outer_wall_offset > 0) {
|
||||||
BOOST_LOG_TRIVIAL(trace) << "Applying the OuterWallOffset meta-strategy with offset = " << outer_wall_offset << ".";
|
BOOST_LOG_TRIVIAL(trace) << "Applying the OuterWallOffset meta-strategy with offset = " << outer_wall_offset << ".";
|
||||||
ret = std::make_unique<OuterWallInsetBeadingStrategy>(outer_wall_offset, std::move(ret));
|
ret = std::make_unique<OuterWallInsetBeadingStrategy>(outer_wall_offset, std::move(ret));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,29 @@ public:
|
|||||||
: BoundingBoxBase(points.begin(), points.end())
|
: BoundingBoxBase(points.begin(), points.end())
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void reset() { this->defined = false; this->min = PointType::Zero(); this->max = PointType::Zero(); }
|
void reset()
|
||||||
|
{
|
||||||
|
this->defined = false;
|
||||||
|
this->min = PointType::Zero();
|
||||||
|
this->max = PointType::Zero();
|
||||||
|
}
|
||||||
|
// B66
|
||||||
|
Polygon polygon(bool is_scaled = false) const
|
||||||
|
{
|
||||||
|
Polygon polygon;
|
||||||
|
polygon.points.clear();
|
||||||
|
polygon.points.resize(4);
|
||||||
|
double scale_factor = 1 / (is_scaled ? SCALING_FACTOR : 1);
|
||||||
|
polygon.points[0](0) = this->min(0) * scale_factor;
|
||||||
|
polygon.points[0](1) = this->min(1) * scale_factor;
|
||||||
|
polygon.points[1](0) = this->max(0) * scale_factor;
|
||||||
|
polygon.points[1](1) = this->min(1) * scale_factor;
|
||||||
|
polygon.points[2](0) = this->max(0) * scale_factor;
|
||||||
|
polygon.points[2](1) = this->max(1) * scale_factor;
|
||||||
|
polygon.points[3](0) = this->min(0) * scale_factor;
|
||||||
|
polygon.points[3](1) = this->max(1) * scale_factor;
|
||||||
|
return polygon;
|
||||||
|
};
|
||||||
void merge(const PointType &point);
|
void merge(const PointType &point);
|
||||||
void merge(const PointsType &points);
|
void merge(const PointsType &points);
|
||||||
void merge(const BoundingBoxBase<PointType, PointsType> &bb);
|
void merge(const BoundingBoxBase<PointType, PointsType> &bb);
|
||||||
|
|||||||
@@ -311,46 +311,42 @@ BuildVolume::ObjectState BuildVolume::object_state(const indexed_triangle_set& i
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//B52
|
// B52 //B66
|
||||||
BuildVolume::ObjectState BuildVolume::volume_state_bbox(const BoundingBoxf3& volume_bbox, bool ignore_bottom) const
|
BuildVolume::ObjectState BuildVolume::volume_state_bbox(const BoundingBoxf3& volume_bbox, bool ignore_bottom) const
|
||||||
{
|
{
|
||||||
assert(m_type == Type::Rectangle);
|
assert(m_type == Type::Rectangle);
|
||||||
BoundingBox3Base<Vec3d> build_volume = this->bounding_volume().inflated(SceneEpsilon);
|
BoundingBox3Base<Vec3d> build_volume = this->bounding_volume().inflated(SceneEpsilon);
|
||||||
std::vector<BoundingBox3Base<Vec3d>> exclude_build_volume;
|
if (m_max_print_height == 0.0)
|
||||||
|
build_volume.max.z() = std::numeric_limits<double>::max();
|
||||||
|
if (ignore_bottom)
|
||||||
|
build_volume.min.z() = -std::numeric_limits<double>::max();
|
||||||
|
|
||||||
|
return build_volume.max.z() <= -SceneEpsilon ? ObjectState::Below :
|
||||||
|
build_volume.contains(volume_bbox) ? ObjectState::Inside :
|
||||||
|
build_volume.intersects(volume_bbox) ? ObjectState::Colliding :
|
||||||
|
ObjectState::Outside;
|
||||||
|
}
|
||||||
|
|
||||||
|
// B66
|
||||||
|
BuildVolume::ObjectState BuildVolume::check_outside(Polygon hull) const
|
||||||
|
{
|
||||||
|
if (m_exclude_bed_shape.size() > 0) {
|
||||||
for (int i = 1; i < m_exclude_bed_shape.size(); i += 7) {
|
for (int i = 1; i < m_exclude_bed_shape.size(); i += 7) {
|
||||||
std::vector<Vec2d> tem_exclude_bed_shap;
|
std::vector<Vec2d> tem_exclude_bed_shap;
|
||||||
for (int j = 1; j < 6; j++)
|
for (int j = 1; j < 6; j++)
|
||||||
tem_exclude_bed_shap.push_back(m_exclude_bed_shape[i + j]);
|
tem_exclude_bed_shap.push_back(m_exclude_bed_shape[i + j]);
|
||||||
BoundingBoxf tem_bboxf = get_extents(tem_exclude_bed_shap);
|
BoundingBoxf tem_bboxf = get_extents(tem_exclude_bed_shap);
|
||||||
auto tem_exclude_bboxf = BoundingBoxf3{to_3d(tem_bboxf.min, 0.), to_3d(tem_bboxf.max, m_max_print_height)};
|
auto tem_exclude_bboxf = BoundingBoxf3{to_3d(tem_bboxf.min, 0.), to_3d(tem_bboxf.max, m_max_print_height)};
|
||||||
BoundingBox3Base<Vec3d> tem_build_volume = tem_exclude_bboxf.inflated(SceneEpsilon);
|
Slic3r::Polygon p = tem_exclude_bboxf.polygon(true); // instance convex hull is scaled, so we need to scale here
|
||||||
exclude_build_volume.push_back(tem_build_volume);
|
if (intersection({p}, {hull}).empty() == false) {
|
||||||
}
|
return ObjectState::Colliding;
|
||||||
|
|
||||||
bool is_contain = false;
|
|
||||||
bool is_intersect = false;
|
|
||||||
|
|
||||||
for (const auto &tem_build_volume : exclude_build_volume) {
|
|
||||||
if (tem_build_volume.contains(volume_bbox)) {
|
|
||||||
is_contain=true;
|
|
||||||
is_intersect = false;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (tem_build_volume.intersects(volume_bbox)) {
|
|
||||||
is_contain = false;
|
|
||||||
is_intersect = true;
|
|
||||||
}
|
}
|
||||||
|
return ObjectState::Inside;
|
||||||
|
} else {
|
||||||
|
return ObjectState::Inside;
|
||||||
}
|
}
|
||||||
if (m_max_print_height == 0.0)
|
|
||||||
build_volume.max.z() = std::numeric_limits<double>::max();
|
|
||||||
if (ignore_bottom)
|
|
||||||
build_volume.min.z() = -std::numeric_limits<double>::max();
|
|
||||||
return build_volume.max.z() <= - SceneEpsilon ? ObjectState::Below :
|
|
||||||
is_contain ? ObjectState::Outside :
|
|
||||||
is_intersect ? ObjectState::Outside :
|
|
||||||
build_volume.contains(volume_bbox) ? ObjectState::Inside :
|
|
||||||
build_volume.intersects(volume_bbox) ? ObjectState::Colliding :
|
|
||||||
ObjectState::Outside;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//B52
|
//B52
|
||||||
@@ -369,32 +365,33 @@ bool BuildVolume::all_paths_inside(const GCodeProcessorResult& paths, const Boun
|
|||||||
build_volume.max.z() = std::numeric_limits<double>::max();
|
build_volume.max.z() = std::numeric_limits<double>::max();
|
||||||
if (ignore_bottom)
|
if (ignore_bottom)
|
||||||
build_volume.min.z() = -std::numeric_limits<double>::max();
|
build_volume.min.z() = -std::numeric_limits<double>::max();
|
||||||
std::vector<BoundingBox3Base<Vec3d>> exclude_build_volume;
|
// B66
|
||||||
|
Points pts;
|
||||||
|
for (const GCodeProcessorResult::MoveVertex &move : paths.moves) {
|
||||||
|
if (move.type == EMoveType::Extrude && move.extrusion_role != GCodeExtrusionRole::Custom && move.width != 0.0f &&
|
||||||
|
move.height != 0.0f)
|
||||||
|
pts.emplace_back(Point(scale_(move.position.x()), scale_(move.position.y())));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((build_volume.contains(paths_bbox))) {
|
||||||
|
if (m_exclude_bed_shape.size() > 0) {
|
||||||
|
Slic3r::Polygon convex_hull_2d = Slic3r::Geometry::convex_hull(std::move(pts));
|
||||||
for (int i = 1; i < m_exclude_bed_shape.size(); i += 7) {
|
for (int i = 1; i < m_exclude_bed_shape.size(); i += 7) {
|
||||||
std::vector<Vec2d> tem_exclude_bed_shap;
|
std::vector<Vec2d> tem_exclude_bed_shap;
|
||||||
for (int j = 1; j < 5; j++)
|
for (int j = 1; j < 6; j++)
|
||||||
tem_exclude_bed_shap.push_back(m_exclude_bed_shape[i + j]);
|
tem_exclude_bed_shap.push_back(m_exclude_bed_shape[i + j]);
|
||||||
BoundingBoxf tem_bboxf = get_extents(tem_exclude_bed_shap);
|
BoundingBoxf tem_bboxf = get_extents(tem_exclude_bed_shap);
|
||||||
auto tem_exclude_bboxf = BoundingBoxf3{to_3d(tem_bboxf.min, 0.), to_3d(tem_bboxf.max, m_max_print_height)};
|
auto tem_exclude_bboxf = BoundingBoxf3{to_3d(tem_bboxf.min, 0.), to_3d(tem_bboxf.max, m_max_print_height)};
|
||||||
BoundingBox3Base<Vec3d> tem_build_volume = tem_exclude_bboxf.inflated(SceneEpsilon);
|
Slic3r::Polygon p = tem_exclude_bboxf.polygon(true); // instance convex hull is scaled, so we need to scale here
|
||||||
exclude_build_volume.push_back(tem_build_volume);
|
if (intersection({p}, {convex_hull_2d}).empty() == false) {
|
||||||
}
|
return false;
|
||||||
|
|
||||||
bool is_contain = false;
|
|
||||||
bool is_intersect = false;
|
|
||||||
|
|
||||||
for (const auto &tem_build_volume : exclude_build_volume) {
|
|
||||||
if (tem_build_volume.contains(paths_bbox)) {
|
|
||||||
is_contain = true;
|
|
||||||
is_intersect = false;
|
|
||||||
break;
|
break;
|
||||||
} else if (tem_build_volume.intersects(paths_bbox)) {
|
}
|
||||||
is_contain = false;
|
}
|
||||||
is_intersect = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (build_volume.contains(paths_bbox) && !is_contain && !is_intersect);
|
return build_volume.contains(paths_bbox);
|
||||||
}
|
}
|
||||||
case Type::Circle:
|
case Type::Circle:
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -87,6 +87,8 @@ public:
|
|||||||
// Called by GLVolumeCollection::check_outside_state() after an object is manipulated with gizmos for example.
|
// Called by GLVolumeCollection::check_outside_state() after an object is manipulated with gizmos for example.
|
||||||
// Called for a rectangular bed:
|
// Called for a rectangular bed:
|
||||||
ObjectState volume_state_bbox(const BoundingBoxf3& volume_bbox, bool ignore_bottom = true) const;
|
ObjectState volume_state_bbox(const BoundingBoxf3& volume_bbox, bool ignore_bottom = true) const;
|
||||||
|
// B66
|
||||||
|
BuildVolume::ObjectState check_outside(Polygon hull) const;
|
||||||
|
|
||||||
// 2) Test called on G-code paths.
|
// 2) Test called on G-code paths.
|
||||||
// Using BedEpsilon for all tests.
|
// Using BedEpsilon for all tests.
|
||||||
|
|||||||
@@ -88,6 +88,10 @@ set(SLIC3R_SOURCES
|
|||||||
Fill/FillBase.hpp
|
Fill/FillBase.hpp
|
||||||
Fill/FillConcentric.cpp
|
Fill/FillConcentric.cpp
|
||||||
Fill/FillConcentric.hpp
|
Fill/FillConcentric.hpp
|
||||||
|
Fill/FillConcentricInternal.cpp
|
||||||
|
Fill/FillConcentricInternal.hpp
|
||||||
|
Fill/FillCrossHatch.cpp
|
||||||
|
Fill/FillCrossHatch.hpp
|
||||||
Fill/FillEnsuring.cpp
|
Fill/FillEnsuring.cpp
|
||||||
Fill/FillEnsuring.hpp
|
Fill/FillEnsuring.hpp
|
||||||
Fill/FillHoneycomb.cpp
|
Fill/FillHoneycomb.cpp
|
||||||
|
|||||||
@@ -66,7 +66,8 @@ namespace ClipperUtils {
|
|||||||
// Useful as an optimization for expensive ClipperLib operations, for example when clipping source polygons one by one
|
// Useful as an optimization for expensive ClipperLib operations, for example when clipping source polygons one by one
|
||||||
// with a set of polygons covering the whole layer below.
|
// with a set of polygons covering the whole layer below.
|
||||||
template<typename PointsType>
|
template<typename PointsType>
|
||||||
inline void clip_clipper_polygon_with_subject_bbox_templ(const PointsType &src, const BoundingBox &bbox, PointsType &out)
|
//w38
|
||||||
|
inline void clip_clipper_polygon_with_subject_bbox_templ(const PointsType &src, const BoundingBox &bbox, PointsType &out,const bool get_entire_polygons=false)
|
||||||
{
|
{
|
||||||
using PointType = typename PointsType::value_type;
|
using PointType = typename PointsType::value_type;
|
||||||
|
|
||||||
@@ -121,6 +122,8 @@ namespace ClipperUtils {
|
|||||||
|
|
||||||
void clip_clipper_polygon_with_subject_bbox(const Points &src, const BoundingBox &bbox, Points &out)
|
void clip_clipper_polygon_with_subject_bbox(const Points &src, const BoundingBox &bbox, Points &out)
|
||||||
{ clip_clipper_polygon_with_subject_bbox_templ(src, bbox, out); }
|
{ clip_clipper_polygon_with_subject_bbox_templ(src, bbox, out); }
|
||||||
|
//w38
|
||||||
|
void clip_clipper_polygon_with_subject_bbox(const Points &src, const BoundingBox &bbox, Points &out, const bool get_entire_polygons) { clip_clipper_polygon_with_subject_bbox_templ(src, bbox, out, get_entire_polygons); }
|
||||||
void clip_clipper_polygon_with_subject_bbox(const ZPoints &src, const BoundingBox &bbox, ZPoints &out)
|
void clip_clipper_polygon_with_subject_bbox(const ZPoints &src, const BoundingBox &bbox, ZPoints &out)
|
||||||
{ clip_clipper_polygon_with_subject_bbox_templ(src, bbox, out); }
|
{ clip_clipper_polygon_with_subject_bbox_templ(src, bbox, out); }
|
||||||
|
|
||||||
@@ -149,6 +152,14 @@ namespace ClipperUtils {
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//w38
|
||||||
|
[[nodiscard]] Polygon clip_clipper_polygon_with_subject_bbox(const Polygon &src, const BoundingBox &bbox, const bool get_entire_polygons)
|
||||||
|
{
|
||||||
|
Polygon out;
|
||||||
|
clip_clipper_polygon_with_subject_bbox(src.points, bbox, out.points, get_entire_polygons);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]] Polygons clip_clipper_polygons_with_subject_bbox(const Polygons &src, const BoundingBox &bbox)
|
[[nodiscard]] Polygons clip_clipper_polygons_with_subject_bbox(const Polygons &src, const BoundingBox &bbox)
|
||||||
{
|
{
|
||||||
Polygons out;
|
Polygons out;
|
||||||
@@ -172,7 +183,36 @@ namespace ClipperUtils {
|
|||||||
out.end());
|
out.end());
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
//w38
|
||||||
|
[[nodiscard]] Polygons clip_clipper_polygons_with_subject_bbox(const ExPolygon & src,
|
||||||
|
const BoundingBox &bbox,
|
||||||
|
const bool get_entire_polygons)
|
||||||
|
{
|
||||||
|
Polygons out;
|
||||||
|
out.reserve(src.num_contours());
|
||||||
|
out.emplace_back(clip_clipper_polygon_with_subject_bbox(src.contour, bbox, get_entire_polygons));
|
||||||
|
for (const Polygon &p : src.holes)
|
||||||
|
out.emplace_back(clip_clipper_polygon_with_subject_bbox(p, bbox, get_entire_polygons));
|
||||||
|
out.erase(std::remove_if(out.begin(), out.end(), [](const Polygon &polygon) { return polygon.empty(); }), out.end());
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
//w38
|
||||||
|
[[nodiscard]] Polygons clip_clipper_polygons_with_subject_bbox(const ExPolygons & src,
|
||||||
|
const BoundingBox &bbox,
|
||||||
|
const bool get_entire_polygons)
|
||||||
|
{
|
||||||
|
Polygons out;
|
||||||
|
out.reserve(number_polygons(src));
|
||||||
|
for (const ExPolygon &p : src) {
|
||||||
|
Polygons temp = clip_clipper_polygons_with_subject_bbox(p, bbox, get_entire_polygons);
|
||||||
|
out.insert(out.end(), temp.begin(), temp.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
out.erase(std::remove_if(out.begin(), out.end(), [](const Polygon &polygon) { return polygon.empty(); }), out.end());
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static ExPolygons PolyTreeToExPolygons(ClipperLib::PolyTree &&polytree)
|
static ExPolygons PolyTreeToExPolygons(ClipperLib::PolyTree &&polytree)
|
||||||
{
|
{
|
||||||
@@ -793,6 +833,7 @@ Slic3r::ExPolygons union_ex(const Slic3r::ExPolygons &subject, const Slic3r::Pol
|
|||||||
Slic3r::ExPolygons union_ex(const Slic3r::Surfaces &subject)
|
Slic3r::ExPolygons union_ex(const Slic3r::Surfaces &subject)
|
||||||
{ return PolyTreeToExPolygons(clipper_do_polytree(ClipperLib::ctUnion, ClipperUtils::SurfacesProvider(subject), ClipperUtils::EmptyPathsProvider(), ClipperLib::pftNonZero)); }
|
{ return PolyTreeToExPolygons(clipper_do_polytree(ClipperLib::ctUnion, ClipperUtils::SurfacesProvider(subject), ClipperUtils::EmptyPathsProvider(), ClipperLib::pftNonZero)); }
|
||||||
|
|
||||||
|
|
||||||
template<typename PathsProvider1, typename PathsProvider2>
|
template<typename PathsProvider1, typename PathsProvider2>
|
||||||
Polylines _clipper_pl_open(ClipperLib::ClipType clipType, PathsProvider1 &&subject, PathsProvider2 &&clip)
|
Polylines _clipper_pl_open(ClipperLib::ClipType clipType, PathsProvider1 &&subject, PathsProvider2 &&clip)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -326,9 +326,23 @@ namespace ClipperUtils {
|
|||||||
[[nodiscard]] ZPoints clip_clipper_polygon_with_subject_bbox(const ZPoints &src, const BoundingBox &bbox);
|
[[nodiscard]] ZPoints clip_clipper_polygon_with_subject_bbox(const ZPoints &src, const BoundingBox &bbox);
|
||||||
void clip_clipper_polygon_with_subject_bbox(const Polygon &src, const BoundingBox &bbox, Polygon &out);
|
void clip_clipper_polygon_with_subject_bbox(const Polygon &src, const BoundingBox &bbox, Polygon &out);
|
||||||
[[nodiscard]] Polygon clip_clipper_polygon_with_subject_bbox(const Polygon &src, const BoundingBox &bbox);
|
[[nodiscard]] Polygon clip_clipper_polygon_with_subject_bbox(const Polygon &src, const BoundingBox &bbox);
|
||||||
|
|
||||||
|
//w38
|
||||||
|
[[nodiscard]] Polygons clip_clipper_polygons_with_subject_bbox(const ExPolygon & src,
|
||||||
|
const BoundingBox &bbox,
|
||||||
|
const bool get_entire_polygons);
|
||||||
[[nodiscard]] Polygons clip_clipper_polygons_with_subject_bbox(const Polygons &src, const BoundingBox &bbox);
|
[[nodiscard]] Polygons clip_clipper_polygons_with_subject_bbox(const Polygons &src, const BoundingBox &bbox);
|
||||||
[[nodiscard]] Polygons clip_clipper_polygons_with_subject_bbox(const ExPolygon &src, const BoundingBox &bbox);
|
[[nodiscard]] Polygons clip_clipper_polygons_with_subject_bbox(const ExPolygon &src, const BoundingBox &bbox);
|
||||||
}
|
|
||||||
|
//w38
|
||||||
|
[[nodiscard]] Polygons clip_clipper_polygons_with_subject_bbox(const ExPolygons & src,
|
||||||
|
const BoundingBox &bbox,
|
||||||
|
const bool get_entire_polygons);
|
||||||
|
[[nodiscard]] Polygon clip_clipper_polygon_with_subject_bbox(const Polygon & src,
|
||||||
|
const BoundingBox &bbox,
|
||||||
|
const bool get_entire_polygons);
|
||||||
|
void clip_clipper_polygon_with_subject_bbox(const Points &src, const BoundingBox &bbox, Points &out, const bool get_entire_polygons);
|
||||||
|
}
|
||||||
|
|
||||||
// offset Polygons
|
// offset Polygons
|
||||||
// Wherever applicable, please use the expand() / shrink() variants instead, they convey their purpose better.
|
// Wherever applicable, please use the expand() / shrink() variants instead, they convey their purpose better.
|
||||||
@@ -447,6 +461,7 @@ Slic3r::Polylines diff_pl(const Slic3r::Polylines &subject, const Slic3r::ExPol
|
|||||||
Slic3r::Polylines diff_pl(const Slic3r::Polylines &subject, const Slic3r::ExPolygons &clip);
|
Slic3r::Polylines diff_pl(const Slic3r::Polylines &subject, const Slic3r::ExPolygons &clip);
|
||||||
Slic3r::Polylines diff_pl(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip);
|
Slic3r::Polylines diff_pl(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip);
|
||||||
|
|
||||||
|
|
||||||
inline Slic3r::Lines diff_ln(const Slic3r::Lines &subject, const Slic3r::Polygons &clip)
|
inline Slic3r::Lines diff_ln(const Slic3r::Lines &subject, const Slic3r::Polygons &clip)
|
||||||
{
|
{
|
||||||
return _clipper_ln(ClipperLib::ctDifference, subject, clip);
|
return _clipper_ln(ClipperLib::ctDifference, subject, clip);
|
||||||
@@ -473,6 +488,7 @@ Slic3r::ExPolygons intersection_ex(const Slic3r::Surfaces &subject, const Slic3r
|
|||||||
Slic3r::ExPolygons intersection_ex(const Slic3r::Surfaces &subject, const Slic3r::ExPolygons &clip, ApplySafetyOffset do_safety_offset = ApplySafetyOffset::No);
|
Slic3r::ExPolygons intersection_ex(const Slic3r::Surfaces &subject, const Slic3r::ExPolygons &clip, ApplySafetyOffset do_safety_offset = ApplySafetyOffset::No);
|
||||||
Slic3r::ExPolygons intersection_ex(const Slic3r::Surfaces &subject, const Slic3r::Surfaces &clip, ApplySafetyOffset do_safety_offset = ApplySafetyOffset::No);
|
Slic3r::ExPolygons intersection_ex(const Slic3r::Surfaces &subject, const Slic3r::Surfaces &clip, ApplySafetyOffset do_safety_offset = ApplySafetyOffset::No);
|
||||||
Slic3r::ExPolygons intersection_ex(const Slic3r::SurfacesPtr &subject, const Slic3r::ExPolygons &clip, ApplySafetyOffset do_safety_offset = ApplySafetyOffset::No);
|
Slic3r::ExPolygons intersection_ex(const Slic3r::SurfacesPtr &subject, const Slic3r::ExPolygons &clip, ApplySafetyOffset do_safety_offset = ApplySafetyOffset::No);
|
||||||
|
|
||||||
Slic3r::Polylines intersection_pl(const Slic3r::Polylines &subject, const Slic3r::Polygon &clip);
|
Slic3r::Polylines intersection_pl(const Slic3r::Polylines &subject, const Slic3r::Polygon &clip);
|
||||||
Slic3r::Polylines intersection_pl(const Slic3r::Polyline &subject, const Slic3r::ExPolygon &clip);
|
Slic3r::Polylines intersection_pl(const Slic3r::Polyline &subject, const Slic3r::ExPolygon &clip);
|
||||||
Slic3r::Polylines intersection_pl(const Slic3r::Polylines &subject, const Slic3r::ExPolygon &clip);
|
Slic3r::Polylines intersection_pl(const Slic3r::Polylines &subject, const Slic3r::ExPolygon &clip);
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include <limits>
|
#include <limits>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
void ExtrusionPath::intersect_expolygons(const ExPolygons &collection, ExtrusionEntityCollection* retval) const
|
void ExtrusionPath::intersect_expolygons(const ExPolygons &collection, ExtrusionEntityCollection* retval) const
|
||||||
@@ -112,6 +113,22 @@ Polyline ExtrusionMultiPath::as_polyline() const
|
|||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
//w38
|
||||||
|
bool ExtrusionLoop::make_clockwise()
|
||||||
|
{
|
||||||
|
bool was_ccw = this->polygon().is_counter_clockwise();
|
||||||
|
if (was_ccw)
|
||||||
|
this->reverse_loop();
|
||||||
|
return was_ccw;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ExtrusionLoop::make_counter_clockwise()
|
||||||
|
{
|
||||||
|
bool was_cw = this->polygon().is_clockwise();
|
||||||
|
if (was_cw)
|
||||||
|
this->reverse_loop();
|
||||||
|
return was_cw;
|
||||||
|
}
|
||||||
|
|
||||||
double ExtrusionLoop::area() const
|
double ExtrusionLoop::area() const
|
||||||
{
|
{
|
||||||
@@ -334,4 +351,5 @@ double ExtrusionLoop::min_mm3_per_mm() const
|
|||||||
return min_mm3_per_mm;
|
return min_mm3_per_mm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -326,6 +326,9 @@ public:
|
|||||||
append(dst, p.polyline.points);
|
append(dst, p.polyline.points);
|
||||||
}
|
}
|
||||||
double total_volume() const override { double volume =0.; for (const auto& path : paths) volume += path.total_volume(); return volume; }
|
double total_volume() const override { double volume =0.; for (const auto& path : paths) volume += path.total_volume(); return volume; }
|
||||||
|
//w38
|
||||||
|
bool make_clockwise();
|
||||||
|
bool make_counter_clockwise();
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
bool validate() const {
|
bool validate() const {
|
||||||
@@ -376,6 +379,8 @@ inline void extrusion_entities_append_paths(ExtrusionEntitiesPtr &dst, Polylines
|
|||||||
polylines.clear();
|
polylines.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
inline void extrusion_entities_append_loops(ExtrusionEntitiesPtr &dst, Polygons &&loops, const ExtrusionAttributes &attributes)
|
inline void extrusion_entities_append_loops(ExtrusionEntitiesPtr &dst, Polygons &&loops, const ExtrusionAttributes &attributes)
|
||||||
{
|
{
|
||||||
dst.reserve(dst.size() + loops.size());
|
dst.reserve(dst.size() + loops.size());
|
||||||
|
|||||||
@@ -95,9 +95,13 @@ struct ExtrusionRole : public ExtrusionRoleModifiers
|
|||||||
|
|
||||||
// Special flags describing loop
|
// Special flags describing loop
|
||||||
enum ExtrusionLoopRole {
|
enum ExtrusionLoopRole {
|
||||||
elrDefault,
|
//w38
|
||||||
elrContourInternalPerimeter,
|
elrDefault = 0x0,
|
||||||
elrSkirt,
|
// Loop for the hole, not for the contour
|
||||||
|
elrHole = 0x1,
|
||||||
|
// Loop that is the most closest to infill
|
||||||
|
elrInternal = 0x2,
|
||||||
|
elrSkirt = 0x4,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Be careful when editing this list as many parts of the code depend
|
// Be careful when editing this list as many parts of the code depend
|
||||||
|
|||||||
@@ -20,6 +20,8 @@
|
|||||||
//w21
|
//w21
|
||||||
#include "../ShortestPath.hpp"
|
#include "../ShortestPath.hpp"
|
||||||
//w11
|
//w11
|
||||||
|
//w29
|
||||||
|
#include "FillConcentricInternal.hpp"
|
||||||
|
|
||||||
#include "LayerRegion.hpp"
|
#include "LayerRegion.hpp"
|
||||||
|
|
||||||
@@ -125,9 +127,10 @@ struct SurfaceFill {
|
|||||||
//w11
|
//w11
|
||||||
static bool is_narrow_infill_area(const ExPolygon &expolygon)
|
static bool is_narrow_infill_area(const ExPolygon &expolygon)
|
||||||
{
|
{
|
||||||
|
//w29
|
||||||
ExPolygons offsets = offset_ex(expolygon, -scale_(NARROW_INFILL_AREA_THRESHOLD));
|
ExPolygons offsets = offset_ex(expolygon, -scale_(NARROW_INFILL_AREA_THRESHOLD));
|
||||||
ExPolygons offsets_min = offset_ex(expolygon, -scale_(NARROW_INFILL_AREA_THRESHOLD_MIN));
|
//ExPolygons offsets_min = offset_ex(expolygon, -scale_(NARROW_INFILL_AREA_THRESHOLD_MIN));
|
||||||
if (offsets.empty() && !offsets_min.empty())
|
if (offsets.empty() )
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -340,34 +343,41 @@ std::vector<SurfaceFill> group_fills(const Layer &layer)
|
|||||||
// Use ipEnsuring pattern for all internal Solids.
|
// Use ipEnsuring pattern for all internal Solids.
|
||||||
//w11
|
//w11
|
||||||
if (layer.object()->config().detect_narrow_internal_solid_infill) {
|
if (layer.object()->config().detect_narrow_internal_solid_infill) {
|
||||||
for (size_t i = 0; i < surface_fills.size(); i++) {
|
//w29
|
||||||
|
size_t surface_fills_size = surface_fills.size();
|
||||||
|
for (size_t i = 0; i < surface_fills_size; i++) {
|
||||||
if (surface_fills[i].surface.surface_type != stInternalSolid)
|
if (surface_fills[i].surface.surface_type != stInternalSolid)
|
||||||
continue;
|
continue;
|
||||||
|
//w29
|
||||||
size_t expolygons_size = surface_fills[i].expolygons.size();
|
size_t expolygons_size = surface_fills[i].expolygons.size();
|
||||||
std::vector<size_t> narrow_expolygons_index;
|
std::vector<size_t> narrow_expolygons_index;
|
||||||
narrow_expolygons_index.reserve(expolygons_size);
|
narrow_expolygons_index.reserve(expolygons_size);
|
||||||
|
|
||||||
for (size_t j = 0; j < expolygons_size; j++)
|
for (size_t j = 0; j < expolygons_size; j++)
|
||||||
if (is_narrow_infill_area(surface_fills[i].expolygons[j]))
|
if (is_narrow_infill_area(surface_fills[i].expolygons[j]))
|
||||||
narrow_expolygons_index.push_back(j);
|
narrow_expolygons_index.push_back(j);
|
||||||
|
//w29
|
||||||
if (narrow_expolygons_index.size() == expolygons_size) {
|
if (narrow_expolygons_index.size() == 0) {
|
||||||
surface_fills[i].params.pattern = ipConcentricInternal;
|
continue;
|
||||||
|
} else if (narrow_expolygons_index.size() == expolygons_size) {
|
||||||
|
surface_fills[i].params.pattern = ipConcentric;
|
||||||
} else {
|
} else {
|
||||||
surface_fills[i].params.pattern = ipEnsuring;
|
//w29
|
||||||
}
|
params = surface_fills[i].params;
|
||||||
//w21
|
params.pattern = ipConcentric;
|
||||||
if (narrow_expolygons_index.size() != expolygons_size && narrow_expolygons_index.size() != expolygons_size) {
|
surface_fills.emplace_back(params);
|
||||||
|
surface_fills.back().region_id = surface_fills[i].region_id;
|
||||||
|
surface_fills.back().surface.surface_type = stInternalSolid;
|
||||||
|
surface_fills.back().surface.thickness = surface_fills[i].surface.thickness;
|
||||||
surface_fills.back().region_id_group = surface_fills[i].region_id_group;
|
surface_fills.back().region_id_group = surface_fills[i].region_id_group;
|
||||||
surface_fills.back().no_overlap_expolygons = surface_fills[i].no_overlap_expolygons;
|
surface_fills.back().no_overlap_expolygons = surface_fills[i].no_overlap_expolygons;
|
||||||
}
|
for (size_t j = 0; j < narrow_expolygons_index.size(); j++) {
|
||||||
}
|
surface_fills.back().expolygons.emplace_back(std::move(surface_fills[i].expolygons[narrow_expolygons_index[j]]));
|
||||||
} else {
|
}
|
||||||
for (size_t surface_fill_id = 0; surface_fill_id < surface_fills.size(); ++surface_fill_id)
|
for (int j = narrow_expolygons_index.size() - 1; j >= 0; j--) {
|
||||||
if (SurfaceFill &fill = surface_fills[surface_fill_id]; fill.surface.surface_type == stInternalSolid) {
|
surface_fills[i].expolygons.erase(surface_fills[i].expolygons.begin() + narrow_expolygons_index[j]);
|
||||||
fill.params.pattern = ipEnsuring;
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return surface_fills;
|
return surface_fills;
|
||||||
}
|
}
|
||||||
@@ -525,14 +535,19 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
|
|||||||
f->print_config = &this->object()->print()->config();
|
f->print_config = &this->object()->print()->config();
|
||||||
f->print_object_config = &this->object()->config();
|
f->print_object_config = &this->object()->config();
|
||||||
|
|
||||||
if (surface_fill.params.pattern == ipLightning)
|
//w29
|
||||||
dynamic_cast<FillLightning::Filler*>(f.get())->generator = lightning_generator;
|
if (surface_fill.params.pattern == ipConcentricInternal) {
|
||||||
|
FillConcentricInternal *fill_concentric = dynamic_cast<FillConcentricInternal *>(f.get());
|
||||||
if (surface_fill.params.pattern == ipEnsuring) {
|
assert(fill_concentric != nullptr);
|
||||||
auto *fill_ensuring = dynamic_cast<FillEnsuring *>(f.get());
|
fill_concentric->print_config = &this->object()->print()->config();
|
||||||
assert(fill_ensuring != nullptr);
|
fill_concentric->print_object_config = &this->object()->config();
|
||||||
fill_ensuring->print_region_config = &m_regions[surface_fill.region_id]->region().config();
|
} else if (surface_fill.params.pattern == ipConcentric) {
|
||||||
}
|
FillConcentric *fill_concentric = dynamic_cast<FillConcentric *>(f.get());
|
||||||
|
assert(fill_concentric != nullptr);
|
||||||
|
fill_concentric->print_config = &this->object()->print()->config();
|
||||||
|
fill_concentric->print_object_config = &this->object()->config();
|
||||||
|
} else if (surface_fill.params.pattern == ipLightning)
|
||||||
|
dynamic_cast<FillLightning::Filler *>(f.get())->generator = lightning_generator;
|
||||||
|
|
||||||
// calculate flow spacing for infill pattern generation
|
// calculate flow spacing for infill pattern generation
|
||||||
bool using_internal_flow = ! surface_fill.surface.is_solid() && ! surface_fill.params.bridge;
|
bool using_internal_flow = ! surface_fill.surface.is_solid() && ! surface_fill.params.bridge;
|
||||||
@@ -562,62 +577,60 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
|
|||||||
params.anchor_length_max = surface_fill.params.anchor_length_max;
|
params.anchor_length_max = surface_fill.params.anchor_length_max;
|
||||||
params.resolution = resolution;
|
params.resolution = resolution;
|
||||||
//w14
|
//w14
|
||||||
params.use_arachne = (perimeter_generator == PerimeterGeneratorType::Arachne && surface_fill.params.pattern == ipConcentric) || surface_fill.params.pattern == ipEnsuring || surface_fill.params.pattern == ipConcentricInternal;
|
//w29
|
||||||
|
params.use_arachne = (perimeter_generator == PerimeterGeneratorType::Arachne && surface_fill.params.pattern == ipConcentric) || surface_fill.params.pattern == ipEnsuring || surface_fill.params.pattern == ipConcentric;
|
||||||
params.layer_height = layerm.layer()->height;
|
params.layer_height = layerm.layer()->height;
|
||||||
|
//w29
|
||||||
|
params.flow = surface_fill.params.flow;
|
||||||
|
params.extrusion_role = surface_fill.params.extrusion_role;
|
||||||
|
params.using_internal_flow = !surface_fill.surface.is_solid() && !surface_fill.params.bridge;
|
||||||
|
|
||||||
for (ExPolygon &expoly : surface_fill.expolygons) {
|
for (ExPolygon &expoly : surface_fill.expolygons) {
|
||||||
// Spacing is modified by the filler to indicate adjustments. Reset it for each expolygon.
|
// Spacing is modified by the filler to indicate adjustments. Reset it for each expolygon.
|
||||||
f->spacing = surface_fill.params.spacing;
|
f->spacing = surface_fill.params.spacing;
|
||||||
//w21
|
// w21
|
||||||
f->no_overlap_expolygons = intersection_ex(surface_fill.no_overlap_expolygons, ExPolygons() = {expoly}, ApplySafetyOffset::Yes);
|
f->no_overlap_expolygons = intersection_ex(surface_fill.no_overlap_expolygons, ExPolygons() = {expoly}, ApplySafetyOffset::Yes);
|
||||||
surface_fill.surface.expolygon = std::move(expoly);
|
surface_fill.surface.expolygon = std::move(expoly);
|
||||||
Polylines polylines;
|
Polylines polylines;
|
||||||
ThickPolylines thick_polylines;
|
ThickPolylines thick_polylines;
|
||||||
//w14
|
// w14
|
||||||
if (this->object()->config().detect_narrow_internal_solid_infill &&
|
//w29
|
||||||
(surface_fill.params.pattern == ipConcentricInternal || surface_fill.params.pattern == ipEnsuring)) {
|
/* if (this->object()->config().detect_narrow_internal_solid_infill &&
|
||||||
layerm.region().config().infill_overlap.percent ?
|
(surface_fill.params.pattern == ipConcentricInternal || surface_fill.params.pattern == ipEnsuring)) {
|
||||||
f->overlap = layerm.region().config().perimeter_extrusion_width * layerm.region().config().infill_overlap.value / 100 * (-1) :
|
layerm.region().config().infill_overlap.percent ? f->overlap = layerm.region().config().perimeter_extrusion_width *
|
||||||
f->overlap = float(layerm.region().config().infill_overlap.value);
|
layerm.region().config().infill_overlap.value / 100 * (-1) :
|
||||||
|
f->overlap = float(layerm.region().config().infill_overlap.value);
|
||||||
} else
|
} else
|
||||||
f->overlap = 0;
|
f->overlap = 0;*/
|
||||||
|
//w29
|
||||||
try {
|
f->fill_surface_extrusion(&surface_fill.surface, params, polylines, thick_polylines);
|
||||||
if (params.use_arachne) {
|
|
||||||
thick_polylines = f->fill_surface_arachne(&surface_fill.surface, params);
|
|
||||||
//w21
|
|
||||||
//if (f->layer_id % 2 == 0 && surface_fill.params.pattern == ipConcentricInternal)
|
|
||||||
// std::reverse(thick_polylines.begin(), thick_polylines.end());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
polylines = f->fill_surface(&surface_fill.surface, params);
|
|
||||||
}
|
|
||||||
} catch (InfillFailedException &) {
|
|
||||||
}
|
|
||||||
if (!polylines.empty() || !thick_polylines.empty()) {
|
if (!polylines.empty() || !thick_polylines.empty()) {
|
||||||
// calculate actual flow from spacing (which might have been adjusted by the infill
|
// calculate actual flow from spacing (which might have been adjusted by the infill
|
||||||
// pattern generator)
|
// pattern generator)
|
||||||
double flow_mm3_per_mm = surface_fill.params.flow.mm3_per_mm();
|
double flow_mm3_per_mm = surface_fill.params.flow.mm3_per_mm();
|
||||||
double flow_width = surface_fill.params.flow.width();
|
double flow_width = surface_fill.params.flow.width();
|
||||||
if (using_internal_flow) {
|
if (using_internal_flow) {
|
||||||
// if we used the internal flow we're not doing a solid infill
|
// if we used the internal flow we're not doing a solid infill
|
||||||
// so we can safely ignore the slight variation that might have
|
// so we can safely ignore the slight variation that might have
|
||||||
// been applied to f->spacing
|
// been applied to f->spacing
|
||||||
} else {
|
} else {
|
||||||
Flow new_flow = surface_fill.params.flow.with_spacing(float(f->spacing));
|
Flow new_flow = surface_fill.params.flow.with_spacing(float(f->spacing));
|
||||||
flow_mm3_per_mm = new_flow.mm3_per_mm();
|
flow_mm3_per_mm = new_flow.mm3_per_mm();
|
||||||
flow_width = new_flow.width();
|
flow_width = new_flow.width();
|
||||||
}
|
}
|
||||||
// Save into layer.
|
// Save into layer.
|
||||||
ExtrusionEntityCollection *eec = new ExtrusionEntityCollection();
|
ExtrusionEntityCollection *eec = new ExtrusionEntityCollection();
|
||||||
auto fill_begin = uint32_t(layerm.fills().size());
|
auto fill_begin = uint32_t(layerm.fills().size());
|
||||||
// Only concentric fills are not sorted.
|
// Only concentric fills are not sorted.
|
||||||
eec->no_sort = f->no_sort();
|
eec->no_sort = f->no_sort();
|
||||||
if (params.use_arachne) {
|
if (params.use_arachne) {
|
||||||
for (const ThickPolyline &thick_polyline : thick_polylines) {
|
for (const ThickPolyline &thick_polyline : thick_polylines) {
|
||||||
Flow new_flow = surface_fill.params.flow.with_spacing(float(f->spacing));
|
Flow new_flow = surface_fill.params.flow.with_spacing(float(f->spacing));
|
||||||
|
|
||||||
ExtrusionMultiPath multi_path = PerimeterGenerator::thick_polyline_to_multi_path(thick_polyline, surface_fill.params.extrusion_role, new_flow, scaled<float>(0.05), float(SCALED_EPSILON));
|
ExtrusionMultiPath multi_path = PerimeterGenerator::thick_polyline_to_multi_path(thick_polyline,
|
||||||
|
surface_fill.params.extrusion_role,
|
||||||
|
new_flow, scaled<float>(0.05),
|
||||||
|
float(SCALED_EPSILON));
|
||||||
// Append paths to collection.
|
// Append paths to collection.
|
||||||
if (!multi_path.empty()) {
|
if (!multi_path.empty()) {
|
||||||
if (multi_path.paths.front().first_point() == multi_path.paths.back().last_point())
|
if (multi_path.paths.front().first_point() == multi_path.paths.back().last_point())
|
||||||
@@ -633,15 +646,15 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
|
|||||||
delete eec;
|
delete eec;
|
||||||
thick_polylines.clear();
|
thick_polylines.clear();
|
||||||
} else {
|
} else {
|
||||||
extrusion_entities_append_paths(
|
//w29
|
||||||
eec->entities, std::move(polylines),
|
extrusion_entities_append_paths(eec->entities, std::move(polylines),
|
||||||
ExtrusionAttributes{ surface_fill.params.extrusion_role,
|
ExtrusionAttributes{surface_fill.params.extrusion_role,
|
||||||
ExtrusionFlow{ flow_mm3_per_mm, float(flow_width), surface_fill.params.flow.height() }
|
ExtrusionFlow{flow_mm3_per_mm, float(flow_width),
|
||||||
});
|
surface_fill.params.flow.height()}});
|
||||||
//w21
|
// w21
|
||||||
if (surface_fill.params.pattern == ipMonotonicLines && surface_fill.surface.surface_type == stTop) {
|
if (surface_fill.params.pattern == ipMonotonicLines && surface_fill.surface.surface_type == stTop) {
|
||||||
ExPolygons unextruded_areas = diff_ex(f->no_overlap_expolygons, union_ex(eec->polygons_covered_by_spacing(10)));
|
ExPolygons unextruded_areas = diff_ex(f->no_overlap_expolygons, union_ex(eec->polygons_covered_by_spacing(10)));
|
||||||
ExPolygons gapfill_areas = union_ex(unextruded_areas);
|
ExPolygons gapfill_areas = union_ex(unextruded_areas);
|
||||||
if (!f->no_overlap_expolygons.empty())
|
if (!f->no_overlap_expolygons.empty())
|
||||||
gapfill_areas = intersection_ex(gapfill_areas, f->no_overlap_expolygons);
|
gapfill_areas = intersection_ex(gapfill_areas, f->no_overlap_expolygons);
|
||||||
if (gapfill_areas.size() > 0 && params.density >= 1) {
|
if (gapfill_areas.size() > 0 && params.density >= 1) {
|
||||||
@@ -650,7 +663,7 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
|
|||||||
double max = 2. * new_flow.scaled_spacing();
|
double max = 2. * new_flow.scaled_spacing();
|
||||||
ExPolygons gaps_ex = diff_ex(opening_ex(gapfill_areas, float(min / 2.)),
|
ExPolygons gaps_ex = diff_ex(opening_ex(gapfill_areas, float(min / 2.)),
|
||||||
offset2_ex(gapfill_areas, -float(max / 2.), float(max / 2. + ClipperSafetyOffset)));
|
offset2_ex(gapfill_areas, -float(max / 2.), float(max / 2. + ClipperSafetyOffset)));
|
||||||
Points ordering_points;
|
Points ordering_points;
|
||||||
ordering_points.reserve(gaps_ex.size());
|
ordering_points.reserve(gaps_ex.size());
|
||||||
ExPolygons gaps_ex_sorted;
|
ExPolygons gaps_ex_sorted;
|
||||||
gaps_ex_sorted.reserve(gaps_ex.size());
|
gaps_ex_sorted.reserve(gaps_ex.size());
|
||||||
@@ -674,7 +687,8 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
|
|||||||
}),
|
}),
|
||||||
polylines.end());
|
polylines.end());
|
||||||
|
|
||||||
variable_width_gap(polylines, ExtrusionRole::GapFill, surface_fill.params.flow, gap_fill.entities,filter_gap_infill_value);
|
variable_width_gap(polylines, ExtrusionRole::GapFill, surface_fill.params.flow, gap_fill.entities,
|
||||||
|
filter_gap_infill_value);
|
||||||
|
|
||||||
eec->append(std::move(gap_fill.entities));
|
eec->append(std::move(gap_fill.entities));
|
||||||
}
|
}
|
||||||
@@ -683,8 +697,9 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
|
|||||||
layerm.m_fills.entities.push_back(eec);
|
layerm.m_fills.entities.push_back(eec);
|
||||||
}
|
}
|
||||||
insert_fills_into_islands(*this, uint32_t(surface_fill.region_id), fill_begin, uint32_t(layerm.fills().size()));
|
insert_fills_into_islands(*this, uint32_t(surface_fill.region_id), fill_begin, uint32_t(layerm.fills().size()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (LayerSlice &lslice : this->lslices_ex)
|
for (LayerSlice &lslice : this->lslices_ex)
|
||||||
@@ -978,6 +993,8 @@ void Layer::make_ironing()
|
|||||||
|
|
||||||
// First classify regions based on the extruder used.
|
// First classify regions based on the extruder used.
|
||||||
struct IroningParams {
|
struct IroningParams {
|
||||||
|
//w33
|
||||||
|
InfillPattern pattern;
|
||||||
int extruder = -1;
|
int extruder = -1;
|
||||||
bool just_infill = false;
|
bool just_infill = false;
|
||||||
// Spacing of the ironing lines, also to calculate the extrusion flow from.
|
// Spacing of the ironing lines, also to calculate the extrusion flow from.
|
||||||
@@ -1018,7 +1035,9 @@ void Layer::make_ironing()
|
|||||||
bool operator==(const IroningParams &rhs) const {
|
bool operator==(const IroningParams &rhs) const {
|
||||||
return this->extruder == rhs.extruder && this->just_infill == rhs.just_infill &&
|
return this->extruder == rhs.extruder && this->just_infill == rhs.just_infill &&
|
||||||
this->line_spacing == rhs.line_spacing && this->height == rhs.height && this->speed == rhs.speed &&
|
this->line_spacing == rhs.line_spacing && this->height == rhs.height && this->speed == rhs.speed &&
|
||||||
this->angle == rhs.angle;
|
this->angle == rhs.angle
|
||||||
|
//w33
|
||||||
|
&& this->pattern == rhs.pattern;
|
||||||
}
|
}
|
||||||
|
|
||||||
LayerRegion *layerm;
|
LayerRegion *layerm;
|
||||||
@@ -1068,27 +1087,48 @@ void Layer::make_ironing()
|
|||||||
ironing_params.angle = config.fill_angle * M_PI / 180.;
|
ironing_params.angle = config.fill_angle * M_PI / 180.;
|
||||||
ironing_params.layerm = layerm;
|
ironing_params.layerm = layerm;
|
||||||
ironing_params.region_id = region_id;
|
ironing_params.region_id = region_id;
|
||||||
|
//w33
|
||||||
|
ironing_params.pattern = config.ironing_pattern;
|
||||||
by_extruder.emplace_back(ironing_params);
|
by_extruder.emplace_back(ironing_params);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::sort(by_extruder.begin(), by_extruder.end());
|
std::sort(by_extruder.begin(), by_extruder.end());
|
||||||
|
|
||||||
FillRectilinear fill;
|
//w33
|
||||||
|
//FillRectilinear fill;
|
||||||
FillParams fill_params;
|
FillParams fill_params;
|
||||||
fill.set_bounding_box(this->object()->bounding_box());
|
//fill.set_bounding_box(this->object()->bounding_box());
|
||||||
// Layer ID is used for orienting the infill in alternating directions.
|
// Layer ID is used for orienting the infill in alternating directions.
|
||||||
// Layer::id() returns layer ID including raft layers, subtract them to make the infill direction independent
|
// Layer::id() returns layer ID including raft layers, subtract them to make the infill direction independent
|
||||||
// from raft.
|
// from raft.
|
||||||
//FIXME ironing does not take fill angle into account. Shall it? Does it matter?
|
//FIXME ironing does not take fill angle into account. Shall it? Does it matter?
|
||||||
fill.layer_id = this->id() - this->object()->get_layer(0)->id();
|
//w33
|
||||||
fill.z = this->print_z;
|
//fill.layer_id = this->id() - this->object()->get_layer(0)->id();
|
||||||
fill.overlap = 0;
|
//fill.z = this->print_z;
|
||||||
|
//fill.overlap = 0;
|
||||||
fill_params.density = 1.;
|
fill_params.density = 1.;
|
||||||
fill_params.monotonic = true;
|
fill_params.monotonic = true;
|
||||||
|
//w33
|
||||||
|
InfillPattern f_pattern = ipRectilinear;
|
||||||
|
std::unique_ptr<Fill> f = std::unique_ptr<Fill>(Fill::new_from_type(f_pattern));
|
||||||
|
f->set_bounding_box(this->object()->bounding_box());
|
||||||
|
f->layer_id = this->id();
|
||||||
|
f->z = this->print_z;
|
||||||
|
f->overlap = 0;
|
||||||
|
|
||||||
for (size_t i = 0; i < by_extruder.size();) {
|
for (size_t i = 0; i < by_extruder.size();) {
|
||||||
// Find span of regions equivalent to the ironing operation.
|
// Find span of regions equivalent to the ironing operation.
|
||||||
IroningParams &ironing_params = by_extruder[i];
|
IroningParams &ironing_params = by_extruder[i];
|
||||||
|
//w33
|
||||||
|
if (f_pattern != ironing_params.pattern) {
|
||||||
|
f_pattern = ironing_params.pattern;
|
||||||
|
f = std::unique_ptr<Fill>(Fill::new_from_type(f_pattern));
|
||||||
|
f->set_bounding_box(this->object()->bounding_box());
|
||||||
|
f->layer_id = this->id();
|
||||||
|
f->z = this->print_z;
|
||||||
|
f->overlap = 0;
|
||||||
|
}
|
||||||
|
|
||||||
size_t j = i;
|
size_t j = i;
|
||||||
for (++ j; j < by_extruder.size() && ironing_params == by_extruder[j]; ++ j) ;
|
for (++ j; j < by_extruder.size() && ironing_params == by_extruder[j]; ++ j) ;
|
||||||
|
|
||||||
@@ -1150,10 +1190,15 @@ void Layer::make_ironing()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create the filler object.
|
// Create the filler object.
|
||||||
fill.spacing = ironing_params.line_spacing;
|
//w33
|
||||||
fill.angle = float(ironing_params.angle + 0.25 * M_PI);
|
//fill.spacing = ironing_params.line_spacing;
|
||||||
fill.link_max_length = (coord_t)scale_(3. * fill.spacing);
|
//fill.angle = float(ironing_params.angle + 0.25 * M_PI);
|
||||||
double extrusion_height = ironing_params.height * fill.spacing / nozzle_dmr;
|
//fill.link_max_length = (coord_t)scale_(3. * fill.spacing);
|
||||||
|
//double extrusion_height = ironing_params.height * fill.spacing / nozzle_dmr;
|
||||||
|
f->spacing = ironing_params.line_spacing;
|
||||||
|
f->angle = float(ironing_params.angle + 0.25 * M_PI);
|
||||||
|
f->link_max_length = (coord_t) scale_(3. * f->spacing);
|
||||||
|
double extrusion_height = ironing_params.height * f->spacing / nozzle_dmr;
|
||||||
float extrusion_width = Flow::rounded_rectangle_extrusion_width_from_spacing(float(nozzle_dmr), float(extrusion_height));
|
float extrusion_width = Flow::rounded_rectangle_extrusion_width_from_spacing(float(nozzle_dmr), float(extrusion_height));
|
||||||
double flow_mm3_per_mm = nozzle_dmr * extrusion_height;
|
double flow_mm3_per_mm = nozzle_dmr * extrusion_height;
|
||||||
Surface surface_fill(stTop, ExPolygon());
|
Surface surface_fill(stTop, ExPolygon());
|
||||||
@@ -1162,7 +1207,9 @@ void Layer::make_ironing()
|
|||||||
Polylines polylines;
|
Polylines polylines;
|
||||||
try {
|
try {
|
||||||
assert(!fill_params.use_arachne);
|
assert(!fill_params.use_arachne);
|
||||||
polylines = fill.fill_surface(&surface_fill, fill_params);
|
//w33
|
||||||
|
//polylines = fill.fill_surface(&surface_fill, fill_params);
|
||||||
|
polylines = f->fill_surface(&surface_fill, fill_params);
|
||||||
} catch (InfillFailedException &) {
|
} catch (InfillFailedException &) {
|
||||||
}
|
}
|
||||||
if (! polylines.empty()) {
|
if (! polylines.empty()) {
|
||||||
|
|||||||
@@ -6,6 +6,40 @@
|
|||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
|
//w36
|
||||||
|
template <typename T> int sgn(T val) {
|
||||||
|
return (T(0) < val) - (val < T(0));
|
||||||
|
}
|
||||||
|
//w36
|
||||||
|
static coordf_t triWave(coordf_t pos, coordf_t gridSize)
|
||||||
|
{
|
||||||
|
float t = (pos / (gridSize * 2.)) + 0.25;
|
||||||
|
t = t - (int)t;
|
||||||
|
return((1. - abs(t * 8. - 4.)) * (gridSize / 4.) + (gridSize / 4.));
|
||||||
|
}
|
||||||
|
//w36
|
||||||
|
static coordf_t troctWave(coordf_t pos, coordf_t gridSize, coordf_t Zpos)
|
||||||
|
{
|
||||||
|
coordf_t Zcycle = triWave(Zpos, gridSize);
|
||||||
|
coordf_t perpOffset = Zcycle / 2;
|
||||||
|
coordf_t y = triWave(pos, gridSize);
|
||||||
|
return ((abs(y) > abs(perpOffset)) ? (sgn(y) * perpOffset) : (y * sgn(perpOffset)));
|
||||||
|
}
|
||||||
|
//w36
|
||||||
|
static std::vector<coordf_t> getCriticalPoints(coordf_t Zpos, coordf_t gridSize)
|
||||||
|
{
|
||||||
|
std::vector<coordf_t> res = {0.};
|
||||||
|
coordf_t perpOffset = abs(triWave(Zpos, gridSize) / 2.);
|
||||||
|
|
||||||
|
coordf_t normalisedOffset = perpOffset / gridSize;
|
||||||
|
if (normalisedOffset > 0) {
|
||||||
|
res.push_back(gridSize * (0. + normalisedOffset));
|
||||||
|
res.push_back(gridSize * (1. - normalisedOffset));
|
||||||
|
res.push_back(gridSize * (1. + normalisedOffset));
|
||||||
|
res.push_back(gridSize * (2. - normalisedOffset));
|
||||||
|
}
|
||||||
|
return (res);
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
Creates a contiguous sequence of points at a specified height that make
|
Creates a contiguous sequence of points at a specified height that make
|
||||||
up a horizontal slice of the edges of a space filling truncated
|
up a horizontal slice of the edges of a space filling truncated
|
||||||
@@ -20,33 +54,47 @@ Credits: David Eccles (gringer).
|
|||||||
// basic printing line (i.e. Y points for columns, X points for rows)
|
// basic printing line (i.e. Y points for columns, X points for rows)
|
||||||
// Note: a negative offset only causes a change in the perpendicular
|
// Note: a negative offset only causes a change in the perpendicular
|
||||||
// direction
|
// direction
|
||||||
static std::vector<coordf_t> colinearPoints(const coordf_t offset, const size_t baseLocation, size_t gridLength)
|
//w36
|
||||||
|
static std::vector<coordf_t> colinearPoints(const coordf_t Zpos, coordf_t gridSize, std::vector<coordf_t> critPoints,
|
||||||
|
const size_t baseLocation, size_t gridLength)
|
||||||
{
|
{
|
||||||
const coordf_t offset2 = std::abs(offset / coordf_t(2.));
|
//w36
|
||||||
std::vector<coordf_t> points;
|
std::vector<coordf_t> points;
|
||||||
points.push_back(baseLocation - offset2);
|
//w36
|
||||||
for (size_t i = 0; i < gridLength; ++i) {
|
points.push_back(baseLocation);
|
||||||
points.push_back(baseLocation + i + offset2);
|
for (coordf_t cLoc = baseLocation; cLoc < gridLength; cLoc += (gridSize * 2)) {
|
||||||
points.push_back(baseLocation + i + 1 - offset2);
|
for (size_t pi = 0; pi < critPoints.size(); pi++) {
|
||||||
|
points.push_back(baseLocation + cLoc + critPoints[pi]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
points.push_back(baseLocation + gridLength + offset2);
|
//w36
|
||||||
|
points.push_back(gridLength);
|
||||||
return points;
|
return points;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate an array of points for the dimension that is perpendicular to
|
// Generate an array of points for the dimension that is perpendicular to
|
||||||
// the basic printing line (i.e. X points for columns, Y points for rows)
|
// the basic printing line (i.e. X points for columns, Y points for rows)
|
||||||
static std::vector<coordf_t> perpendPoints(const coordf_t offset, const size_t baseLocation, size_t gridLength)
|
//w36
|
||||||
|
static std::vector<coordf_t> perpendPoints(const coordf_t Zpos,
|
||||||
|
coordf_t gridSize,
|
||||||
|
std::vector<coordf_t> critPoints,
|
||||||
|
size_t baseLocation,
|
||||||
|
size_t gridLength,
|
||||||
|
size_t offsetBase,
|
||||||
|
coordf_t perpDir)
|
||||||
{
|
{
|
||||||
coordf_t offset2 = offset / coordf_t(2.);
|
//w36
|
||||||
coord_t side = 2 * (baseLocation & 1) - 1;
|
|
||||||
std::vector<coordf_t> points;
|
std::vector<coordf_t> points;
|
||||||
points.push_back(baseLocation - offset2 * side);
|
//w36
|
||||||
for (size_t i = 0; i < gridLength; ++i) {
|
points.push_back(offsetBase);
|
||||||
side = 2*((i+baseLocation) & 1) - 1;
|
for (coordf_t cLoc = baseLocation; cLoc < gridLength; cLoc += gridSize * 2) {
|
||||||
points.push_back(baseLocation + offset2 * side);
|
for (size_t pi = 0; pi < critPoints.size(); pi++) {
|
||||||
points.push_back(baseLocation + offset2 * side);
|
coordf_t offset = troctWave(critPoints[pi], gridSize, Zpos);
|
||||||
|
points.push_back(offsetBase + (offset * perpDir));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
points.push_back(baseLocation - offset2 * side);
|
//w36
|
||||||
|
points.push_back(offsetBase);
|
||||||
return points;
|
return points;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,40 +122,32 @@ static inline Pointfs zip(const std::vector<coordf_t> &x, const std::vector<coor
|
|||||||
// horizontal slice of a truncated regular octahedron with edge length 1.
|
// horizontal slice of a truncated regular octahedron with edge length 1.
|
||||||
// curveType specifies which lines to print, 1 for vertical lines
|
// curveType specifies which lines to print, 1 for vertical lines
|
||||||
// (columns), 2 for horizontal lines (rows), and 3 for both.
|
// (columns), 2 for horizontal lines (rows), and 3 for both.
|
||||||
static std::vector<Pointfs> makeNormalisedGrid(coordf_t z, size_t gridWidth, size_t gridHeight, size_t curveType)
|
//w36
|
||||||
|
static std::vector<Pointfs> makeActualGrid(coordf_t Zpos, coordf_t gridSize, size_t boundsX, size_t boundsY)
|
||||||
{
|
{
|
||||||
// offset required to create a regular octagram
|
//w36
|
||||||
coordf_t octagramGap = coordf_t(0.5);
|
std::vector<Pointfs> points;
|
||||||
|
std::vector<coordf_t> critPoints = getCriticalPoints(Zpos, gridSize);
|
||||||
// sawtooth wave function for range f($z) = [-$octagramGap .. $octagramGap]
|
coordf_t zCycle = fmod(Zpos + gridSize / 2, gridSize * 2.) / (gridSize * 2.);
|
||||||
coordf_t a = std::sqrt(coordf_t(2.)); // period
|
bool printVert = zCycle < 0.5;
|
||||||
coordf_t wave = fabs(fmod(z, a) - a/2.)/a*4. - 1.;
|
if (printVert) {
|
||||||
coordf_t offset = wave * octagramGap;
|
int perpDir = -1;
|
||||||
|
for (coordf_t x = 0; x <= (boundsX); x += gridSize, perpDir *= -1) {
|
||||||
std::vector<Pointfs> points;
|
|
||||||
if ((curveType & 1) != 0) {
|
|
||||||
for (size_t x = 0; x <= gridWidth; ++x) {
|
|
||||||
points.push_back(Pointfs());
|
points.push_back(Pointfs());
|
||||||
Pointfs &newPoints = points.back();
|
Pointfs &newPoints = points.back();
|
||||||
newPoints = zip(
|
newPoints = zip(perpendPoints(Zpos, gridSize, critPoints, 0, boundsY, x, perpDir),
|
||||||
perpendPoints(offset, x, gridHeight),
|
colinearPoints(Zpos, gridSize, critPoints, 0, boundsY));
|
||||||
colinearPoints(offset, 0, gridHeight));
|
if (perpDir == 1)
|
||||||
// trim points to grid edges
|
|
||||||
trim(newPoints, coordf_t(0.), coordf_t(0.), coordf_t(gridWidth), coordf_t(gridHeight));
|
|
||||||
if (x & 1)
|
|
||||||
std::reverse(newPoints.begin(), newPoints.end());
|
std::reverse(newPoints.begin(), newPoints.end());
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
if ((curveType & 2) != 0) {
|
int perpDir = 1;
|
||||||
for (size_t y = 0; y <= gridHeight; ++y) {
|
for (coordf_t y = gridSize; y <= (boundsY); y += gridSize, perpDir *= -1) {
|
||||||
points.push_back(Pointfs());
|
points.push_back(Pointfs());
|
||||||
Pointfs &newPoints = points.back();
|
Pointfs &newPoints = points.back();
|
||||||
newPoints = zip(
|
newPoints = zip(colinearPoints(Zpos, gridSize, critPoints, 0, boundsX),
|
||||||
colinearPoints(offset, 0, gridWidth),
|
perpendPoints(Zpos, gridSize, critPoints, 0, boundsX, y, perpDir));
|
||||||
perpendPoints(offset, y, gridWidth));
|
if (perpDir == -1)
|
||||||
// trim points to grid edges
|
|
||||||
trim(newPoints, coordf_t(0.), coordf_t(0.), coordf_t(gridWidth), coordf_t(gridHeight));
|
|
||||||
if (y & 1)
|
|
||||||
std::reverse(newPoints.begin(), newPoints.end());
|
std::reverse(newPoints.begin(), newPoints.end());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -117,18 +157,19 @@ static std::vector<Pointfs> makeNormalisedGrid(coordf_t z, size_t gridWidth, siz
|
|||||||
// Generate a set of curves (array of array of 2d points) that describe a
|
// Generate a set of curves (array of array of 2d points) that describe a
|
||||||
// horizontal slice of a truncated regular octahedron with a specified
|
// horizontal slice of a truncated regular octahedron with a specified
|
||||||
// grid square size.
|
// grid square size.
|
||||||
static Polylines makeGrid(coord_t z, coord_t gridSize, size_t gridWidth, size_t gridHeight, size_t curveType)
|
//w36
|
||||||
|
static Polylines makeGrid(coordf_t z, coordf_t gridSize, coordf_t boundWidth, coordf_t boundHeight, bool fillEvenly)
|
||||||
{
|
{
|
||||||
coord_t scaleFactor = gridSize;
|
//w36
|
||||||
coordf_t normalisedZ = coordf_t(z) / coordf_t(scaleFactor);
|
std::vector<Pointfs> polylines = makeActualGrid(z, gridSize, boundWidth, boundHeight);
|
||||||
std::vector<Pointfs> polylines = makeNormalisedGrid(normalisedZ, gridWidth, gridHeight, curveType);
|
Polylines result;
|
||||||
Polylines result;
|
|
||||||
result.reserve(polylines.size());
|
result.reserve(polylines.size());
|
||||||
for (std::vector<Pointfs>::const_iterator it_polylines = polylines.begin(); it_polylines != polylines.end(); ++ it_polylines) {
|
for (std::vector<Pointfs>::const_iterator it_polylines = polylines.begin(); it_polylines != polylines.end(); ++it_polylines) {
|
||||||
result.push_back(Polyline());
|
result.push_back(Polyline());
|
||||||
Polyline &polyline = result.back();
|
Polyline &polyline = result.back();
|
||||||
for (Pointfs::const_iterator it = it_polylines->begin(); it != it_polylines->end(); ++ it)
|
//w36
|
||||||
polyline.points.push_back(Point(coord_t((*it)(0) * scaleFactor), coord_t((*it)(1) * scaleFactor)));
|
for (Pointfs::const_iterator it = it_polylines->begin(); it != it_polylines->end(); ++it)
|
||||||
|
polyline.points.push_back(Point(coord_t((*it)(0)), coord_t((*it)(1))));
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -141,34 +182,67 @@ void Fill3DHoneycomb::_fill_surface_single(
|
|||||||
Polylines &polylines_out)
|
Polylines &polylines_out)
|
||||||
{
|
{
|
||||||
// no rotation is supported for this infill pattern
|
// no rotation is supported for this infill pattern
|
||||||
|
//w36
|
||||||
|
auto infill_angle = float(this->angle);
|
||||||
|
if (std::abs(infill_angle) >= EPSILON)
|
||||||
|
expolygon.rotate(-infill_angle);
|
||||||
BoundingBox bb = expolygon.contour.bounding_box();
|
BoundingBox bb = expolygon.contour.bounding_box();
|
||||||
coord_t distance = coord_t(scale_(this->spacing) / params.density);
|
//w36
|
||||||
|
|
||||||
// align bounding box to a multiple of our honeycomb grid module
|
// align bounding box to a multiple of our honeycomb grid module
|
||||||
// (a module is 2*$distance since one $distance half-module is
|
// (a module is 2*$distance since one $distance half-module is
|
||||||
// growing while the other $distance half-module is shrinking)
|
// growing while the other $distance half-module is shrinking)
|
||||||
bb.merge(align_to_grid(bb.min, Point(2*distance, 2*distance)));
|
//w36
|
||||||
|
coordf_t zScale = sqrt(2);
|
||||||
|
coordf_t gridSize = (scale_(this->spacing) * ((zScale + 1.) / 2.) / params.density);
|
||||||
|
|
||||||
// generate pattern
|
|
||||||
Polylines polylines = makeGrid(
|
|
||||||
scale_(this->z),
|
|
||||||
distance,
|
|
||||||
ceil(bb.size()(0) / distance) + 1,
|
|
||||||
ceil(bb.size()(1) / distance) + 1,
|
|
||||||
((this->layer_id/thickness_layers) % 2) + 1);
|
|
||||||
|
|
||||||
|
coordf_t layerHeight = scale_(thickness_layers);
|
||||||
|
|
||||||
|
coordf_t layersPerModule = floor((gridSize * 2) / (zScale * layerHeight) + 0.05);
|
||||||
|
if (params.density > 0.42) {
|
||||||
|
layersPerModule = 2;
|
||||||
|
gridSize = (scale_(this->spacing) * 1.1 / params.density);
|
||||||
|
zScale = (gridSize * 2) / (layersPerModule * layerHeight);
|
||||||
|
} else {
|
||||||
|
if (layersPerModule < 2) {
|
||||||
|
layersPerModule = 2;
|
||||||
|
}
|
||||||
|
zScale = (gridSize * 2) / (layersPerModule * layerHeight);
|
||||||
|
gridSize = (scale_(this->spacing) * ((zScale + 1.) / 2.) / params.density);
|
||||||
|
layersPerModule = floor((gridSize * 2) / (zScale * layerHeight) + 0.05);
|
||||||
|
if (layersPerModule < 2) {
|
||||||
|
layersPerModule = 2;
|
||||||
|
}
|
||||||
|
zScale = (gridSize * 2) / (layersPerModule * layerHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
bb.merge(align_to_grid(bb.min, Point(gridSize * 4, gridSize * 4)));
|
||||||
|
|
||||||
|
Polylines polylines =
|
||||||
|
makeGrid(
|
||||||
|
scale_(this->z) * zScale,
|
||||||
|
gridSize,
|
||||||
|
bb.size()(0),
|
||||||
|
bb.size()(1),
|
||||||
|
!params.dont_adjust);
|
||||||
// move pattern in place
|
// move pattern in place
|
||||||
for (Polyline &pl : polylines)
|
for (Polyline &pl : polylines) {
|
||||||
pl.translate(bb.min);
|
pl.translate(bb.min);
|
||||||
|
}
|
||||||
// clip pattern to boundaries, chain the clipped polylines
|
// clip pattern to boundaries, chain the clipped polylines
|
||||||
polylines = intersection_pl(polylines, expolygon);
|
polylines = intersection_pl(polylines, to_polygons(expolygon));
|
||||||
|
if (!polylines.empty()) {
|
||||||
|
int infill_start_idx = polylines_out.size();
|
||||||
|
if (params.dont_connect() || polylines.size() <= 1)
|
||||||
|
append(polylines_out, chain_polylines(std::move(polylines)));
|
||||||
|
else
|
||||||
|
this->connect_infill(std::move(polylines), expolygon, polylines_out, this->spacing, params);
|
||||||
|
|
||||||
// connect lines if needed
|
if (std::abs(infill_angle) >= EPSILON) {
|
||||||
if (params.dont_connect() || polylines.size() <= 1)
|
for (auto it = polylines_out.begin() + infill_start_idx; it != polylines_out.end(); ++it)
|
||||||
append(polylines_out, chain_polylines(std::move(polylines)));
|
it->rotate(infill_angle);
|
||||||
else
|
}
|
||||||
this->connect_infill(std::move(polylines), expolygon, polylines_out, this->spacing, params);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Slic3r
|
} // namespace Slic3r
|
||||||
|
|||||||
@@ -16,7 +16,8 @@ public:
|
|||||||
~Fill3DHoneycomb() override {}
|
~Fill3DHoneycomb() override {}
|
||||||
|
|
||||||
// require bridge flow since most of this pattern hangs in air
|
// require bridge flow since most of this pattern hangs in air
|
||||||
bool use_bridge_flow() const override { return true; }
|
//w36
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void _fill_surface_single(
|
void _fill_surface_single(
|
||||||
|
|||||||
@@ -21,6 +21,10 @@
|
|||||||
#include "FillAdaptive.hpp"
|
#include "FillAdaptive.hpp"
|
||||||
#include "FillLightning.hpp"
|
#include "FillLightning.hpp"
|
||||||
#include "FillEnsuring.hpp"
|
#include "FillEnsuring.hpp"
|
||||||
|
//w29
|
||||||
|
#include "FillConcentricInternal.hpp"
|
||||||
|
//w32
|
||||||
|
#include "FillCrossHatch.hpp"
|
||||||
|
|
||||||
#include <boost/log/trivial.hpp>
|
#include <boost/log/trivial.hpp>
|
||||||
|
|
||||||
@@ -53,7 +57,10 @@ Fill* Fill::new_from_type(const InfillPattern type)
|
|||||||
case ipLightning: return new FillLightning::Filler();
|
case ipLightning: return new FillLightning::Filler();
|
||||||
case ipEnsuring: return new FillEnsuring();
|
case ipEnsuring: return new FillEnsuring();
|
||||||
//w14
|
//w14
|
||||||
case ipConcentricInternal: return new FillConcentric();
|
//w29
|
||||||
|
case ipConcentricInternal: return new FillConcentricInternal();
|
||||||
|
//w32
|
||||||
|
case ipCrossHatch: return new FillCrossHatch();
|
||||||
default: throw Slic3r::InvalidArgument("unknown type");
|
default: throw Slic3r::InvalidArgument("unknown type");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -105,6 +112,157 @@ ThickPolylines Fill::fill_surface_arachne(const Surface *surface, const FillPara
|
|||||||
return thick_polylines_out;
|
return thick_polylines_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//w29
|
||||||
|
void Fill::fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, Polylines &polylines, ThickPolylines &thick_polylines)
|
||||||
|
{
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (params.use_arachne)
|
||||||
|
thick_polylines = this->fill_surface_arachne(surface, params);
|
||||||
|
else
|
||||||
|
polylines = this->fill_surface(surface, params);
|
||||||
|
} catch (InfillFailedException &) {}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
//w29
|
||||||
|
void Fill::variable_width(const ThickPolylines &polylines, ExtrusionRole role, const Flow &flow, std::vector<ExtrusionEntity *> &out)
|
||||||
|
{
|
||||||
|
const float tolerance = float(scale_(0.05));
|
||||||
|
for (const ThickPolyline &p : polylines) {
|
||||||
|
ExtrusionPaths paths = thick_polyline_to_extrusion_paths_2(p, role, flow, tolerance);
|
||||||
|
if (!paths.empty()) {
|
||||||
|
if (paths.front().first_point() == paths.back().last_point())
|
||||||
|
out.emplace_back(new ExtrusionLoop(std::move(paths)));
|
||||||
|
else {
|
||||||
|
for (ExtrusionPath &path : paths)
|
||||||
|
out.emplace_back(new ExtrusionPath(std::move(path)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//w29
|
||||||
|
ExtrusionPaths Fill::thick_polyline_to_extrusion_paths_2(const ThickPolyline &thick_polyline,
|
||||||
|
ExtrusionRole role,
|
||||||
|
const Flow & flow,
|
||||||
|
const float tolerance)
|
||||||
|
{
|
||||||
|
ExtrusionPaths paths;
|
||||||
|
ExtrusionPath path(role);
|
||||||
|
ThickLines lines = thick_polyline.thicklines();
|
||||||
|
|
||||||
|
size_t start_index = 0;
|
||||||
|
double max_width, min_width;
|
||||||
|
|
||||||
|
for (int i = 0; i < (int) lines.size(); ++i) {
|
||||||
|
const ThickLine &line = lines[i];
|
||||||
|
|
||||||
|
if (i == 0) {
|
||||||
|
max_width = line.a_width;
|
||||||
|
min_width = line.a_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
const coordf_t line_len = line.length();
|
||||||
|
if (line_len < SCALED_EPSILON)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
double thickness_delta = std::max(fabs(max_width - line.b_width), fabs(min_width - line.b_width));
|
||||||
|
if (thickness_delta > tolerance) {
|
||||||
|
if (start_index != i) {
|
||||||
|
path = ExtrusionPath(role);
|
||||||
|
double length = lines[start_index].length();
|
||||||
|
double sum = lines[start_index].length() * 0.5 * (lines[start_index].a_width + lines[start_index].b_width);
|
||||||
|
path.polyline.append(lines[start_index].a);
|
||||||
|
for (int idx = start_index + 1; idx < i; idx++) {
|
||||||
|
length += lines[idx].length();
|
||||||
|
sum += lines[idx].length() * 0.5 * (lines[idx].a_width + lines[idx].b_width);
|
||||||
|
path.polyline.append(lines[idx].a);
|
||||||
|
}
|
||||||
|
path.polyline.append(lines[i].a);
|
||||||
|
if (length > SCALED_EPSILON) {
|
||||||
|
double w = sum / length;
|
||||||
|
Flow new_flow = flow.with_width(unscale<float>(w) + flow.height() * float(1. - 0.25 * PI));
|
||||||
|
|
||||||
|
// path.mm3_per_mm = new_flow.mm3_per_mm();
|
||||||
|
path.set_mm3_per_mm(new_flow.mm3_per_mm());
|
||||||
|
// path.width = new_flow.width();
|
||||||
|
path.set_width(new_flow.width());
|
||||||
|
// path.height = new_flow.height();
|
||||||
|
path.set_height(new_flow.height());
|
||||||
|
paths.emplace_back(std::move(path));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
start_index = i;
|
||||||
|
max_width = line.a_width;
|
||||||
|
min_width = line.a_width;
|
||||||
|
thickness_delta = fabs(line.a_width - line.b_width);
|
||||||
|
if (thickness_delta > tolerance) {
|
||||||
|
const unsigned int segments = (unsigned int) ceil(thickness_delta / tolerance);
|
||||||
|
const coordf_t seg_len = line_len / segments;
|
||||||
|
Points pp;
|
||||||
|
std::vector<coordf_t> width;
|
||||||
|
{
|
||||||
|
pp.push_back(line.a);
|
||||||
|
width.push_back(line.a_width);
|
||||||
|
for (size_t j = 1; j < segments; ++j) {
|
||||||
|
pp.push_back(
|
||||||
|
(line.a.cast<double>() + (line.b - line.a).cast<double>().normalized() * (j * seg_len)).cast<coord_t>());
|
||||||
|
|
||||||
|
coordf_t w = line.a_width + (j * seg_len) * (line.b_width - line.a_width) / line_len;
|
||||||
|
width.push_back(w);
|
||||||
|
width.push_back(w);
|
||||||
|
}
|
||||||
|
pp.push_back(line.b);
|
||||||
|
width.push_back(line.b_width);
|
||||||
|
|
||||||
|
assert(pp.size() == segments + 1u);
|
||||||
|
assert(width.size() == segments * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
lines.erase(lines.begin() + i);
|
||||||
|
for (size_t j = 0; j < segments; ++j) {
|
||||||
|
ThickLine new_line(pp[j], pp[j + 1]);
|
||||||
|
new_line.a_width = width[2 * j];
|
||||||
|
new_line.b_width = width[2 * j + 1];
|
||||||
|
lines.insert(lines.begin() + i + j, new_line);
|
||||||
|
}
|
||||||
|
--i;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
max_width = std::max(max_width, std::max(line.a_width, line.b_width));
|
||||||
|
min_width = std::min(min_width, std::min(line.a_width, line.b_width));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
size_t final_size = lines.size();
|
||||||
|
if (start_index < final_size) {
|
||||||
|
path = ExtrusionPath(role);
|
||||||
|
double length = lines[start_index].length();
|
||||||
|
double sum = lines[start_index].length() * lines[start_index].a_width;
|
||||||
|
path.polyline.append(lines[start_index].a);
|
||||||
|
for (int idx = start_index + 1; idx < final_size; idx++) {
|
||||||
|
length += lines[idx].length();
|
||||||
|
sum += lines[idx].length() * lines[idx].a_width;
|
||||||
|
path.polyline.append(lines[idx].a);
|
||||||
|
}
|
||||||
|
path.polyline.append(lines[final_size - 1].b);
|
||||||
|
if (length > SCALED_EPSILON) {
|
||||||
|
double w = sum / length;
|
||||||
|
Flow new_flow = flow.with_width(unscale<float>(w) + flow.height() * float(1. - 0.25 * PI));
|
||||||
|
// path.mm3_per_mm = new_flow.mm3_per_mm();
|
||||||
|
path.set_mm3_per_mm(new_flow.mm3_per_mm());
|
||||||
|
// path.width = new_flow.width();
|
||||||
|
path.set_width(new_flow.width());
|
||||||
|
// path.height = new_flow.height();
|
||||||
|
path.set_height(new_flow.height());
|
||||||
|
paths.emplace_back(std::move(path));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return paths;
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate a new spacing to fill width with possibly integer number of lines,
|
// Calculate a new spacing to fill width with possibly integer number of lines,
|
||||||
// the first and last line being centered at the interval ends.
|
// the first and last line being centered at the interval ends.
|
||||||
// This function possibly increases the spacing, never decreases,
|
// This function possibly increases the spacing, never decreases,
|
||||||
|
|||||||
@@ -15,6 +15,9 @@
|
|||||||
#include "../Utils.hpp"
|
#include "../Utils.hpp"
|
||||||
#include "../ExPolygon.hpp"
|
#include "../ExPolygon.hpp"
|
||||||
#include "../PrintConfig.hpp"
|
#include "../PrintConfig.hpp"
|
||||||
|
//w29
|
||||||
|
#include "../ExtrusionEntity.hpp"
|
||||||
|
#include "../ExtrusionEntityCollection.hpp"
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
@@ -63,6 +66,11 @@ struct FillParams
|
|||||||
bool use_arachne { false };
|
bool use_arachne { false };
|
||||||
// Layer height for Concentric infill with Arachne.
|
// Layer height for Concentric infill with Arachne.
|
||||||
coordf_t layer_height { 0.f };
|
coordf_t layer_height { 0.f };
|
||||||
|
//w29
|
||||||
|
Flow flow;
|
||||||
|
ExtrusionRole extrusion_role{ExtrusionRole::None};
|
||||||
|
bool using_internal_flow{false};
|
||||||
|
//bool can_reverse{true};
|
||||||
};
|
};
|
||||||
static_assert(IsTriviallyCopyable<FillParams>::value, "FillParams class is not POD (and it should be - see constructor).");
|
static_assert(IsTriviallyCopyable<FillParams>::value, "FillParams class is not POD (and it should be - see constructor).");
|
||||||
|
|
||||||
@@ -116,6 +124,13 @@ public:
|
|||||||
// Perform the fill.
|
// Perform the fill.
|
||||||
virtual Polylines fill_surface(const Surface *surface, const FillParams ¶ms);
|
virtual Polylines fill_surface(const Surface *surface, const FillParams ¶ms);
|
||||||
virtual ThickPolylines fill_surface_arachne(const Surface *surface, const FillParams ¶ms);
|
virtual ThickPolylines fill_surface_arachne(const Surface *surface, const FillParams ¶ms);
|
||||||
|
//w29
|
||||||
|
virtual void fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, Polylines &polylines,ThickPolylines &thick_polylines);
|
||||||
|
void variable_width(const ThickPolylines &polylines, ExtrusionRole role, const Flow &flow, std::vector<ExtrusionEntity *> &out);
|
||||||
|
ExtrusionPaths thick_polyline_to_extrusion_paths_2(const ThickPolyline &thick_polyline,
|
||||||
|
ExtrusionRole role,
|
||||||
|
const Flow & flow,
|
||||||
|
const float tolerance);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Fill() :
|
Fill() :
|
||||||
|
|||||||
74
src/libslic3r/Fill/FillConcentricInternal.cpp
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
#include "../ClipperUtils.hpp"
|
||||||
|
#include "../ExPolygon.hpp"
|
||||||
|
#include "../Surface.hpp"
|
||||||
|
#include "Arachne/WallToolPaths.hpp"
|
||||||
|
|
||||||
|
#include "FillConcentricInternal.hpp"
|
||||||
|
|
||||||
|
#include <libslic3r/ShortestPath.hpp>
|
||||||
|
|
||||||
|
namespace Slic3r {
|
||||||
|
|
||||||
|
void FillConcentricInternal::fill_surface_extrusion(const Surface * surface,
|
||||||
|
const FillParams ¶ms,
|
||||||
|
Polylines & polylines,
|
||||||
|
ThickPolylines & thick_polylines_out)
|
||||||
|
{
|
||||||
|
assert(this->print_config != nullptr && this->print_object_config != nullptr);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < this->no_overlap_expolygons.size(); ++i) {
|
||||||
|
ExPolygon &expolygon = this->no_overlap_expolygons[i];
|
||||||
|
Point bbox_size = expolygon.contour.bounding_box().size();
|
||||||
|
coord_t min_spacing = params.flow.scaled_spacing();
|
||||||
|
|
||||||
|
coord_t loops_count = std::max(bbox_size.x(), bbox_size.y()) / min_spacing + 1;
|
||||||
|
Polygons polygons = to_polygons(expolygon);
|
||||||
|
|
||||||
|
Arachne::WallToolPaths wallToolPaths(polygons, min_spacing, min_spacing, loops_count, 0, params.layer_height,
|
||||||
|
*this->print_object_config, *this->print_config);
|
||||||
|
|
||||||
|
std::vector<Arachne::VariableWidthLines> loops = wallToolPaths.getToolPaths();
|
||||||
|
std::vector<const Arachne::ExtrusionLine *> all_extrusions;
|
||||||
|
for (Arachne::VariableWidthLines &loop : loops) {
|
||||||
|
if (loop.empty())
|
||||||
|
continue;
|
||||||
|
for (const Arachne::ExtrusionLine &wall : loop)
|
||||||
|
all_extrusions.emplace_back(&wall);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t firts_poly_idx = thick_polylines_out.size();
|
||||||
|
Point last_pos(0, 0);
|
||||||
|
for (const Arachne::ExtrusionLine *extrusion : all_extrusions) {
|
||||||
|
if (extrusion->empty())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ThickPolyline thick_polyline = Arachne::to_thick_polyline(*extrusion);
|
||||||
|
if (extrusion->is_closed && thick_polyline.points.front() == thick_polyline.points.back() &&
|
||||||
|
thick_polyline.width.front() == thick_polyline.width.back()) {
|
||||||
|
thick_polyline.points.pop_back();
|
||||||
|
assert(thick_polyline.points.size() * 2 == thick_polyline.width.size());
|
||||||
|
int nearest_idx = last_pos.nearest_point_index(thick_polyline.points);
|
||||||
|
std::rotate(thick_polyline.points.begin(), thick_polyline.points.begin() + nearest_idx, thick_polyline.points.end());
|
||||||
|
std::rotate(thick_polyline.width.begin(), thick_polyline.width.begin() + 2 * nearest_idx, thick_polyline.width.end());
|
||||||
|
thick_polyline.points.emplace_back(thick_polyline.points.front());
|
||||||
|
}
|
||||||
|
thick_polylines_out.emplace_back(std::move(thick_polyline));
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t j = firts_poly_idx;
|
||||||
|
for (size_t i = firts_poly_idx; i < thick_polylines_out.size(); ++i) {
|
||||||
|
thick_polylines_out[i].clip_end(this->loop_clipping);
|
||||||
|
if (thick_polylines_out[i].is_valid()) {
|
||||||
|
if (j < i)
|
||||||
|
thick_polylines_out[j] = std::move(thick_polylines_out[i]);
|
||||||
|
++j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (j < thick_polylines_out.size())
|
||||||
|
thick_polylines_out.erase(thick_polylines_out.begin() + int(j), thick_polylines_out.end());
|
||||||
|
|
||||||
|
reorder_by_shortest_traverse(thick_polylines_out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Slic3r
|
||||||
165
src/libslic3r/Fill/FillConcentricInternal.hpp
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
#ifndef slic3r_FillConcentricInternal_hpp_
|
||||||
|
#define slic3r_FillConcentricInternal_hpp_
|
||||||
|
|
||||||
|
#include "FillBase.hpp"
|
||||||
|
|
||||||
|
namespace Slic3r {
|
||||||
|
|
||||||
|
class FillConcentricInternal : public Fill
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
~FillConcentricInternal() override = default;
|
||||||
|
void fill_surface_extrusion(const Surface * surface,
|
||||||
|
const FillParams ¶ms,
|
||||||
|
Polylines & polylines,
|
||||||
|
ThickPolylines & thick_polylines) override;
|
||||||
|
void variable_width(const ThickPolylines &polylines, ExtrusionRole role, const Flow &flow, std::vector<ExtrusionEntity *> &out)
|
||||||
|
{
|
||||||
|
const float tolerance = float(scale_(0.05));
|
||||||
|
for (const ThickPolyline &p : polylines) {
|
||||||
|
ExtrusionPaths paths = thick_polyline_to_extrusion_paths_2(p, role, flow, tolerance);
|
||||||
|
// Append paths to collection.
|
||||||
|
if (!paths.empty()) {
|
||||||
|
if (paths.front().first_point() == paths.back().last_point())
|
||||||
|
out.emplace_back(new ExtrusionLoop(std::move(paths)));
|
||||||
|
else {
|
||||||
|
for (ExtrusionPath &path : paths)
|
||||||
|
out.emplace_back(new ExtrusionPath(std::move(path)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ExtrusionPaths thick_polyline_to_extrusion_paths_2(const ThickPolyline &thick_polyline,
|
||||||
|
ExtrusionRole role,
|
||||||
|
const Flow & flow,
|
||||||
|
const float tolerance)
|
||||||
|
{
|
||||||
|
ExtrusionPaths paths;
|
||||||
|
ExtrusionPath path(role);
|
||||||
|
ThickLines lines = thick_polyline.thicklines();
|
||||||
|
|
||||||
|
size_t start_index = 0;
|
||||||
|
double max_width, min_width;
|
||||||
|
|
||||||
|
for (int i = 0; i < (int) lines.size(); ++i) {
|
||||||
|
const ThickLine &line = lines[i];
|
||||||
|
|
||||||
|
if (i == 0) {
|
||||||
|
max_width = line.a_width;
|
||||||
|
min_width = line.a_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
const coordf_t line_len = line.length();
|
||||||
|
if (line_len < SCALED_EPSILON)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
double thickness_delta = std::max(fabs(max_width - line.b_width), fabs(min_width - line.b_width));
|
||||||
|
if (thickness_delta > tolerance) {
|
||||||
|
if (start_index != i) {
|
||||||
|
path = ExtrusionPath(role);
|
||||||
|
double length = lines[start_index].length();
|
||||||
|
double sum = lines[start_index].length() * 0.5 * (lines[start_index].a_width + lines[start_index].b_width);
|
||||||
|
path.polyline.append(lines[start_index].a);
|
||||||
|
for (int idx = start_index + 1; idx < i; idx++) {
|
||||||
|
length += lines[idx].length();
|
||||||
|
sum += lines[idx].length() * 0.5 * (lines[idx].a_width + lines[idx].b_width);
|
||||||
|
path.polyline.append(lines[idx].a);
|
||||||
|
}
|
||||||
|
path.polyline.append(lines[i].a);
|
||||||
|
if (length > SCALED_EPSILON) {
|
||||||
|
double w = sum / length;
|
||||||
|
Flow new_flow = flow.with_width(unscale<float>(w) + flow.height() * float(1. - 0.25 * PI));
|
||||||
|
|
||||||
|
// path.mm3_per_mm = new_flow.mm3_per_mm();
|
||||||
|
path.set_mm3_per_mm(new_flow.mm3_per_mm());
|
||||||
|
// path.width = new_flow.width();
|
||||||
|
path.set_width(new_flow.width());
|
||||||
|
// path.height = new_flow.height();
|
||||||
|
path.set_height(new_flow.height());
|
||||||
|
paths.emplace_back(std::move(path));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
start_index = i;
|
||||||
|
max_width = line.a_width;
|
||||||
|
min_width = line.a_width;
|
||||||
|
thickness_delta = fabs(line.a_width - line.b_width);
|
||||||
|
if (thickness_delta > tolerance) {
|
||||||
|
const unsigned int segments = (unsigned int) ceil(thickness_delta / tolerance);
|
||||||
|
const coordf_t seg_len = line_len / segments;
|
||||||
|
Points pp;
|
||||||
|
std::vector<coordf_t> width;
|
||||||
|
{
|
||||||
|
pp.push_back(line.a);
|
||||||
|
width.push_back(line.a_width);
|
||||||
|
for (size_t j = 1; j < segments; ++j) {
|
||||||
|
pp.push_back(
|
||||||
|
(line.a.cast<double>() + (line.b - line.a).cast<double>().normalized() * (j * seg_len)).cast<coord_t>());
|
||||||
|
|
||||||
|
coordf_t w = line.a_width + (j * seg_len) * (line.b_width - line.a_width) / line_len;
|
||||||
|
width.push_back(w);
|
||||||
|
width.push_back(w);
|
||||||
|
}
|
||||||
|
pp.push_back(line.b);
|
||||||
|
width.push_back(line.b_width);
|
||||||
|
|
||||||
|
assert(pp.size() == segments + 1u);
|
||||||
|
assert(width.size() == segments * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
lines.erase(lines.begin() + i);
|
||||||
|
for (size_t j = 0; j < segments; ++j) {
|
||||||
|
ThickLine new_line(pp[j], pp[j + 1]);
|
||||||
|
new_line.a_width = width[2 * j];
|
||||||
|
new_line.b_width = width[2 * j + 1];
|
||||||
|
lines.insert(lines.begin() + i + j, new_line);
|
||||||
|
}
|
||||||
|
--i;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
max_width = std::max(max_width, std::max(line.a_width, line.b_width));
|
||||||
|
min_width = std::min(min_width, std::min(line.a_width, line.b_width));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
size_t final_size = lines.size();
|
||||||
|
if (start_index < final_size) {
|
||||||
|
path = ExtrusionPath(role);
|
||||||
|
double length = lines[start_index].length();
|
||||||
|
double sum = lines[start_index].length() * lines[start_index].a_width;
|
||||||
|
path.polyline.append(lines[start_index].a);
|
||||||
|
for (int idx = start_index + 1; idx < final_size; idx++) {
|
||||||
|
length += lines[idx].length();
|
||||||
|
sum += lines[idx].length() * lines[idx].a_width;
|
||||||
|
path.polyline.append(lines[idx].a);
|
||||||
|
}
|
||||||
|
path.polyline.append(lines[final_size - 1].b);
|
||||||
|
if (length > SCALED_EPSILON) {
|
||||||
|
double w = sum / length;
|
||||||
|
Flow new_flow = flow.with_width(unscale<float>(w) + flow.height() * float(1. - 0.25 * PI));
|
||||||
|
// path.mm3_per_mm = new_flow.mm3_per_mm();
|
||||||
|
path.set_mm3_per_mm(new_flow.mm3_per_mm());
|
||||||
|
// path.width = new_flow.width();
|
||||||
|
path.set_width(new_flow.width());
|
||||||
|
// path.height = new_flow.height();
|
||||||
|
path.set_height(new_flow.height());
|
||||||
|
paths.emplace_back(std::move(path));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return paths;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Fill *clone() const override { return new FillConcentricInternal(*this); };
|
||||||
|
bool no_sort() const override { return true; }
|
||||||
|
|
||||||
|
const PrintConfig * print_config = nullptr;
|
||||||
|
const PrintObjectConfig *print_object_config = nullptr;
|
||||||
|
|
||||||
|
friend class Layer;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Slic3r
|
||||||
|
|
||||||
|
#endif // slic3r_FillConcentricInternal_hpp_
|
||||||
236
src/libslic3r/Fill/FillCrossHatch.cpp
Normal file
@@ -0,0 +1,236 @@
|
|||||||
|
#include "../ClipperUtils.hpp"
|
||||||
|
#include "../ShortestPath.hpp"
|
||||||
|
#include "../Surface.hpp"
|
||||||
|
|
||||||
|
#include "FillCrossHatch.hpp"
|
||||||
|
|
||||||
|
namespace Slic3r {
|
||||||
|
|
||||||
|
// CrossHatch Infill: Enhances 3D Printing Speed & Reduces Noise
|
||||||
|
// CrossHatch, as its name hints, alternates line direction by 90 degrees every few layers to improve adhesion.
|
||||||
|
// It introduces transform layers between direction shifts for better line cohesion, which fixes the weakness of line infill.
|
||||||
|
// The transform technique is inspired by David Eccles, improved 3D honeycomb but also a more flexible implementation.
|
||||||
|
// This method notably increases printing speed, meeting the demands of modern high-speed 3D printers, and reduces noise for most layers.
|
||||||
|
// By Bambu Lab
|
||||||
|
|
||||||
|
// graph credits: David Eccles (gringer).
|
||||||
|
// But we made a different definition for points.
|
||||||
|
/* o---o
|
||||||
|
* / \
|
||||||
|
* / \
|
||||||
|
* \ /
|
||||||
|
* \ /
|
||||||
|
* o---o
|
||||||
|
* p1 p2 p3 p4
|
||||||
|
*
|
||||||
|
* // X1 = progress * (1/8) * period
|
||||||
|
* // X2 = ( (1/2 - progress) * (1/8) ) * period
|
||||||
|
* // X3 = X1 + (1/2) * period
|
||||||
|
* // X4 = ( (1 - progress) * (1/8) ) * period
|
||||||
|
* // Y1 = X1
|
||||||
|
* // Y2 = X1
|
||||||
|
* // Y3 = -X1
|
||||||
|
* // Y4 = -X1
|
||||||
|
*/
|
||||||
|
|
||||||
|
static Pointfs generate_one_cycle(double progress, coordf_t period)
|
||||||
|
{
|
||||||
|
Pointfs out;
|
||||||
|
double offset = progress * 1. / 8. * period;
|
||||||
|
out.reserve(4);
|
||||||
|
out.push_back(Vec2d(0.25 * period - offset, offset));
|
||||||
|
out.push_back(Vec2d(0.25 * period + offset, offset));
|
||||||
|
out.push_back(Vec2d(0.75 * period - offset, -offset));
|
||||||
|
out.push_back(Vec2d(0.75 * period + offset, -offset));
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Polylines generate_transform_pattern(double inprogress, int direction, coordf_t ingrid_size, coordf_t inwidth, coordf_t inheight)
|
||||||
|
{
|
||||||
|
coordf_t width = inwidth;
|
||||||
|
coordf_t height = inheight;
|
||||||
|
coordf_t grid_size = ingrid_size * 2; // we due with odd and even saparately.
|
||||||
|
double progress = inprogress;
|
||||||
|
Polylines out_polylines;
|
||||||
|
|
||||||
|
// generate template patterns;
|
||||||
|
Pointfs one_cycle_points = generate_one_cycle(progress, grid_size);
|
||||||
|
|
||||||
|
Polyline one_cycle;
|
||||||
|
one_cycle.points.reserve(one_cycle_points.size());
|
||||||
|
for (size_t i = 0; i < one_cycle_points.size(); i++) one_cycle.points.push_back(Point(one_cycle_points[i]));
|
||||||
|
|
||||||
|
// swap if vertical
|
||||||
|
if (direction < 0) {
|
||||||
|
width = height;
|
||||||
|
height = inwidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
// replicate polylines;
|
||||||
|
Polylines odd_polylines;
|
||||||
|
Polyline odd_poly;
|
||||||
|
int num_of_cycle = width / grid_size + 2;
|
||||||
|
odd_poly.points.reserve(num_of_cycle * one_cycle.size());
|
||||||
|
|
||||||
|
// replicate to odd line
|
||||||
|
Point translate = Point(0, 0);
|
||||||
|
for (size_t i = 0; i < num_of_cycle; i++) {
|
||||||
|
Polyline odd_points;
|
||||||
|
odd_points = Polyline(one_cycle);
|
||||||
|
odd_points.translate(Point(i * grid_size, 0.0));
|
||||||
|
odd_poly.points.insert(odd_poly.points.end(), odd_points.begin(), odd_points.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
// fill the height
|
||||||
|
int num_of_lines = height / grid_size + 2;
|
||||||
|
odd_polylines.reserve(num_of_lines * odd_poly.size());
|
||||||
|
for (size_t i = 0; i < num_of_lines; i++) {
|
||||||
|
Polyline poly = odd_poly;
|
||||||
|
poly.translate(Point(0.0, grid_size * i));
|
||||||
|
odd_polylines.push_back(poly);
|
||||||
|
}
|
||||||
|
// save to output
|
||||||
|
out_polylines.insert(out_polylines.end(), odd_polylines.begin(), odd_polylines.end());
|
||||||
|
|
||||||
|
// replicate to even lines
|
||||||
|
Polylines even_polylines;
|
||||||
|
even_polylines.reserve(odd_polylines.size());
|
||||||
|
for (size_t i = 0; i < odd_polylines.size(); i++) {
|
||||||
|
Polyline even = odd_poly;
|
||||||
|
even.translate(Point(-0.5 * grid_size, (i + 0.5) * grid_size));
|
||||||
|
even_polylines.push_back(even);
|
||||||
|
}
|
||||||
|
|
||||||
|
// save for output
|
||||||
|
out_polylines.insert(out_polylines.end(), even_polylines.begin(), even_polylines.end());
|
||||||
|
|
||||||
|
// change to vertical if need
|
||||||
|
if (direction < 0) {
|
||||||
|
// swap xy, see if we need better performance method
|
||||||
|
for (Polyline& poly : out_polylines) {
|
||||||
|
for (Point& p : poly) { std::swap(p.x(), p.y()); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return out_polylines;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Polylines generate_repeat_pattern(int direction, coordf_t grid_size, coordf_t inwidth, coordf_t inheight)
|
||||||
|
{
|
||||||
|
coordf_t width = inwidth;
|
||||||
|
coordf_t height = inheight;
|
||||||
|
Polylines out_polylines;
|
||||||
|
|
||||||
|
// swap if vertical
|
||||||
|
if (direction < 0) {
|
||||||
|
width = height;
|
||||||
|
height = inwidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
int num_of_lines = height / grid_size + 1;
|
||||||
|
out_polylines.reserve(num_of_lines);
|
||||||
|
|
||||||
|
for (int i = 0; i < num_of_lines; i++) {
|
||||||
|
Polyline poly;
|
||||||
|
poly.points.reserve(2);
|
||||||
|
poly.append(Point(coordf_t(0), coordf_t(grid_size * i)));
|
||||||
|
poly.append(Point(width, coordf_t(grid_size * i)));
|
||||||
|
out_polylines.push_back(poly);
|
||||||
|
}
|
||||||
|
|
||||||
|
// change to vertical if needed
|
||||||
|
if (direction < 0) {
|
||||||
|
// swap xy
|
||||||
|
for (Polyline& poly : out_polylines) {
|
||||||
|
for (Point& p : poly) { std::swap(p.x(), p.y()); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return out_polylines;
|
||||||
|
}
|
||||||
|
|
||||||
|
// it makes the real patterns that overlap the bounding box
|
||||||
|
// repeat_ratio define the ratio between the height of repeat pattern and grid
|
||||||
|
static Polylines generate_infill_layers(coordf_t z_height, double repeat_ratio, coordf_t grid_size, coordf_t width, coordf_t height)
|
||||||
|
{
|
||||||
|
Polylines result;
|
||||||
|
coordf_t trans_layer_size = grid_size * 0.4; // upper.
|
||||||
|
coordf_t repeat_layer_size = grid_size * repeat_ratio; // lower.
|
||||||
|
z_height += repeat_layer_size / 2; // offset to improve first few layer strength
|
||||||
|
coordf_t period = trans_layer_size + repeat_layer_size;
|
||||||
|
coordf_t remains = z_height - std::floor(z_height / period) * period;
|
||||||
|
coordf_t trans_z = remains - repeat_layer_size; // put repeat layer first.
|
||||||
|
coordf_t repeat_z = remains;
|
||||||
|
|
||||||
|
int phase = fmod(z_height, period * 2) - (period - 1); // add epsilon
|
||||||
|
int direction = phase <= 0 ? -1 : 1;
|
||||||
|
|
||||||
|
// this is a repeat layer
|
||||||
|
if (trans_z < 0) {
|
||||||
|
result = generate_repeat_pattern(direction, grid_size, width, height);
|
||||||
|
}
|
||||||
|
// this is a transform layer
|
||||||
|
else {
|
||||||
|
double progress = fmod(trans_z, trans_layer_size) / trans_layer_size;
|
||||||
|
|
||||||
|
// split the progress to forward and backward, with a opposite direction.
|
||||||
|
if (progress < 0.5)
|
||||||
|
result = generate_transform_pattern((progress + 0.1) * 2, direction, grid_size, width, height); // increase overlapping.
|
||||||
|
else
|
||||||
|
result = generate_transform_pattern((1.1 - progress) * 2, -1 * direction, grid_size, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FillCrossHatch::_fill_surface_single(
|
||||||
|
const FillParams& params, unsigned int thickness_layers, const std::pair<float, Point>& direction, ExPolygon expolygon, Polylines& polylines_out)
|
||||||
|
{
|
||||||
|
// rotate angle
|
||||||
|
auto infill_angle = float(this->angle);
|
||||||
|
if (std::abs(infill_angle) >= EPSILON) expolygon.rotate(-infill_angle);
|
||||||
|
|
||||||
|
// get the rotated bounding box
|
||||||
|
BoundingBox bb = expolygon.contour.bounding_box();
|
||||||
|
|
||||||
|
// linespace modifier
|
||||||
|
coord_t line_spacing = coord_t(scale_(this->spacing) / params.density);
|
||||||
|
|
||||||
|
// reduce density
|
||||||
|
if (params.density < 0.999) line_spacing *= 1.5;
|
||||||
|
|
||||||
|
bb.merge(align_to_grid(bb.min, Point(line_spacing * 4, line_spacing * 4)));
|
||||||
|
|
||||||
|
// generate pattern
|
||||||
|
Polylines polylines = generate_infill_layers(scale_(this->z), 1, line_spacing, bb.size()(0), bb.size()(1));
|
||||||
|
|
||||||
|
// shift the pattern to the actual space
|
||||||
|
for (Polyline& pl : polylines) { pl.translate(bb.min); }
|
||||||
|
|
||||||
|
polylines = intersection_pl(polylines, to_polygons(expolygon));
|
||||||
|
|
||||||
|
// --- remove small remains from gyroid infill
|
||||||
|
if (!polylines.empty()) {
|
||||||
|
// Remove very small bits, but be careful to not remove infill lines connecting thin walls!
|
||||||
|
// The infill perimeter lines should be separated by around a single infill line width.
|
||||||
|
const double minlength = scale_(0.8 * this->spacing);
|
||||||
|
polylines.erase(std::remove_if(polylines.begin(), polylines.end(), [minlength](const Polyline& pl)
|
||||||
|
{ return pl.length() < minlength; }), polylines.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!polylines.empty()) {
|
||||||
|
int infill_start_idx = polylines_out.size(); // only rotate what belongs to us.
|
||||||
|
// connect lines
|
||||||
|
if (params.dont_connect() || polylines.size() <= 1)
|
||||||
|
append(polylines_out, chain_polylines(std::move(polylines)));
|
||||||
|
else
|
||||||
|
this->connect_infill(std::move(polylines), expolygon, polylines_out, this->spacing, params);
|
||||||
|
|
||||||
|
// rotate back
|
||||||
|
if (std::abs(infill_angle) >= EPSILON) {
|
||||||
|
for (auto it = polylines_out.begin() + infill_start_idx; it != polylines_out.end(); ++it) it->rotate(infill_angle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Slic3r
|
||||||
28
src/libslic3r/Fill/FillCrossHatch.hpp
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
#ifndef slic3r_FillCrossHatch_hpp_
|
||||||
|
#define slic3r_FillCrossHatch_hpp_
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#include "../libslic3r.h"
|
||||||
|
|
||||||
|
#include "FillBase.hpp"
|
||||||
|
|
||||||
|
namespace Slic3r {
|
||||||
|
|
||||||
|
class FillCrossHatch : public Fill
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Fill *clone() const override { return new FillCrossHatch(*this); };
|
||||||
|
~FillCrossHatch() override {}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void _fill_surface_single(const FillParams & params,
|
||||||
|
unsigned int thickness_layers,
|
||||||
|
const std::pair<float, Point> &direction,
|
||||||
|
ExPolygon expolygon,
|
||||||
|
Polylines & polylines_out) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Slic3r
|
||||||
|
|
||||||
|
#endif // slic3r_FillCrossHatch_hpp_
|
||||||
@@ -190,6 +190,8 @@ static constexpr const char *SVG_FILE_PATH_IN_3MF_ATTR = "filepath3mf";
|
|||||||
static constexpr const char *DEPTH_ATTR = "depth";
|
static constexpr const char *DEPTH_ATTR = "depth";
|
||||||
static constexpr const char *USE_SURFACE_ATTR = "use_surface";
|
static constexpr const char *USE_SURFACE_ATTR = "use_surface";
|
||||||
// static constexpr const char *FIX_TRANSFORMATION_ATTR = "transform";
|
// static constexpr const char *FIX_TRANSFORMATION_ATTR = "transform";
|
||||||
|
|
||||||
|
|
||||||
const unsigned int VALID_OBJECT_TYPES_COUNT = 1;
|
const unsigned int VALID_OBJECT_TYPES_COUNT = 1;
|
||||||
const char* VALID_OBJECT_TYPES[] =
|
const char* VALID_OBJECT_TYPES[] =
|
||||||
{
|
{
|
||||||
@@ -336,6 +338,7 @@ namespace Slic3r {
|
|||||||
class _3MF_Importer : public _3MF_Base
|
class _3MF_Importer : public _3MF_Base
|
||||||
{
|
{
|
||||||
typedef std::pair<std::string, int> PathId;
|
typedef std::pair<std::string, int> PathId;
|
||||||
|
|
||||||
struct Component
|
struct Component
|
||||||
{
|
{
|
||||||
PathId object_id;
|
PathId object_id;
|
||||||
@@ -476,7 +479,6 @@ namespace Slic3r {
|
|||||||
typedef std::map<int, CutObjectInfo> IdToCutObjectInfoMap;
|
typedef std::map<int, CutObjectInfo> IdToCutObjectInfoMap;
|
||||||
typedef std::map<int, std::vector<sla::SupportPoint>> IdToSlaSupportPointsMap;
|
typedef std::map<int, std::vector<sla::SupportPoint>> IdToSlaSupportPointsMap;
|
||||||
typedef std::map<int, std::vector<sla::DrainHole>> IdToSlaDrainHolesMap;
|
typedef std::map<int, std::vector<sla::DrainHole>> IdToSlaDrainHolesMap;
|
||||||
|
|
||||||
using PathToEmbossShapeFileMap = std::map<std::string, std::shared_ptr<std::string>>;
|
using PathToEmbossShapeFileMap = std::map<std::string, std::shared_ptr<std::string>>;
|
||||||
// Version of the 3mf file
|
// Version of the 3mf file
|
||||||
unsigned int m_version;
|
unsigned int m_version;
|
||||||
@@ -554,6 +556,7 @@ namespace Slic3r {
|
|||||||
// handlers to parse the .rels file
|
// handlers to parse the .rels file
|
||||||
void _handle_start_relationships_element(const char* name, const char** attributes);
|
void _handle_start_relationships_element(const char* name, const char** attributes);
|
||||||
bool _handle_start_relationship(const char **attributes, unsigned int num_attributes);
|
bool _handle_start_relationship(const char **attributes, unsigned int num_attributes);
|
||||||
|
|
||||||
// handlers to parse the .model file
|
// handlers to parse the .model file
|
||||||
void _handle_start_model_xml_element(const char* name, const char** attributes);
|
void _handle_start_model_xml_element(const char* name, const char** attributes);
|
||||||
void _handle_end_model_xml_element(const char* name);
|
void _handle_end_model_xml_element(const char* name);
|
||||||
@@ -627,6 +630,7 @@ namespace Slic3r {
|
|||||||
|
|
||||||
// callbacks to parse the .rels file
|
// callbacks to parse the .rels file
|
||||||
static void XMLCALL _handle_start_relationships_element(void *userData, const char *name, const char **attributes);
|
static void XMLCALL _handle_start_relationships_element(void *userData, const char *name, const char **attributes);
|
||||||
|
|
||||||
// callbacks to parse the .model file
|
// callbacks to parse the .model file
|
||||||
static void XMLCALL _handle_start_model_xml_element(void* userData, const char* name, const char** attributes);
|
static void XMLCALL _handle_start_model_xml_element(void* userData, const char* name, const char** attributes);
|
||||||
static void XMLCALL _handle_end_model_xml_element(void* userData, const char* name);
|
static void XMLCALL _handle_end_model_xml_element(void* userData, const char* name);
|
||||||
@@ -724,6 +728,7 @@ namespace Slic3r {
|
|||||||
m_model_path = MODEL_FILE;
|
m_model_path = MODEL_FILE;
|
||||||
_extract_relationships_from_archive(archive, stat);
|
_extract_relationships_from_archive(archive, stat);
|
||||||
bool found_model = false;
|
bool found_model = false;
|
||||||
|
|
||||||
// we first loop the entries to read from the .model files which are not root
|
// we first loop the entries to read from the .model files which are not root
|
||||||
for (mz_uint i = 0; i < num_entries; ++i) {
|
for (mz_uint i = 0; i < num_entries; ++i) {
|
||||||
if (mz_zip_reader_file_stat(&archive, i, &stat)) {
|
if (mz_zip_reader_file_stat(&archive, i, &stat)) {
|
||||||
@@ -754,6 +759,7 @@ namespace Slic3r {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read root model file
|
// Read root model file
|
||||||
if (start_part_stat.m_file_index < num_entries) {
|
if (start_part_stat.m_file_index < num_entries) {
|
||||||
try {
|
try {
|
||||||
@@ -1045,6 +1051,7 @@ namespace Slic3r {
|
|||||||
bool _3MF_Importer::_is_svg_shape_file(const std::string &name) const {
|
bool _3MF_Importer::_is_svg_shape_file(const std::string &name) const {
|
||||||
return boost::starts_with(name, MODEL_FOLDER) && boost::ends_with(name, ".svg");
|
return boost::starts_with(name, MODEL_FOLDER) && boost::ends_with(name, ".svg");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _3MF_Importer::_extract_model_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat)
|
bool _3MF_Importer::_extract_model_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat)
|
||||||
{
|
{
|
||||||
if (stat.m_uncomp_size == 0) {
|
if (stat.m_uncomp_size == 0) {
|
||||||
@@ -1502,6 +1509,7 @@ namespace Slic3r {
|
|||||||
svg->file_data = m_path_to_emboss_shape_files[filename];
|
svg->file_data = m_path_to_emboss_shape_files[filename];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _3MF_Importer::_extract_model_config_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat, Model& model)
|
bool _3MF_Importer::_extract_model_config_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat, Model& model)
|
||||||
{
|
{
|
||||||
if (stat.m_uncomp_size == 0) {
|
if (stat.m_uncomp_size == 0) {
|
||||||
@@ -1634,7 +1642,8 @@ namespace Slic3r {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
void _3MF_Importer::_handle_start_model_xml_element(const char* name, const char** attributes)
|
|
||||||
|
void _3MF_Importer::_handle_start_model_xml_element(const char *name, const char **attributes)
|
||||||
{
|
{
|
||||||
if (m_xml_parser == nullptr)
|
if (m_xml_parser == nullptr)
|
||||||
return;
|
return;
|
||||||
@@ -1775,6 +1784,7 @@ namespace Slic3r {
|
|||||||
{
|
{
|
||||||
if (!m_model_path.empty())
|
if (!m_model_path.empty())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// deletes all non-built or non-instanced objects
|
// deletes all non-built or non-instanced objects
|
||||||
for (const IdToModelObjectMap::value_type& object : m_objects) {
|
for (const IdToModelObjectMap::value_type& object : m_objects) {
|
||||||
if (object.second >= int(m_model->objects.size())) {
|
if (object.second >= int(m_model->objects.size())) {
|
||||||
@@ -1956,7 +1966,11 @@ namespace Slic3r {
|
|||||||
|
|
||||||
m_curr_object.geometry.custom_supports.push_back(get_attribute_value_string(attributes, num_attributes, CUSTOM_SUPPORTS_ATTR));
|
m_curr_object.geometry.custom_supports.push_back(get_attribute_value_string(attributes, num_attributes, CUSTOM_SUPPORTS_ATTR));
|
||||||
m_curr_object.geometry.custom_seam.push_back(get_attribute_value_string(attributes, num_attributes, CUSTOM_SEAM_ATTR));
|
m_curr_object.geometry.custom_seam.push_back(get_attribute_value_string(attributes, num_attributes, CUSTOM_SEAM_ATTR));
|
||||||
m_curr_object.geometry.mm_segmentation.push_back(get_attribute_value_string(attributes, num_attributes, MM_SEGMENTATION_ATTR));
|
std::string mm_segmentation_serialized = get_attribute_value_string(attributes, num_attributes, MM_SEGMENTATION_ATTR);
|
||||||
|
if (mm_segmentation_serialized.empty())
|
||||||
|
mm_segmentation_serialized = get_attribute_value_string(attributes, num_attributes, "paint_color");
|
||||||
|
m_curr_object.geometry.mm_segmentation.push_back(mm_segmentation_serialized);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1983,7 +1997,8 @@ namespace Slic3r {
|
|||||||
{
|
{
|
||||||
std::string path = get_attribute_value_string(attributes, num_attributes, PPATH_ATTR);
|
std::string path = get_attribute_value_string(attributes, num_attributes, PPATH_ATTR);
|
||||||
if (path.empty()) path = m_model_path;
|
if (path.empty()) path = m_model_path;
|
||||||
int object_id = get_attribute_value_int(attributes, num_attributes, OBJECTID_ATTR);
|
|
||||||
|
int object_id = get_attribute_value_int(attributes, num_attributes, OBJECTID_ATTR);
|
||||||
Transform3d transform = get_transform_from_3mf_specs_string(get_attribute_value_string(attributes, num_attributes, TRANSFORM_ATTR));
|
Transform3d transform = get_transform_from_3mf_specs_string(get_attribute_value_string(attributes, num_attributes, TRANSFORM_ATTR));
|
||||||
|
|
||||||
PathId path_id { path, object_id };
|
PathId path_id { path, object_id };
|
||||||
@@ -2131,11 +2146,11 @@ namespace Slic3r {
|
|||||||
{
|
{
|
||||||
IdToMetadataMap::iterator object = m_objects_metadata.find(m_curr_config.object_id);
|
IdToMetadataMap::iterator object = m_objects_metadata.find(m_curr_config.object_id);
|
||||||
if (object == m_objects_metadata.end()) {
|
if (object == m_objects_metadata.end()) {
|
||||||
add_error("Cannot assign volume mesh to a valid object");
|
add_error("Can not assign volume mesh to a valid object");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (object->second.volumes.empty()) {
|
if (object->second.volumes.empty()) {
|
||||||
add_error("Cannot assign mesh to a valid volume");
|
add_error("Can not assign mesh to a valid volume");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ObjectMetadata::VolumeMetadata& volume = object->second.volumes.back();
|
ObjectMetadata::VolumeMetadata& volume = object->second.volumes.back();
|
||||||
@@ -2470,12 +2485,12 @@ namespace Slic3r {
|
|||||||
volume->supported_facets.shrink_to_fit();
|
volume->supported_facets.shrink_to_fit();
|
||||||
volume->seam_facets.shrink_to_fit();
|
volume->seam_facets.shrink_to_fit();
|
||||||
volume->mm_segmentation_facets.shrink_to_fit();
|
volume->mm_segmentation_facets.shrink_to_fit();
|
||||||
|
|
||||||
if (auto &es = volume_data.shape_configuration; es.has_value())
|
if (auto &es = volume_data.shape_configuration; es.has_value())
|
||||||
volume->emboss_shape = std::move(es);
|
volume->emboss_shape = std::move(es);
|
||||||
if (auto &tc = volume_data.text_configuration; tc.has_value())
|
if (auto &tc = volume_data.text_configuration; tc.has_value())
|
||||||
volume->text_configuration = std::move(tc);
|
volume->text_configuration = std::move(tc);
|
||||||
|
|
||||||
|
|
||||||
// apply the remaining volume's metadata
|
// apply the remaining volume's metadata
|
||||||
for (const Metadata& metadata : volume_data.metadata) {
|
for (const Metadata& metadata : volume_data.metadata) {
|
||||||
if (metadata.key == NAME_KEY)
|
if (metadata.key == NAME_KEY)
|
||||||
@@ -3554,6 +3569,7 @@ namespace Slic3r {
|
|||||||
if (const std::optional<EmbossShape> &es = volume->emboss_shape;
|
if (const std::optional<EmbossShape> &es = volume->emboss_shape;
|
||||||
es.has_value())
|
es.has_value())
|
||||||
to_xml(stream, *es, *volume, archive);
|
to_xml(stream, *es, *volume, archive);
|
||||||
|
|
||||||
if (const std::optional<TextConfiguration> &tc = volume->text_configuration;
|
if (const std::optional<TextConfiguration> &tc = volume->text_configuration;
|
||||||
tc.has_value())
|
tc.has_value())
|
||||||
TextConfigurationSerialization::to_xml(stream, *tc);
|
TextConfigurationSerialization::to_xml(stream, *tc);
|
||||||
@@ -3759,11 +3775,12 @@ S bimap_cvt(const boost::bimap<F, S> &bmap, F f, const S &def_value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// TextConfiguration serialization
|
/// TextConfiguration serialization
|
||||||
/// </summary>
|
/// </summary>
|
||||||
const TextConfigurationSerialization::TypeToName TextConfigurationSerialization::type_to_name =
|
const TextConfigurationSerialization::TypeToName TextConfigurationSerialization::type_to_name =
|
||||||
boost::assign::list_of<TypeToName::relation>
|
boost::assign::list_of<TypeToName::relation>
|
||||||
(EmbossStyle::Type::file_path, "file_name")
|
(EmbossStyle::Type::file_path, "file_name")
|
||||||
(EmbossStyle::Type::wx_win_font_descr, "wxFontDescriptor_Windows")
|
(EmbossStyle::Type::wx_win_font_descr, "wxFontDescriptor_Windows")
|
||||||
(EmbossStyle::Type::wx_lin_font_descr, "wxFontDescriptor_Linux")
|
(EmbossStyle::Type::wx_lin_font_descr, "wxFontDescriptor_Linux")
|
||||||
@@ -3780,6 +3797,8 @@ const TextConfigurationSerialization::VerticalAlignToName TextConfigurationSeria
|
|||||||
(FontProp::VerticalAlign::top, "top")
|
(FontProp::VerticalAlign::top, "top")
|
||||||
(FontProp::VerticalAlign::center, "middle")
|
(FontProp::VerticalAlign::center, "middle")
|
||||||
(FontProp::VerticalAlign::bottom, "bottom");
|
(FontProp::VerticalAlign::bottom, "bottom");
|
||||||
|
|
||||||
|
|
||||||
void TextConfigurationSerialization::to_xml(std::stringstream &stream, const TextConfiguration &tc)
|
void TextConfigurationSerialization::to_xml(std::stringstream &stream, const TextConfiguration &tc)
|
||||||
{
|
{
|
||||||
stream << " <" << TEXT_TAG << " ";
|
stream << " <" << TEXT_TAG << " ";
|
||||||
@@ -3827,6 +3846,7 @@ namespace {
|
|||||||
|
|
||||||
FontProp::HorizontalAlign read_horizontal_align(const char **attributes, unsigned int num_attributes, const TextConfigurationSerialization::HorizontalAlignToName& horizontal_align_to_name){
|
FontProp::HorizontalAlign read_horizontal_align(const char **attributes, unsigned int num_attributes, const TextConfigurationSerialization::HorizontalAlignToName& horizontal_align_to_name){
|
||||||
std::string horizontal_align_str = get_attribute_value_string(attributes, num_attributes, HORIZONTAL_ALIGN_ATTR);
|
std::string horizontal_align_str = get_attribute_value_string(attributes, num_attributes, HORIZONTAL_ALIGN_ATTR);
|
||||||
|
|
||||||
// Back compatibility
|
// Back compatibility
|
||||||
// PS 2.6.0 do not have align
|
// PS 2.6.0 do not have align
|
||||||
if (horizontal_align_str.empty())
|
if (horizontal_align_str.empty())
|
||||||
@@ -3838,10 +3858,11 @@ FontProp::HorizontalAlign read_horizontal_align(const char **attributes, unsigne
|
|||||||
int horizontal_align_int = 0;
|
int horizontal_align_int = 0;
|
||||||
if(boost::spirit::qi::parse(horizontal_align_str.c_str(), horizontal_align_str.c_str() + 1, boost::spirit::qi::int_, horizontal_align_int))
|
if(boost::spirit::qi::parse(horizontal_align_str.c_str(), horizontal_align_str.c_str() + 1, boost::spirit::qi::int_, horizontal_align_int))
|
||||||
return static_cast<FontProp::HorizontalAlign>(horizontal_align_int);
|
return static_cast<FontProp::HorizontalAlign>(horizontal_align_int);
|
||||||
}
|
}
|
||||||
|
|
||||||
return bimap_cvt(horizontal_align_to_name, std::string_view(horizontal_align_str), FontProp::HorizontalAlign::center);
|
return bimap_cvt(horizontal_align_to_name, std::string_view(horizontal_align_str), FontProp::HorizontalAlign::center);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
FontProp::VerticalAlign read_vertical_align(const char **attributes, unsigned int num_attributes, const TextConfigurationSerialization::VerticalAlignToName& vertical_align_to_name){
|
FontProp::VerticalAlign read_vertical_align(const char **attributes, unsigned int num_attributes, const TextConfigurationSerialization::VerticalAlignToName& vertical_align_to_name){
|
||||||
std::string vertical_align_str = get_attribute_value_string(attributes, num_attributes, VERTICAL_ALIGN_ATTR);
|
std::string vertical_align_str = get_attribute_value_string(attributes, num_attributes, VERTICAL_ALIGN_ATTR);
|
||||||
@@ -3860,7 +3881,8 @@ FontProp::VerticalAlign read_vertical_align(const char **attributes, unsigned in
|
|||||||
}
|
}
|
||||||
|
|
||||||
return bimap_cvt(vertical_align_to_name, std::string_view(vertical_align_str), FontProp::VerticalAlign::center);
|
return bimap_cvt(vertical_align_to_name, std::string_view(vertical_align_str), FontProp::VerticalAlign::center);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
std::optional<TextConfiguration> TextConfigurationSerialization::read(const char **attributes, unsigned int num_attributes)
|
std::optional<TextConfiguration> TextConfigurationSerialization::read(const char **attributes, unsigned int num_attributes)
|
||||||
@@ -3882,6 +3904,7 @@ std::optional<TextConfiguration> TextConfigurationSerialization::read(const char
|
|||||||
fp.align = FontProp::Align(
|
fp.align = FontProp::Align(
|
||||||
read_horizontal_align(attributes, num_attributes, horizontal_align_to_name),
|
read_horizontal_align(attributes, num_attributes, horizontal_align_to_name),
|
||||||
read_vertical_align(attributes, num_attributes, vertical_align_to_name));
|
read_vertical_align(attributes, num_attributes, vertical_align_to_name));
|
||||||
|
|
||||||
int collection_number = get_attribute_value_int(attributes, num_attributes, COLLECTION_NUMBER_ATTR);
|
int collection_number = get_attribute_value_int(attributes, num_attributes, COLLECTION_NUMBER_ATTR);
|
||||||
if (collection_number > 0) fp.collection_number = static_cast<unsigned int>(collection_number);
|
if (collection_number > 0) fp.collection_number = static_cast<unsigned int>(collection_number);
|
||||||
|
|
||||||
|
|||||||
@@ -166,6 +166,7 @@ public:
|
|||||||
|
|
||||||
std::optional<Point> last_position;
|
std::optional<Point> last_position;
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class GCodeOutputStream {
|
class GCodeOutputStream {
|
||||||
public:
|
public:
|
||||||
@@ -455,6 +456,9 @@ private:
|
|||||||
// Processor
|
// Processor
|
||||||
GCodeProcessor m_processor;
|
GCodeProcessor m_processor;
|
||||||
|
|
||||||
|
//Y27
|
||||||
|
bool m_resonance_avoidance;
|
||||||
|
|
||||||
// Back-pointer to Print (const).
|
// Back-pointer to Print (const).
|
||||||
const Print* m_print;
|
const Print* m_print;
|
||||||
std::string _extrude(
|
std::string _extrude(
|
||||||
@@ -465,6 +469,13 @@ private:
|
|||||||
|
|
||||||
// On the first printing layer. This flag triggers first layer speeds.
|
// On the first printing layer. This flag triggers first layer speeds.
|
||||||
bool on_first_layer() const { return m_layer != nullptr && m_layer->id() == 0; }
|
bool on_first_layer() const { return m_layer != nullptr && m_layer->id() == 0; }
|
||||||
|
//w25
|
||||||
|
int layer_id() const
|
||||||
|
{
|
||||||
|
if (m_layer == nullptr)
|
||||||
|
return -1;
|
||||||
|
return m_layer->id();
|
||||||
|
}
|
||||||
// To control print speed of 1st object layer over raft interface.
|
// To control print speed of 1st object layer over raft interface.
|
||||||
bool object_layer_over_raft() const { return m_object_layer_over_raft; }
|
bool object_layer_over_raft() const { return m_object_layer_over_raft; }
|
||||||
|
|
||||||
|
|||||||
@@ -236,6 +236,8 @@ struct PerExtruderAdjustments
|
|||||||
float slowdown_below_layer_time = 0.f;
|
float slowdown_below_layer_time = 0.f;
|
||||||
// Minimum print speed allowed for this extruder.
|
// Minimum print speed allowed for this extruder.
|
||||||
float min_print_speed = 0.f;
|
float min_print_speed = 0.f;
|
||||||
|
//Y28
|
||||||
|
bool dont_slow_down_outer_wall = true;
|
||||||
|
|
||||||
// Parsed lines.
|
// Parsed lines.
|
||||||
std::vector<CoolingLine> lines;
|
std::vector<CoolingLine> lines;
|
||||||
@@ -344,6 +346,8 @@ std::vector<PerExtruderAdjustments> CoolingBuffer::parse_layer_gcode(const std::
|
|||||||
adj.cooling_slow_down_enabled = m_config.cooling.get_at(extruder_id);
|
adj.cooling_slow_down_enabled = m_config.cooling.get_at(extruder_id);
|
||||||
adj.slowdown_below_layer_time = float(m_config.slowdown_below_layer_time.get_at(extruder_id));
|
adj.slowdown_below_layer_time = float(m_config.slowdown_below_layer_time.get_at(extruder_id));
|
||||||
adj.min_print_speed = float(m_config.min_print_speed.get_at(extruder_id));
|
adj.min_print_speed = float(m_config.min_print_speed.get_at(extruder_id));
|
||||||
|
//Y28
|
||||||
|
adj.dont_slow_down_outer_wall = m_config.dont_slow_down_outer_wall.get_at(extruder_id);
|
||||||
map_extruder_to_per_extruder_adjustment[extruder_id] = i;
|
map_extruder_to_per_extruder_adjustment[extruder_id] = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -424,7 +428,12 @@ std::vector<PerExtruderAdjustments> CoolingBuffer::parse_layer_gcode(const std::
|
|||||||
line.type |= CoolingLine::TYPE_EXTERNAL_PERIMETER;
|
line.type |= CoolingLine::TYPE_EXTERNAL_PERIMETER;
|
||||||
if (wipe)
|
if (wipe)
|
||||||
line.type |= CoolingLine::TYPE_WIPE;
|
line.type |= CoolingLine::TYPE_WIPE;
|
||||||
if (boost::contains(sline, ";_EXTRUDE_SET_SPEED") && ! wipe) {
|
//Y28
|
||||||
|
bool adjust_external = true;
|
||||||
|
if (adjustment->dont_slow_down_outer_wall && external_perimeter)
|
||||||
|
adjust_external = false;
|
||||||
|
|
||||||
|
if (boost::contains(sline, ";_EXTRUDE_SET_SPEED") && ! wipe && adjust_external) {
|
||||||
line.type |= CoolingLine::TYPE_ADJUSTABLE;
|
line.type |= CoolingLine::TYPE_ADJUSTABLE;
|
||||||
active_speed_modifier = adjustment->lines.size();
|
active_speed_modifier = adjustment->lines.size();
|
||||||
}
|
}
|
||||||
@@ -799,19 +808,19 @@ std::string CoolingBuffer::apply_layer_cooldown(
|
|||||||
auto change_extruder_set_fan = [this, layer_id, layer_time, &new_gcode, &bridge_fan_control, &bridge_fan_speed]() {
|
auto change_extruder_set_fan = [this, layer_id, layer_time, &new_gcode, &bridge_fan_control, &bridge_fan_speed]() {
|
||||||
#define EXTRUDER_CONFIG(OPT) m_config.OPT.get_at(m_current_extruder)
|
#define EXTRUDER_CONFIG(OPT) m_config.OPT.get_at(m_current_extruder)
|
||||||
int min_fan_speed = EXTRUDER_CONFIG(min_fan_speed);
|
int min_fan_speed = EXTRUDER_CONFIG(min_fan_speed);
|
||||||
//B15
|
//B15//Y26
|
||||||
int enable_auxiliary_fan = EXTRUDER_CONFIG(enable_auxiliary_fan);
|
int enable_auxiliary_fan;
|
||||||
|
if (m_config.opt_bool("seal_print"))
|
||||||
|
enable_auxiliary_fan = EXTRUDER_CONFIG(enable_auxiliary_fan);
|
||||||
|
else
|
||||||
|
enable_auxiliary_fan = EXTRUDER_CONFIG(enable_auxiliary_fan_unseal);
|
||||||
//B25
|
//B25
|
||||||
int enable_volume_fan = EXTRUDER_CONFIG(enable_volume_fan);
|
int enable_volume_fan = EXTRUDER_CONFIG(enable_volume_fan);
|
||||||
int fan_speed_new = EXTRUDER_CONFIG(fan_always_on) ? min_fan_speed : 0;
|
int fan_speed_new = EXTRUDER_CONFIG(fan_always_on) ? min_fan_speed : 0;
|
||||||
|
|
||||||
std::pair<int, int> custom_fan_speed_limits{fan_speed_new, 100 };
|
std::pair<int, int> custom_fan_speed_limits{fan_speed_new, 100 };
|
||||||
int disable_fan_first_layers = EXTRUDER_CONFIG(disable_fan_first_layers);
|
int disable_fan_first_layers = EXTRUDER_CONFIG(disable_fan_first_layers);
|
||||||
|
|
||||||
//B39
|
//B39
|
||||||
int disable_rapid_cooling_fan_first_layers = EXTRUDER_CONFIG(disable_rapid_cooling_fan_first_layers);
|
int disable_rapid_cooling_fan_first_layers = EXTRUDER_CONFIG(disable_rapid_cooling_fan_first_layers);
|
||||||
|
|
||||||
|
|
||||||
// Is the fan speed ramp enabled?
|
// Is the fan speed ramp enabled?
|
||||||
int full_fan_speed_layer = EXTRUDER_CONFIG(full_fan_speed_layer);
|
int full_fan_speed_layer = EXTRUDER_CONFIG(full_fan_speed_layer);
|
||||||
if (disable_fan_first_layers <= 0 && full_fan_speed_layer > 0) {
|
if (disable_fan_first_layers <= 0 && full_fan_speed_layer > 0) {
|
||||||
@@ -862,21 +871,18 @@ std::string CoolingBuffer::apply_layer_cooldown(
|
|||||||
new_gcode += fan_gcode.str();
|
new_gcode += fan_gcode.str();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//B25
|
|
||||||
if (int(layer_id) == disable_fan_first_layers) {
|
|
||||||
int volume_fan_speed_new = 255 * enable_volume_fan / 100;
|
|
||||||
if (volume_fan_speed_new != m_volume_fan_speed) {
|
|
||||||
std::ostringstream fan_gcode;
|
|
||||||
m_volume_fan_speed = volume_fan_speed_new;
|
|
||||||
fan_gcode << "M106 P3 S" << volume_fan_speed_new << "\n";
|
|
||||||
new_gcode += fan_gcode.str();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fan_speed_new != m_fan_speed) {
|
if (fan_speed_new != m_fan_speed) {
|
||||||
m_fan_speed = fan_speed_new;
|
m_fan_speed = fan_speed_new;
|
||||||
new_gcode += GCodeWriter::set_fan(m_config.gcode_flavor, m_config.gcode_comments, m_fan_speed);
|
new_gcode += GCodeWriter::set_fan(m_config.gcode_flavor, m_config.gcode_comments, m_fan_speed);
|
||||||
}
|
}
|
||||||
|
//B25
|
||||||
|
int volume_fan_speed_new = 255 * enable_volume_fan / 100;
|
||||||
|
if (volume_fan_speed_new != m_volume_fan_speed) {
|
||||||
|
std::ostringstream fan_gcode;
|
||||||
|
m_volume_fan_speed = volume_fan_speed_new;
|
||||||
|
fan_gcode << "M106 P3 S" << volume_fan_speed_new << "\n";
|
||||||
|
new_gcode += fan_gcode.str();
|
||||||
|
}
|
||||||
custom_fan_speed_limits.first = std::min(custom_fan_speed_limits.first, custom_fan_speed_limits.second);
|
custom_fan_speed_limits.first = std::min(custom_fan_speed_limits.first, custom_fan_speed_limits.second);
|
||||||
return custom_fan_speed_limits;
|
return custom_fan_speed_limits;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -683,7 +683,10 @@ void Layer::make_perimeters()
|
|||||||
&& config.infill_overlap == other_config.infill_overlap
|
&& config.infill_overlap == other_config.infill_overlap
|
||||||
&& config.fuzzy_skin == other_config.fuzzy_skin
|
&& config.fuzzy_skin == other_config.fuzzy_skin
|
||||||
&& config.fuzzy_skin_thickness == other_config.fuzzy_skin_thickness
|
&& config.fuzzy_skin_thickness == other_config.fuzzy_skin_thickness
|
||||||
&& config.fuzzy_skin_point_dist == other_config.fuzzy_skin_point_dist)
|
&& config.fuzzy_skin_point_dist == other_config.fuzzy_skin_point_dist
|
||||||
|
//w38
|
||||||
|
&& config.overhang_reverse == other_config.overhang_reverse
|
||||||
|
&& config.overhang_reverse_threshold == other_config.overhang_reverse_threshold)
|
||||||
{
|
{
|
||||||
layer_region_reset_perimeters(*other_layerm);
|
layer_region_reset_perimeters(*other_layerm);
|
||||||
layer_region_ids.push_back(it - m_regions.begin());
|
layer_region_ids.push_back(it - m_regions.begin());
|
||||||
|
|||||||
@@ -114,6 +114,8 @@ void LayerRegion::make_perimeters(
|
|||||||
Polygons lower_layer_polygons_cache;
|
Polygons lower_layer_polygons_cache;
|
||||||
//w16
|
//w16
|
||||||
Polygons upper_layer_polygons_cache;
|
Polygons upper_layer_polygons_cache;
|
||||||
|
//w38
|
||||||
|
params.lower_slices = lower_slices;
|
||||||
|
|
||||||
for (const Surface &surface : slices) {
|
for (const Surface &surface : slices) {
|
||||||
auto perimeters_begin = uint32_t(m_perimeters.size());
|
auto perimeters_begin = uint32_t(m_perimeters.size());
|
||||||
@@ -137,7 +139,9 @@ void LayerRegion::make_perimeters(
|
|||||||
m_thin_fills,
|
m_thin_fills,
|
||||||
fill_expolygons,
|
fill_expolygons,
|
||||||
//w21
|
//w21
|
||||||
fill_no_overlap_expolygons);
|
fill_no_overlap_expolygons,
|
||||||
|
//w23
|
||||||
|
this->layer()->id());
|
||||||
else
|
else
|
||||||
PerimeterGenerator::process_arachne(
|
PerimeterGenerator::process_arachne(
|
||||||
// input:
|
// input:
|
||||||
@@ -152,7 +156,9 @@ void LayerRegion::make_perimeters(
|
|||||||
m_thin_fills,
|
m_thin_fills,
|
||||||
fill_expolygons,
|
fill_expolygons,
|
||||||
//w21
|
//w21
|
||||||
fill_no_overlap_expolygons);
|
fill_no_overlap_expolygons,
|
||||||
|
//w23
|
||||||
|
this->layer()->id());
|
||||||
|
|
||||||
else
|
else
|
||||||
PerimeterGenerator::process_classic(
|
PerimeterGenerator::process_classic(
|
||||||
@@ -169,7 +175,9 @@ void LayerRegion::make_perimeters(
|
|||||||
m_thin_fills,
|
m_thin_fills,
|
||||||
fill_expolygons,
|
fill_expolygons,
|
||||||
//w21
|
//w21
|
||||||
fill_no_overlap_expolygons);
|
fill_no_overlap_expolygons,
|
||||||
|
//w23
|
||||||
|
this->layer()->id());
|
||||||
perimeter_and_gapfill_ranges.emplace_back(
|
perimeter_and_gapfill_ranges.emplace_back(
|
||||||
ExtrusionRange{ perimeters_begin, uint32_t(m_perimeters.size()) },
|
ExtrusionRange{ perimeters_begin, uint32_t(m_perimeters.size()) },
|
||||||
ExtrusionRange{ gap_fills_begin, uint32_t(m_thin_fills.size()) });
|
ExtrusionRange{ gap_fills_begin, uint32_t(m_thin_fills.size()) });
|
||||||
@@ -419,86 +427,241 @@ ExpansionResult expand_expolygons(
|
|||||||
// Extract bridging surfaces from "surfaces", expand them into "shells" using expansion_params,
|
// Extract bridging surfaces from "surfaces", expand them into "shells" using expansion_params,
|
||||||
// detect bridges.
|
// detect bridges.
|
||||||
// Trim "shells" by the expanded bridges.
|
// Trim "shells" by the expanded bridges.
|
||||||
Surfaces expand_bridges_detect_orientations(
|
//w36
|
||||||
Surfaces &surfaces,
|
Surfaces expand_bridges_detect_orientations(Surfaces & surfaces,
|
||||||
std::vector<ExpansionZone>& expansion_zones,
|
ExPolygons & shells,
|
||||||
const float closing_radius
|
const Algorithm::RegionExpansionParameters &expansion_params_into_solid_infill,
|
||||||
)
|
ExPolygons & sparse,
|
||||||
|
const Algorithm::RegionExpansionParameters &expansion_params_into_sparse_infill,
|
||||||
|
const float closing_radius)
|
||||||
{
|
{
|
||||||
using namespace Slic3r::Algorithm;
|
using namespace Slic3r::Algorithm;
|
||||||
|
|
||||||
double thickness;
|
//w36
|
||||||
ExPolygons bridge_expolygons = fill_surfaces_extract_expolygons(surfaces, {stBottomBridge}, thickness);
|
double thickness;
|
||||||
if (bridge_expolygons.empty())
|
ExPolygons bridges_ex = fill_surfaces_extract_expolygons(surfaces, {stBottomBridge}, thickness);
|
||||||
|
if (bridges_ex.empty())
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
// Calculate bridge anchors and their expansions in their respective shell region.
|
// Calculate bridge anchors and their expansions in their respective shell region.
|
||||||
ExpansionResult expansion_result{expand_expolygons(
|
//w36
|
||||||
bridge_expolygons,
|
WaveSeeds bridge_anchors = wave_seeds(bridges_ex, shells, expansion_params_into_solid_infill.tiny_expansion, true);
|
||||||
expansion_zones
|
std::vector<RegionExpansionEx> bridge_expansions = propagate_waves_ex(bridge_anchors, shells, expansion_params_into_solid_infill);
|
||||||
)};
|
bool expanded_into_shells = !bridge_expansions.empty();
|
||||||
|
bool expanded_into_sparse = false;
|
||||||
|
{
|
||||||
|
WaveSeeds bridge_anchors_sparse = wave_seeds(bridges_ex, sparse, expansion_params_into_sparse_infill.tiny_expansion, true);
|
||||||
|
std::vector<RegionExpansionEx> bridge_expansions_sparse = propagate_waves_ex(bridge_anchors_sparse, sparse,
|
||||||
|
expansion_params_into_sparse_infill);
|
||||||
|
if (!bridge_expansions_sparse.empty()) {
|
||||||
|
expanded_into_sparse = true;
|
||||||
|
for (WaveSeed &seed : bridge_anchors_sparse)
|
||||||
|
seed.boundary += uint32_t(shells.size());
|
||||||
|
for (RegionExpansionEx &expansion : bridge_expansions_sparse)
|
||||||
|
expansion.boundary_id += uint32_t(shells.size());
|
||||||
|
append(bridge_anchors, std::move(bridge_anchors_sparse));
|
||||||
|
append(bridge_expansions, std::move(bridge_expansions_sparse));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<Bridge> bridges{get_grouped_bridges(
|
// Cache for detecting bridge orientation and merging regions with overlapping expansions.
|
||||||
std::move(bridge_expolygons),
|
struct Bridge
|
||||||
expansion_result.expansions
|
{
|
||||||
)};
|
ExPolygon expolygon;
|
||||||
bridge_expolygons.clear();
|
uint32_t group_id;
|
||||||
|
std::vector<RegionExpansionEx>::const_iterator bridge_expansion_begin;
|
||||||
|
double angle = -1;
|
||||||
|
};
|
||||||
|
std::vector<Bridge> bridges;
|
||||||
|
{
|
||||||
|
bridges.reserve(bridges_ex.size());
|
||||||
|
uint32_t group_id = 0;
|
||||||
|
for (ExPolygon &ex : bridges_ex)
|
||||||
|
bridges.push_back({std::move(ex), group_id++, bridge_expansions.end()});
|
||||||
|
bridges_ex.clear();
|
||||||
|
}
|
||||||
|
|
||||||
std::sort(expansion_result.anchors.begin(), expansion_result.anchors.end(), Algorithm::lower_by_src_and_boundary);
|
// Group the bridge surfaces by overlaps.
|
||||||
detect_bridge_directions(expansion_result.anchors, bridges, expansion_zones);
|
auto group_id = [&bridges](uint32_t src_id) {
|
||||||
|
uint32_t group_id = bridges[src_id].group_id;
|
||||||
|
while (group_id != src_id) {
|
||||||
|
src_id = group_id;
|
||||||
|
group_id = bridges[src_id].group_id;
|
||||||
|
}
|
||||||
|
bridges[src_id].group_id = group_id;
|
||||||
|
return group_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
{
|
||||||
|
// Cache of bboxes per expansion boundary.
|
||||||
|
std::vector<BoundingBox> bboxes;
|
||||||
|
// Detect overlaps of bridge anchors inside their respective shell regions.
|
||||||
|
// bridge_expansions are sorted by boundary id and source id.
|
||||||
|
for (auto it = bridge_expansions.begin(); it != bridge_expansions.end();) {
|
||||||
|
// For each boundary region:
|
||||||
|
auto it_begin = it;
|
||||||
|
auto it_end = std::next(it_begin);
|
||||||
|
for (; it_end != bridge_expansions.end() && it_end->boundary_id == it_begin->boundary_id; ++it_end)
|
||||||
|
;
|
||||||
|
bboxes.clear();
|
||||||
|
bboxes.reserve(it_end - it_begin);
|
||||||
|
for (auto it2 = it_begin; it2 != it_end; ++it2)
|
||||||
|
bboxes.emplace_back(get_extents(it2->expolygon.contour));
|
||||||
|
// For each bridge anchor of the current source:
|
||||||
|
for (; it != it_end; ++it) {
|
||||||
|
// A grup id for this bridge.
|
||||||
|
for (auto it2 = std::next(it); it2 != it_end; ++it2)
|
||||||
|
if (it->src_id != it2->src_id && bboxes[it - it_begin].overlap(bboxes[it2 - it_begin]) &&
|
||||||
|
// One may ignore holes, they are irrelevant for intersection test.
|
||||||
|
!intersection(it->expolygon.contour, it2->expolygon.contour).empty()) {
|
||||||
|
// The two bridge regions intersect. Give them the same (lower) group id.
|
||||||
|
uint32_t id = group_id(it->src_id);
|
||||||
|
uint32_t id2 = group_id(it2->src_id);
|
||||||
|
if (id < id2)
|
||||||
|
bridges[id2].group_id = id;
|
||||||
|
else
|
||||||
|
bridges[id].group_id = id2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Detect bridge directions.
|
||||||
|
{
|
||||||
|
std::sort(bridge_anchors.begin(), bridge_anchors.end(), Algorithm::lower_by_src_and_boundary);
|
||||||
|
auto it_bridge_anchor = bridge_anchors.begin();
|
||||||
|
Lines lines;
|
||||||
|
Polygons anchor_areas;
|
||||||
|
for (uint32_t bridge_id = 0; bridge_id < uint32_t(bridges.size()); ++bridge_id) {
|
||||||
|
Bridge &bridge = bridges[bridge_id];
|
||||||
|
// lines.clear();
|
||||||
|
anchor_areas.clear();
|
||||||
|
int32_t last_anchor_id = -1;
|
||||||
|
for (; it_bridge_anchor != bridge_anchors.end() && it_bridge_anchor->src == bridge_id; ++it_bridge_anchor) {
|
||||||
|
if (last_anchor_id != int(it_bridge_anchor->boundary)) {
|
||||||
|
last_anchor_id = int(it_bridge_anchor->boundary);
|
||||||
|
append(anchor_areas,
|
||||||
|
to_polygons(last_anchor_id < int32_t(shells.size()) ? shells[last_anchor_id] :
|
||||||
|
sparse[last_anchor_id - int32_t(shells.size())]));
|
||||||
|
}
|
||||||
|
// if (Points &polyline = it_bridge_anchor->path; polyline.size() >= 2) {
|
||||||
|
// reserve_more_power_of_2(lines, polyline.size() - 1);
|
||||||
|
// for (size_t i = 1; i < polyline.size(); ++ i)
|
||||||
|
// lines.push_back({ polyline[i - 1], polyline[1] });
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
lines = to_lines(diff_pl(to_polylines(bridge.expolygon), expand(anchor_areas, float(SCALED_EPSILON))));
|
||||||
|
auto [bridging_dir, unsupported_dist] = detect_bridging_direction(lines, to_polygons(bridge.expolygon));
|
||||||
|
bridge.angle = M_PI + std::atan2(bridging_dir.y(), bridging_dir.x());
|
||||||
|
#if 0
|
||||||
|
coordf_t stroke_width = scale_(0.06);
|
||||||
|
BoundingBox bbox = get_extents(anchor_areas);
|
||||||
|
bbox.merge(get_extents(bridge.expolygon));
|
||||||
|
bbox.offset(scale_(1.));
|
||||||
|
::Slic3r::SVG
|
||||||
|
svg(debug_out_path(("bridge" + std::to_string(bridge.angle) + "_" /* + std::to_string(this->layer()->bottom_z())*/).c_str()),
|
||||||
|
bbox);
|
||||||
|
svg.draw(bridge.expolygon, "cyan");
|
||||||
|
svg.draw(lines, "green", stroke_width);
|
||||||
|
svg.draw(anchor_areas, "red");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Merge the groups with the same group id, produce surfaces by merging source overhangs with their newly expanded anchors.
|
// Merge the groups with the same group id, produce surfaces by merging source overhangs with their newly expanded anchors.
|
||||||
std::sort(expansion_result.expansions.begin(), expansion_result.expansions.end(), [](auto &l, auto &r) {
|
//w36
|
||||||
return l.src_id < r.src_id || (l.src_id == r.src_id && l.boundary_id < r.boundary_id);
|
Surfaces out;
|
||||||
});
|
{
|
||||||
Surfaces out{merge_bridges(bridges, expansion_result.expansions, closing_radius)};
|
Polygons acc;
|
||||||
|
Surface templ{stBottomBridge, {}};
|
||||||
|
std::sort(bridge_expansions.begin(), bridge_expansions.end(),
|
||||||
|
[](auto &l, auto &r) { return l.src_id < r.src_id || (l.src_id == r.src_id && l.boundary_id < r.boundary_id); });
|
||||||
|
for (auto it = bridge_expansions.begin(); it != bridge_expansions.end();) {
|
||||||
|
bridges[it->src_id].bridge_expansion_begin = it;
|
||||||
|
uint32_t src_id = it->src_id;
|
||||||
|
for (++it; it != bridge_expansions.end() && it->src_id == src_id; ++it)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
for (uint32_t bridge_id = 0; bridge_id < uint32_t(bridges.size()); ++bridge_id)
|
||||||
|
if (group_id(bridge_id) == bridge_id) {
|
||||||
|
// Head of the group.
|
||||||
|
acc.clear();
|
||||||
|
for (uint32_t bridge_id2 = bridge_id; bridge_id2 < uint32_t(bridges.size()); ++bridge_id2)
|
||||||
|
if (group_id(bridge_id2) == bridge_id) {
|
||||||
|
append(acc, to_polygons(std::move(bridges[bridge_id2].expolygon)));
|
||||||
|
auto it_bridge_expansion = bridges[bridge_id2].bridge_expansion_begin;
|
||||||
|
assert(it_bridge_expansion == bridge_expansions.end() || it_bridge_expansion->src_id == bridge_id2);
|
||||||
|
for (; it_bridge_expansion != bridge_expansions.end() && it_bridge_expansion->src_id == bridge_id2;
|
||||||
|
++it_bridge_expansion)
|
||||||
|
append(acc, to_polygons(std::move(it_bridge_expansion->expolygon)));
|
||||||
|
}
|
||||||
|
// FIXME try to be smart and pick the best bridging angle for all?
|
||||||
|
templ.bridge_angle = bridges[bridge_id].angle;
|
||||||
|
// NOTE: The current regularization of the shells can create small unasigned regions in the object (E.G. benchy)
|
||||||
|
// without the following closing operation, those regions will stay unfilled and cause small holes in the expanded surface.
|
||||||
|
// look for narrow_ensure_vertical_wall_thickness_region_radius filter.
|
||||||
|
ExPolygons final = closing_ex(acc, closing_radius);
|
||||||
|
// without safety offset, artifacts are generated (GH #2494)
|
||||||
|
// union_safety_offset_ex(acc)
|
||||||
|
for (ExPolygon &ex : final)
|
||||||
|
out.emplace_back(templ, std::move(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Clip by the expanded bridges.
|
// Clip by the expanded bridges.
|
||||||
for (ExpansionZone& expansion_zone : expansion_zones)
|
//w36
|
||||||
if (expansion_zone.expanded_into)
|
if (expanded_into_shells)
|
||||||
expansion_zone.expolygons = diff_ex(expansion_zone.expolygons, out);
|
shells = diff_ex(shells, out);
|
||||||
|
if (expanded_into_sparse)
|
||||||
|
sparse = diff_ex(sparse, out);
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
Surfaces expand_merge_surfaces(
|
//w36
|
||||||
Surfaces &surfaces,
|
Surfaces expand_merge_surfaces(Surfaces & surfaces,
|
||||||
SurfaceType surface_type,
|
SurfaceType surface_type,
|
||||||
std::vector<ExpansionZone>& expansion_zones,
|
ExPolygons & shells,
|
||||||
const float closing_radius,
|
const Algorithm::RegionExpansionParameters &expansion_params_into_solid_infill,
|
||||||
const double bridge_angle
|
ExPolygons & sparse,
|
||||||
)
|
const Algorithm::RegionExpansionParameters &expansion_params_into_sparse_infill,
|
||||||
|
const float closing_radius,
|
||||||
|
const double bridge_angle )
|
||||||
{
|
{
|
||||||
using namespace Slic3r::Algorithm;
|
using namespace Slic3r::Algorithm;
|
||||||
|
|
||||||
double thickness;
|
double thickness;
|
||||||
ExPolygons src = fill_surfaces_extract_expolygons(surfaces, {surface_type}, thickness);
|
ExPolygons src = fill_surfaces_extract_expolygons(surfaces, {surface_type}, thickness);
|
||||||
if (src.empty())
|
if (src.empty())
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
unsigned processed_expolygons_count = 0;
|
//w36
|
||||||
std::vector<RegionExpansion> expansions;
|
|
||||||
for (ExpansionZone& expansion_zone : expansion_zones) {
|
|
||||||
std::vector<RegionExpansion> zone_expansions = propagate_waves(src, expansion_zone.expolygons, expansion_zone.parameters);
|
|
||||||
expansion_zone.expanded_into = !zone_expansions.empty();
|
|
||||||
|
|
||||||
for (RegionExpansion &expansion : zone_expansions)
|
std::vector<RegionExpansion> expansions = propagate_waves(src, shells, expansion_params_into_solid_infill);
|
||||||
expansion.boundary_id += processed_expolygons_count;
|
bool expanded_into_shells = !expansions.empty();
|
||||||
|
bool expanded_into_sparse = false;
|
||||||
processed_expolygons_count += expansion_zone.expolygons.size();
|
{
|
||||||
append(expansions, std::move(zone_expansions));
|
std::vector<RegionExpansion> expansions2 = propagate_waves(src, sparse, expansion_params_into_sparse_infill);
|
||||||
|
if (!expansions2.empty()) {
|
||||||
|
expanded_into_sparse = true;
|
||||||
|
for (RegionExpansion &expansion : expansions2)
|
||||||
|
expansion.boundary_id += uint32_t(shells.size());
|
||||||
|
append(expansions, std::move(expansions2));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<ExPolygon> expanded = merge_expansions_into_expolygons(std::move(src), std::move(expansions));
|
std::vector<ExPolygon> expanded = merge_expansions_into_expolygons(std::move(src), std::move(expansions));
|
||||||
//NOTE: The current regularization of the shells can create small unasigned regions in the object (E.G. benchy)
|
// NOTE: The current regularization of the shells can create small unasigned regions in the object (E.G. benchy)
|
||||||
// without the following closing operation, those regions will stay unfilled and cause small holes in the expanded surface.
|
// without the following closing operation, those regions will stay unfilled and cause small holes in the expanded surface.
|
||||||
// look for narrow_ensure_vertical_wall_thickness_region_radius filter.
|
// look for narrow_ensure_vertical_wall_thickness_region_radius filter.
|
||||||
expanded = closing_ex(expanded, closing_radius);
|
expanded = closing_ex(expanded, closing_radius);
|
||||||
// Trim the zones by the expanded expolygons.
|
// Trim the shells by the expanded expolygons.
|
||||||
for (ExpansionZone& expansion_zone : expansion_zones)
|
//w36
|
||||||
if (expansion_zone.expanded_into)
|
if (expanded_into_shells)
|
||||||
expansion_zone.expolygons = diff_ex(expansion_zone.expolygons, expanded);
|
shells = diff_ex(shells, expanded);
|
||||||
|
if (expanded_into_sparse)
|
||||||
|
sparse = diff_ex(sparse, expanded);
|
||||||
|
|
||||||
Surface templ{ surface_type, {} };
|
Surface templ{surface_type, {}};
|
||||||
templ.bridge_angle = bridge_angle;
|
templ.bridge_angle = bridge_angle;
|
||||||
Surfaces out;
|
Surfaces out;
|
||||||
out.reserve(expanded.size());
|
out.reserve(expanded.size());
|
||||||
@@ -516,52 +679,54 @@ void LayerRegion::process_external_surfaces(const Layer *lower_layer, const Poly
|
|||||||
#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
|
#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
|
||||||
|
|
||||||
// Width of the perimeters.
|
// Width of the perimeters.
|
||||||
float shell_width = 0;
|
float shell_width = 0;
|
||||||
float expansion_min = 0;
|
float expansion_min = 0;
|
||||||
if (int num_perimeters = this->region().config().perimeters; num_perimeters > 0) {
|
if (int num_perimeters = this->region().config().perimeters; num_perimeters > 0) {
|
||||||
Flow external_perimeter_flow = this->flow(frExternalPerimeter);
|
Flow external_perimeter_flow = this->flow(frExternalPerimeter);
|
||||||
Flow perimeter_flow = this->flow(frPerimeter);
|
Flow perimeter_flow = this->flow(frPerimeter);
|
||||||
shell_width = 0.5f * external_perimeter_flow.scaled_width() + external_perimeter_flow.scaled_spacing();
|
shell_width = 0.5f * external_perimeter_flow.scaled_width() + external_perimeter_flow.scaled_spacing();
|
||||||
shell_width += perimeter_flow.scaled_spacing() * (num_perimeters - 1);
|
shell_width += perimeter_flow.scaled_spacing() * (num_perimeters - 1);
|
||||||
expansion_min = perimeter_flow.scaled_spacing();
|
expansion_min = perimeter_flow.scaled_spacing();
|
||||||
} else {
|
} else {
|
||||||
// TODO: Maybe there is better solution when printing with zero perimeters, but this works reasonably well, given the situation
|
// TODO: Maybe there is better solution when printing with zero perimeters, but this works reasonably well, given the situation
|
||||||
shell_width = float(SCALED_EPSILON);
|
shell_width = float(SCALED_EPSILON);
|
||||||
expansion_min = float(SCALED_EPSILON);;
|
expansion_min = float(SCALED_EPSILON);
|
||||||
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scaled expansions of the respective external surfaces.
|
// Scaled expansions of the respective external surfaces.
|
||||||
float expansion_top = shell_width * sqrt(2.);
|
float expansion_top = shell_width * sqrt(2.);
|
||||||
float expansion_bottom = expansion_top;
|
float expansion_bottom = expansion_top;
|
||||||
float expansion_bottom_bridge = expansion_top;
|
float expansion_bottom_bridge = expansion_top;
|
||||||
// Expand by waves of expansion_step size (expansion_step is scaled), but with no more steps than max_nr_expansion_steps.
|
// Expand by waves of expansion_step size (expansion_step is scaled), but with no more steps than max_nr_expansion_steps.
|
||||||
static constexpr const float expansion_step = scaled<float>(0.1);
|
static constexpr const float expansion_step = scaled<float>(0.1);
|
||||||
// Don't take more than max_nr_steps for small expansion_step.
|
// Don't take more than max_nr_steps for small expansion_step.
|
||||||
static constexpr const size_t max_nr_expansion_steps = 5;
|
static constexpr const size_t max_nr_expansion_steps = 5;
|
||||||
// Radius (with added epsilon) to absorb empty regions emering from regularization of ensuring, viz const float narrow_ensure_vertical_wall_thickness_region_radius = 0.5f * 0.65f * min_perimeter_infill_spacing;
|
// Radius (with added epsilon) to absorb empty regions emering from regularization of ensuring, viz const float
|
||||||
|
// narrow_ensure_vertical_wall_thickness_region_radius = 0.5f * 0.65f * min_perimeter_infill_spacing;
|
||||||
const float closing_radius = 0.55f * 0.65f * 1.05f * this->flow(frSolidInfill).scaled_spacing();
|
const float closing_radius = 0.55f * 0.65f * 1.05f * this->flow(frSolidInfill).scaled_spacing();
|
||||||
|
|
||||||
// Expand the top / bottom / bridge surfaces into the shell thickness solid infills.
|
// Expand the top / bottom / bridge surfaces into the shell thickness solid infills.
|
||||||
double layer_thickness;
|
double layer_thickness;
|
||||||
ExPolygons shells = union_ex(fill_surfaces_extract_expolygons(m_fill_surfaces.surfaces, { stInternalSolid }, layer_thickness));
|
//w36
|
||||||
ExPolygons sparse = union_ex(fill_surfaces_extract_expolygons(m_fill_surfaces.surfaces, { stInternal }, layer_thickness));
|
ExPolygons shells = union_ex(fill_surfaces_extract_expolygons(m_fill_surfaces.surfaces, {stInternalSolid}, layer_thickness));
|
||||||
ExPolygons top_expolygons = union_ex(fill_surfaces_extract_expolygons(m_fill_surfaces.surfaces, { stTop }, layer_thickness));
|
ExPolygons sparse = union_ex(fill_surfaces_extract_expolygons(m_fill_surfaces.surfaces, {stInternal}, layer_thickness));
|
||||||
const auto expansion_params_into_sparse_infill = RegionExpansionParameters::build(expansion_min, expansion_step, max_nr_expansion_steps);
|
|
||||||
const auto expansion_params_into_solid_infill = RegionExpansionParameters::build(expansion_bottom_bridge, expansion_step, max_nr_expansion_steps);
|
|
||||||
|
|
||||||
std::vector<ExpansionZone> expansion_zones{
|
|
||||||
ExpansionZone{std::move(shells), expansion_params_into_solid_infill},
|
|
||||||
ExpansionZone{std::move(sparse), expansion_params_into_sparse_infill},
|
|
||||||
ExpansionZone{std::move(top_expolygons), expansion_params_into_solid_infill},
|
|
||||||
};
|
|
||||||
|
|
||||||
SurfaceCollection bridges;
|
SurfaceCollection bridges;
|
||||||
|
//w36
|
||||||
|
const auto expansion_params_into_sparse_infill = RegionExpansionParameters::build(expansion_min, expansion_step, max_nr_expansion_steps);
|
||||||
{
|
{
|
||||||
BOOST_LOG_TRIVIAL(trace) << "Processing external surface, detecting bridges. layer" << this->layer()->print_z;
|
BOOST_LOG_TRIVIAL(trace) << "Processing external surface, detecting bridges. layer" << this->layer()->print_z;
|
||||||
const double custom_angle = this->region().config().bridge_angle.value;
|
//w36
|
||||||
bridges.surfaces = custom_angle > 0 ?
|
const double custom_angle = this->region().config().bridge_angle.value;
|
||||||
expand_merge_surfaces(m_fill_surfaces.surfaces, stBottomBridge, expansion_zones, closing_radius, Geometry::deg2rad(custom_angle)) :
|
const auto expansion_params_into_solid_infill = RegionExpansionParameters::build(expansion_bottom_bridge, expansion_step,
|
||||||
expand_bridges_detect_orientations(m_fill_surfaces.surfaces, expansion_zones, closing_radius);
|
max_nr_expansion_steps);
|
||||||
|
bridges.surfaces = custom_angle > 0 ?
|
||||||
|
expand_merge_surfaces(m_fill_surfaces.surfaces, stBottomBridge, shells, expansion_params_into_solid_infill,
|
||||||
|
sparse, expansion_params_into_sparse_infill, closing_radius,
|
||||||
|
Geometry::deg2rad(custom_angle)) :
|
||||||
|
expand_bridges_detect_orientations(m_fill_surfaces.surfaces, shells, expansion_params_into_solid_infill,
|
||||||
|
sparse, expansion_params_into_sparse_infill, closing_radius);
|
||||||
BOOST_LOG_TRIVIAL(trace) << "Processing external surface, detecting bridges - done";
|
BOOST_LOG_TRIVIAL(trace) << "Processing external surface, detecting bridges - done";
|
||||||
#if 0
|
#if 0
|
||||||
{
|
{
|
||||||
@@ -570,37 +735,30 @@ void LayerRegion::process_external_surfaces(const Layer *lower_layer, const Poly
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
//w36
|
||||||
|
|
||||||
m_fill_surfaces.remove_types({ stTop });
|
Surfaces bottoms = expand_merge_surfaces(m_fill_surfaces.surfaces, stBottom, shells,
|
||||||
{
|
RegionExpansionParameters::build(expansion_bottom, expansion_step, max_nr_expansion_steps),
|
||||||
Surface top_templ(stTop, {});
|
sparse, expansion_params_into_sparse_infill, closing_radius);
|
||||||
top_templ.thickness = layer_thickness;
|
Surfaces tops = expand_merge_surfaces(m_fill_surfaces.surfaces, stTop, shells,
|
||||||
m_fill_surfaces.append(std::move(expansion_zones.back().expolygons), top_templ);
|
RegionExpansionParameters::build(expansion_top, expansion_step, max_nr_expansion_steps), sparse,
|
||||||
}
|
expansion_params_into_sparse_infill, closing_radius);
|
||||||
|
|
||||||
expansion_zones.pop_back();
|
// m_fill_surfaces.remove_types({ stBottomBridge, stBottom, stTop, stInternal, stInternalSolid });
|
||||||
|
|
||||||
expansion_zones.at(0).parameters = RegionExpansionParameters::build(expansion_bottom, expansion_step, max_nr_expansion_steps);
|
|
||||||
Surfaces bottoms = expand_merge_surfaces(m_fill_surfaces.surfaces, stBottom, expansion_zones, closing_radius);
|
|
||||||
|
|
||||||
expansion_zones.at(0).parameters = RegionExpansionParameters::build(expansion_top, expansion_step, max_nr_expansion_steps);
|
|
||||||
Surfaces tops = expand_merge_surfaces(m_fill_surfaces.surfaces, stTop, expansion_zones, closing_radius);
|
|
||||||
|
|
||||||
// m_fill_surfaces.remove_types({ stBottomBridge, stBottom, stTop, stInternal, stInternalSolid });
|
|
||||||
m_fill_surfaces.clear();
|
m_fill_surfaces.clear();
|
||||||
unsigned zones_expolygons_count = 0;
|
//w36
|
||||||
for (const ExpansionZone& zone : expansion_zones)
|
reserve_more(m_fill_surfaces.surfaces, shells.size() + sparse.size() + bridges.size() + bottoms.size() + tops.size());
|
||||||
zones_expolygons_count += zone.expolygons.size();
|
|
||||||
reserve_more(m_fill_surfaces.surfaces, zones_expolygons_count + bridges.size() + bottoms.size() + tops.size());
|
|
||||||
{
|
{
|
||||||
Surface solid_templ(stInternalSolid, {});
|
Surface solid_templ(stInternalSolid, {});
|
||||||
solid_templ.thickness = layer_thickness;
|
solid_templ.thickness = layer_thickness;
|
||||||
m_fill_surfaces.append(std::move(expansion_zones[0].expolygons), solid_templ);
|
//w36
|
||||||
|
m_fill_surfaces.append(std::move(shells), solid_templ);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
Surface sparse_templ(stInternal, {});
|
Surface sparse_templ(stInternal, {});
|
||||||
sparse_templ.thickness = layer_thickness;
|
sparse_templ.thickness = layer_thickness;
|
||||||
m_fill_surfaces.append(std::move(expansion_zones[1].expolygons), sparse_templ);
|
//w36
|
||||||
|
m_fill_surfaces.append(std::move(sparse), sparse_templ);
|
||||||
}
|
}
|
||||||
m_fill_surfaces.append(std::move(bridges.surfaces));
|
m_fill_surfaces.append(std::move(bridges.surfaces));
|
||||||
m_fill_surfaces.append(std::move(bottoms));
|
m_fill_surfaces.append(std::move(bottoms));
|
||||||
|
|||||||
@@ -205,23 +205,44 @@ struct ExpansionZone {
|
|||||||
* detect bridges.
|
* detect bridges.
|
||||||
* Trim "shells" by the expanded bridges.
|
* Trim "shells" by the expanded bridges.
|
||||||
*/
|
*/
|
||||||
Surfaces expand_bridges_detect_orientations(
|
// w36
|
||||||
|
/* Surfaces expand_bridges_detect_orientations(
|
||||||
Surfaces &surfaces,
|
Surfaces &surfaces,
|
||||||
std::vector<ExpansionZone>& expansion_zones,
|
std::vector<ExpansionZone>& expansion_zones,
|
||||||
const float closing_radius
|
const float closing_radius
|
||||||
);
|
);*/
|
||||||
|
|
||||||
|
//w36
|
||||||
|
Surfaces expand_bridges_detect_orientations(Surfaces & surfaces,
|
||||||
|
ExPolygons & shells,
|
||||||
|
const Algorithm::RegionExpansionParameters &expansion_params_into_solid_infill,
|
||||||
|
ExPolygons & sparse,
|
||||||
|
const Algorithm::RegionExpansionParameters &expansion_params_into_sparse_infill,
|
||||||
|
const float closing_radius);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract bridging surfaces from "surfaces", expand them into "shells" using expansion_params.
|
* Extract bridging surfaces from "surfaces", expand them into "shells" using expansion_params.
|
||||||
* Trim "shells" by the expanded bridges.
|
* Trim "shells" by the expanded bridges.
|
||||||
*/
|
*/
|
||||||
Surfaces expand_merge_surfaces(
|
|
||||||
|
// w36
|
||||||
|
/* Surfaces expand_merge_surfaces(
|
||||||
Surfaces &surfaces,
|
Surfaces &surfaces,
|
||||||
SurfaceType surface_type,
|
SurfaceType surface_type,
|
||||||
std::vector<ExpansionZone>& expansion_zones,
|
std::vector<ExpansionZone>& expansion_zones,
|
||||||
const float closing_radius,
|
const float closing_radius,
|
||||||
const double bridge_angle = -1
|
const double bridge_angle = -1
|
||||||
);
|
);*/
|
||||||
|
|
||||||
|
// w36
|
||||||
|
Surfaces expand_merge_surfaces(Surfaces & surfaces,
|
||||||
|
SurfaceType surface_type,
|
||||||
|
ExPolygons & shells,
|
||||||
|
const Algorithm::RegionExpansionParameters &expansion_params_into_solid_infill,
|
||||||
|
ExPolygons & sparse,
|
||||||
|
const Algorithm::RegionExpansionParameters &expansion_params_into_sparse_infill,
|
||||||
|
const float closing_radius,
|
||||||
|
const double bridge_angle = -1.);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -888,6 +888,16 @@ const BoundingBoxf3& ModelObject::bounding_box_approx() const
|
|||||||
return m_bounding_box_approx;
|
return m_bounding_box_approx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// B66
|
||||||
|
Polygon ModelInstance::convex_hull_2d()
|
||||||
|
{
|
||||||
|
Polygon convex_hull;
|
||||||
|
{
|
||||||
|
const Transform3d &trafo_instance = get_matrix();
|
||||||
|
convex_hull = get_object()->convex_hull_2d(trafo_instance);
|
||||||
|
}
|
||||||
|
return convex_hull;
|
||||||
|
}
|
||||||
// Returns the bounding box of the transformed instances.
|
// Returns the bounding box of the transformed instances.
|
||||||
// This bounding box is approximate and not snug.
|
// This bounding box is approximate and not snug.
|
||||||
const BoundingBoxf3& ModelObject::bounding_box_exact() const
|
const BoundingBoxf3& ModelObject::bounding_box_exact() const
|
||||||
|
|||||||
@@ -1158,6 +1158,8 @@ public:
|
|||||||
const Transform3d& get_matrix() const { return m_transformation.get_matrix(); }
|
const Transform3d& get_matrix() const { return m_transformation.get_matrix(); }
|
||||||
Transform3d get_matrix_no_offset() const { return m_transformation.get_matrix_no_offset(); }
|
Transform3d get_matrix_no_offset() const { return m_transformation.get_matrix_no_offset(); }
|
||||||
|
|
||||||
|
// B66
|
||||||
|
Polygon convex_hull_2d();
|
||||||
bool is_printable() const { return object->printable && printable && (print_volume_state == ModelInstancePVS_Inside); }
|
bool is_printable() const { return object->printable && printable && (print_volume_state == ModelInstancePVS_Inside); }
|
||||||
|
|
||||||
void invalidate_object_bounding_box() { object->invalidate_bounding_box(); }
|
void invalidate_object_bounding_box() { object->invalidate_bounding_box(); }
|
||||||
|
|||||||
@@ -285,12 +285,62 @@ static void fuzzy_extrusion_line(Arachne::ExtrusionLine &ext_lines, double fuzzy
|
|||||||
|
|
||||||
using PerimeterGeneratorLoops = std::vector<PerimeterGeneratorLoop>;
|
using PerimeterGeneratorLoops = std::vector<PerimeterGeneratorLoop>;
|
||||||
|
|
||||||
static ExtrusionEntityCollection traverse_loops_classic(const PerimeterGenerator::Parameters ¶ms, const Polygons &lower_slices_polygons_cache, const PerimeterGeneratorLoops &loops, ThickPolylines &thin_walls)
|
//w38
|
||||||
|
template<class _T>
|
||||||
|
static bool detect_steep_overhang(const PrintRegionConfig &config,
|
||||||
|
bool is_contour,
|
||||||
|
const BoundingBox & extrusion_bboxs,
|
||||||
|
double extrusion_width,
|
||||||
|
const _T extrusion,
|
||||||
|
const ExPolygons * lower_slices,
|
||||||
|
bool & steep_overhang_contour,
|
||||||
|
bool & steep_overhang_hole)
|
||||||
|
{
|
||||||
|
double threshold = config.overhang_reverse_threshold.get_abs_value(extrusion_width);
|
||||||
|
// Special case: reverse on every odd layer
|
||||||
|
if (threshold < EPSILON) {
|
||||||
|
if (is_contour) {
|
||||||
|
steep_overhang_contour = true;
|
||||||
|
} else {
|
||||||
|
steep_overhang_hole = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Polygons lower_slcier_chopped = ClipperUtils::clip_clipper_polygons_with_subject_bbox(*lower_slices, extrusion_bboxs,true);
|
||||||
|
|
||||||
|
// All we need to check is whether we have lines outside `threshold`
|
||||||
|
double off = threshold - 0.5 * extrusion_width;
|
||||||
|
|
||||||
|
auto limiton_polygons = offset(lower_slcier_chopped, float(scale_(off)));
|
||||||
|
|
||||||
|
auto remain_polylines = diff_pl(extrusion, limiton_polygons);
|
||||||
|
if (!remain_polylines.empty()) {
|
||||||
|
if (is_contour) {
|
||||||
|
steep_overhang_contour = true;
|
||||||
|
} else {
|
||||||
|
steep_overhang_hole = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//w38
|
||||||
|
static ExtrusionEntityCollection traverse_loops_classic(const PerimeterGenerator::Parameters ¶ms, const Polygons &lower_slices_polygons_cache, const PerimeterGeneratorLoops &loops, ThickPolylines &thin_walls,
|
||||||
|
bool & steep_overhang_contour,
|
||||||
|
bool & steep_overhang_hole)
|
||||||
{
|
{
|
||||||
// loops is an arrayref of ::Loop objects
|
// loops is an arrayref of ::Loop objects
|
||||||
// turn each one into an ExtrusionLoop object
|
// turn each one into an ExtrusionLoop object
|
||||||
ExtrusionEntityCollection coll;
|
ExtrusionEntityCollection coll;
|
||||||
Polygon fuzzified;
|
Polygon fuzzified;
|
||||||
|
//w38
|
||||||
|
bool overhangs_reverse = params.config.overhang_reverse &&
|
||||||
|
params.layer_id % 2 == 1;
|
||||||
for (const PerimeterGeneratorLoop &loop : loops) {
|
for (const PerimeterGeneratorLoop &loop : loops) {
|
||||||
bool is_external = loop.is_external();
|
bool is_external = loop.is_external();
|
||||||
|
|
||||||
@@ -301,13 +351,24 @@ static ExtrusionEntityCollection traverse_loops_classic(const PerimeterGenerator
|
|||||||
// Note that we set loop role to ContourInternalPerimeter
|
// Note that we set loop role to ContourInternalPerimeter
|
||||||
// also when loop is both internal and external (i.e.
|
// also when loop is both internal and external (i.e.
|
||||||
// there's only one contour loop).
|
// there's only one contour loop).
|
||||||
loop_role = elrContourInternalPerimeter;
|
//w38
|
||||||
|
loop_role = elrInternal;//loop_role = elrContourInternalPerimeter;
|
||||||
} else {
|
} else {
|
||||||
loop_role = elrDefault;
|
//w38
|
||||||
|
loop_role = loop.is_contour? elrDefault : elrHole;//loop_role = elrDefault;
|
||||||
}
|
}
|
||||||
|
|
||||||
// detect overhanging/bridging perimeters
|
// detect overhanging/bridging perimeters
|
||||||
ExtrusionPaths paths;
|
ExtrusionPaths paths;
|
||||||
|
//w38
|
||||||
|
double extrusion_width;
|
||||||
|
if (is_external) {
|
||||||
|
|
||||||
|
extrusion_width = params.ext_perimeter_flow.width();
|
||||||
|
} else {
|
||||||
|
extrusion_width = params.perimeter_flow.width();
|
||||||
|
}
|
||||||
|
|
||||||
const Polygon &polygon = loop.fuzzify ? fuzzified : loop.polygon;
|
const Polygon &polygon = loop.fuzzify ? fuzzified : loop.polygon;
|
||||||
if (loop.fuzzify) {
|
if (loop.fuzzify) {
|
||||||
fuzzified = loop.polygon;
|
fuzzified = loop.polygon;
|
||||||
@@ -318,6 +379,19 @@ static ExtrusionEntityCollection traverse_loops_classic(const PerimeterGenerator
|
|||||||
params.object_config.support_material_contact_distance.value == 0)) {
|
params.object_config.support_material_contact_distance.value == 0)) {
|
||||||
BoundingBox bbox(polygon.points);
|
BoundingBox bbox(polygon.points);
|
||||||
bbox.offset(SCALED_EPSILON);
|
bbox.offset(SCALED_EPSILON);
|
||||||
|
//w38
|
||||||
|
if (overhangs_reverse && params.config.fuzzy_skin != FuzzySkinType::None) {
|
||||||
|
if (loop.is_contour) {
|
||||||
|
steep_overhang_contour = true;
|
||||||
|
} else if (params.config.fuzzy_skin != FuzzySkinType::External) {
|
||||||
|
steep_overhang_hole = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool found_steep_overhang = (loop.is_contour && steep_overhang_contour) || (!loop.is_contour && steep_overhang_hole);
|
||||||
|
if (overhangs_reverse && !found_steep_overhang) {
|
||||||
|
detect_steep_overhang(params.config, loop.is_contour, bbox, extrusion_width, Polygons{polygon},
|
||||||
|
params.lower_slices, steep_overhang_contour, steep_overhang_hole);
|
||||||
|
}
|
||||||
Polygons lower_slices_polygons_clipped = ClipperUtils::clip_clipper_polygons_with_subject_bbox(lower_slices_polygons_cache, bbox);
|
Polygons lower_slices_polygons_clipped = ClipperUtils::clip_clipper_polygons_with_subject_bbox(lower_slices_polygons_cache, bbox);
|
||||||
// get non-overhang paths by intersecting this loop with the grown lower slices
|
// get non-overhang paths by intersecting this loop with the grown lower slices
|
||||||
extrusion_paths_append(
|
extrusion_paths_append(
|
||||||
@@ -381,10 +455,13 @@ static ExtrusionEntityCollection traverse_loops_classic(const PerimeterGenerator
|
|||||||
} else {
|
} else {
|
||||||
const PerimeterGeneratorLoop &loop = loops[idx.first];
|
const PerimeterGeneratorLoop &loop = loops[idx.first];
|
||||||
assert(thin_walls.empty());
|
assert(thin_walls.empty());
|
||||||
ExtrusionEntityCollection children = traverse_loops_classic(params, lower_slices_polygons_cache, loop.children, thin_walls);
|
//w38
|
||||||
|
ExtrusionEntityCollection children = traverse_loops_classic(params, lower_slices_polygons_cache, loop.children, thin_walls,steep_overhang_contour, steep_overhang_hole);
|
||||||
out.entities.reserve(out.entities.size() + children.entities.size() + 1);
|
out.entities.reserve(out.entities.size() + children.entities.size() + 1);
|
||||||
ExtrusionLoop *eloop = static_cast<ExtrusionLoop*>(coll.entities[idx.first]);
|
ExtrusionLoop *eloop = static_cast<ExtrusionLoop*>(coll.entities[idx.first]);
|
||||||
coll.entities[idx.first] = nullptr;
|
coll.entities[idx.first] = nullptr;
|
||||||
|
//w38
|
||||||
|
//eloop->make_counter_clockwise();
|
||||||
if (loop.is_contour) {
|
if (loop.is_contour) {
|
||||||
if (eloop->is_clockwise())
|
if (eloop->is_clockwise())
|
||||||
eloop->reverse_loop();
|
eloop->reverse_loop();
|
||||||
@@ -505,8 +582,16 @@ struct PerimeterGeneratorArachneExtrusion
|
|||||||
bool fuzzify = false;
|
bool fuzzify = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
static ExtrusionEntityCollection traverse_extrusions(const PerimeterGenerator::Parameters ¶ms, const Polygons &lower_slices_polygons_cache, std::vector<PerimeterGeneratorArachneExtrusion> &pg_extrusions)
|
//w38
|
||||||
|
static ExtrusionEntityCollection traverse_extrusions(const PerimeterGenerator::Parameters & params,
|
||||||
|
const Polygons & lower_slices_polygons_cache,
|
||||||
|
std::vector<PerimeterGeneratorArachneExtrusion> &pg_extrusions,
|
||||||
|
bool & steep_overhang_contour,
|
||||||
|
bool & steep_overhang_hole)
|
||||||
{
|
{
|
||||||
|
//w38
|
||||||
|
bool overhangs_reverse = params.config.overhang_reverse &&
|
||||||
|
params.layer_id % 2 == 1;
|
||||||
ExtrusionEntityCollection extrusion_coll;
|
ExtrusionEntityCollection extrusion_coll;
|
||||||
for (PerimeterGeneratorArachneExtrusion &pg_extrusion : pg_extrusions) {
|
for (PerimeterGeneratorArachneExtrusion &pg_extrusion : pg_extrusions) {
|
||||||
Arachne::ExtrusionLine *extrusion = pg_extrusion.extrusion;
|
Arachne::ExtrusionLine *extrusion = pg_extrusion.extrusion;
|
||||||
@@ -556,6 +641,40 @@ static ExtrusionEntityCollection traverse_extrusions(const PerimeterGenerator::P
|
|||||||
extrusion_paths_append(paths, clip_extrusion(extrusion_path, lower_slices_paths, ClipperLib_Z::ctIntersection), role_normal,
|
extrusion_paths_append(paths, clip_extrusion(extrusion_path, lower_slices_paths, ClipperLib_Z::ctIntersection), role_normal,
|
||||||
is_external ? params.ext_perimeter_flow : params.perimeter_flow);
|
is_external ? params.ext_perimeter_flow : params.perimeter_flow);
|
||||||
|
|
||||||
|
//w38
|
||||||
|
if (overhangs_reverse && params.config.fuzzy_skin != FuzzySkinType::None) {
|
||||||
|
if (pg_extrusion.is_contour) {
|
||||||
|
steep_overhang_contour = true;
|
||||||
|
} else if (params.config.fuzzy_skin != FuzzySkinType::External) {
|
||||||
|
steep_overhang_hole = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool found_steep_overhang = (pg_extrusion.is_contour && steep_overhang_contour) ||
|
||||||
|
(!pg_extrusion.is_contour && steep_overhang_hole);
|
||||||
|
if (overhangs_reverse && !found_steep_overhang) {
|
||||||
|
std::map<double, ExtrusionPaths> recognization_paths;
|
||||||
|
for (const ExtrusionPath &path : paths) {
|
||||||
|
if (recognization_paths.count(path.width()))
|
||||||
|
recognization_paths[path.width()].emplace_back(std::move(path));
|
||||||
|
else
|
||||||
|
recognization_paths.insert(std::pair<double, ExtrusionPaths>(path.width(), {std::move(path)}));
|
||||||
|
}
|
||||||
|
for (const auto &it : recognization_paths) {
|
||||||
|
Polylines be_clipped;
|
||||||
|
|
||||||
|
for (const ExtrusionPath &p : it.second) {
|
||||||
|
be_clipped.emplace_back(std::move(p.polyline));
|
||||||
|
}
|
||||||
|
|
||||||
|
BoundingBox extrusion_bboxs = get_extents(be_clipped);
|
||||||
|
|
||||||
|
if (detect_steep_overhang(params.config, pg_extrusion.is_contour, extrusion_bboxs, it.first, be_clipped,
|
||||||
|
params.lower_slices, steep_overhang_contour, steep_overhang_hole)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// get overhang paths by checking what parts of this loop fall
|
// get overhang paths by checking what parts of this loop fall
|
||||||
// outside the grown lower slices (thus where the distance between
|
// outside the grown lower slices (thus where the distance between
|
||||||
// the loop centerline and original lower slices is >= half nozzle diameter
|
// the loop centerline and original lower slices is >= half nozzle diameter
|
||||||
@@ -571,6 +690,9 @@ static ExtrusionEntityCollection traverse_extrusions(const PerimeterGenerator::P
|
|||||||
// Especially for open extrusion, we need to select a starting point that is at the start
|
// Especially for open extrusion, we need to select a starting point that is at the start
|
||||||
// or the end of the extrusions to make one continuous line. Also, we prefer a non-overhang
|
// or the end of the extrusions to make one continuous line. Also, we prefer a non-overhang
|
||||||
// starting point.
|
// starting point.
|
||||||
|
//w38
|
||||||
|
//ExtrusionLoop extrusion_loop(std::move(paths), pg_extrusion.is_contour ? elrDefault : elrHole);
|
||||||
|
//extrusion_loop.make_counter_clockwise();
|
||||||
struct PointInfo
|
struct PointInfo
|
||||||
{
|
{
|
||||||
size_t occurrence = 0;
|
size_t occurrence = 0;
|
||||||
@@ -1105,6 +1227,33 @@ void PerimeterGenerator::add_infill_contour_for_arachne(ExPolygons infill_contou
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//w38
|
||||||
|
static void reorient_perimeters(ExtrusionEntityCollection &entities, bool steep_overhang_contour, bool steep_overhang_hole, bool reverse_internal_only)
|
||||||
|
{
|
||||||
|
if (steep_overhang_hole || steep_overhang_contour) {
|
||||||
|
for (auto entity : entities) {
|
||||||
|
if (entity->is_loop()) {
|
||||||
|
ExtrusionLoop *eloop = static_cast<ExtrusionLoop *>(entity);
|
||||||
|
bool need_reverse = ((eloop->loop_role() & elrHole) == elrHole) ? steep_overhang_hole : steep_overhang_contour;
|
||||||
|
bool isExternal = false;
|
||||||
|
if (reverse_internal_only) {
|
||||||
|
for (auto path : eloop->paths) {
|
||||||
|
if (path.role().is_external_perimeter()) {
|
||||||
|
isExternal = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (need_reverse && !isExternal) {
|
||||||
|
eloop->make_clockwise();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Thanks, Cura developers, for implementing an algorithm for generating perimeters with variable width (Arachne) that is based on the paper
|
// Thanks, Cura developers, for implementing an algorithm for generating perimeters with variable width (Arachne) that is based on the paper
|
||||||
// "A framework for adaptive width control of dense contour-parallel toolpaths in fused deposition modeling"
|
// "A framework for adaptive width control of dense contour-parallel toolpaths in fused deposition modeling"
|
||||||
void PerimeterGenerator::process_arachne(
|
void PerimeterGenerator::process_arachne(
|
||||||
@@ -1123,7 +1272,9 @@ void PerimeterGenerator::process_arachne(
|
|||||||
// Infills without the gap fills
|
// Infills without the gap fills
|
||||||
ExPolygons &out_fill_expolygons,
|
ExPolygons &out_fill_expolygons,
|
||||||
//w21
|
//w21
|
||||||
ExPolygons &out_fill_no_overlap)
|
ExPolygons &out_fill_no_overlap,
|
||||||
|
//w23
|
||||||
|
const size_t layer_id)
|
||||||
{
|
{
|
||||||
// other perimeters
|
// other perimeters
|
||||||
coord_t perimeter_spacing = params.perimeter_flow.scaled_spacing();
|
coord_t perimeter_spacing = params.perimeter_flow.scaled_spacing();
|
||||||
@@ -1147,14 +1298,27 @@ void PerimeterGenerator::process_arachne(
|
|||||||
// extra perimeters for each one
|
// extra perimeters for each one
|
||||||
// detect how many perimeters must be generated for this island
|
// detect how many perimeters must be generated for this island
|
||||||
int loop_number = params.config.perimeters + surface.extra_perimeters - 1; // 0-indexed loops
|
int loop_number = params.config.perimeters + surface.extra_perimeters - 1; // 0-indexed loops
|
||||||
ExPolygons last = offset_ex(surface.expolygon.simplify_p(params.scaled_resolution), - float(ext_perimeter_width / 2. - ext_perimeter_spacing / 2.));
|
//w39
|
||||||
|
//ExPolygons last = offset_ex(surface.expolygon.simplify_p(params.scaled_resolution), - float(ext_perimeter_width / 2. - ext_perimeter_spacing / 2.));
|
||||||
|
double surface_simplify_resolution = (params.print_config.arc_fitting != ArcFittingType::Disabled &&
|
||||||
|
params.config.fuzzy_skin == FuzzySkinType::None) ?
|
||||||
|
0.2 * scale_(params.print_config.resolution) :
|
||||||
|
params.print_config.resolution;
|
||||||
|
auto apply_precise_outer_wall = params.config.precise_outer_wall && !params.config.external_perimeters_first;
|
||||||
|
ExPolygons last = apply_precise_outer_wall? offset_ex(surface.expolygon.simplify_p(surface_simplify_resolution),
|
||||||
|
-float(ext_perimeter_width - ext_perimeter_spacing) ) :offset_ex(surface.expolygon.simplify_p(params.scaled_resolution),
|
||||||
|
-float(ext_perimeter_width / 2. - ext_perimeter_spacing / 2.));
|
||||||
|
coord_t wall_0_inset = 0;
|
||||||
|
if (apply_precise_outer_wall)
|
||||||
|
wall_0_inset = -coord_t(ext_perimeter_width / 2 - ext_perimeter_spacing / 2);
|
||||||
Polygons last_p = to_polygons(last);
|
Polygons last_p = to_polygons(last);
|
||||||
|
|
||||||
//w16
|
//w16
|
||||||
if (upper_slices == nullptr && params.object_config.top_one_wall_type == TopOneWallType::Onlytopmost)
|
//w23
|
||||||
|
if ((upper_slices == nullptr && params.object_config.top_one_wall_type == TopOneWallType::Onlytopmost)||(params.object_config.only_one_wall_first_layer && layer_id == 0))
|
||||||
loop_number = 0;
|
loop_number = 0;
|
||||||
|
//w39
|
||||||
Arachne::WallToolPaths wallToolPaths(last_p, ext_perimeter_spacing, perimeter_spacing, coord_t(loop_number + 1), 0, params.layer_height, params.object_config, params.print_config);
|
Arachne::WallToolPaths wallToolPaths(last_p, ext_perimeter_spacing, perimeter_spacing, coord_t(loop_number + 1), wall_0_inset, params.layer_height, params.object_config, params.print_config);
|
||||||
std::vector<Arachne::VariableWidthLines> perimeters = wallToolPaths.getToolPaths();
|
std::vector<Arachne::VariableWidthLines> perimeters = wallToolPaths.getToolPaths();
|
||||||
loop_number = int(perimeters.size()) - 1;
|
loop_number = int(perimeters.size()) - 1;
|
||||||
|
|
||||||
@@ -1305,8 +1469,15 @@ void PerimeterGenerator::process_arachne(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ExtrusionEntityCollection extrusion_coll = traverse_extrusions(params, lower_slices_polygons_cache, ordered_extrusions); !extrusion_coll.empty())
|
//w38
|
||||||
|
bool steep_overhang_contour = false;
|
||||||
|
bool steep_overhang_hole = false;
|
||||||
|
if (ExtrusionEntityCollection extrusion_coll = traverse_extrusions(params, lower_slices_polygons_cache, ordered_extrusions,
|
||||||
|
steep_overhang_contour, steep_overhang_hole);
|
||||||
|
!extrusion_coll.empty()) {
|
||||||
|
reorient_perimeters(extrusion_coll, steep_overhang_contour, steep_overhang_hole, params.config.overhang_reverse_internal_only);
|
||||||
out_loops.append(extrusion_coll);
|
out_loops.append(extrusion_coll);
|
||||||
|
}
|
||||||
|
|
||||||
ExPolygons infill_contour = union_ex(wallToolPaths.getInnerContour());
|
ExPolygons infill_contour = union_ex(wallToolPaths.getInnerContour());
|
||||||
//w17
|
//w17
|
||||||
@@ -1388,9 +1559,11 @@ void PerimeterGenerator::process_with_one_wall_arachne(
|
|||||||
// Gaps without the thin walls
|
// Gaps without the thin walls
|
||||||
ExtrusionEntityCollection & /* out_gap_fill */,
|
ExtrusionEntityCollection & /* out_gap_fill */,
|
||||||
// Infills without the gap fills
|
// Infills without the gap fills
|
||||||
ExPolygons &out_fill_expolygons,
|
ExPolygons &out_fill_expolygons,
|
||||||
//w21
|
//w21
|
||||||
ExPolygons &out_fill_no_overlap)
|
ExPolygons &out_fill_no_overlap,
|
||||||
|
//w23
|
||||||
|
const size_t layer_id)
|
||||||
{
|
{
|
||||||
// other perimeters
|
// other perimeters
|
||||||
coord_t perimeter_spacing = params.perimeter_flow.scaled_spacing();
|
coord_t perimeter_spacing = params.perimeter_flow.scaled_spacing();
|
||||||
@@ -1409,7 +1582,7 @@ void PerimeterGenerator::process_with_one_wall_arachne(
|
|||||||
double nozzle_diameter = params.print_config.nozzle_diameter.get_at(params.config.perimeter_extruder-1);
|
double nozzle_diameter = params.print_config.nozzle_diameter.get_at(params.config.perimeter_extruder-1);
|
||||||
lower_slices_polygons_cache = offset(*lower_slices, float(scale_(+nozzle_diameter/2)));
|
lower_slices_polygons_cache = offset(*lower_slices, float(scale_(+nozzle_diameter/2)));
|
||||||
}
|
}
|
||||||
if (params.config.overhangs && upper_slices != nullptr && upper_slices_polygons_cache.empty()) {
|
if ( upper_slices != nullptr && upper_slices_polygons_cache.empty()) {
|
||||||
double upper_nozzle_diameter = params.print_config.nozzle_diameter.get_at(params.config.perimeter_extruder - 1);
|
double upper_nozzle_diameter = params.print_config.nozzle_diameter.get_at(params.config.perimeter_extruder - 1);
|
||||||
upper_slices_polygons_cache = offset(*upper_slices, float(scale_(EPSILON)));
|
upper_slices_polygons_cache = offset(*upper_slices, float(scale_(EPSILON)));
|
||||||
}
|
}
|
||||||
@@ -1419,7 +1592,23 @@ void PerimeterGenerator::process_with_one_wall_arachne(
|
|||||||
// extra perimeters for each one
|
// extra perimeters for each one
|
||||||
// detect how many perimeters must be generated for this island
|
// detect how many perimeters must be generated for this island
|
||||||
int loop_number = params.config.perimeters + surface.extra_perimeters - 1; // 0-indexed loops
|
int loop_number = params.config.perimeters + surface.extra_perimeters - 1; // 0-indexed loops
|
||||||
ExPolygons last = offset_ex(surface.expolygon.simplify_p(params.scaled_resolution), - float(ext_perimeter_width / 2. - ext_perimeter_spacing / 2.));
|
//w23
|
||||||
|
if (params.object_config.only_one_wall_first_layer && layer_id == 0)
|
||||||
|
loop_number = 0;
|
||||||
|
//w39
|
||||||
|
//ExPolygons last = offset_ex(surface.expolygon.simplify_p(params.scaled_resolution), - float(ext_perimeter_width / 2. - ext_perimeter_spacing / 2.));
|
||||||
|
double surface_simplify_resolution = (params.print_config.arc_fitting != ArcFittingType::Disabled &&
|
||||||
|
params.config.fuzzy_skin == FuzzySkinType::None) ?
|
||||||
|
0.2 * scale_(params.print_config.resolution) :
|
||||||
|
params.print_config.resolution;
|
||||||
|
auto apply_precise_outer_wall = params.config.precise_outer_wall && !params.config.external_perimeters_first;
|
||||||
|
ExPolygons last = apply_precise_outer_wall ? offset_ex(surface.expolygon.simplify_p(surface_simplify_resolution),
|
||||||
|
-float(ext_perimeter_width - ext_perimeter_spacing)) :
|
||||||
|
offset_ex(surface.expolygon.simplify_p(params.scaled_resolution),
|
||||||
|
-float(ext_perimeter_width / 2. - ext_perimeter_spacing / 2.));
|
||||||
|
coord_t wall_0_inset = 0;
|
||||||
|
if (apply_precise_outer_wall)
|
||||||
|
wall_0_inset = -coord_t(ext_perimeter_width / 2 - ext_perimeter_spacing / 2);
|
||||||
Polygons last_p = to_polygons(last);
|
Polygons last_p = to_polygons(last);
|
||||||
|
|
||||||
int remain_loops = -1;
|
int remain_loops = -1;
|
||||||
@@ -1429,8 +1618,8 @@ void PerimeterGenerator::process_with_one_wall_arachne(
|
|||||||
|
|
||||||
loop_number = 0;
|
loop_number = 0;
|
||||||
}
|
}
|
||||||
|
//w39
|
||||||
Arachne::WallToolPaths wallToolPaths(last_p, ext_perimeter_spacing, perimeter_spacing, coord_t(loop_number + 1), 0, params.layer_height, params.object_config, params.print_config);
|
Arachne::WallToolPaths wallToolPaths(last_p, ext_perimeter_spacing, perimeter_spacing, coord_t(loop_number + 1), wall_0_inset, params.layer_height, params.object_config, params.print_config);
|
||||||
std::vector<Arachne::VariableWidthLines> perimeters = wallToolPaths.getToolPaths();
|
std::vector<Arachne::VariableWidthLines> perimeters = wallToolPaths.getToolPaths();
|
||||||
loop_number = int(perimeters.size()) - 1;
|
loop_number = int(perimeters.size()) - 1;
|
||||||
|
|
||||||
@@ -1637,8 +1826,15 @@ void PerimeterGenerator::process_with_one_wall_arachne(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ExtrusionEntityCollection extrusion_coll = traverse_extrusions(params, lower_slices_polygons_cache, ordered_extrusions); !extrusion_coll.empty())
|
//w38
|
||||||
|
bool steep_overhang_contour = false;
|
||||||
|
bool steep_overhang_hole = false;
|
||||||
|
if (ExtrusionEntityCollection extrusion_coll = traverse_extrusions(params, lower_slices_polygons_cache, ordered_extrusions,
|
||||||
|
steep_overhang_contour, steep_overhang_hole);
|
||||||
|
!extrusion_coll.empty()) {
|
||||||
|
reorient_perimeters(extrusion_coll, steep_overhang_contour, steep_overhang_hole, params.config.overhang_reverse_internal_only);
|
||||||
out_loops.append(extrusion_coll);
|
out_loops.append(extrusion_coll);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//w16
|
//w16
|
||||||
@@ -1771,7 +1967,9 @@ void PerimeterGenerator::process_classic(
|
|||||||
// Infills without the gap fills
|
// Infills without the gap fills
|
||||||
ExPolygons &out_fill_expolygons,
|
ExPolygons &out_fill_expolygons,
|
||||||
//w21
|
//w21
|
||||||
ExPolygons &out_fill_no_overlap)
|
ExPolygons &out_fill_no_overlap,
|
||||||
|
//w23
|
||||||
|
const size_t layer_id)
|
||||||
{
|
{
|
||||||
// other perimeters
|
// other perimeters
|
||||||
coord_t perimeter_width = params.perimeter_flow.scaled_width();
|
coord_t perimeter_width = params.perimeter_flow.scaled_width();
|
||||||
@@ -1779,7 +1977,13 @@ void PerimeterGenerator::process_classic(
|
|||||||
// external perimeters
|
// external perimeters
|
||||||
coord_t ext_perimeter_width = params.ext_perimeter_flow.scaled_width();
|
coord_t ext_perimeter_width = params.ext_perimeter_flow.scaled_width();
|
||||||
coord_t ext_perimeter_spacing = params.ext_perimeter_flow.scaled_spacing();
|
coord_t ext_perimeter_spacing = params.ext_perimeter_flow.scaled_spacing();
|
||||||
coord_t ext_perimeter_spacing2 = scaled<coord_t>(0.5f * (params.ext_perimeter_flow.spacing() + params.perimeter_flow.spacing()));
|
coord_t ext_perimeter_spacing2; //= scaled<coord_t>(0.5f * (params.ext_perimeter_flow.spacing() + params.perimeter_flow.spacing()));
|
||||||
|
//w39
|
||||||
|
if (params.config.precise_outer_wall && !params.config.external_perimeters_first)
|
||||||
|
ext_perimeter_spacing2 = scaled<coord_t>(0.5f * (params.ext_perimeter_flow.width() + params.perimeter_flow.width()));
|
||||||
|
else
|
||||||
|
ext_perimeter_spacing2 = scaled<coord_t>(0.5f * (params.ext_perimeter_flow.spacing() + params.perimeter_flow.spacing()));
|
||||||
|
|
||||||
// solid infill
|
// solid infill
|
||||||
coord_t solid_infill_spacing = params.solid_infill_flow.scaled_spacing();
|
coord_t solid_infill_spacing = params.solid_infill_flow.scaled_spacing();
|
||||||
|
|
||||||
@@ -1817,11 +2021,13 @@ void PerimeterGenerator::process_classic(
|
|||||||
ExPolygons top_fills;
|
ExPolygons top_fills;
|
||||||
//w16
|
//w16
|
||||||
|
|
||||||
if (params.config.overhangs && upper_slices != nullptr && upper_layer_polygons_cache.empty()) {
|
if ( upper_slices != nullptr && upper_layer_polygons_cache.empty()) {
|
||||||
double upper_nozzle_diameter = params.print_config.nozzle_diameter.get_at(params.config.perimeter_extruder - 1);
|
double upper_nozzle_diameter = params.print_config.nozzle_diameter.get_at(params.config.perimeter_extruder - 1);
|
||||||
upper_layer_polygons_cache = offset(*upper_slices, float(scale_(+upper_nozzle_diameter / 2)));
|
upper_layer_polygons_cache = offset(*upper_slices, float(scale_(+upper_nozzle_diameter / 2)));
|
||||||
}
|
}
|
||||||
if (loop_number > 0 && params.object_config.top_one_wall_type != TopOneWallType::Disable && upper_slices == nullptr)
|
//w16
|
||||||
|
//w23
|
||||||
|
if (loop_number > 0 && (params.object_config.top_one_wall_type != TopOneWallType::Disable && upper_slices == nullptr) || (params.object_config.only_one_wall_first_layer && layer_id == 0))
|
||||||
loop_number = 0;
|
loop_number = 0;
|
||||||
if (loop_number >= 0) {
|
if (loop_number >= 0) {
|
||||||
// In case no perimeters are to be generated, loop_number will equal to -1.
|
// In case no perimeters are to be generated, loop_number will equal to -1.
|
||||||
@@ -2025,7 +2231,11 @@ void PerimeterGenerator::process_classic(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// at this point, all loops should be in contours[0]
|
// at this point, all loops should be in contours[0]
|
||||||
ExtrusionEntityCollection entities = traverse_loops_classic(params, lower_layer_polygons_cache, contours.front(), thin_walls);
|
//w38
|
||||||
|
bool steep_overhang_contour = false;
|
||||||
|
bool steep_overhang_hole = false;
|
||||||
|
ExtrusionEntityCollection entities = traverse_loops_classic(params, lower_layer_polygons_cache, contours.front(), thin_walls,steep_overhang_contour, steep_overhang_hole);
|
||||||
|
reorient_perimeters(entities, steep_overhang_contour, steep_overhang_hole, params.config.overhang_reverse_internal_only);
|
||||||
// if brim will be printed, reverse the order of perimeters so that
|
// if brim will be printed, reverse the order of perimeters so that
|
||||||
// we continue inwards after having finished the brim
|
// we continue inwards after having finished the brim
|
||||||
// TODO: add test for perimeter order
|
// TODO: add test for perimeter order
|
||||||
@@ -2102,7 +2312,7 @@ void PerimeterGenerator::process_classic(
|
|||||||
if (!top_fills.empty()) {
|
if (!top_fills.empty()) {
|
||||||
infill_areas = union_ex(infill_areas, offset_ex(top_infill_exp, double(infill_peri_overlap)));
|
infill_areas = union_ex(infill_areas, offset_ex(top_infill_exp, double(infill_peri_overlap)));
|
||||||
}
|
}
|
||||||
append(out_fill_expolygons, std::move(top_infill_exp));
|
|
||||||
//w21
|
//w21
|
||||||
{
|
{
|
||||||
ExPolygons polyWithoutOverlap;
|
ExPolygons polyWithoutOverlap;
|
||||||
|
|||||||
@@ -39,7 +39,9 @@ struct Parameters {
|
|||||||
scaled_resolution(scaled<double>(print_config.gcode_resolution.value)),
|
scaled_resolution(scaled<double>(print_config.gcode_resolution.value)),
|
||||||
mm3_per_mm(perimeter_flow.mm3_per_mm()),
|
mm3_per_mm(perimeter_flow.mm3_per_mm()),
|
||||||
ext_mm3_per_mm(ext_perimeter_flow.mm3_per_mm()),
|
ext_mm3_per_mm(ext_perimeter_flow.mm3_per_mm()),
|
||||||
mm3_per_mm_overhang(overhang_flow.mm3_per_mm())
|
mm3_per_mm_overhang(overhang_flow.mm3_per_mm()),
|
||||||
|
//w38
|
||||||
|
lower_slices(lower_slices)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,6 +55,8 @@ struct Parameters {
|
|||||||
const PrintRegionConfig &config;
|
const PrintRegionConfig &config;
|
||||||
const PrintObjectConfig &object_config;
|
const PrintObjectConfig &object_config;
|
||||||
const PrintConfig &print_config;
|
const PrintConfig &print_config;
|
||||||
|
//w38
|
||||||
|
const ExPolygons * lower_slices;
|
||||||
|
|
||||||
// Derived parameters
|
// Derived parameters
|
||||||
bool spiral_vase;
|
bool spiral_vase;
|
||||||
@@ -83,7 +87,9 @@ void process_classic(
|
|||||||
// Infills without the gap fills
|
// Infills without the gap fills
|
||||||
ExPolygons &out_fill_expolygons,
|
ExPolygons &out_fill_expolygons,
|
||||||
//w21
|
//w21
|
||||||
ExPolygons &out_fill_no_overlap);
|
ExPolygons &out_fill_no_overlap,
|
||||||
|
//w23
|
||||||
|
const size_t layer_id );
|
||||||
|
|
||||||
void process_arachne(
|
void process_arachne(
|
||||||
// Inputs:
|
// Inputs:
|
||||||
@@ -100,9 +106,11 @@ void process_arachne(
|
|||||||
// Gaps without the thin walls
|
// Gaps without the thin walls
|
||||||
ExtrusionEntityCollection &out_gap_fill,
|
ExtrusionEntityCollection &out_gap_fill,
|
||||||
// Infills without the gap fills
|
// Infills without the gap fills
|
||||||
ExPolygons &out_fill_expolygons,
|
ExPolygons &out_fill_expolygons,
|
||||||
//w21
|
//w21
|
||||||
ExPolygons &out_fill_no_overlap);
|
ExPolygons &out_fill_no_overlap,
|
||||||
|
//w23
|
||||||
|
const size_t layer_id);
|
||||||
|
|
||||||
void process_with_one_wall_arachne(
|
void process_with_one_wall_arachne(
|
||||||
// Inputs:
|
// Inputs:
|
||||||
@@ -120,9 +128,11 @@ void process_with_one_wall_arachne(
|
|||||||
// Gaps without the thin walls
|
// Gaps without the thin walls
|
||||||
ExtrusionEntityCollection &out_gap_fill,
|
ExtrusionEntityCollection &out_gap_fill,
|
||||||
// Infills without the gap fills
|
// Infills without the gap fills
|
||||||
ExPolygons &out_fill_expolygons,
|
ExPolygons &out_fill_expolygons,
|
||||||
//w21
|
//w21
|
||||||
ExPolygons &out_fill_no_overlap);
|
ExPolygons &out_fill_no_overlap,
|
||||||
|
//w23
|
||||||
|
const size_t layer_id);
|
||||||
|
|
||||||
//w16
|
//w16
|
||||||
void add_infill_contour_for_arachne(ExPolygons infill_contour,
|
void add_infill_contour_for_arachne(ExPolygons infill_contour,
|
||||||
|
|||||||
@@ -81,6 +81,52 @@ Points collect_duplicates(Points pts /* Copy */)
|
|||||||
}
|
}
|
||||||
return duplicits;
|
return duplicits;
|
||||||
}
|
}
|
||||||
|
//w29
|
||||||
|
int Point::nearest_point_index(const Points &points) const
|
||||||
|
{
|
||||||
|
PointConstPtrs p;
|
||||||
|
p.reserve(points.size());
|
||||||
|
for (Points::const_iterator it = points.begin(); it != points.end(); ++it)
|
||||||
|
p.push_back(&*it);
|
||||||
|
return this->nearest_point_index(p);
|
||||||
|
}
|
||||||
|
//w29
|
||||||
|
int Point::nearest_point_index(const PointConstPtrs &points) const
|
||||||
|
{
|
||||||
|
int idx = -1;
|
||||||
|
double distance = -1; // double because long is limited to 2147483647 on some platforms and it's not enough
|
||||||
|
|
||||||
|
for (PointConstPtrs::const_iterator it = points.begin(); it != points.end(); ++it) {
|
||||||
|
/* If the X distance of the candidate is > than the total distance of the
|
||||||
|
best previous candidate, we know we don't want it */
|
||||||
|
double d = sqr<double>((*this) (0) - (*it)->x());
|
||||||
|
if (distance != -1 && d > distance)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* If the Y distance of the candidate is > than the total distance of the
|
||||||
|
best previous candidate, we know we don't want it */
|
||||||
|
d += sqr<double>((*this) (1) - (*it)->y());
|
||||||
|
if (distance != -1 && d > distance)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
idx = it - points.begin();
|
||||||
|
distance = d;
|
||||||
|
|
||||||
|
if (distance < EPSILON)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
//w29
|
||||||
|
int Point::nearest_point_index(const PointPtrs &points) const
|
||||||
|
{
|
||||||
|
PointConstPtrs p;
|
||||||
|
p.reserve(points.size());
|
||||||
|
for (PointPtrs::const_iterator it = points.begin(); it != points.end(); ++it)
|
||||||
|
p.push_back(*it);
|
||||||
|
return this->nearest_point_index(p);
|
||||||
|
}
|
||||||
|
|
||||||
template<bool IncludeBoundary>
|
template<bool IncludeBoundary>
|
||||||
BoundingBox get_extents(const Points &pts)
|
BoundingBox get_extents(const Points &pts)
|
||||||
|
|||||||
@@ -212,6 +212,10 @@ public:
|
|||||||
Point rotated(double angle) const { Point res(*this); res.rotate(angle); return res; }
|
Point rotated(double angle) const { Point res(*this); res.rotate(angle); return res; }
|
||||||
Point rotated(double cos_a, double sin_a) const { Point res(*this); res.rotate(cos_a, sin_a); return res; }
|
Point rotated(double cos_a, double sin_a) const { Point res(*this); res.rotate(cos_a, sin_a); return res; }
|
||||||
Point rotated(double angle, const Point ¢er) const { Point res(*this); res.rotate(angle, center); return res; }
|
Point rotated(double angle, const Point ¢er) const { Point res(*this); res.rotate(angle, center); return res; }
|
||||||
|
//w29
|
||||||
|
int nearest_point_index(const Points &points) const;
|
||||||
|
int nearest_point_index(const PointConstPtrs &points) const;
|
||||||
|
int nearest_point_index(const PointPtrs &points) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline bool operator<(const Point &l, const Point &r)
|
inline bool operator<(const Point &l, const Point &r)
|
||||||
|
|||||||
@@ -113,6 +113,47 @@ void Polyline::simplify(double tolerance)
|
|||||||
this->points = MultiPoint::douglas_peucker(this->points, tolerance);
|
this->points = MultiPoint::douglas_peucker(this->points, tolerance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//w28
|
||||||
|
Polylines Polyline::equally_spaced_lines(double distance) const
|
||||||
|
{
|
||||||
|
Polylines lines;
|
||||||
|
Polyline line;
|
||||||
|
line.append(this->first_point());
|
||||||
|
double len = 0;
|
||||||
|
|
||||||
|
for (Points::const_iterator it = this->points.begin() + 1; it != this->points.end(); ++it) {
|
||||||
|
Vec2d p1 = line.points.back().cast<double>();
|
||||||
|
Vec2d v = it->cast<double>() - p1;
|
||||||
|
double segment_length = v.norm();
|
||||||
|
len += segment_length;
|
||||||
|
if (len < distance)
|
||||||
|
continue;
|
||||||
|
if (len == distance) {
|
||||||
|
line.append(*it);
|
||||||
|
lines.emplace_back(line);
|
||||||
|
|
||||||
|
line.clear();
|
||||||
|
line.append(*it);
|
||||||
|
len = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
double take = distance;
|
||||||
|
line.append((p1 + v * (take / v.norm())).cast<coord_t>());
|
||||||
|
lines.emplace_back(line);
|
||||||
|
|
||||||
|
line.clear();
|
||||||
|
line.append(lines.back().last_point());
|
||||||
|
--it;
|
||||||
|
len = -take;
|
||||||
|
}
|
||||||
|
if (line.size() == 1) {
|
||||||
|
line.append(this->last_point());
|
||||||
|
if (line.first_point() != line.last_point())
|
||||||
|
lines.emplace_back(line);
|
||||||
|
}
|
||||||
|
return lines;
|
||||||
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
// This method simplifies all *lines* contained in the supplied area
|
// This method simplifies all *lines* contained in the supplied area
|
||||||
template <class T>
|
template <class T>
|
||||||
|
|||||||
@@ -81,6 +81,8 @@ public:
|
|||||||
|
|
||||||
using iterator = Points::iterator;
|
using iterator = Points::iterator;
|
||||||
using const_iterator = Points::const_iterator;
|
using const_iterator = Points::const_iterator;
|
||||||
|
//w28
|
||||||
|
Polylines equally_spaced_lines(double distance) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline bool operator==(const Polyline &lhs, const Polyline &rhs) { return lhs.points == rhs.points; }
|
inline bool operator==(const Polyline &lhs, const Polyline &rhs) { return lhs.points == rhs.points; }
|
||||||
|
|||||||
@@ -466,21 +466,41 @@ static std::vector<std::string> s_Preset_print_options {
|
|||||||
"wipe_tower_width", "wipe_tower_cone_angle", "wipe_tower_rotation_angle", "wipe_tower_brim_width", "wipe_tower_bridging", "single_extruder_multi_material_priming", "mmu_segmented_region_max_width",
|
"wipe_tower_width", "wipe_tower_cone_angle", "wipe_tower_rotation_angle", "wipe_tower_brim_width", "wipe_tower_bridging", "single_extruder_multi_material_priming", "mmu_segmented_region_max_width",
|
||||||
"mmu_segmented_region_interlocking_depth", "wipe_tower_extruder", "wipe_tower_no_sparse_layers", "wipe_tower_extra_flow", "wipe_tower_extra_spacing", "compatible_printers", "compatible_printers_condition", "inherits",
|
"mmu_segmented_region_interlocking_depth", "wipe_tower_extruder", "wipe_tower_no_sparse_layers", "wipe_tower_extra_flow", "wipe_tower_extra_spacing", "compatible_printers", "compatible_printers_condition", "inherits",
|
||||||
"perimeter_generator", "wall_transition_length", "wall_transition_filter_deviation", "wall_transition_angle",
|
"perimeter_generator", "wall_transition_length", "wall_transition_filter_deviation", "wall_transition_angle",
|
||||||
"wall_distribution_count", "min_feature_size", "min_bead_width"
|
"wall_distribution_count", "min_feature_size", "min_bead_width",
|
||||||
//B36
|
//B36
|
||||||
,"first_layer_travel_speed"
|
"first_layer_travel_speed",
|
||||||
//B37
|
//B37
|
||||||
,"first_layer_infill_speed"
|
"first_layer_infill_speed",
|
||||||
//w11
|
//w11
|
||||||
,"detect_narrow_internal_solid_infill"
|
"detect_narrow_internal_solid_infill",
|
||||||
//Y21
|
//Y21
|
||||||
,"seam_gap"
|
"seam_gap",
|
||||||
//w16
|
//w16
|
||||||
, "top_one_wall_type"
|
"top_one_wall_type",
|
||||||
//w17
|
//w17
|
||||||
,"top_area_threshold"
|
"top_area_threshold",
|
||||||
//w21
|
//w21
|
||||||
,"filter_top_gap_infill"
|
"filter_top_gap_infill",
|
||||||
|
//w23
|
||||||
|
"only_one_wall_first_layer",
|
||||||
|
//w25
|
||||||
|
"slow_down_layers",
|
||||||
|
//w26
|
||||||
|
"elefant_foot_compensation_layers",
|
||||||
|
//w27
|
||||||
|
"precise_z_height",
|
||||||
|
//w28
|
||||||
|
"max_bridge_length",
|
||||||
|
//w30
|
||||||
|
"top_solid_infill_flow_ratio", "bottom_solid_infill_flow_ratio",
|
||||||
|
//w33
|
||||||
|
"ironing_pattern",
|
||||||
|
//w38
|
||||||
|
"overhang_reverse", "overhang_reverse_internal_only", "overhang_reverse_threshold",
|
||||||
|
//w39
|
||||||
|
"precise_outer_wall",
|
||||||
|
//Y27
|
||||||
|
"resonance_avoidance", "min_resonance_avoidance_speed", "max_resonance_avoidance_speed"
|
||||||
};
|
};
|
||||||
|
|
||||||
static std::vector<std::string> s_Preset_filament_options {
|
static std::vector<std::string> s_Preset_filament_options {
|
||||||
@@ -501,6 +521,8 @@ static std::vector<std::string> s_Preset_filament_options {
|
|||||||
"filament_vendor", "compatible_prints", "compatible_prints_condition", "compatible_printers", "compatible_printers_condition", "inherits",
|
"filament_vendor", "compatible_prints", "compatible_prints_condition", "compatible_printers", "compatible_printers_condition", "inherits",
|
||||||
//B15
|
//B15
|
||||||
"enable_auxiliary_fan",
|
"enable_auxiliary_fan",
|
||||||
|
//Y26
|
||||||
|
"enable_auxiliary_fan_unseal",
|
||||||
//B24
|
//B24
|
||||||
"volume_temperature",
|
"volume_temperature",
|
||||||
//B25
|
//B25
|
||||||
@@ -515,6 +537,10 @@ static std::vector<std::string> s_Preset_filament_options {
|
|||||||
"disable_rapid_cooling_fan_first_layers",
|
"disable_rapid_cooling_fan_first_layers",
|
||||||
//Y23
|
//Y23
|
||||||
"filament_shrink",
|
"filament_shrink",
|
||||||
|
//Y26
|
||||||
|
"seal_print",
|
||||||
|
//Y28
|
||||||
|
"dont_slow_down_outer_wall",
|
||||||
//w15
|
//w15
|
||||||
"filament_wipe_distance"
|
"filament_wipe_distance"
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -179,7 +179,8 @@ void PresetBundle::setup_directories()
|
|||||||
data_dir / "sla_print",
|
data_dir / "sla_print",
|
||||||
data_dir / "sla_material",
|
data_dir / "sla_material",
|
||||||
data_dir / "printer",
|
data_dir / "printer",
|
||||||
data_dir / "physical_printer"
|
data_dir / "physical_printer",
|
||||||
|
data_dir / "user" // y5
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
for (const boost::filesystem::path &path : paths) {
|
for (const boost::filesystem::path &path : paths) {
|
||||||
@@ -253,7 +254,8 @@ void PresetBundle::import_newer_configs(const std::string& from)
|
|||||||
from_data_dir / "sla_print",
|
from_data_dir / "sla_print",
|
||||||
from_data_dir / "sla_material",
|
from_data_dir / "sla_material",
|
||||||
from_data_dir / "printer",
|
from_data_dir / "printer",
|
||||||
from_data_dir / "physical_printer"
|
from_data_dir / "physical_printer",
|
||||||
|
from_data_dir / "user" //y5
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
// copy recursively all files
|
// copy recursively all files
|
||||||
@@ -2047,4 +2049,17 @@ void copy_bed_model_and_texture_if_needed(DynamicPrintConfig& config)
|
|||||||
do_copy(config.option<ConfigOptionString>("bed_custom_model"), "model");
|
do_copy(config.option<ConfigOptionString>("bed_custom_model"), "model");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// y3
|
||||||
|
std::set<std::string> PresetBundle::get_vendors()
|
||||||
|
{
|
||||||
|
std::set<std::string> qidiVendors;
|
||||||
|
for (auto vendor_profile : vendors) {
|
||||||
|
for (auto vendor_model : vendor_profile.second.models) {
|
||||||
|
std::string vendor_name = vendor_model.name;
|
||||||
|
qidiVendors.emplace(vendor_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return qidiVendors;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Slic3r
|
} // namespace Slic3r
|
||||||
|
|||||||
@@ -190,6 +190,9 @@ public:
|
|||||||
return { Preset::TYPE_PRINTER, Preset::TYPE_SLA_PRINT, Preset::TYPE_SLA_MATERIAL };
|
return { Preset::TYPE_PRINTER, Preset::TYPE_SLA_PRINT, Preset::TYPE_SLA_MATERIAL };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//y3
|
||||||
|
std::set<std::string> get_vendors();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::pair<PresetsConfigSubstitutions, std::string> load_system_presets(ForwardCompatibilitySubstitutionRule compatibility_rule);
|
std::pair<PresetsConfigSubstitutions, std::string> load_system_presets(ForwardCompatibilitySubstitutionRule compatibility_rule);
|
||||||
// Merge one vendor's presets with the other vendor's presets, report duplicates.
|
// Merge one vendor's presets with the other vendor's presets, report duplicates.
|
||||||
|
|||||||
@@ -83,6 +83,8 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
|
|||||||
"disable_fan_first_layers",
|
"disable_fan_first_layers",
|
||||||
//B39
|
//B39
|
||||||
"disable_rapid_cooling_fan_first_layers",
|
"disable_rapid_cooling_fan_first_layers",
|
||||||
|
//Y28
|
||||||
|
"dont_slow_down_outer_wall",
|
||||||
"duplicate_distance",
|
"duplicate_distance",
|
||||||
"end_gcode",
|
"end_gcode",
|
||||||
"end_filament_gcode",
|
"end_filament_gcode",
|
||||||
@@ -251,7 +253,9 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
|
|||||||
|| opt_key == "first_layer_travel_speed"
|
|| opt_key == "first_layer_travel_speed"
|
||||||
//B37
|
//B37
|
||||||
|| opt_key == "first_layer_infill_speed"
|
|| opt_key == "first_layer_infill_speed"
|
||||||
|| opt_key == "z_offset") {
|
|| opt_key == "z_offset"
|
||||||
|
//w25
|
||||||
|
|| opt_key == "slow_down_layers") {
|
||||||
steps.emplace_back(psWipeTower);
|
steps.emplace_back(psWipeTower);
|
||||||
steps.emplace_back(psSkirtBrim);
|
steps.emplace_back(psSkirtBrim);
|
||||||
} else if (opt_key == "filament_soluble") {
|
} else if (opt_key == "filament_soluble") {
|
||||||
@@ -576,7 +580,8 @@ std::string Print::validate(std::vector<std::string>* warnings) const
|
|||||||
for (size_t print_object_idx = 0; print_object_idx < m_objects.size(); ++ print_object_idx) {
|
for (size_t print_object_idx = 0; print_object_idx < m_objects.size(); ++ print_object_idx) {
|
||||||
const PrintObject &print_object = *m_objects[print_object_idx];
|
const PrintObject &print_object = *m_objects[print_object_idx];
|
||||||
//FIXME It is quite expensive to generate object layers just to get the print height!
|
//FIXME It is quite expensive to generate object layers just to get the print height!
|
||||||
if (auto layers = generate_object_layers(print_object.slicing_parameters(), layer_height_profile(print_object_idx));
|
//w27
|
||||||
|
if (auto layers = generate_object_layers(print_object.slicing_parameters(), layer_height_profile(print_object_idx),print_object.config().precise_z_height.value);
|
||||||
! layers.empty() && layers.back() > this->config().max_print_height + EPSILON) {
|
! layers.empty() && layers.back() > this->config().max_print_height + EPSILON) {
|
||||||
return
|
return
|
||||||
// Test whether the last slicing plane is below or above the print volume.
|
// Test whether the last slicing plane is below or above the print volume.
|
||||||
|
|||||||
@@ -270,7 +270,6 @@ public:
|
|||||||
&& this->config().brim_width.value > 0.
|
&& this->config().brim_width.value > 0.
|
||||||
&& ! this->has_raft();
|
&& ! this->has_raft();
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is the *total* layer count (including support layers)
|
// This is the *total* layer count (including support layers)
|
||||||
// this value is not supposed to be compared with Layer::id
|
// this value is not supposed to be compared with Layer::id
|
||||||
// since they have different semantics.
|
// since they have different semantics.
|
||||||
|
|||||||