Compare commits

...

116 Commits

Author SHA1 Message Date
QIDI TECH
53b881144c Version update 1.1.6 2024-09-21 16:59:23 +08:00
QIDI TECH
ecff478fd4 Add X-Plus 4 and several filaments 2024-09-20 20:26:12 +08:00
QIDI TECH
43fc6f262a Update logo 2024-09-20 18:09:37 +08:00
QIDI TECH
18a0c7bd80 Optimize Device 2024-09-20 18:07:25 +08:00
QIDI TECH
007578e041 Update QIDI model 2024-09-20 18:04:48 +08:00
QIDI TECH
e6b82214e5 Optimize device 2024-09-16 16:22:16 +08:00
QIDI TECH
5ed1560c59 Optimize the device list and add user login 2024-08-31 09:35:24 +08:00
Gradbb
a6ed4e65cb Update QIDITechnology.ini 2024-07-31 16:13:46 +08:00
sunsets
ca82d85cc2 Update version.inc 2024-07-30 13:57:33 +08:00
sunsets
f69a71d1f5 Delete QIDINetwork 2024-07-29 18:44:06 +08:00
sunsets
e61c252aee delete 2024-07-29 11:09:50 +08:00
wjyLearn
146a4a15ed y2: fix some bug
1. Fixed a bug where the login window was not destroyed when switching languages;
2. Fixed the display issue when the model does not have the corresponding picture;
3. Fix button display problem when the local device has no IP address.
2024-07-29 10:53:47 +08:00
wjyLearn
4bdb7b76df Revert "Update .gitignore"
This reverts commit 9509b4ffab.
2024-07-29 10:46:56 +08:00
wjyLearn
9509b4ffab Update .gitignore 2024-07-29 10:46:38 +08:00
sunsets
8413db6570 Add files via upload 2024-07-29 10:41:11 +08:00
sunsets
bebee387c5 Update .gitignore 2024-07-29 10:38:48 +08:00
sunsets
7e1ce117f7 init 2024-07-29 10:38:11 +08:00
sunsets
a23a37cbca Delete src/slic3r/Utils/qidi/QIDINetwork.hpp 2024-07-29 10:37:07 +08:00
sunsets
df89ee4f35 Delete src/slic3r/Utils/qidi/QIDINetwork.cpp 2024-07-29 10:36:54 +08:00
sunsets
141752edf2 Update .gitignore 2024-07-29 10:35:59 +08:00
sunsets
7a86f18bac Update .gitignore 2024-07-29 10:34:09 +08:00
sunsets
61424985ac Update .gitignore 2024-07-29 10:31:11 +08:00
sunsets
ad0b449ad4 QIDI 2024-07-29 10:30:21 +08:00
sunsets
6e8f38f01a Update .gitignore 2024-07-29 10:29:26 +08:00
sunsets
24cff06406 Delete 2024-07-29 10:25:05 +08:00
sunsets
4277d8118c QIDINetwork 2024-07-29 10:22:47 +08:00
sunsets
7de8f0817f Update .gitignore 2024-07-29 10:21:25 +08:00
sunsets
4e223315f8 change QIDINetwork location 2024-07-29 10:18:58 +08:00
sunsets
db53ba056c Update .gitignore 2024-07-29 10:08:09 +08:00
QIDI TECH
5005a1df1b Update device 2024-07-26 14:02:02 +08:00
QIDI TECH
2b8deba938 Add PETG Note in PA calibration 2024-07-23 14:19:21 +08:00
QIDI TECH
6cf7a38bb9 Update Q1 2024-07-19 08:53:41 +08:00
QIDI TECH
be65279049 Update Q1 2024-07-19 08:50:26 +08:00
QIDI TECH
aca63cc7e0 Update Q1 2024-07-19 08:49:25 +08:00
QIDI TECH
90f64f7151 Update AboutDialog.cpp 2024-07-12 09:13:09 +08:00
sunsets
84312d4cb8 Merge branch 'master' of https://github.com/QIDITECH/QIDISlicer 2024-07-08 08:42:31 +08:00
sunsets
df194b11c8 Fixed a bug where Linux would not run 2024-07-08 08:42:21 +08:00
Wang YB
8e9d4777f4 fix some bug 2024-07-05 10:54:54 +08:00
sunsets
5d9df179dd version 1.1.5 2024-07-02 14:00:45 +08:00
sunsets
8912079f62 Update AppConfig.cpp 2024-07-02 10:40:44 +08:00
QIDI TECH
e505af5cc7 Update QIDITechnology.ini 2024-07-01 20:25:31 +08:00
QIDI TECH
11bda61bc8 Close the dont_slow_down_outer_wall 2024-07-01 15:14:34 +08:00
sunsets
4c9bbc53a3 Remove suspended threads to optimize cpu usage 2024-07-01 14:44:16 +08:00
Wang YB
e9146c950a fix bug elefant_foot_compensation_layers 2024-06-27 14:09:54 +08:00
QIDI TECH
3d288f47b1 Update bed stl 2024-06-22 13:19:39 +08:00
QIDI TECH
69126621fc Update Resonance Avoidance 2024-06-21 14:19:23 +08:00
QIDI TECH
b7e961c443 Update CoolingBuffer.cpp 2024-06-21 14:11:03 +08:00
QIDI TECH
5b5ff0a1eb Update start_gcode 2024-06-18 16:36:10 +08:00
QIDI TECH
e033b37e75 Update Resonance Avoidance 2024-06-18 16:34:22 +08:00
QIDI TECH
f25014959b Add Don't slow down outer walls 2024-06-18 16:30:47 +08:00
QIDI TECH
78513b7b86 Update GCode.cpp 2024-06-14 10:32:51 +08:00
QIDI TECH
0fe9657904 Update QIDITechnology.ini 2024-06-13 16:55:32 +08:00
QIDI TECH
f0c70857ae Update Plater.cpp 2024-06-13 16:52:47 +08:00
QIDI TECH
e21feab522 Add Resonance Avoidance 2024-06-13 16:28:33 +08:00
QIDI TECH
5b7a66b64c Add filament option ——Seal 2024-06-11 10:48:28 +08:00
QIDI TECH
c2d1c70e10 Open the fan when the PA pattern is calibrated 2024-06-11 10:30:56 +08:00
Wang YB
a1c4285ffc fix "reverse on odd" 2024-06-05 10:44:28 +08:00
Wang YB
ad0215fa2f add "precise_outer_wall" 2024-05-25 11:23:26 +08:00
QIDI TECH
8ef53eceee Merge branch 'master' of https://github.com/QIDITECH/QIDISlicer 2024-05-24 19:24:18 +08:00
QIDI TECH
9e5911b2c3 Add QIDILink in guide 2024-05-24 19:24:12 +08:00
Wang YB
4e0134d651 Update test_perimeters.cpp 2024-05-24 18:08:56 +08:00
Wang YB
783b825007 add "overhang_reverse_internal_only" 2024-05-24 13:50:59 +08:00
Wang YB
201cb4a2fd remove "scarf seam" 2024-05-24 11:25:22 +08:00
Wang YB
125abfca57 add “overhang_reverse” 2024-05-24 10:54:29 +08:00
Wang YB
e77259c80b add scarf seam 2024-05-21 11:32:40 +08:00
sunsets
0b00c61781 Merge branch 'master' of https://github.com/QIDITECH/QIDISlicer 2024-05-20 16:05:56 +08:00
sunsets
13d99fd843 Exclude region judgment before optimizing slice 2024-05-20 16:05:53 +08:00
Wang YB
f743590509 update test_layer_region 2024-05-20 14:20:34 +08:00
sunsets
323538586d Merge branch 'master' of https://github.com/QIDITECH/QIDISlicer 2024-05-17 14:39:34 +08:00
sunsets
cb05d9d4a0 Remove the device name from lower case 2024-05-17 14:38:34 +08:00
Wang YB
01cbd4c5d4 Update PrintObjectSlice.cpp 2024-05-16 16:12:57 +08:00
Wang YB
25062b9f99 update mark 2024-05-16 15:57:24 +08:00
sunsets
d4f6c80a43 Version 1.1.4 2024-05-16 13:39:35 +08:00
Wang YB
ee237cfc16 fix surface detection 2024-05-14 11:17:56 +08:00
QIDI TECH
a9889b297e Update FlowRate calib 2024-05-09 10:20:08 +08:00
sunsets
508ba0444c Optimized exclusion region 2024-05-08 13:37:23 +08:00
QIDI TECH
090eebdabc Update QIDITechnology.ini 2024-05-07 16:56:23 +08:00
Wang YB
5368acee65 Revert change "make_overhang_printable " 2024-05-07 14:26:22 +08:00
Wang YB
c2b5393b82 Update LayerRegion.cpp 2024-05-06 19:20:17 +08:00
Wang YB
4404fdc03c update support_material_synchronize_layers tooltip 2024-05-06 09:09:16 +08:00
Wang YB
8c0b581581 modify support_material_synchronize_layers 2024-05-04 17:00:05 +08:00
Wang YB
96b64539e2 fix default value 2024-05-03 15:40:40 +08:00
Wang YB
e768b990a8 add ironing_pattern "Concentric" 2024-05-03 15:14:02 +08:00
Wang YB
a2ddbe8eb4 add infill pattern "Cross Hatch" 2024-04-30 15:05:11 +08:00
Wang YB
a3e0809506 Update make_overhang_printable_angle default value 2024-04-30 11:25:44 +08:00
Wang YB
b13c47456b Update QIDITechnology.ini 2024-04-30 10:40:44 +08:00
Wang YB
6121002516 add make_overhang_printable 2024-04-30 10:38:59 +08:00
Wang YB
8fa61058d4 Update QIDITechnology.ini 2024-04-29 13:08:42 +08:00
Wang YB
0053429d72 add top&bottom infill flow ratio 2024-04-29 13:07:12 +08:00
Wang YB
da44f549e1 Update QIDITechnology.ini 2024-04-27 16:13:39 +08:00
Wang YB
04ad174e91 add FillConcentricinternal update solidinfill 2024-04-27 16:09:27 +08:00
Wang YB
9c52fb3733 Update QIDITechnology.ini 2024-04-25 10:35:29 +08:00
Wang YB
128a023c41 fix max_bridge_length with support_material_style 2024-04-25 10:33:58 +08:00
Wang YB
b9452a91a2 add max_bridge_length 2024-04-25 09:57:55 +08:00
Wang YB
cc68470ac8 add “precise_z_height” 2024-04-23 08:51:20 +08:00
Wang YB
0de9767ff0 Update GCode.cpp 2024-04-20 14:47:08 +08:00
Wang YB
3217389d20 Update QIDITechnology.ini 2024-04-19 18:17:32 +08:00
Wang YB
05d820c13d add elefant_foot_compensation_layers 2024-04-18 11:21:55 +08:00
Wang YB
68553eba55 add slow_down_layers 2024-04-18 10:11:17 +08:00
Wang YB
6e4ada127d update xy_compensation 2024-04-18 09:00:06 +08:00
Wang YB
4d2d510050 Update ConfigManipulation.cpp 2024-04-16 09:31:49 +08:00
Wang YB
825c980cef improve 3DHoneyComb 2024-04-15 19:20:03 +08:00
sunsets
2a46a2f415 Update test_perimeters.cpp 2024-04-13 14:29:48 +08:00
sunsets
ea3407798b Revert "Update test_perimeters.cpp"
This reverts commit d06a7dfa89.
2024-04-13 14:29:02 +08:00
sunsets
9917cfeb69 Merge branch 'master' of https://github.com/QIDITECH/QIDISlicer 2024-04-13 13:42:18 +08:00
sunsets
d06a7dfa89 Update test_perimeters.cpp 2024-04-13 13:42:16 +08:00
Wang YB
ecde3d5864 Update PrintConfig.cpp 2024-04-13 09:00:01 +08:00
Wang YB
446c2c4e75 add only_one_wall_first_layer 2024-04-12 18:57:00 +08:00
HYzd766
2466489049 Update QIDITechnology.ini 2024-04-12 10:46:41 +08:00
QIDI TECH
b9997e7ee2 Update GLCanvas3D.cpp 2024-04-10 17:50:02 +08:00
Wang YB
b6d7c8a367 fix classic's top_gap_infill 2024-04-10 15:03:54 +08:00
QIDI TECH
05e2b540ab improves loading of 3MFs generated by BambuStudio 2024-04-10 13:44:24 +08:00
QIDI TECH
0491f84149 delete Q1 and add PLA Silk 2024-04-09 11:30:44 +08:00
Wang YB
88c9efa548 fix first layer infill areas 2024-04-08 10:20:07 +08:00
QIDI TECH
e6a64eb5cb arachne prints numbers better in calib 2024-04-08 09:48:00 +08:00
sunsets
a630648563 Adaptive udp return information changes 2024-04-08 09:37:36 +08:00
201 changed files with 34189 additions and 2340 deletions

2
.gitignore vendored
View File

@@ -21,3 +21,5 @@ deps/build-linux/*
**/.idea/
.pkg_cache
CMakeUserPresets.json
/resources/profiles
/src/slic3r/QIDI

BIN
resources/icon.icns Normal file

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 114 KiB

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.9 KiB

After

Width:  |  Height:  |  Size: 7.1 KiB

View File

@@ -1,56 +1,20 @@
<?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="图层_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">
<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
C256,229.1,229.1,256,196,256z"/>
</g>
<g>
<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
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
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>
<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
H60z"/>
<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
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"/>
</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>

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 114 KiB

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.9 KiB

After

Width:  |  Height:  |  Size: 7.1 KiB

View File

@@ -1,56 +1,20 @@
<?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="图层_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">
<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
C256,229.1,229.1,256,196,256z"/>
</g>
<g>
<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
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
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>
<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
H60z"/>
<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
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"/>
</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>

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

View File

Before

Width:  |  Height:  |  Size: 437 B

After

Width:  |  Height:  |  Size: 437 B

View 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

View File

Before

Width:  |  Height:  |  Size: 417 B

After

Width:  |  Height:  |  Size: 417 B

View 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

View 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

View File

Before

Width:  |  Height:  |  Size: 543 B

After

Width:  |  Height:  |  Size: 543 B

View 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

View 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

View File

Before

Width:  |  Height:  |  Size: 659 B

After

Width:  |  Height:  |  Size: 659 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 141 KiB

After

Width:  |  Height:  |  Size: 119 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 141 KiB

After

Width:  |  Height:  |  Size: 119 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -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
1.1.3 Optimize parameters
min_slic3r_version = 1.1.2

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 36 KiB

View File

@@ -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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

View File

@@ -66,6 +66,7 @@ var LangText={
"l44": "Different filaments have different 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.",
"l47": "Or you can find a solution through WIKI.",
},
"zh_CN": {
"t1": "用户指南",
@@ -134,6 +135,7 @@ var LangText={
"l44": "不同线材的最大体积速度各不相同。",
"l45": "喷嘴材质、口径、打印温度、等都会影响最大体积速度。",
"l46": "测试时打印速度会逐层增加,当模型表面出现空洞或缺丝时,说明该层已达到最大体积速度,根据高度比例算出最大体积速度。",
"l47": "或者你可以通过WIKI来找到解决方案。",
},
"ja": {
"t1": "ユーザーガイド",
@@ -202,6 +204,7 @@ var LangText={
"l44": "最大体積速度は線材によって異なります。",
"l45": "ノズルの材質、口径、印刷温度などが最大体積速度に影響します。",
"l46": "テスト時の印刷速度は層ごとに増加します。模型の表面に穴ができたり、糸が欠けたりした場合、その層が最大体積速度に達したことを示し、高さの割合から最大体積速度を算出します。",
"l47": "WIKIで解決策を見つけることもできます.",
},
"fr": {
"t1": "Guide de l'utilisateur",
@@ -270,6 +273,7 @@ var LangText={
"l44": "Différents filaments ont une vitesse de volume maximale différente.",
"l45": "Le matériau de la buse, le calibre, la température dimpression, etc., affecteront la vitesse de volume maximum.",
"l46": "Pendant lessai, la vitesse dimpression 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": {
"t1": "Benutzerhandbuch",
@@ -338,6 +342,7 @@ var LangText={
"l44": "Es gibt eine vielzahl Von lichtern mit 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.",
"l47": "Oder Sie finden eine Lösung über WIKI.",
},
"be": {
"t1": "Кіраўніцтва карыстальніка",
@@ -406,6 +411,7 @@ var LangText={
"l44": "Различные нити накала имеют разную максимальную объемную скорость.",
"l45": "Материал сопла, калибр, температура печати и т.д., повлияет на максимальную объемную скорость.",
"l46": "Во время теста скорость печати будет увеличиваться слой за слоем. Если на поверхности модели имеется отверстие или недостающая проволока, это указывает на то, что слой достиг максимальной объемной скорости, а максимальная объемная скорость рассчитывается в соответствии с отношением высоты.",
"l47": "Или вы можете найти решение через WIKI.",
},
};

View File

@@ -93,7 +93,7 @@ li {
}
.accordion > li ol {
width: 100%;
background-color: #333;
background-color: #333333;
}
.accordion > li ol li {
position: relative;

Binary file not shown.

After

Width:  |  Height:  |  Size: 502 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@@ -61,6 +61,10 @@
<div class="MenuBtnIcon"><img src="img/MenuBtnIcon.svg"/></div>
<div class="trans" tid="t18"></div>
</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')">
<div class="MenuBtnIcon"><img src="img/MenuBtnIcon.svg"/></div>
<div class="trans" tid="t13"></div>
@@ -97,6 +101,10 @@
<i class="fa fa-caret-right"></i>
</label>
<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')">
<div class="MenuBtnIcon"><img src="img/MenuBtnIcon.svg"/></div>
<div>Q1 Pro</div>
@@ -170,6 +178,10 @@
<div class="AutozoomImage"><img src="img/ExcludeObjects.gif"/></div>
<div class="ThumbnailTitle trans" tid="t18"></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="AutozoomImage"><img src="img/DownloadModel.png"/></div>
<div class="ThumbnailTitle trans" tid="t13"></div>
@@ -244,6 +256,11 @@
<div class="AutozoomImage"><img src="img/ExcludeObjects.gif"/></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="IntroduceTitle trans" tid="t13"></div>
<div class="IntroduceTextBold trans" tid="l1"></div>
@@ -314,10 +331,16 @@
<div class="IntroduceText trans" tid="l46"></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="AutozoomImage"><img src="img/Q1 ProPoster.png"/></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 class="IntroduceBoard" board="X-MAX 3">
@@ -595,7 +618,18 @@
<div class="IntroduceTitle trans" tid="t6"></div>
<div class="IntroduceText trans" tid="l2"></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="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="CenterImage"><img src="img/Q1 Pro.png"/></div>
<div class="ThumbnailTitle">Q1 Pro</div>

View File

@@ -4,6 +4,7 @@ body {
align-items: center;
/* <20><>ҳ<EFBFBD><D2B3>ռ<EFBFBD><D5BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĸ߶<C4B8> */
height: 100vh;
background: #EEEEEE;
}
#GifBoard {

Binary file not shown.

After

Width:  |  Height:  |  Size: 502 KiB

View 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>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 1.7 MiB

View File

@@ -26,6 +26,8 @@
#include <cstring>
#include <iostream>
#include <math.h>
//B64
#include "nlohmann/json.hpp"
#include <boost/algorithm/string/predicate.hpp>
#include <boost/filesystem.hpp>
#include <boost/nowide/args.hpp>

View File

@@ -211,11 +211,33 @@ void AppConfig::set_defaults()
if (get("sys_menu_enabled").empty())
set("sys_menu_enabled", "1");
//B45
#endif // _WIN32
// B45
if (get("machine_list_minification").empty())
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
erase("", "main_frame_maximized");
erase("", "main_frame_pos");

View File

@@ -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 << ".";
ret = std::make_unique<WideningBeadingStrategy>(std::move(ret), min_feature_size, min_bead_width);
}
if (outer_wall_offset > 0) {
//w39
if (outer_wall_offset != 0){//if (outer_wall_offset > 0) {
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));
}

View File

@@ -31,7 +31,29 @@ public:
: 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 PointsType &points);
void merge(const BoundingBoxBase<PointType, PointsType> &bb);

View File

@@ -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
{
assert(m_type == Type::Rectangle);
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) {
std::vector<Vec2d> tem_exclude_bed_shap;
for (int j = 1; j < 6; j++)
tem_exclude_bed_shap.push_back(m_exclude_bed_shape[i + j]);
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)};
BoundingBox3Base<Vec3d> tem_build_volume = tem_exclude_bboxf.inflated(SceneEpsilon);
exclude_build_volume.push_back(tem_build_volume);
}
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;
Slic3r::Polygon p = tem_exclude_bboxf.polygon(true); // instance convex hull is scaled, so we need to scale here
if (intersection({p}, {hull}).empty() == false) {
return ObjectState::Colliding;
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
@@ -369,32 +365,33 @@ bool BuildVolume::all_paths_inside(const GCodeProcessorResult& paths, const Boun
build_volume.max.z() = std::numeric_limits<double>::max();
if (ignore_bottom)
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) {
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]);
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)};
BoundingBox3Base<Vec3d> tem_build_volume = tem_exclude_bboxf.inflated(SceneEpsilon);
exclude_build_volume.push_back(tem_build_volume);
}
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;
Slic3r::Polygon p = tem_exclude_bboxf.polygon(true); // instance convex hull is scaled, so we need to scale here
if (intersection({p}, {convex_hull_2d}).empty() == false) {
return false;
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:
{

View File

@@ -87,6 +87,8 @@ public:
// Called by GLVolumeCollection::check_outside_state() after an object is manipulated with gizmos for example.
// Called for a rectangular bed:
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.
// Using BedEpsilon for all tests.

View File

@@ -88,6 +88,10 @@ set(SLIC3R_SOURCES
Fill/FillBase.hpp
Fill/FillConcentric.cpp
Fill/FillConcentric.hpp
Fill/FillConcentricInternal.cpp
Fill/FillConcentricInternal.hpp
Fill/FillCrossHatch.cpp
Fill/FillCrossHatch.hpp
Fill/FillEnsuring.cpp
Fill/FillEnsuring.hpp
Fill/FillHoneycomb.cpp

View File

@@ -66,7 +66,8 @@ namespace ClipperUtils {
// 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.
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;
@@ -121,6 +122,8 @@ namespace ClipperUtils {
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); }
//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)
{ clip_clipper_polygon_with_subject_bbox_templ(src, bbox, out); }
@@ -149,6 +152,14 @@ namespace ClipperUtils {
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)
{
Polygons out;
@@ -172,7 +183,36 @@ namespace ClipperUtils {
out.end());
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)
{
@@ -793,6 +833,7 @@ Slic3r::ExPolygons union_ex(const Slic3r::ExPolygons &subject, const Slic3r::Pol
Slic3r::ExPolygons union_ex(const Slic3r::Surfaces &subject)
{ return PolyTreeToExPolygons(clipper_do_polytree(ClipperLib::ctUnion, ClipperUtils::SurfacesProvider(subject), ClipperUtils::EmptyPathsProvider(), ClipperLib::pftNonZero)); }
template<typename PathsProvider1, typename PathsProvider2>
Polylines _clipper_pl_open(ClipperLib::ClipType clipType, PathsProvider1 &&subject, PathsProvider2 &&clip)
{

View File

@@ -326,9 +326,23 @@ namespace ClipperUtils {
[[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);
[[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 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
// 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::Polygons &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);
@@ -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::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::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::Polylines &subject, const Slic3r::ExPolygon &clip);

View File

@@ -9,6 +9,7 @@
#include <limits>
#include <sstream>
namespace Slic3r {
void ExtrusionPath::intersect_expolygons(const ExPolygons &collection, ExtrusionEntityCollection* retval) const
@@ -112,6 +113,22 @@ Polyline ExtrusionMultiPath::as_polyline() const
}
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
{
@@ -334,4 +351,5 @@ double ExtrusionLoop::min_mm3_per_mm() const
return min_mm3_per_mm;
}
}

View File

@@ -326,6 +326,9 @@ public:
append(dst, p.polyline.points);
}
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
bool validate() const {
@@ -376,6 +379,8 @@ inline void extrusion_entities_append_paths(ExtrusionEntitiesPtr &dst, Polylines
polylines.clear();
}
inline void extrusion_entities_append_loops(ExtrusionEntitiesPtr &dst, Polygons &&loops, const ExtrusionAttributes &attributes)
{
dst.reserve(dst.size() + loops.size());

View File

@@ -95,9 +95,13 @@ struct ExtrusionRole : public ExtrusionRoleModifiers
// Special flags describing loop
enum ExtrusionLoopRole {
elrDefault,
elrContourInternalPerimeter,
elrSkirt,
//w38
elrDefault = 0x0,
// 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

View File

@@ -20,6 +20,8 @@
//w21
#include "../ShortestPath.hpp"
//w11
//w29
#include "FillConcentricInternal.hpp"
#include "LayerRegion.hpp"
@@ -125,9 +127,10 @@ struct SurfaceFill {
//w11
static bool is_narrow_infill_area(const ExPolygon &expolygon)
{
//w29
ExPolygons offsets = offset_ex(expolygon, -scale_(NARROW_INFILL_AREA_THRESHOLD));
ExPolygons offsets_min = offset_ex(expolygon, -scale_(NARROW_INFILL_AREA_THRESHOLD_MIN));
if (offsets.empty() && !offsets_min.empty())
//ExPolygons offsets_min = offset_ex(expolygon, -scale_(NARROW_INFILL_AREA_THRESHOLD_MIN));
if (offsets.empty() )
return true;
return false;
@@ -340,34 +343,41 @@ std::vector<SurfaceFill> group_fills(const Layer &layer)
// Use ipEnsuring pattern for all internal Solids.
//w11
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)
continue;
size_t expolygons_size = surface_fills[i].expolygons.size();
//w29
size_t expolygons_size = surface_fills[i].expolygons.size();
std::vector<size_t> narrow_expolygons_index;
narrow_expolygons_index.reserve(expolygons_size);
for (size_t j = 0; j < expolygons_size; j++)
if (is_narrow_infill_area(surface_fills[i].expolygons[j]))
narrow_expolygons_index.push_back(j);
if (narrow_expolygons_index.size() == expolygons_size) {
surface_fills[i].params.pattern = ipConcentricInternal;
//w29
if (narrow_expolygons_index.size() == 0) {
continue;
} else if (narrow_expolygons_index.size() == expolygons_size) {
surface_fills[i].params.pattern = ipConcentric;
} else {
surface_fills[i].params.pattern = ipEnsuring;
}
//w21
if (narrow_expolygons_index.size() != expolygons_size && narrow_expolygons_index.size() != expolygons_size) {
//w29
params = surface_fills[i].params;
params.pattern = ipConcentric;
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().no_overlap_expolygons = surface_fills[i].no_overlap_expolygons;
}
}
} else {
for (size_t surface_fill_id = 0; surface_fill_id < surface_fills.size(); ++surface_fill_id)
if (SurfaceFill &fill = surface_fills[surface_fill_id]; fill.surface.surface_type == stInternalSolid) {
fill.params.pattern = ipEnsuring;
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]]));
}
for (int j = narrow_expolygons_index.size() - 1; j >= 0; j--) {
surface_fills[i].expolygons.erase(surface_fills[i].expolygons.begin() + narrow_expolygons_index[j]);
}
}
}
}
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_object_config = &this->object()->config();
if (surface_fill.params.pattern == ipLightning)
dynamic_cast<FillLightning::Filler*>(f.get())->generator = lightning_generator;
if (surface_fill.params.pattern == ipEnsuring) {
auto *fill_ensuring = dynamic_cast<FillEnsuring *>(f.get());
assert(fill_ensuring != nullptr);
fill_ensuring->print_region_config = &m_regions[surface_fill.region_id]->region().config();
}
//w29
if (surface_fill.params.pattern == ipConcentricInternal) {
FillConcentricInternal *fill_concentric = dynamic_cast<FillConcentricInternal *>(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 == 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
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.resolution = resolution;
//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;
//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) {
// Spacing is modified by the filler to indicate adjustments. Reset it for each expolygon.
f->spacing = surface_fill.params.spacing;
//w21
// Spacing is modified by the filler to indicate adjustments. Reset it for each expolygon.
f->spacing = surface_fill.params.spacing;
// w21
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;
ThickPolylines thick_polylines;
//w14
if (this->object()->config().detect_narrow_internal_solid_infill &&
(surface_fill.params.pattern == ipConcentricInternal || surface_fill.params.pattern == ipEnsuring)) {
layerm.region().config().infill_overlap.percent ?
f->overlap = layerm.region().config().perimeter_extrusion_width * layerm.region().config().infill_overlap.value / 100 * (-1) :
f->overlap = float(layerm.region().config().infill_overlap.value);
// w14
//w29
/* if (this->object()->config().detect_narrow_internal_solid_infill &&
(surface_fill.params.pattern == ipConcentricInternal || surface_fill.params.pattern == ipEnsuring)) {
layerm.region().config().infill_overlap.percent ? f->overlap = layerm.region().config().perimeter_extrusion_width *
layerm.region().config().infill_overlap.value / 100 * (-1) :
f->overlap = float(layerm.region().config().infill_overlap.value);
} else
f->overlap = 0;
try {
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 &) {
}
f->overlap = 0;*/
//w29
f->fill_surface_extrusion(&surface_fill.surface, params, polylines, thick_polylines);
if (!polylines.empty() || !thick_polylines.empty()) {
// calculate actual flow from spacing (which might have been adjusted by the infill
// pattern generator)
double flow_mm3_per_mm = surface_fill.params.flow.mm3_per_mm();
double flow_width = surface_fill.params.flow.width();
if (using_internal_flow) {
// if we used the internal flow we're not doing a solid infill
// so we can safely ignore the slight variation that might have
// been applied to f->spacing
} else {
Flow new_flow = surface_fill.params.flow.with_spacing(float(f->spacing));
flow_mm3_per_mm = new_flow.mm3_per_mm();
flow_width = new_flow.width();
}
// Save into layer.
// pattern generator)
double flow_mm3_per_mm = surface_fill.params.flow.mm3_per_mm();
double flow_width = surface_fill.params.flow.width();
if (using_internal_flow) {
// if we used the internal flow we're not doing a solid infill
// so we can safely ignore the slight variation that might have
// been applied to f->spacing
} else {
Flow new_flow = surface_fill.params.flow.with_spacing(float(f->spacing));
flow_mm3_per_mm = new_flow.mm3_per_mm();
flow_width = new_flow.width();
}
// Save into layer.
ExtrusionEntityCollection *eec = new ExtrusionEntityCollection();
auto fill_begin = uint32_t(layerm.fills().size());
// Only concentric fills are not sorted.
eec->no_sort = f->no_sort();
auto fill_begin = uint32_t(layerm.fills().size());
// Only concentric fills are not sorted.
eec->no_sort = f->no_sort();
if (params.use_arachne) {
for (const ThickPolyline &thick_polyline : thick_polylines) {
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.
if (!multi_path.empty()) {
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;
thick_polylines.clear();
} else {
extrusion_entities_append_paths(
eec->entities, std::move(polylines),
ExtrusionAttributes{ surface_fill.params.extrusion_role,
ExtrusionFlow{ flow_mm3_per_mm, float(flow_width), surface_fill.params.flow.height() }
});
//w21
if (surface_fill.params.pattern == ipMonotonicLines && surface_fill.surface.surface_type == stTop) {
//w29
extrusion_entities_append_paths(eec->entities, std::move(polylines),
ExtrusionAttributes{surface_fill.params.extrusion_role,
ExtrusionFlow{flow_mm3_per_mm, float(flow_width),
surface_fill.params.flow.height()}});
// w21
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 gapfill_areas = union_ex(unextruded_areas);
ExPolygons gapfill_areas = union_ex(unextruded_areas);
if (!f->no_overlap_expolygons.empty())
gapfill_areas = intersection_ex(gapfill_areas, f->no_overlap_expolygons);
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();
ExPolygons gaps_ex = diff_ex(opening_ex(gapfill_areas, float(min / 2.)),
offset2_ex(gapfill_areas, -float(max / 2.), float(max / 2. + ClipperSafetyOffset)));
Points ordering_points;
Points ordering_points;
ordering_points.reserve(gaps_ex.size());
ExPolygons gaps_ex_sorted;
gaps_ex_sorted.reserve(gaps_ex.size());
@@ -674,7 +687,8 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
}),
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));
}
@@ -683,8 +697,9 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
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()));
}
}
}
}
}
for (LayerSlice &lslice : this->lslices_ex)
@@ -978,6 +993,8 @@ void Layer::make_ironing()
// First classify regions based on the extruder used.
struct IroningParams {
//w33
InfillPattern pattern;
int extruder = -1;
bool just_infill = false;
// 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 {
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->angle == rhs.angle;
this->angle == rhs.angle
//w33
&& this->pattern == rhs.pattern;
}
LayerRegion *layerm;
@@ -1068,27 +1087,48 @@ void Layer::make_ironing()
ironing_params.angle = config.fill_angle * M_PI / 180.;
ironing_params.layerm = layerm;
ironing_params.region_id = region_id;
//w33
ironing_params.pattern = config.ironing_pattern;
by_extruder.emplace_back(ironing_params);
}
}
std::sort(by_extruder.begin(), by_extruder.end());
FillRectilinear fill;
//w33
//FillRectilinear fill;
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() returns layer ID including raft layers, subtract them to make the infill direction independent
// from raft.
//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();
fill.z = this->print_z;
fill.overlap = 0;
//w33
//fill.layer_id = this->id() - this->object()->get_layer(0)->id();
//fill.z = this->print_z;
//fill.overlap = 0;
fill_params.density = 1.;
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();) {
// Find span of regions equivalent to the ironing operation.
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;
for (++ j; j < by_extruder.size() && ironing_params == by_extruder[j]; ++ j) ;
@@ -1150,10 +1190,15 @@ void Layer::make_ironing()
}
// Create the filler object.
fill.spacing = ironing_params.line_spacing;
fill.angle = float(ironing_params.angle + 0.25 * M_PI);
fill.link_max_length = (coord_t)scale_(3. * fill.spacing);
double extrusion_height = ironing_params.height * fill.spacing / nozzle_dmr;
//w33
//fill.spacing = ironing_params.line_spacing;
//fill.angle = float(ironing_params.angle + 0.25 * M_PI);
//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));
double flow_mm3_per_mm = nozzle_dmr * extrusion_height;
Surface surface_fill(stTop, ExPolygon());
@@ -1162,7 +1207,9 @@ void Layer::make_ironing()
Polylines polylines;
try {
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 &) {
}
if (! polylines.empty()) {

View File

@@ -6,6 +6,40 @@
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
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)
// Note: a negative offset only causes a change in the perpendicular
// 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;
points.push_back(baseLocation - offset2);
for (size_t i = 0; i < gridLength; ++i) {
points.push_back(baseLocation + i + offset2);
points.push_back(baseLocation + i + 1 - offset2);
//w36
points.push_back(baseLocation);
for (coordf_t cLoc = baseLocation; cLoc < gridLength; cLoc += (gridSize * 2)) {
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;
}
// 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)
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.);
coord_t side = 2 * (baseLocation & 1) - 1;
//w36
std::vector<coordf_t> points;
points.push_back(baseLocation - offset2 * side);
for (size_t i = 0; i < gridLength; ++i) {
side = 2*((i+baseLocation) & 1) - 1;
points.push_back(baseLocation + offset2 * side);
points.push_back(baseLocation + offset2 * side);
//w36
points.push_back(offsetBase);
for (coordf_t cLoc = baseLocation; cLoc < gridLength; cLoc += gridSize * 2) {
for (size_t pi = 0; pi < critPoints.size(); pi++) {
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;
}
@@ -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.
// curveType specifies which lines to print, 1 for vertical lines
// (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
coordf_t octagramGap = coordf_t(0.5);
// sawtooth wave function for range f($z) = [-$octagramGap .. $octagramGap]
coordf_t a = std::sqrt(coordf_t(2.)); // period
coordf_t wave = fabs(fmod(z, a) - a/2.)/a*4. - 1.;
coordf_t offset = wave * octagramGap;
std::vector<Pointfs> points;
if ((curveType & 1) != 0) {
for (size_t x = 0; x <= gridWidth; ++x) {
//w36
std::vector<Pointfs> points;
std::vector<coordf_t> critPoints = getCriticalPoints(Zpos, gridSize);
coordf_t zCycle = fmod(Zpos + gridSize / 2, gridSize * 2.) / (gridSize * 2.);
bool printVert = zCycle < 0.5;
if (printVert) {
int perpDir = -1;
for (coordf_t x = 0; x <= (boundsX); x += gridSize, perpDir *= -1) {
points.push_back(Pointfs());
Pointfs &newPoints = points.back();
newPoints = zip(
perpendPoints(offset, x, gridHeight),
colinearPoints(offset, 0, gridHeight));
// trim points to grid edges
trim(newPoints, coordf_t(0.), coordf_t(0.), coordf_t(gridWidth), coordf_t(gridHeight));
if (x & 1)
newPoints = zip(perpendPoints(Zpos, gridSize, critPoints, 0, boundsY, x, perpDir),
colinearPoints(Zpos, gridSize, critPoints, 0, boundsY));
if (perpDir == 1)
std::reverse(newPoints.begin(), newPoints.end());
}
}
if ((curveType & 2) != 0) {
for (size_t y = 0; y <= gridHeight; ++y) {
} else {
int perpDir = 1;
for (coordf_t y = gridSize; y <= (boundsY); y += gridSize, perpDir *= -1) {
points.push_back(Pointfs());
Pointfs &newPoints = points.back();
newPoints = zip(
colinearPoints(offset, 0, gridWidth),
perpendPoints(offset, y, gridWidth));
// trim points to grid edges
trim(newPoints, coordf_t(0.), coordf_t(0.), coordf_t(gridWidth), coordf_t(gridHeight));
if (y & 1)
newPoints = zip(colinearPoints(Zpos, gridSize, critPoints, 0, boundsX),
perpendPoints(Zpos, gridSize, critPoints, 0, boundsX, y, perpDir));
if (perpDir == -1)
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
// horizontal slice of a truncated regular octahedron with a specified
// 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;
coordf_t normalisedZ = coordf_t(z) / coordf_t(scaleFactor);
std::vector<Pointfs> polylines = makeNormalisedGrid(normalisedZ, gridWidth, gridHeight, curveType);
Polylines result;
//w36
std::vector<Pointfs> polylines = makeActualGrid(z, gridSize, boundWidth, boundHeight);
Polylines result;
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());
Polyline &polyline = result.back();
for (Pointfs::const_iterator it = it_polylines->begin(); it != it_polylines->end(); ++ it)
polyline.points.push_back(Point(coord_t((*it)(0) * scaleFactor), coord_t((*it)(1) * scaleFactor)));
//w36
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;
}
@@ -141,34 +182,67 @@ void Fill3DHoneycomb::_fill_surface_single(
Polylines &polylines_out)
{
// 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();
coord_t distance = coord_t(scale_(this->spacing) / params.density);
//w36
// 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)
bb.merge(align_to_grid(bb.min, Point(2*distance, 2*distance)));
// 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);
//w36
coordf_t zScale = sqrt(2);
coordf_t gridSize = (scale_(this->spacing) * ((zScale + 1.) / 2.) / params.density);
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
for (Polyline &pl : polylines)
pl.translate(bb.min);
for (Polyline &pl : polylines) {
pl.translate(bb.min);
}
// 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 (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);
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

View File

@@ -16,7 +16,8 @@ public:
~Fill3DHoneycomb() override {}
// require bridge flow since most of this pattern hangs in air
bool use_bridge_flow() const override { return true; }
//w36
protected:
void _fill_surface_single(

View File

@@ -21,6 +21,10 @@
#include "FillAdaptive.hpp"
#include "FillLightning.hpp"
#include "FillEnsuring.hpp"
//w29
#include "FillConcentricInternal.hpp"
//w32
#include "FillCrossHatch.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 ipEnsuring: return new FillEnsuring();
//w14
case ipConcentricInternal: return new FillConcentric();
//w29
case ipConcentricInternal: return new FillConcentricInternal();
//w32
case ipCrossHatch: return new FillCrossHatch();
default: throw Slic3r::InvalidArgument("unknown type");
}
}
@@ -105,6 +112,157 @@ ThickPolylines Fill::fill_surface_arachne(const Surface *surface, const FillPara
return thick_polylines_out;
}
//w29
void Fill::fill_surface_extrusion(const Surface *surface, const FillParams &params, 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,
// the first and last line being centered at the interval ends.
// This function possibly increases the spacing, never decreases,

View File

@@ -15,6 +15,9 @@
#include "../Utils.hpp"
#include "../ExPolygon.hpp"
#include "../PrintConfig.hpp"
//w29
#include "../ExtrusionEntity.hpp"
#include "../ExtrusionEntityCollection.hpp"
namespace Slic3r {
@@ -63,6 +66,11 @@ struct FillParams
bool use_arachne { false };
// Layer height for Concentric infill with Arachne.
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).");
@@ -116,6 +124,13 @@ public:
// Perform the fill.
virtual Polylines fill_surface(const Surface *surface, const FillParams &params);
virtual ThickPolylines fill_surface_arachne(const Surface *surface, const FillParams &params);
//w29
virtual void fill_surface_extrusion(const Surface *surface, const FillParams &params, 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:
Fill() :

View 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 &params,
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

View 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 &params,
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_

View 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

View 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_

View File

@@ -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 *USE_SURFACE_ATTR = "use_surface";
// static constexpr const char *FIX_TRANSFORMATION_ATTR = "transform";
const unsigned int VALID_OBJECT_TYPES_COUNT = 1;
const char* VALID_OBJECT_TYPES[] =
{
@@ -336,6 +338,7 @@ namespace Slic3r {
class _3MF_Importer : public _3MF_Base
{
typedef std::pair<std::string, int> PathId;
struct Component
{
PathId object_id;
@@ -476,7 +479,6 @@ namespace Slic3r {
typedef std::map<int, CutObjectInfo> IdToCutObjectInfoMap;
typedef std::map<int, std::vector<sla::SupportPoint>> IdToSlaSupportPointsMap;
typedef std::map<int, std::vector<sla::DrainHole>> IdToSlaDrainHolesMap;
using PathToEmbossShapeFileMap = std::map<std::string, std::shared_ptr<std::string>>;
// Version of the 3mf file
unsigned int m_version;
@@ -554,6 +556,7 @@ namespace Slic3r {
// handlers to parse the .rels file
void _handle_start_relationships_element(const char* name, const char** attributes);
bool _handle_start_relationship(const char **attributes, unsigned int num_attributes);
// handlers to parse the .model file
void _handle_start_model_xml_element(const char* name, const char** attributes);
void _handle_end_model_xml_element(const char* name);
@@ -627,6 +630,7 @@ namespace Slic3r {
// callbacks to parse the .rels file
static void XMLCALL _handle_start_relationships_element(void *userData, const char *name, const char **attributes);
// 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_end_model_xml_element(void* userData, const char* name);
@@ -724,6 +728,7 @@ namespace Slic3r {
m_model_path = MODEL_FILE;
_extract_relationships_from_archive(archive, stat);
bool found_model = false;
// we first loop the entries to read from the .model files which are not root
for (mz_uint i = 0; i < num_entries; ++i) {
if (mz_zip_reader_file_stat(&archive, i, &stat)) {
@@ -754,6 +759,7 @@ namespace Slic3r {
}
}
}
// Read root model file
if (start_part_stat.m_file_index < num_entries) {
try {
@@ -1045,6 +1051,7 @@ namespace Slic3r {
bool _3MF_Importer::_is_svg_shape_file(const std::string &name) const {
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)
{
if (stat.m_uncomp_size == 0) {
@@ -1502,6 +1509,7 @@ namespace Slic3r {
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)
{
if (stat.m_uncomp_size == 0) {
@@ -1634,7 +1642,8 @@ namespace Slic3r {
}
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)
return;
@@ -1775,6 +1784,7 @@ namespace Slic3r {
{
if (!m_model_path.empty())
return true;
// deletes all non-built or non-instanced objects
for (const IdToModelObjectMap::value_type& object : m_objects) {
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_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;
}
@@ -1983,9 +1997,10 @@ namespace Slic3r {
{
std::string path = get_attribute_value_string(attributes, num_attributes, PPATH_ATTR);
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));
PathId path_id { path, object_id };
IdToModelObjectMap::iterator object_item = m_objects.find(path_id);
if (object_item == m_objects.end()) {
@@ -2096,7 +2111,7 @@ namespace Slic3r {
{
public:
TextConfigurationSerialization() = delete;
using TypeToName = boost::bimap<EmbossStyle::Type, std::string_view>;
static const TypeToName type_to_name;
@@ -2131,11 +2146,11 @@ namespace Slic3r {
{
IdToMetadataMap::iterator object = m_objects_metadata.find(m_curr_config.object_id);
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;
}
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;
}
ObjectMetadata::VolumeMetadata& volume = object->second.volumes.back();
@@ -2470,11 +2485,11 @@ namespace Slic3r {
volume->supported_facets.shrink_to_fit();
volume->seam_facets.shrink_to_fit();
volume->mm_segmentation_facets.shrink_to_fit();
if (auto &es = volume_data.shape_configuration; es.has_value())
volume->emboss_shape = std::move(es);
if (auto &tc = volume_data.text_configuration; tc.has_value())
volume->text_configuration = std::move(tc);
// apply the remaining volume's metadata
for (const Metadata& metadata : volume_data.metadata) {
@@ -3550,10 +3565,11 @@ namespace Slic3r {
for (const std::string& key : volume->config.keys()) {
stream << " <" << METADATA_TAG << " " << TYPE_ATTR << "=\"" << VOLUME_TYPE << "\" " << KEY_ATTR << "=\"" << key << "\" " << VALUE_ATTR << "=\"" << volume->config.opt_serialize(key) << "\"/>\n";
}
if (const std::optional<EmbossShape> &es = volume->emboss_shape;
es.has_value())
to_xml(stream, *es, *volume, archive);
if (const std::optional<TextConfiguration> &tc = volume->text_configuration;
tc.has_value())
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
/// <summary>
/// TextConfiguration serialization
/// </summary>
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::wx_win_font_descr, "wxFontDescriptor_Windows")
(EmbossStyle::Type::wx_lin_font_descr, "wxFontDescriptor_Linux")
@@ -3780,6 +3797,8 @@ const TextConfigurationSerialization::VerticalAlignToName TextConfigurationSeria
(FontProp::VerticalAlign::top, "top")
(FontProp::VerticalAlign::center, "middle")
(FontProp::VerticalAlign::bottom, "bottom");
void TextConfigurationSerialization::to_xml(std::stringstream &stream, const TextConfiguration &tc)
{
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){
std::string horizontal_align_str = get_attribute_value_string(attributes, num_attributes, HORIZONTAL_ALIGN_ATTR);
// Back compatibility
// PS 2.6.0 do not have align
if (horizontal_align_str.empty())
@@ -3838,10 +3858,11 @@ FontProp::HorizontalAlign read_horizontal_align(const char **attributes, unsigne
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))
return static_cast<FontProp::HorizontalAlign>(horizontal_align_int);
}
}
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){
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);
}
}
} // namespace
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(
read_horizontal_align(attributes, num_attributes, horizontal_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);
if (collection_number > 0) fp.collection_number = static_cast<unsigned int>(collection_number);

File diff suppressed because it is too large Load Diff

View File

@@ -166,6 +166,7 @@ public:
std::optional<Point> last_position;
private:
class GCodeOutputStream {
public:
@@ -455,6 +456,9 @@ private:
// Processor
GCodeProcessor m_processor;
//Y27
bool m_resonance_avoidance;
// Back-pointer to Print (const).
const Print* m_print;
std::string _extrude(
@@ -465,6 +469,13 @@ private:
// On the first printing layer. This flag triggers first layer speeds.
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.
bool object_layer_over_raft() const { return m_object_layer_over_raft; }

View File

@@ -236,6 +236,8 @@ struct PerExtruderAdjustments
float slowdown_below_layer_time = 0.f;
// Minimum print speed allowed for this extruder.
float min_print_speed = 0.f;
//Y28
bool dont_slow_down_outer_wall = true;
// Parsed 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.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));
//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;
}
@@ -424,7 +428,12 @@ std::vector<PerExtruderAdjustments> CoolingBuffer::parse_layer_gcode(const std::
line.type |= CoolingLine::TYPE_EXTERNAL_PERIMETER;
if (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;
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]() {
#define EXTRUDER_CONFIG(OPT) m_config.OPT.get_at(m_current_extruder)
int min_fan_speed = EXTRUDER_CONFIG(min_fan_speed);
//B15
int enable_auxiliary_fan = EXTRUDER_CONFIG(enable_auxiliary_fan);
//B15//Y26
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
int enable_volume_fan = EXTRUDER_CONFIG(enable_volume_fan);
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 };
int disable_fan_first_layers = EXTRUDER_CONFIG(disable_fan_first_layers);
//B39
int disable_rapid_cooling_fan_first_layers = EXTRUDER_CONFIG(disable_rapid_cooling_fan_first_layers);
// Is the fan speed ramp enabled?
int full_fan_speed_layer = EXTRUDER_CONFIG(full_fan_speed_layer);
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();
}
}
//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) {
m_fan_speed = fan_speed_new;
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);
return custom_fan_speed_limits;
};

View File

@@ -683,7 +683,10 @@ void Layer::make_perimeters()
&& config.infill_overlap == other_config.infill_overlap
&& config.fuzzy_skin == other_config.fuzzy_skin
&& 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_ids.push_back(it - m_regions.begin());

View File

@@ -114,6 +114,8 @@ void LayerRegion::make_perimeters(
Polygons lower_layer_polygons_cache;
//w16
Polygons upper_layer_polygons_cache;
//w38
params.lower_slices = lower_slices;
for (const Surface &surface : slices) {
auto perimeters_begin = uint32_t(m_perimeters.size());
@@ -137,7 +139,9 @@ void LayerRegion::make_perimeters(
m_thin_fills,
fill_expolygons,
//w21
fill_no_overlap_expolygons);
fill_no_overlap_expolygons,
//w23
this->layer()->id());
else
PerimeterGenerator::process_arachne(
// input:
@@ -152,7 +156,9 @@ void LayerRegion::make_perimeters(
m_thin_fills,
fill_expolygons,
//w21
fill_no_overlap_expolygons);
fill_no_overlap_expolygons,
//w23
this->layer()->id());
else
PerimeterGenerator::process_classic(
@@ -169,7 +175,9 @@ void LayerRegion::make_perimeters(
m_thin_fills,
fill_expolygons,
//w21
fill_no_overlap_expolygons);
fill_no_overlap_expolygons,
//w23
this->layer()->id());
perimeter_and_gapfill_ranges.emplace_back(
ExtrusionRange{ perimeters_begin, uint32_t(m_perimeters.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,
// detect bridges.
// Trim "shells" by the expanded bridges.
Surfaces expand_bridges_detect_orientations(
Surfaces &surfaces,
std::vector<ExpansionZone>& expansion_zones,
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)
{
using namespace Slic3r::Algorithm;
double thickness;
ExPolygons bridge_expolygons = fill_surfaces_extract_expolygons(surfaces, {stBottomBridge}, thickness);
if (bridge_expolygons.empty())
//w36
double thickness;
ExPolygons bridges_ex = fill_surfaces_extract_expolygons(surfaces, {stBottomBridge}, thickness);
if (bridges_ex.empty())
return {};
// Calculate bridge anchors and their expansions in their respective shell region.
ExpansionResult expansion_result{expand_expolygons(
bridge_expolygons,
expansion_zones
)};
//w36
WaveSeeds bridge_anchors = wave_seeds(bridges_ex, shells, expansion_params_into_solid_infill.tiny_expansion, true);
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(
std::move(bridge_expolygons),
expansion_result.expansions
)};
bridge_expolygons.clear();
// Cache for detecting bridge orientation and merging regions with overlapping expansions.
struct Bridge
{
ExPolygon expolygon;
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);
detect_bridge_directions(expansion_result.anchors, bridges, expansion_zones);
// Group the bridge surfaces by overlaps.
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.
std::sort(expansion_result.expansions.begin(), expansion_result.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);
});
Surfaces out{merge_bridges(bridges, expansion_result.expansions, closing_radius)};
//w36
Surfaces out;
{
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.
for (ExpansionZone& expansion_zone : expansion_zones)
if (expansion_zone.expanded_into)
expansion_zone.expolygons = diff_ex(expansion_zone.expolygons, out);
//w36
if (expanded_into_shells)
shells = diff_ex(shells, out);
if (expanded_into_sparse)
sparse = diff_ex(sparse, out);
return out;
}
Surfaces expand_merge_surfaces(
Surfaces &surfaces,
SurfaceType surface_type,
std::vector<ExpansionZone>& expansion_zones,
const float closing_radius,
const double bridge_angle
)
//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 )
{
using namespace Slic3r::Algorithm;
double thickness;
double thickness;
ExPolygons src = fill_surfaces_extract_expolygons(surfaces, {surface_type}, thickness);
if (src.empty())
return {};
unsigned processed_expolygons_count = 0;
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();
//w36
for (RegionExpansion &expansion : zone_expansions)
expansion.boundary_id += processed_expolygons_count;
processed_expolygons_count += expansion_zone.expolygons.size();
append(expansions, std::move(zone_expansions));
std::vector<RegionExpansion> expansions = propagate_waves(src, shells, expansion_params_into_solid_infill);
bool expanded_into_shells = !expansions.empty();
bool expanded_into_sparse = false;
{
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));
//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.
// look for narrow_ensure_vertical_wall_thickness_region_radius filter.
expanded = closing_ex(expanded, closing_radius);
// Trim the zones by the expanded expolygons.
for (ExpansionZone& expansion_zone : expansion_zones)
if (expansion_zone.expanded_into)
expansion_zone.expolygons = diff_ex(expansion_zone.expolygons, expanded);
// Trim the shells by the expanded expolygons.
//w36
if (expanded_into_shells)
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;
Surfaces out;
out.reserve(expanded.size());
@@ -516,52 +679,54 @@ void LayerRegion::process_external_surfaces(const Layer *lower_layer, const Poly
#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
// Width of the perimeters.
float shell_width = 0;
float shell_width = 0;
float expansion_min = 0;
if (int num_perimeters = this->region().config().perimeters; num_perimeters > 0) {
Flow external_perimeter_flow = this->flow(frExternalPerimeter);
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);
expansion_min = perimeter_flow.scaled_spacing();
} else {
// TODO: Maybe there is better solution when printing with zero perimeters, but this works reasonably well, given the situation
shell_width = float(SCALED_EPSILON);
expansion_min = float(SCALED_EPSILON);;
expansion_min = float(SCALED_EPSILON);
;
}
// Scaled expansions of the respective external surfaces.
float expansion_top = shell_width * sqrt(2.);
float expansion_bottom = expansion_top;
float expansion_bottom_bridge = expansion_top;
float expansion_top = shell_width * sqrt(2.);
float expansion_bottom = 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.
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.
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;
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;
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.
double layer_thickness;
ExPolygons shells = union_ex(fill_surfaces_extract_expolygons(m_fill_surfaces.surfaces, { stInternalSolid }, layer_thickness));
ExPolygons sparse = union_ex(fill_surfaces_extract_expolygons(m_fill_surfaces.surfaces, { stInternal }, layer_thickness));
ExPolygons top_expolygons = union_ex(fill_surfaces_extract_expolygons(m_fill_surfaces.surfaces, { stTop }, 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},
};
//w36
ExPolygons shells = union_ex(fill_surfaces_extract_expolygons(m_fill_surfaces.surfaces, {stInternalSolid}, layer_thickness));
ExPolygons sparse = union_ex(fill_surfaces_extract_expolygons(m_fill_surfaces.surfaces, {stInternal}, layer_thickness));
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;
const double custom_angle = this->region().config().bridge_angle.value;
bridges.surfaces = custom_angle > 0 ?
expand_merge_surfaces(m_fill_surfaces.surfaces, stBottomBridge, expansion_zones, closing_radius, Geometry::deg2rad(custom_angle)) :
expand_bridges_detect_orientations(m_fill_surfaces.surfaces, expansion_zones, closing_radius);
//w36
const double custom_angle = this->region().config().bridge_angle.value;
const auto expansion_params_into_solid_infill = RegionExpansionParameters::build(expansion_bottom_bridge, expansion_step,
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";
#if 0
{
@@ -570,37 +735,30 @@ void LayerRegion::process_external_surfaces(const Layer *lower_layer, const Poly
}
#endif
}
//w36
m_fill_surfaces.remove_types({ stTop });
{
Surface top_templ(stTop, {});
top_templ.thickness = layer_thickness;
m_fill_surfaces.append(std::move(expansion_zones.back().expolygons), top_templ);
}
Surfaces bottoms = expand_merge_surfaces(m_fill_surfaces.surfaces, stBottom, shells,
RegionExpansionParameters::build(expansion_bottom, expansion_step, max_nr_expansion_steps),
sparse, expansion_params_into_sparse_infill, closing_radius);
Surfaces tops = expand_merge_surfaces(m_fill_surfaces.surfaces, stTop, shells,
RegionExpansionParameters::build(expansion_top, expansion_step, max_nr_expansion_steps), sparse,
expansion_params_into_sparse_infill, closing_radius);
expansion_zones.pop_back();
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.remove_types({ stBottomBridge, stBottom, stTop, stInternal, stInternalSolid });
m_fill_surfaces.clear();
unsigned zones_expolygons_count = 0;
for (const ExpansionZone& zone : expansion_zones)
zones_expolygons_count += zone.expolygons.size();
reserve_more(m_fill_surfaces.surfaces, zones_expolygons_count + bridges.size() + bottoms.size() + tops.size());
//w36
reserve_more(m_fill_surfaces.surfaces, shells.size() + sparse.size() + bridges.size() + bottoms.size() + tops.size());
{
Surface solid_templ(stInternalSolid, {});
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, {});
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(bottoms));

View File

@@ -205,23 +205,44 @@ struct ExpansionZone {
* detect bridges.
* Trim "shells" by the expanded bridges.
*/
Surfaces expand_bridges_detect_orientations(
// w36
/* Surfaces expand_bridges_detect_orientations(
Surfaces &surfaces,
std::vector<ExpansionZone>& expansion_zones,
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.
* Trim "shells" by the expanded bridges.
*/
Surfaces expand_merge_surfaces(
// w36
/* Surfaces expand_merge_surfaces(
Surfaces &surfaces,
SurfaceType surface_type,
std::vector<ExpansionZone>& expansion_zones,
const float closing_radius,
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.);
}

View File

@@ -888,6 +888,16 @@ const BoundingBoxf3& ModelObject::bounding_box_approx() const
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.
// This bounding box is approximate and not snug.
const BoundingBoxf3& ModelObject::bounding_box_exact() const

View File

@@ -1158,6 +1158,8 @@ public:
const Transform3d& get_matrix() const { return m_transformation.get_matrix(); }
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); }
void invalidate_object_bounding_box() { object->invalidate_bounding_box(); }

View File

@@ -285,12 +285,62 @@ static void fuzzy_extrusion_line(Arachne::ExtrusionLine &ext_lines, double fuzzy
using PerimeterGeneratorLoops = std::vector<PerimeterGeneratorLoop>;
static ExtrusionEntityCollection traverse_loops_classic(const PerimeterGenerator::Parameters &params, 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 &params, 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
// turn each one into an ExtrusionLoop object
ExtrusionEntityCollection coll;
Polygon fuzzified;
//w38
bool overhangs_reverse = params.config.overhang_reverse &&
params.layer_id % 2 == 1;
for (const PerimeterGeneratorLoop &loop : loops) {
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
// also when loop is both internal and external (i.e.
// there's only one contour loop).
loop_role = elrContourInternalPerimeter;
//w38
loop_role = elrInternal;//loop_role = elrContourInternalPerimeter;
} else {
loop_role = elrDefault;
//w38
loop_role = loop.is_contour? elrDefault : elrHole;//loop_role = elrDefault;
}
// detect overhanging/bridging perimeters
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;
if (loop.fuzzify) {
fuzzified = loop.polygon;
@@ -318,6 +379,19 @@ static ExtrusionEntityCollection traverse_loops_classic(const PerimeterGenerator
params.object_config.support_material_contact_distance.value == 0)) {
BoundingBox bbox(polygon.points);
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);
// get non-overhang paths by intersecting this loop with the grown lower slices
extrusion_paths_append(
@@ -381,10 +455,13 @@ static ExtrusionEntityCollection traverse_loops_classic(const PerimeterGenerator
} else {
const PerimeterGeneratorLoop &loop = loops[idx.first];
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);
ExtrusionLoop *eloop = static_cast<ExtrusionLoop*>(coll.entities[idx.first]);
coll.entities[idx.first] = nullptr;
//w38
//eloop->make_counter_clockwise();
if (loop.is_contour) {
if (eloop->is_clockwise())
eloop->reverse_loop();
@@ -505,8 +582,16 @@ struct PerimeterGeneratorArachneExtrusion
bool fuzzify = false;
};
static ExtrusionEntityCollection traverse_extrusions(const PerimeterGenerator::Parameters &params, 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;
for (PerimeterGeneratorArachneExtrusion &pg_extrusion : pg_extrusions) {
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,
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
// outside the grown lower slices (thus where the distance between
// 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
// or the end of the extrusions to make one continuous line. Also, we prefer a non-overhang
// starting point.
//w38
//ExtrusionLoop extrusion_loop(std::move(paths), pg_extrusion.is_contour ? elrDefault : elrHole);
//extrusion_loop.make_counter_clockwise();
struct PointInfo
{
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
// "A framework for adaptive width control of dense contour-parallel toolpaths in fused deposition modeling"
void PerimeterGenerator::process_arachne(
@@ -1123,7 +1272,9 @@ void PerimeterGenerator::process_arachne(
// Infills without the gap fills
ExPolygons &out_fill_expolygons,
//w21
ExPolygons &out_fill_no_overlap)
ExPolygons &out_fill_no_overlap,
//w23
const size_t layer_id)
{
// other perimeters
coord_t perimeter_spacing = params.perimeter_flow.scaled_spacing();
@@ -1147,14 +1298,27 @@ void PerimeterGenerator::process_arachne(
// extra perimeters for each one
// detect how many perimeters must be generated for this island
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);
//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;
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);
//w39
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();
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);
}
ExPolygons infill_contour = union_ex(wallToolPaths.getInnerContour());
//w17
@@ -1388,9 +1559,11 @@ void PerimeterGenerator::process_with_one_wall_arachne(
// Gaps without the thin walls
ExtrusionEntityCollection & /* out_gap_fill */,
// Infills without the gap fills
ExPolygons &out_fill_expolygons,
ExPolygons &out_fill_expolygons,
//w21
ExPolygons &out_fill_no_overlap)
ExPolygons &out_fill_no_overlap,
//w23
const size_t layer_id)
{
// other perimeters
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);
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);
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
// detect how many perimeters must be generated for this island
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);
int remain_loops = -1;
@@ -1429,8 +1618,8 @@ void PerimeterGenerator::process_with_one_wall_arachne(
loop_number = 0;
}
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);
//w39
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();
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);
}
//w16
@@ -1771,7 +1967,9 @@ void PerimeterGenerator::process_classic(
// Infills without the gap fills
ExPolygons &out_fill_expolygons,
//w21
ExPolygons &out_fill_no_overlap)
ExPolygons &out_fill_no_overlap,
//w23
const size_t layer_id)
{
// other perimeters
coord_t perimeter_width = params.perimeter_flow.scaled_width();
@@ -1779,7 +1977,13 @@ void PerimeterGenerator::process_classic(
// external perimeters
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_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
coord_t solid_infill_spacing = params.solid_infill_flow.scaled_spacing();
@@ -1817,11 +2021,13 @@ void PerimeterGenerator::process_classic(
ExPolygons top_fills;
//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);
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;
if (loop_number >= 0) {
// 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]
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
// we continue inwards after having finished the brim
// TODO: add test for perimeter order
@@ -2102,7 +2312,7 @@ void PerimeterGenerator::process_classic(
if (!top_fills.empty()) {
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
{
ExPolygons polyWithoutOverlap;

View File

@@ -39,7 +39,9 @@ struct Parameters {
scaled_resolution(scaled<double>(print_config.gcode_resolution.value)),
mm3_per_mm(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 PrintObjectConfig &object_config;
const PrintConfig &print_config;
//w38
const ExPolygons * lower_slices;
// Derived parameters
bool spiral_vase;
@@ -83,7 +87,9 @@ void process_classic(
// Infills without the gap fills
ExPolygons &out_fill_expolygons,
//w21
ExPolygons &out_fill_no_overlap);
ExPolygons &out_fill_no_overlap,
//w23
const size_t layer_id );
void process_arachne(
// Inputs:
@@ -100,9 +106,11 @@ void process_arachne(
// Gaps without the thin walls
ExtrusionEntityCollection &out_gap_fill,
// Infills without the gap fills
ExPolygons &out_fill_expolygons,
ExPolygons &out_fill_expolygons,
//w21
ExPolygons &out_fill_no_overlap);
ExPolygons &out_fill_no_overlap,
//w23
const size_t layer_id);
void process_with_one_wall_arachne(
// Inputs:
@@ -120,9 +128,11 @@ void process_with_one_wall_arachne(
// Gaps without the thin walls
ExtrusionEntityCollection &out_gap_fill,
// Infills without the gap fills
ExPolygons &out_fill_expolygons,
ExPolygons &out_fill_expolygons,
//w21
ExPolygons &out_fill_no_overlap);
ExPolygons &out_fill_no_overlap,
//w23
const size_t layer_id);
//w16
void add_infill_contour_for_arachne(ExPolygons infill_contour,

View File

@@ -81,6 +81,52 @@ Points collect_duplicates(Points pts /* Copy */)
}
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>
BoundingBox get_extents(const Points &pts)

View File

@@ -212,6 +212,10 @@ public:
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 angle, const Point &center) 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)

View File

@@ -113,6 +113,47 @@ void Polyline::simplify(double 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
// This method simplifies all *lines* contained in the supplied area
template <class T>

View File

@@ -81,6 +81,8 @@ public:
using iterator = Points::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; }

View File

@@ -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",
"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",
"wall_distribution_count", "min_feature_size", "min_bead_width"
"wall_distribution_count", "min_feature_size", "min_bead_width",
//B36
,"first_layer_travel_speed"
"first_layer_travel_speed",
//B37
,"first_layer_infill_speed"
"first_layer_infill_speed",
//w11
,"detect_narrow_internal_solid_infill"
"detect_narrow_internal_solid_infill",
//Y21
,"seam_gap"
"seam_gap",
//w16
, "top_one_wall_type"
"top_one_wall_type",
//w17
,"top_area_threshold"
"top_area_threshold",
//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 {
@@ -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",
//B15
"enable_auxiliary_fan",
//Y26
"enable_auxiliary_fan_unseal",
//B24
"volume_temperature",
//B25
@@ -515,6 +537,10 @@ static std::vector<std::string> s_Preset_filament_options {
"disable_rapid_cooling_fan_first_layers",
//Y23
"filament_shrink",
//Y26
"seal_print",
//Y28
"dont_slow_down_outer_wall",
//w15
"filament_wipe_distance"
};

View File

@@ -179,7 +179,8 @@ void PresetBundle::setup_directories()
data_dir / "sla_print",
data_dir / "sla_material",
data_dir / "printer",
data_dir / "physical_printer"
data_dir / "physical_printer",
data_dir / "user" // y5
#endif
};
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_material",
from_data_dir / "printer",
from_data_dir / "physical_printer"
from_data_dir / "physical_printer",
from_data_dir / "user" //y5
#endif
};
// 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");
}
// 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

View File

@@ -190,6 +190,9 @@ public:
return { Preset::TYPE_PRINTER, Preset::TYPE_SLA_PRINT, Preset::TYPE_SLA_MATERIAL };
}
//y3
std::set<std::string> get_vendors();
private:
std::pair<PresetsConfigSubstitutions, std::string> load_system_presets(ForwardCompatibilitySubstitutionRule compatibility_rule);
// Merge one vendor's presets with the other vendor's presets, report duplicates.

View File

@@ -83,6 +83,8 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
"disable_fan_first_layers",
//B39
"disable_rapid_cooling_fan_first_layers",
//Y28
"dont_slow_down_outer_wall",
"duplicate_distance",
"end_gcode",
"end_filament_gcode",
@@ -251,7 +253,9 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
|| opt_key == "first_layer_travel_speed"
//B37
|| 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(psSkirtBrim);
} 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) {
const PrintObject &print_object = *m_objects[print_object_idx];
//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) {
return
// Test whether the last slicing plane is below or above the print volume.

View File

@@ -270,7 +270,6 @@ public:
&& this->config().brim_width.value > 0.
&& ! this->has_raft();
}
// This is the *total* layer count (including support layers)
// this value is not supposed to be compared with Layer::id
// since they have different semantics.

Some files were not shown because too many files have changed in this diff Show More