Compare commits

..

72 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
172 changed files with 32233 additions and 1629 deletions

2
.gitignore vendored
View File

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

BIN
resources/icon.icns Normal file

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"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> <!-- Generator: Adobe Illustrator 25.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="图层_2" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" <svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 256 256" enable-background="new 0 0 256 256" xml:space="preserve"> viewBox="0 0 256 256" enable-background="new 0 0 256 256" xml:space="preserve">
<g> <g>
<path fill="#4479FB" d="M196,256H60c-33.1,0-60-26.9-60-60V60C0,26.9,26.9,0,60,0h136c33.1,0,60,26.9,60,60v136 <path fill="#FFFFFF" d="M60,252c-30.9,0-56-25.1-56-56V60C4,29.1,29.1,4,60,4h136c30.9,0,56,25.1,56,56v136c0,30.9-25.1,56-56,56
C256,229.1,229.1,256,196,256z"/> H60z"/>
</g> <g>
<g> <path fill="#303AB2" d="M196,8c28.7,0,52,23.3,52,52v136c0,28.7-23.3,52-52,52H60c-28.7,0-52-23.3-52-52V60C8,31.3,31.3,8,60,8
<path fill="#FFFFFF" d="M194.5,188.5c-7.6-3.5-15-7.5-22.2-11.8c-6.8-4.2-13.1-8.5-18.7-12.9c17.1-13.5,23.2-36.1,13.2-56.7 H196 M196,0H60C26.9,0,0,26.9,0,60v136c0,33.1,26.9,60,60,60h136c33.1,0,60-26.9,60-60V60C256,26.9,229.1,0,196,0L196,0z"/>
c-12.7-26.1-46.3-39.2-75.2-29.1c-31.6,11-41,43-25.8,68.7c-48.2-53.1,7.3-123.8,85-99.8c26.2,8.1,48.9,25.8,60.8,50.2 </g>
C227.4,129.7,219.5,165.3,194.5,188.5z"/>
</g>
<g>
<path fill="#FFFFFF" d="M34.7,158.5c17.6,36.2,59,57.6,100.3,54.8c-16.2-6.1-32-16-45-29c-7.8-7.8-13.8-16-18.2-24.2
c-9.1-6.3-16.9-14.3-23-23.6C37.5,118.9,34.6,99.6,39,82C24.6,104.1,21.9,132.2,34.7,158.5L34.7,158.5z"/>
</g>
<g>
<path fill="#FFFFFF" d="M234.5,206.6c-28.2,6.1-68-4.1-97.8-26.7c-35.1-26.6-43.5-60.9-19.9-78.1c-8,18.8,7,47.1,40.6,71.4
C181.1,190.4,209.2,202,234.5,206.6z"/>
</g>
<g>
<path fill="#FFFFFF" d="M187.4,212.9c-29.6,5.2-68.1-7.9-94.8-34.2c-33-32.6-35.5-73.3-5.5-90.8c12-7,27.4-9.2,43.6-7.3
c-4.7,1.3-9.2,3.1-13.2,5.4c-30,17.5-26.8,58.9,7.2,92.4C142.6,196.1,165.4,208.1,187.4,212.9L187.4,212.9z"/>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g> </g>
<path fill="#303AB2" d="M145,177.9v-13.2v-21.3c0-2.3,1.2-4.5,3.2-5.6l28.3-16.3l13-7.5V93c0-4.6-2.5-8.9-6.5-11.2l-57.8-33.4
c-4-2.3-8.9-2.3-13,0L54.5,81.8c-4,2.3-6.5,6.6-6.5,11.2v66.7c0,4.6,2.5,8.9,6.5,11.2l57.8,33.4c4,2.3,8.9,2.3,13,0l19.7-11.4l0,0
V177.9z M125.2,115.2c-4,2.3-6.5,6.6-6.5,11.2v55.4c0,5-5.4,8.1-9.7,5.6l-44.8-25.9c-2-1.2-3.2-3.3-3.2-5.6V96.7
c0-2.3,1.2-4.5,3.2-5.6l51.3-29.6c2-1.2,4.5-1.2,6.5,0l38.3,22.1c4.3,2.5,4.3,8.7,0,11.2L125.2,115.2z"/>
<path fill="#303AB2" d="M198.3,108.9l-8.8,5.1v18.2v1.8v22.1v7.5c0,2.3-1.2,4.4-3.2,5.5l0,0l-0.7,0.4l-0.9,0.5l-8.1,4.7l-5.2,3
L145,192.9l0,0v6.4v3.1v0.1c0,0,0,0,0,0v0.4c0.1,4.8,5.2,7.9,9.5,5.7l0.2-0.1l5.2-3l44.9-26c2-1.2,3.2-3.3,3.2-5.6v-59.4
C208,109.5,202.6,106.4,198.3,108.9z"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

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"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> <!-- Generator: Adobe Illustrator 25.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="图层_2" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" <svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 256 256" enable-background="new 0 0 256 256" xml:space="preserve"> viewBox="0 0 256 256" enable-background="new 0 0 256 256" xml:space="preserve">
<g> <g>
<path fill="#4479FB" d="M196,256H60c-33.1,0-60-26.9-60-60V60C0,26.9,26.9,0,60,0h136c33.1,0,60,26.9,60,60v136 <path fill="#FFFFFF" d="M60,252c-30.9,0-56-25.1-56-56V60C4,29.1,29.1,4,60,4h136c30.9,0,56,25.1,56,56v136c0,30.9-25.1,56-56,56
C256,229.1,229.1,256,196,256z"/> H60z"/>
</g> <g>
<g> <path fill="#303AB2" d="M196,8c28.7,0,52,23.3,52,52v136c0,28.7-23.3,52-52,52H60c-28.7,0-52-23.3-52-52V60C8,31.3,31.3,8,60,8
<path fill="#FFFFFF" d="M194.5,188.5c-7.6-3.5-15-7.5-22.2-11.8c-6.8-4.2-13.1-8.5-18.7-12.9c17.1-13.5,23.2-36.1,13.2-56.7 H196 M196,0H60C26.9,0,0,26.9,0,60v136c0,33.1,26.9,60,60,60h136c33.1,0,60-26.9,60-60V60C256,26.9,229.1,0,196,0L196,0z"/>
c-12.7-26.1-46.3-39.2-75.2-29.1c-31.6,11-41,43-25.8,68.7c-48.2-53.1,7.3-123.8,85-99.8c26.2,8.1,48.9,25.8,60.8,50.2 </g>
C227.4,129.7,219.5,165.3,194.5,188.5z"/>
</g>
<g>
<path fill="#FFFFFF" d="M34.7,158.5c17.6,36.2,59,57.6,100.3,54.8c-16.2-6.1-32-16-45-29c-7.8-7.8-13.8-16-18.2-24.2
c-9.1-6.3-16.9-14.3-23-23.6C37.5,118.9,34.6,99.6,39,82C24.6,104.1,21.9,132.2,34.7,158.5L34.7,158.5z"/>
</g>
<g>
<path fill="#FFFFFF" d="M234.5,206.6c-28.2,6.1-68-4.1-97.8-26.7c-35.1-26.6-43.5-60.9-19.9-78.1c-8,18.8,7,47.1,40.6,71.4
C181.1,190.4,209.2,202,234.5,206.6z"/>
</g>
<g>
<path fill="#FFFFFF" d="M187.4,212.9c-29.6,5.2-68.1-7.9-94.8-34.2c-33-32.6-35.5-73.3-5.5-90.8c12-7,27.4-9.2,43.6-7.3
c-4.7,1.3-9.2,3.1-13.2,5.4c-30,17.5-26.8,58.9,7.2,92.4C142.6,196.1,165.4,208.1,187.4,212.9L187.4,212.9z"/>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g> </g>
<path fill="#303AB2" d="M145,177.9v-13.2v-21.3c0-2.3,1.2-4.5,3.2-5.6l28.3-16.3l13-7.5V93c0-4.6-2.5-8.9-6.5-11.2l-57.8-33.4
c-4-2.3-8.9-2.3-13,0L54.5,81.8c-4,2.3-6.5,6.6-6.5,11.2v66.7c0,4.6,2.5,8.9,6.5,11.2l57.8,33.4c4,2.3,8.9,2.3,13,0l19.7-11.4l0,0
V177.9z M125.2,115.2c-4,2.3-6.5,6.6-6.5,11.2v55.4c0,5-5.4,8.1-9.7,5.6l-44.8-25.9c-2-1.2-3.2-3.3-3.2-5.6V96.7
c0-2.3,1.2-4.5,3.2-5.6l51.3-29.6c2-1.2,4.5-1.2,6.5,0l38.3,22.1c4.3,2.5,4.3,8.7,0,11.2L125.2,115.2z"/>
<path fill="#303AB2" d="M198.3,108.9l-8.8,5.1v18.2v1.8v22.1v7.5c0,2.3-1.2,4.4-3.2,5.5l0,0l-0.7,0.4l-0.9,0.5l-8.1,4.7l-5.2,3
L145,192.9l0,0v6.4v3.1v0.1c0,0,0,0,0,0v0.4c0.1,4.8,5.2,7.9,9.5,5.7l0.2-0.1l5.2-3l44.9-26c2-1.2,3.2-3.3,3.2-5.6v-59.4
C208,109.5,202.6,106.4,198.3,108.9z"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

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

File diff suppressed because it is too large Load Diff

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.", "l44": "Different filaments have different maximum volume speed.",
"l45": "Nozzle material, caliber, printing temperature, etc., will affect the maximum volume speed.", "l45": "Nozzle material, caliber, printing temperature, etc., will affect the maximum volume speed.",
"l46": "During the test, the printing speed will increase layer by layer. When there is a hole or missing wire on the surface of the model, it indicates that the layer has reached the maximum volume speed, and the maximum volume speed is calculated according to the ratio of height.", "l46": "During the test, the printing speed will increase layer by layer. When there is a hole or missing wire on the surface of the model, it indicates that the layer has reached the maximum volume speed, and the maximum volume speed is calculated according to the ratio of height.",
"l47": "Or you can find a solution through WIKI.",
}, },
"zh_CN": { "zh_CN": {
"t1": "用户指南", "t1": "用户指南",
@@ -134,6 +135,7 @@ var LangText={
"l44": "不同线材的最大体积速度各不相同。", "l44": "不同线材的最大体积速度各不相同。",
"l45": "喷嘴材质、口径、打印温度、等都会影响最大体积速度。", "l45": "喷嘴材质、口径、打印温度、等都会影响最大体积速度。",
"l46": "测试时打印速度会逐层增加,当模型表面出现空洞或缺丝时,说明该层已达到最大体积速度,根据高度比例算出最大体积速度。", "l46": "测试时打印速度会逐层增加,当模型表面出现空洞或缺丝时,说明该层已达到最大体积速度,根据高度比例算出最大体积速度。",
"l47": "或者你可以通过WIKI来找到解决方案。",
}, },
"ja": { "ja": {
"t1": "ユーザーガイド", "t1": "ユーザーガイド",
@@ -202,6 +204,7 @@ var LangText={
"l44": "最大体積速度は線材によって異なります。", "l44": "最大体積速度は線材によって異なります。",
"l45": "ノズルの材質、口径、印刷温度などが最大体積速度に影響します。", "l45": "ノズルの材質、口径、印刷温度などが最大体積速度に影響します。",
"l46": "テスト時の印刷速度は層ごとに増加します。模型の表面に穴ができたり、糸が欠けたりした場合、その層が最大体積速度に達したことを示し、高さの割合から最大体積速度を算出します。", "l46": "テスト時の印刷速度は層ごとに増加します。模型の表面に穴ができたり、糸が欠けたりした場合、その層が最大体積速度に達したことを示し、高さの割合から最大体積速度を算出します。",
"l47": "WIKIで解決策を見つけることもできます.",
}, },
"fr": { "fr": {
"t1": "Guide de l'utilisateur", "t1": "Guide de l'utilisateur",
@@ -270,6 +273,7 @@ var LangText={
"l44": "Différents filaments ont une vitesse de volume maximale différente.", "l44": "Différents filaments ont une vitesse de volume maximale différente.",
"l45": "Le matériau de la buse, le calibre, la température dimpression, etc., affecteront la vitesse de volume maximum.", "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.", "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": { "de": {
"t1": "Benutzerhandbuch", "t1": "Benutzerhandbuch",
@@ -338,6 +342,7 @@ var LangText={
"l44": "Es gibt eine vielzahl Von lichtern mit maximale geschwindigkeit.", "l44": "Es gibt eine vielzahl Von lichtern mit maximale geschwindigkeit.",
"l45": "Die düsen, der durchmesser, die drucktemperatur all das beeinflusst die maximale geschwindigkeit.", "l45": "Die düsen, der durchmesser, die drucktemperatur all das beeinflusst die maximale geschwindigkeit.",
"l46": "Bei den tests wird die druckgeschwindigkeit etage für etage erhöht Wenn eine öffnung Oder keine linie in der oberfläche eines modells angezeigt wird, zeigt sie an, dass sie die höchstgeschwindigkeit erreicht hat und dass die höchste geschwindigkeit nach höhe angegeben wird.", "l46": "Bei den tests wird die druckgeschwindigkeit etage für etage erhöht Wenn eine öffnung Oder keine linie in der oberfläche eines modells angezeigt wird, zeigt sie an, dass sie die höchstgeschwindigkeit erreicht hat und dass die höchste geschwindigkeit nach höhe angegeben wird.",
"l47": "Oder Sie finden eine Lösung über WIKI.",
}, },
"be": { "be": {
"t1": "Кіраўніцтва карыстальніка", "t1": "Кіраўніцтва карыстальніка",
@@ -406,6 +411,7 @@ var LangText={
"l44": "Различные нити накала имеют разную максимальную объемную скорость.", "l44": "Различные нити накала имеют разную максимальную объемную скорость.",
"l45": "Материал сопла, калибр, температура печати и т.д., повлияет на максимальную объемную скорость.", "l45": "Материал сопла, калибр, температура печати и т.д., повлияет на максимальную объемную скорость.",
"l46": "Во время теста скорость печати будет увеличиваться слой за слоем. Если на поверхности модели имеется отверстие или недостающая проволока, это указывает на то, что слой достиг максимальной объемной скорости, а максимальная объемная скорость рассчитывается в соответствии с отношением высоты.", "l46": "Во время теста скорость печати будет увеличиваться слой за слоем. Если на поверхности модели имеется отверстие или недостающая проволока, это указывает на то, что слой достиг максимальной объемной скорости, а максимальная объемная скорость рассчитывается в соответствии с отношением высоты.",
"l47": "Или вы можете найти решение через WIKI.",
}, },
}; };

View File

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

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="MenuBtnIcon"><img src="img/MenuBtnIcon.svg"/></div>
<div class="trans" tid="t18"></div> <div class="trans" tid="t18"></div>
</li> </li>
<li menu="QIDILink" class="MenuBtn" onClick="GotoMenu('QIDILink')">
<div class="MenuBtnIcon"><img src="img/MenuBtnIcon.svg"/></div>
<div>QIDI Link</div>
</li>
<li menu="ModelDownload" class="MenuBtn" onClick="GotoMenu('ModelDownload')"> <li menu="ModelDownload" class="MenuBtn" onClick="GotoMenu('ModelDownload')">
<div class="MenuBtnIcon"><img src="img/MenuBtnIcon.svg"/></div> <div class="MenuBtnIcon"><img src="img/MenuBtnIcon.svg"/></div>
<div class="trans" tid="t13"></div> <div class="trans" tid="t13"></div>
@@ -97,6 +101,10 @@
<i class="fa fa-caret-right"></i> <i class="fa fa-caret-right"></i>
</label> </label>
<ol> <ol>
<li menu="X-Plus 4" class="MenuBtn" onClick="GotoMenu('X-Plus 4')">
<div class="MenuBtnIcon"><img src="img/MenuBtnIcon.svg"/></div>
<div>X-Plus 4</div>
</li>
<li menu="Q1 Pro" class="MenuBtn" onClick="GotoMenu('Q1 Pro')"> <li menu="Q1 Pro" class="MenuBtn" onClick="GotoMenu('Q1 Pro')">
<div class="MenuBtnIcon"><img src="img/MenuBtnIcon.svg"/></div> <div class="MenuBtnIcon"><img src="img/MenuBtnIcon.svg"/></div>
<div>Q1 Pro</div> <div>Q1 Pro</div>
@@ -170,6 +178,10 @@
<div class="AutozoomImage"><img src="img/ExcludeObjects.gif"/></div> <div class="AutozoomImage"><img src="img/ExcludeObjects.gif"/></div>
<div class="ThumbnailTitle trans" tid="t18"></div> <div class="ThumbnailTitle trans" tid="t18"></div>
</div> </div>
<div class="Thumbnail" onClick="GotoMenu('QIDILink')">
<div class="AutozoomImage"><img src="img/QIDILink.png"/></div>
<div class="ThumbnailTitle">QIDI Link</div>
</div>
<div class="Thumbnail" onClick="GotoMenu('ModelDownload')"> <div class="Thumbnail" onClick="GotoMenu('ModelDownload')">
<div class="AutozoomImage"><img src="img/DownloadModel.png"/></div> <div class="AutozoomImage"><img src="img/DownloadModel.png"/></div>
<div class="ThumbnailTitle trans" tid="t13"></div> <div class="ThumbnailTitle trans" tid="t13"></div>
@@ -244,6 +256,11 @@
<div class="AutozoomImage"><img src="img/ExcludeObjects.gif"/></div> <div class="AutozoomImage"><img src="img/ExcludeObjects.gif"/></div>
</div> </div>
<div class="IntroduceBoard" board="QIDILink">
<div class="IntroduceTitle">QIDI Link</div>
<div class="AutozoomImage"><img src="img/QIDILink.png"/></div>
</div>
<div class="IntroduceBoard" board="ModelDownload"> <div class="IntroduceBoard" board="ModelDownload">
<div class="IntroduceTitle trans" tid="t13"></div> <div class="IntroduceTitle trans" tid="t13"></div>
<div class="IntroduceTextBold trans" tid="l1"></div> <div class="IntroduceTextBold trans" tid="l1"></div>
@@ -314,10 +331,16 @@
<div class="IntroduceText trans" tid="l46"></div> <div class="IntroduceText trans" tid="l46"></div>
</div> </div>
<div class="IntroduceBoard" board="X-Plus 4">
<div class="AutozoomImage"><img src="img/X-Plus4Poster.png"/></div>
<div class="IntroduceTextBold trans" tid="l0"></div>
<div class="IntroduceText">https://qidi3d.com/products/qidi-x-plus-4</div>
</div>
<div class="IntroduceBoard" board="Q1 Pro"> <div class="IntroduceBoard" board="Q1 Pro">
<div class="AutozoomImage"><img src="img/Q1 ProPoster.png"/></div> <div class="AutozoomImage"><img src="img/Q1 ProPoster.png"/></div>
<div class="IntroduceTextBold trans" tid="l0"></div> <div class="IntroduceTextBold trans" tid="l0"></div>
<div class="IntroduceText">https://qidi3d.com</div> <div class="IntroduceText">https://qidi3d.com/products/q1-pro-3d-printer</div>
</div> </div>
<div class="IntroduceBoard" board="X-MAX 3"> <div class="IntroduceBoard" board="X-MAX 3">
@@ -595,7 +618,18 @@
<div class="IntroduceTitle trans" tid="t6"></div> <div class="IntroduceTitle trans" tid="t6"></div>
<div class="IntroduceText trans" tid="l2"></div> <div class="IntroduceText trans" tid="l2"></div>
<div class="IntroduceText trans" tid="l3"></div> <div class="IntroduceText trans" tid="l3"></div>
<div><br></div>
<div class="IntroduceText trans" tid="l47"></div>
<div class="IntroduceText">https://wiki.qidi3d.com</div>
<div class="EmailBlock"> <div class="EmailBlock">
<div class="PrinterBlock">
<div class="CenterImage"><img src="img/X-Plus 4.png"/></div>
<div class="ThumbnailTitle">X-Plus 4</div>
<div class="IntroduceText">
<b>E-mail:</b><br/>Plus4support@qidi3d.com<br>Plus4Ams@qidi3d.com<br/><br>
<b>Skype:</b><br/>Plus4support@qidi3d.com
</div>
</div>
<div class="PrinterBlock"> <div class="PrinterBlock">
<div class="CenterImage"><img src="img/Q1 Pro.png"/></div> <div class="CenterImage"><img src="img/Q1 Pro.png"/></div>
<div class="ThumbnailTitle">Q1 Pro</div> <div class="ThumbnailTitle">Q1 Pro</div>

View File

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

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 <cstring>
#include <iostream> #include <iostream>
#include <math.h> #include <math.h>
//B64
#include "nlohmann/json.hpp"
#include <boost/algorithm/string/predicate.hpp> #include <boost/algorithm/string/predicate.hpp>
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <boost/nowide/args.hpp> #include <boost/nowide/args.hpp>

View File

@@ -211,11 +211,33 @@ void AppConfig::set_defaults()
if (get("sys_menu_enabled").empty()) if (get("sys_menu_enabled").empty())
set("sys_menu_enabled", "1"); set("sys_menu_enabled", "1");
//B45
#endif // _WIN32
// B45
if (get("machine_list_minification").empty()) if (get("machine_list_minification").empty())
set("machine_list_minification", "1"); set("machine_list_minification", "1");
#endif // _WIN32
//B64
if (get("user_token").empty())
set("user_token", "");
//y5
if(get("user_head_url").empty())
set("user_head_url", "");
if(get("user_head_name").empty())
set("user_head_name", "");
if (get("sending_interval").empty()) {
set("sending_interval", "5");
}
if (get("max_send").empty()) {
set("max_send", "3");
}
if (get("machine_list_net").empty())
set("machine_list_net", "0");
// Remove legacy window positions/sizes // Remove legacy window positions/sizes
erase("", "main_frame_maximized"); erase("", "main_frame_maximized");
erase("", "main_frame_pos"); erase("", "main_frame_pos");

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 << "."; BOOST_LOG_TRIVIAL(trace) << "Applying the Widening Beading meta-strategy with minimum input width " << min_feature_size << " and minimum output width " << min_bead_width << ".";
ret = std::make_unique<WideningBeadingStrategy>(std::move(ret), min_feature_size, min_bead_width); ret = std::make_unique<WideningBeadingStrategy>(std::move(ret), min_feature_size, min_bead_width);
} }
//w39
if (outer_wall_offset > 0) { if (outer_wall_offset != 0){//if (outer_wall_offset > 0) {
BOOST_LOG_TRIVIAL(trace) << "Applying the OuterWallOffset meta-strategy with offset = " << outer_wall_offset << "."; BOOST_LOG_TRIVIAL(trace) << "Applying the OuterWallOffset meta-strategy with offset = " << outer_wall_offset << ".";
ret = std::make_unique<OuterWallInsetBeadingStrategy>(outer_wall_offset, std::move(ret)); ret = std::make_unique<OuterWallInsetBeadingStrategy>(outer_wall_offset, std::move(ret));
} }

View File

@@ -311,47 +311,42 @@ BuildVolume::ObjectState BuildVolume::object_state(const indexed_triangle_set& i
} }
} }
//B52 // B52 //B66
BuildVolume::ObjectState BuildVolume::volume_state_bbox(const BoundingBoxf3& volume_bbox, bool ignore_bottom) const BuildVolume::ObjectState BuildVolume::volume_state_bbox(const BoundingBoxf3& volume_bbox, bool ignore_bottom) const
{ {
assert(m_type == Type::Rectangle); assert(m_type == Type::Rectangle);
BoundingBox3Base<Vec3d> build_volume = this->bounding_volume().inflated(SceneEpsilon); BoundingBox3Base<Vec3d> build_volume = this->bounding_volume().inflated(SceneEpsilon);
std::vector<BoundingBox3Base<Vec3d>> exclude_build_volume; if (m_max_print_height == 0.0)
build_volume.max.z() = std::numeric_limits<double>::max();
if (ignore_bottom)
build_volume.min.z() = -std::numeric_limits<double>::max();
return build_volume.max.z() <= -SceneEpsilon ? ObjectState::Below :
build_volume.contains(volume_bbox) ? ObjectState::Inside :
build_volume.intersects(volume_bbox) ? ObjectState::Colliding :
ObjectState::Outside;
}
// B66
BuildVolume::ObjectState BuildVolume::check_outside(Polygon hull) const
{
if (m_exclude_bed_shape.size() > 0) {
for (int i = 1; i < m_exclude_bed_shape.size(); i += 7) { for (int i = 1; i < m_exclude_bed_shape.size(); i += 7) {
std::vector<Vec2d> tem_exclude_bed_shap; std::vector<Vec2d> tem_exclude_bed_shap;
for (int j = 1; j < 6; j++) for (int j = 1; j < 6; j++)
tem_exclude_bed_shap.push_back(m_exclude_bed_shape[i + j]); tem_exclude_bed_shap.push_back(m_exclude_bed_shape[i + j]);
BoundingBoxf tem_bboxf = get_extents(tem_exclude_bed_shap); BoundingBoxf tem_bboxf = get_extents(tem_exclude_bed_shap);
auto tem_exclude_bboxf = BoundingBoxf3{to_3d(tem_bboxf.min, 0.), to_3d(tem_bboxf.max, m_max_print_height)}; auto tem_exclude_bboxf = BoundingBoxf3{to_3d(tem_bboxf.min, 0.), to_3d(tem_bboxf.max, m_max_print_height)};
BoundingBox3Base<Vec3d> tem_build_volume = tem_exclude_bboxf.inflated(SceneEpsilon); Slic3r::Polygon p = tem_exclude_bboxf.polygon(true); // instance convex hull is scaled, so we need to scale here
exclude_build_volume.push_back(tem_build_volume); if (intersection({p}, {hull}).empty() == false) {
} return ObjectState::Colliding;
bool is_contain = false;
bool is_intersect = false;
for (const auto &tem_build_volume : exclude_build_volume) {
if (tem_build_volume.contains(volume_bbox)) {
is_contain=true;
is_intersect = false;
break; break;
} }
else if (tem_build_volume.intersects(volume_bbox)) {
is_contain = false;
is_intersect = true;
break;
} }
return ObjectState::Inside;
} else {
return ObjectState::Inside;
} }
if (m_max_print_height == 0.0)
build_volume.max.z() = std::numeric_limits<double>::max();
if (ignore_bottom)
build_volume.min.z() = -std::numeric_limits<double>::max();
return build_volume.max.z() <= - SceneEpsilon ? ObjectState::Below :
is_contain ? ObjectState::Outside :
is_intersect ? ObjectState::Outside :
build_volume.contains(volume_bbox) ? ObjectState::Inside :
build_volume.intersects(volume_bbox) ? ObjectState::Colliding :
ObjectState::Outside;
} }
//B52 //B52

View File

@@ -87,6 +87,8 @@ public:
// Called by GLVolumeCollection::check_outside_state() after an object is manipulated with gizmos for example. // Called by GLVolumeCollection::check_outside_state() after an object is manipulated with gizmos for example.
// Called for a rectangular bed: // Called for a rectangular bed:
ObjectState volume_state_bbox(const BoundingBoxf3& volume_bbox, bool ignore_bottom = true) const; ObjectState volume_state_bbox(const BoundingBoxf3& volume_bbox, bool ignore_bottom = true) const;
// B66
BuildVolume::ObjectState check_outside(Polygon hull) const;
// 2) Test called on G-code paths. // 2) Test called on G-code paths.
// Using BedEpsilon for all tests. // Using BedEpsilon for all tests.

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 // Useful as an optimization for expensive ClipperLib operations, for example when clipping source polygons one by one
// with a set of polygons covering the whole layer below. // with a set of polygons covering the whole layer below.
template<typename PointsType> template<typename PointsType>
inline void clip_clipper_polygon_with_subject_bbox_templ(const PointsType &src, const BoundingBox &bbox, PointsType &out) //w38
inline void clip_clipper_polygon_with_subject_bbox_templ(const PointsType &src, const BoundingBox &bbox, PointsType &out,const bool get_entire_polygons=false)
{ {
using PointType = typename PointsType::value_type; using PointType = typename PointsType::value_type;
@@ -121,6 +122,8 @@ namespace ClipperUtils {
void clip_clipper_polygon_with_subject_bbox(const Points &src, const BoundingBox &bbox, Points &out) void clip_clipper_polygon_with_subject_bbox(const Points &src, const BoundingBox &bbox, Points &out)
{ clip_clipper_polygon_with_subject_bbox_templ(src, bbox, out); } { clip_clipper_polygon_with_subject_bbox_templ(src, bbox, out); }
//w38
void clip_clipper_polygon_with_subject_bbox(const Points &src, const BoundingBox &bbox, Points &out, const bool get_entire_polygons) { clip_clipper_polygon_with_subject_bbox_templ(src, bbox, out, get_entire_polygons); }
void clip_clipper_polygon_with_subject_bbox(const ZPoints &src, const BoundingBox &bbox, ZPoints &out) void clip_clipper_polygon_with_subject_bbox(const ZPoints &src, const BoundingBox &bbox, ZPoints &out)
{ clip_clipper_polygon_with_subject_bbox_templ(src, bbox, out); } { clip_clipper_polygon_with_subject_bbox_templ(src, bbox, out); }
@@ -149,6 +152,14 @@ namespace ClipperUtils {
return out; return out;
} }
//w38
[[nodiscard]] Polygon clip_clipper_polygon_with_subject_bbox(const Polygon &src, const BoundingBox &bbox, const bool get_entire_polygons)
{
Polygon out;
clip_clipper_polygon_with_subject_bbox(src.points, bbox, out.points, get_entire_polygons);
return out;
}
[[nodiscard]] Polygons clip_clipper_polygons_with_subject_bbox(const Polygons &src, const BoundingBox &bbox) [[nodiscard]] Polygons clip_clipper_polygons_with_subject_bbox(const Polygons &src, const BoundingBox &bbox)
{ {
Polygons out; Polygons out;
@@ -172,7 +183,36 @@ namespace ClipperUtils {
out.end()); out.end());
return out; return out;
} }
}
//w38
[[nodiscard]] Polygons clip_clipper_polygons_with_subject_bbox(const ExPolygon & src,
const BoundingBox &bbox,
const bool get_entire_polygons)
{
Polygons out;
out.reserve(src.num_contours());
out.emplace_back(clip_clipper_polygon_with_subject_bbox(src.contour, bbox, get_entire_polygons));
for (const Polygon &p : src.holes)
out.emplace_back(clip_clipper_polygon_with_subject_bbox(p, bbox, get_entire_polygons));
out.erase(std::remove_if(out.begin(), out.end(), [](const Polygon &polygon) { return polygon.empty(); }), out.end());
return out;
}
//w38
[[nodiscard]] Polygons clip_clipper_polygons_with_subject_bbox(const ExPolygons & src,
const BoundingBox &bbox,
const bool get_entire_polygons)
{
Polygons out;
out.reserve(number_polygons(src));
for (const ExPolygon &p : src) {
Polygons temp = clip_clipper_polygons_with_subject_bbox(p, bbox, get_entire_polygons);
out.insert(out.end(), temp.begin(), temp.end());
}
out.erase(std::remove_if(out.begin(), out.end(), [](const Polygon &polygon) { return polygon.empty(); }), out.end());
return out;
}
}
static ExPolygons PolyTreeToExPolygons(ClipperLib::PolyTree &&polytree) static ExPolygons PolyTreeToExPolygons(ClipperLib::PolyTree &&polytree)
{ {

View File

@@ -326,9 +326,23 @@ namespace ClipperUtils {
[[nodiscard]] ZPoints clip_clipper_polygon_with_subject_bbox(const ZPoints &src, const BoundingBox &bbox); [[nodiscard]] ZPoints clip_clipper_polygon_with_subject_bbox(const ZPoints &src, const BoundingBox &bbox);
void clip_clipper_polygon_with_subject_bbox(const Polygon &src, const BoundingBox &bbox, Polygon &out); void clip_clipper_polygon_with_subject_bbox(const Polygon &src, const BoundingBox &bbox, Polygon &out);
[[nodiscard]] Polygon clip_clipper_polygon_with_subject_bbox(const Polygon &src, const BoundingBox &bbox); [[nodiscard]] Polygon clip_clipper_polygon_with_subject_bbox(const Polygon &src, const BoundingBox &bbox);
//w38
[[nodiscard]] Polygons clip_clipper_polygons_with_subject_bbox(const ExPolygon & src,
const BoundingBox &bbox,
const bool get_entire_polygons);
[[nodiscard]] Polygons clip_clipper_polygons_with_subject_bbox(const Polygons &src, const BoundingBox &bbox); [[nodiscard]] Polygons clip_clipper_polygons_with_subject_bbox(const Polygons &src, const BoundingBox &bbox);
[[nodiscard]] Polygons clip_clipper_polygons_with_subject_bbox(const ExPolygon &src, const BoundingBox &bbox); [[nodiscard]] Polygons clip_clipper_polygons_with_subject_bbox(const ExPolygon &src, const BoundingBox &bbox);
}
//w38
[[nodiscard]] Polygons clip_clipper_polygons_with_subject_bbox(const ExPolygons & src,
const BoundingBox &bbox,
const bool get_entire_polygons);
[[nodiscard]] Polygon clip_clipper_polygon_with_subject_bbox(const Polygon & src,
const BoundingBox &bbox,
const bool get_entire_polygons);
void clip_clipper_polygon_with_subject_bbox(const Points &src, const BoundingBox &bbox, Points &out, const bool get_entire_polygons);
}
// offset Polygons // offset Polygons
// Wherever applicable, please use the expand() / shrink() variants instead, they convey their purpose better. // Wherever applicable, please use the expand() / shrink() variants instead, they convey their purpose better.

View File

@@ -9,6 +9,7 @@
#include <limits> #include <limits>
#include <sstream> #include <sstream>
namespace Slic3r { namespace Slic3r {
void ExtrusionPath::intersect_expolygons(const ExPolygons &collection, ExtrusionEntityCollection* retval) const void ExtrusionPath::intersect_expolygons(const ExPolygons &collection, ExtrusionEntityCollection* retval) const
@@ -112,6 +113,22 @@ Polyline ExtrusionMultiPath::as_polyline() const
} }
return out; return out;
} }
//w38
bool ExtrusionLoop::make_clockwise()
{
bool was_ccw = this->polygon().is_counter_clockwise();
if (was_ccw)
this->reverse_loop();
return was_ccw;
}
bool ExtrusionLoop::make_counter_clockwise()
{
bool was_cw = this->polygon().is_clockwise();
if (was_cw)
this->reverse_loop();
return was_cw;
}
double ExtrusionLoop::area() const double ExtrusionLoop::area() const
{ {
@@ -334,4 +351,5 @@ double ExtrusionLoop::min_mm3_per_mm() const
return min_mm3_per_mm; return min_mm3_per_mm;
} }
} }

View File

@@ -326,6 +326,9 @@ public:
append(dst, p.polyline.points); append(dst, p.polyline.points);
} }
double total_volume() const override { double volume =0.; for (const auto& path : paths) volume += path.total_volume(); return volume; } double total_volume() const override { double volume =0.; for (const auto& path : paths) volume += path.total_volume(); return volume; }
//w38
bool make_clockwise();
bool make_counter_clockwise();
#ifndef NDEBUG #ifndef NDEBUG
bool validate() const { bool validate() const {

View File

@@ -95,9 +95,13 @@ struct ExtrusionRole : public ExtrusionRoleModifiers
// Special flags describing loop // Special flags describing loop
enum ExtrusionLoopRole { enum ExtrusionLoopRole {
elrDefault, //w38
elrContourInternalPerimeter, elrDefault = 0x0,
elrSkirt, // Loop for the hole, not for the contour
elrHole = 0x1,
// Loop that is the most closest to infill
elrInternal = 0x2,
elrSkirt = 0x4,
}; };
// Be careful when editing this list as many parts of the code depend // Be careful when editing this list as many parts of the code depend

View File

@@ -343,6 +343,7 @@ std::vector<SurfaceFill> group_fills(const Layer &layer)
// Use ipEnsuring pattern for all internal Solids. // Use ipEnsuring pattern for all internal Solids.
//w11 //w11
if (layer.object()->config().detect_narrow_internal_solid_infill) { if (layer.object()->config().detect_narrow_internal_solid_infill) {
//w29
size_t surface_fills_size = surface_fills.size(); size_t surface_fills_size = surface_fills.size();
for (size_t i = 0; i < surface_fills_size; i++) { for (size_t i = 0; i < surface_fills_size; i++) {
if (surface_fills[i].surface.surface_type != stInternalSolid) if (surface_fills[i].surface.surface_type != stInternalSolid)
@@ -354,12 +355,13 @@ std::vector<SurfaceFill> group_fills(const Layer &layer)
for (size_t j = 0; j < expolygons_size; j++) for (size_t j = 0; j < expolygons_size; j++)
if (is_narrow_infill_area(surface_fills[i].expolygons[j])) if (is_narrow_infill_area(surface_fills[i].expolygons[j]))
narrow_expolygons_index.push_back(j); narrow_expolygons_index.push_back(j);
//w29
if (narrow_expolygons_index.size() == 0) { if (narrow_expolygons_index.size() == 0) {
continue; continue;
} else if (narrow_expolygons_index.size() == expolygons_size) { } else if (narrow_expolygons_index.size() == expolygons_size) {
surface_fills[i].params.pattern = ipConcentric; surface_fills[i].params.pattern = ipConcentric;
} else { } else {
//w29
params = surface_fills[i].params; params = surface_fills[i].params;
params.pattern = ipConcentric; params.pattern = ipConcentric;
surface_fills.emplace_back(params); surface_fills.emplace_back(params);
@@ -575,6 +577,7 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
params.anchor_length_max = surface_fill.params.anchor_length_max; params.anchor_length_max = surface_fill.params.anchor_length_max;
params.resolution = resolution; params.resolution = resolution;
//w14 //w14
//w29
params.use_arachne = (perimeter_generator == PerimeterGeneratorType::Arachne && surface_fill.params.pattern == ipConcentric) || surface_fill.params.pattern == ipEnsuring || surface_fill.params.pattern == ipConcentric; params.use_arachne = (perimeter_generator == PerimeterGeneratorType::Arachne && surface_fill.params.pattern == ipConcentric) || surface_fill.params.pattern == ipEnsuring || surface_fill.params.pattern == ipConcentric;
params.layer_height = layerm.layer()->height; params.layer_height = layerm.layer()->height;
//w29 //w29
@@ -643,6 +646,7 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
delete eec; delete eec;
thick_polylines.clear(); thick_polylines.clear();
} else { } else {
//w29
extrusion_entities_append_paths(eec->entities, std::move(polylines), extrusion_entities_append_paths(eec->entities, std::move(polylines),
ExtrusionAttributes{surface_fill.params.extrusion_role, ExtrusionAttributes{surface_fill.params.extrusion_role,
ExtrusionFlow{flow_mm3_per_mm, float(flow_width), ExtrusionFlow{flow_mm3_per_mm, float(flow_width),
@@ -699,43 +703,41 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
} }
for (LayerSlice &lslice : this->lslices_ex) for (LayerSlice &lslice : this->lslices_ex)
for (LayerIsland &island : lslice.islands) { for (LayerIsland &island : lslice.islands) {
if (!island.thin_fills.empty()) { if (! island.thin_fills.empty()) {
// Copy thin fills into fills packed as a collection. // Copy thin fills into fills packed as a collection.
// Fills are always stored as collections, the rest of the pipeline (wipe into infill, G-code generator) relies on it. // Fills are always stored as collections, the rest of the pipeline (wipe into infill, G-code generator) relies on it.
LayerRegion & layerm = *this->get_region(island.perimeters.region()); LayerRegion &layerm = *this->get_region(island.perimeters.region());
ExtrusionEntityCollection &collection = *(new ExtrusionEntityCollection()); ExtrusionEntityCollection &collection = *(new ExtrusionEntityCollection());
layerm.m_fills.entities.push_back(&collection); layerm.m_fills.entities.push_back(&collection);
collection.entities.reserve(island.thin_fills.size()); collection.entities.reserve(island.thin_fills.size());
for (uint32_t fill_id : island.thin_fills) for (uint32_t fill_id : island.thin_fills)
collection.entities.push_back(layerm.thin_fills().entities[fill_id]->clone()); collection.entities.push_back(layerm.thin_fills().entities[fill_id]->clone());
island.add_fill_range( island.add_fill_range({ island.perimeters.region(), { uint32_t(layerm.m_fills.entities.size() - 1), uint32_t(layerm.m_fills.entities.size()) } });
{island.perimeters.region(), {uint32_t(layerm.m_fills.entities.size() - 1), uint32_t(layerm.m_fills.entities.size())}}); }
} // Sort the fills by region ID.
// Sort the fills by region ID. std::sort(island.fills.begin(), island.fills.end(), [](auto &l, auto &r){ return l.region() < r.region() || (l.region() == r.region() && *l.begin() < *r.begin()); });
std::sort(island.fills.begin(), island.fills.end(), // Compress continuous fill ranges of the same region.
[](auto &l, auto &r) { return l.region() < r.region() || (l.region() == r.region() && *l.begin() < *r.begin()); }); {
// Compress continuous fill ranges of the same region. size_t k = 0;
{ for (size_t i = 0; i < island.fills.size();) {
size_t k = 0; uint32_t region_id = island.fills[i].region();
for (size_t i = 0; i < island.fills.size();) { uint32_t begin = *island.fills[i].begin();
uint32_t region_id = island.fills[i].region(); uint32_t end = *island.fills[i].end();
uint32_t begin = *island.fills[i].begin(); size_t j = i + 1;
uint32_t end = *island.fills[i].end(); for (; j < island.fills.size() && island.fills[j].region() == region_id && *island.fills[j].begin() == end; ++ j)
size_t j = i + 1; end = *island.fills[j].end();
for (; j < island.fills.size() && island.fills[j].region() == region_id && *island.fills[j].begin() == end; ++j) island.fills[k ++] = { region_id, { begin, end } };
end = *island.fills[j].end(); i = j;
island.fills[k++] = {region_id, {begin, end}}; }
i = j; island.fills.erase(island.fills.begin() + k, island.fills.end());
} }
island.fills.erase(island.fills.begin() + k, island.fills.end()); }
}
}
#ifndef NDEBUG #ifndef NDEBUG
for (LayerRegion *layerm : m_regions) for (LayerRegion *layerm : m_regions)
for (const ExtrusionEntity *e : layerm->fills()) for (const ExtrusionEntity *e : layerm->fills())
assert(dynamic_cast<const ExtrusionEntityCollection *>(e) != nullptr); assert(dynamic_cast<const ExtrusionEntityCollection*>(e) != nullptr);
#endif #endif
} }
//w21 //w21
@@ -1100,11 +1102,13 @@ void Layer::make_ironing()
// Layer::id() returns layer ID including raft layers, subtract them to make the infill direction independent // Layer::id() returns layer ID including raft layers, subtract them to make the infill direction independent
// from raft. // from raft.
//FIXME ironing does not take fill angle into account. Shall it? Does it matter? //FIXME ironing does not take fill angle into account. Shall it? Does it matter?
//w33
//fill.layer_id = this->id() - this->object()->get_layer(0)->id(); //fill.layer_id = this->id() - this->object()->get_layer(0)->id();
//fill.z = this->print_z; //fill.z = this->print_z;
//fill.overlap = 0; //fill.overlap = 0;
fill_params.density = 1.; fill_params.density = 1.;
fill_params.monotonic = true; fill_params.monotonic = true;
//w33
InfillPattern f_pattern = ipRectilinear; InfillPattern f_pattern = ipRectilinear;
std::unique_ptr<Fill> f = std::unique_ptr<Fill>(Fill::new_from_type(f_pattern)); std::unique_ptr<Fill> f = std::unique_ptr<Fill>(Fill::new_from_type(f_pattern));
f->set_bounding_box(this->object()->bounding_box()); f->set_bounding_box(this->object()->bounding_box());

View File

@@ -6,15 +6,18 @@
namespace Slic3r { namespace Slic3r {
//w36
template <typename T> int sgn(T val) { template <typename T> int sgn(T val) {
return (T(0) < val) - (val < T(0)); return (T(0) < val) - (val < T(0));
} }
//w36
static coordf_t triWave(coordf_t pos, coordf_t gridSize) static coordf_t triWave(coordf_t pos, coordf_t gridSize)
{ {
float t = (pos / (gridSize * 2.)) + 0.25; float t = (pos / (gridSize * 2.)) + 0.25;
t = t - (int)t; t = t - (int)t;
return((1. - abs(t * 8. - 4.)) * (gridSize / 4.) + (gridSize / 4.)); return((1. - abs(t * 8. - 4.)) * (gridSize / 4.) + (gridSize / 4.));
} }
//w36
static coordf_t troctWave(coordf_t pos, coordf_t gridSize, coordf_t Zpos) static coordf_t troctWave(coordf_t pos, coordf_t gridSize, coordf_t Zpos)
{ {
coordf_t Zcycle = triWave(Zpos, gridSize); coordf_t Zcycle = triWave(Zpos, gridSize);
@@ -22,6 +25,7 @@ static coordf_t troctWave(coordf_t pos, coordf_t gridSize, coordf_t Zpos)
coordf_t y = triWave(pos, gridSize); coordf_t y = triWave(pos, gridSize);
return ((abs(y) > abs(perpOffset)) ? (sgn(y) * perpOffset) : (y * sgn(perpOffset))); return ((abs(y) > abs(perpOffset)) ? (sgn(y) * perpOffset) : (y * sgn(perpOffset)));
} }
//w36
static std::vector<coordf_t> getCriticalPoints(coordf_t Zpos, coordf_t gridSize) static std::vector<coordf_t> getCriticalPoints(coordf_t Zpos, coordf_t gridSize)
{ {
std::vector<coordf_t> res = {0.}; std::vector<coordf_t> res = {0.};
@@ -50,22 +54,27 @@ Credits: David Eccles (gringer).
// basic printing line (i.e. Y points for columns, X points for rows) // basic printing line (i.e. Y points for columns, X points for rows)
// Note: a negative offset only causes a change in the perpendicular // Note: a negative offset only causes a change in the perpendicular
// direction // direction
//w36
static std::vector<coordf_t> colinearPoints(const coordf_t Zpos, coordf_t gridSize, std::vector<coordf_t> critPoints, 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 size_t baseLocation, size_t gridLength)
{ {
//w36
std::vector<coordf_t> points; std::vector<coordf_t> points;
//w36
points.push_back(baseLocation); points.push_back(baseLocation);
for (coordf_t cLoc = baseLocation; cLoc < gridLength; cLoc += (gridSize * 2)) { for (coordf_t cLoc = baseLocation; cLoc < gridLength; cLoc += (gridSize * 2)) {
for (size_t pi = 0; pi < critPoints.size(); pi++) { for (size_t pi = 0; pi < critPoints.size(); pi++) {
points.push_back(baseLocation + cLoc + critPoints[pi]); points.push_back(baseLocation + cLoc + critPoints[pi]);
} }
} }
//w36
points.push_back(gridLength); points.push_back(gridLength);
return points; return points;
} }
// Generate an array of points for the dimension that is perpendicular to // Generate an array of points for the dimension that is perpendicular to
// the basic printing line (i.e. X points for columns, Y points for rows) // the basic printing line (i.e. X points for columns, Y points for rows)
//w36
static std::vector<coordf_t> perpendPoints(const coordf_t Zpos, static std::vector<coordf_t> perpendPoints(const coordf_t Zpos,
coordf_t gridSize, coordf_t gridSize,
std::vector<coordf_t> critPoints, std::vector<coordf_t> critPoints,
@@ -74,7 +83,9 @@ static std::vector<coordf_t> perpendPoints(const coordf_t Zpos,
size_t offsetBase, size_t offsetBase,
coordf_t perpDir) coordf_t perpDir)
{ {
//w36
std::vector<coordf_t> points; std::vector<coordf_t> points;
//w36
points.push_back(offsetBase); points.push_back(offsetBase);
for (coordf_t cLoc = baseLocation; cLoc < gridLength; cLoc += gridSize * 2) { for (coordf_t cLoc = baseLocation; cLoc < gridLength; cLoc += gridSize * 2) {
for (size_t pi = 0; pi < critPoints.size(); pi++) { for (size_t pi = 0; pi < critPoints.size(); pi++) {
@@ -82,6 +93,7 @@ static std::vector<coordf_t> perpendPoints(const coordf_t Zpos,
points.push_back(offsetBase + (offset * perpDir)); points.push_back(offsetBase + (offset * perpDir));
} }
} }
//w36
points.push_back(offsetBase); points.push_back(offsetBase);
return points; return points;
} }
@@ -110,8 +122,10 @@ static inline Pointfs zip(const std::vector<coordf_t> &x, const std::vector<coor
// horizontal slice of a truncated regular octahedron with edge length 1. // horizontal slice of a truncated regular octahedron with edge length 1.
// curveType specifies which lines to print, 1 for vertical lines // curveType specifies which lines to print, 1 for vertical lines
// (columns), 2 for horizontal lines (rows), and 3 for both. // (columns), 2 for horizontal lines (rows), and 3 for both.
//w36
static std::vector<Pointfs> makeActualGrid(coordf_t Zpos, coordf_t gridSize, size_t boundsX, size_t boundsY) static std::vector<Pointfs> makeActualGrid(coordf_t Zpos, coordf_t gridSize, size_t boundsX, size_t boundsY)
{ {
//w36
std::vector<Pointfs> points; std::vector<Pointfs> points;
std::vector<coordf_t> critPoints = getCriticalPoints(Zpos, gridSize); std::vector<coordf_t> critPoints = getCriticalPoints(Zpos, gridSize);
coordf_t zCycle = fmod(Zpos + gridSize / 2, gridSize * 2.) / (gridSize * 2.); coordf_t zCycle = fmod(Zpos + gridSize / 2, gridSize * 2.) / (gridSize * 2.);
@@ -143,14 +157,17 @@ static std::vector<Pointfs> makeActualGrid(coordf_t Zpos, coordf_t gridSize, siz
// Generate a set of curves (array of array of 2d points) that describe a // Generate a set of curves (array of array of 2d points) that describe a
// horizontal slice of a truncated regular octahedron with a specified // horizontal slice of a truncated regular octahedron with a specified
// grid square size. // grid square size.
//w36
static Polylines makeGrid(coordf_t z, coordf_t gridSize, coordf_t boundWidth, coordf_t boundHeight, bool fillEvenly) static Polylines makeGrid(coordf_t z, coordf_t gridSize, coordf_t boundWidth, coordf_t boundHeight, bool fillEvenly)
{ {
//w36
std::vector<Pointfs> polylines = makeActualGrid(z, gridSize, boundWidth, boundHeight); std::vector<Pointfs> polylines = makeActualGrid(z, gridSize, boundWidth, boundHeight);
Polylines result; Polylines result;
result.reserve(polylines.size()); result.reserve(polylines.size());
for (std::vector<Pointfs>::const_iterator it_polylines = polylines.begin(); it_polylines != polylines.end(); ++it_polylines) { for (std::vector<Pointfs>::const_iterator it_polylines = polylines.begin(); it_polylines != polylines.end(); ++it_polylines) {
result.push_back(Polyline()); result.push_back(Polyline());
Polyline &polyline = result.back(); Polyline &polyline = result.back();
//w36
for (Pointfs::const_iterator it = it_polylines->begin(); it != it_polylines->end(); ++it) 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)))); polyline.points.push_back(Point(coord_t((*it)(0)), coord_t((*it)(1))));
} }
@@ -165,13 +182,16 @@ void Fill3DHoneycomb::_fill_surface_single(
Polylines &polylines_out) Polylines &polylines_out)
{ {
// no rotation is supported for this infill pattern // no rotation is supported for this infill pattern
//w36
auto infill_angle = float(this->angle); auto infill_angle = float(this->angle);
if (std::abs(infill_angle) >= EPSILON) if (std::abs(infill_angle) >= EPSILON)
expolygon.rotate(-infill_angle); expolygon.rotate(-infill_angle);
BoundingBox bb = expolygon.contour.bounding_box(); BoundingBox bb = expolygon.contour.bounding_box();
//w36
// align bounding box to a multiple of our honeycomb grid module // align bounding box to a multiple of our honeycomb grid module
// (a module is 2*$distance since one $distance half-module is // (a module is 2*$distance since one $distance half-module is
// growing while the other $distance half-module is shrinking) // growing while the other $distance half-module is shrinking)
//w36
coordf_t zScale = sqrt(2); coordf_t zScale = sqrt(2);
coordf_t gridSize = (scale_(this->spacing) * ((zScale + 1.) / 2.) / params.density); coordf_t gridSize = (scale_(this->spacing) * ((zScale + 1.) / 2.) / params.density);

View File

@@ -16,6 +16,7 @@ public:
~Fill3DHoneycomb() override {} ~Fill3DHoneycomb() override {}
// require bridge flow since most of this pattern hangs in air // require bridge flow since most of this pattern hangs in air
//w36
protected: protected:

View File

@@ -125,7 +125,7 @@ void Fill::fill_surface_extrusion(const Surface *surface, const FillParams &para
} }
//w29
void Fill::variable_width(const ThickPolylines &polylines, ExtrusionRole role, const Flow &flow, std::vector<ExtrusionEntity *> &out) void Fill::variable_width(const ThickPolylines &polylines, ExtrusionRole role, const Flow &flow, std::vector<ExtrusionEntity *> &out)
{ {
const float tolerance = float(scale_(0.05)); const float tolerance = float(scale_(0.05));
@@ -141,6 +141,7 @@ void Fill::variable_width(const ThickPolylines &polylines, ExtrusionRole role, c
} }
} }
} }
//w29
ExtrusionPaths Fill::thick_polyline_to_extrusion_paths_2(const ThickPolyline &thick_polyline, ExtrusionPaths Fill::thick_polyline_to_extrusion_paths_2(const ThickPolyline &thick_polyline,
ExtrusionRole role, ExtrusionRole role,
const Flow & flow, const Flow & flow,

File diff suppressed because it is too large Load Diff

View File

@@ -166,6 +166,7 @@ public:
std::optional<Point> last_position; std::optional<Point> last_position;
private: private:
class GCodeOutputStream { class GCodeOutputStream {
public: public:
@@ -455,6 +456,9 @@ private:
// Processor // Processor
GCodeProcessor m_processor; GCodeProcessor m_processor;
//Y27
bool m_resonance_avoidance;
// Back-pointer to Print (const). // Back-pointer to Print (const).
const Print* m_print; const Print* m_print;
std::string _extrude( std::string _extrude(

View File

@@ -236,6 +236,8 @@ struct PerExtruderAdjustments
float slowdown_below_layer_time = 0.f; float slowdown_below_layer_time = 0.f;
// Minimum print speed allowed for this extruder. // Minimum print speed allowed for this extruder.
float min_print_speed = 0.f; float min_print_speed = 0.f;
//Y28
bool dont_slow_down_outer_wall = true;
// Parsed lines. // Parsed lines.
std::vector<CoolingLine> lines; std::vector<CoolingLine> lines;
@@ -344,6 +346,8 @@ std::vector<PerExtruderAdjustments> CoolingBuffer::parse_layer_gcode(const std::
adj.cooling_slow_down_enabled = m_config.cooling.get_at(extruder_id); adj.cooling_slow_down_enabled = m_config.cooling.get_at(extruder_id);
adj.slowdown_below_layer_time = float(m_config.slowdown_below_layer_time.get_at(extruder_id)); adj.slowdown_below_layer_time = float(m_config.slowdown_below_layer_time.get_at(extruder_id));
adj.min_print_speed = float(m_config.min_print_speed.get_at(extruder_id)); adj.min_print_speed = float(m_config.min_print_speed.get_at(extruder_id));
//Y28
adj.dont_slow_down_outer_wall = m_config.dont_slow_down_outer_wall.get_at(extruder_id);
map_extruder_to_per_extruder_adjustment[extruder_id] = i; map_extruder_to_per_extruder_adjustment[extruder_id] = i;
} }
@@ -424,7 +428,12 @@ std::vector<PerExtruderAdjustments> CoolingBuffer::parse_layer_gcode(const std::
line.type |= CoolingLine::TYPE_EXTERNAL_PERIMETER; line.type |= CoolingLine::TYPE_EXTERNAL_PERIMETER;
if (wipe) if (wipe)
line.type |= CoolingLine::TYPE_WIPE; line.type |= CoolingLine::TYPE_WIPE;
if (boost::contains(sline, ";_EXTRUDE_SET_SPEED") && ! wipe) { //Y28
bool adjust_external = true;
if (adjustment->dont_slow_down_outer_wall && external_perimeter)
adjust_external = false;
if (boost::contains(sline, ";_EXTRUDE_SET_SPEED") && ! wipe && adjust_external) {
line.type |= CoolingLine::TYPE_ADJUSTABLE; line.type |= CoolingLine::TYPE_ADJUSTABLE;
active_speed_modifier = adjustment->lines.size(); active_speed_modifier = adjustment->lines.size();
} }
@@ -799,19 +808,19 @@ std::string CoolingBuffer::apply_layer_cooldown(
auto change_extruder_set_fan = [this, layer_id, layer_time, &new_gcode, &bridge_fan_control, &bridge_fan_speed]() { auto change_extruder_set_fan = [this, layer_id, layer_time, &new_gcode, &bridge_fan_control, &bridge_fan_speed]() {
#define EXTRUDER_CONFIG(OPT) m_config.OPT.get_at(m_current_extruder) #define EXTRUDER_CONFIG(OPT) m_config.OPT.get_at(m_current_extruder)
int min_fan_speed = EXTRUDER_CONFIG(min_fan_speed); int min_fan_speed = EXTRUDER_CONFIG(min_fan_speed);
//B15 //B15//Y26
int enable_auxiliary_fan = EXTRUDER_CONFIG(enable_auxiliary_fan); int enable_auxiliary_fan;
if (m_config.opt_bool("seal_print"))
enable_auxiliary_fan = EXTRUDER_CONFIG(enable_auxiliary_fan);
else
enable_auxiliary_fan = EXTRUDER_CONFIG(enable_auxiliary_fan_unseal);
//B25 //B25
int enable_volume_fan = EXTRUDER_CONFIG(enable_volume_fan); int enable_volume_fan = EXTRUDER_CONFIG(enable_volume_fan);
int fan_speed_new = EXTRUDER_CONFIG(fan_always_on) ? min_fan_speed : 0; int fan_speed_new = EXTRUDER_CONFIG(fan_always_on) ? min_fan_speed : 0;
std::pair<int, int> custom_fan_speed_limits{fan_speed_new, 100 }; std::pair<int, int> custom_fan_speed_limits{fan_speed_new, 100 };
int disable_fan_first_layers = EXTRUDER_CONFIG(disable_fan_first_layers); int disable_fan_first_layers = EXTRUDER_CONFIG(disable_fan_first_layers);
//B39 //B39
int disable_rapid_cooling_fan_first_layers = EXTRUDER_CONFIG(disable_rapid_cooling_fan_first_layers); int disable_rapid_cooling_fan_first_layers = EXTRUDER_CONFIG(disable_rapid_cooling_fan_first_layers);
// Is the fan speed ramp enabled? // Is the fan speed ramp enabled?
int full_fan_speed_layer = EXTRUDER_CONFIG(full_fan_speed_layer); int full_fan_speed_layer = EXTRUDER_CONFIG(full_fan_speed_layer);
if (disable_fan_first_layers <= 0 && full_fan_speed_layer > 0) { if (disable_fan_first_layers <= 0 && full_fan_speed_layer > 0) {
@@ -862,21 +871,18 @@ std::string CoolingBuffer::apply_layer_cooldown(
new_gcode += fan_gcode.str(); new_gcode += fan_gcode.str();
} }
} }
//B25
if (int(layer_id) == disable_fan_first_layers) {
int volume_fan_speed_new = 255 * enable_volume_fan / 100;
if (volume_fan_speed_new != m_volume_fan_speed) {
std::ostringstream fan_gcode;
m_volume_fan_speed = volume_fan_speed_new;
fan_gcode << "M106 P3 S" << volume_fan_speed_new << "\n";
new_gcode += fan_gcode.str();
}
}
if (fan_speed_new != m_fan_speed) { if (fan_speed_new != m_fan_speed) {
m_fan_speed = fan_speed_new; m_fan_speed = fan_speed_new;
new_gcode += GCodeWriter::set_fan(m_config.gcode_flavor, m_config.gcode_comments, m_fan_speed); new_gcode += GCodeWriter::set_fan(m_config.gcode_flavor, m_config.gcode_comments, m_fan_speed);
} }
//B25
int volume_fan_speed_new = 255 * enable_volume_fan / 100;
if (volume_fan_speed_new != m_volume_fan_speed) {
std::ostringstream fan_gcode;
m_volume_fan_speed = volume_fan_speed_new;
fan_gcode << "M106 P3 S" << volume_fan_speed_new << "\n";
new_gcode += fan_gcode.str();
}
custom_fan_speed_limits.first = std::min(custom_fan_speed_limits.first, custom_fan_speed_limits.second); custom_fan_speed_limits.first = std::min(custom_fan_speed_limits.first, custom_fan_speed_limits.second);
return custom_fan_speed_limits; return custom_fan_speed_limits;
}; };

View File

@@ -683,7 +683,10 @@ void Layer::make_perimeters()
&& config.infill_overlap == other_config.infill_overlap && config.infill_overlap == other_config.infill_overlap
&& config.fuzzy_skin == other_config.fuzzy_skin && config.fuzzy_skin == other_config.fuzzy_skin
&& config.fuzzy_skin_thickness == other_config.fuzzy_skin_thickness && config.fuzzy_skin_thickness == other_config.fuzzy_skin_thickness
&& config.fuzzy_skin_point_dist == other_config.fuzzy_skin_point_dist) && config.fuzzy_skin_point_dist == other_config.fuzzy_skin_point_dist
//w38
&& config.overhang_reverse == other_config.overhang_reverse
&& config.overhang_reverse_threshold == other_config.overhang_reverse_threshold)
{ {
layer_region_reset_perimeters(*other_layerm); layer_region_reset_perimeters(*other_layerm);
layer_region_ids.push_back(it - m_regions.begin()); layer_region_ids.push_back(it - m_regions.begin());

View File

@@ -114,6 +114,8 @@ void LayerRegion::make_perimeters(
Polygons lower_layer_polygons_cache; Polygons lower_layer_polygons_cache;
//w16 //w16
Polygons upper_layer_polygons_cache; Polygons upper_layer_polygons_cache;
//w38
params.lower_slices = lower_slices;
for (const Surface &surface : slices) { for (const Surface &surface : slices) {
auto perimeters_begin = uint32_t(m_perimeters.size()); auto perimeters_begin = uint32_t(m_perimeters.size());
@@ -425,6 +427,7 @@ ExpansionResult expand_expolygons(
// Extract bridging surfaces from "surfaces", expand them into "shells" using expansion_params, // Extract bridging surfaces from "surfaces", expand them into "shells" using expansion_params,
// detect bridges. // detect bridges.
// Trim "shells" by the expanded bridges. // Trim "shells" by the expanded bridges.
//w36
Surfaces expand_bridges_detect_orientations(Surfaces & surfaces, Surfaces expand_bridges_detect_orientations(Surfaces & surfaces,
ExPolygons & shells, ExPolygons & shells,
const Algorithm::RegionExpansionParameters &expansion_params_into_solid_infill, const Algorithm::RegionExpansionParameters &expansion_params_into_solid_infill,
@@ -434,12 +437,14 @@ Surfaces expand_bridges_detect_orientations(Surfaces &
{ {
using namespace Slic3r::Algorithm; using namespace Slic3r::Algorithm;
//w36
double thickness; double thickness;
ExPolygons bridges_ex = fill_surfaces_extract_expolygons(surfaces, {stBottomBridge}, thickness); ExPolygons bridges_ex = fill_surfaces_extract_expolygons(surfaces, {stBottomBridge}, thickness);
if (bridges_ex.empty()) if (bridges_ex.empty())
return {}; return {};
// Calculate bridge anchors and their expansions in their respective shell region. // Calculate bridge anchors and their expansions in their respective shell region.
//w36
WaveSeeds bridge_anchors = wave_seeds(bridges_ex, shells, expansion_params_into_solid_infill.tiny_expansion, true); 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); 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_shells = !bridge_expansions.empty();
@@ -564,6 +569,7 @@ Surfaces expand_bridges_detect_orientations(Surfaces &
} }
// Merge the groups with the same group id, produce surfaces by merging source overhangs with their newly expanded anchors. // Merge the groups with the same group id, produce surfaces by merging source overhangs with their newly expanded anchors.
//w36
Surfaces out; Surfaces out;
{ {
Polygons acc; Polygons acc;
@@ -603,6 +609,7 @@ Surfaces expand_bridges_detect_orientations(Surfaces &
} }
// Clip by the expanded bridges. // Clip by the expanded bridges.
//w36
if (expanded_into_shells) if (expanded_into_shells)
shells = diff_ex(shells, out); shells = diff_ex(shells, out);
if (expanded_into_sparse) if (expanded_into_sparse)
@@ -610,14 +617,15 @@ Surfaces expand_bridges_detect_orientations(Surfaces &
return out; return out;
} }
static Surfaces expand_merge_surfaces(Surfaces & surfaces, //w36
Surfaces expand_merge_surfaces(Surfaces & surfaces,
SurfaceType surface_type, SurfaceType surface_type,
ExPolygons & shells, ExPolygons & shells,
const Algorithm::RegionExpansionParameters &expansion_params_into_solid_infill, const Algorithm::RegionExpansionParameters &expansion_params_into_solid_infill,
ExPolygons & sparse, ExPolygons & sparse,
const Algorithm::RegionExpansionParameters &expansion_params_into_sparse_infill, const Algorithm::RegionExpansionParameters &expansion_params_into_sparse_infill,
const float closing_radius, const float closing_radius,
const double bridge_angle = -1.) const double bridge_angle )
{ {
using namespace Slic3r::Algorithm; using namespace Slic3r::Algorithm;
@@ -626,6 +634,8 @@ static Surfaces expand_merge_surfaces(Surfaces &
if (src.empty()) if (src.empty())
return {}; return {};
//w36
std::vector<RegionExpansion> expansions = propagate_waves(src, shells, expansion_params_into_solid_infill); std::vector<RegionExpansion> expansions = propagate_waves(src, shells, expansion_params_into_solid_infill);
bool expanded_into_shells = !expansions.empty(); bool expanded_into_shells = !expansions.empty();
bool expanded_into_sparse = false; bool expanded_into_sparse = false;
@@ -645,6 +655,7 @@ static Surfaces expand_merge_surfaces(Surfaces &
// look for narrow_ensure_vertical_wall_thickness_region_radius filter. // look for narrow_ensure_vertical_wall_thickness_region_radius filter.
expanded = closing_ex(expanded, closing_radius); expanded = closing_ex(expanded, closing_radius);
// Trim the shells by the expanded expolygons. // Trim the shells by the expanded expolygons.
//w36
if (expanded_into_shells) if (expanded_into_shells)
shells = diff_ex(shells, expanded); shells = diff_ex(shells, expanded);
if (expanded_into_sparse) if (expanded_into_sparse)
@@ -697,13 +708,16 @@ void LayerRegion::process_external_surfaces(const Layer *lower_layer, const Poly
// Expand the top / bottom / bridge surfaces into the shell thickness solid infills. // Expand the top / bottom / bridge surfaces into the shell thickness solid infills.
double layer_thickness; double layer_thickness;
//w36
ExPolygons shells = union_ex(fill_surfaces_extract_expolygons(m_fill_surfaces.surfaces, {stInternalSolid}, 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 sparse = union_ex(fill_surfaces_extract_expolygons(m_fill_surfaces.surfaces, {stInternal}, layer_thickness));
SurfaceCollection bridges; SurfaceCollection bridges;
//w36
const auto expansion_params_into_sparse_infill = RegionExpansionParameters::build(expansion_min, expansion_step, max_nr_expansion_steps); const auto expansion_params_into_sparse_infill = RegionExpansionParameters::build(expansion_min, expansion_step, max_nr_expansion_steps);
{ {
BOOST_LOG_TRIVIAL(trace) << "Processing external surface, detecting bridges. layer" << this->layer()->print_z; BOOST_LOG_TRIVIAL(trace) << "Processing external surface, detecting bridges. layer" << this->layer()->print_z;
//w36
const double custom_angle = this->region().config().bridge_angle.value; const double custom_angle = this->region().config().bridge_angle.value;
const auto expansion_params_into_solid_infill = RegionExpansionParameters::build(expansion_bottom_bridge, expansion_step, const auto expansion_params_into_solid_infill = RegionExpansionParameters::build(expansion_bottom_bridge, expansion_step,
max_nr_expansion_steps); max_nr_expansion_steps);
@@ -721,6 +735,7 @@ void LayerRegion::process_external_surfaces(const Layer *lower_layer, const Poly
} }
#endif #endif
} }
//w36
Surfaces bottoms = expand_merge_surfaces(m_fill_surfaces.surfaces, stBottom, shells, Surfaces bottoms = expand_merge_surfaces(m_fill_surfaces.surfaces, stBottom, shells,
RegionExpansionParameters::build(expansion_bottom, expansion_step, max_nr_expansion_steps), RegionExpansionParameters::build(expansion_bottom, expansion_step, max_nr_expansion_steps),
@@ -731,15 +746,18 @@ void LayerRegion::process_external_surfaces(const Layer *lower_layer, const Poly
// m_fill_surfaces.remove_types({ stBottomBridge, stBottom, stTop, stInternal, stInternalSolid }); // m_fill_surfaces.remove_types({ stBottomBridge, stBottom, stTop, stInternal, stInternalSolid });
m_fill_surfaces.clear(); m_fill_surfaces.clear();
//w36
reserve_more(m_fill_surfaces.surfaces, shells.size() + sparse.size() + bridges.size() + bottoms.size() + tops.size()); reserve_more(m_fill_surfaces.surfaces, shells.size() + sparse.size() + bridges.size() + bottoms.size() + tops.size());
{ {
Surface solid_templ(stInternalSolid, {}); Surface solid_templ(stInternalSolid, {});
solid_templ.thickness = layer_thickness; solid_templ.thickness = layer_thickness;
//w36
m_fill_surfaces.append(std::move(shells), solid_templ); m_fill_surfaces.append(std::move(shells), solid_templ);
} }
{ {
Surface sparse_templ(stInternal, {}); Surface sparse_templ(stInternal, {});
sparse_templ.thickness = layer_thickness; sparse_templ.thickness = layer_thickness;
//w36
m_fill_surfaces.append(std::move(sparse), sparse_templ); m_fill_surfaces.append(std::move(sparse), sparse_templ);
} }
m_fill_surfaces.append(std::move(bridges.surfaces)); m_fill_surfaces.append(std::move(bridges.surfaces));

View File

@@ -205,23 +205,44 @@ struct ExpansionZone {
* detect bridges. * detect bridges.
* Trim "shells" by the expanded bridges. * Trim "shells" by the expanded bridges.
*/ */
Surfaces expand_bridges_detect_orientations( // w36
/* Surfaces expand_bridges_detect_orientations(
Surfaces &surfaces, Surfaces &surfaces,
std::vector<ExpansionZone>& expansion_zones, std::vector<ExpansionZone>& expansion_zones,
const float closing_radius const float closing_radius
); );*/
//w36
Surfaces expand_bridges_detect_orientations(Surfaces & surfaces,
ExPolygons & shells,
const Algorithm::RegionExpansionParameters &expansion_params_into_solid_infill,
ExPolygons & sparse,
const Algorithm::RegionExpansionParameters &expansion_params_into_sparse_infill,
const float closing_radius);
/** /**
* Extract bridging surfaces from "surfaces", expand them into "shells" using expansion_params. * Extract bridging surfaces from "surfaces", expand them into "shells" using expansion_params.
* Trim "shells" by the expanded bridges. * Trim "shells" by the expanded bridges.
*/ */
Surfaces expand_merge_surfaces(
// w36
/* Surfaces expand_merge_surfaces(
Surfaces &surfaces, Surfaces &surfaces,
SurfaceType surface_type, SurfaceType surface_type,
std::vector<ExpansionZone>& expansion_zones, std::vector<ExpansionZone>& expansion_zones,
const float closing_radius, const float closing_radius,
const double bridge_angle = -1 const double bridge_angle = -1
); );*/
// w36
Surfaces expand_merge_surfaces(Surfaces & surfaces,
SurfaceType surface_type,
ExPolygons & shells,
const Algorithm::RegionExpansionParameters &expansion_params_into_solid_infill,
ExPolygons & sparse,
const Algorithm::RegionExpansionParameters &expansion_params_into_sparse_infill,
const float closing_radius,
const double bridge_angle = -1.);
} }

View File

@@ -888,6 +888,16 @@ const BoundingBoxf3& ModelObject::bounding_box_approx() const
return m_bounding_box_approx; return m_bounding_box_approx;
} }
// B66
Polygon ModelInstance::convex_hull_2d()
{
Polygon convex_hull;
{
const Transform3d &trafo_instance = get_matrix();
convex_hull = get_object()->convex_hull_2d(trafo_instance);
}
return convex_hull;
}
// Returns the bounding box of the transformed instances. // Returns the bounding box of the transformed instances.
// This bounding box is approximate and not snug. // This bounding box is approximate and not snug.
const BoundingBoxf3& ModelObject::bounding_box_exact() const const BoundingBoxf3& ModelObject::bounding_box_exact() const

View File

@@ -1158,6 +1158,8 @@ public:
const Transform3d& get_matrix() const { return m_transformation.get_matrix(); } const Transform3d& get_matrix() const { return m_transformation.get_matrix(); }
Transform3d get_matrix_no_offset() const { return m_transformation.get_matrix_no_offset(); } Transform3d get_matrix_no_offset() const { return m_transformation.get_matrix_no_offset(); }
// B66
Polygon convex_hull_2d();
bool is_printable() const { return object->printable && printable && (print_volume_state == ModelInstancePVS_Inside); } bool is_printable() const { return object->printable && printable && (print_volume_state == ModelInstancePVS_Inside); }
void invalidate_object_bounding_box() { object->invalidate_bounding_box(); } void invalidate_object_bounding_box() { object->invalidate_bounding_box(); }

View File

@@ -285,12 +285,62 @@ static void fuzzy_extrusion_line(Arachne::ExtrusionLine &ext_lines, double fuzzy
using PerimeterGeneratorLoops = std::vector<PerimeterGeneratorLoop>; using PerimeterGeneratorLoops = std::vector<PerimeterGeneratorLoop>;
static ExtrusionEntityCollection traverse_loops_classic(const PerimeterGenerator::Parameters &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 // loops is an arrayref of ::Loop objects
// turn each one into an ExtrusionLoop object // turn each one into an ExtrusionLoop object
ExtrusionEntityCollection coll; ExtrusionEntityCollection coll;
Polygon fuzzified; Polygon fuzzified;
//w38
bool overhangs_reverse = params.config.overhang_reverse &&
params.layer_id % 2 == 1;
for (const PerimeterGeneratorLoop &loop : loops) { for (const PerimeterGeneratorLoop &loop : loops) {
bool is_external = loop.is_external(); bool is_external = loop.is_external();
@@ -301,13 +351,24 @@ static ExtrusionEntityCollection traverse_loops_classic(const PerimeterGenerator
// Note that we set loop role to ContourInternalPerimeter // Note that we set loop role to ContourInternalPerimeter
// also when loop is both internal and external (i.e. // also when loop is both internal and external (i.e.
// there's only one contour loop). // there's only one contour loop).
loop_role = elrContourInternalPerimeter; //w38
loop_role = elrInternal;//loop_role = elrContourInternalPerimeter;
} else { } else {
loop_role = elrDefault; //w38
loop_role = loop.is_contour? elrDefault : elrHole;//loop_role = elrDefault;
} }
// detect overhanging/bridging perimeters // detect overhanging/bridging perimeters
ExtrusionPaths paths; ExtrusionPaths paths;
//w38
double extrusion_width;
if (is_external) {
extrusion_width = params.ext_perimeter_flow.width();
} else {
extrusion_width = params.perimeter_flow.width();
}
const Polygon &polygon = loop.fuzzify ? fuzzified : loop.polygon; const Polygon &polygon = loop.fuzzify ? fuzzified : loop.polygon;
if (loop.fuzzify) { if (loop.fuzzify) {
fuzzified = loop.polygon; fuzzified = loop.polygon;
@@ -318,6 +379,19 @@ static ExtrusionEntityCollection traverse_loops_classic(const PerimeterGenerator
params.object_config.support_material_contact_distance.value == 0)) { params.object_config.support_material_contact_distance.value == 0)) {
BoundingBox bbox(polygon.points); BoundingBox bbox(polygon.points);
bbox.offset(SCALED_EPSILON); bbox.offset(SCALED_EPSILON);
//w38
if (overhangs_reverse && params.config.fuzzy_skin != FuzzySkinType::None) {
if (loop.is_contour) {
steep_overhang_contour = true;
} else if (params.config.fuzzy_skin != FuzzySkinType::External) {
steep_overhang_hole = true;
}
}
bool found_steep_overhang = (loop.is_contour && steep_overhang_contour) || (!loop.is_contour && steep_overhang_hole);
if (overhangs_reverse && !found_steep_overhang) {
detect_steep_overhang(params.config, loop.is_contour, bbox, extrusion_width, Polygons{polygon},
params.lower_slices, steep_overhang_contour, steep_overhang_hole);
}
Polygons lower_slices_polygons_clipped = ClipperUtils::clip_clipper_polygons_with_subject_bbox(lower_slices_polygons_cache, bbox); Polygons lower_slices_polygons_clipped = ClipperUtils::clip_clipper_polygons_with_subject_bbox(lower_slices_polygons_cache, bbox);
// get non-overhang paths by intersecting this loop with the grown lower slices // get non-overhang paths by intersecting this loop with the grown lower slices
extrusion_paths_append( extrusion_paths_append(
@@ -381,10 +455,13 @@ static ExtrusionEntityCollection traverse_loops_classic(const PerimeterGenerator
} else { } else {
const PerimeterGeneratorLoop &loop = loops[idx.first]; const PerimeterGeneratorLoop &loop = loops[idx.first];
assert(thin_walls.empty()); assert(thin_walls.empty());
ExtrusionEntityCollection children = traverse_loops_classic(params, lower_slices_polygons_cache, loop.children, thin_walls); //w38
ExtrusionEntityCollection children = traverse_loops_classic(params, lower_slices_polygons_cache, loop.children, thin_walls,steep_overhang_contour, steep_overhang_hole);
out.entities.reserve(out.entities.size() + children.entities.size() + 1); out.entities.reserve(out.entities.size() + children.entities.size() + 1);
ExtrusionLoop *eloop = static_cast<ExtrusionLoop*>(coll.entities[idx.first]); ExtrusionLoop *eloop = static_cast<ExtrusionLoop*>(coll.entities[idx.first]);
coll.entities[idx.first] = nullptr; coll.entities[idx.first] = nullptr;
//w38
//eloop->make_counter_clockwise();
if (loop.is_contour) { if (loop.is_contour) {
if (eloop->is_clockwise()) if (eloop->is_clockwise())
eloop->reverse_loop(); eloop->reverse_loop();
@@ -505,8 +582,16 @@ struct PerimeterGeneratorArachneExtrusion
bool fuzzify = false; bool fuzzify = false;
}; };
static ExtrusionEntityCollection traverse_extrusions(const PerimeterGenerator::Parameters &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; ExtrusionEntityCollection extrusion_coll;
for (PerimeterGeneratorArachneExtrusion &pg_extrusion : pg_extrusions) { for (PerimeterGeneratorArachneExtrusion &pg_extrusion : pg_extrusions) {
Arachne::ExtrusionLine *extrusion = pg_extrusion.extrusion; Arachne::ExtrusionLine *extrusion = pg_extrusion.extrusion;
@@ -556,6 +641,40 @@ static ExtrusionEntityCollection traverse_extrusions(const PerimeterGenerator::P
extrusion_paths_append(paths, clip_extrusion(extrusion_path, lower_slices_paths, ClipperLib_Z::ctIntersection), role_normal, extrusion_paths_append(paths, clip_extrusion(extrusion_path, lower_slices_paths, ClipperLib_Z::ctIntersection), role_normal,
is_external ? params.ext_perimeter_flow : params.perimeter_flow); is_external ? params.ext_perimeter_flow : params.perimeter_flow);
//w38
if (overhangs_reverse && params.config.fuzzy_skin != FuzzySkinType::None) {
if (pg_extrusion.is_contour) {
steep_overhang_contour = true;
} else if (params.config.fuzzy_skin != FuzzySkinType::External) {
steep_overhang_hole = true;
}
}
bool found_steep_overhang = (pg_extrusion.is_contour && steep_overhang_contour) ||
(!pg_extrusion.is_contour && steep_overhang_hole);
if (overhangs_reverse && !found_steep_overhang) {
std::map<double, ExtrusionPaths> recognization_paths;
for (const ExtrusionPath &path : paths) {
if (recognization_paths.count(path.width()))
recognization_paths[path.width()].emplace_back(std::move(path));
else
recognization_paths.insert(std::pair<double, ExtrusionPaths>(path.width(), {std::move(path)}));
}
for (const auto &it : recognization_paths) {
Polylines be_clipped;
for (const ExtrusionPath &p : it.second) {
be_clipped.emplace_back(std::move(p.polyline));
}
BoundingBox extrusion_bboxs = get_extents(be_clipped);
if (detect_steep_overhang(params.config, pg_extrusion.is_contour, extrusion_bboxs, it.first, be_clipped,
params.lower_slices, steep_overhang_contour, steep_overhang_hole)) {
break;
}
}
}
// get overhang paths by checking what parts of this loop fall // get overhang paths by checking what parts of this loop fall
// outside the grown lower slices (thus where the distance between // outside the grown lower slices (thus where the distance between
// the loop centerline and original lower slices is >= half nozzle diameter // the loop centerline and original lower slices is >= half nozzle diameter
@@ -571,6 +690,9 @@ static ExtrusionEntityCollection traverse_extrusions(const PerimeterGenerator::P
// Especially for open extrusion, we need to select a starting point that is at the start // Especially for open extrusion, we need to select a starting point that is at the start
// or the end of the extrusions to make one continuous line. Also, we prefer a non-overhang // or the end of the extrusions to make one continuous line. Also, we prefer a non-overhang
// starting point. // starting point.
//w38
//ExtrusionLoop extrusion_loop(std::move(paths), pg_extrusion.is_contour ? elrDefault : elrHole);
//extrusion_loop.make_counter_clockwise();
struct PointInfo struct PointInfo
{ {
size_t occurrence = 0; size_t occurrence = 0;
@@ -1105,6 +1227,33 @@ void PerimeterGenerator::add_infill_contour_for_arachne(ExPolygons infill_contou
} }
//w38
static void reorient_perimeters(ExtrusionEntityCollection &entities, bool steep_overhang_contour, bool steep_overhang_hole, bool reverse_internal_only)
{
if (steep_overhang_hole || steep_overhang_contour) {
for (auto entity : entities) {
if (entity->is_loop()) {
ExtrusionLoop *eloop = static_cast<ExtrusionLoop *>(entity);
bool need_reverse = ((eloop->loop_role() & elrHole) == elrHole) ? steep_overhang_hole : steep_overhang_contour;
bool isExternal = false;
if (reverse_internal_only) {
for (auto path : eloop->paths) {
if (path.role().is_external_perimeter()) {
isExternal = true;
break;
}
}
}
if (need_reverse && !isExternal) {
eloop->make_clockwise();
}
}
}
}
}
// Thanks, Cura developers, for implementing an algorithm for generating perimeters with variable width (Arachne) that is based on the paper // Thanks, Cura developers, for implementing an algorithm for generating perimeters with variable width (Arachne) that is based on the paper
// "A framework for adaptive width control of dense contour-parallel toolpaths in fused deposition modeling" // "A framework for adaptive width control of dense contour-parallel toolpaths in fused deposition modeling"
void PerimeterGenerator::process_arachne( void PerimeterGenerator::process_arachne(
@@ -1149,15 +1298,27 @@ void PerimeterGenerator::process_arachne(
// extra perimeters for each one // extra perimeters for each one
// detect how many perimeters must be generated for this island // detect how many perimeters must be generated for this island
int loop_number = params.config.perimeters + surface.extra_perimeters - 1; // 0-indexed loops int loop_number = params.config.perimeters + surface.extra_perimeters - 1; // 0-indexed loops
ExPolygons last = offset_ex(surface.expolygon.simplify_p(params.scaled_resolution), - float(ext_perimeter_width / 2. - ext_perimeter_spacing / 2.)); //w39
//ExPolygons last = offset_ex(surface.expolygon.simplify_p(params.scaled_resolution), - float(ext_perimeter_width / 2. - ext_perimeter_spacing / 2.));
double surface_simplify_resolution = (params.print_config.arc_fitting != ArcFittingType::Disabled &&
params.config.fuzzy_skin == FuzzySkinType::None) ?
0.2 * scale_(params.print_config.resolution) :
params.print_config.resolution;
auto apply_precise_outer_wall = params.config.precise_outer_wall && !params.config.external_perimeters_first;
ExPolygons last = apply_precise_outer_wall? offset_ex(surface.expolygon.simplify_p(surface_simplify_resolution),
-float(ext_perimeter_width - ext_perimeter_spacing) ) :offset_ex(surface.expolygon.simplify_p(params.scaled_resolution),
-float(ext_perimeter_width / 2. - ext_perimeter_spacing / 2.));
coord_t wall_0_inset = 0;
if (apply_precise_outer_wall)
wall_0_inset = -coord_t(ext_perimeter_width / 2 - ext_perimeter_spacing / 2);
Polygons last_p = to_polygons(last); Polygons last_p = to_polygons(last);
//w16 //w16
//w23 //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)) if ((upper_slices == nullptr && params.object_config.top_one_wall_type == TopOneWallType::Onlytopmost)||(params.object_config.only_one_wall_first_layer && layer_id == 0))
loop_number = 0; loop_number = 0;
//w39
Arachne::WallToolPaths wallToolPaths(last_p, ext_perimeter_spacing, perimeter_spacing, coord_t(loop_number + 1), 0, params.layer_height, params.object_config, params.print_config); Arachne::WallToolPaths wallToolPaths(last_p, ext_perimeter_spacing, perimeter_spacing, coord_t(loop_number + 1), wall_0_inset, params.layer_height, params.object_config, params.print_config);
std::vector<Arachne::VariableWidthLines> perimeters = wallToolPaths.getToolPaths(); std::vector<Arachne::VariableWidthLines> perimeters = wallToolPaths.getToolPaths();
loop_number = int(perimeters.size()) - 1; loop_number = int(perimeters.size()) - 1;
@@ -1308,8 +1469,15 @@ void PerimeterGenerator::process_arachne(
} }
} }
if (ExtrusionEntityCollection extrusion_coll = traverse_extrusions(params, lower_slices_polygons_cache, ordered_extrusions); !extrusion_coll.empty()) //w38
bool steep_overhang_contour = false;
bool steep_overhang_hole = false;
if (ExtrusionEntityCollection extrusion_coll = traverse_extrusions(params, lower_slices_polygons_cache, ordered_extrusions,
steep_overhang_contour, steep_overhang_hole);
!extrusion_coll.empty()) {
reorient_perimeters(extrusion_coll, steep_overhang_contour, steep_overhang_hole, params.config.overhang_reverse_internal_only);
out_loops.append(extrusion_coll); out_loops.append(extrusion_coll);
}
ExPolygons infill_contour = union_ex(wallToolPaths.getInnerContour()); ExPolygons infill_contour = union_ex(wallToolPaths.getInnerContour());
//w17 //w17
@@ -1427,7 +1595,20 @@ void PerimeterGenerator::process_with_one_wall_arachne(
//w23 //w23
if (params.object_config.only_one_wall_first_layer && layer_id == 0) if (params.object_config.only_one_wall_first_layer && layer_id == 0)
loop_number = 0; loop_number = 0;
ExPolygons last = offset_ex(surface.expolygon.simplify_p(params.scaled_resolution), - float(ext_perimeter_width / 2. - ext_perimeter_spacing / 2.)); //w39
//ExPolygons last = offset_ex(surface.expolygon.simplify_p(params.scaled_resolution), - float(ext_perimeter_width / 2. - ext_perimeter_spacing / 2.));
double surface_simplify_resolution = (params.print_config.arc_fitting != ArcFittingType::Disabled &&
params.config.fuzzy_skin == FuzzySkinType::None) ?
0.2 * scale_(params.print_config.resolution) :
params.print_config.resolution;
auto apply_precise_outer_wall = params.config.precise_outer_wall && !params.config.external_perimeters_first;
ExPolygons last = apply_precise_outer_wall ? offset_ex(surface.expolygon.simplify_p(surface_simplify_resolution),
-float(ext_perimeter_width - ext_perimeter_spacing)) :
offset_ex(surface.expolygon.simplify_p(params.scaled_resolution),
-float(ext_perimeter_width / 2. - ext_perimeter_spacing / 2.));
coord_t wall_0_inset = 0;
if (apply_precise_outer_wall)
wall_0_inset = -coord_t(ext_perimeter_width / 2 - ext_perimeter_spacing / 2);
Polygons last_p = to_polygons(last); Polygons last_p = to_polygons(last);
int remain_loops = -1; int remain_loops = -1;
@@ -1437,8 +1618,8 @@ void PerimeterGenerator::process_with_one_wall_arachne(
loop_number = 0; loop_number = 0;
} }
//w39
Arachne::WallToolPaths wallToolPaths(last_p, ext_perimeter_spacing, perimeter_spacing, coord_t(loop_number + 1), 0, params.layer_height, params.object_config, params.print_config); Arachne::WallToolPaths wallToolPaths(last_p, ext_perimeter_spacing, perimeter_spacing, coord_t(loop_number + 1), wall_0_inset, params.layer_height, params.object_config, params.print_config);
std::vector<Arachne::VariableWidthLines> perimeters = wallToolPaths.getToolPaths(); std::vector<Arachne::VariableWidthLines> perimeters = wallToolPaths.getToolPaths();
loop_number = int(perimeters.size()) - 1; loop_number = int(perimeters.size()) - 1;
@@ -1645,8 +1826,15 @@ void PerimeterGenerator::process_with_one_wall_arachne(
} }
} }
if (ExtrusionEntityCollection extrusion_coll = traverse_extrusions(params, lower_slices_polygons_cache, ordered_extrusions); !extrusion_coll.empty()) //w38
bool steep_overhang_contour = false;
bool steep_overhang_hole = false;
if (ExtrusionEntityCollection extrusion_coll = traverse_extrusions(params, lower_slices_polygons_cache, ordered_extrusions,
steep_overhang_contour, steep_overhang_hole);
!extrusion_coll.empty()) {
reorient_perimeters(extrusion_coll, steep_overhang_contour, steep_overhang_hole, params.config.overhang_reverse_internal_only);
out_loops.append(extrusion_coll); out_loops.append(extrusion_coll);
}
//w16 //w16
@@ -1789,7 +1977,13 @@ void PerimeterGenerator::process_classic(
// external perimeters // external perimeters
coord_t ext_perimeter_width = params.ext_perimeter_flow.scaled_width(); coord_t ext_perimeter_width = params.ext_perimeter_flow.scaled_width();
coord_t ext_perimeter_spacing = params.ext_perimeter_flow.scaled_spacing(); coord_t ext_perimeter_spacing = params.ext_perimeter_flow.scaled_spacing();
coord_t ext_perimeter_spacing2 = scaled<coord_t>(0.5f * (params.ext_perimeter_flow.spacing() + params.perimeter_flow.spacing())); coord_t ext_perimeter_spacing2; //= scaled<coord_t>(0.5f * (params.ext_perimeter_flow.spacing() + params.perimeter_flow.spacing()));
//w39
if (params.config.precise_outer_wall && !params.config.external_perimeters_first)
ext_perimeter_spacing2 = scaled<coord_t>(0.5f * (params.ext_perimeter_flow.width() + params.perimeter_flow.width()));
else
ext_perimeter_spacing2 = scaled<coord_t>(0.5f * (params.ext_perimeter_flow.spacing() + params.perimeter_flow.spacing()));
// solid infill // solid infill
coord_t solid_infill_spacing = params.solid_infill_flow.scaled_spacing(); coord_t solid_infill_spacing = params.solid_infill_flow.scaled_spacing();
@@ -2037,7 +2231,11 @@ void PerimeterGenerator::process_classic(
} }
} }
// at this point, all loops should be in contours[0] // at this point, all loops should be in contours[0]
ExtrusionEntityCollection entities = traverse_loops_classic(params, lower_layer_polygons_cache, contours.front(), thin_walls); //w38
bool steep_overhang_contour = false;
bool steep_overhang_hole = false;
ExtrusionEntityCollection entities = traverse_loops_classic(params, lower_layer_polygons_cache, contours.front(), thin_walls,steep_overhang_contour, steep_overhang_hole);
reorient_perimeters(entities, steep_overhang_contour, steep_overhang_hole, params.config.overhang_reverse_internal_only);
// if brim will be printed, reverse the order of perimeters so that // if brim will be printed, reverse the order of perimeters so that
// we continue inwards after having finished the brim // we continue inwards after having finished the brim
// TODO: add test for perimeter order // TODO: add test for perimeter order

View File

@@ -39,7 +39,9 @@ struct Parameters {
scaled_resolution(scaled<double>(print_config.gcode_resolution.value)), scaled_resolution(scaled<double>(print_config.gcode_resolution.value)),
mm3_per_mm(perimeter_flow.mm3_per_mm()), mm3_per_mm(perimeter_flow.mm3_per_mm()),
ext_mm3_per_mm(ext_perimeter_flow.mm3_per_mm()), ext_mm3_per_mm(ext_perimeter_flow.mm3_per_mm()),
mm3_per_mm_overhang(overhang_flow.mm3_per_mm()) mm3_per_mm_overhang(overhang_flow.mm3_per_mm()),
//w38
lower_slices(lower_slices)
{ {
} }
@@ -53,6 +55,8 @@ struct Parameters {
const PrintRegionConfig &config; const PrintRegionConfig &config;
const PrintObjectConfig &object_config; const PrintObjectConfig &object_config;
const PrintConfig &print_config; const PrintConfig &print_config;
//w38
const ExPolygons * lower_slices;
// Derived parameters // Derived parameters
bool spiral_vase; bool spiral_vase;

View File

@@ -90,7 +90,7 @@ int Point::nearest_point_index(const Points &points) const
p.push_back(&*it); p.push_back(&*it);
return this->nearest_point_index(p); return this->nearest_point_index(p);
} }
//w29
int Point::nearest_point_index(const PointConstPtrs &points) const int Point::nearest_point_index(const PointConstPtrs &points) const
{ {
int idx = -1; int idx = -1;
@@ -118,7 +118,7 @@ int Point::nearest_point_index(const PointConstPtrs &points) const
return idx; return idx;
} }
//w29
int Point::nearest_point_index(const PointPtrs &points) const int Point::nearest_point_index(const PointPtrs &points) const
{ {
PointConstPtrs p; PointConstPtrs p;

View File

@@ -466,35 +466,41 @@ static std::vector<std::string> s_Preset_print_options {
"wipe_tower_width", "wipe_tower_cone_angle", "wipe_tower_rotation_angle", "wipe_tower_brim_width", "wipe_tower_bridging", "single_extruder_multi_material_priming", "mmu_segmented_region_max_width", "wipe_tower_width", "wipe_tower_cone_angle", "wipe_tower_rotation_angle", "wipe_tower_brim_width", "wipe_tower_bridging", "single_extruder_multi_material_priming", "mmu_segmented_region_max_width",
"mmu_segmented_region_interlocking_depth", "wipe_tower_extruder", "wipe_tower_no_sparse_layers", "wipe_tower_extra_flow", "wipe_tower_extra_spacing", "compatible_printers", "compatible_printers_condition", "inherits", "mmu_segmented_region_interlocking_depth", "wipe_tower_extruder", "wipe_tower_no_sparse_layers", "wipe_tower_extra_flow", "wipe_tower_extra_spacing", "compatible_printers", "compatible_printers_condition", "inherits",
"perimeter_generator", "wall_transition_length", "wall_transition_filter_deviation", "wall_transition_angle", "perimeter_generator", "wall_transition_length", "wall_transition_filter_deviation", "wall_transition_angle",
"wall_distribution_count", "min_feature_size", "min_bead_width" "wall_distribution_count", "min_feature_size", "min_bead_width",
//B36 //B36
,"first_layer_travel_speed" "first_layer_travel_speed",
//B37 //B37
,"first_layer_infill_speed" "first_layer_infill_speed",
//w11 //w11
,"detect_narrow_internal_solid_infill" "detect_narrow_internal_solid_infill",
//Y21 //Y21
,"seam_gap" "seam_gap",
//w16 //w16
, "top_one_wall_type" "top_one_wall_type",
//w17 //w17
,"top_area_threshold" "top_area_threshold",
//w21 //w21
,"filter_top_gap_infill" "filter_top_gap_infill",
//w23 //w23
,"only_one_wall_first_layer" "only_one_wall_first_layer",
//w25 //w25
,"slow_down_layers" "slow_down_layers",
//w26 //w26
,"elefant_foot_compensation_layers" "elefant_foot_compensation_layers",
//w27 //w27
,"precise_z_height" "precise_z_height",
//w28 //w28
,"max_bridge_length" "max_bridge_length",
//w30 //w30
,"top_solid_infill_flow_ratio", "bottom_solid_infill_flow_ratio" "top_solid_infill_flow_ratio", "bottom_solid_infill_flow_ratio",
//w33 //w33
,"ironing_pattern" "ironing_pattern",
//w38
"overhang_reverse", "overhang_reverse_internal_only", "overhang_reverse_threshold",
//w39
"precise_outer_wall",
//Y27
"resonance_avoidance", "min_resonance_avoidance_speed", "max_resonance_avoidance_speed"
}; };
static std::vector<std::string> s_Preset_filament_options { static std::vector<std::string> s_Preset_filament_options {
@@ -515,6 +521,8 @@ static std::vector<std::string> s_Preset_filament_options {
"filament_vendor", "compatible_prints", "compatible_prints_condition", "compatible_printers", "compatible_printers_condition", "inherits", "filament_vendor", "compatible_prints", "compatible_prints_condition", "compatible_printers", "compatible_printers_condition", "inherits",
//B15 //B15
"enable_auxiliary_fan", "enable_auxiliary_fan",
//Y26
"enable_auxiliary_fan_unseal",
//B24 //B24
"volume_temperature", "volume_temperature",
//B25 //B25
@@ -529,6 +537,10 @@ static std::vector<std::string> s_Preset_filament_options {
"disable_rapid_cooling_fan_first_layers", "disable_rapid_cooling_fan_first_layers",
//Y23 //Y23
"filament_shrink", "filament_shrink",
//Y26
"seal_print",
//Y28
"dont_slow_down_outer_wall",
//w15 //w15
"filament_wipe_distance" "filament_wipe_distance"
}; };

View File

@@ -179,7 +179,8 @@ void PresetBundle::setup_directories()
data_dir / "sla_print", data_dir / "sla_print",
data_dir / "sla_material", data_dir / "sla_material",
data_dir / "printer", data_dir / "printer",
data_dir / "physical_printer" data_dir / "physical_printer",
data_dir / "user" // y5
#endif #endif
}; };
for (const boost::filesystem::path &path : paths) { for (const boost::filesystem::path &path : paths) {
@@ -253,7 +254,8 @@ void PresetBundle::import_newer_configs(const std::string& from)
from_data_dir / "sla_print", from_data_dir / "sla_print",
from_data_dir / "sla_material", from_data_dir / "sla_material",
from_data_dir / "printer", from_data_dir / "printer",
from_data_dir / "physical_printer" from_data_dir / "physical_printer",
from_data_dir / "user" //y5
#endif #endif
}; };
// copy recursively all files // copy recursively all files
@@ -2047,4 +2049,17 @@ void copy_bed_model_and_texture_if_needed(DynamicPrintConfig& config)
do_copy(config.option<ConfigOptionString>("bed_custom_model"), "model"); do_copy(config.option<ConfigOptionString>("bed_custom_model"), "model");
} }
// y3
std::set<std::string> PresetBundle::get_vendors()
{
std::set<std::string> qidiVendors;
for (auto vendor_profile : vendors) {
for (auto vendor_model : vendor_profile.second.models) {
std::string vendor_name = vendor_model.name;
qidiVendors.emplace(vendor_name);
}
}
return qidiVendors;
}
} // namespace Slic3r } // namespace Slic3r

View File

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

View File

@@ -83,6 +83,8 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
"disable_fan_first_layers", "disable_fan_first_layers",
//B39 //B39
"disable_rapid_cooling_fan_first_layers", "disable_rapid_cooling_fan_first_layers",
//Y28
"dont_slow_down_outer_wall",
"duplicate_distance", "duplicate_distance",
"end_gcode", "end_gcode",
"end_filament_gcode", "end_filament_gcode",

View File

@@ -980,6 +980,7 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
new_full_config.option("physical_printer_settings_id", true); new_full_config.option("physical_printer_settings_id", true);
new_full_config.normalize_fdm(); new_full_config.normalize_fdm();
// Find modified keys of the various configs. Resolve overrides extruder retract values by filament profiles. // Find modified keys of the various configs. Resolve overrides extruder retract values by filament profiles.
DynamicPrintConfig filament_overrides; DynamicPrintConfig filament_overrides;
t_config_option_keys print_diff = print_config_diffs(m_config, new_full_config, filament_overrides); t_config_option_keys print_diff = print_config_diffs(m_config, new_full_config, filament_overrides);

View File

@@ -332,6 +332,13 @@ void PrintConfigDef::init_common_params()
def->mode = comAdvanced; def->mode = comAdvanced;
def->set_default_value(new ConfigOptionBool(0)); def->set_default_value(new ConfigOptionBool(0));
//w39
def = this->add("precise_outer_wall", coBool);
def->label = L("Precise wall");
def->tooltip = L("Improve shell precision by adjusting outer wall spacing. This also improves layer consistency.\nNote: This setting "
"will only take effect if the wall sequence is configured to Inner-Outer");
def->set_default_value(new ConfigOptionBool{false});
def = this->add("thumbnails", coString); def = this->add("thumbnails", coString);
def->label = L("G-code thumbnails"); def->label = L("G-code thumbnails");
def->tooltip = L("Picture sizes to be stored into a .gcode / .bgcode and .sl1 / .sl1s files, in the following format: \"XxY/EXT, XxY/EXT, ...\"\n" def->tooltip = L("Picture sizes to be stored into a .gcode / .bgcode and .sl1 / .sl1s files, in the following format: \"XxY/EXT, XxY/EXT, ...\"\n"
@@ -522,6 +529,13 @@ void PrintConfigDef::init_fff_params()
def->max = 65; def->max = 65;
def->set_default_value(new ConfigOptionInts { 0 }); def->set_default_value(new ConfigOptionInts { 0 });
//Y26
def = this->add("seal_print", coBool);
def->label = L("Seal");
def->tooltip = L("Sealing box printing will be more stable and reliable, but the heat dissipation of the model will be poor. "
"Determine whether to unpack and print according to the actual situation.");
def->set_default_value(new ConfigOptionBool(true));
def = this->add("before_layer_gcode", coString); def = this->add("before_layer_gcode", coString);
def->label = L("Before layer change G-code"); def->label = L("Before layer change G-code");
def->tooltip = L("This custom code is inserted at every layer change, right before the Z move. " def->tooltip = L("This custom code is inserted at every layer change, right before the Z move. "
@@ -688,6 +702,30 @@ void PrintConfigDef::init_fff_params()
def->mode = comExpert; def->mode = comExpert;
def->set_default_value(new ConfigOptionBools{false}); def->set_default_value(new ConfigOptionBools{false});
//Y27
def = this->add("resonance_avoidance", coBool);
def->label = L("Resonance avoidance");
def->tooltip = L("By reducing the speed of the outer wall to avoid the resonance zone of the printer, ringing on the surface of the model are avoided.\n"
"Please turn this option off when testing ringing.");
def->mode = comExpert;
def->set_default_value(new ConfigOptionBool(true));
def = this->add("min_resonance_avoidance_speed", coFloat);
def->label = L("Min");
def->tooltip = L("Minimum speed of resonance avoidance.");
def->sidetext = L("mm/s");
def->min = 0;
def->mode = comExpert;
def->set_default_value(new ConfigOptionFloat(70));
def = this->add("max_resonance_avoidance_speed", coFloat);
def->label = L("Max");
def->tooltip = L("Maximum speed of resonance avoidance.");
def->sidetext = L("mm/s");
def->min = 0;
def->mode = comExpert;
def->set_default_value(new ConfigOptionFloat(120));
// TRN FilamentSettings : "Dynamic fan speeds" // TRN FilamentSettings : "Dynamic fan speeds"
auto fan_speed_setting_description = L("Overhang size is expressed as a percentage of overlap of the extrusion with the previous layer: " auto fan_speed_setting_description = L("Overhang size is expressed as a percentage of overlap of the extrusion with the previous layer: "
"100% would be full overlap (no overhang), while 0% represents full overhang (floating extrusion, bridge). " "100% would be full overlap (no overhang), while 0% represents full overhang (floating extrusion, bridge). "
@@ -1984,6 +2022,7 @@ void PrintConfigDef::init_fff_params()
def->mode = comAdvanced; def->mode = comAdvanced;
def->set_default_value(new ConfigOptionEnum<MachineLimitsUsage>(MachineLimitsUsage::TimeEstimateOnly)); def->set_default_value(new ConfigOptionEnum<MachineLimitsUsage>(MachineLimitsUsage::TimeEstimateOnly));
{ {
struct AxisDefault { struct AxisDefault {
std::string name; std::string name;
@@ -2191,15 +2230,24 @@ void PrintConfigDef::init_fff_params()
def->mode = comExpert; def->mode = comExpert;
def->set_default_value(new ConfigOptionBool(false)); def->set_default_value(new ConfigOptionBool(false));
//B15 //B15//Y26
def = this->add("enable_auxiliary_fan", coInts); def = this->add("enable_auxiliary_fan", coInts);
def->label = L("Rapid Cooling Fan Speed"); def->label = L("Seal");
def->tooltip = L("This setting represents the PWM your rapid cooling fan needs to work."); def->tooltip = L("This setting represents the PWM your rapid cooling fan needs to work when the printing is sealing.");
def->sidetext = L("%"); def->sidetext = L("%");
def->min = 0; def->min = 0;
def->max = 100; def->max = 100;
def->mode = comExpert; def->mode = comExpert;
def->set_default_value(new ConfigOptionInts { 35 }); def->set_default_value(new ConfigOptionInts { 100 });
def = this->add("enable_auxiliary_fan_unseal", coInts);
def->label = L("Unseal");
def->tooltip = L("This setting represents the PWM your rapid cooling fan needs to work when the printing is unsealing.");
def->sidetext = L("%");
def->min = 0;
def->max = 100;
def->mode = comExpert;
def->set_default_value(new ConfigOptionInts { 0 });
//B25 //B25
def = this->add("enable_volume_fan", coInts); def = this->add("enable_volume_fan", coInts);
@@ -2220,6 +2268,17 @@ void PrintConfigDef::init_fff_params()
def->mode = comAdvanced; def->mode = comAdvanced;
def->set_default_value(new ConfigOptionFloats { 0.07 }); def->set_default_value(new ConfigOptionFloats { 0.07 });
//Y28
def = this->add("dont_slow_down_outer_wall", coBools);
def->label = L("Don't slow down outer walls");
def->tooltip = L("If enabled, this setting will ensure external perimeters are not slowed down to meet the minimum layer time. "
"This is particularly helpful in the below scenarios:\n\n "
"1. To avoid changes in shine when printing glossy filaments \n"
"2. To avoid changes in external wall speed which may create slight wall artefacts that appear like z banding \n"
"3. To avoid printing at speeds which cause VFAs (fine artefacts) on the external walls\n\n");
def->mode = comExpert;
def->set_default_value(new ConfigOptionBools { true });
def = this->add("min_print_speed", coFloats); def = this->add("min_print_speed", coFloats);
def->label = L("Min print speed"); def->label = L("Min print speed");
def->tooltip = L("Slic3r will not scale speed down below this speed."); def->tooltip = L("Slic3r will not scale speed down below this speed.");
@@ -2307,6 +2366,40 @@ void PrintConfigDef::init_fff_params()
def->mode = comAdvanced; def->mode = comAdvanced;
def->set_default_value(new ConfigOptionBool(true)); def->set_default_value(new ConfigOptionBool(true));
//w38
def = this->add("overhang_reverse", coBool);
def->label = L("Reverse on odd");
def->category = L("Layers and Perimeters");
def->tooltip = L("Extrude perimeters that have a part over an overhang in the reverse direction on odd layers. This alternating "
"pattern can drastically improve steep overhang.");
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionBool(false));
def = this->add("overhang_reverse_internal_only", coBool);
def->label = L("Reverse only internal perimeters");
def->category = L("Layers and Perimeters");
def->tooltip = L("Apply the reverse perimeters logic only on internal perimeters. \n\nThis setting greatly reduces part stresses as "
"they are now distributed in alternating directions. This should reduce part warping while also maintaining external "
"wall quality. This feature can be very useful for warp prone material, like ABS/ASA, and also for elastic filaments, "
"like TPU and Silk PLA. It can also help reduce warping on floating regions over supports.\n\nFor this setting to be "
"the most effective, it is recomended to set the Reverse Threshold to 0 so that all internal walls print in "
"alternating directions on odd layers irrespective of their overhang degree.");
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionBool(false));
//w38
def = this->add("overhang_reverse_threshold", coFloatOrPercent);
def->label = L("Reverse threshold");
def->category = L("Layers and Perimeters");
def->tooltip = L("Number of mm the overhang need to be for the reversal to be considered useful. Can be a % of the perimeter width."
"\nValue 0 enables reversal on every odd layers regardless.");
def->sidetext = L("mm or %");
def->ratio_over = "line_width";
def->min = 0;
def->max_literal = 20;
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionFloatOrPercent(50, true));
def = this->add("parking_pos_retraction", coFloat); def = this->add("parking_pos_retraction", coFloat);
def->label = L("Filament parking position"); def->label = L("Filament parking position");
def->tooltip = L("Distance of the extruder tip from the position where the filament is parked " def->tooltip = L("Distance of the extruder tip from the position where the filament is parked "
@@ -3225,6 +3318,7 @@ void PrintConfigDef::init_fff_params()
def->label = L("Synchronize with object layers"); def->label = L("Synchronize with object layers");
def->category = L("Support material"); def->category = L("Support material");
// TRN PrintSettings : "Synchronize with object layers" // TRN PrintSettings : "Synchronize with object layers"
//w34
def->tooltip = L("If not checked, support layers to use layer heights that are independent of the object layer."); def->tooltip = L("If not checked, support layers to use layer heights that are independent of the object layer.");
def->mode = comExpert; def->mode = comExpert;
def->set_default_value(new ConfigOptionBool(false)); def->set_default_value(new ConfigOptionBool(false));

View File

@@ -535,7 +535,7 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionInt, raft_layers)) ((ConfigOptionInt, raft_layers))
((ConfigOptionEnum<SeamPosition>, seam_position)) ((ConfigOptionEnum<SeamPosition>, seam_position))
//Y21 //Y21
((ConfigOptionPercent, seam_gap)) ((ConfigOptionPercent, seam_gap))
((ConfigOptionBool, staggered_inner_seams)) ((ConfigOptionBool, staggered_inner_seams))
// ((ConfigOptionFloat, seam_preferred_direction)) // ((ConfigOptionFloat, seam_preferred_direction))
// ((ConfigOptionFloat, seam_preferred_direction_jitter)) // ((ConfigOptionFloat, seam_preferred_direction_jitter))
@@ -626,6 +626,10 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionFloatOrPercent, overhang_speed_1)) ((ConfigOptionFloatOrPercent, overhang_speed_1))
((ConfigOptionFloatOrPercent, overhang_speed_2)) ((ConfigOptionFloatOrPercent, overhang_speed_2))
((ConfigOptionFloatOrPercent, overhang_speed_3)) ((ConfigOptionFloatOrPercent, overhang_speed_3))
//Y27
((ConfigOptionBool, resonance_avoidance))
((ConfigOptionFloat, min_resonance_avoidance_speed))
((ConfigOptionFloat, max_resonance_avoidance_speed))
((ConfigOptionBool, external_perimeters_first)) ((ConfigOptionBool, external_perimeters_first))
((ConfigOptionBool, extra_perimeters)) ((ConfigOptionBool, extra_perimeters))
((ConfigOptionBool, extra_perimeters_on_overhangs)) ((ConfigOptionBool, extra_perimeters_on_overhangs))
@@ -675,7 +679,13 @@ PRINT_CONFIG_CLASS_DEFINE(
//w30 //w30
((ConfigOptionFloat, top_solid_infill_flow_ratio)) ((ConfigOptionFloat, top_solid_infill_flow_ratio))
((ConfigOptionFloat, bottom_solid_infill_flow_ratio)) ((ConfigOptionFloat, bottom_solid_infill_flow_ratio))
)
//w38
((ConfigOptionBool, overhang_reverse))
((ConfigOptionBool, overhang_reverse_internal_only))
((ConfigOptionFloatOrPercent, overhang_reverse_threshold))
//w39
((ConfigOptionBool, precise_outer_wall)))
PRINT_CONFIG_CLASS_DEFINE( PRINT_CONFIG_CLASS_DEFINE(
MachineEnvelopeConfig, MachineEnvelopeConfig,
@@ -831,6 +841,8 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE(
((ConfigOptionBool, chamber_temperature)) ((ConfigOptionBool, chamber_temperature))
//B24 //B24
((ConfigOptionInts, volume_temperature)) ((ConfigOptionInts, volume_temperature))
//Y26
((ConfigOptionBool, seal_print))
((ConfigOptionFloat, bridge_acceleration)) ((ConfigOptionFloat, bridge_acceleration))
((ConfigOptionInts, bridge_fan_speed)) ((ConfigOptionInts, bridge_fan_speed))
((ConfigOptionBools, enable_dynamic_fan_speeds)) ((ConfigOptionBools, enable_dynamic_fan_speeds))
@@ -848,6 +860,8 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE(
((ConfigOptionInts, enable_volume_fan)) ((ConfigOptionInts, enable_volume_fan))
//B15 //B15
((ConfigOptionInts, enable_auxiliary_fan)) ((ConfigOptionInts, enable_auxiliary_fan))
//Y26
((ConfigOptionInts, enable_auxiliary_fan_unseal))
((ConfigOptionFloat, default_acceleration)) ((ConfigOptionFloat, default_acceleration))
((ConfigOptionInts, disable_fan_first_layers)) ((ConfigOptionInts, disable_fan_first_layers))
//B39 //B39
@@ -886,6 +900,8 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE(
((ConfigOptionInts, min_fan_speed)) ((ConfigOptionInts, min_fan_speed))
((ConfigOptionFloats, min_layer_height)) ((ConfigOptionFloats, min_layer_height))
((ConfigOptionFloat, max_print_height)) ((ConfigOptionFloat, max_print_height))
//Y28
((ConfigOptionBools, dont_slow_down_outer_wall))
((ConfigOptionFloats, min_print_speed)) ((ConfigOptionFloats, min_print_speed))
((ConfigOptionFloat, min_skirt_length)) ((ConfigOptionFloat, min_skirt_length))
((ConfigOptionString, notes)) ((ConfigOptionString, notes))

View File

@@ -852,7 +852,9 @@ bool PrintObject::invalidate_state_by_config_options(
|| opt_key == "fuzzy_skin_point_dist" || opt_key == "fuzzy_skin_point_dist"
|| opt_key == "overhangs" || opt_key == "overhangs"
|| opt_key == "thin_walls" || opt_key == "thin_walls"
|| opt_key == "thick_bridges") { || opt_key == "thick_bridges"
//w39
|| opt_key == "precise_outer_wall") {
steps.emplace_back(posPerimeters); steps.emplace_back(posPerimeters);
steps.emplace_back(posSupportMaterial); steps.emplace_back(posSupportMaterial);
} else if (opt_key == "bridge_flow_ratio") { } else if (opt_key == "bridge_flow_ratio") {
@@ -876,7 +878,11 @@ bool PrintObject::invalidate_state_by_config_options(
//w17 //w17
|| opt_key == "top_area_threshold" || opt_key == "top_area_threshold"
//w23 //w23
|| opt_key == "only_one_wall_first_layer") { || opt_key == "only_one_wall_first_layer"
//w38
|| opt_key == "overhang_reverse"
|| opt_key == "overhang_reverse_internal_only"
|| opt_key == "overhang_reverse_threshold") {
steps.emplace_back(posSlice); steps.emplace_back(posSlice);
} else if ( } else if (
opt_key == "seam_position" opt_key == "seam_position"

View File

@@ -774,6 +774,7 @@ void PrintObject::slice_volumes()
float(scale_(m_config.elefant_foot_compensation.value)) : float(scale_(m_config.elefant_foot_compensation.value)) :
0.f; 0.f;
// Uncompensated slices for the first layer in case the Elephant foot compensation is applied. // Uncompensated slices for the first layer in case the Elephant foot compensation is applied.
//w24
std::vector<ExPolygons> lslices_elfoot_uncompensated; std::vector<ExPolygons> lslices_elfoot_uncompensated;
//w26 //w26
lslices_elfoot_uncompensated.resize(elephant_foot_compensation_scaled > 0 ? std::min(m_config.elefant_foot_compensation_layers.value, (int)m_layers.size()) : 0); lslices_elfoot_uncompensated.resize(elephant_foot_compensation_scaled > 0 ? std::min(m_config.elefant_foot_compensation_layers.value, (int)m_layers.size()) : 0);
@@ -786,6 +787,7 @@ void PrintObject::slice_volumes()
m_print->throw_if_canceled(); m_print->throw_if_canceled();
Layer *layer = m_layers[layer_id]; Layer *layer = m_layers[layer_id];
//w24 //w24
//w26
float elfoot = elephant_foot_compensation_scaled > 0 && layer_id < m_config.elefant_foot_compensation_layers.value ? float elfoot = elephant_foot_compensation_scaled > 0 && layer_id < m_config.elefant_foot_compensation_layers.value ?
elephant_foot_compensation_scaled - (elephant_foot_compensation_scaled / m_config.elefant_foot_compensation_layers.value) * layer_id : elephant_foot_compensation_scaled - (elephant_foot_compensation_scaled / m_config.elefant_foot_compensation_layers.value) * layer_id :
0.f; 0.f;
@@ -795,15 +797,18 @@ void PrintObject::slice_volumes()
//w24 //w24
ExPolygons expolygons_to_compensate = to_expolygons(std::move(layerm->slices().surfaces)); ExPolygons expolygons_to_compensate = to_expolygons(std::move(layerm->slices().surfaces));
if (xy_contour_scaled > 0 || xy_hole_scaled > 0) { if (xy_contour_scaled > 0 || xy_hole_scaled > 0) {
//w24
expolygons_to_compensate = _shrink_contour_holes(std::max(0.f, xy_contour_scaled), expolygons_to_compensate = _shrink_contour_holes(std::max(0.f, xy_contour_scaled),
std::max(0.f, xy_hole_scaled), std::max(0.f, xy_hole_scaled),
expolygons_to_compensate); expolygons_to_compensate);
} }
if (xy_contour_scaled < 0 || xy_hole_scaled < 0) { if (xy_contour_scaled < 0 || xy_hole_scaled < 0) {
//w24
expolygons_to_compensate = _shrink_contour_holes(std::min(0.f, xy_contour_scaled), expolygons_to_compensate = _shrink_contour_holes(std::min(0.f, xy_contour_scaled),
std::min(0.f, xy_hole_scaled), std::min(0.f, xy_hole_scaled),
expolygons_to_compensate); expolygons_to_compensate);
} }
//w24
lslices_elfoot_uncompensated[layer_id] = expolygons_to_compensate; lslices_elfoot_uncompensated[layer_id] = expolygons_to_compensate;
layerm->m_slices.set( layerm->m_slices.set(
union_ex( union_ex(
@@ -817,13 +822,11 @@ void PrintObject::slice_volumes()
if (xy_contour_scaled != 0.0f || xy_hole_scaled != 0.0f) { if (xy_contour_scaled != 0.0f || xy_hole_scaled != 0.0f) {
ExPolygons expolygons = to_expolygons(std::move(layerm->m_slices.surfaces)); ExPolygons expolygons = to_expolygons(std::move(layerm->m_slices.surfaces));
if (xy_contour_scaled > 0 || xy_hole_scaled > 0) { if (xy_contour_scaled > 0 || xy_hole_scaled > 0) {
expolygons = _shrink_contour_holes(std::max(0.f, xy_contour_scaled), expolygons = _shrink_contour_holes(std::max(0.f, xy_contour_scaled), std::max(0.f, xy_hole_scaled),
std::max(0.f, xy_hole_scaled),
expolygons); expolygons);
} }
if (xy_contour_scaled < 0 || xy_hole_scaled < 0) { if (xy_contour_scaled < 0 || xy_hole_scaled < 0) {
expolygons = _shrink_contour_holes(std::min(0.f, xy_contour_scaled), expolygons = _shrink_contour_holes(std::min(0.f, xy_contour_scaled), std::min(0.f, xy_hole_scaled),
std::min(0.f, xy_hole_scaled),
expolygons); expolygons);
} }
layerm->m_slices.set(std::move(expolygons), stInternal); layerm->m_slices.set(std::move(expolygons), stInternal);
@@ -856,6 +859,7 @@ void PrintObject::slice_volumes()
ExPolygons trimming; ExPolygons trimming;
static const float eps = float(scale_(m_config.slice_closing_radius.value) * 1.5); static const float eps = float(scale_(m_config.slice_closing_radius.value) * 1.5);
if (elfoot > 0.f) { if (elfoot > 0.f) {
//w24
ExPolygons expolygons_to_compensate = offset_ex(layer->merged(eps), -eps); ExPolygons expolygons_to_compensate = offset_ex(layer->merged(eps), -eps);
lslices_elfoot_uncompensated[layer_id] = expolygons_to_compensate; lslices_elfoot_uncompensated[layer_id] = expolygons_to_compensate;
trimming = Slic3r::elephant_foot_compensation(expolygons_to_compensate, trimming = Slic3r::elephant_foot_compensation(expolygons_to_compensate,
@@ -864,9 +868,7 @@ void PrintObject::slice_volumes()
trimming = layer->merged(float(SCALED_EPSILON)); trimming = layer->merged(float(SCALED_EPSILON));
} }
if (min_growth < 0.0f) if (min_growth < 0.0f)
trimming = _shrink_contour_holes(std::min(0.f, xy_contour_scaled), trimming = _shrink_contour_holes(std::min(0.f, xy_contour_scaled), std::min(0.f, xy_hole_scaled), trimming);
std::min(0.f, xy_hole_scaled),
trimming);
for (size_t region_id = 0; region_id < layer->regions().size(); ++region_id) { for (size_t region_id = 0; region_id < layer->regions().size(); ++region_id) {
ExPolygons contour_exp = to_expolygons(std::move(layer->regions()[region_id]->m_slices.surfaces)); ExPolygons contour_exp = to_expolygons(std::move(layer->regions()[region_id]->m_slices.surfaces));

View File

@@ -125,6 +125,7 @@ SlicingParameters SlicingParameters::create_from_config(
if (params.gap_object_support <= 0) if (params.gap_object_support <= 0)
params.gap_object_support = params.gap_support_object; params.gap_object_support = params.gap_support_object;
//w34
if (object_config.support_material_synchronize_layers) { if (object_config.support_material_synchronize_layers) {
params.gap_raft_object = std::round(params.gap_raft_object / object_config.layer_height + EPSILON) * object_config.layer_height; params.gap_raft_object = std::round(params.gap_raft_object / object_config.layer_height + EPSILON) * object_config.layer_height;
params.gap_object_support = std::round(params.gap_object_support / object_config.layer_height + EPSILON) * params.gap_object_support = std::round(params.gap_object_support / object_config.layer_height + EPSILON) *

View File

@@ -167,10 +167,11 @@ void adjust_layer_height_profile(
// Produce object layers as pairs of low / high layer boundaries, stored into a linear vector. // Produce object layers as pairs of low / high layer boundaries, stored into a linear vector.
// The object layers are based at z=0, ignoring the raft layers. // The object layers are based at z=0, ignoring the raft layers.
//w27
std::vector<coordf_t> generate_object_layers( std::vector<coordf_t> generate_object_layers(
const SlicingParameters &slicing_params, const SlicingParameters &slicing_params,
const std::vector<coordf_t> &layer_height_profile, const std::vector<coordf_t> &layer_height_profile,
//w27
bool is_precise_z_height); bool is_precise_z_height);
// Check whether the layer height profile describes a fixed layer height profile. // Check whether the layer height profile describes a fixed layer height profile.

View File

@@ -207,10 +207,10 @@ static std::vector<std::pair<TreeSupportSettings, std::vector<size_t>>> group_me
double max_bridge_length = scale_(config.max_bridge_length.value); double max_bridge_length = scale_(config.max_bridge_length.value);
bool bridge_break = (config.max_bridge_length.value > 0) && (config.support_material_style == smsOrganic); bool bridge_break = (config.max_bridge_length.value > 0) && (config.support_material_style == smsOrganic);
//w28
size_t num_overhang_layers = support_auto ? num_object_layers : std::min(num_object_layers, std::max(size_t(support_enforce_layers), enforcers_layers.size())); size_t num_overhang_layers = support_auto ? num_object_layers : std::min(num_object_layers, std::max(size_t(support_enforce_layers), enforcers_layers.size()));
tbb::parallel_for(tbb::blocked_range<LayerIndex>(1, num_overhang_layers), tbb::parallel_for(tbb::blocked_range<LayerIndex>(1, num_overhang_layers),
[&print_object, &config, &print_config, &enforcers_layers, &blockers_layers, [&print_object, &config, &print_config, &enforcers_layers, &blockers_layers,
//w28
support_auto, support_enforce_layers, support_threshold_auto, tan_threshold, enforcer_overhang_offset, num_raft_layers, &throw_on_cancel, &out,bridge_break,max_bridge_length] support_auto, support_enforce_layers, support_threshold_auto, tan_threshold, enforcer_overhang_offset, num_raft_layers, &throw_on_cancel, &out,bridge_break,max_bridge_length]
(const tbb::blocked_range<LayerIndex> &range) { (const tbb::blocked_range<LayerIndex> &range) {
for (LayerIndex layer_id = range.begin(); layer_id < range.end(); ++ layer_id) { for (LayerIndex layer_id = range.begin(); layer_id < range.end(); ++ layer_id) {

View File

@@ -6,4 +6,6 @@
#define SLIC3R_VERSION "@SLIC3R_VERSION@" #define SLIC3R_VERSION "@SLIC3R_VERSION@"
#define SLIC3R_BUILD_ID "@SLIC3R_BUILD_ID@" #define SLIC3R_BUILD_ID "@SLIC3R_BUILD_ID@"
//B64
#define QDT_RELEASE_TO_PUBLIC @QDT_RELEASE_TO_PUBLIC@
#endif /* __SLIC3R_VERSION_H */ #endif /* __SLIC3R_VERSION_H */

View File

@@ -0,0 +1,73 @@
#pragma once
#include <type_traits>
#include <utility>
#include <nlohmann/detail/conversions/from_json.hpp>
#include <nlohmann/detail/conversions/to_json.hpp>
#include <nlohmann/detail/meta/identity_tag.hpp>
#include <nlohmann/detail/meta/type_traits.hpp>
namespace nlohmann
{
template<typename ValueType, typename>
struct adl_serializer
{
/*!
@brief convert a JSON value to any value type
This function is usually called by the `get()` function of the
@ref basic_json class (either explicit or via conversion operators).
@note This function is chosen for default-constructible value types.
@param[in] j JSON value to read from
@param[in,out] val value to write to
*/
template<typename BasicJsonType, typename TargetType = ValueType>
static auto from_json(BasicJsonType && j, TargetType& val) noexcept(
noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))
-> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), val), void())
{
::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
}
/*!
@brief convert a JSON value to any value type
This function is usually called by the `get()` function of the
@ref basic_json class (either explicit or via conversion operators).
@note This function is chosen for value types which are not default-constructible.
@param[in] j JSON value to read from
@return copy of the JSON value, converted to @a ValueType
*/
template<typename BasicJsonType, typename TargetType = ValueType>
static auto from_json(BasicJsonType && j) noexcept(
noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {})))
-> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {}))
{
return ::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {});
}
/*!
@brief convert any value type to a JSON value
This function is usually called by the constructors of the @ref basic_json
class.
@param[in,out] j JSON value to write to
@param[in] val value to read from
*/
template<typename BasicJsonType, typename TargetType = ValueType>
static auto to_json(BasicJsonType& j, TargetType && val) noexcept(
noexcept(::nlohmann::to_json(j, std::forward<TargetType>(val))))
-> decltype(::nlohmann::to_json(j, std::forward<TargetType>(val)), void())
{
::nlohmann::to_json(j, std::forward<TargetType>(val));
}
};
} // namespace nlohmann

View File

@@ -0,0 +1,169 @@
#pragma once
#include <cstdint> // uint8_t, uint64_t
#include <tuple> // tie
#include <utility> // move
namespace nlohmann
{
/*!
@brief an internal type for a backed binary type
This type extends the template parameter @a BinaryType provided to `basic_json`
with a subtype used by BSON and MessagePack. This type exists so that the user
does not have to specify a type themselves with a specific naming scheme in
order to override the binary type.
@tparam BinaryType container to store bytes (`std::vector<std::uint8_t>` by
default)
@since version 3.8.0; changed type of subtypes to std::uint64_t in 3.10.0.
*/
template<typename BinaryType>
class byte_container_with_subtype : public BinaryType
{
public:
/// the type of the underlying container
using container_type = BinaryType;
/// the type of the subtype
using subtype_type = std::uint64_t;
byte_container_with_subtype() noexcept(noexcept(container_type()))
: container_type()
{}
byte_container_with_subtype(const container_type& b) noexcept(noexcept(container_type(b)))
: container_type(b)
{}
byte_container_with_subtype(container_type&& b) noexcept(noexcept(container_type(std::move(b))))
: container_type(std::move(b))
{}
byte_container_with_subtype(const container_type& b, subtype_type subtype_) noexcept(noexcept(container_type(b)))
: container_type(b)
, m_subtype(subtype_)
, m_has_subtype(true)
{}
byte_container_with_subtype(container_type&& b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b))))
: container_type(std::move(b))
, m_subtype(subtype_)
, m_has_subtype(true)
{}
bool operator==(const byte_container_with_subtype& rhs) const
{
return std::tie(static_cast<const BinaryType&>(*this), m_subtype, m_has_subtype) ==
std::tie(static_cast<const BinaryType&>(rhs), rhs.m_subtype, rhs.m_has_subtype);
}
bool operator!=(const byte_container_with_subtype& rhs) const
{
return !(rhs == *this);
}
/*!
@brief sets the binary subtype
Sets the binary subtype of the value, also flags a binary JSON value as
having a subtype, which has implications for serialization.
@complexity Constant.
@exceptionsafety No-throw guarantee: this member function never throws
exceptions.
@sa see @ref subtype() -- return the binary subtype
@sa see @ref clear_subtype() -- clears the binary subtype
@sa see @ref has_subtype() -- returns whether or not the binary value has a
subtype
@since version 3.8.0
*/
void set_subtype(subtype_type subtype_) noexcept
{
m_subtype = subtype_;
m_has_subtype = true;
}
/*!
@brief return the binary subtype
Returns the numerical subtype of the value if it has a subtype. If it does
not have a subtype, this function will return subtype_type(-1) as a sentinel
value.
@return the numerical subtype of the binary value
@complexity Constant.
@exceptionsafety No-throw guarantee: this member function never throws
exceptions.
@sa see @ref set_subtype() -- sets the binary subtype
@sa see @ref clear_subtype() -- clears the binary subtype
@sa see @ref has_subtype() -- returns whether or not the binary value has a
subtype
@since version 3.8.0; fixed return value to properly return
subtype_type(-1) as documented in version 3.10.0
*/
constexpr subtype_type subtype() const noexcept
{
return m_has_subtype ? m_subtype : subtype_type(-1);
}
/*!
@brief return whether the value has a subtype
@return whether the value has a subtype
@complexity Constant.
@exceptionsafety No-throw guarantee: this member function never throws
exceptions.
@sa see @ref subtype() -- return the binary subtype
@sa see @ref set_subtype() -- sets the binary subtype
@sa see @ref clear_subtype() -- clears the binary subtype
@since version 3.8.0
*/
constexpr bool has_subtype() const noexcept
{
return m_has_subtype;
}
/*!
@brief clears the binary subtype
Clears the binary subtype and flags the value as not having a subtype, which
has implications for serialization; for instance MessagePack will prefer the
bin family over the ext family.
@complexity Constant.
@exceptionsafety No-throw guarantee: this member function never throws
exceptions.
@sa see @ref subtype() -- return the binary subtype
@sa see @ref set_subtype() -- sets the binary subtype
@sa see @ref has_subtype() -- returns whether or not the binary value has a
subtype
@since version 3.8.0
*/
void clear_subtype() noexcept
{
m_subtype = 0;
m_has_subtype = false;
}
private:
subtype_type m_subtype = 0;
bool m_has_subtype = false;
};
} // namespace nlohmann

View File

@@ -0,0 +1,482 @@
#pragma once
#include <algorithm> // transform
#include <array> // array
#include <forward_list> // forward_list
#include <iterator> // inserter, front_inserter, end
#include <map> // map
#include <string> // string
#include <tuple> // tuple, make_tuple
#include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
#include <unordered_map> // unordered_map
#include <utility> // pair, declval
#include <valarray> // valarray
#include <nlohmann/detail/exceptions.hpp>
#include <nlohmann/detail/macro_scope.hpp>
#include <nlohmann/detail/meta/cpp_future.hpp>
#include <nlohmann/detail/meta/identity_tag.hpp>
#include <nlohmann/detail/meta/type_traits.hpp>
#include <nlohmann/detail/value_t.hpp>
#ifdef JSON_HAS_CPP_17
#include <filesystem>
#endif
namespace nlohmann
{
namespace detail
{
template<typename BasicJsonType>
void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_null()))
{
JSON_THROW(type_error::create(302, "type must be null, but is " + std::string(j.type_name()), j));
}
n = nullptr;
}
// overloads for basic_json template parameters
template < typename BasicJsonType, typename ArithmeticType,
enable_if_t < std::is_arithmetic<ArithmeticType>::value&&
!std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
int > = 0 >
void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
{
switch (static_cast<value_t>(j))
{
case value_t::number_unsigned:
{
val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
break;
}
case value_t::number_integer:
{
val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
break;
}
case value_t::number_float:
{
val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
break;
}
case value_t::null:
case value_t::object:
case value_t::array:
case value_t::string:
case value_t::boolean:
case value_t::binary:
case value_t::discarded:
default:
JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()), j));
}
}
template<typename BasicJsonType>
void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_boolean()))
{
JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(j.type_name()), j));
}
b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
}
template<typename BasicJsonType>
void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
{
JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), j));
}
s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
}
template <
typename BasicJsonType, typename ConstructibleStringType,
enable_if_t <
is_constructible_string_type<BasicJsonType, ConstructibleStringType>::value&&
!std::is_same<typename BasicJsonType::string_t,
ConstructibleStringType>::value,
int > = 0 >
void from_json(const BasicJsonType& j, ConstructibleStringType& s)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
{
JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), j));
}
s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
}
template<typename BasicJsonType>
void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
{
get_arithmetic_value(j, val);
}
template<typename BasicJsonType>
void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val)
{
get_arithmetic_value(j, val);
}
template<typename BasicJsonType>
void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)
{
get_arithmetic_value(j, val);
}
template<typename BasicJsonType, typename EnumType,
enable_if_t<std::is_enum<EnumType>::value, int> = 0>
void from_json(const BasicJsonType& j, EnumType& e)
{
typename std::underlying_type<EnumType>::type val;
get_arithmetic_value(j, val);
e = static_cast<EnumType>(val);
}
// forward_list doesn't have an insert method
template<typename BasicJsonType, typename T, typename Allocator,
enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
{
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
}
l.clear();
std::transform(j.rbegin(), j.rend(),
std::front_inserter(l), [](const BasicJsonType & i)
{
return i.template get<T>();
});
}
// valarray doesn't have an insert method
template<typename BasicJsonType, typename T,
enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
void from_json(const BasicJsonType& j, std::valarray<T>& l)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
{
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
}
l.resize(j.size());
std::transform(j.begin(), j.end(), std::begin(l),
[](const BasicJsonType & elem)
{
return elem.template get<T>();
});
}
template<typename BasicJsonType, typename T, std::size_t N>
auto from_json(const BasicJsonType& j, T (&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
-> decltype(j.template get<T>(), void())
{
for (std::size_t i = 0; i < N; ++i)
{
arr[i] = j.at(i).template get<T>();
}
}
template<typename BasicJsonType>
void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/)
{
arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
}
template<typename BasicJsonType, typename T, std::size_t N>
auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
priority_tag<2> /*unused*/)
-> decltype(j.template get<T>(), void())
{
for (std::size_t i = 0; i < N; ++i)
{
arr[i] = j.at(i).template get<T>();
}
}
template<typename BasicJsonType, typename ConstructibleArrayType,
enable_if_t<
std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
int> = 0>
auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/)
-> decltype(
arr.reserve(std::declval<typename ConstructibleArrayType::size_type>()),
j.template get<typename ConstructibleArrayType::value_type>(),
void())
{
using std::end;
ConstructibleArrayType ret;
ret.reserve(j.size());
std::transform(j.begin(), j.end(),
std::inserter(ret, end(ret)), [](const BasicJsonType & i)
{
// get<BasicJsonType>() returns *this, this won't call a from_json
// method when value_type is BasicJsonType
return i.template get<typename ConstructibleArrayType::value_type>();
});
arr = std::move(ret);
}
template<typename BasicJsonType, typename ConstructibleArrayType,
enable_if_t<
std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
int> = 0>
void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr,
priority_tag<0> /*unused*/)
{
using std::end;
ConstructibleArrayType ret;
std::transform(
j.begin(), j.end(), std::inserter(ret, end(ret)),
[](const BasicJsonType & i)
{
// get<BasicJsonType>() returns *this, this won't call a from_json
// method when value_type is BasicJsonType
return i.template get<typename ConstructibleArrayType::value_type>();
});
arr = std::move(ret);
}
template < typename BasicJsonType, typename ConstructibleArrayType,
enable_if_t <
is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value&&
!is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value&&
!is_constructible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
!std::is_same<ConstructibleArrayType, typename BasicJsonType::binary_t>::value&&
!is_basic_json<ConstructibleArrayType>::value,
int > = 0 >
auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr)
-> decltype(from_json_array_impl(j, arr, priority_tag<3> {}),
j.template get<typename ConstructibleArrayType::value_type>(),
void())
{
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
{
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
}
from_json_array_impl(j, arr, priority_tag<3> {});
}
template < typename BasicJsonType, typename T, std::size_t... Idx >
std::array<T, sizeof...(Idx)> from_json_inplace_array_impl(BasicJsonType&& j,
identity_tag<std::array<T, sizeof...(Idx)>> /*unused*/, index_sequence<Idx...> /*unused*/)
{
return { { std::forward<BasicJsonType>(j).at(Idx).template get<T>()... } };
}
template < typename BasicJsonType, typename T, std::size_t N >
auto from_json(BasicJsonType&& j, identity_tag<std::array<T, N>> tag)
-> decltype(from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {}))
{
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
{
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
}
return from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {});
}
template<typename BasicJsonType>
void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_binary()))
{
JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(j.type_name()), j));
}
bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>();
}
template<typename BasicJsonType, typename ConstructibleObjectType,
enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0>
void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
{
JSON_THROW(type_error::create(302, "type must be object, but is " + std::string(j.type_name()), j));
}
ConstructibleObjectType ret;
const auto* inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
using value_type = typename ConstructibleObjectType::value_type;
std::transform(
inner_object->begin(), inner_object->end(),
std::inserter(ret, ret.begin()),
[](typename BasicJsonType::object_t::value_type const & p)
{
return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>());
});
obj = std::move(ret);
}
// overload for arithmetic types, not chosen for basic_json template arguments
// (BooleanType, etc..); note: Is it really necessary to provide explicit
// overloads for boolean_t etc. in case of a custom BooleanType which is not
// an arithmetic type?
template < typename BasicJsonType, typename ArithmeticType,
enable_if_t <
std::is_arithmetic<ArithmeticType>::value&&
!std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value&&
!std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value&&
!std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value&&
!std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
int > = 0 >
void from_json(const BasicJsonType& j, ArithmeticType& val)
{
switch (static_cast<value_t>(j))
{
case value_t::number_unsigned:
{
val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
break;
}
case value_t::number_integer:
{
val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
break;
}
case value_t::number_float:
{
val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
break;
}
case value_t::boolean:
{
val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
break;
}
case value_t::null:
case value_t::object:
case value_t::array:
case value_t::string:
case value_t::binary:
case value_t::discarded:
default:
JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()), j));
}
}
template<typename BasicJsonType, typename... Args, std::size_t... Idx>
std::tuple<Args...> from_json_tuple_impl_base(BasicJsonType&& j, index_sequence<Idx...> /*unused*/)
{
return std::make_tuple(std::forward<BasicJsonType>(j).at(Idx).template get<Args>()...);
}
template < typename BasicJsonType, class A1, class A2 >
std::pair<A1, A2> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::pair<A1, A2>> /*unused*/, priority_tag<0> /*unused*/)
{
return {std::forward<BasicJsonType>(j).at(0).template get<A1>(),
std::forward<BasicJsonType>(j).at(1).template get<A2>()};
}
template<typename BasicJsonType, typename A1, typename A2>
void from_json_tuple_impl(BasicJsonType&& j, std::pair<A1, A2>& p, priority_tag<1> /*unused*/)
{
p = from_json_tuple_impl(std::forward<BasicJsonType>(j), identity_tag<std::pair<A1, A2>> {}, priority_tag<0> {});
}
template<typename BasicJsonType, typename... Args>
std::tuple<Args...> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::tuple<Args...>> /*unused*/, priority_tag<2> /*unused*/)
{
return from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
}
template<typename BasicJsonType, typename... Args>
void from_json_tuple_impl(BasicJsonType&& j, std::tuple<Args...>& t, priority_tag<3> /*unused*/)
{
t = from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
}
template<typename BasicJsonType, typename TupleRelated>
auto from_json(BasicJsonType&& j, TupleRelated&& t)
-> decltype(from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {}))
{
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
{
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
}
return from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {});
}
template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
typename = enable_if_t < !std::is_constructible <
typename BasicJsonType::string_t, Key >::value >>
void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
{
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
}
m.clear();
for (const auto& p : j)
{
if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
{
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name()), j));
}
m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
}
}
template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
typename = enable_if_t < !std::is_constructible <
typename BasicJsonType::string_t, Key >::value >>
void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
{
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
}
m.clear();
for (const auto& p : j)
{
if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
{
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name()), j));
}
m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
}
}
#ifdef JSON_HAS_CPP_17
template<typename BasicJsonType>
void from_json(const BasicJsonType& j, std::filesystem::path& p)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
{
JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), j));
}
p = *j.template get_ptr<const typename BasicJsonType::string_t*>();
}
#endif
struct from_json_fn
{
template<typename BasicJsonType, typename T>
auto operator()(const BasicJsonType& j, T&& val) const
noexcept(noexcept(from_json(j, std::forward<T>(val))))
-> decltype(from_json(j, std::forward<T>(val)))
{
return from_json(j, std::forward<T>(val));
}
};
} // namespace detail
/// namespace to hold default `from_json` function
/// to see why this is required:
/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
{
constexpr const auto& from_json = detail::static_const<detail::from_json_fn>::value; // NOLINT(misc-definitions-in-headers)
} // namespace
} // namespace nlohmann

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,420 @@
#pragma once
#include <algorithm> // copy
#include <iterator> // begin, end
#include <string> // string
#include <tuple> // tuple, get
#include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
#include <utility> // move, forward, declval, pair
#include <valarray> // valarray
#include <vector> // vector
#include <nlohmann/detail/macro_scope.hpp>
#include <nlohmann/detail/iterators/iteration_proxy.hpp>
#include <nlohmann/detail/meta/cpp_future.hpp>
#include <nlohmann/detail/meta/type_traits.hpp>
#include <nlohmann/detail/value_t.hpp>
#ifdef JSON_HAS_CPP_17
#include <filesystem>
#endif
namespace nlohmann
{
namespace detail
{
//////////////////
// constructors //
//////////////////
/*
* Note all external_constructor<>::construct functions need to call
* j.m_value.destroy(j.m_type) to avoid a memory leak in case j contains an
* allocated value (e.g., a string). See bug issue
* https://github.com/nlohmann/json/issues/2865 for more information.
*/
template<value_t> struct external_constructor;
template<>
struct external_constructor<value_t::boolean>
{
template<typename BasicJsonType>
static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
{
j.m_value.destroy(j.m_type);
j.m_type = value_t::boolean;
j.m_value = b;
j.assert_invariant();
}
};
template<>
struct external_constructor<value_t::string>
{
template<typename BasicJsonType>
static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
{
j.m_value.destroy(j.m_type);
j.m_type = value_t::string;
j.m_value = s;
j.assert_invariant();
}
template<typename BasicJsonType>
static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s)
{
j.m_value.destroy(j.m_type);
j.m_type = value_t::string;
j.m_value = std::move(s);
j.assert_invariant();
}
template < typename BasicJsonType, typename CompatibleStringType,
enable_if_t < !std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value,
int > = 0 >
static void construct(BasicJsonType& j, const CompatibleStringType& str)
{
j.m_value.destroy(j.m_type);
j.m_type = value_t::string;
j.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
j.assert_invariant();
}
};
template<>
struct external_constructor<value_t::binary>
{
template<typename BasicJsonType>
static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b)
{
j.m_value.destroy(j.m_type);
j.m_type = value_t::binary;
j.m_value = typename BasicJsonType::binary_t(b);
j.assert_invariant();
}
template<typename BasicJsonType>
static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b)
{
j.m_value.destroy(j.m_type);
j.m_type = value_t::binary;
j.m_value = typename BasicJsonType::binary_t(std::move(b));
j.assert_invariant();
}
};
template<>
struct external_constructor<value_t::number_float>
{
template<typename BasicJsonType>
static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept
{
j.m_value.destroy(j.m_type);
j.m_type = value_t::number_float;
j.m_value = val;
j.assert_invariant();
}
};
template<>
struct external_constructor<value_t::number_unsigned>
{
template<typename BasicJsonType>
static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept
{
j.m_value.destroy(j.m_type);
j.m_type = value_t::number_unsigned;
j.m_value = val;
j.assert_invariant();
}
};
template<>
struct external_constructor<value_t::number_integer>
{
template<typename BasicJsonType>
static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept
{
j.m_value.destroy(j.m_type);
j.m_type = value_t::number_integer;
j.m_value = val;
j.assert_invariant();
}
};
template<>
struct external_constructor<value_t::array>
{
template<typename BasicJsonType>
static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
{
j.m_value.destroy(j.m_type);
j.m_type = value_t::array;
j.m_value = arr;
j.set_parents();
j.assert_invariant();
}
template<typename BasicJsonType>
static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
{
j.m_value.destroy(j.m_type);
j.m_type = value_t::array;
j.m_value = std::move(arr);
j.set_parents();
j.assert_invariant();
}
template < typename BasicJsonType, typename CompatibleArrayType,
enable_if_t < !std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value,
int > = 0 >
static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
{
using std::begin;
using std::end;
j.m_value.destroy(j.m_type);
j.m_type = value_t::array;
j.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
j.set_parents();
j.assert_invariant();
}
template<typename BasicJsonType>
static void construct(BasicJsonType& j, const std::vector<bool>& arr)
{
j.m_value.destroy(j.m_type);
j.m_type = value_t::array;
j.m_value = value_t::array;
j.m_value.array->reserve(arr.size());
for (const bool x : arr)
{
j.m_value.array->push_back(x);
j.set_parent(j.m_value.array->back());
}
j.assert_invariant();
}
template<typename BasicJsonType, typename T,
enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
static void construct(BasicJsonType& j, const std::valarray<T>& arr)
{
j.m_value.destroy(j.m_type);
j.m_type = value_t::array;
j.m_value = value_t::array;
j.m_value.array->resize(arr.size());
if (arr.size() > 0)
{
std::copy(std::begin(arr), std::end(arr), j.m_value.array->begin());
}
j.set_parents();
j.assert_invariant();
}
};
template<>
struct external_constructor<value_t::object>
{
template<typename BasicJsonType>
static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
{
j.m_value.destroy(j.m_type);
j.m_type = value_t::object;
j.m_value = obj;
j.set_parents();
j.assert_invariant();
}
template<typename BasicJsonType>
static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
{
j.m_value.destroy(j.m_type);
j.m_type = value_t::object;
j.m_value = std::move(obj);
j.set_parents();
j.assert_invariant();
}
template < typename BasicJsonType, typename CompatibleObjectType,
enable_if_t < !std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int > = 0 >
static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
{
using std::begin;
using std::end;
j.m_value.destroy(j.m_type);
j.m_type = value_t::object;
j.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
j.set_parents();
j.assert_invariant();
}
};
/////////////
// to_json //
/////////////
template<typename BasicJsonType, typename T,
enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
void to_json(BasicJsonType& j, T b) noexcept
{
external_constructor<value_t::boolean>::construct(j, b);
}
template<typename BasicJsonType, typename CompatibleString,
enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0>
void to_json(BasicJsonType& j, const CompatibleString& s)
{
external_constructor<value_t::string>::construct(j, s);
}
template<typename BasicJsonType>
void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s)
{
external_constructor<value_t::string>::construct(j, std::move(s));
}
template<typename BasicJsonType, typename FloatType,
enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
void to_json(BasicJsonType& j, FloatType val) noexcept
{
external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
}
template<typename BasicJsonType, typename CompatibleNumberUnsignedType,
enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0>
void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
{
external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
}
template<typename BasicJsonType, typename CompatibleNumberIntegerType,
enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0>
void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
{
external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
}
template<typename BasicJsonType, typename EnumType,
enable_if_t<std::is_enum<EnumType>::value, int> = 0>
void to_json(BasicJsonType& j, EnumType e) noexcept
{
using underlying_type = typename std::underlying_type<EnumType>::type;
external_constructor<value_t::number_integer>::construct(j, static_cast<underlying_type>(e));
}
template<typename BasicJsonType>
void to_json(BasicJsonType& j, const std::vector<bool>& e)
{
external_constructor<value_t::array>::construct(j, e);
}
template < typename BasicJsonType, typename CompatibleArrayType,
enable_if_t < is_compatible_array_type<BasicJsonType,
CompatibleArrayType>::value&&
!is_compatible_object_type<BasicJsonType, CompatibleArrayType>::value&&
!is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value&&
!std::is_same<typename BasicJsonType::binary_t, CompatibleArrayType>::value&&
!is_basic_json<CompatibleArrayType>::value,
int > = 0 >
void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
{
external_constructor<value_t::array>::construct(j, arr);
}
template<typename BasicJsonType>
void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin)
{
external_constructor<value_t::binary>::construct(j, bin);
}
template<typename BasicJsonType, typename T,
enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
void to_json(BasicJsonType& j, const std::valarray<T>& arr)
{
external_constructor<value_t::array>::construct(j, std::move(arr));
}
template<typename BasicJsonType>
void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
{
external_constructor<value_t::array>::construct(j, std::move(arr));
}
template < typename BasicJsonType, typename CompatibleObjectType,
enable_if_t < is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value&& !is_basic_json<CompatibleObjectType>::value, int > = 0 >
void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
{
external_constructor<value_t::object>::construct(j, obj);
}
template<typename BasicJsonType>
void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
{
external_constructor<value_t::object>::construct(j, std::move(obj));
}
template <
typename BasicJsonType, typename T, std::size_t N,
enable_if_t < !std::is_constructible<typename BasicJsonType::string_t,
const T(&)[N]>::value, // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
int > = 0 >
void to_json(BasicJsonType& j, const T(&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
{
external_constructor<value_t::array>::construct(j, arr);
}
template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible<BasicJsonType, T1>::value&& std::is_constructible<BasicJsonType, T2>::value, int > = 0 >
void to_json(BasicJsonType& j, const std::pair<T1, T2>& p)
{
j = { p.first, p.second };
}
// for https://github.com/nlohmann/json/pull/1134
template<typename BasicJsonType, typename T,
enable_if_t<std::is_same<T, iteration_proxy_value<typename BasicJsonType::iterator>>::value, int> = 0>
void to_json(BasicJsonType& j, const T& b)
{
j = { {b.key(), b.value()} };
}
template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...> /*unused*/)
{
j = { std::get<Idx>(t)... };
}
template<typename BasicJsonType, typename T, enable_if_t<is_constructible_tuple<BasicJsonType, T>::value, int > = 0>
void to_json(BasicJsonType& j, const T& t)
{
to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value> {});
}
#ifdef JSON_HAS_CPP_17
template<typename BasicJsonType>
void to_json(BasicJsonType& j, const std::filesystem::path& p)
{
j = p.string();
}
#endif
struct to_json_fn
{
template<typename BasicJsonType, typename T>
auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
-> decltype(to_json(j, std::forward<T>(val)), void())
{
return to_json(j, std::forward<T>(val));
}
};
} // namespace detail
/// namespace to hold default `to_json` function
/// to see why this is required:
/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
{
constexpr const auto& to_json = detail::static_const<detail::to_json_fn>::value; // NOLINT(misc-definitions-in-headers)
} // namespace
} // namespace nlohmann

View File

@@ -0,0 +1,429 @@
#pragma once
#include <exception> // exception
#include <stdexcept> // runtime_error
#include <string> // to_string
#include <vector> // vector
#include <nlohmann/detail/value_t.hpp>
#include <nlohmann/detail/string_escape.hpp>
#include <nlohmann/detail/input/position_t.hpp>
#include <nlohmann/detail/macro_scope.hpp>
namespace nlohmann
{
namespace detail
{
////////////////
// exceptions //
////////////////
/*!
@brief general exception of the @ref basic_json class
This class is an extension of `std::exception` objects with a member @a id for
exception ids. It is used as the base class for all exceptions thrown by the
@ref basic_json class. This class can hence be used as "wildcard" to catch
exceptions.
Subclasses:
- @ref parse_error for exceptions indicating a parse error
- @ref invalid_iterator for exceptions indicating errors with iterators
- @ref type_error for exceptions indicating executing a member function with
a wrong type
- @ref out_of_range for exceptions indicating access out of the defined range
- @ref other_error for exceptions indicating other library errors
@internal
@note To have nothrow-copy-constructible exceptions, we internally use
`std::runtime_error` which can cope with arbitrary-length error messages.
Intermediate strings are built with static functions and then passed to
the actual constructor.
@endinternal
@liveexample{The following code shows how arbitrary library exceptions can be
caught.,exception}
@since version 3.0.0
*/
class exception : public std::exception
{
public:
/// returns the explanatory string
const char* what() const noexcept override
{
return m.what();
}
/// the id of the exception
const int id; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)
protected:
JSON_HEDLEY_NON_NULL(3)
exception(int id_, const char* what_arg) : id(id_), m(what_arg) {}
static std::string name(const std::string& ename, int id_)
{
return "[json.exception." + ename + "." + std::to_string(id_) + "] ";
}
template<typename BasicJsonType>
static std::string diagnostics(const BasicJsonType& leaf_element)
{
#if JSON_DIAGNOSTICS
std::vector<std::string> tokens;
for (const auto* current = &leaf_element; current->m_parent != nullptr; current = current->m_parent)
{
switch (current->m_parent->type())
{
case value_t::array:
{
for (std::size_t i = 0; i < current->m_parent->m_value.array->size(); ++i)
{
if (&current->m_parent->m_value.array->operator[](i) == current)
{
tokens.emplace_back(std::to_string(i));
break;
}
}
break;
}
case value_t::object:
{
for (const auto& element : *current->m_parent->m_value.object)
{
if (&element.second == current)
{
tokens.emplace_back(element.first.c_str());
break;
}
}
break;
}
case value_t::null: // LCOV_EXCL_LINE
case value_t::string: // LCOV_EXCL_LINE
case value_t::boolean: // LCOV_EXCL_LINE
case value_t::number_integer: // LCOV_EXCL_LINE
case value_t::number_unsigned: // LCOV_EXCL_LINE
case value_t::number_float: // LCOV_EXCL_LINE
case value_t::binary: // LCOV_EXCL_LINE
case value_t::discarded: // LCOV_EXCL_LINE
default: // LCOV_EXCL_LINE
break; // LCOV_EXCL_LINE
}
}
if (tokens.empty())
{
return "";
}
return "(" + std::accumulate(tokens.rbegin(), tokens.rend(), std::string{},
[](const std::string & a, const std::string & b)
{
return a + "/" + detail::escape(b);
}) + ") ";
#else
static_cast<void>(leaf_element);
return "";
#endif
}
private:
/// an exception object as storage for error messages
std::runtime_error m;
};
/*!
@brief exception indicating a parse error
This exception is thrown by the library when a parse error occurs. Parse errors
can occur during the deserialization of JSON text, CBOR, MessagePack, as well
as when using JSON Patch.
Member @a byte holds the byte index of the last read character in the input
file.
Exceptions have ids 1xx.
name / id | example message | description
------------------------------ | --------------- | -------------------------
json.exception.parse_error.101 | parse error at 2: unexpected end of input; expected string literal | This error indicates a syntax error while deserializing a JSON text. The error message describes that an unexpected token (character) was encountered, and the member @a byte indicates the error position.
json.exception.parse_error.102 | parse error at 14: missing or wrong low surrogate | JSON uses the `\uxxxx` format to describe Unicode characters. Code points above above 0xFFFF are split into two `\uxxxx` entries ("surrogate pairs"). This error indicates that the surrogate pair is incomplete or contains an invalid code point.
json.exception.parse_error.103 | parse error: code points above 0x10FFFF are invalid | Unicode supports code points up to 0x10FFFF. Code points above 0x10FFFF are invalid.
json.exception.parse_error.104 | parse error: JSON patch must be an array of objects | [RFC 6902](https://tools.ietf.org/html/rfc6902) requires a JSON Patch document to be a JSON document that represents an array of objects.
json.exception.parse_error.105 | parse error: operation must have string member 'op' | An operation of a JSON Patch document must contain exactly one "op" member, whose value indicates the operation to perform. Its value must be one of "add", "remove", "replace", "move", "copy", or "test"; other values are errors.
json.exception.parse_error.106 | parse error: array index '01' must not begin with '0' | An array index in a JSON Pointer ([RFC 6901](https://tools.ietf.org/html/rfc6901)) may be `0` or any number without a leading `0`.
json.exception.parse_error.107 | parse error: JSON pointer must be empty or begin with '/' - was: 'foo' | A JSON Pointer must be a Unicode string containing a sequence of zero or more reference tokens, each prefixed by a `/` character.
json.exception.parse_error.108 | parse error: escape character '~' must be followed with '0' or '1' | In a JSON Pointer, only `~0` and `~1` are valid escape sequences.
json.exception.parse_error.109 | parse error: array index 'one' is not a number | A JSON Pointer array index must be a number.
json.exception.parse_error.110 | parse error at 1: cannot read 2 bytes from vector | When parsing CBOR or MessagePack, the byte vector ends before the complete value has been read.
json.exception.parse_error.112 | parse error at 1: error reading CBOR; last byte: 0xF8 | Not all types of CBOR or MessagePack are supported. This exception occurs if an unsupported byte was read.
json.exception.parse_error.113 | parse error at 2: expected a CBOR string; last byte: 0x98 | While parsing a map key, a value that is not a string has been read.
json.exception.parse_error.114 | parse error: Unsupported BSON record type 0x0F | The parsing of the corresponding BSON record type is not implemented (yet).
json.exception.parse_error.115 | parse error at byte 5: syntax error while parsing UBJSON high-precision number: invalid number text: 1A | A UBJSON high-precision number could not be parsed.
@note For an input with n bytes, 1 is the index of the first character and n+1
is the index of the terminating null byte or the end of file. This also
holds true when reading a byte vector (CBOR or MessagePack).
@liveexample{The following code shows how a `parse_error` exception can be
caught.,parse_error}
@sa - @ref exception for the base class of the library exceptions
@sa - @ref invalid_iterator for exceptions indicating errors with iterators
@sa - @ref type_error for exceptions indicating executing a member function with
a wrong type
@sa - @ref out_of_range for exceptions indicating access out of the defined range
@sa - @ref other_error for exceptions indicating other library errors
@since version 3.0.0
*/
class parse_error : public exception
{
public:
/*!
@brief create a parse error exception
@param[in] id_ the id of the exception
@param[in] pos the position where the error occurred (or with
chars_read_total=0 if the position cannot be
determined)
@param[in] what_arg the explanatory string
@return parse_error object
*/
template<typename BasicJsonType>
static parse_error create(int id_, const position_t& pos, const std::string& what_arg, const BasicJsonType& context)
{
std::string w = exception::name("parse_error", id_) + "parse error" +
position_string(pos) + ": " + exception::diagnostics(context) + what_arg;
return parse_error(id_, pos.chars_read_total, w.c_str());
}
template<typename BasicJsonType>
static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, const BasicJsonType& context)
{
std::string w = exception::name("parse_error", id_) + "parse error" +
(byte_ != 0 ? (" at byte " + std::to_string(byte_)) : "") +
": " + exception::diagnostics(context) + what_arg;
return parse_error(id_, byte_, w.c_str());
}
/*!
@brief byte index of the parse error
The byte index of the last read character in the input file.
@note For an input with n bytes, 1 is the index of the first character and
n+1 is the index of the terminating null byte or the end of file.
This also holds true when reading a byte vector (CBOR or MessagePack).
*/
const std::size_t byte;
private:
parse_error(int id_, std::size_t byte_, const char* what_arg)
: exception(id_, what_arg), byte(byte_) {}
static std::string position_string(const position_t& pos)
{
return " at line " + std::to_string(pos.lines_read + 1) +
", column " + std::to_string(pos.chars_read_current_line);
}
};
/*!
@brief exception indicating errors with iterators
This exception is thrown if iterators passed to a library function do not match
the expected semantics.
Exceptions have ids 2xx.
name / id | example message | description
----------------------------------- | --------------- | -------------------------
json.exception.invalid_iterator.201 | iterators are not compatible | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid.
json.exception.invalid_iterator.202 | iterator does not fit current value | In an erase or insert function, the passed iterator @a pos does not belong to the JSON value for which the function was called. It hence does not define a valid position for the deletion/insertion.
json.exception.invalid_iterator.203 | iterators do not fit current value | Either iterator passed to function @ref erase(IteratorType first, IteratorType last) does not belong to the JSON value from which values shall be erased. It hence does not define a valid range to delete values from.
json.exception.invalid_iterator.204 | iterators out of range | When an iterator range for a primitive type (number, boolean, or string) is passed to a constructor or an erase function, this range has to be exactly (@ref begin(), @ref end()), because this is the only way the single stored value is expressed. All other ranges are invalid.
json.exception.invalid_iterator.205 | iterator out of range | When an iterator for a primitive type (number, boolean, or string) is passed to an erase function, the iterator has to be the @ref begin() iterator, because it is the only way to address the stored value. All other iterators are invalid.
json.exception.invalid_iterator.206 | cannot construct with iterators from null | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) belong to a JSON null value and hence to not define a valid range.
json.exception.invalid_iterator.207 | cannot use key() for non-object iterators | The key() member function can only be used on iterators belonging to a JSON object, because other types do not have a concept of a key.
json.exception.invalid_iterator.208 | cannot use operator[] for object iterators | The operator[] to specify a concrete offset cannot be used on iterators belonging to a JSON object, because JSON objects are unordered.
json.exception.invalid_iterator.209 | cannot use offsets with object iterators | The offset operators (+, -, +=, -=) cannot be used on iterators belonging to a JSON object, because JSON objects are unordered.
json.exception.invalid_iterator.210 | iterators do not fit | The iterator range passed to the insert function are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid.
json.exception.invalid_iterator.211 | passed iterators may not belong to container | The iterator range passed to the insert function must not be a subrange of the container to insert to.
json.exception.invalid_iterator.212 | cannot compare iterators of different containers | When two iterators are compared, they must belong to the same container.
json.exception.invalid_iterator.213 | cannot compare order of object iterators | The order of object iterators cannot be compared, because JSON objects are unordered.
json.exception.invalid_iterator.214 | cannot get value | Cannot get value for iterator: Either the iterator belongs to a null value or it is an iterator to a primitive type (number, boolean, or string), but the iterator is different to @ref begin().
@liveexample{The following code shows how an `invalid_iterator` exception can be
caught.,invalid_iterator}
@sa - @ref exception for the base class of the library exceptions
@sa - @ref parse_error for exceptions indicating a parse error
@sa - @ref type_error for exceptions indicating executing a member function with
a wrong type
@sa - @ref out_of_range for exceptions indicating access out of the defined range
@sa - @ref other_error for exceptions indicating other library errors
@since version 3.0.0
*/
class invalid_iterator : public exception
{
public:
template<typename BasicJsonType>
static invalid_iterator create(int id_, const std::string& what_arg, const BasicJsonType& context)
{
std::string w = exception::name("invalid_iterator", id_) + exception::diagnostics(context) + what_arg;
return invalid_iterator(id_, w.c_str());
}
private:
JSON_HEDLEY_NON_NULL(3)
invalid_iterator(int id_, const char* what_arg)
: exception(id_, what_arg) {}
};
/*!
@brief exception indicating executing a member function with a wrong type
This exception is thrown in case of a type error; that is, a library function is
executed on a JSON value whose type does not match the expected semantics.
Exceptions have ids 3xx.
name / id | example message | description
----------------------------- | --------------- | -------------------------
json.exception.type_error.301 | cannot create object from initializer list | To create an object from an initializer list, the initializer list must consist only of a list of pairs whose first element is a string. When this constraint is violated, an array is created instead.
json.exception.type_error.302 | type must be object, but is array | During implicit or explicit value conversion, the JSON type must be compatible to the target type. For instance, a JSON string can only be converted into string types, but not into numbers or boolean types.
json.exception.type_error.303 | incompatible ReferenceType for get_ref, actual type is object | To retrieve a reference to a value stored in a @ref basic_json object with @ref get_ref, the type of the reference must match the value type. For instance, for a JSON array, the @a ReferenceType must be @ref array_t &.
json.exception.type_error.304 | cannot use at() with string | The @ref at() member functions can only be executed for certain JSON types.
json.exception.type_error.305 | cannot use operator[] with string | The @ref operator[] member functions can only be executed for certain JSON types.
json.exception.type_error.306 | cannot use value() with string | The @ref value() member functions can only be executed for certain JSON types.
json.exception.type_error.307 | cannot use erase() with string | The @ref erase() member functions can only be executed for certain JSON types.
json.exception.type_error.308 | cannot use push_back() with string | The @ref push_back() and @ref operator+= member functions can only be executed for certain JSON types.
json.exception.type_error.309 | cannot use insert() with | The @ref insert() member functions can only be executed for certain JSON types.
json.exception.type_error.310 | cannot use swap() with number | The @ref swap() member functions can only be executed for certain JSON types.
json.exception.type_error.311 | cannot use emplace_back() with string | The @ref emplace_back() member function can only be executed for certain JSON types.
json.exception.type_error.312 | cannot use update() with string | The @ref update() member functions can only be executed for certain JSON types.
json.exception.type_error.313 | invalid value to unflatten | The @ref unflatten function converts an object whose keys are JSON Pointers back into an arbitrary nested JSON value. The JSON Pointers must not overlap, because then the resulting value would not be well defined.
json.exception.type_error.314 | only objects can be unflattened | The @ref unflatten function only works for an object whose keys are JSON Pointers.
json.exception.type_error.315 | values in object must be primitive | The @ref unflatten function only works for an object whose keys are JSON Pointers and whose values are primitive.
json.exception.type_error.316 | invalid UTF-8 byte at index 10: 0x7E | The @ref dump function only works with UTF-8 encoded strings; that is, if you assign a `std::string` to a JSON value, make sure it is UTF-8 encoded. |
json.exception.type_error.317 | JSON value cannot be serialized to requested format | The dynamic type of the object cannot be represented in the requested serialization format (e.g. a raw `true` or `null` JSON object cannot be serialized to BSON) |
@liveexample{The following code shows how a `type_error` exception can be
caught.,type_error}
@sa - @ref exception for the base class of the library exceptions
@sa - @ref parse_error for exceptions indicating a parse error
@sa - @ref invalid_iterator for exceptions indicating errors with iterators
@sa - @ref out_of_range for exceptions indicating access out of the defined range
@sa - @ref other_error for exceptions indicating other library errors
@since version 3.0.0
*/
class type_error : public exception
{
public:
template<typename BasicJsonType>
static type_error create(int id_, const std::string& what_arg, const BasicJsonType& context)
{
std::string w = exception::name("type_error", id_) + exception::diagnostics(context) + what_arg;
return type_error(id_, w.c_str());
}
private:
JSON_HEDLEY_NON_NULL(3)
type_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
};
/*!
@brief exception indicating access out of the defined range
This exception is thrown in case a library function is called on an input
parameter that exceeds the expected range, for instance in case of array
indices or nonexisting object keys.
Exceptions have ids 4xx.
name / id | example message | description
------------------------------- | --------------- | -------------------------
json.exception.out_of_range.401 | array index 3 is out of range | The provided array index @a i is larger than @a size-1.
json.exception.out_of_range.402 | array index '-' (3) is out of range | The special array index `-` in a JSON Pointer never describes a valid element of the array, but the index past the end. That is, it can only be used to add elements at this position, but not to read it.
json.exception.out_of_range.403 | key 'foo' not found | The provided key was not found in the JSON object.
json.exception.out_of_range.404 | unresolved reference token 'foo' | A reference token in a JSON Pointer could not be resolved.
json.exception.out_of_range.405 | JSON pointer has no parent | The JSON Patch operations 'remove' and 'add' can not be applied to the root element of the JSON value.
json.exception.out_of_range.406 | number overflow parsing '10E1000' | A parsed number could not be stored as without changing it to NaN or INF.
json.exception.out_of_range.407 | number overflow serializing '9223372036854775808' | UBJSON and BSON only support integer numbers up to 9223372036854775807. (until version 3.8.0) |
json.exception.out_of_range.408 | excessive array size: 8658170730974374167 | The size (following `#`) of an UBJSON array or object exceeds the maximal capacity. |
json.exception.out_of_range.409 | BSON key cannot contain code point U+0000 (at byte 2) | Key identifiers to be serialized to BSON cannot contain code point U+0000, since the key is stored as zero-terminated c-string |
@liveexample{The following code shows how an `out_of_range` exception can be
caught.,out_of_range}
@sa - @ref exception for the base class of the library exceptions
@sa - @ref parse_error for exceptions indicating a parse error
@sa - @ref invalid_iterator for exceptions indicating errors with iterators
@sa - @ref type_error for exceptions indicating executing a member function with
a wrong type
@sa - @ref other_error for exceptions indicating other library errors
@since version 3.0.0
*/
class out_of_range : public exception
{
public:
template<typename BasicJsonType>
static out_of_range create(int id_, const std::string& what_arg, const BasicJsonType& context)
{
std::string w = exception::name("out_of_range", id_) + exception::diagnostics(context) + what_arg;
return out_of_range(id_, w.c_str());
}
private:
JSON_HEDLEY_NON_NULL(3)
out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}
};
/*!
@brief exception indicating other library errors
This exception is thrown in case of errors that cannot be classified with the
other exception types.
Exceptions have ids 5xx.
name / id | example message | description
------------------------------ | --------------- | -------------------------
json.exception.other_error.501 | unsuccessful: {"op":"test","path":"/baz", "value":"bar"} | A JSON Patch operation 'test' failed. The unsuccessful operation is also printed.
@sa - @ref exception for the base class of the library exceptions
@sa - @ref parse_error for exceptions indicating a parse error
@sa - @ref invalid_iterator for exceptions indicating errors with iterators
@sa - @ref type_error for exceptions indicating executing a member function with
a wrong type
@sa - @ref out_of_range for exceptions indicating access out of the defined range
@liveexample{The following code shows how an `other_error` exception can be
caught.,other_error}
@since version 3.0.0
*/
class other_error : public exception
{
public:
template<typename BasicJsonType>
static other_error create(int id_, const std::string& what_arg, const BasicJsonType& context)
{
std::string w = exception::name("other_error", id_) + exception::diagnostics(context) + what_arg;
return other_error(id_, w.c_str());
}
private:
JSON_HEDLEY_NON_NULL(3)
other_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
};
} // namespace detail
} // namespace nlohmann

View File

@@ -0,0 +1,122 @@
#pragma once
#include <cstdint> // uint8_t
#include <cstddef> // size_t
#include <functional> // hash
#include <nlohmann/detail/macro_scope.hpp>
#include <nlohmann/detail/value_t.hpp>
namespace nlohmann
{
namespace detail
{
// boost::hash_combine
inline std::size_t combine(std::size_t seed, std::size_t h) noexcept
{
seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U);
return seed;
}
/*!
@brief hash a JSON value
The hash function tries to rely on std::hash where possible. Furthermore, the
type of the JSON value is taken into account to have different hash values for
null, 0, 0U, and false, etc.
@tparam BasicJsonType basic_json specialization
@param j JSON value to hash
@return hash value of j
*/
template<typename BasicJsonType>
std::size_t hash(const BasicJsonType& j)
{
using string_t = typename BasicJsonType::string_t;
using number_integer_t = typename BasicJsonType::number_integer_t;
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
using number_float_t = typename BasicJsonType::number_float_t;
const auto type = static_cast<std::size_t>(j.type());
switch (j.type())
{
case BasicJsonType::value_t::null:
case BasicJsonType::value_t::discarded:
{
return combine(type, 0);
}
case BasicJsonType::value_t::object:
{
auto seed = combine(type, j.size());
for (const auto& element : j.items())
{
const auto h = std::hash<string_t> {}(element.key());
seed = combine(seed, h);
seed = combine(seed, hash(element.value()));
}
return seed;
}
case BasicJsonType::value_t::array:
{
auto seed = combine(type, j.size());
for (const auto& element : j)
{
seed = combine(seed, hash(element));
}
return seed;
}
case BasicJsonType::value_t::string:
{
const auto h = std::hash<string_t> {}(j.template get_ref<const string_t&>());
return combine(type, h);
}
case BasicJsonType::value_t::boolean:
{
const auto h = std::hash<bool> {}(j.template get<bool>());
return combine(type, h);
}
case BasicJsonType::value_t::number_integer:
{
const auto h = std::hash<number_integer_t> {}(j.template get<number_integer_t>());
return combine(type, h);
}
case BasicJsonType::value_t::number_unsigned:
{
const auto h = std::hash<number_unsigned_t> {}(j.template get<number_unsigned_t>());
return combine(type, h);
}
case BasicJsonType::value_t::number_float:
{
const auto h = std::hash<number_float_t> {}(j.template get<number_float_t>());
return combine(type, h);
}
case BasicJsonType::value_t::binary:
{
auto seed = combine(type, j.get_binary().size());
const auto h = std::hash<bool> {}(j.get_binary().has_subtype());
seed = combine(seed, h);
seed = combine(seed, static_cast<std::size_t>(j.get_binary().subtype()));
for (const auto byte : j.get_binary())
{
seed = combine(seed, std::hash<std::uint8_t> {}(byte));
}
return seed;
}
default: // LCOV_EXCL_LINE
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
return 0; // LCOV_EXCL_LINE
}
}
} // namespace detail
} // namespace nlohmann

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,483 @@
#pragma once
#include <array> // array
#include <cstddef> // size_t
#include <cstring> // strlen
#include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
#include <memory> // shared_ptr, make_shared, addressof
#include <numeric> // accumulate
#include <string> // string, char_traits
#include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
#include <utility> // pair, declval
#ifndef JSON_NO_IO
#include <cstdio> // FILE *
#include <istream> // istream
#endif // JSON_NO_IO
#include <nlohmann/detail/iterators/iterator_traits.hpp>
#include <nlohmann/detail/macro_scope.hpp>
namespace nlohmann
{
namespace detail
{
/// the supported input formats
enum class input_format_t { json, cbor, msgpack, ubjson, bson };
////////////////////
// input adapters //
////////////////////
#ifndef JSON_NO_IO
/*!
Input adapter for stdio file access. This adapter read only 1 byte and do not use any
buffer. This adapter is a very low level adapter.
*/
class file_input_adapter
{
public:
using char_type = char;
JSON_HEDLEY_NON_NULL(2)
explicit file_input_adapter(std::FILE* f) noexcept
: m_file(f)
{}
// make class move-only
file_input_adapter(const file_input_adapter&) = delete;
file_input_adapter(file_input_adapter&&) noexcept = default;
file_input_adapter& operator=(const file_input_adapter&) = delete;
file_input_adapter& operator=(file_input_adapter&&) = delete;
~file_input_adapter() = default;
std::char_traits<char>::int_type get_character() noexcept
{
return std::fgetc(m_file);
}
private:
/// the file pointer to read from
std::FILE* m_file;
};
/*!
Input adapter for a (caching) istream. Ignores a UFT Byte Order Mark at
beginning of input. Does not support changing the underlying std::streambuf
in mid-input. Maintains underlying std::istream and std::streambuf to support
subsequent use of standard std::istream operations to process any input
characters following those used in parsing the JSON input. Clears the
std::istream flags; any input errors (e.g., EOF) will be detected by the first
subsequent call for input from the std::istream.
*/
class input_stream_adapter
{
public:
using char_type = char;
~input_stream_adapter()
{
// clear stream flags; we use underlying streambuf I/O, do not
// maintain ifstream flags, except eof
if (is != nullptr)
{
is->clear(is->rdstate() & std::ios::eofbit);
}
}
explicit input_stream_adapter(std::istream& i)
: is(&i), sb(i.rdbuf())
{}
// delete because of pointer members
input_stream_adapter(const input_stream_adapter&) = delete;
input_stream_adapter& operator=(input_stream_adapter&) = delete;
input_stream_adapter& operator=(input_stream_adapter&&) = delete;
input_stream_adapter(input_stream_adapter&& rhs) noexcept
: is(rhs.is), sb(rhs.sb)
{
rhs.is = nullptr;
rhs.sb = nullptr;
}
// std::istream/std::streambuf use std::char_traits<char>::to_int_type, to
// ensure that std::char_traits<char>::eof() and the character 0xFF do not
// end up as the same value, eg. 0xFFFFFFFF.
std::char_traits<char>::int_type get_character()
{
auto res = sb->sbumpc();
// set eof manually, as we don't use the istream interface.
if (JSON_HEDLEY_UNLIKELY(res == std::char_traits<char>::eof()))
{
is->clear(is->rdstate() | std::ios::eofbit);
}
return res;
}
private:
/// the associated input stream
std::istream* is = nullptr;
std::streambuf* sb = nullptr;
};
#endif // JSON_NO_IO
// General-purpose iterator-based adapter. It might not be as fast as
// theoretically possible for some containers, but it is extremely versatile.
template<typename IteratorType>
class iterator_input_adapter
{
public:
using char_type = typename std::iterator_traits<IteratorType>::value_type;
iterator_input_adapter(IteratorType first, IteratorType last)
: current(std::move(first)), end(std::move(last))
{}
typename std::char_traits<char_type>::int_type get_character()
{
if (JSON_HEDLEY_LIKELY(current != end))
{
auto result = std::char_traits<char_type>::to_int_type(*current);
std::advance(current, 1);
return result;
}
return std::char_traits<char_type>::eof();
}
private:
IteratorType current;
IteratorType end;
template<typename BaseInputAdapter, size_t T>
friend struct wide_string_input_helper;
bool empty() const
{
return current == end;
}
};
template<typename BaseInputAdapter, size_t T>
struct wide_string_input_helper;
template<typename BaseInputAdapter>
struct wide_string_input_helper<BaseInputAdapter, 4>
{
// UTF-32
static void fill_buffer(BaseInputAdapter& input,
std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
size_t& utf8_bytes_index,
size_t& utf8_bytes_filled)
{
utf8_bytes_index = 0;
if (JSON_HEDLEY_UNLIKELY(input.empty()))
{
utf8_bytes[0] = std::char_traits<char>::eof();
utf8_bytes_filled = 1;
}
else
{
// get the current character
const auto wc = input.get_character();
// UTF-32 to UTF-8 encoding
if (wc < 0x80)
{
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
utf8_bytes_filled = 1;
}
else if (wc <= 0x7FF)
{
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u) & 0x1Fu));
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
utf8_bytes_filled = 2;
}
else if (wc <= 0xFFFF)
{
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u) & 0x0Fu));
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
utf8_bytes_filled = 3;
}
else if (wc <= 0x10FFFF)
{
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | ((static_cast<unsigned int>(wc) >> 18u) & 0x07u));
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 12u) & 0x3Fu));
utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
utf8_bytes_filled = 4;
}
else
{
// unknown character
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
utf8_bytes_filled = 1;
}
}
}
};
template<typename BaseInputAdapter>
struct wide_string_input_helper<BaseInputAdapter, 2>
{
// UTF-16
static void fill_buffer(BaseInputAdapter& input,
std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
size_t& utf8_bytes_index,
size_t& utf8_bytes_filled)
{
utf8_bytes_index = 0;
if (JSON_HEDLEY_UNLIKELY(input.empty()))
{
utf8_bytes[0] = std::char_traits<char>::eof();
utf8_bytes_filled = 1;
}
else
{
// get the current character
const auto wc = input.get_character();
// UTF-16 to UTF-8 encoding
if (wc < 0x80)
{
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
utf8_bytes_filled = 1;
}
else if (wc <= 0x7FF)
{
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u)));
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
utf8_bytes_filled = 2;
}
else if (0xD800 > wc || wc >= 0xE000)
{
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u)));
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
utf8_bytes_filled = 3;
}
else
{
if (JSON_HEDLEY_UNLIKELY(!input.empty()))
{
const auto wc2 = static_cast<unsigned int>(input.get_character());
const auto charcode = 0x10000u + (((static_cast<unsigned int>(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu));
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | (charcode >> 18u));
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu));
utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu));
utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (charcode & 0x3Fu));
utf8_bytes_filled = 4;
}
else
{
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
utf8_bytes_filled = 1;
}
}
}
}
};
// Wraps another input apdater to convert wide character types into individual bytes.
template<typename BaseInputAdapter, typename WideCharType>
class wide_string_input_adapter
{
public:
using char_type = char;
wide_string_input_adapter(BaseInputAdapter base)
: base_adapter(base) {}
typename std::char_traits<char>::int_type get_character() noexcept
{
// check if buffer needs to be filled
if (utf8_bytes_index == utf8_bytes_filled)
{
fill_buffer<sizeof(WideCharType)>();
JSON_ASSERT(utf8_bytes_filled > 0);
JSON_ASSERT(utf8_bytes_index == 0);
}
// use buffer
JSON_ASSERT(utf8_bytes_filled > 0);
JSON_ASSERT(utf8_bytes_index < utf8_bytes_filled);
return utf8_bytes[utf8_bytes_index++];
}
private:
BaseInputAdapter base_adapter;
template<size_t T>
void fill_buffer()
{
wide_string_input_helper<BaseInputAdapter, T>::fill_buffer(base_adapter, utf8_bytes, utf8_bytes_index, utf8_bytes_filled);
}
/// a buffer for UTF-8 bytes
std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}};
/// index to the utf8_codes array for the next valid byte
std::size_t utf8_bytes_index = 0;
/// number of valid bytes in the utf8_codes array
std::size_t utf8_bytes_filled = 0;
};
template<typename IteratorType, typename Enable = void>
struct iterator_input_adapter_factory
{
using iterator_type = IteratorType;
using char_type = typename std::iterator_traits<iterator_type>::value_type;
using adapter_type = iterator_input_adapter<iterator_type>;
static adapter_type create(IteratorType first, IteratorType last)
{
return adapter_type(std::move(first), std::move(last));
}
};
template<typename T>
struct is_iterator_of_multibyte
{
using value_type = typename std::iterator_traits<T>::value_type;
enum
{
value = sizeof(value_type) > 1
};
};
template<typename IteratorType>
struct iterator_input_adapter_factory<IteratorType, enable_if_t<is_iterator_of_multibyte<IteratorType>::value>>
{
using iterator_type = IteratorType;
using char_type = typename std::iterator_traits<iterator_type>::value_type;
using base_adapter_type = iterator_input_adapter<iterator_type>;
using adapter_type = wide_string_input_adapter<base_adapter_type, char_type>;
static adapter_type create(IteratorType first, IteratorType last)
{
return adapter_type(base_adapter_type(std::move(first), std::move(last)));
}
};
// General purpose iterator-based input
template<typename IteratorType>
typename iterator_input_adapter_factory<IteratorType>::adapter_type input_adapter(IteratorType first, IteratorType last)
{
using factory_type = iterator_input_adapter_factory<IteratorType>;
return factory_type::create(first, last);
}
// Convenience shorthand from container to iterator
// Enables ADL on begin(container) and end(container)
// Encloses the using declarations in namespace for not to leak them to outside scope
namespace container_input_adapter_factory_impl
{
using std::begin;
using std::end;
template<typename ContainerType, typename Enable = void>
struct container_input_adapter_factory {};
template<typename ContainerType>
struct container_input_adapter_factory< ContainerType,
void_t<decltype(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))>>
{
using adapter_type = decltype(input_adapter(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>())));
static adapter_type create(const ContainerType& container)
{
return input_adapter(begin(container), end(container));
}
};
} // namespace container_input_adapter_factory_impl
template<typename ContainerType>
typename container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::adapter_type input_adapter(const ContainerType& container)
{
return container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::create(container);
}
#ifndef JSON_NO_IO
// Special cases with fast paths
inline file_input_adapter input_adapter(std::FILE* file)
{
return file_input_adapter(file);
}
inline input_stream_adapter input_adapter(std::istream& stream)
{
return input_stream_adapter(stream);
}
inline input_stream_adapter input_adapter(std::istream&& stream)
{
return input_stream_adapter(stream);
}
#endif // JSON_NO_IO
using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval<const char*>(), std::declval<const char*>()));
// Null-delimited strings, and the like.
template < typename CharT,
typename std::enable_if <
std::is_pointer<CharT>::value&&
!std::is_array<CharT>::value&&
std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
sizeof(typename std::remove_pointer<CharT>::type) == 1,
int >::type = 0 >
contiguous_bytes_input_adapter input_adapter(CharT b)
{
auto length = std::strlen(reinterpret_cast<const char*>(b));
const auto* ptr = reinterpret_cast<const char*>(b);
return input_adapter(ptr, ptr + length);
}
template<typename T, std::size_t N>
auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N)) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
{
return input_adapter(array, array + N);
}
// This class only handles inputs of input_buffer_adapter type.
// It's required so that expressions like {ptr, len} can be implicitely casted
// to the correct adapter.
class span_input_adapter
{
public:
template < typename CharT,
typename std::enable_if <
std::is_pointer<CharT>::value&&
std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
sizeof(typename std::remove_pointer<CharT>::type) == 1,
int >::type = 0 >
span_input_adapter(CharT b, std::size_t l)
: ia(reinterpret_cast<const char*>(b), reinterpret_cast<const char*>(b) + l) {}
template<class IteratorType,
typename std::enable_if<
std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value,
int>::type = 0>
span_input_adapter(IteratorType first, IteratorType last)
: ia(input_adapter(first, last)) {}
contiguous_bytes_input_adapter&& get()
{
return std::move(ia); // NOLINT(hicpp-move-const-arg,performance-move-const-arg)
}
private:
contiguous_bytes_input_adapter ia;
};
} // namespace detail
} // namespace nlohmann

View File

@@ -0,0 +1,711 @@
#pragma once
#include <cstddef>
#include <string> // string
#include <utility> // move
#include <vector> // vector
#include <nlohmann/detail/exceptions.hpp>
#include <nlohmann/detail/macro_scope.hpp>
namespace nlohmann
{
/*!
@brief SAX interface
This class describes the SAX interface used by @ref nlohmann::json::sax_parse.
Each function is called in different situations while the input is parsed. The
boolean return value informs the parser whether to continue processing the
input.
*/
template<typename BasicJsonType>
struct json_sax
{
using number_integer_t = typename BasicJsonType::number_integer_t;
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
using number_float_t = typename BasicJsonType::number_float_t;
using string_t = typename BasicJsonType::string_t;
using binary_t = typename BasicJsonType::binary_t;
/*!
@brief a null value was read
@return whether parsing should proceed
*/
virtual bool null() = 0;
/*!
@brief a boolean value was read
@param[in] val boolean value
@return whether parsing should proceed
*/
virtual bool boolean(bool val) = 0;
/*!
@brief an integer number was read
@param[in] val integer value
@return whether parsing should proceed
*/
virtual bool number_integer(number_integer_t val) = 0;
/*!
@brief an unsigned integer number was read
@param[in] val unsigned integer value
@return whether parsing should proceed
*/
virtual bool number_unsigned(number_unsigned_t val) = 0;
/*!
@brief an floating-point number was read
@param[in] val floating-point value
@param[in] s raw token value
@return whether parsing should proceed
*/
virtual bool number_float(number_float_t val, const string_t& s) = 0;
/*!
@brief a string was read
@param[in] val string value
@return whether parsing should proceed
@note It is safe to move the passed string.
*/
virtual bool string(string_t& val) = 0;
/*!
@brief a binary string was read
@param[in] val binary value
@return whether parsing should proceed
@note It is safe to move the passed binary.
*/
virtual bool binary(binary_t& val) = 0;
/*!
@brief the beginning of an object was read
@param[in] elements number of object elements or -1 if unknown
@return whether parsing should proceed
@note binary formats may report the number of elements
*/
virtual bool start_object(std::size_t elements) = 0;
/*!
@brief an object key was read
@param[in] val object key
@return whether parsing should proceed
@note It is safe to move the passed string.
*/
virtual bool key(string_t& val) = 0;
/*!
@brief the end of an object was read
@return whether parsing should proceed
*/
virtual bool end_object() = 0;
/*!
@brief the beginning of an array was read
@param[in] elements number of array elements or -1 if unknown
@return whether parsing should proceed
@note binary formats may report the number of elements
*/
virtual bool start_array(std::size_t elements) = 0;
/*!
@brief the end of an array was read
@return whether parsing should proceed
*/
virtual bool end_array() = 0;
/*!
@brief a parse error occurred
@param[in] position the position in the input where the error occurs
@param[in] last_token the last read token
@param[in] ex an exception object describing the error
@return whether parsing should proceed (must return false)
*/
virtual bool parse_error(std::size_t position,
const std::string& last_token,
const detail::exception& ex) = 0;
json_sax() = default;
json_sax(const json_sax&) = default;
json_sax(json_sax&&) noexcept = default;
json_sax& operator=(const json_sax&) = default;
json_sax& operator=(json_sax&&) noexcept = default;
virtual ~json_sax() = default;
};
namespace detail
{
/*!
@brief SAX implementation to create a JSON value from SAX events
This class implements the @ref json_sax interface and processes the SAX events
to create a JSON value which makes it basically a DOM parser. The structure or
hierarchy of the JSON value is managed by the stack `ref_stack` which contains
a pointer to the respective array or object for each recursion depth.
After successful parsing, the value that is passed by reference to the
constructor contains the parsed value.
@tparam BasicJsonType the JSON type
*/
template<typename BasicJsonType>
class json_sax_dom_parser
{
public:
using number_integer_t = typename BasicJsonType::number_integer_t;
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
using number_float_t = typename BasicJsonType::number_float_t;
using string_t = typename BasicJsonType::string_t;
using binary_t = typename BasicJsonType::binary_t;
/*!
@param[in,out] r reference to a JSON value that is manipulated while
parsing
@param[in] allow_exceptions_ whether parse errors yield exceptions
*/
explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true)
: root(r), allow_exceptions(allow_exceptions_)
{}
// make class move-only
json_sax_dom_parser(const json_sax_dom_parser&) = delete;
json_sax_dom_parser(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
json_sax_dom_parser& operator=(const json_sax_dom_parser&) = delete;
json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
~json_sax_dom_parser() = default;
bool null()
{
handle_value(nullptr);
return true;
}
bool boolean(bool val)
{
handle_value(val);
return true;
}
bool number_integer(number_integer_t val)
{
handle_value(val);
return true;
}
bool number_unsigned(number_unsigned_t val)
{
handle_value(val);
return true;
}
bool number_float(number_float_t val, const string_t& /*unused*/)
{
handle_value(val);
return true;
}
bool string(string_t& val)
{
handle_value(val);
return true;
}
bool binary(binary_t& val)
{
handle_value(std::move(val));
return true;
}
bool start_object(std::size_t len)
{
ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
if (JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size()))
{
JSON_THROW(out_of_range::create(408, "excessive object size: " + std::to_string(len), *ref_stack.back()));
}
return true;
}
bool key(string_t& val)
{
// add null at given key and store the reference for later
object_element = &(ref_stack.back()->m_value.object->operator[](val));
return true;
}
bool end_object()
{
ref_stack.back()->set_parents();
ref_stack.pop_back();
return true;
}
bool start_array(std::size_t len)
{
ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
if (JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size()))
{
JSON_THROW(out_of_range::create(408, "excessive array size: " + std::to_string(len), *ref_stack.back()));
}
return true;
}
bool end_array()
{
ref_stack.back()->set_parents();
ref_stack.pop_back();
return true;
}
template<class Exception>
bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
const Exception& ex)
{
errored = true;
static_cast<void>(ex);
if (allow_exceptions)
{
JSON_THROW(ex);
}
return false;
}
constexpr bool is_errored() const
{
return errored;
}
private:
/*!
@invariant If the ref stack is empty, then the passed value will be the new
root.
@invariant If the ref stack contains a value, then it is an array or an
object to which we can add elements
*/
template<typename Value>
JSON_HEDLEY_RETURNS_NON_NULL
BasicJsonType* handle_value(Value&& v)
{
if (ref_stack.empty())
{
root = BasicJsonType(std::forward<Value>(v));
return &root;
}
JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
if (ref_stack.back()->is_array())
{
ref_stack.back()->m_value.array->emplace_back(std::forward<Value>(v));
return &(ref_stack.back()->m_value.array->back());
}
JSON_ASSERT(ref_stack.back()->is_object());
JSON_ASSERT(object_element);
*object_element = BasicJsonType(std::forward<Value>(v));
return object_element;
}
/// the parsed JSON value
BasicJsonType& root;
/// stack to model hierarchy of values
std::vector<BasicJsonType*> ref_stack {};
/// helper to hold the reference for the next object element
BasicJsonType* object_element = nullptr;
/// whether a syntax error occurred
bool errored = false;
/// whether to throw exceptions in case of errors
const bool allow_exceptions = true;
};
template<typename BasicJsonType>
class json_sax_dom_callback_parser
{
public:
using number_integer_t = typename BasicJsonType::number_integer_t;
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
using number_float_t = typename BasicJsonType::number_float_t;
using string_t = typename BasicJsonType::string_t;
using binary_t = typename BasicJsonType::binary_t;
using parser_callback_t = typename BasicJsonType::parser_callback_t;
using parse_event_t = typename BasicJsonType::parse_event_t;
json_sax_dom_callback_parser(BasicJsonType& r,
const parser_callback_t cb,
const bool allow_exceptions_ = true)
: root(r), callback(cb), allow_exceptions(allow_exceptions_)
{
keep_stack.push_back(true);
}
// make class move-only
json_sax_dom_callback_parser(const json_sax_dom_callback_parser&) = delete;
json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
json_sax_dom_callback_parser& operator=(const json_sax_dom_callback_parser&) = delete;
json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
~json_sax_dom_callback_parser() = default;
bool null()
{
handle_value(nullptr);
return true;
}
bool boolean(bool val)
{
handle_value(val);
return true;
}
bool number_integer(number_integer_t val)
{
handle_value(val);
return true;
}
bool number_unsigned(number_unsigned_t val)
{
handle_value(val);
return true;
}
bool number_float(number_float_t val, const string_t& /*unused*/)
{
handle_value(val);
return true;
}
bool string(string_t& val)
{
handle_value(val);
return true;
}
bool binary(binary_t& val)
{
handle_value(std::move(val));
return true;
}
bool start_object(std::size_t len)
{
// check callback for object start
const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded);
keep_stack.push_back(keep);
auto val = handle_value(BasicJsonType::value_t::object, true);
ref_stack.push_back(val.second);
// check object limit
if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size()))
{
JSON_THROW(out_of_range::create(408, "excessive object size: " + std::to_string(len), *ref_stack.back()));
}
return true;
}
bool key(string_t& val)
{
BasicJsonType k = BasicJsonType(val);
// check callback for key
const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k);
key_keep_stack.push_back(keep);
// add discarded value at given key and store the reference for later
if (keep && ref_stack.back())
{
object_element = &(ref_stack.back()->m_value.object->operator[](val) = discarded);
}
return true;
}
bool end_object()
{
if (ref_stack.back())
{
if (!callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))
{
// discard object
*ref_stack.back() = discarded;
}
else
{
ref_stack.back()->set_parents();
}
}
JSON_ASSERT(!ref_stack.empty());
JSON_ASSERT(!keep_stack.empty());
ref_stack.pop_back();
keep_stack.pop_back();
if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured())
{
// remove discarded value
for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it)
{
if (it->is_discarded())
{
ref_stack.back()->erase(it);
break;
}
}
}
return true;
}
bool start_array(std::size_t len)
{
const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded);
keep_stack.push_back(keep);
auto val = handle_value(BasicJsonType::value_t::array, true);
ref_stack.push_back(val.second);
// check array limit
if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size()))
{
JSON_THROW(out_of_range::create(408, "excessive array size: " + std::to_string(len), *ref_stack.back()));
}
return true;
}
bool end_array()
{
bool keep = true;
if (ref_stack.back())
{
keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back());
if (keep)
{
ref_stack.back()->set_parents();
}
else
{
// discard array
*ref_stack.back() = discarded;
}
}
JSON_ASSERT(!ref_stack.empty());
JSON_ASSERT(!keep_stack.empty());
ref_stack.pop_back();
keep_stack.pop_back();
// remove discarded value
if (!keep && !ref_stack.empty() && ref_stack.back()->is_array())
{
ref_stack.back()->m_value.array->pop_back();
}
return true;
}
template<class Exception>
bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
const Exception& ex)
{
errored = true;
static_cast<void>(ex);
if (allow_exceptions)
{
JSON_THROW(ex);
}
return false;
}
constexpr bool is_errored() const
{
return errored;
}
private:
/*!
@param[in] v value to add to the JSON value we build during parsing
@param[in] skip_callback whether we should skip calling the callback
function; this is required after start_array() and
start_object() SAX events, because otherwise we would call the
callback function with an empty array or object, respectively.
@invariant If the ref stack is empty, then the passed value will be the new
root.
@invariant If the ref stack contains a value, then it is an array or an
object to which we can add elements
@return pair of boolean (whether value should be kept) and pointer (to the
passed value in the ref_stack hierarchy; nullptr if not kept)
*/
template<typename Value>
std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false)
{
JSON_ASSERT(!keep_stack.empty());
// do not handle this value if we know it would be added to a discarded
// container
if (!keep_stack.back())
{
return {false, nullptr};
}
// create value
auto value = BasicJsonType(std::forward<Value>(v));
// check callback
const bool keep = skip_callback || callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
// do not handle this value if we just learnt it shall be discarded
if (!keep)
{
return {false, nullptr};
}
if (ref_stack.empty())
{
root = std::move(value);
return {true, &root};
}
// skip this value if we already decided to skip the parent
// (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
if (!ref_stack.back())
{
return {false, nullptr};
}
// we now only expect arrays and objects
JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
// array
if (ref_stack.back()->is_array())
{
ref_stack.back()->m_value.array->emplace_back(std::move(value));
return {true, &(ref_stack.back()->m_value.array->back())};
}
// object
JSON_ASSERT(ref_stack.back()->is_object());
// check if we should store an element for the current key
JSON_ASSERT(!key_keep_stack.empty());
const bool store_element = key_keep_stack.back();
key_keep_stack.pop_back();
if (!store_element)
{
return {false, nullptr};
}
JSON_ASSERT(object_element);
*object_element = std::move(value);
return {true, object_element};
}
/// the parsed JSON value
BasicJsonType& root;
/// stack to model hierarchy of values
std::vector<BasicJsonType*> ref_stack {};
/// stack to manage which values to keep
std::vector<bool> keep_stack {};
/// stack to manage which object keys to keep
std::vector<bool> key_keep_stack {};
/// helper to hold the reference for the next object element
BasicJsonType* object_element = nullptr;
/// whether a syntax error occurred
bool errored = false;
/// callback function
const parser_callback_t callback = nullptr;
/// whether to throw exceptions in case of errors
const bool allow_exceptions = true;
/// a discarded value for the callback
BasicJsonType discarded = BasicJsonType::value_t::discarded;
};
template<typename BasicJsonType>
class json_sax_acceptor
{
public:
using number_integer_t = typename BasicJsonType::number_integer_t;
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
using number_float_t = typename BasicJsonType::number_float_t;
using string_t = typename BasicJsonType::string_t;
using binary_t = typename BasicJsonType::binary_t;
bool null()
{
return true;
}
bool boolean(bool /*unused*/)
{
return true;
}
bool number_integer(number_integer_t /*unused*/)
{
return true;
}
bool number_unsigned(number_unsigned_t /*unused*/)
{
return true;
}
bool number_float(number_float_t /*unused*/, const string_t& /*unused*/)
{
return true;
}
bool string(string_t& /*unused*/)
{
return true;
}
bool binary(binary_t& /*unused*/)
{
return true;
}
bool start_object(std::size_t /*unused*/ = std::size_t(-1))
{
return true;
}
bool key(string_t& /*unused*/)
{
return true;
}
bool end_object()
{
return true;
}
bool start_array(std::size_t /*unused*/ = std::size_t(-1))
{
return true;
}
bool end_array()
{
return true;
}
bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/)
{
return false;
}
};
} // namespace detail
} // namespace nlohmann

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