Compare commits

...

150 Commits

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

2
.gitignore vendored
View File

@@ -12,7 +12,6 @@ xs/MANIFEST.bak
xs/assertlib*
.init_bundle.ini
.vs/*
local-lib
/src/TAGS
/.vscode/
build-linux/*
@@ -22,3 +21,4 @@ deps/build-linux/*
**/.idea/
.pkg_cache
CMakeUserPresets.json
/src/slic3r/QIDI

132
Build.PL
View File

@@ -1,132 +0,0 @@
#!/usr/bin/perl
print "This script is currently used for installing Perl dependenices for running\n";
print "the libslic3r unit / integration tests through Perl prove.\n";
print "If you don't plan to run the unit / integration tests, you don't need to\n";
print "install these dependencies to build and run QIDISlicer.\n";
use strict;
use warnings;
use Config;
use File::Spec;
my %prereqs = qw(
Devel::CheckLib 0
ExtUtils::MakeMaker 6.80
ExtUtils::ParseXS 3.22
ExtUtils::XSpp 0
ExtUtils::XSpp::Cmd 0
ExtUtils::CppGuess 0
ExtUtils::Typemaps 0
ExtUtils::Typemaps::Basic 0
File::Basename 0
File::Spec 0
Getopt::Long 0
Module::Build::WithXSpp 0.14
Moo 1.003001
POSIX 0
Scalar::Util 0
Test::More 0
IO::Scalar 0
Time::HiRes 0
);
my %recommends = qw(
Class::XSAccessor 0
Test::Harness 0
);
my $sudo = grep { $_ eq '--sudo' } @ARGV;
my $nolocal = grep { $_ eq '--nolocal' } @ARGV;
my @missing_prereqs = ();
if ($ENV{SLIC3R_NO_AUTO}) {
foreach my $module (sort keys %prereqs) {
my $version = $prereqs{$module};
next if eval "use $module $version; 1";
push @missing_prereqs, $module if exists $prereqs{$module};
print "Missing prerequisite $module $version\n";
}
foreach my $module (sort keys %recommends) {
my $version = $recommends{$module};
next if eval "use $module $version; 1";
print "Missing optional $module $version\n";
}
} else {
my @try = (
$ENV{CPANM} // (),
File::Spec->catfile($Config{sitebin}, 'cpanm'),
File::Spec->catfile($Config{installscript}, 'cpanm'),
);
my $cpanm;
foreach my $path (@try) {
if (-e $path) { # don't use -x because it fails on Windows
$cpanm = $path;
last;
}
}
if (!$cpanm) {
if ($^O =~ /^(?:darwin|linux)$/ && system(qw(which cpanm)) == 0) {
$cpanm = 'cpanm';
}
}
die <<'EOF'
cpanm was not found. Please install it before running this script.
There are several ways to install cpanm, try one of these:
apt-get install cpanminus
curl -L http://cpanmin.us | perl - --sudo App::cpanminus
cpan App::cpanminus
If it is installed in a non-standard location you can do:
CPANM=/path/to/cpanm perl Build.PL
EOF
if !$cpanm;
my @cpanm_args = ();
push @cpanm_args, "--sudo" if $sudo;
# install local::lib without --local-lib otherwise it's not usable afterwards
if (!eval "use local::lib qw(local-lib); 1") {
my $res = system $cpanm, @cpanm_args, 'local::lib';
warn "Warning: local::lib is required. You might need to run the `cpanm --sudo local::lib` command in order to install it.\n"
if $res != 0;
}
push @cpanm_args, ('--local-lib', 'local-lib') if ! $nolocal;
# make sure our cpanm is updated (old ones don't support the ~ syntax)
system $cpanm, @cpanm_args, 'App::cpanminus';
my %modules = (%prereqs, %recommends);
foreach my $module (sort keys %modules) {
my $version = $modules{$module};
my @cmd = ($cpanm, @cpanm_args);
# temporary workaround for upstream bug in test
push @cmd, '--notest'
if $module =~ /^(?:OpenGL|Test::Harness)$/;
push @cmd, "$module~$version";
my $res = system @cmd;
if ($res != 0) {
if (exists $prereqs{$module}) {
push @missing_prereqs, $module;
} else {
printf "Don't worry, this module is optional.\n";
}
}
}
}
print "\n";
print "In the next step, you need to build the QIDISlicer C++ library.\n";
print "1) Create a build directory and change to it\n";
print "2) run cmake .. -DCMAKE_BUILD_TYPE=Release\n";
print "3) run make\n";
print "4) to execute the automatic tests, run ctest --verbose\n";
__END__

View File

@@ -29,7 +29,6 @@ option(SLIC3R_FHS "Assume QIDISlicer is to be installed in a FHS d
option(SLIC3R_PCH "Use precompiled headers" 1)
option(SLIC3R_MSVC_COMPILE_PARALLEL "Compile on Visual Studio in parallel" 1)
option(SLIC3R_MSVC_PDB "Generate PDB files on MSVC in Release mode" 1)
option(SLIC3R_PERL_XS "Compile XS Perl module and enable Perl unit and integration tests" 0)
option(SLIC3R_ASAN "Enable ASan on Clang and GCC" 0)
option(SLIC3R_UBSAN "Enable UBSan on Clang and GCC" 0)
option(SLIC3R_ENABLE_FORMAT_STEP "Enable compilation of STEP file support" ON)
@@ -72,7 +71,6 @@ option(SLIC3R_BUILD_TESTS "Build unit tests" ON)
if (IS_CROSS_COMPILE)
message("Detected cross compilation setup. Tests and encoding checks will be forcedly disabled!")
set(SLIC3R_PERL_XS OFF CACHE BOOL "" FORCE)
set(SLIC3R_BUILD_TESTS OFF CACHE BOOL "" FORCE)
endif ()
@@ -165,9 +163,6 @@ if(NOT WIN32)
add_compile_options("$<$<CONFIG:DEBUG>:-DDEBUG>")
endif()
# To be able to link libslic3r with the Perl XS module.
# Once we get rid of Perl and libslic3r is linked statically, we can get rid of -fPIC
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
# WIN10SDK_PATH is used to point CMake to the WIN10 SDK installation directory.
# We pick it from environment if it is not defined in another way
@@ -239,7 +234,8 @@ if (NOT MSVC AND ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMP
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall" )
endif ()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-reorder" )
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-enum-constexpr-conversion" )
# On GCC and Clang, no return from a non-void function is a warning only. Here, we make it an error.
add_compile_options(-Werror=return-type)
@@ -608,12 +604,6 @@ set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT Q
add_dependencies(gettext_make_pot hintsToPot)
# Perl bindings, currently only used for the unit / integration tests of libslic3r.
# Also runs the unit / integration tests.
#FIXME Port the tests into C++ to finally get rid of the Perl!
if (SLIC3R_PERL_XS)
add_subdirectory(xs)
endif ()
if(SLIC3R_BUILD_SANDBOXES)
add_subdirectory(sandboxes)

View File

@@ -1,103 +0,0 @@
{
"build_systems":
[
{
"name": "List",
//"file_regex": " at ([^-\\s]*) line ([0-9]*)",
// "file_regex": " at (D\\:\\/src\\/Slic3r\\/.*?) line ([0-9]*)",
"shell_cmd": "ls -l"
},
{
"name": "Run",
"working_dir": "$project_path",
"file_regex": " at (.*?) line ([0-9]*)",
// "shell_cmd": "chdir & perl slic3r.pl --DataDir \"C:\\Users\\Public\\Documents\\QIDI3D\\Slic3r settings MK2\" --gui \"..\\Slic3r-tests\\gap fill torture 20 -rt.stl\""
"shell_cmd": "chdir & perl slic3r.pl"
},
{
"name": "full",
"file_regex": "^(..[^:]*):([0-9]+):?([0-9]+)?:? (.*)$",
"shell_cmd": "chdir & perl Build.pl"
},
{
"name": "xs",
"working_dir": "$project_path/build",
// for Visual Studio:
"file_regex": "^(..[^:]*)\\(([0-9]+)\\)(.*)$",
// For GCC:
// "file_regex": "^(..[^:]*):([0-9]+):?([0-9]+)?:? (.*)$",
"shell_cmd": "chdir & ninja -j 6 -v",
"env": {
// "PATH": "C:\\Program Files (x86)\\MSBuild\\12.0\\bin\\amd64;C:\\Program Files (x86)\\Microsoft Visual Studio 12.0\\VC\\BIN\\amd64;C:\\Program Files (x86)\\Microsoft Visual Studio 12.0\\Common7\\IDE;C:\\Program Files (x86)\\Microsoft Visual Studio 12.0\\Common7\\Tools;%PATH%;c:\\wperl64d\\site\\bin;c:\\wperl64d\\bin",
// "PERL_CPANM_HOME": "c:\\wperl64d\\cpanm",
// "WXDIR": "D:\\src-perl\\wxWidgets-3.0.3-beta1",
// "BOOST_DIR": "D:\\src-perl\\boost_1_61_0",
// "BOOST_INCLUDEDIR": "D:\\src-perl\\boost_1_61_0",
// "BOOST_LIBRARYDIR": "D:\\src-perl\\boost_1_61_0\\stage\\x64\\lib",
// "SLIC3R_STATIC": "1"
}
},
{
"name": "xs & run",
"working_dir": "$project_path/build",
"file_regex": "^(..[^:]*):([0-9]+):?([0-9]+)?:? (.*)$",
"shell_cmd": "chdir & ninja -j 6 & cd .. & perl slic3r.pl --gui \"..\\Slic3r-tests\\star3-big2.stl\""
},
{
"name": "Slic3r - clean",
"working_dir": "$project_path/build",
"file_regex": "^(..[^:]*)(?::|\\()([0-9]+)(?::|\\))(?:([0-9]+):)?\\s*(.*)",
"shell_cmd": ["chdir & ninja clean"]
},
{
"name": "run tests",
"working_dir": "$project_path/build",
// for Visual Studio:
"file_regex": "^(..[^:]*)\\(([0-9]+)\\)(.*)$",
"shell_cmd": "chdir & ctest --verbose"
},
{
"name": "Clean & Configure",
"working_dir": "$project_path",
// for Visual Studio:
"file_regex": "^(..[^:]*)(?::|\\()([0-9]+)(?::|\\))(?:([0-9]+):)?\\s*(.*)",
"shell_cmd": "chdir & rmdir /S /Q build & mkdir build & cd build & cmake -G Ninja .. -DCMAKE_COLOR_MAKEFILE=OFF -DCMAKE_RULE_PROGRESS=OFF -DCMAKE_RULE_MESSAGES=OFF -DCMAKE_VERBOSE_MAKEFILE=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo"
},
{
"name": "Configure",
"working_dir": "$project_path/build",
// for Visual Studio:
"file_regex": "^(..[^:]*)(?::|\\()([0-9]+)(?::|\\))(?:([0-9]+):)?\\s*(.*)",
"shell_cmd": "cmake -G Ninja .. -DCMAKE_COLOR_MAKEFILE=OFF -DCMAKE_RULE_PROGRESS=OFF -DCMAKE_RULE_MESSAGES=OFF -DCMAKE_VERBOSE_MAKEFILE=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo"
}
],
"folders":
[
{
"path": ".",
// "folder_exclude_patterns": [".svn", "._d", ".metadata", ".settings"],
"file_exclude_patterns": ["XS.c", "*.pch", "*.ilk", "*.js" ]
}
],
"settings":
{
"sublimegdb_workingdir": "${folder:${project_path:run}}",
// NOTE: You MUST provide --interpreter=mi for the plugin to work
// "sublimegdb_commandline": "D:\\Qt\\Tools\\mingw492_32\\bin\\gdb.exe --interpreter=mi -ex 'target localhost:2345'",
// "sublimegdb_commandline": "D:\\Qt\\Tools\\mingw492_32\\bin\\gdb.exe --interpreter=mi perl --args perl slic3r.pl",
// "sublimegdb_commandline": "D:\\Qt\\Tools\\mingw492_32\\bin\\gdb.exe --interpreter=mi perl --args slic3r.pl ",
// "sublimegdb_commandline": "D:\\Qt\\Tools\\mingw492_32\\bin\\gdb.exe --interpreter=mi -e C:\\Strawberry\\perl\\bin\\perl.exe -s C:\\Strawberry\\perl\\site\\lib\\auto\\Slic3r\\XS\\XS.xs.dll --args perl slic3r.pl -j 1 --gui D:\\src\\Slic3r-tests\\star3-big.stl",
"sublimegdb_commandline": "D:\\Qt\\Tools\\mingw492_32\\bin\\gdb.exe --interpreter=mi perl.exe --args perl slic3r.pl -j 1 --gui", // D:\\src\\Slic3r-tests\\star3-big.stl",
// "sublimegdb_commandline": "D:\\Qt\\Tools\\mingw492_32\\bin\\gdb.exe --interpreter=mi -x slic3r.gdb",
// "arguments": "slic3r -j 1 --gui ../Slic3r-tests/star3-big.stl",
// "arguments": "../slic3r.pl -j 1 --gui",
// "sublimegdb_exec_cmd": "-exec-continue",
// Add "pending breakpoints" for symbols that are dynamically loaded from
// external shared libraries
"debug_ext" : true,
"run_after_init": false,
"close_views": false
}
}

115
README.md
View File

@@ -4,30 +4,123 @@
# QIDISlicer
QIDISlicer is a professional 3D printer slicing softwarewhich is perfectly compatible with all printers and 3D printing filaments of QIDI Technology. Multi-platform support, simple inerface, easy to use, complate functions, easy to learn 3D printing.
**Notice:QIDISlicer as a new software dedicated to QIDI's new high speed printers, please make sure your firmware version is V 4.0.0 or above.**
QIDISlicer is based on [PrusaSlicer](https://github.com/prusa3d/PrusaSlicer) by Prusa Research, which is from [Slic3r](https://github.com/Slic3r/Slic3r) by Alessandro Ranellucci and the RepRap community.
Thanks to PrusaSlicer, Bambulab and OrcaSlicer for their contributions to the 3D printing community.
See the [QIDI's homepage](https://qidi3d.com) for more information.
### Firmware
<details open>
<summary>Content Navigation</summary>
<ol>
<li>
<a href="#function-introduction">Function Introduction</a>
</li>
<li>
<a href="#wiki">Wiki</a>
</li>
<li>
<a href="#Supporting-QIDI-Link-App">Supporting QIDI Link App</a>
</li>
<li>
<a href="#report-issues-and-make-suggestions">Report Issues and Make Suggestions</a>
<ul>
<li><a href="#some-formatting-requirements">Some Formatting Requirements</a></li>
</ul>
</li>
<li>
<a href="#license">License</a>
</li>
</ol>
</details>
You can find the printer's firmware here:
----
[X-MAX 3](https://github.com/QIDITECH/QIDI_MAX3)
## Function Introduction
[X-Plus 3](https://github.com/QIDITECH/QIDI_PLUS3)
<p align="center">
<img src="/readmeRes/UI.png" alt="UI">
</p>
[X-smart 3](https://github.com/QIDITECH/QIDI_SMART3)
### Key features are:
### Report Issues and Make Suggestions
* **Slicer:** Fast and stable 3D model slicer
* **Printer:** Perfect compatibility with all high-speed 3D printers of QIDI TECH
* **Filament:** Perfect compatibility with all filaments of QIDI TECH and some general filaments
* **LAN:** The printer can be directly connected through IP, convenient, safe and stable
* **Internet:** Remote connection, start printing anytime, anywhere
Please send your question in the form of video or pictures to us through the [After-Sales Service](https://qidi3d.com/pages/warranty-policy-after-sales-support), we will reply to your information within 12 hours.
### Other major features are:
Please try to contact us through [After-Sales Service](https://qidi3d.com/pages/warranty-policy-after-sales-support) and report problems or suggestions. On github, we cannot obtain your order information, operation records and other private intelligence, nor can we generate after-sales orders, send repair files, etc. Thank you for your understanding and cooperation.
* **Model:** A variety of model operations, move, scale, rotate, crop, color, repair, combine, split, and more
* **Parameter:** Rich parameter Settings, fine adjustment for a variety of complex models and application scenarios
* **Calibration:** Multiple calibration functions to adjust the best parameters according to the actual situation
### License
----
## wiki
The wiki below aims to provide a detailed explanation of the QIDISlicer settings, how to get the most out of them as
well as how to calibrate and setup your printer.
The wiki is work in progress so bear with us while we get it up and running!
**[Access the wiki here](https://wiki.qidi3d.com/en/software/QIDISlicier)**
----
## Supporting QIDI Link App
**[Access QIDI Link App Guide Here](https://wiki.qidi3d.com/en/app)**
The supporting QIDI Link App supports IOS and Android platforms. In the app, you can scan the code to connect to the printer, remotely monitor the printer's printing progress, control the printer's printing parameters, and perform operations such as feeding and returning materials.
<p align="center">
<img src="/readmeRes/qidilink.png" alt="Add filament option ——Seal">
</p>
----
## Report Issues and Make Suggestions
Please send your question in the form of video or pictures to us through
the [After-Sales Service](https://qidi3d.com/pages/warranty-policy-after-sales-support), we will reply to your
information within 12 hours.
Please try to contact us through [After-Sales Service](https://qidi3d.com/pages/warranty-policy-after-sales-support) and
report problems or suggestions. On github, we cannot obtain your order information, operation records and other private
intelligence, nor can we generate after-sales orders, send repair files, etc. Thank you for your understanding and
cooperation.
### Some formatting requirements
#### Issue Title:
Briefly describe the issue (e.g., `could not open file`)
#### Description:
Provide a detailed description of the issue.This will help our engineers quickly locate the problem and assist you in
resolving it
- **Issue Description**:
- A clear explanation of the problem.
- Compare the expected behavior with the actual behavior.
- **Steps to Reproduce**:
1. Step one
2. Step two
3. Step three
- Specific steps to reproduce the issue. Include a precise sequence of actions if possible.
- **Additional Information**:
- **Screenshots/Images**: Attach relevant screenshots or images that help in understanding the issue. Please add or
link to images here.
- **Environment Information**:
- Operating System Version
- Browser/Application Version
- Other relevant environment details
## License
QIDISlicer is licensed under the _GNU Affero General Public License, version 3_. QIDISlicer is based on PrusaSlicer by PrusaResearch.

View File

@@ -1,109 +0,0 @@
# Find the wxWidgets module based on the information provided by the Perl Alien::wxWidgets module.
# Check for the Perl & PerlLib modules
include(LibFindMacros)
libfind_package(AlienWx Perl)
libfind_package(AlienWx PerlLibs)
if (AlienWx_DEBUG)
message(STATUS " AlienWx_FIND_COMPONENTS=${AlienWx_FIND_COMPONENTS}")
endif()
# Execute an Alien::Wx module to find the relevant information regarding
# the wxWidgets used by the Perl interpreter.
# Perl specific stuff
set(AlienWx_TEMP_INCLUDE ${CMAKE_CURRENT_BINARY_DIR}/AlienWx_TEMP_INCLUDE.txt)
execute_process(
COMMAND ${PERL_EXECUTABLE} -e "
# Import Perl modules.
use strict;
use warnings;
use Text::ParseWords;
BEGIN {
# CMake sets the environment variables CC and CXX to the detected C compiler.
# There is an issue with the Perl ExtUtils::CBuilder, which does not handle whitespaces
# in the paths correctly on Windows, so we rather drop the CMake auto-detected paths.
delete \$ENV{CC};
delete \$ENV{CXX};
}
use Alien::wxWidgets;
use ExtUtils::CppGuess;
# Test for a Visual Studio compiler
my \$cpp_guess = ExtUtils::CppGuess->new;
my \$mswin = \$^O eq 'MSWin32';
my \$msvc = \$cpp_guess->is_msvc;
# List of wxWidgets components to be used.
my @components = split /;/, '${AlienWx_FIND_COMPONENTS}';
# Query the available data from Alien::wxWidgets.
my \$version = Alien::wxWidgets->version;
my \$config = Alien::wxWidgets->config;
my \$compiler = Alien::wxWidgets->compiler;
my \$linker = Alien::wxWidgets->linker;
my \$include_path = ' ' . Alien::wxWidgets->include_path;
my \$defines = ' ' . Alien::wxWidgets->defines;
my \$cflags = Alien::wxWidgets->c_flags;
my \$linkflags = Alien::wxWidgets->link_flags;
my \$libraries = ' ' . Alien::wxWidgets->libraries(@components);
my \$gui_toolkit = Alien::wxWidgets->config->{toolkit};
#my @libraries = Alien::wxWidgets->link_libraries(@components);
#my @implib = Alien::wxWidgets->import_libraries(@components);
#my @shrlib = Alien::wxWidgets->shared_libraries(@components);
#my @keys = Alien::wxWidgets->library_keys; # 'gl', 'adv', ...
#my \$library_path = Alien::wxWidgets->shared_library_path;
#my \$key = Alien::wxWidgets->key;
#my \$prefix = Alien::wxWidgets->prefix;
my \$filename = '${AlienWx_TEMP_INCLUDE}';
open(my $fh, '>', \$filename) or die \"Could not open file '\$filename' \$!\";
# Convert a space separated lists to CMake semicolon separated lists,
# escape the backslashes,
# export the resulting list to a temp file.
sub cmake_set_var {
my (\$varname, \$content) = @_;
# Remove line separators.
\$content =~ s/\\r|\\n//g;
# Escape the path separators.
\$content =~ s/\\\\/\\\\\\\\\\\\\\\\/g;
my @words = shellwords(\$content);
print \$fh \"set(AlienWx_\$varname \\\"\" . join(';', @words) . \"\\\")\\n\";
}
cmake_set_var('VERSION', \$version);
\$include_path =~ s/ -I/ /g;
cmake_set_var('INCLUDE_DIRS', \$include_path);
\$libraries =~ s/ -L/ -LIBPATH:/g if \$msvc;
cmake_set_var('LIBRARIES', \$libraries);
#cmake_set_var('LIBRARY_DIRS', );
#\$defines =~ s/ -D/ /g;
cmake_set_var('DEFINITIONS', \$defines);
#cmake_set_var('DEFINITIONS_DEBUG', );
cmake_set_var('CXX_FLAGS', \$cflags);
cmake_set_var('GUI_TOOLKIT', \$gui_toolkit);
close \$fh;
")
include(${AlienWx_TEMP_INCLUDE})
file(REMOVE ${AlienWx_TEMP_INCLUDE})
unset(AlienWx_TEMP_INCLUDE)
if (AlienWx_DEBUG)
message(STATUS " AlienWx_VERSION = ${AlienWx_VERSION}")
message(STATUS " AlienWx_INCLUDE_DIRS = ${AlienWx_INCLUDE_DIRS}")
message(STATUS " AlienWx_LIBRARIES = ${AlienWx_LIBRARIES}")
message(STATUS " AlienWx_LIBRARY_DIRS = ${AlienWx_LIBRARY_DIRS}")
message(STATUS " AlienWx_DEFINITIONS = ${AlienWx_DEFINITIONS}")
message(STATUS " AlienWx_DEFINITIONS_DEBUG = ${AlienWx_DEFINITIONS_DEBUG}")
message(STATUS " AlienWx_CXX_FLAGS = ${AlienWx_CXX_FLAGS}")
message(STATUS " AlienWx_GUI_TOOLKIT = ${AlienWx_GUI_TOOLKIT}")
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(AlienWx
REQUIRED_VARS AlienWx_INCLUDE_DIRS AlienWx_LIBRARIES
# HANDLE_COMPONENTS
VERSION_VAR AlienWx_VERSION)

View File

@@ -1,88 +0,0 @@
# Find the dependencies for linking with the Perl runtime library.
# Check for the Perl & PerlLib modules
include(LibFindMacros)
libfind_package(PerlEmbed Perl)
libfind_package(PerlEmbed PerlLibs)
# Execute an Alien::Wx module to find the relevant information regarding
# the wxWidgets used by the Perl interpreter.
# Perl specific stuff
set(PerlEmbed_TEMP_INCLUDE ${CMAKE_CURRENT_BINARY_DIR}/PerlEmbed_TEMP_INCLUDE.txt)
execute_process(
COMMAND ${PERL_EXECUTABLE} -MExtUtils::Embed -e "
# Import Perl modules.
use strict;
use warnings;
use Config;
use Text::ParseWords;
use ExtUtils::CppGuess;
# Test for a Visual Studio compiler
my \$cpp_guess = ExtUtils::CppGuess->new;
my \$mswin = \$^O eq 'MSWin32';
my \$msvc = \$cpp_guess->is_msvc;
# Query the available data from Alien::wxWidgets.
my \$ccflags;
my \$ldflags;
{ local *STDOUT; open STDOUT, '>', \\\$ccflags; ccflags; }
{ local *STDOUT; open STDOUT, '>', \\\$ldflags; ldopts; }
\$ccflags = ' ' . \$ccflags;
\$ldflags = ' ' . \$ldflags;
my \$filename = '${PerlEmbed_TEMP_INCLUDE}';
open(my $fh, '>', \$filename) or die \"Could not open file '\$filename' \$!\";
# Convert a space separated lists to CMake semicolon separated lists,
# escape the backslashes,
# export the resulting list to a temp file.
sub cmake_set_var {
my (\$varname, \$content) = @_;
# Remove line separators.
\$content =~ s/\\r|\\n//g;
# Escape the path separators.
\$content =~ s/\\\\/\\\\\\\\\\\\\\\\/g;
my @words = shellwords(\$content);
print \$fh \"set(PerlEmbed_\$varname \\\"\" . join(';', @words) . \"\\\")\\n\";
}
cmake_set_var('ARCHNAME', \$Config{archname});
cmake_set_var('CCFLAGS', \$ccflags);
\$ldflags =~ s/ -L/ -LIBPATH:/g if \$msvc;
cmake_set_var('LD', \$Config{ld});
cmake_set_var('LDFLAGS', \$ldflags);
cmake_set_var('CCCDLFLAGS', \$Config{cccdlflags});
cmake_set_var('LDDLFLAGS', \$Config{lddlflags});
cmake_set_var('DLEXT', \$Config{dlext});
close \$fh;
")
include(${PerlEmbed_TEMP_INCLUDE})
file(REMOVE ${PerlEmbed_TEMP_INCLUDE})
unset(PerlEmbed_TEMP_INCLUDE)
if (PerlEmbed_DEBUG)
# First show the configuration extracted by FindPerl & FindPerlLibs:
message(STATUS " PERL_INCLUDE_PATH = ${PERL_INCLUDE_PATH}")
message(STATUS " PERL_LIBRARY = ${PERL_LIBRARY}")
message(STATUS " PERL_EXECUTABLE = ${PERL_EXECUTABLE}")
message(STATUS " PERL_SITESEARCH = ${PERL_SITESEARCH}")
message(STATUS " PERL_SITELIB = ${PERL_SITELIB}")
message(STATUS " PERL_VENDORARCH = ${PERL_VENDORARCH}")
message(STATUS " PERL_VENDORLIB = ${PERL_VENDORLIB}")
message(STATUS " PERL_ARCHLIB = ${PERL_ARCHLIB}")
message(STATUS " PERL_PRIVLIB = ${PERL_PRIVLIB}")
message(STATUS " PERL_EXTRA_C_FLAGS = ${PERL_EXTRA_C_FLAGS}")
# Second show the configuration extracted by this module (FindPerlEmbed):
message(STATUS " PerlEmbed_ARCHNAME = ${PerlEmbed_ARCHNAME}")
message(STATUS " PerlEmbed_CCFLAGS = ${PerlEmbed_CCFLAGS}")
message(STATUS " PerlEmbed_CCCDLFLAGS = ${PerlEmbed_CCCDLFLAGS}")
message(STATUS " LD = ${PerlEmbed_LD}")
message(STATUS " PerlEmbed_LDFLAGS = ${PerlEmbed_LDFLAGS}")
message(STATUS " PerlEmbed_LDDLFLAGS = ${PerlEmbed_LDDLFLAGS}")
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(PerlEmbed
REQUIRED_VARS PerlEmbed_CCFLAGS PerlEmbed_LDFLAGS
VERSION_VAR PERL_VERSION)

View File

@@ -1,9 +1,8 @@
set(LibBGCode_SOURCE_DIR "" CACHE PATH "Optionally specify local LibBGCode source directory")
set(_source_dir_line
URL https://github.com/prusa3d/libbgcode/archive/bc390aab4427589a6402b4c7f65cf4d0a8f987ec.zip
URL_HASH SHA256=0c86cb67232089728233014f937e2a07d133a61e31dd8811a9c905e563a49f24
)
URL https://github.com/prusa3d/libbgcode/archive/6f43cb004ef3d3bda37dde49f6235e24d2717629.zip
URL_HASH SHA256=eb5198caecb6a693a294af6a56c37b0adb1eb159a34a9c3116970b80659ee9f9)
if (LibBGCode_SOURCE_DIR)
set(_source_dir_line "SOURCE_DIR;${LibBGCode_SOURCE_DIR};BUILD_ALWAYS;ON")

View File

@@ -15,7 +15,7 @@ endif ()
add_cmake_project(OpenVDB
# 8.2 patched
URL https://github.com/tamasmeszaros/openvdb/archive/a68fd58d0e2b85f01adeb8b13d7555183ab10aa5.zip
URL https://github.com/prusa3d/openvdb/archive/a68fd58d0e2b85f01adeb8b13d7555183ab10aa5.zip
URL_HASH SHA256=f353e7b99bd0cbfc27ac9082de51acf32a8bc0b3e21ff9661ecca6f205ec1d81
CMAKE_ARGS
-DCMAKE_POSITION_INDEPENDENT_CODE=ON

View File

@@ -1,51 +0,0 @@
# This package loads all the non-GUI Slic3r perl packages.
package Slic3r;
# Copyright holder: Alessandro Ranellucci
# This application is licensed under the GNU Affero General Public License, version 3
use strict;
use warnings;
use Config;
require v5.10;
our $VERSION = VERSION();
our $BUILD = BUILD();
our $FORK_NAME = FORK_NAME();
our $debug = 0;
sub debugf {
printf @_ if $debug;
}
our $loglevel = 0;
BEGIN {
$debug = 1 if (defined($ENV{'SLIC3R_DEBUGOUT'}) && $ENV{'SLIC3R_DEBUGOUT'} == 1);
print "Debugging output enabled\n" if $debug;
}
use FindBin;
use Moo 1.003001;
use Slic3r::XS; # import all symbols (constants etc.) before they get parsed
use Slic3r::Config;
use Slic3r::GCode::Reader;
use Slic3r::Line;
use Slic3r::Model;
use Slic3r::Point;
use Slic3r::Polygon;
use Slic3r::Polyline;
our $build = eval "use Slic3r::Build; 1";
# Scaling between the float and integer coordinates.
# Floats are in mm.
use constant SCALING_FACTOR => 0.000001;
# Set the logging level at the Slic3r XS module.
$Slic3r::loglevel = (defined($ENV{'SLIC3R_LOGLEVEL'}) && $ENV{'SLIC3R_LOGLEVEL'} =~ /^[1-9]/) ? $ENV{'SLIC3R_LOGLEVEL'} : 0;
set_logging_level($Slic3r::loglevel);
1;

View File

@@ -1,32 +0,0 @@
# Extends C++ class Slic3r::DynamicPrintConfig
# This perl class does not keep any perl class variables,
# all the storage is handled by the underlying C++ code.
package Slic3r::Config;
use strict;
use warnings;
use utf8;
use List::Util qw(first max);
# C++ Slic3r::PrintConfigDef exported as a Perl hash of hashes.
# The C++ counterpart is a constant singleton.
our $Options = print_config_def();
# Generate accessors.
{
no strict 'refs';
for my $opt_key (keys %$Options) {
*{$opt_key} = sub {
#print "Slic3r::Config::accessor $opt_key\n";
$_[0]->get($opt_key)
};
}
}
package Slic3r::Config::Static;
use parent 'Slic3r::Config';
sub Slic3r::Config::GCode::new { Slic3r::Config::Static::new_GCodeConfig }
sub Slic3r::Config::Print::new { Slic3r::Config::Static::new_PrintConfig }
1;

View File

@@ -1,90 +0,0 @@
# Helper module to parse and interpret a G-code file,
# invoking a callback for each move extracted from the G-code.
# Currently used by the automatic tests only.
package Slic3r::GCode::Reader;
use Moo;
has 'config' => (is => 'ro', default => sub { Slic3r::Config::GCode->new });
has 'X' => (is => 'rw', default => sub {0});
has 'Y' => (is => 'rw', default => sub {0});
has 'Z' => (is => 'rw', default => sub {0});
has 'E' => (is => 'rw', default => sub {0});
has 'F' => (is => 'rw', default => sub {0});
has '_extrusion_axis' => (is => 'rw', default => sub {"E"});
our $Verbose = 0;
my @AXES = qw(X Y Z E);
sub apply_print_config {
my ($self, $print_config) = @_;
$self->config->apply_static($print_config);
$self->_extrusion_axis($self->config->get_extrusion_axis);
}
sub clone {
my $self = shift;
return (ref $self)->new(
map { $_ => $self->$_ } (@AXES, 'F', '_extrusion_axis', 'config'),
);
}
sub parse {
my $self = shift;
my ($gcode, $cb) = @_;
foreach my $raw_line (split /\R+/, $gcode) {
print "$raw_line\n" if $Verbose || $ENV{SLIC3R_TESTS_GCODE};
my $line = $raw_line;
$line =~ s/\s*;(.*)//; # strip comment
my %info = (comment => $1, raw => $raw_line);
# parse command
my ($command, @args) = split /\s+/, $line;
$command //= '';
my %args = map { /([A-Z])(.*)/; ($1 => $2) } @args;
# convert extrusion axis
if (exists $args{ $self->_extrusion_axis }) {
$args{E} = $args{ $self->_extrusion_axis };
}
# check motion
if ($command =~ /^G[01]$/) {
foreach my $axis (@AXES) {
if (exists $args{$axis}) {
$self->$axis(0) if $axis eq 'E' && $self->config->use_relative_e_distances;
$info{"dist_$axis"} = $args{$axis} - $self->$axis;
$info{"new_$axis"} = $args{$axis};
} else {
$info{"dist_$axis"} = 0;
$info{"new_$axis"} = $self->$axis;
}
}
$info{dist_XY} = sqrt(($info{dist_X}**2) + ($info{dist_Y}**2));
if (exists $args{E}) {
if ($info{dist_E} > 0) {
$info{extruding} = 1;
} elsif ($info{dist_E} < 0) {
$info{retracting} = 1
}
} else {
$info{travel} = 1;
}
}
# run callback
$cb->($self, $command, \%args, \%info);
# update coordinates
if ($command =~ /^(?:G[01]|G92)$/) {
for my $axis (@AXES, 'F') {
$self->$axis($args{$axis}) if exists $args{$axis};
}
}
# TODO: update temperatures
}
}
1;

View File

@@ -1,36 +0,0 @@
package Slic3r::Geometry;
use strict;
use warnings;
require Exporter;
our @ISA = qw(Exporter);
# Exported by this module. The last section starting with convex_hull is exported by Geometry.xsp
our @EXPORT_OK = qw(
PI epsilon
scale
unscale
scaled_epsilon
X Y Z
convex_hull
deg2rad
rad2deg
);
use constant PI => 4 * atan2(1, 1);
use constant A => 0;
use constant B => 1;
use constant X1 => 0;
use constant Y1 => 1;
use constant X2 => 2;
use constant Y2 => 3;
sub epsilon () { 1E-4 }
sub scaled_epsilon () { epsilon / &Slic3r::SCALING_FACTOR }
sub scale ($) { $_[0] / &Slic3r::SCALING_FACTOR }
sub unscale ($) { $_[0] * &Slic3r::SCALING_FACTOR }
1;

View File

@@ -1,8 +0,0 @@
package Slic3r::Line;
use strict;
use warnings;
# a line is a two-points line
use parent 'Slic3r::Polyline';
1;

View File

@@ -1,136 +0,0 @@
# extends C++ class Slic3r::Model
package Slic3r::Model;
use List::Util qw(first max any);
sub merge {
my $class = shift;
my @models = @_;
my $new_model = ref($class)
? $class
: $class->new;
$new_model->add_object($_) for map @{$_->objects}, @models;
return $new_model;
}
sub add_object {
my $self = shift;
if (@_ == 1) {
# we have a Model::Object
my ($object) = @_;
return $self->_add_object_clone($object);
} else {
my (%args) = @_;
my $new_object = $self->_add_object;
$new_object->set_name($args{name})
if defined $args{name};
$new_object->set_input_file($args{input_file})
if defined $args{input_file};
$new_object->config->apply($args{config})
if defined $args{config};
$new_object->set_layer_height_ranges($args{layer_height_ranges})
if defined $args{layer_height_ranges};
$new_object->set_origin_translation($args{origin_translation})
if defined $args{origin_translation};
return $new_object;
}
}
sub set_material {
my $self = shift;
my ($material_id, $attributes) = @_;
my $material = $self->add_material($material_id);
$material->apply($attributes // {});
return $material;
}
# Extends C++ class Slic3r::ModelMaterial
package Slic3r::Model::Material;
sub apply {
my ($self, $attributes) = @_;
$self->set_attribute($_, $attributes{$_}) for keys %$attributes;
}
# Extends C++ class Slic3r::ModelObject
package Slic3r::Model::Object;
use List::Util qw(first sum);
sub add_volume {
my $self = shift;
my $new_volume;
if (@_ == 1) {
# we have a Model::Volume
my ($volume) = @_;
$new_volume = $self->_add_volume_clone($volume);
if ($volume->material_id ne '') {
# merge material attributes and config (should we rename materials in case of duplicates?)
if (my $material = $volume->object->model->get_material($volume->material_id)) {
my %attributes = %{ $material->attributes };
if ($self->model->has_material($volume->material_id)) {
%attributes = (%attributes, %{ $self->model->get_material($volume->material_id)->attributes })
}
my $new_material = $self->model->set_material($volume->material_id, {%attributes});
$new_material->config->apply($material->config);
}
}
} else {
my %args = @_;
$new_volume = $self->_add_volume($args{mesh});
$new_volume->set_name($args{name})
if defined $args{name};
$new_volume->set_material_id($args{material_id})
if defined $args{material_id};
$new_volume->set_modifier($args{modifier})
if defined $args{modifier};
$new_volume->config->apply($args{config})
if defined $args{config};
}
if ($new_volume->material_id ne '' && !defined $self->model->get_material($new_volume->material_id)) {
# TODO: this should be a trigger on Volume::material_id
$self->model->set_material($new_volume->material_id);
}
$self->invalidate_bounding_box;
return $new_volume;
}
sub add_instance {
my $self = shift;
if (@_ == 1) {
# we have a Model::Instance
my ($instance) = @_;
return $self->_add_instance_clone($instance);
} else {
my (%args) = @_;
my $new_instance = $self->_add_instance;
$new_instance->set_rotations($args{rotation})
if defined $args{rotation};
$new_instance->set_scaling_factors($args{scaling_factor})
if defined $args{scaling_factor};
$new_instance->set_offset($args{offset})
if defined $args{offset};
return $new_instance;
}
}
1;

View File

@@ -1,28 +0,0 @@
package Slic3r::Point;
use strict;
use warnings;
sub new_scale {
my $class = shift;
return $class->new(map Slic3r::Geometry::scale($_), @_);
}
package Slic3r::Pointf;
use strict;
use warnings;
sub new_unscale {
my $class = shift;
return $class->new(map Slic3r::Geometry::unscale($_), @_);
}
package Slic3r::Pointf3;
use strict;
use warnings;
sub new_unscale {
my $class = shift;
return $class->new(map Slic3r::Geometry::unscale($_), @_);
}
1;

View File

@@ -1,8 +0,0 @@
package Slic3r::Polygon;
use strict;
use warnings;
# a polygon is a closed polyline.
use parent 'Slic3r::Polyline';
1;

View File

@@ -1,13 +0,0 @@
package Slic3r::Polyline;
use strict;
use warnings;
use Slic3r::Geometry qw(X Y);
sub new_scale {
my $class = shift;
my @points = map { ref($_) eq 'Slic3r::Point' ? $_->pp : $_ } @_;
return $class->new(map [ Slic3r::Geometry::scale($_->[X]), Slic3r::Geometry::scale($_->[Y]) ], @points);
}
1;

File diff suppressed because one or more lines are too long

BIN
readmeRes/UI.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 168 KiB

BIN
readmeRes/qidilink.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 560 KiB

BIN
resources/icon.icns Normal file

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 114 KiB

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.9 KiB

After

Width:  |  Height:  |  Size: 7.1 KiB

View File

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

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 114 KiB

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.9 KiB

After

Width:  |  Height:  |  Size: 7.1 KiB

View File

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

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

View File

Before

Width:  |  Height:  |  Size: 437 B

After

Width:  |  Height:  |  Size: 437 B

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="24px" height="24px" viewBox="0 0 24 24" enable-background="new 0 0 24 24" xml:space="preserve">
<path fill="#ADADAF" d="M11,11V5h2v6h6v2h-6v6h-2v-6H5v-2H11z"/>
</svg>

After

Width:  |  Height:  |  Size: 437 B

View File

@@ -0,0 +1,17 @@
<?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="16px" height="16px" viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
<path fill="#4479FB" d="M14.6,13.1l-1.4-7.3c-0.1-0.6-0.7-1.1-1.4-1.1H9.5C9.9,4.3,10,3.9,10,3.4c0-1.1-0.9-2-2-2s-2,0.9-2,2
c0,0.5,0.2,1,0.5,1.3H4.1c-0.7,0-1.2,0.5-1.4,1.1l-1.4,7.3c-0.2,0.8,0.5,1.6,1.4,1.6h10.5C14.1,14.7,14.8,13.9,14.6,13.1z M8,2.3
c0.6,0,1,0.5,1,1s-0.5,1-1,1s-1-0.5-1-1S7.4,2.3,8,2.3z M13.6,13.5c0,0-0.1,0.1-0.3,0.1H2.7c-0.2,0-0.3-0.1-0.3-0.1
c0-0.1-0.1-0.1-0.1-0.2L3.8,6c0-0.2,0.2-0.3,0.4-0.3h7.7c0.2,0,0.4,0.1,0.4,0.3l1.4,7.3C13.7,13.4,13.6,13.5,13.6,13.5z"/>
<g>
<path fill="#4479FB" d="M6.9,12c-0.2-0.4-0.4-0.7-0.6-0.9c-0.2-0.2-0.4-0.4-0.6-0.6H5.4v1.6H4.5V8.2h0.9v1.6h0.2l1.1-1.6h1
l-1.3,1.9c0.3,0.3,0.6,0.6,0.8,0.8c0.2,0.3,0.5,0.7,0.7,1.1H6.9z"/>
<path fill="#4479FB" d="M11.5,11.9C11.3,12,11.1,12,11,12.1c-0.2,0-0.4,0.1-0.7,0.1c-0.4,0-0.8-0.1-1.1-0.2
c-0.3-0.2-0.6-0.4-0.8-0.7c-0.2-0.3-0.3-0.6-0.3-1c0-0.4,0.1-0.8,0.3-1.1c0.2-0.3,0.4-0.6,0.8-0.7c0.3-0.2,0.7-0.3,1.1-0.3
c0.2,0,0.4,0,0.6,0.1c0.2,0,0.4,0.1,0.5,0.1V9c-0.4-0.1-0.7-0.2-1-0.2c-0.4,0-0.7,0.1-1,0.3C9.1,9.4,9,9.7,9,10.2
c0,0.3,0.1,0.5,0.2,0.7c0.1,0.2,0.3,0.3,0.5,0.4c0.2,0.1,0.4,0.1,0.7,0.1c0.2,0,0.3,0,0.4,0v-0.9h-0.4V9.8h1.2V11.9z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

Before

Width:  |  Height:  |  Size: 417 B

After

Width:  |  Height:  |  Size: 417 B

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="24px" height="24px" viewBox="0 0 24 24" enable-background="new 0 0 24 24" xml:space="preserve">
<path fill="#ADADAF" d="M5,13v-2h14v2H5z"/>
</svg>

After

Width:  |  Height:  |  Size: 417 B

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="24px" height="24px" viewBox="0 0 24 24" enable-background="new 0 0 24 24" xml:space="preserve">
<path fill="#4479fb" d="M16.8,3l-2,2H5v14h14V9.2l2-2V20c0,0.6-0.4,1-1,1H4c-0.6,0-1-0.4-1-1V4c0-0.6,0.4-1,1-1H16.8z M20.5,2.1
l1.4,1.4l-9.2,9.2l-1.4,0l0-1.4L20.5,2.1z"/>
</svg>

After

Width:  |  Height:  |  Size: 543 B

View File

Before

Width:  |  Height:  |  Size: 543 B

After

Width:  |  Height:  |  Size: 543 B

View File

@@ -0,0 +1,155 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="10px" height="10px" viewBox="0 0 10 10" enable-background="new 0 0 10 10" xml:space="preserve">
<defs>
<filter id="Adobe_OpacityMaskFilter" filterUnits="userSpaceOnUse" x="0.7" y="0.6" width="3.7" height="3.7">
<feColorMatrix type="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0"/>
</filter>
</defs>
<mask maskUnits="userSpaceOnUse" x="0.7" y="0.6" width="3.7" height="3.7" id="mask1_7_73_2_">
<path id="path3_2_" fill="#FFFFFF" filter="url(#Adobe_OpacityMaskFilter)" d="M10,0.1H0v10h10V0.1z"/>
</mask>
<g id="g5" transform="translate(-0.13363557,-0.18774744)" mask="url(#mask1_7_73_2_)">
<path id="path4" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M2.7,4.3l1.6-1.6L2.7,1L1,2.7L2.7,4.3z"/>
<path id="path5" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M2.7,3.5l0.8-0.8L2.7,1.8L1.8,2.7L2.7,3.5z"/>
<path id="path31" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M2.7,4.3l1.6-1.6L2.7,1L1,2.7L2.7,4.3z"/>
<path id="path32" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M2.7,3.5l0.8-0.8L2.7,1.8L1.8,2.7L2.7,3.5z"/>
<path id="path50" fill="none" stroke="#999999" stroke-width="0.3" d="M2.7,4.3l1.6-1.6L2.7,1L1,2.7L2.7,4.3z"/>
<path id="path51" fill="none" stroke="#999999" stroke-width="0.3" d="M2.7,3.5l0.8-0.8L2.7,1.8L1.8,2.7L2.7,3.5z"/>
</g>
<defs>
<filter id="Adobe_OpacityMaskFilter_1_" filterUnits="userSpaceOnUse" x="4" y="0.6" width="3.7" height="3.7">
<feColorMatrix type="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0"/>
</filter>
</defs>
<mask maskUnits="userSpaceOnUse" x="4" y="0.6" width="3.7" height="3.7" id="mask2_7_73_2_">
<path id="path6_2_" fill="#FFFFFF" filter="url(#Adobe_OpacityMaskFilter_1_)" d="M10,0.1H0v10h10V0.1z"/>
</mask>
<g id="g8" transform="translate(-0.13363557,-0.18774744)" mask="url(#mask2_7_73_2_)">
<path id="path7" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M6,4.3l1.6-1.6L6,1L4.4,2.7L6,4.3z"/>
<path id="path8" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M6,3.5l0.8-0.8L6,1.8L5.1,2.7L6,3.5z"/>
<path id="path33" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M6,4.3l1.6-1.6L6,1L4.4,2.7L6,4.3z"/>
<path id="path34" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M6,3.5l0.8-0.8L6,1.8L5.1,2.7L6,3.5z"/>
<path id="path52" fill="none" stroke="#999999" stroke-width="0.3" d="M6,4.3l1.6-1.6L6,1L4.4,2.7L6,4.3z"/>
<path id="path53" fill="none" stroke="#999999" stroke-width="0.3" d="M6,3.5l0.8-0.8L6,1.8L5.1,2.7L6,3.5z"/>
</g>
<defs>
<filter id="Adobe_OpacityMaskFilter_2_" filterUnits="userSpaceOnUse" x="7.3" y="0.7" width="2.1" height="3.5">
<feColorMatrix type="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0"/>
</filter>
</defs>
<mask maskUnits="userSpaceOnUse" x="7.3" y="0.7" width="2.1" height="3.5" id="mask3_7_73_2_">
<path id="path9_2_" fill="#FFFFFF" filter="url(#Adobe_OpacityMaskFilter_2_)" d="M10,0.1H0v10h10V0.1z"/>
</mask>
<g id="g11" transform="translate(-0.13363557,-0.18774744)" mask="url(#mask3_7_73_2_)">
<path id="path10" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M9.2,4.2L7.6,2.6l1.6-1.7"/>
<path id="path11" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M9.2,3.4L8.4,2.6l0.8-0.8"/>
<path id="path35" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M9.2,4.2L7.6,2.6l1.6-1.7"/>
<path id="path36" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M9.2,3.4L8.4,2.6l0.8-0.8"/>
<path id="path54" fill="none" stroke="#999999" stroke-width="0.3" d="M9.2,4.2L7.6,2.6l1.6-1.7"/>
<path id="path55" fill="none" stroke="#999999" stroke-width="0.3" d="M9.5,3.7l-1-1l1-1"/>
</g>
<defs>
<filter id="Adobe_OpacityMaskFilter_3_" filterUnits="userSpaceOnUse" x="0.7" y="4" width="3.7" height="3.7">
<feColorMatrix type="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0"/>
</filter>
</defs>
<mask maskUnits="userSpaceOnUse" x="0.7" y="4" width="3.7" height="3.7" id="mask4_7_73_2_">
<path id="path12_2_" fill="#FFFFFF" filter="url(#Adobe_OpacityMaskFilter_3_)" d="M10,0.1H0v10h10V0.1z"/>
</mask>
<g id="g14" transform="translate(-0.13363557,-0.18774744)" mask="url(#mask4_7_73_2_)">
<path id="path13" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M2.7,7.6L4.3,6L2.7,4.4L1.1,6L2.7,7.6z"/>
<path id="path14" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M2.7,6.9L3.5,6L2.7,5.2L1.8,6L2.7,6.9z"/>
<path id="path37" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M2.7,7.6L4.3,6L2.7,4.4L1.1,6L2.7,7.6z"/>
<path id="path38" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M2.7,6.9L3.5,6L2.7,5.2L1.8,6L2.7,6.9z"/>
<path id="path56" fill="none" stroke="#999999" stroke-width="0.3" d="M2.7,7.6L4.3,6L2.7,4.4L1.1,6L2.7,7.6z"/>
<path id="path57" fill="none" stroke="#999999" stroke-width="0.3" d="M2.7,6.9L3.5,6L2.7,5.2L1.8,6L2.7,6.9z"/>
</g>
<defs>
<filter id="Adobe_OpacityMaskFilter_4_" filterUnits="userSpaceOnUse" x="4" y="4" width="3.7" height="3.7">
<feColorMatrix type="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0"/>
</filter>
</defs>
<mask maskUnits="userSpaceOnUse" x="4" y="4" width="3.7" height="3.7" id="mask5_7_73_2_">
<path id="path15_2_" fill="#FFFFFF" filter="url(#Adobe_OpacityMaskFilter_4_)" d="M10,0.1H0v10h10V0.1z"/>
</mask>
<g id="g17" transform="translate(-0.13363557,-0.18774744)" mask="url(#mask5_7_73_2_)">
<path id="path16" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M6,7.6L7.6,6L6,4.4L4.4,6L6,7.6z"/>
<path id="path17" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M6,6.9L6.9,6L6,5.2L5.2,6L6,6.9z"/>
<path id="path39" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M6,7.6L7.6,6L6,4.4L4.4,6L6,7.6z"/>
<path id="path40" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M6,6.9L6.9,6L6,5.2L5.2,6L6,6.9z"/>
<path id="path58" fill="none" stroke="#999999" stroke-width="0.3" d="M6,7.6L7.6,6L6,4.4L4.4,6L6,7.6z"/>
<path id="path59" fill="none" stroke="#999999" stroke-width="0.3" d="M6,6.9L6.9,6L6,5.2L5.2,6L6,6.9z"/>
</g>
<defs>
<filter id="Adobe_OpacityMaskFilter_5_" filterUnits="userSpaceOnUse" x="7.3" y="4" width="2.1" height="3.5">
<feColorMatrix type="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0"/>
</filter>
</defs>
<mask maskUnits="userSpaceOnUse" x="7.3" y="4" width="2.1" height="3.5" id="mask6_7_73_2_">
<path id="path18_2_" fill="#FFFFFF" filter="url(#Adobe_OpacityMaskFilter_5_)" d="M10,0.1H0v10h10V0.1z"/>
</mask>
<g id="g20" transform="translate(-0.13363557,-0.18774744)" mask="url(#mask6_7_73_2_)">
<path id="path19" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M9.2,7.6L7.6,5.9l1.6-1.6"/>
<path id="path20" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M9.2,6.7L8.4,5.9l0.8-0.8"/>
<path id="path41" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M9.2,7.6L7.6,5.9l1.6-1.6"/>
<path id="path42" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M9.2,6.7L8.4,5.9l0.8-0.8"/>
<path id="path60" fill="none" stroke="#999999" stroke-width="0.3" d="M9.2,7.6L7.6,5.9l1.6-1.6"/>
<path id="path61" fill="none" stroke="#999999" stroke-width="0.3" d="M9.4,7l-1-1l1-1"/>
</g>
<defs>
<filter id="Adobe_OpacityMaskFilter_6_" filterUnits="userSpaceOnUse" x="0.7" y="7.2" width="3.6" height="2.2">
<feColorMatrix type="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0"/>
</filter>
</defs>
<mask maskUnits="userSpaceOnUse" x="0.7" y="7.2" width="3.6" height="2.2" id="mask7_7_73_2_">
<path id="path21_2_" fill="#FFFFFF" filter="url(#Adobe_OpacityMaskFilter_6_)" d="M10,0.1H0v10h10V0.1z"/>
</mask>
<g id="g23" transform="translate(-0.13363557,-0.18774744)" mask="url(#mask7_7_73_2_)">
<path id="path22" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M0.9,9.3l1.7-1.7l1.7,1.7"/>
<path id="path23" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M1.8,9.3l0.8-0.9l0.8,0.9"/>
<path id="path43" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M0.9,9.3l1.7-1.7l1.7,1.7"/>
<path id="path44" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M1.8,9.3l0.8-0.9l0.8,0.9"/>
<path id="path62" fill="none" stroke="#999999" stroke-width="0.3" d="M0.9,9.3l1.7-1.7l1.7,1.7"/>
<path id="path63" fill="none" stroke="#999999" stroke-width="0.3" d="M1.8,9.4l0.9-1l0.9,1.1"/>
</g>
<defs>
<filter id="Adobe_OpacityMaskFilter_7_" filterUnits="userSpaceOnUse" x="4.1" y="7.3" width="3.5" height="2">
<feColorMatrix type="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0"/>
</filter>
</defs>
<mask maskUnits="userSpaceOnUse" x="4.1" y="7.3" width="3.5" height="2" id="mask8_7_73_2_">
<path id="path24_2_" fill="#FFFFFF" filter="url(#Adobe_OpacityMaskFilter_7_)" d="M10,0.1H0v10h10V0.1z"/>
</mask>
<g id="g26" transform="translate(-0.06473357,-0.11884544)" mask="url(#mask8_7_73_2_)">
<path id="path25" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M4.3,9.3l1.6-1.7l1.7,1.7"/>
<path id="path26" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M5.1,9.3l0.8-0.9l0.8,0.9"/>
<path id="path45" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M4.3,9.3l1.6-1.7l1.7,1.7"/>
<path id="path46" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M5.1,9.3l0.8-0.9l0.8,0.9"/>
<path id="path64" fill="none" stroke="#999999" stroke-width="0.3" d="M4.3,9.3l1.6-1.7l1.7,1.7"/>
<path id="path65" fill="none" stroke="#999999" stroke-width="0.3" d="M5.1,9.3l0.8-0.9l0.8,0.9"/>
</g>
<defs>
<filter id="Adobe_OpacityMaskFilter_8_" filterUnits="userSpaceOnUse" x="7.3" y="7.3" width="2.1" height="2">
<feColorMatrix type="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0"/>
</filter>
</defs>
<mask maskUnits="userSpaceOnUse" x="7.3" y="7.3" width="2.1" height="2" id="mask9_7_73_2_">
<path id="path27_2_" fill="#FFFFFF" filter="url(#Adobe_OpacityMaskFilter_8_)" d="M10,0.1H0v10h10V0.1z"/>
</mask>
<g id="g29" transform="translate(-0.13363557,-0.18774744)" mask="url(#mask9_7_73_2_)">
<path id="path28" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M7.5,9.3l1.7-1.7"/>
<path id="path29" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M8.4,9.3l0.8-0.9"/>
<path id="path47" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M7.5,9.3l1.7-1.7"/>
<path id="path48" fill="none" stroke="#B5BFC2" stroke-width="0.3" d="M8.4,9.3l0.8-0.9"/>
<path id="path66" fill="none" stroke="#999999" stroke-width="0.3" d="M7.5,9.3l1.7-1.7"/>
<path id="path67" fill="none" stroke="#999999" stroke-width="0.3" d="M8.3,9.5l1.1-1.3"/>
</g>
<path id="path68" fill="none" stroke="#4479FB" stroke-width="0.478" d="M2.4,0.7l6.9,6.9"/>
<path id="path68-8" fill="none" stroke="#4479FB" stroke-width="0.4997" d="M0.7,2.2l6.9,7.1"/>
<path id="path69" fill="none" stroke="#4479FB" stroke-width="0.478" d="M0.7,5.6l3.6,3.7"/>
<path id="path70" fill="none" stroke="#4479FB" stroke-width="0.5048" d="M5.7,0.7l3.6,3.5"/>
<path id="rect1" fill="none" stroke="#4479FB" stroke-width="0.406" stroke-linejoin="round" stroke-miterlimit="3.9" d="M1.5,0.7h7
c0.5,0,0.9,0.4,0.9,0.9v6.9c0,0.5-0.4,0.9-0.9,0.9h-7C1,9.3,0.7,8.9,0.7,8.5V1.5C0.7,1.1,1,0.7,1.5,0.7z"/>
</svg>

After

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -0,0 +1,13 @@
<?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="16px" height="16px" viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
<path fill="#4479FB" d="M8.5,9.2L8.3,9.1c-0.2,0-0.4,0-0.5,0L7.5,9.2c-1.3,0.4-2.3,1.6-2.3,3v0.5h5.5v-0.5
C10.8,10.8,9.8,9.6,8.5,9.2z"/>
<path fill="#4479FB" d="M7.9,6.8l-2-1.4c0,0,0-0.1,0-0.1h4.2c0,0,0.1,0.1,0,0.1l-2,1.4C8,6.9,7.9,6.9,7.9,6.8z"/>
<path fill="#4479FB" d="M13.3,14h-0.4v-1.8c0-1.7-0.9-3.3-2.3-4.2c1.4-0.9,2.3-2.5,2.3-4.2V2h0.4C13.7,2,14,1.7,14,1.4
s-0.3-0.7-0.6-0.7H2.7C2.3,0.7,2,1,2,1.4S2.3,2,2.7,2h0.4v1.8c0,1.7,0.9,3.3,2.3,4.2c-1.4,0.9-2.3,2.5-2.3,4.2V14H2.7
C2.3,14,2,14.3,2,14.6c0,0.4,0.3,0.7,0.6,0.7h10.7c0.4,0,0.6-0.3,0.6-0.7C14,14.3,13.7,14,13.3,14z M4.1,12.2c0-1.4,0.8-2.7,2-3.4
C6.3,8.6,6.5,8.3,6.5,8c0-0.3-0.2-0.6-0.4-0.7c-1.2-0.7-2-2-2-3.4V2h7.9v1.8c0,1.4-0.8,2.7-2,3.4C9.6,7.4,9.5,7.7,9.5,8
c0,0.3,0.2,0.6,0.4,0.7c1.2,0.7,2,2,2,3.4V14H4.1V12.2z"/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="24px" height="24px" viewBox="0 0 24 24" enable-background="new 0 0 24 24" xml:space="preserve">
<path fill="#4479fb" d="M5.5,4.4C7.2,2.9,9.5,2,12,2c5.5,0,10,4.5,10,10c0,2.1-0.7,4.1-1.8,5.7L17,12h3c0-4.4-3.6-8-8-8
C9.8,4,7.9,4.8,6.5,6.2L5.5,4.4z M18.5,19.6c-1.8,1.5-4,2.4-6.5,2.4C6.5,22,2,17.5,2,12c0-2.1,0.7-4.1,1.8-5.7L7,12H4
c0,4.4,3.6,8,8,8c2.2,0,4.1-0.8,5.5-2.2L18.5,19.6z"/>
</svg>

After

Width:  |  Height:  |  Size: 659 B

View File

Before

Width:  |  Height:  |  Size: 659 B

After

Width:  |  Height:  |  Size: 659 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 141 KiB

After

Width:  |  Height:  |  Size: 119 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 141 KiB

After

Width:  |  Height:  |  Size: 119 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -1,3 +1,13 @@
min_slic3r_version = 1.1.7
1.1.7 Optimize parameters
min_slic3r_version = 1.1.6
1.1.6 Optimize parameters
min_slic3r_version = 1.1.5
1.1.5 Optimize parameters
min_slic3r_version = 1.1.4
1.1.4 Optimize parameters
min_slic3r_version = 1.1.3
1.1.3 Optimize parameters
min_slic3r_version = 1.1.2
1.1.2 Optimize parameters
min_slic3r_version = 1.1.1

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 36 KiB

View File

@@ -0,0 +1,73 @@
<?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_x5F_复制" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
x="0px" y="0px" viewBox="0 0 864.6 864.6" enable-background="new 0 0 864.6 864.6" xml:space="preserve">
<rect x="0" y="843.1" fill="#FFFFFF" width="830.6" height="0.4"/>
<rect x="0.4" y="814.8" fill="#FFFFFF" width="829.5" height="0.4"/>
<rect x="0" y="785.9" fill="#FFFFFF" width="863.8" height="1.4"/>
<rect x="0" y="758.1" fill="#FFFFFF" width="863.8" height="0.4"/>
<rect x="0" y="729.7" fill="#FFFFFF" width="863.8" height="0.4"/>
<rect x="0" y="701.4" fill="#FFFFFF" width="863.8" height="0.4"/>
<rect x="0" y="673" fill="#FFFFFF" width="863.8" height="0.4"/>
<rect x="0" y="644.2" fill="#FFFFFF" width="863.8" height="1.4"/>
<rect x="0" y="616.3" fill="#FFFFFF" width="863.8" height="0.4"/>
<rect x="0" y="588" fill="#FFFFFF" width="863.8" height="0.4"/>
<rect x="0" y="559.6" fill="#FFFFFF" width="863.8" height="0.4"/>
<rect x="0" y="531.3" fill="#FFFFFF" width="863.8" height="0.4"/>
<rect x="0" y="502.4" fill="#FFFFFF" width="863.8" height="1.4"/>
<rect x="0.1" y="474.6" fill="#FFFFFF" width="863.7" height="0.4"/>
<rect x="0" y="446.3" fill="#FFFFFF" width="863.8" height="0.4"/>
<rect x="0.1" y="417.9" fill="#FFFFFF" width="863.7" height="0.4"/>
<rect x="0" y="389.6" fill="#FFFFFF" width="863.8" height="0.4"/>
<rect x="0" y="360.7" fill="#FFFFFF" width="863.8" height="1.4"/>
<rect x="0" y="332.9" fill="#FFFFFF" width="863.8" height="0.4"/>
<rect x="0" y="304.5" fill="#FFFFFF" width="863.8" height="0.4"/>
<rect x="0" y="276.2" fill="#FFFFFF" width="863.8" height="0.4"/>
<rect x="0" y="247.8" fill="#FFFFFF" width="863.8" height="0.4"/>
<rect x="0" y="219" fill="#FFFFFF" width="863.8" height="1.4"/>
<rect x="0" y="191.1" fill="#FFFFFF" width="863.8" height="0.4"/>
<rect x="0" y="162.8" fill="#FFFFFF" width="863.8" height="0.4"/>
<rect x="0" y="134.4" fill="#FFFFFF" width="863.8" height="0.4"/>
<rect x="0" y="106.1" fill="#FFFFFF" width="863.8" height="0.4"/>
<rect x="0" y="77.3" fill="#FFFFFF" width="863.8" height="1.4"/>
<rect y="863.2" fill="#FFFFFF" width="830.6" height="1.4"/>
<rect x="100.6" fill="#FFFFFF" width="764" height="1.4"/>
<rect y="8.5" fill="#FFFFFF" width="100.6" height="1.4"/>
<rect x="829.2" y="806.5" fill="#FFFFFF" width="35.4" height="1.4"/>
<rect x="829.2" y="807.9" fill="#FFFFFF" width="1.4" height="56.7"/>
<rect x="99.2" y="0" fill="#FFFFFF" width="1.4" height="9.2"/>
<rect x="0" y="8.9" fill="#FFFFFF" width="1.4" height="855.7"/>
<rect x="863.2" fill="#FFFFFF" width="1.4" height="807.2"/>
<rect x="0" y="49.4" fill="#FFFFFF" width="863.8" height="0.4"/>
<rect x="0" y="21.1" fill="#FFFFFF" width="864.6" height="0.4"/>
<rect x="21.1" y="9.6" fill="#FFFFFF" width="0.4" height="855"/>
<rect x="49.4" y="9.6" fill="#FFFFFF" width="0.4" height="855"/>
<rect x="77.3" y="9.6" fill="#FFFFFF" width="1.4" height="855"/>
<rect x="106.1" y="0.7" fill="#FFFFFF" width="0.4" height="863.9"/>
<rect x="134.4" y="0.7" fill="#FFFFFF" width="0.4" height="863.9"/>
<rect x="162.8" y="0" fill="#FFFFFF" width="0.4" height="864.6"/>
<rect x="191.1" y="0" fill="#FFFFFF" width="0.4" height="864.6"/>
<rect x="219" y="0" fill="#FFFFFF" width="1.4" height="864.6"/>
<rect x="247.8" y="0" fill="#FFFFFF" width="0.4" height="864.6"/>
<rect x="276.2" y="0" fill="#FFFFFF" width="0.4" height="864.6"/>
<rect x="304.5" y="0" fill="#FFFFFF" width="0.4" height="864.6"/>
<rect x="332.9" y="0" fill="#FFFFFF" width="0.4" height="864.6"/>
<rect x="360.7" y="0" fill="#FFFFFF" width="1.4" height="864.6"/>
<rect x="389.6" y="0" fill="#FFFFFF" width="0.4" height="864.6"/>
<rect x="417.9" y="0" fill="#FFFFFF" width="0.4" height="864.6"/>
<rect x="446.3" y="0" fill="#FFFFFF" width="0.4" height="864.6"/>
<rect x="474.6" y="0" fill="#FFFFFF" width="0.4" height="864.6"/>
<rect x="502.4" y="0" fill="#FFFFFF" width="1.4" height="864.6"/>
<rect x="531.3" y="0" fill="#FFFFFF" width="0.4" height="864.6"/>
<rect x="559.6" y="0" fill="#FFFFFF" width="0.4" height="864.6"/>
<rect x="588" y="0" fill="#FFFFFF" width="0.4" height="864.6"/>
<rect x="616.3" y="0" fill="#FFFFFF" width="0.4" height="864.6"/>
<rect x="644.2" y="0" fill="#FFFFFF" width="1.4" height="864.6"/>
<rect x="673" y="0" fill="#FFFFFF" width="0.4" height="864.6"/>
<rect x="701.4" y="0" fill="#FFFFFF" width="0.4" height="864.6"/>
<rect x="729.7" y="0" fill="#FFFFFF" width="0.4" height="864.6"/>
<rect x="758.1" y="0" fill="#FFFFFF" width="0.4" height="864.6"/>
<rect x="785.9" y="0" fill="#FFFFFF" width="1.4" height="864.6"/>
<rect x="814.8" y="0" fill="#FFFFFF" width="0.4" height="864.6"/>
<rect x="843.1" y="0" fill="#FFFFFF" width="0.4" height="807.2"/>
</svg>

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

View File

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

View File

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

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 502 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@@ -61,6 +61,10 @@
<div class="MenuBtnIcon"><img src="img/MenuBtnIcon.svg"/></div>
<div class="trans" tid="t18"></div>
</li>
<li menu="QIDILink" class="MenuBtn" onClick="GotoMenu('QIDILink')">
<div class="MenuBtnIcon"><img src="img/MenuBtnIcon.svg"/></div>
<div>QIDI Link</div>
</li>
<li menu="ModelDownload" class="MenuBtn" onClick="GotoMenu('ModelDownload')">
<div class="MenuBtnIcon"><img src="img/MenuBtnIcon.svg"/></div>
<div class="trans" tid="t13"></div>
@@ -97,6 +101,10 @@
<i class="fa fa-caret-right"></i>
</label>
<ol>
<li menu="X-Plus 4" class="MenuBtn" onClick="GotoMenu('X-Plus 4')">
<div class="MenuBtnIcon"><img src="img/MenuBtnIcon.svg"/></div>
<div>X-Plus 4</div>
</li>
<li menu="Q1 Pro" class="MenuBtn" onClick="GotoMenu('Q1 Pro')">
<div class="MenuBtnIcon"><img src="img/MenuBtnIcon.svg"/></div>
<div>Q1 Pro</div>
@@ -170,6 +178,10 @@
<div class="AutozoomImage"><img src="img/ExcludeObjects.gif"/></div>
<div class="ThumbnailTitle trans" tid="t18"></div>
</div>
<div class="Thumbnail" onClick="GotoMenu('QIDILink')">
<div class="AutozoomImage"><img src="img/QIDILink.png"/></div>
<div class="ThumbnailTitle">QIDI Link</div>
</div>
<div class="Thumbnail" onClick="GotoMenu('ModelDownload')">
<div class="AutozoomImage"><img src="img/DownloadModel.png"/></div>
<div class="ThumbnailTitle trans" tid="t13"></div>
@@ -244,6 +256,11 @@
<div class="AutozoomImage"><img src="img/ExcludeObjects.gif"/></div>
</div>
<div class="IntroduceBoard" board="QIDILink">
<div class="IntroduceTitle">QIDI Link</div>
<div class="AutozoomImage"><img src="img/QIDILink.png"/></div>
</div>
<div class="IntroduceBoard" board="ModelDownload">
<div class="IntroduceTitle trans" tid="t13"></div>
<div class="IntroduceTextBold trans" tid="l1"></div>
@@ -314,10 +331,16 @@
<div class="IntroduceText trans" tid="l46"></div>
</div>
<div class="IntroduceBoard" board="X-Plus 4">
<div class="AutozoomImage"><img src="img/X-Plus4Poster.png"/></div>
<div class="IntroduceTextBold trans" tid="l0"></div>
<div class="IntroduceText">https://qidi3d.com/products/plus4-3d-printer</div>
</div>
<div class="IntroduceBoard" board="Q1 Pro">
<div class="AutozoomImage"><img src="img/Q1 ProPoster.png"/></div>
<div class="IntroduceTextBold trans" tid="l0"></div>
<div class="IntroduceText">https://qidi3d.com</div>
<div class="IntroduceText">https://qidi3d.com/products/q1-pro-3d-printer</div>
</div>
<div class="IntroduceBoard" board="X-MAX 3">
@@ -340,262 +363,34 @@
<div class="IntroduceBoard" board="Filaments">
<div class="FilamentsTable">
<table cellspacing="0">
<thead>
<tr>
<th>Filament</th>
<th>Drying box</th>
<th>Anneal</th>
<th>Water resistance</th>
<th>Corrosion resistance</th>
<th>Creep resistance</th>
<th>HDT 0.45</th>
<th>HDT 1.80</th>
<th>Tensile strength(MPa)</th>
<th>Tensile modulus(MPa)</th>
<th>Elongation at break(%)</th>
<th>Flexural strength(MPa)</th>
<th>Flexural modulus(MPa)</th>
<th>Notch impact strength(KJ/㎡)</th>
</tr>
</thead>
<tbody>
<tr v-for="(item, index) in 1" :key="index">
<td>ABS Odorless</td>
<td>≤30</td>
<td>/</td>
<td>++</td>
<td>+</td>
<td>+++</td>
<td>92℃</td>
<td>86℃</td>
<td>41.65 ± 0.27</td>
<td>2351.00 ± 92.00</td>
<td>7.95 ± 4.53</td>
<td>67.81 ± 0.54</td>
<td>2400.00 ± 79.69</td>
<td>20.03 ± 1.32</td>
</tr>
<tr v-for="(item, index) in 1" :key="index">
<td>ABS Rapido</td>
<td>≤30</td>
<td>/</td>
<td>++</td>
<td>+</td>
<td>+++</td>
<td>85℃</td>
<td>/</td>
<td>41 ± 1</td>
<td>3850 ± 150</td>
<td>11 ± 1</td>
<td>77.5 ± 2.5</td>
<td>77.5 ± 2.5</td>
<td>20 ± 2</td>
</tr>
<tr v-for="(item, index) in 1" :key="index">
<td>ABS-GF25</td>
<td>≤30</td>
<td>/</td>
<td>+++</td>
<td>+</td>
<td>+++</td>
<td>97℃</td>
<td>93℃</td>
<td>48.48 ± 0.61</td>
<td>3752.13 ± 68.39</td>
<td>2.10 ± 0.10</td>
<td>78.80 ± 1.26</td>
<td>3531.71 ± 75.79</td>
<td>8.91 ± 0.63</td>
</tr>
<tr v-for="(item, index) in 1" :key="index">
<td>ASA</td>
<td>≤30</td>
<td>/</td>
<td>+++</td>
<td>+</td>
<td>+++</td>
<td>94℃</td>
<td>86℃</td>
<td>38.50 ± 1.60</td>
<td>2317.00 ± 246.00</td>
<td>5.20 ± 1.40</td>
<td>64.49 ± 1.30</td>
<td>2399.00 ± 147.00</td>
<td>12.90 ± 0.90</td>
</tr>
<tr v-for="(item, index) in 1" :key="index">
<td>ASA-Aero</td>
<td>≤30</td>
<td>/</td>
<td>++</td>
<td>+</td>
<td>++</td>
<td>70℃</td>
<td>55℃</td>
<td>8.25 ± 0.15</td>
<td>593.99 ± 24.34</td>
<td>11.52 ± 0.58</td>
<td>14.31 ± 1.66</td>
<td>457.94 ± 20.84</td>
<td>2.29 ± 0.13</td>
</tr>
<tr v-for="(item, index) in 1" :key="index">
<td>PA12-CF</td>
<td>≤15</td>
<td>80-100℃</td>
<td>+</td>
<td>++</td>
<td>+</td>
<td>149.6℃</td>
<td>112.4℃</td>
<td>87.49 ± 2.81</td>
<td>5438.40 ± 282.82</td>
<td>2.59 ± 0.19</td>
<td>133.17 ± 4.66</td>
<td>4667.43 ± 339.80</td>
<td>6.11 ± 1.45</td>
</tr>
<tr v-for="(item, index) in 1" :key="index">
<td>PAHT-CF</td>
<td>≤15</td>
<td>80-100℃</td>
<td>++</td>
<td>+++</td>
<td>+++</td>
<td>192.3℃</td>
<td>121.7℃</td>
<td>104.90 ± 1.99</td>
<td>8383.26 ± 419.53</td>
<td>1.60 ± 0.07</td>
<td>147.70 ± 4.09</td>
<td>5969.35 ± 145.28</td>
<td>6.17 ± 0.2</td>
</tr>
<tr v-for="(item, index) in 1" :key="index">
<td>PC/ABS-FR</td>
<td>≤15</td>
<td>/</td>
<td>+++</td>
<td>+</td>
<td>+++</td>
<td>88℃</td>
<td>83℃</td>
<td>52.51 ± 0.28</td>
<td>2588.73 ± 64.81</td>
<td>5.55 ± 0.99</td>
<td>85.95 ± 0.83</td>
<td>2504.55 ± 22.88</td>
<td>8.39 ± 0.46</td>
</tr>
<tr v-for="(item, index) in 1" :key="index">
<td>PET-CF</td>
<td>≤15</td>
<td>80-100℃</td>
<td>+++</td>
<td>+++</td>
<td>+++</td>
<td>148.8℃</td>
<td>112.1℃</td>
<td>87.41 ± 3.57</td>
<td>6025.53 ± 355.46</td>
<td>1.99 ±0.18</td>
<td>122.69 ± 5.19</td>
<td>5313.21 ± 197.89</td>
<td>5.57 ± 0.58</td>
</tr>
<tr v-for="(item, index) in 1" :key="index">
<td>PETG-Tough</td>
<td>≤20</td>
<td>/</td>
<td>+++</td>
<td>++</td>
<td>+++</td>
<td>78℃</td>
<td>73℃</td>
<td>40.3±0.6</td>
<td>1780±80</td>
<td>4.0±0.2</td>
<td>62.8±0.4</td>
<td>1919±54</td>
<td>13.9±2.3</td>
</tr>
<tr v-for="(item, index) in 1" :key="index">
<td>PLA Rapido</td>
<td>≤30</td>
<td>/</td>
<td>+</td>
<td>+</td>
<td>+</td>
<td>57℃</td>
<td>/</td>
<td>39 ± 3</td>
<td>4650 ± 150</td>
<td>12.5 ± 2.5</td>
<td>72.5 ± 2.5</td>
<td>2850 ± 150</td>
<td>6 ± 2</td>
</tr>
<tr v-for="(item, index) in 1" :key="index">
<td>PLA Rapido Matte</td>
<td>≤30</td>
<td>/</td>
<td>+</td>
<td>+</td>
<td>+</td>
<td>58℃</td>
<td>/</td>
<td>39 ± 3</td>
<td>2400 ± 200</td>
<td>3 ± 1</td>
<td>77.5 ± 2.5</td>
<td>2200 ± 200</td>
<td>7.5 ± 1.5</td>
</tr>
<tr v-for="(item, index) in 1" :key="index">
<td>PLA-CF</td>
<td>≤30</td>
<td>/</td>
<td>+</td>
<td>+</td>
<td>++</td>
<td>55.2℃</td>
<td>52.6℃</td>
<td>54.92 ± 0.22</td>
<td>4020.55 ± 99.11</td>
<td>4.90 ± 0.97</td>
<td>91.57 ± 0.31</td>
<td>4197.66 ± 279.96</td>
<td>6.65 ± 0.38</td>
</tr>
<tr v-for="(item, index) in 1" :key="index">
<td>UltraPA</td>
<td>≤15</td>
<td>/</td>
<td>++</td>
<td>++</td>
<td>++</td>
<td>77.8℃</td>
<td>73.1℃</td>
<td>86.15 ± 0.56</td>
<td>3609.22 ± 153.31</td>
<td>11.68 ± 3.36</td>
<td>121.47 ± 3.14</td>
<td>3314.03 ±181.88</td>
<td>5.78 ± 0.30</td>
</tr>
</tbody>
</table>
<iframe id="filamentTableIframe" class="table-container" style="width: 100%; height: 1000px; border: none;"></iframe>
</div>
<div class="IntroduceTextBold trans" tid="l0"></div>
<div class="IntroduceText">https://qidi3d.com/collections/filaments</div>
</div>
<script>
const urlParams = new URLSearchParams(window.location.search);
const lang = urlParams.get('lang') || 'en';
var iframe = document.getElementById('filamentTableIframe');
iframe.src = 'filament_table.html?lang=' + lang;
</script>
<div class="IssueBoard" board="IssueReport">
<div class="IntroduceTitle trans" tid="t6"></div>
<div class="IntroduceText trans" tid="l2"></div>
<div class="IntroduceText trans" tid="l3"></div>
<div><br></div>
<div class="IntroduceText trans" tid="l47"></div>
<div class="IntroduceText">https://wiki.qidi3d.com</div>
<div class="EmailBlock">
<div class="PrinterBlock">
<div class="CenterImage"><img src="img/X-Plus 4.png"/></div>
<div class="ThumbnailTitle">X-Plus 4</div>
<div class="IntroduceText">
<b>E-mail:</b><br/>Plus4support@qidi3d.com<br>Plus4Ams@qidi3d.com<br/><br>
<b>Skype:</b><br/>Plus4support@qidi3d.com
</div>
</div>
<div class="PrinterBlock">
<div class="CenterImage"><img src="img/Q1 Pro.png"/></div>
<div class="ThumbnailTitle">Q1 Pro</div>

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 502 KiB

View File

@@ -0,0 +1,28 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Printer Connection Required</title>
<link rel="stylesheet" type="text/css" href="css/home.css" />
<script type="text/javascript" src="../data/text.js"></script>
<script type="text/javascript" src="../guide/js/jquery-3.6.0.min.js"></script>
<script type="text/javascript" src="../guide/js/json2.js"></script>
<script type="text/javascript" src="../guide/js/globalapi.js"></script>
<script type="text/javascript" src="../guide/js/home.js"></script>
</head>
<body onLoad="OnInit()">
<div id="GifBoard">
<div class="GifBlock">
<div class="UG_TITLE trans" tid="t4"></div>
<div class="UG_DESC trans" tid="wk2">
Please set up your printer connection to view the device.
</div>
<div class="UG_IMG"><img src="link_connection.png" /></div>
</div>
</div>
<!--<h1 class="trans" tid="t4">Printer Connection</h1>
<p class="trans">Please set up your printer connection to view the device.</p>
<img src="setup_connection.gif" alt="Printer connection setup demonstration" style="max-width: 100%; height: auto; display: block;"/>-->
</body>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 1.7 MiB

70
src/.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,70 @@
{
"files.associations": {
"typeinfo": "cpp",
"any": "cpp",
"array": "cpp",
"atomic": "cpp",
"*.tcc": "cpp",
"bitset": "cpp",
"cctype": "cpp",
"cfenv": "cpp",
"charconv": "cpp",
"chrono": "cpp",
"cinttypes": "cpp",
"clocale": "cpp",
"cmath": "cpp",
"codecvt": "cpp",
"complex": "cpp",
"condition_variable": "cpp",
"csignal": "cpp",
"cstdarg": "cpp",
"cstddef": "cpp",
"cstdint": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"cstring": "cpp",
"ctime": "cpp",
"cwchar": "cpp",
"cwctype": "cpp",
"deque": "cpp",
"forward_list": "cpp",
"list": "cpp",
"unordered_map": "cpp",
"unordered_set": "cpp",
"vector": "cpp",
"exception": "cpp",
"algorithm": "cpp",
"functional": "cpp",
"iterator": "cpp",
"map": "cpp",
"memory": "cpp",
"memory_resource": "cpp",
"numeric": "cpp",
"optional": "cpp",
"random": "cpp",
"ratio": "cpp",
"regex": "cpp",
"set": "cpp",
"string": "cpp",
"string_view": "cpp",
"system_error": "cpp",
"tuple": "cpp",
"type_traits": "cpp",
"utility": "cpp",
"fstream": "cpp",
"future": "cpp",
"initializer_list": "cpp",
"iomanip": "cpp",
"iosfwd": "cpp",
"iostream": "cpp",
"istream": "cpp",
"limits": "cpp",
"mutex": "cpp",
"new": "cpp",
"ostream": "cpp",
"sstream": "cpp",
"stdexcept": "cpp",
"streambuf": "cpp",
"thread": "cpp"
}
}

View File

@@ -26,6 +26,8 @@
#include <cstring>
#include <iostream>
#include <math.h>
//B64
#include "nlohmann/json.hpp"
#include <boost/algorithm/string/predicate.hpp>
#include <boost/filesystem.hpp>
#include <boost/nowide/args.hpp>
@@ -130,12 +132,6 @@ int CLI::run(int argc, char **argv)
// On Unix systems, the qidi-slicer binary may be symlinked to give the application a different meaning.
boost::algorithm::iends_with(boost::filesystem::path(argv[0]).filename().string(), "gcodeviewer");
#endif // _WIN32
#if ENABLE_GL_CORE_PROFILE
std::pair<int, int> opengl_version = { 0, 0 };
#if ENABLE_OPENGL_DEBUG_OPTION
bool opengl_debug = false;
#endif // ENABLE_OPENGL_DEBUG_OPTION
#endif // ENABLE_GL_CORE_PROFILE
const std::vector<std::string> &load_configs = m_config.option<ConfigOptionStrings>("load", true)->values;
const ForwardCompatibilitySubstitutionRule config_substitution_rule = m_config.option<ConfigOptionEnum<ForwardCompatibilitySubstitutionRule>>("config_compatibility", true)->value;
@@ -174,7 +170,11 @@ int CLI::run(int argc, char **argv)
m_print_config.apply(config);
}
#ifdef SLIC3R_GUI
#if ENABLE_GL_CORE_PROFILE
std::pair<int, int> opengl_version = { 0, 0 };
bool opengl_debug = false;
bool opengl_compatibility_profile = false;
// search for special keys into command line parameters
auto it = std::find(m_actions.begin(), m_actions.end(), "gcodeviewer");
if (it != m_actions.end()) {
@@ -185,30 +185,37 @@ int CLI::run(int argc, char **argv)
it = std::find(m_actions.begin(), m_actions.end(), "opengl-version");
if (it != m_actions.end()) {
std::string opengl_version_str = m_config.opt_string("opengl-version");
if (std::find(Slic3r::GUI::OpenGLVersions::core_str.begin(), Slic3r::GUI::OpenGLVersions::core_str.end(), opengl_version_str) == Slic3r::GUI::OpenGLVersions::core_str.end()) {
if (std::find(Slic3r::GUI::OpenGLVersions::precore_str.begin(), Slic3r::GUI::OpenGLVersions::precore_str.end(), opengl_version_str) == Slic3r::GUI::OpenGLVersions::precore_str.end()) {
boost::nowide::cerr << "Found invalid OpenGL version: " << opengl_version_str << std::endl;
opengl_version_str.clear();
const Semver opengl_minimum = Semver(3,2,0);
const std::string opengl_version_str = m_config.opt_string("opengl-version");
boost::optional<Semver> semver = Semver::parse(opengl_version_str);
if (semver.has_value() && (*semver) >= opengl_minimum ) {
opengl_version.first = semver->maj();
opengl_version.second = semver->min();
if (std::find(Slic3r::GUI::OpenGLVersions::core.begin(), Slic3r::GUI::OpenGLVersions::core.end(), std::make_pair(opengl_version.first, opengl_version.second)) == Slic3r::GUI::OpenGLVersions::core.end()) {
opengl_version = { 0, 0 };
boost::nowide::cerr << "Required OpenGL version " << opengl_version_str << " not recognized.\n Option 'opengl-version' ignored." << std::endl;
}
} else
boost::nowide::cerr << "Required OpenGL version " << opengl_version_str << " is invalid. Must be greater than or equal to " <<
opengl_minimum.to_string() << "\n Option 'opengl-version' ignored." << std::endl;
start_gui = true;
m_actions.erase(it);
}
if (!opengl_version_str.empty()) {
std::vector<std::string> tokens;
boost::split(tokens, opengl_version_str, boost::is_any_of("."), boost::token_compress_on);
opengl_version.first = std::stoi(tokens[0].c_str());
opengl_version.second = std::stoi(tokens[1].c_str());
}
it = std::find(m_actions.begin(), m_actions.end(), "opengl-compatibility");
if (it != m_actions.end()) {
start_gui = true;
opengl_compatibility_profile = true;
// reset version as compatibility profile always take the highest version
// supported by the graphic card
opengl_version = std::make_pair(0, 0);
m_actions.erase(it);
}
it = std::find(m_actions.begin(), m_actions.end(), "opengl-debug");
if (it != m_actions.end()) {
start_gui = true;
#if ENABLE_OPENGL_DEBUG_OPTION
opengl_debug = true;
#endif // ENABLE_OPENGL_DEBUG_OPTION
m_actions.erase(it);
}
#else
@@ -222,6 +229,16 @@ int CLI::run(int argc, char **argv)
}
}
#endif // ENABLE_GL_CORE_PROFILE
#else // SLIC3R_GUI
// If there is no GUI, we shall ignore the parameters. Remove them from the list.
for (const std::string& s : { "opengl-version", "opengl-compatibility", "opengl-debug", "gcodeviewer" }) {
auto it = std::find(m_actions.cbegin(), m_actions.cend(), s);
if (it != m_actions.end()) {
boost::nowide::cerr << "Parameter '" << s << "' is ignored, this PrusaSlicer build is CLI only." << std::endl;
m_actions.erase(it);
}
}
#endif
// Read input file(s) if any.
for (const std::string& file : m_input_files)
@@ -702,10 +719,9 @@ int CLI::run(int argc, char **argv)
params.download_url = download_url;
params.delete_after_load = delete_after_load;
#if ENABLE_GL_CORE_PROFILE
#if ENABLE_OPENGL_DEBUG_OPTION
params.opengl_version = opengl_version;
params.opengl_debug = opengl_debug;
#endif // ENABLE_OPENGL_DEBUG_OPTION
params.opengl_compatibiity_profile = opengl_compatibility_profile;
#endif // ENABLE_GL_CORE_PROFILE
return Slic3r::GUI::GUI_Run(params);
#else // SLIC3R_GUI
@@ -781,6 +797,7 @@ bool CLI::setup(int argc, char **argv)
set_var_dir((path_resources / "icons").string());
set_local_dir((path_resources / "localization").string());
set_sys_shapes_dir((path_resources / "shapes").string());
set_custom_gcodes_dir((path_resources / "custom_gcodes").string());
// Parse all command line options into a DynamicConfig.
// If any option is unsupported, print usage and abort immediately.
@@ -805,6 +822,11 @@ bool CLI::setup(int argc, char **argv)
set_logging_level(opt_loglevel->value);
}
{
const ConfigOptionInt *opt_threads = m_config.opt<ConfigOptionInt>("threads");
if (opt_threads != nullptr)
thread_count = opt_threads->value;
}
//FIXME Validating at this stage most likely does not make sense, as the config is not fully initialized yet.
std::string validity = m_config.validate();

View File

@@ -268,7 +268,7 @@ int wmain(int argc, wchar_t **argv)
// In that case, use Mesa.
(::GetSystemMetrics(SM_REMOTESESSION) && !force_hw) ||
// Try to load the default OpenGL driver and test its context version.
! opengl_version_check.load_opengl_dll() || ! opengl_version_check.is_version_greater_or_equal_to(2, 0);
! opengl_version_check.load_opengl_dll() || ! opengl_version_check.is_version_greater_or_equal_to(3, 2);
#endif /* SLIC3R_GUI */
wchar_t path_to_exe[MAX_PATH + 1] = { 0 };

View File

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

View File

@@ -41,8 +41,8 @@ BeadingStrategyPtr BeadingStrategyFactory::makeStrategy(const coord_t preferred_
BOOST_LOG_TRIVIAL(trace) << "Applying the Widening Beading meta-strategy with minimum input width " << min_feature_size << " and minimum output width " << min_bead_width << ".";
ret = std::make_unique<WideningBeadingStrategy>(std::move(ret), min_feature_size, min_bead_width);
}
if (outer_wall_offset > 0) {
//w39
if (outer_wall_offset != 0){//if (outer_wall_offset > 0) {
BOOST_LOG_TRIVIAL(trace) << "Applying the OuterWallOffset meta-strategy with offset = " << outer_wall_offset << ".";
ret = std::make_unique<OuterWallInsetBeadingStrategy>(outer_wall_offset, std::move(ret));
}

View File

@@ -10,7 +10,6 @@
#include <functional>
#include <boost/log/trivial.hpp>
#include "utils/VoronoiUtils.hpp"
#include "utils/linearAlg2D.hpp"
#include "Utils.hpp"
@@ -19,26 +18,9 @@
#include "Geometry/VoronoiUtilsCgal.hpp"
#include "../EdgeGrid.hpp"
#include "Geometry/VoronoiUtils.hpp"
#define SKELETAL_TRAPEZOIDATION_BEAD_SEARCH_MAX 1000 //A limit to how long it'll keep searching for adjacent beads. Increasing will re-use beadings more often (saving performance), but search longer for beading (costing performance).
namespace boost::polygon {
template<> struct geometry_concept<Slic3r::Arachne::PolygonsSegmentIndex>
{
typedef segment_concept type;
};
template<> struct segment_traits<Slic3r::Arachne::PolygonsSegmentIndex>
{
typedef coord_t coordinate_type;
typedef Slic3r::Point point_type;
static inline point_type get(const Slic3r::Arachne::PolygonsSegmentIndex &CSegment, direction_1d dir)
{
return dir.to_int() ? CSegment.p() : CSegment.next().p();
}
};
} // namespace boost::polygon
namespace Slic3r::Arachne
{
@@ -108,8 +90,7 @@ static void export_graph_to_svg(const std::string
}
#endif
SkeletalTrapezoidation::node_t& SkeletalTrapezoidation::makeNode(vd_t::vertex_type& vd_node, Point p)
{
SkeletalTrapezoidation::node_t &SkeletalTrapezoidation::makeNode(const VD::vertex_type &vd_node, Point p) {
auto he_node_it = vd_node_to_he_node.find(&vd_node);
if (he_node_it == vd_node_to_he_node.end())
{
@@ -124,8 +105,7 @@ SkeletalTrapezoidation::node_t& SkeletalTrapezoidation::makeNode(vd_t::vertex_ty
}
}
void SkeletalTrapezoidation::transferEdge(Point from, Point to, vd_t::edge_type& vd_edge, edge_t*& prev_edge, Point& start_source_point, Point& end_source_point, const std::vector<Segment>& segments)
{
void SkeletalTrapezoidation::transferEdge(Point from, Point to, const VD::edge_type &vd_edge, edge_t *&prev_edge, Point &start_source_point, Point &end_source_point, const std::vector<Segment> &segments) {
auto he_edge_it = vd_edge_to_he_edge.find(vd_edge.twin());
if (he_edge_it != vd_edge_to_he_edge.end())
{ // Twin segment(s) have already been made
@@ -235,22 +215,18 @@ void SkeletalTrapezoidation::transferEdge(Point from, Point to, vd_t::edge_type&
}
}
Points SkeletalTrapezoidation::discretize(const vd_t::edge_type& vd_edge, const std::vector<Segment>& segments)
Points SkeletalTrapezoidation::discretize(const VD::edge_type& vd_edge, const std::vector<Segment>& segments)
{
assert(Geometry::VoronoiUtils::is_in_range<coord_t>(vd_edge));
/*Terminology in this function assumes that the edge moves horizontally from
left to right. This is not necessarily the case; the edge can go in any
direction, but it helps to picture it in a certain direction in your head.*/
const vd_t::cell_type* left_cell = vd_edge.cell();
const vd_t::cell_type* right_cell = vd_edge.twin()->cell();
const VD::cell_type *left_cell = vd_edge.cell();
const VD::cell_type *right_cell = vd_edge.twin()->cell();
assert(VoronoiUtils::p(vd_edge.vertex0()).x() <= std::numeric_limits<coord_t>::max() && VoronoiUtils::p(vd_edge.vertex0()).x() >= std::numeric_limits<coord_t>::lowest());
assert(VoronoiUtils::p(vd_edge.vertex0()).y() <= std::numeric_limits<coord_t>::max() && VoronoiUtils::p(vd_edge.vertex0()).y() >= std::numeric_limits<coord_t>::lowest());
assert(VoronoiUtils::p(vd_edge.vertex1()).x() <= std::numeric_limits<coord_t>::max() && VoronoiUtils::p(vd_edge.vertex1()).x() >= std::numeric_limits<coord_t>::lowest());
assert(VoronoiUtils::p(vd_edge.vertex1()).y() <= std::numeric_limits<coord_t>::max() && VoronoiUtils::p(vd_edge.vertex1()).y() >= std::numeric_limits<coord_t>::lowest());
Point start = VoronoiUtils::p(vd_edge.vertex0()).cast<coord_t>();
Point end = VoronoiUtils::p(vd_edge.vertex1()).cast<coord_t>();
Point start = Geometry::VoronoiUtils::to_point(vd_edge.vertex0()).cast<coord_t>();
Point end = Geometry::VoronoiUtils::to_point(vd_edge.vertex1()).cast<coord_t>();
bool point_left = left_cell->contains_point();
bool point_right = right_cell->contains_point();
@@ -260,17 +236,17 @@ Points SkeletalTrapezoidation::discretize(const vd_t::edge_type& vd_edge, const
}
else if (point_left != point_right) //This is a parabolic edge between a point and a line.
{
Point p = VoronoiUtils::getSourcePoint(*(point_left ? left_cell : right_cell), segments);
const Segment& s = VoronoiUtils::getSourceSegment(*(point_left ? right_cell : left_cell), segments);
return VoronoiUtils::discretizeParabola(p, s, start, end, discretization_step_size, transitioning_angle);
Point p = Geometry::VoronoiUtils::get_source_point(*(point_left ? left_cell : right_cell), segments.begin(), segments.end());
const Segment& s = Geometry::VoronoiUtils::get_source_segment(*(point_left ? right_cell : left_cell), segments.begin(), segments.end());
return Geometry::VoronoiUtils::discretize_parabola(p, s, start, end, discretization_step_size, transitioning_angle);
}
else //This is a straight edge between two points.
{
/*While the edge is straight, it is still discretized since the part
becomes narrower between the two points. As such it may need different
beadings along the way.*/
Point left_point = VoronoiUtils::getSourcePoint(*left_cell, segments);
Point right_point = VoronoiUtils::getSourcePoint(*right_cell, segments);
Point left_point = Geometry::VoronoiUtils::get_source_point(*left_cell, segments.begin(), segments.end());
Point right_point = Geometry::VoronoiUtils::get_source_point(*right_cell, segments.begin(), segments.end());
coord_t d = (right_point - left_point).cast<int64_t>().norm();
Point middle = (left_point + right_point) / 2;
Point x_axis_dir = perp(Point(right_point - left_point));
@@ -350,8 +326,7 @@ Points SkeletalTrapezoidation::discretize(const vd_t::edge_type& vd_edge, const
}
}
bool SkeletalTrapezoidation::computePointCellRange(vd_t::cell_type& cell, Point& start_source_point, Point& end_source_point, vd_t::edge_type*& starting_vd_edge, vd_t::edge_type*& ending_vd_edge, const std::vector<Segment>& segments)
{
bool SkeletalTrapezoidation::computePointCellRange(const VD::cell_type &cell, Point &start_source_point, Point &end_source_point, const VD::edge_type *&starting_vd_edge, const VD::edge_type *&ending_vd_edge, const std::vector<Segment> &segments) {
if (cell.incident_edge()->is_infinite())
return false; //Infinite edges only occur outside of the polygon. Don't copy any part of this cell.
@@ -359,16 +334,16 @@ bool SkeletalTrapezoidation::computePointCellRange(vd_t::cell_type& cell, Point&
// Copy whole cell into graph or not at all
// If the cell.incident_edge()->vertex0() is far away so much that it doesn't even fit into Vec2i64, then there is no way that it will be inside the input polygon.
if (const vd_t::vertex_type &vert = *cell.incident_edge()->vertex0();
if (const VD::vertex_type &vert = *cell.incident_edge()->vertex0();
vert.x() >= double(std::numeric_limits<int64_t>::max()) || vert.x() <= double(std::numeric_limits<int64_t>::lowest()) ||
vert.y() >= double(std::numeric_limits<int64_t>::max()) || vert.y() <= double(std::numeric_limits<int64_t>::lowest()))
return false; // Don't copy any part of this cell
const Point source_point = VoronoiUtils::getSourcePoint(cell, segments);
const PolygonsPointIndex source_point_index = VoronoiUtils::getSourcePointIndex(cell, segments);
Vec2i64 some_point = VoronoiUtils::p(cell.incident_edge()->vertex0());
const Point source_point = Geometry::VoronoiUtils::get_source_point(cell, segments.begin(), segments.end());
const PolygonsPointIndex source_point_index = Geometry::VoronoiUtils::get_source_point_index(cell, segments.begin(), segments.end());
Vec2i64 some_point = Geometry::VoronoiUtils::to_point(cell.incident_edge()->vertex0());
if (some_point == source_point.cast<int64_t>())
some_point = VoronoiUtils::p(cell.incident_edge()->vertex1());
some_point = Geometry::VoronoiUtils::to_point(cell.incident_edge()->vertex1());
//Test if the some_point is even inside the polygon.
//The edge leading out of a polygon must have an endpoint that's not in the corner following the contour of the polygon at that vertex.
@@ -377,16 +352,16 @@ bool SkeletalTrapezoidation::computePointCellRange(vd_t::cell_type& cell, Point&
if (!LinearAlg2D::isInsideCorner(source_point_index.prev().p(), source_point_index.p(), source_point_index.next().p(), some_point))
return false; // Don't copy any part of this cell
vd_t::edge_type* vd_edge = cell.incident_edge();
const VD::edge_type* vd_edge = cell.incident_edge();
do {
assert(vd_edge->is_finite());
if (Vec2i64 p1 = VoronoiUtils::p(vd_edge->vertex1()); p1 == source_point.cast<int64_t>()) {
if (Vec2i64 p1 = Geometry::VoronoiUtils::to_point(vd_edge->vertex1()); p1 == source_point.cast<int64_t>()) {
start_source_point = source_point;
end_source_point = source_point;
starting_vd_edge = vd_edge->next();
ending_vd_edge = vd_edge;
} else {
assert((VoronoiUtils::p(vd_edge->vertex0()) == source_point.cast<int64_t>() || !vd_edge->is_secondary()) && "point cells must end in the point! They cannot cross the point with an edge, because collinear edges are not allowed in the input.");
assert((Geometry::VoronoiUtils::to_point(vd_edge->vertex0()) == source_point.cast<int64_t>() || !vd_edge->is_secondary()) && "point cells must end in the point! They cannot cross the point with an edge, because collinear edges are not allowed in the input.");
}
}
while (vd_edge = vd_edge->next(), vd_edge != cell.incident_edge());
@@ -395,46 +370,6 @@ bool SkeletalTrapezoidation::computePointCellRange(vd_t::cell_type& cell, Point&
return true;
}
void SkeletalTrapezoidation::computeSegmentCellRange(vd_t::cell_type& cell, Point& start_source_point, Point& end_source_point, vd_t::edge_type*& starting_vd_edge, vd_t::edge_type*& ending_vd_edge, const std::vector<Segment>& segments)
{
const Segment &source_segment = VoronoiUtils::getSourceSegment(cell, segments);
const Point from = source_segment.from();
const Point to = source_segment.to();
// Find starting edge
// Find end edge
bool seen_possible_start = false;
bool after_start = false;
bool ending_edge_is_set_before_start = false;
vd_t::edge_type* edge = cell.incident_edge();
do {
if (edge->is_infinite())
continue;
Vec2i64 v0 = VoronoiUtils::p(edge->vertex0());
Vec2i64 v1 = VoronoiUtils::p(edge->vertex1());
assert(!(v0 == to.cast<int64_t>() && v1 == from.cast<int64_t>() ));
if (v0 == to.cast<int64_t>() && !after_start) { // Use the last edge which starts in source_segment.to
starting_vd_edge = edge;
seen_possible_start = true;
}
else if (seen_possible_start) {
after_start = true;
}
if (v1 == from.cast<int64_t>() && (!ending_vd_edge || ending_edge_is_set_before_start)) {
ending_edge_is_set_before_start = !after_start;
ending_vd_edge = edge;
}
} while (edge = edge->next(), edge != cell.incident_edge());
assert(starting_vd_edge && ending_vd_edge);
assert(starting_vd_edge != ending_vd_edge);
start_source_point = source_segment.to();
end_source_point = source_segment.from();
}
SkeletalTrapezoidation::SkeletalTrapezoidation(const Polygons& polys, const BeadingStrategy& beading_strategy,
double transitioning_angle, coord_t discretization_step_size,
@@ -450,194 +385,6 @@ SkeletalTrapezoidation::SkeletalTrapezoidation(const Polygons& polys, const Bead
constructFromPolygons(polys);
}
static bool has_finite_edge_with_non_finite_vertex(const Geometry::VoronoiDiagram &voronoi_diagram)
{
for (const VoronoiUtils::vd_t::edge_type &edge : voronoi_diagram.edges()) {
if (edge.is_finite()) {
assert(edge.vertex0() != nullptr && edge.vertex1() != nullptr);
if (edge.vertex0() == nullptr || edge.vertex1() == nullptr || !VoronoiUtils::is_finite(*edge.vertex0()) ||
!VoronoiUtils::is_finite(*edge.vertex1()))
return true;
}
}
return false;
}
static bool detect_missing_voronoi_vertex(const Geometry::VoronoiDiagram &voronoi_diagram, const std::vector<SkeletalTrapezoidation::Segment> &segments) {
if (has_finite_edge_with_non_finite_vertex(voronoi_diagram))
return true;
for (VoronoiUtils::vd_t::cell_type cell : voronoi_diagram.cells()) {
if (!cell.incident_edge())
continue; // There is no spoon
if (cell.contains_segment()) {
const SkeletalTrapezoidation::Segment &source_segment = VoronoiUtils::getSourceSegment(cell, segments);
const Point from = source_segment.from();
const Point to = source_segment.to();
// Find starting edge
// Find end edge
bool seen_possible_start = false;
bool after_start = false;
bool ending_edge_is_set_before_start = false;
VoronoiUtils::vd_t::edge_type *starting_vd_edge = nullptr;
VoronoiUtils::vd_t::edge_type *ending_vd_edge = nullptr;
VoronoiUtils::vd_t::edge_type *edge = cell.incident_edge();
do {
if (edge->is_infinite() || edge->vertex0() == nullptr || edge->vertex1() == nullptr || !VoronoiUtils::is_finite(*edge->vertex0()) || !VoronoiUtils::is_finite(*edge->vertex1()))
continue;
Vec2i64 v0 = VoronoiUtils::p(edge->vertex0());
Vec2i64 v1 = VoronoiUtils::p(edge->vertex1());
assert(!(v0 == to.cast<int64_t>() && v1 == from.cast<int64_t>()));
if (v0 == to.cast<int64_t>() && !after_start) { // Use the last edge which starts in source_segment.to
starting_vd_edge = edge;
seen_possible_start = true;
} else if (seen_possible_start) {
after_start = true;
}
if (v1 == from.cast<int64_t>() && (!ending_vd_edge || ending_edge_is_set_before_start)) {
ending_edge_is_set_before_start = !after_start;
ending_vd_edge = edge;
}
} while (edge = edge->next(), edge != cell.incident_edge());
if (!starting_vd_edge || !ending_vd_edge || starting_vd_edge == ending_vd_edge)
return true;
}
}
return false;
}
static bool has_missing_twin_edge(const SkeletalTrapezoidationGraph &graph)
{
for (const auto &edge : graph.edges)
if (edge.twin == nullptr)
return true;
return false;
}
using PointMap = SkeletalTrapezoidation::PointMap;
inline static void rotate_back_skeletal_trapezoidation_graph_after_fix(SkeletalTrapezoidationGraph &graph,
const double fix_angle,
const PointMap &vertex_mapping)
{
for (STHalfEdgeNode &node : graph.nodes) {
// If a mapping exists between a rotated point and an original point, use this mapping. Otherwise, rotate a point in the opposite direction.
if (auto node_it = vertex_mapping.find(node.p); node_it != vertex_mapping.end())
node.p = node_it->second;
else
node.p.rotate(-fix_angle);
}
}
bool detect_voronoi_edge_intersecting_input_segment(const Geometry::VoronoiDiagram &voronoi_diagram, const std::vector<VoronoiUtils::Segment> &segments)
{
for (VoronoiUtils::vd_t::cell_type cell : voronoi_diagram.cells()) {
if (!cell.incident_edge())
continue; // Degenerated cell, there is no spoon
if (!cell.contains_segment())
continue; // Skip cells that don't contain segments.
const VoronoiUtils::Segment &source_segment = VoronoiUtils::getSourceSegment(cell, segments);
const Vec2d source_segment_from = source_segment.from().cast<double>();
const Vec2d source_segment_vec = source_segment.to().cast<double>() - source_segment_from;
Point start_source_point, end_source_point;
VoronoiUtils::vd_t::edge_type *begin_voronoi_edge = nullptr, *end_voronoi_edge = nullptr;
SkeletalTrapezoidation::computeSegmentCellRange(cell, start_source_point, end_source_point, begin_voronoi_edge, end_voronoi_edge, segments);
// All Voronoi vertices must be on left side of the source segment, otherwise Voronoi diagram is invalid.
// FIXME Lukas H.: Be aware that begin_voronoi_edge and end_voronoi_edge could be nullptr in some specific cases.
// It mostly happens when there is some missing Voronoi, for example, in GH issue #8846 (IssuesWithMysteriousPerimeters.3mf).
if (begin_voronoi_edge != nullptr && end_voronoi_edge != nullptr)
for (VoronoiUtils::vd_t::edge_type *edge = begin_voronoi_edge; edge != end_voronoi_edge; edge = edge->next())
if (const Vec2d edge_v1(edge->vertex1()->x(), edge->vertex1()->y()); Slic3r::cross2(source_segment_vec, edge_v1 - source_segment_from) < 0)
return true;
}
return false;
}
enum class VoronoiDiagramStatus {
NO_ISSUE_DETECTED,
MISSING_VORONOI_VERTEX,
NON_PLANAR_VORONOI_DIAGRAM,
VORONOI_EDGE_INTERSECTING_INPUT_SEGMENT,
OTHER_TYPE_OF_VORONOI_DIAGRAM_DEGENERATION
};
// Try to detect cases when some Voronoi vertex is missing, when the Voronoi diagram
// is not planar or some Voronoi edge is intersecting input segment.
VoronoiDiagramStatus detect_voronoi_diagram_known_issues(const Geometry::VoronoiDiagram &voronoi_diagram,
const std::vector<SkeletalTrapezoidation::Segment> &segments)
{
if (const bool has_missing_voronoi_vertex = detect_missing_voronoi_vertex(voronoi_diagram, segments); has_missing_voronoi_vertex) {
return VoronoiDiagramStatus::MISSING_VORONOI_VERTEX;
} else if (const bool has_voronoi_edge_intersecting_input_segment = detect_voronoi_edge_intersecting_input_segment(voronoi_diagram, segments); has_voronoi_edge_intersecting_input_segment) {
// Detection if Voronoi edge is intersecting input segment detects at least one model in GH issue #8446.
return VoronoiDiagramStatus::VORONOI_EDGE_INTERSECTING_INPUT_SEGMENT;
} else if (const bool is_voronoi_diagram_planar = Geometry::VoronoiUtilsCgal::is_voronoi_diagram_planar_angle(voronoi_diagram, segments); !is_voronoi_diagram_planar) {
// Detection of non-planar Voronoi diagram detects at least GH issues #8474, #8514 and #8446.
return VoronoiDiagramStatus::NON_PLANAR_VORONOI_DIAGRAM;
}
return VoronoiDiagramStatus::NO_ISSUE_DETECTED;
}
inline static std::pair<PointMap, double> try_to_fix_degenerated_voronoi_diagram_by_rotation(
Geometry::VoronoiDiagram &voronoi_diagram,
const Polygons &polys,
Polygons &polys_rotated,
std::vector<SkeletalTrapezoidation::Segment> &segments,
const std::vector<double> &fix_angles)
{
const Polygons polys_rotated_original = polys_rotated;
double fixed_by_angle = fix_angles.front();
PointMap vertex_mapping;
for (const double &fix_angle : fix_angles) {
vertex_mapping.clear();
polys_rotated = polys_rotated_original;
fixed_by_angle = fix_angle;
for (Polygon &poly : polys_rotated)
poly.rotate(fix_angle);
assert(polys_rotated.size() == polys.size());
for (size_t poly_idx = 0; poly_idx < polys.size(); ++poly_idx) {
assert(polys_rotated[poly_idx].size() == polys[poly_idx].size());
for (size_t point_idx = 0; point_idx < polys[poly_idx].size(); ++point_idx)
vertex_mapping.insert({polys_rotated[poly_idx][point_idx], polys[poly_idx][point_idx]});
}
segments.clear();
for (size_t poly_idx = 0; poly_idx < polys_rotated.size(); poly_idx++)
for (size_t point_idx = 0; point_idx < polys_rotated[poly_idx].size(); point_idx++)
segments.emplace_back(&polys_rotated, poly_idx, point_idx);
voronoi_diagram.clear();
construct_voronoi(segments.begin(), segments.end(), &voronoi_diagram);
#ifdef ARACHNE_DEBUG_VORONOI
{
static int iRun = 0;
dump_voronoi_to_svg(debug_out_path("arachne_voronoi-diagram-rotated-%d.svg", iRun++).c_str(), voronoi_diagram, to_points(polys), to_lines(polys));
}
#endif
if (detect_voronoi_diagram_known_issues(voronoi_diagram, segments) == VoronoiDiagramStatus::NO_ISSUE_DETECTED)
break;
}
assert(Geometry::VoronoiUtilsCgal::is_voronoi_diagram_planar_intersection(voronoi_diagram));
return {vertex_mapping, fixed_by_angle};
}
void SkeletalTrapezoidation::constructFromPolygons(const Polygons& polys)
{
@@ -670,8 +417,8 @@ void SkeletalTrapezoidation::constructFromPolygons(const Polygons& polys)
}
#endif
Geometry::VoronoiDiagram voronoi_diagram;
construct_voronoi(segments.begin(), segments.end(), &voronoi_diagram);
VD voronoi_diagram;
voronoi_diagram.construct_voronoi(segments.cbegin(), segments.cend());
#ifdef ARACHNE_DEBUG_VORONOI
{
@@ -680,45 +427,15 @@ void SkeletalTrapezoidation::constructFromPolygons(const Polygons& polys)
}
#endif
// When any Voronoi vertex is missing, the Voronoi diagram is not planar, or some voronoi edge is
// intersecting input segment, rotate the input polygon and try again.
VoronoiDiagramStatus status = detect_voronoi_diagram_known_issues(voronoi_diagram, segments);
const std::vector<double> fix_angles = {PI / 6, PI / 5, PI / 7, PI / 11};
double fixed_by_angle = fix_angles.front();
PointMap vertex_mapping;
// polys_copy is referenced through items stored in the std::vector segments.
Polygons polys_copy = polys;
if (status != VoronoiDiagramStatus::NO_ISSUE_DETECTED) {
if (status == VoronoiDiagramStatus::MISSING_VORONOI_VERTEX)
BOOST_LOG_TRIVIAL(warning) << "Detected missing Voronoi vertex, input polygons will be rotated back and forth.";
else if (status == VoronoiDiagramStatus::NON_PLANAR_VORONOI_DIAGRAM)
BOOST_LOG_TRIVIAL(warning) << "Detected non-planar Voronoi diagram, input polygons will be rotated back and forth.";
else if (status == VoronoiDiagramStatus::VORONOI_EDGE_INTERSECTING_INPUT_SEGMENT)
BOOST_LOG_TRIVIAL(warning) << "Detected Voronoi edge intersecting input segment, input polygons will be rotated back and forth.";
std::tie(vertex_mapping, fixed_by_angle) = try_to_fix_degenerated_voronoi_diagram_by_rotation(voronoi_diagram, polys, polys_copy, segments, fix_angles);
VoronoiDiagramStatus status_after_fix = detect_voronoi_diagram_known_issues(voronoi_diagram, segments);
assert(status_after_fix == VoronoiDiagramStatus::NO_ISSUE_DETECTED);
if (status_after_fix == VoronoiDiagramStatus::MISSING_VORONOI_VERTEX)
BOOST_LOG_TRIVIAL(error) << "Detected missing Voronoi vertex even after the rotation of input.";
else if (status_after_fix == VoronoiDiagramStatus::NON_PLANAR_VORONOI_DIAGRAM)
BOOST_LOG_TRIVIAL(error) << "Detected non-planar Voronoi diagram even after the rotation of input.";
else if (status_after_fix == VoronoiDiagramStatus::VORONOI_EDGE_INTERSECTING_INPUT_SEGMENT)
BOOST_LOG_TRIVIAL(error) << "Detected Voronoi edge intersecting input segment even after the rotation of input.";
}
process_voronoi_diagram:
assert(this->graph.edges.empty() && this->graph.nodes.empty() && this->vd_edge_to_he_edge.empty() && this->vd_node_to_he_node.empty());
for (vd_t::cell_type cell : voronoi_diagram.cells()) {
for (const VD::cell_type &cell : voronoi_diagram.cells()) {
if (!cell.incident_edge())
continue; // There is no spoon
Point start_source_point;
Point end_source_point;
vd_t::edge_type* starting_voronoi_edge = nullptr;
vd_t::edge_type* ending_voronoi_edge = nullptr;
const VD::edge_type *starting_voronoi_edge = nullptr;
const VD::edge_type *ending_voronoi_edge = nullptr;
// Compute and store result in above variables
if (cell.contains_point()) {
@@ -727,7 +444,12 @@ process_voronoi_diagram:
continue;
} else {
assert(cell.contains_segment());
computeSegmentCellRange(cell, start_source_point, end_source_point, starting_voronoi_edge, ending_voronoi_edge, segments);
Geometry::SegmentCellRange<Point> cell_range = Geometry::VoronoiUtils::compute_segment_cell_range(cell, segments.cbegin(), segments.cend());
assert(cell_range.is_valid());
start_source_point = cell_range.segment_start_point;
end_source_point = cell_range.segment_end_point;
starting_voronoi_edge = cell_range.edge_begin;
ending_voronoi_edge = cell_range.edge_end;
}
if (!starting_voronoi_edge || !ending_voronoi_edge) {
@@ -736,68 +458,30 @@ process_voronoi_diagram:
}
// Copy start to end edge to graph
assert(Geometry::VoronoiUtils::is_in_range<coord_t>(*starting_voronoi_edge));
edge_t* prev_edge = nullptr;
assert(VoronoiUtils::p(starting_voronoi_edge->vertex1()).x() <= std::numeric_limits<coord_t>::max() && VoronoiUtils::p(starting_voronoi_edge->vertex1()).x() >= std::numeric_limits<coord_t>::lowest());
assert(VoronoiUtils::p(starting_voronoi_edge->vertex1()).y() <= std::numeric_limits<coord_t>::max() && VoronoiUtils::p(starting_voronoi_edge->vertex1()).y() >= std::numeric_limits<coord_t>::lowest());
transferEdge(start_source_point, VoronoiUtils::p(starting_voronoi_edge->vertex1()).cast<coord_t>(), *starting_voronoi_edge, prev_edge, start_source_point, end_source_point, segments);
transferEdge(start_source_point, Geometry::VoronoiUtils::to_point(starting_voronoi_edge->vertex1()).cast<coord_t>(), *starting_voronoi_edge, prev_edge, start_source_point, end_source_point, segments);
node_t* starting_node = vd_node_to_he_node[starting_voronoi_edge->vertex0()];
starting_node->data.distance_to_boundary = 0;
constexpr bool is_next_to_start_or_end = true;
graph.makeRib(prev_edge, start_source_point, end_source_point, is_next_to_start_or_end);
for (vd_t::edge_type* vd_edge = starting_voronoi_edge->next(); vd_edge != ending_voronoi_edge; vd_edge = vd_edge->next()) {
for (const VD::edge_type* vd_edge = starting_voronoi_edge->next(); vd_edge != ending_voronoi_edge; vd_edge = vd_edge->next()) {
assert(vd_edge->is_finite());
assert(VoronoiUtils::p(vd_edge->vertex0()).x() <= std::numeric_limits<coord_t>::max() && VoronoiUtils::p(vd_edge->vertex0()).x() >= std::numeric_limits<coord_t>::lowest());
assert(VoronoiUtils::p(vd_edge->vertex0()).y() <= std::numeric_limits<coord_t>::max() && VoronoiUtils::p(vd_edge->vertex0()).y() >= std::numeric_limits<coord_t>::lowest());
assert(VoronoiUtils::p(vd_edge->vertex1()).x() <= std::numeric_limits<coord_t>::max() && VoronoiUtils::p(vd_edge->vertex1()).x() >= std::numeric_limits<coord_t>::lowest());
assert(VoronoiUtils::p(vd_edge->vertex1()).y() <= std::numeric_limits<coord_t>::max() && VoronoiUtils::p(vd_edge->vertex1()).y() >= std::numeric_limits<coord_t>::lowest());
assert(Geometry::VoronoiUtils::is_in_range<coord_t>(*vd_edge));
Point v1 = VoronoiUtils::p(vd_edge->vertex0()).cast<coord_t>();
Point v2 = VoronoiUtils::p(vd_edge->vertex1()).cast<coord_t>();
Point v1 = Geometry::VoronoiUtils::to_point(vd_edge->vertex0()).cast<coord_t>();
Point v2 = Geometry::VoronoiUtils::to_point(vd_edge->vertex1()).cast<coord_t>();
transferEdge(v1, v2, *vd_edge, prev_edge, start_source_point, end_source_point, segments);
graph.makeRib(prev_edge, start_source_point, end_source_point, vd_edge->next() == ending_voronoi_edge);
}
assert(VoronoiUtils::p(starting_voronoi_edge->vertex0()).x() <= std::numeric_limits<coord_t>::max() && VoronoiUtils::p(starting_voronoi_edge->vertex0()).x() >= std::numeric_limits<coord_t>::lowest());
assert(VoronoiUtils::p(starting_voronoi_edge->vertex0()).y() <= std::numeric_limits<coord_t>::max() && VoronoiUtils::p(starting_voronoi_edge->vertex0()).y() >= std::numeric_limits<coord_t>::lowest());
transferEdge(VoronoiUtils::p(ending_voronoi_edge->vertex0()).cast<coord_t>(), end_source_point, *ending_voronoi_edge, prev_edge, start_source_point, end_source_point, segments);
transferEdge(Geometry::VoronoiUtils::to_point(ending_voronoi_edge->vertex0()).cast<coord_t>(), end_source_point, *ending_voronoi_edge, prev_edge, start_source_point, end_source_point, segments);
prev_edge->to->data.distance_to_boundary = 0;
}
// For some input polygons, as in GH issues #8474 and #8514 resulting Voronoi diagram is degenerated because it is not planar.
// When this degenerated Voronoi diagram is processed, the resulting half-edge structure contains some edges that don't have
// a twin edge. Based on this, we created a fast mechanism that detects those causes and tries to recompute the Voronoi
// diagram on slightly rotated input polygons that usually make the Voronoi generator generate a non-degenerated Voronoi diagram.
if (status == VoronoiDiagramStatus::NO_ISSUE_DETECTED && has_missing_twin_edge(this->graph)) {
BOOST_LOG_TRIVIAL(warning) << "Detected degenerated Voronoi diagram, input polygons will be rotated back and forth.";
status = VoronoiDiagramStatus::OTHER_TYPE_OF_VORONOI_DIAGRAM_DEGENERATION;
std::tie(vertex_mapping, fixed_by_angle) = try_to_fix_degenerated_voronoi_diagram_by_rotation(voronoi_diagram, polys, polys_copy, segments, fix_angles);
assert(!detect_missing_voronoi_vertex(voronoi_diagram, segments));
if (detect_missing_voronoi_vertex(voronoi_diagram, segments))
BOOST_LOG_TRIVIAL(error) << "Detected missing Voronoi vertex after the rotation of input.";
assert(Geometry::VoronoiUtilsCgal::is_voronoi_diagram_planar_intersection(voronoi_diagram));
this->graph.edges.clear();
this->graph.nodes.clear();
this->vd_edge_to_he_edge.clear();
this->vd_node_to_he_node.clear();
goto process_voronoi_diagram;
}
if (status != VoronoiDiagramStatus::NO_ISSUE_DETECTED) {
assert(!has_missing_twin_edge(this->graph));
if (has_missing_twin_edge(this->graph))
BOOST_LOG_TRIVIAL(error) << "Detected degenerated Voronoi diagram even after the rotation of input.";
}
if (status != VoronoiDiagramStatus::NO_ISSUE_DETECTED)
rotate_back_skeletal_trapezoidation_graph_after_fix(this->graph, fixed_by_angle, vertex_mapping);
#ifdef ARACHNE_DEBUG
assert(Geometry::VoronoiUtilsCgal::is_voronoi_diagram_planar_intersection(voronoi_diagram));

View File

@@ -11,7 +11,6 @@
#include <ankerl/unordered_dense.h>
#include <Arachne/utils/VoronoiUtils.hpp>
#include "utils/HalfEdgeGraph.hpp"
#include "utils/PolygonsSegmentIndex.hpp"
@@ -26,8 +25,9 @@
//#define ARACHNE_DEBUG
//#define ARACHNE_DEBUG_VORONOI
namespace Slic3r::Arachne
{
namespace Slic3r::Arachne {
using VD = Slic3r::Geometry::VoronoiDiagram;
/*!
* Main class of the dynamic beading strategies.
@@ -50,8 +50,6 @@ deposition modeling" by Kuipers et al.
*/
class SkeletalTrapezoidation
{
using pos_t = double;
using vd_t = boost::polygon::voronoi_diagram<pos_t>;
using graph_t = SkeletalTrapezoidationGraph;
using edge_t = STHalfEdge;
using node_t = STHalfEdgeNode;
@@ -83,7 +81,6 @@ class SkeletalTrapezoidation
public:
using Segment = PolygonsSegmentIndex;
using PointMap = ankerl::unordered_dense::map<Point, Point, PointHash>;
using NodeSet = ankerl::unordered_dense::set<node_t*>;
/*!
@@ -168,9 +165,9 @@ protected:
* mapping each voronoi VD edge to the corresponding halfedge HE edge
* In case the result segment is discretized, we map the VD edge to the *last* HE edge
*/
ankerl::unordered_dense::map<vd_t::edge_type*, edge_t*> vd_edge_to_he_edge;
ankerl::unordered_dense::map<vd_t::vertex_type*, node_t*> vd_node_to_he_node;
node_t& makeNode(vd_t::vertex_type& vd_node, Point p); //!< Get the node which the VD node maps to, or create a new mapping if there wasn't any yet.
ankerl::unordered_dense::map<const VD::edge_type *, edge_t *> vd_edge_to_he_edge;
ankerl::unordered_dense::map<const VD::vertex_type *, node_t *> vd_node_to_he_node;
node_t &makeNode(const VD::vertex_type &vd_node, Point p); //!< Get the node which the VD node maps to, or create a new mapping if there wasn't any yet.
/*!
* (Eventual) returned 'polylines per index' result (from generateToolpaths):
@@ -181,7 +178,7 @@ protected:
* Transfer an edge from the VD to the HE and perform discretization of parabolic edges (and vertex-vertex edges)
* \p prev_edge serves as input and output. May be null as input.
*/
void transferEdge(Point from, Point to, vd_t::edge_type& vd_edge, edge_t*& prev_edge, Point& start_source_point, Point& end_source_point, const std::vector<Segment>& segments);
void transferEdge(Point from, Point to, const VD::edge_type &vd_edge, edge_t *&prev_edge, Point &start_source_point, Point &end_source_point, const std::vector<Segment> &segments);
/*!
* Discretize a Voronoi edge that represents the medial axis of a vertex-
@@ -208,7 +205,7 @@ protected:
* \return A number of coordinates along the edge where the edge is broken
* up into discrete pieces.
*/
Points discretize(const vd_t::edge_type& segment, const std::vector<Segment>& segments);
Points discretize(const VD::edge_type& segment, const std::vector<Segment>& segments);
/*!
* Compute the range of line segments that surround a cell of the skeletal
@@ -234,33 +231,7 @@ protected:
* /return Whether the cell is inside of the polygon. If it's outside of the
* polygon we should skip processing it altogether.
*/
static bool computePointCellRange(vd_t::cell_type& cell, Point& start_source_point, Point& end_source_point, vd_t::edge_type*& starting_vd_edge, vd_t::edge_type*& ending_vd_edge, const std::vector<Segment>& segments);
/*!
* Compute the range of line segments that surround a cell of the skeletal
* graph that belongs to a line segment of the medial axis.
*
* This should only be used on cells that belong to a central line segment
* of the skeletal graph, e.g. trapezoid cells, not triangular cells.
*
* The resulting line segments is just the first and the last segment. They
* are linked to the neighboring segments, so you can iterate over the
* segments until you reach the last segment.
* \param cell The cell to compute the range of line segments for.
* \param[out] start_source_point The start point of the source segment of
* this cell.
* \param[out] end_source_point The end point of the source segment of this
* cell.
* \param[out] starting_vd_edge The edge of the Voronoi diagram where the
* loop around the cell starts.
* \param[out] ending_vd_edge The edge of the Voronoi diagram where the loop
* around the cell ends.
* \param points All vertices of the input Polygons.
* \param segments All edges of the input Polygons.
* /return Whether the cell is inside of the polygon. If it's outside of the
* polygon we should skip processing it altogether.
*/
static void computeSegmentCellRange(vd_t::cell_type& cell, Point& start_source_point, Point& end_source_point, vd_t::edge_type*& starting_vd_edge, vd_t::edge_type*& ending_vd_edge, const std::vector<Segment>& segments);
static bool computePointCellRange(const VD::cell_type &cell, Point &start_source_point, Point &end_source_point, const VD::edge_type *&starting_vd_edge, const VD::edge_type *&ending_vd_edge, const std::vector<Segment> &segments);
/*!
* For VD cells associated with an input polygon vertex, we need to separate the node at the end and start of the cell into two
@@ -603,7 +574,7 @@ protected:
*/
void generateLocalMaximaSingleBeads();
friend bool detect_voronoi_edge_intersecting_input_segment(const Geometry::VoronoiDiagram &voronoi_diagram, const std::vector<VoronoiUtils::Segment> &segments);
friend bool detect_voronoi_edge_intersecting_input_segment(const VD &voronoi_diagram, const std::vector<Segment> &segments);
};
} // namespace Slic3r::Arachne

View File

@@ -156,7 +156,6 @@ struct PathsPointIndexLocator
}
};
using PolygonsPointIndexLocator = PathsPointIndexLocator<Polygons>;
}//namespace Slic3r::Arachne

View File

@@ -27,5 +27,24 @@ public:
} // namespace Slic3r::Arachne
namespace boost::polygon {
template<> struct geometry_concept<Slic3r::Arachne::PolygonsSegmentIndex>
{
typedef segment_concept type;
};
template<> struct segment_traits<Slic3r::Arachne::PolygonsSegmentIndex>
{
typedef coord_t coordinate_type;
typedef Slic3r::Point point_type;
static inline point_type get(const Slic3r::Arachne::PolygonsSegmentIndex &CSegment, direction_1d dir)
{
return dir.to_int() ? CSegment.to() : CSegment.from();
}
};
} // namespace boost::polygon
#endif//UTILS_POLYGONS_SEGMENT_INDEX_H

View File

@@ -1,251 +0,0 @@
//Copyright (c) 2021 Ultimaker B.V.
//CuraEngine is released under the terms of the AGPLv3 or higher.
#include <stack>
#include <optional>
#include <boost/log/trivial.hpp>
#include "linearAlg2D.hpp"
#include "VoronoiUtils.hpp"
namespace Slic3r::Arachne
{
Vec2i64 VoronoiUtils::p(const vd_t::vertex_type *node)
{
const double x = node->x();
const double y = node->y();
assert(std::isfinite(x) && std::isfinite(y));
assert(x <= double(std::numeric_limits<int64_t>::max()) && x >= std::numeric_limits<int64_t>::lowest());
assert(y <= double(std::numeric_limits<int64_t>::max()) && y >= std::numeric_limits<int64_t>::lowest());
return {int64_t(x + 0.5 - (x < 0)), int64_t(y + 0.5 - (y < 0))}; // Round to the nearest integer coordinates.
}
Point VoronoiUtils::getSourcePoint(const vd_t::cell_type& cell, const std::vector<Segment>& segments)
{
assert(cell.contains_point());
if(!cell.contains_point())
BOOST_LOG_TRIVIAL(debug) << "Voronoi cell doesn't contain a source point!";
switch (cell.source_category()) {
case boost::polygon::SOURCE_CATEGORY_SINGLE_POINT:
assert(false && "Voronoi diagram is always constructed using segments, so cell.source_category() shouldn't be SOURCE_CATEGORY_SINGLE_POINT!\n");
BOOST_LOG_TRIVIAL(error) << "Voronoi diagram is always constructed using segments, so cell.source_category() shouldn't be SOURCE_CATEGORY_SINGLE_POINT!";
break;
case boost::polygon::SOURCE_CATEGORY_SEGMENT_START_POINT:
assert(cell.source_index() < segments.size());
return segments[cell.source_index()].to();
break;
case boost::polygon::SOURCE_CATEGORY_SEGMENT_END_POINT:
assert(cell.source_index() < segments.size());
return segments[cell.source_index()].from();
break;
default:
assert(false && "getSourcePoint should only be called on point cells!\n");
break;
}
assert(false && "cell.source_category() is equal to an invalid value!\n");
BOOST_LOG_TRIVIAL(error) << "cell.source_category() is equal to an invalid value!";
return {};
}
PolygonsPointIndex VoronoiUtils::getSourcePointIndex(const vd_t::cell_type& cell, const std::vector<Segment>& segments)
{
assert(cell.contains_point());
if(!cell.contains_point())
BOOST_LOG_TRIVIAL(debug) << "Voronoi cell doesn't contain a source point!";
assert(cell.source_category() != boost::polygon::SOURCE_CATEGORY_SINGLE_POINT);
switch (cell.source_category()) {
case boost::polygon::SOURCE_CATEGORY_SEGMENT_START_POINT: {
assert(cell.source_index() < segments.size());
PolygonsPointIndex ret = segments[cell.source_index()];
++ret;
return ret;
break;
}
case boost::polygon::SOURCE_CATEGORY_SEGMENT_END_POINT: {
assert(cell.source_index() < segments.size());
return segments[cell.source_index()];
break;
}
default:
assert(false && "getSourcePoint should only be called on point cells!\n");
break;
}
PolygonsPointIndex ret = segments[cell.source_index()];
return ++ret;
}
const VoronoiUtils::Segment &VoronoiUtils::getSourceSegment(const vd_t::cell_type &cell, const std::vector<Segment> &segments)
{
assert(cell.contains_segment());
if (!cell.contains_segment())
BOOST_LOG_TRIVIAL(debug) << "Voronoi cell doesn't contain a source segment!";
return segments[cell.source_index()];
}
class PointMatrix
{
public:
double matrix[4];
PointMatrix()
{
matrix[0] = 1;
matrix[1] = 0;
matrix[2] = 0;
matrix[3] = 1;
}
PointMatrix(double rotation)
{
rotation = rotation / 180 * M_PI;
matrix[0] = cos(rotation);
matrix[1] = -sin(rotation);
matrix[2] = -matrix[1];
matrix[3] = matrix[0];
}
PointMatrix(const Point p)
{
matrix[0] = p.x();
matrix[1] = p.y();
double f = sqrt((matrix[0] * matrix[0]) + (matrix[1] * matrix[1]));
matrix[0] /= f;
matrix[1] /= f;
matrix[2] = -matrix[1];
matrix[3] = matrix[0];
}
static PointMatrix scale(double s)
{
PointMatrix ret;
ret.matrix[0] = s;
ret.matrix[3] = s;
return ret;
}
Point apply(const Point p) const
{
return Point(coord_t(p.x() * matrix[0] + p.y() * matrix[1]), coord_t(p.x() * matrix[2] + p.y() * matrix[3]));
}
Point unapply(const Point p) const
{
return Point(coord_t(p.x() * matrix[0] + p.y() * matrix[2]), coord_t(p.x() * matrix[1] + p.y() * matrix[3]));
}
};
Points VoronoiUtils::discretizeParabola(const Point& p, const Segment& segment, Point s, Point e, coord_t approximate_step_size, float transitioning_angle)
{
Points discretized;
// x is distance of point projected on the segment ab
// xx is point projected on the segment ab
const Point a = segment.from();
const Point b = segment.to();
const Point ab = b - a;
const Point as = s - a;
const Point ae = e - a;
const coord_t ab_size = ab.cast<int64_t>().norm();
const coord_t sx = as.cast<int64_t>().dot(ab.cast<int64_t>()) / ab_size;
const coord_t ex = ae.cast<int64_t>().dot(ab.cast<int64_t>()) / ab_size;
const coord_t sxex = ex - sx;
assert((as.cast<int64_t>().dot(ab.cast<int64_t>()) / int64_t(ab_size)) <= std::numeric_limits<coord_t>::max());
assert((ae.cast<int64_t>().dot(ab.cast<int64_t>()) / int64_t(ab_size)) <= std::numeric_limits<coord_t>::max());
const Point ap = p - a;
const coord_t px = ap.cast<int64_t>().dot(ab.cast<int64_t>()) / ab_size;
assert((ap.cast<int64_t>().dot(ab.cast<int64_t>()) / int64_t(ab_size)) <= std::numeric_limits<coord_t>::max());
Point pxx;
Line(a, b).distance_to_infinite_squared(p, &pxx);
const Point ppxx = pxx - p;
const coord_t d = ppxx.cast<int64_t>().norm();
const PointMatrix rot = PointMatrix(perp(ppxx));
if (d == 0)
{
discretized.emplace_back(s);
discretized.emplace_back(e);
return discretized;
}
const float marking_bound = atan(transitioning_angle * 0.5);
int64_t msx = - marking_bound * int64_t(d); // projected marking_start
int64_t mex = marking_bound * int64_t(d); // projected marking_end
assert(msx <= std::numeric_limits<coord_t>::max());
assert(double(msx) * double(msx) <= double(std::numeric_limits<int64_t>::max()));
assert(mex <= std::numeric_limits<coord_t>::max());
assert(double(msx) * double(msx) / double(2 * d) + double(d / 2) <= std::numeric_limits<coord_t>::max());
const coord_t marking_start_end_h = msx * msx / (2 * d) + d / 2;
Point marking_start = rot.unapply(Point(coord_t(msx), marking_start_end_h)) + pxx;
Point marking_end = rot.unapply(Point(coord_t(mex), marking_start_end_h)) + pxx;
const int dir = (sx > ex) ? -1 : 1;
if (dir < 0)
{
std::swap(marking_start, marking_end);
std::swap(msx, mex);
}
bool add_marking_start = msx * int64_t(dir) > int64_t(sx - px) * int64_t(dir) && msx * int64_t(dir) < int64_t(ex - px) * int64_t(dir);
bool add_marking_end = mex * int64_t(dir) > int64_t(sx - px) * int64_t(dir) && mex * int64_t(dir) < int64_t(ex - px) * int64_t(dir);
const Point apex = rot.unapply(Point(0, d / 2)) + pxx;
bool add_apex = int64_t(sx - px) * int64_t(dir) < 0 && int64_t(ex - px) * int64_t(dir) > 0;
assert(!(add_marking_start && add_marking_end) || add_apex);
if(add_marking_start && add_marking_end && !add_apex)
{
BOOST_LOG_TRIVIAL(warning) << "Failing to discretize parabola! Must add an apex or one of the endpoints.";
}
const coord_t step_count = static_cast<coord_t>(static_cast<float>(std::abs(ex - sx)) / approximate_step_size + 0.5);
discretized.emplace_back(s);
for (coord_t step = 1; step < step_count; step++)
{
assert(double(sxex) * double(step) <= double(std::numeric_limits<int64_t>::max()));
const int64_t x = int64_t(sx) + int64_t(sxex) * int64_t(step) / int64_t(step_count) - int64_t(px);
assert(double(x) * double(x) <= double(std::numeric_limits<int64_t>::max()));
assert(double(x) * double(x) / double(2 * d) + double(d / 2) <= double(std::numeric_limits<int64_t>::max()));
const int64_t y = int64_t(x) * int64_t(x) / int64_t(2 * d) + int64_t(d / 2);
if (add_marking_start && msx * int64_t(dir) < int64_t(x) * int64_t(dir))
{
discretized.emplace_back(marking_start);
add_marking_start = false;
}
if (add_apex && int64_t(x) * int64_t(dir) > 0)
{
discretized.emplace_back(apex);
add_apex = false; // only add the apex just before the
}
if (add_marking_end && mex * int64_t(dir) < int64_t(x) * int64_t(dir))
{
discretized.emplace_back(marking_end);
add_marking_end = false;
}
assert(x <= std::numeric_limits<coord_t>::max() && x >= std::numeric_limits<coord_t>::lowest());
assert(y <= std::numeric_limits<coord_t>::max() && y >= std::numeric_limits<coord_t>::lowest());
const Point result = rot.unapply(Point(x, y)) + pxx;
discretized.emplace_back(result);
}
if (add_apex)
{
discretized.emplace_back(apex);
}
if (add_marking_end)
{
discretized.emplace_back(marking_end);
}
discretized.emplace_back(e);
return discretized;
}
}//namespace Slic3r::Arachne

View File

@@ -1,47 +0,0 @@
//Copyright (c) 2020 Ultimaker B.V.
//CuraEngine is released under the terms of the AGPLv3 or higher.
#ifndef UTILS_VORONOI_UTILS_H
#define UTILS_VORONOI_UTILS_H
#include <vector>
#include <boost/polygon/voronoi.hpp>
#include "PolygonsSegmentIndex.hpp"
namespace Slic3r::Arachne
{
/*!
*/
class VoronoiUtils
{
public:
using Segment = PolygonsSegmentIndex;
using voronoi_data_t = double;
using vd_t = boost::polygon::voronoi_diagram<voronoi_data_t>;
static Point getSourcePoint(const vd_t::cell_type &cell, const std::vector<Segment> &segments);
static const Segment &getSourceSegment(const vd_t::cell_type &cell, const std::vector<Segment> &segments);
static PolygonsPointIndex getSourcePointIndex(const vd_t::cell_type &cell, const std::vector<Segment> &segments);
static Vec2i64 p(const vd_t::vertex_type *node);
/*!
* Discretize a parabola based on (approximate) step size.
* The \p approximate_step_size is measured parallel to the \p source_segment, not along the parabola.
*/
static Points discretizeParabola(const Point &source_point, const Segment &source_segment, Point start, Point end, coord_t approximate_step_size, float transitioning_angle);
static inline bool is_finite(const VoronoiUtils::vd_t::vertex_type &vertex)
{
return std::isfinite(vertex.x()) && std::isfinite(vertex.y());
}
};
} // namespace Slic3r::Arachne
#endif // UTILS_VORONOI_UTILS_H

View File

@@ -58,7 +58,7 @@ class DefaultArrangerCtl : public Arranger<ArrItem>::Ctl {
public:
DefaultArrangerCtl() = default;
explicit DefaultArrangerCtl(ArrangeTaskBase::Ctl &ctl) : taskctl{&ctl} {}
explicit DefaultArrangerCtl(ArrangeTaskCtl &ctl) : taskctl{&ctl} {}
void update_status(int st) override
{

View File

@@ -325,7 +325,7 @@ class DefaultArranger: public Arranger<ArrItem> {
// a pure RectangleBed with inner-fit polygon calculation.
if (!with_wipe_tower &&
m_settings.get_arrange_strategy() == ArrangeSettingsView::asAuto &&
std::is_convertible_v<Bed, RectangleBed>) {
IsRectangular<Bed>) {
PackStrategyNFP base_strategy{std::move(kernel), ep, Accuracy, stop_cond};
RectangleOverfitPackingStrategy final_strategy{std::move(base_strategy)};

View File

@@ -181,6 +181,11 @@ inline ExPolygons to_expolygons(const ArrangeBed &bed)
ArrangeBed to_arrange_bed(const Points &bedpts);
template<class Bed, class En = void> struct IsRectangular_ : public std::false_type {};
template<> struct IsRectangular_<RectangleBed>: public std::true_type {};
template<> struct IsRectangular_<BoundingBox>: public std::true_type {};
template<class Bed> static constexpr bool IsRectangular = IsRectangular_<Bed>::value;
} // namespace arr2
inline BoundingBox &bounding_box(BoundingBox &bb) { return bb; }

View File

@@ -51,9 +51,9 @@ protected:
public:
TMArrangeKernel() = default;
TMArrangeKernel(Vec2crd gravity_center, size_t itm_cnt, double bedarea = NaNd)
: sink{gravity_center}
, m_bin_area(bedarea)
: m_bin_area(bedarea)
, m_item_cnt{itm_cnt}
, sink{gravity_center}
{}
TMArrangeKernel(size_t itm_cnt, double bedarea = NaNd)
@@ -87,8 +87,6 @@ public:
// Will hold the resulting score
double score = 0;
// Density is the pack density: how big is the arranged pile
double density = 0;
// Distinction of cases for the arrangement scene
enum e_cases {
@@ -96,8 +94,6 @@ public:
// OR for all items in a small-only scene.
BIG_ITEM,
// This branch is for the last big item in a mixed scene
LAST_BIG_ITEM,
// For small items in a mixed scene.
SMALL_ITEM,
@@ -109,10 +105,8 @@ public:
bool bigitems = is_big(envelope_area(item)) || m_rtree.empty();
if (is_wt)
compute_case = WIPE_TOWER;
else if (bigitems && m_rem_cnt > 0)
else if (bigitems)
compute_case = BIG_ITEM;
else if (bigitems && m_rem_cnt == 0)
compute_case = LAST_BIG_ITEM;
else
compute_case = SMALL_ITEM;
@@ -129,20 +123,8 @@ public:
Point top_left{minc.x(), maxc.y()};
Point bottom_right{maxc.x(), minc.y()};
// Now the distance of the gravity center will be calculated to the
// five anchor points and the smallest will be chosen.
std::array<double, 5> dists;
auto cc = fullbb.center(); // The gravity center
dists[0] = (minc - cc).cast<double>().norm();
dists[1] = (maxc - cc).cast<double>().norm();
dists[2] = (itmcntr - cc).template cast<double>().norm();
dists[3] = (top_left - cc).cast<double>().norm();
dists[4] = (bottom_right - cc).cast<double>().norm();
// The smalles distance from the arranged pile center:
double dist = norm(*(std::min_element(dists.begin(), dists.end())));
double bindist = norm((ibb.center() - active_sink).template cast<double>().norm());
dist = 0.8 * dist + 0.2 * bindist;
// The smallest distance from the arranged pile center:
double dist = norm((itmcntr - m_pilebb.center()).template cast<double>().norm());
// Prepare a variable for the alignment score.
// This will indicate: how well is the candidate item
@@ -150,7 +132,7 @@ public:
// with all neighbors and return the score for the best
// alignment. So it is enough for the candidate to be
// aligned with only one item.
auto alignment_score = 1.0;
auto alignment_score = 1.;
auto query = bgi::intersects(ibb);
auto& index = is_big(envelope_area(item)) ? m_rtree : m_smallsrtree;
@@ -170,33 +152,24 @@ public:
auto bb = p.bb;
bb.merge(ibb);
auto bbarea = area(bb);
auto ascore = 1.0 - (fixed_area(item) + parea) / bbarea;
auto ascore = 1.0 - (area(fixed_bounding_box(item)) + area(p.bb)) / bbarea;
if(ascore < alignment_score)
alignment_score = ascore;
}
}
auto fullbbsz = fullbb.size();
density = std::sqrt(norm(fullbbsz.x()) * norm(fullbbsz.y()));
double R = double(m_rem_cnt) / (m_item_cnt);
R = std::pow(R, 1./3.);
// The final mix of the score is the balance between the
// distance from the full pile center, the pack density and
// the alignment with the neighbors
if (result.empty())
score = 0.50 * dist + 0.50 * density;
else
// Let the density matter more when fewer objects remain
score = 0.50 * dist + (1.0 - R) * 0.20 * density +
0.30 * alignment_score;
score = 0.6 * dist + 0.1 * alignment_score + (1.0 - R) * (0.3 * dist) + R * 0.3 * alignment_score;
break;
}
case LAST_BIG_ITEM: {
score = norm((itmcntr - m_pilebb.center()).template cast<double>().norm());
break;
}
case SMALL_ITEM: {
// Here there are the small items that should be placed around the
// already processed bigger items.
@@ -236,8 +209,11 @@ public:
if (m_item_cnt == 0)
m_item_cnt = m_rem_cnt + fixed.size() + 1;
if (std::isnan(m_bin_area))
m_bin_area = area(bed);
if (std::isnan(m_bin_area)) {
auto sz = bounding_box(bed).size();
m_bin_area = scaled<double>(unscaled(sz.x()) * unscaled(sz.y()));
}
m_norm = std::sqrt(m_bin_area);
@@ -245,7 +221,7 @@ public:
m_itemstats.reserve(fixed.size());
m_rtree.clear();
m_smallsrtree.clear();
m_pilebb = {};
m_pilebb = {active_sink, active_sink};
unsigned idx = 0;
for (auto &fixitem : fixed) {
auto fixitmbb = fixed_bounding_box(fixitem);

View File

@@ -101,6 +101,9 @@ ExPolygons to_expolygons(const SegmentedRectangleBed<Args...> &bed)
return to_expolygons(RectangleBed{bed.bb});
}
template<class SegB>
struct IsRectangular_<SegB, std::enable_if_t<IsSegmentedBed<SegB>, void>> : public std::true_type
{};
}} // namespace Slic3r::arr2
#endif // SEGMENTEDRECTANGLEBED_HPP

View File

@@ -115,21 +115,13 @@ ArrangeTask<ArrItem>::process_native(Ctl &ctl)
} subctl{ctl, *this};
auto fixed_items = printable.unselected;
// static (unselected) unprintable objects should not be overlapped by
// movable and printable objects
std::copy(unprintable.unselected.begin(),
unprintable.unselected.end(),
std::back_inserter(fixed_items));
arranger->arrange(printable.selected, fixed_items, bed, subctl);
arranger->arrange(printable.selected, printable.unselected, bed, subctl);
std::vector<int> printable_bed_indices =
get_bed_indices(crange(printable.selected), crange(printable.unselected));
// If there are no printables, leave the physical bed empty
constexpr int SearchFrom = 1;
static constexpr int SearchFrom = 1;
// Unprintable items should go to the first logical (!) bed not containing
// any printable items

View File

@@ -31,7 +31,29 @@ public:
: BoundingBoxBase(points.begin(), points.end())
{}
void reset() { this->defined = false; this->min = PointType::Zero(); this->max = PointType::Zero(); }
void reset()
{
this->defined = false;
this->min = PointType::Zero();
this->max = PointType::Zero();
}
// B66
Polygon polygon(bool is_scaled = false) const
{
Polygon polygon;
polygon.points.clear();
polygon.points.resize(4);
double scale_factor = 1 / (is_scaled ? SCALING_FACTOR : 1);
polygon.points[0](0) = this->min(0) * scale_factor;
polygon.points[0](1) = this->min(1) * scale_factor;
polygon.points[1](0) = this->max(0) * scale_factor;
polygon.points[1](1) = this->min(1) * scale_factor;
polygon.points[2](0) = this->max(0) * scale_factor;
polygon.points[2](1) = this->max(1) * scale_factor;
polygon.points[3](0) = this->min(0) * scale_factor;
polygon.points[3](1) = this->max(1) * scale_factor;
return polygon;
};
void merge(const PointType &point);
void merge(const PointsType &points);
void merge(const BoundingBoxBase<PointType, PointsType> &bb);
@@ -142,6 +164,15 @@ public:
return this->min.x() < other.max.x() && this->max.x() > other.min.x() && this->min.y() < other.max.y() && this->max.y() > other.min.y() &&
this->min.z() < other.max.z() && this->max.z() > other.min.z();
}
// Shares some boundary.
bool shares_boundary(const BoundingBox3Base<PointType>& other) const {
return is_approx(this->min.x(), other.max.x()) ||
is_approx(this->max.x(), other.min.x()) ||
is_approx(this->min.y(), other.max.y()) ||
is_approx(this->max.y(), other.min.y()) ||
is_approx(this->min.z(), other.max.z()) ||
is_approx(this->max.z(), other.min.z());
}
};
// Will prevent warnings caused by non existing definition of template in hpp

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