diff --git a/cmake/modules/MacOSXBundleInfo.plist.in b/cmake/modules/MacOSXBundleInfo.plist.in index aa9aa10..1621c8b 100644 --- a/cmake/modules/MacOSXBundleInfo.plist.in +++ b/cmake/modules/MacOSXBundleInfo.plist.in @@ -2,30 +2,35 @@ - CFBundleDevelopmentRegion - English - CFBundleExecutable - ${MACOSX_BUNDLE_EXECUTABLE_NAME} - CFBundleGetInfoString - ${MACOSX_BUNDLE_INFO_STRING} - CFBundleIconFile - ${MACOSX_BUNDLE_ICON_FILE} - CFBundleIdentifier - com.qiditech.qidi-studio - CFBundleInfoDictionaryVersion - 6.0 - CFBundleLongVersionString - ${MACOSX_BUNDLE_LONG_VERSION_STRING} - CFBundleName - ${MACOSX_BUNDLE_BUNDLE_NAME} - CFBundlePackageType - APPL - CFBundleShortVersionString - ${MACOSX_BUNDLE_SHORT_VERSION_STRING} - CFBundleSignature - ???? - CFBundleVersion - ${MACOSX_BUNDLE_BUNDLE_VERSION} + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${MACOSX_BUNDLE_EXECUTABLE_NAME} + CFBundleGetInfoString + ${MACOSX_BUNDLE_INFO_STRING} + CFBundleIconFile + ${MACOSX_BUNDLE_ICON_FILE} + CFBundleIdentifier + com.qiditech.qidi-studio + CFBundleInfoDictionaryVersion + 6.0 + CFBundleLongVersionString + ${MACOSX_BUNDLE_LONG_VERSION_STRING} + CFBundleName + ${MACOSX_BUNDLE_BUNDLE_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + ${MACOSX_BUNDLE_SHORT_VERSION_STRING} + CFBundleSignature + ???? + CFBundleVersion + ${MACOSX_BUNDLE_BUNDLE_VERSION} + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + CFBundleURLTypes diff --git a/deps/Boost/Boost.cmake b/deps/Boost/Boost.cmake index 16d4a32..5d37030 100644 --- a/deps/Boost/Boost.cmake +++ b/deps/Boost/Boost.cmake @@ -129,7 +129,7 @@ list(APPEND _patch_command COMMAND git init && ${PATCH_CMD} ${CMAKE_CURRENT_LIST ExternalProject_Add( dep_Boost #URL "https://boostorg.jfrog.io/artifactory/main/release/1.78.0/source/boost_1_78_0.zip" - URL "https://github.com/qiditech/boost/releases/download/1.78.0/boost_1_78_0.zip" + URL "https://github.com/bambulab/boost/releases/download/1.78.0/boost_1_78_0.zip" URL_HASH SHA256=f22143b5528e081123c3c5ed437e92f648fe69748e95fa6e2bd41484e2986cc3 DOWNLOAD_DIR ${DEP_DOWNLOAD_DIR}/Boost CONFIGURE_COMMAND "${_bootstrap_cmd}" diff --git a/deps/FFMPEG/FFMPEG.cmake b/deps/FFMPEG/FFMPEG.cmake index 080d6a9..1b169da 100644 --- a/deps/FFMPEG/FFMPEG.cmake +++ b/deps/FFMPEG/FFMPEG.cmake @@ -4,7 +4,7 @@ if (MSVC) set(_dstdir ${DESTDIR}/usr/local) set(_source_dir "${CMAKE_BINARY_DIR}/dep_FFMPEG-prefix/src/dep_FFMPEG") ExternalProject_Add(dep_FFMPEG - URL https://github.com/qiditech/ffmpeg_prebuilts/releases/download/7.0.2/7.0.2_msvc.zip + URL https://github.com/bambulab/ffmpeg_prebuilts/releases/download/7.0.2/7.0.2_msvc.zip URL_HASH SHA256=DF44AE6B97CE84C720695AE7F151B4A9654915D1841C68F10D62A1189E0E7181 DOWNLOAD_DIR ${DEP_DOWNLOAD_DIR}/FFMPEG CONFIGURE_COMMAND "" diff --git a/deps/GMP/GMP.cmake b/deps/GMP/GMP.cmake index 90209fd..468c15a 100644 --- a/deps/GMP/GMP.cmake +++ b/deps/GMP/GMP.cmake @@ -43,7 +43,7 @@ else () endif () ExternalProject_Add(dep_GMP - URL https://github.com/qiditech/gmp/archive/refs/tags/6.2.1.tar.gz + URL https://github.com/bambulab/gmp/archive/refs/tags/6.2.1.tar.gz URL_HASH SHA256=705ae57ee2014b2c6fc0f572c85ee43276b99b6b256ee16c1a9d3a8c4e3609d5 DOWNLOAD_DIR ${DEP_DOWNLOAD_DIR}/GMP BUILD_IN_SOURCE ON diff --git a/deps/OCCT/0001-OCCT-fix.patch b/deps/OCCT/0001-OCCT-fix.patch index d0de170..6dba39d 100644 --- a/deps/OCCT/0001-OCCT-fix.patch +++ b/deps/OCCT/0001-OCCT-fix.patch @@ -195,3 +195,27 @@ index 5ae9899f..0a17372b 100644 if (!myFTLib->IsValid()) { +From 7236e83dcc1e7284e66dc61e612154617ef715d6 Mon Sep 17 00:00:00 2001 +From: dpasukhi +Date: Tue, 27 Aug 2024 11:33:29 +0100 +Subject: [PATCH] 0033808: Coding - FreeType Use unsigned point and contour + indexing in `FT_Outline` + +Changes to auto instead of specific type +--- + src/StdPrs/StdPrs_BRepFont.cxx | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/StdPrs/StdPrs_BRepFont.cxx b/src/StdPrs/StdPrs_BRepFont.cxx +index ab2d9b3c9f..cd701879b1 100644 +--- a/src/StdPrs/StdPrs_BRepFont.cxx ++++ b/src/StdPrs/StdPrs_BRepFont.cxx +@@ -457,7 +457,7 @@ Standard_Boolean StdPrs_BRepFont::renderGlyph (const Standard_Utf32Char theChar, + for (short aContour = 0, aStartIndex = 0; aContour < anOutline->n_contours; ++aContour) + { + const FT_Vector* aPntList = &anOutline->points[aStartIndex]; +- const char* aTags = &anOutline->tags[aStartIndex]; ++ const auto* aTags = &anOutline->tags[aStartIndex]; + const short anEndIndex = anOutline->contours[aContour]; + const short aPntsNb = (anEndIndex - aStartIndex) + 1; + aStartIndex = anEndIndex + 1; \ No newline at end of file diff --git a/deps/OCCT/OCCT.cmake b/deps/OCCT/OCCT.cmake index 98be7bc..6bed3a1 100644 --- a/deps/OCCT/OCCT.cmake +++ b/deps/OCCT/OCCT.cmake @@ -8,7 +8,7 @@ qidistudio_add_cmake_project(OCCT URL https://github.com/Open-Cascade-SAS/OCCT/archive/refs/tags/V7_6_0.zip URL_HASH SHA256=28334f0e98f1b1629799783e9b4d21e05349d89e695809d7e6dfa45ea43e1dbc #PATCH_COMMAND ${PATCH_CMD} ${CMAKE_CURRENT_LIST_DIR}/0001-OCCT-fix.patch - PATCH_COMMAND ${GIT_EXECUTABLE} apply --directory deps/build/dep_OCCT-prefix/src/dep_OCCT --verbose --ignore-space-change --whitespace=fix ${CMAKE_CURRENT_LIST_DIR}/0001-OCCT-fix.patch + PATCH_COMMAND ${GIT_EXECUTABLE} apply --verbose --ignore-space-change --whitespace=fix ${CMAKE_CURRENT_LIST_DIR}/0001-OCCT-fix.patch #DEPENDS dep_Boost #DEPENDS dep_FREETYPE CMAKE_ARGS diff --git a/deps/OpenCV/OpenCV.cmake b/deps/OpenCV/OpenCV.cmake index bd6c1a8..36860e3 100644 --- a/deps/OpenCV/OpenCV.cmake +++ b/deps/OpenCV/OpenCV.cmake @@ -7,7 +7,7 @@ endif () qidistudio_add_cmake_project(OpenCV URL https://github.com/opencv/opencv/archive/refs/tags/4.6.0.tar.gz URL_HASH SHA256=1ec1cba65f9f20fe5a41fda1586e01c70ea0c9a6d7b67c9e13edf0cfe2239277 - PATCH_COMMAND ${GIT_EXECUTABLE} apply --directory deps/build/dep_OpenCV-prefix/src/dep_OpenCV --verbose --ignore-space-change --whitespace=fix ${CMAKE_CURRENT_LIST_DIR}/0001-OpenCV-fix.patch + PATCH_COMMAND ${GIT_EXECUTABLE} apply --verbose --ignore-space-change --whitespace=fix ${CMAKE_CURRENT_LIST_DIR}/0001-OpenCV-fix.patch CMAKE_ARGS -DBUILD_SHARED_LIBS=0 -DBUILD_PERE_TESTS=OFF diff --git a/deps/wxWidgets/wxWidgets.cmake b/deps/wxWidgets/wxWidgets.cmake index 978b294..595ce6d 100644 --- a/deps/wxWidgets/wxWidgets.cmake +++ b/deps/wxWidgets/wxWidgets.cmake @@ -23,7 +23,7 @@ endif () # endif () qidistudio_add_cmake_project(wxWidgets - GIT_REPOSITORY "https://github.com/qiditech/wxWidgets" + GIT_REPOSITORY "https://github.com/bambulab/wxWidgets" GIT_TAG master DEPENDS ${PNG_PKG} ${ZLIB_PKG} ${EXPAT_PKG} ${TIFF_PKG} ${JPEG_PKG} CMAKE_ARGS diff --git a/qds_test_tools/qds_gcode_checker/GCodeChecker.cpp b/qds_test_tools/qds_gcode_checker/GCodeChecker.cpp index b49475d..6d35f70 100644 --- a/qds_test_tools/qds_gcode_checker/GCodeChecker.cpp +++ b/qds_test_tools/qds_gcode_checker/GCodeChecker.cpp @@ -7,8 +7,9 @@ namespace QIDIStudio { //QDS: only check wodth when dE is longer than this value const double CHECK_WIDTH_E_THRESHOLD = 0.0025; -const double WIDTH_THRESHOLD = 0.02; +const double WIDTH_THRESHOLD = 0.05; const double RADIUS_THRESHOLD = 0.005; +const double MULTI_NOZZLE_TEMP_THRESHOLD = 100; const double filament_diameter = 1.75; const double Pi = 3.14159265358979323846; @@ -28,6 +29,8 @@ const std::string nozzle_temperature_initial_layer_Tag = " nozzle_temperature_i const std::string Z_HEIGHT_TAG = " Z_HEIGHT: "; const std::string Initial_Layer_Ptint_Height_Tag = " initial_layer_print_height ="; const std::string Line_Width_Tag = " line_width ="; +const std::string Filament_Map_Tag = " filament_map ="; +const std::string Physical_Extruder_Map_Tag = " physical_extruder_map ="; GCodeCheckResult GCodeChecker::parse_file(const std::string& path) { @@ -38,7 +41,11 @@ GCodeCheckResult GCodeChecker::parse_file(const std::string& path) } std::string line_raw; std::string line; + int line_number = 0; + + while (std::getline(file, line_raw)) { + line_number++; const char *c = line_raw.c_str(); c = skip_whitespaces(c); if (std::toupper(*c) == 'N') @@ -46,7 +53,8 @@ GCodeCheckResult GCodeChecker::parse_file(const std::string& path) c = skip_whitespaces(c); line = c; if (parse_line(line) != GCodeCheckResult::Success) { - std::cout << "Failed to parse line " << line_raw << std::endl; + std::cerr << "Failed to parse line " << line_number + << ": " << line_raw << std::endl; return GCodeCheckResult::ParseFailed; } } @@ -115,17 +123,39 @@ GCodeCheckResult GCodeChecker::parse_comment(GCodeLine& line) if (starts_with(comment, Extrusion_Role_Tag)) { m_role = string_to_role(comment.substr(Extrusion_Role_Tag.length())); check_gap_infill_width = false; - if (m_role == erExternalPerimeter) { - if (z_height == initial_layer_height && nozzle_temp != nozzle_temperature_initial_layer[filament_id]) { - std::cout << "invalid filament nozzle initial layer temperature comment with invalid value!" << std::endl; - return GCodeCheckResult::ParseFailed; - } - if (z_height != initial_layer_height && nozzle_temp != nozzle_temperature[filament_id]) { - std::cout << "invalid filament nozzle temperature comment with invalid value!" << std::endl; - return GCodeCheckResult::ParseFailed; + double check_nozzle_temp = 0.0f; + if (is_multi_nozzle == true) { + check_nozzle_temp = multi_nozzle_temp[current_nozzle_id]; + } + else + { + check_nozzle_temp = nozzle_temp; + } + + if (m_role == erExternalPerimeter) { + if (z_height != initial_layer_height) { + if (is_multi_nozzle) { + double expected_temp = nozzle_temperature[filament_id]; + if (std::abs(check_nozzle_temp - expected_temp) > MULTI_NOZZLE_TEMP_THRESHOLD) { + std::cout << "Multi-nozzle: Invalid filament nozzle temperature! Expected: " + << expected_temp + << ", but got: " << check_nozzle_temp + << " (Threshold: ±100)." << std::endl; + return GCodeCheckResult::ParseFailed; + } + } + else { + if (check_nozzle_temp != nozzle_temperature[filament_id]) { + std::cout << "Invalid filament nozzle temperature! Expected: " + << nozzle_temperature[filament_id] + << ", but got: " << check_nozzle_temp << "." << std::endl; + return GCodeCheckResult::ParseFailed; + } + } } - } else if (m_role == erGapFill) { + } + else if (m_role == erGapFill) { check_gap_infill_width = true; } @@ -189,7 +219,36 @@ GCodeCheckResult GCodeChecker::parse_comment(GCodeLine& line) std::cout << "invalid nozzle temperature initial layer comment with invalid value!" << std::endl; return GCodeCheckResult::ParseFailed; } - } else if (starts_with(comment, Z_HEIGHT_TAG)) { + } + else if (starts_with(comment, Filament_Map_Tag)) { + std::string str = comment.substr(Filament_Map_Tag.size() + 1); + if (!parse_double_from_str(str, filament_map)) { + std::cout << "invalid filament map comment with invalid value!" << std::endl; + return GCodeCheckResult::ParseFailed; + } + else { + for (size_t i = 0; i < filament_map.size(); ++i) { + filament_map[i] -= 1; + } + is_multi_nozzle = true; + } + } + else if (starts_with(comment, Physical_Extruder_Map_Tag)) { + std::string str = comment.substr(Physical_Extruder_Map_Tag.size() + 1); + std::vectortmp; + + if (!parse_double_from_str(str, tmp)){ + std::cout << "invalid physical extruder map comment with invalid value!" << std::endl; + return GCodeCheckResult::ParseFailed; + } + + for (size_t idx = 0; idx < tmp.size(); ++idx) { + physical_to_logic_extruder_map[(int)(tmp[idx])]= idx; + logic_to_physical_extruder_map[idx] = (int)(tmp[idx]); + } + + } + else if (starts_with(comment, Z_HEIGHT_TAG)) { std::string str = comment.substr(Z_HEIGHT_TAG.size()); if (!parse_double_from_str(str, z_height)) { std::cout << "invalid z height comment with invalid value!" << std::endl; @@ -257,7 +316,7 @@ GCodeCheckResult GCodeChecker::parse_command(GCodeLine& gcode_line) case 'T':{ int pt = ::atoi(&cmd[1]); - if (pt == 1000 || pt == 1100 || pt == 255) { + if (pt == 1000 || pt == 1100 || pt == 255 || pt == 1001 || pt == 65535 || pt == 65279) { break; } @@ -267,9 +326,24 @@ GCodeCheckResult GCodeChecker::parse_command(GCodeLine& gcode_line) break; } filament_id = pt; + + if (is_multi_nozzle == true) { + set_current_nozzle(pt); + } + flow_ratio = filament_flow_ratio[pt]; break; } + case 'S': { + if (cmd.compare(0, 4, "SYNC") == 0) { + // Valid SYNC command + } + else { + // Invalid SYNC command + ret = GCodeCheckResult::ParseFailed; + } + break; + } default: { //QDS: other g command? impossible! must be invalid ret = GCodeCheckResult::ParseFailed; @@ -484,16 +558,39 @@ GCodeCheckResult GCodeChecker::parse_M104_M109(const GCodeLine &gcode_line) const char *c = gcode_line.m_raw.c_str(); const char *rs = strchr(c,'S'); - std::string str=rs; - str = str.substr(1); - for (int i = 0; i < str.size(); i++) { - if (str[i] == ' ') - str=str.substr(0,i); + std::string strS = rs; + strS = strS.substr(1); + for (int i = 0; i < strS.size(); i++) { + if (strS[i] == ' ') + strS = strS.substr(0,i); } - if (!parse_double_from_str(str, nozzle_temp)) { + double temp_nozzle_temp; + + if (!parse_double_from_str(strS, temp_nozzle_temp)) { std::cout << "invalid nozzle temperature comment with invalid value!" << std::endl; return GCodeCheckResult::ParseFailed; } + if (is_multi_nozzle == true) { + const char* rt = strchr(c, 'T'); + if (rt) { + std::string strT = rt + 1; // 跳过 'T' + for (size_t i = 0; i < strT.size(); i++) { + if (strT[i] == ' ') { + strT = strT.substr(0, i); + break; + } + } + int logic_nozzle_id = physical_to_logic_extruder_map[std::stoi(strT)]; + multi_nozzle_temp[logic_nozzle_id] = temp_nozzle_temp; + } + else + { + multi_nozzle_temp[current_nozzle_id] = temp_nozzle_temp; + } + } + else { + nozzle_temp = temp_nozzle_temp; + } return GCodeCheckResult::Success; } @@ -689,6 +786,16 @@ GCodeCheckResult GCodeChecker::check_G0_G1_width(const GCodeLine& line) return GCodeCheckResult::Success; } +void GCodeChecker::set_current_nozzle(int filament_id) { + if (filament_id >= 0 && filament_id < static_cast(filament_map.size())) { + current_nozzle_id = filament_map[filament_id]; + } + else { + std::cerr << "Error: filament_id is out of range!" << std::endl; + current_nozzle_id = 0; + } +} + GCodeCheckResult GCodeChecker::check_G2_G3_width(const GCodeLine& line) { auto absolute_position = [this](Axis axis, const GCodeLine& lineG2_3) { diff --git a/qds_test_tools/qds_gcode_checker/GCodeChecker.h b/qds_test_tools/qds_gcode_checker/GCodeChecker.h index d4b9e8f..f6e2404 100644 --- a/qds_test_tools/qds_gcode_checker/GCodeChecker.h +++ b/qds_test_tools/qds_gcode_checker/GCodeChecker.h @@ -5,6 +5,7 @@ #include #include #include +#include namespace QIDIStudio { @@ -116,6 +117,7 @@ private: GCodeCheckResult check_line_width(const GCodeLine& gcode_line); GCodeCheckResult check_G0_G1_width(const GCodeLine& gcode_line); GCodeCheckResult check_G2_G3_width(const GCodeLine& gcode_line); + void set_current_nozzle(int id); double calculate_G1_width(const std::array& source, const std::array& target, @@ -214,12 +216,22 @@ private: bool check_gap_infill_width = false; int filament_id; double flow_ratio = 0; + double nozzle_temp = 0.0f; + std::array multi_nozzle_temp = { 0.0, 0.0 }; + int current_nozzle_id = 0; + + std::vector filament_map; + + std::map physical_to_logic_extruder_map; + std::map logic_to_physical_extruder_map; std::vector filament_flow_ratio; std::vector nozzle_temperature; std::vector nozzle_temperature_initial_layer; + bool has_scarf_joint_seam = false; bool is_wipe_tower = false; + bool is_multi_nozzle = false; }; }