GCodeChecker.h 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. #ifndef _GCodeChecker_H_
  2. #define _GCodeChecker_H_
  3. #include <iostream>
  4. #include <string>
  5. #include <vector>
  6. #include <array>
  7. namespace BambuStudio {
  8. enum class GCodeCheckResult : unsigned char
  9. {
  10. Success,
  11. ParseFailed,
  12. CheckFailed,
  13. Count
  14. };
  15. enum class EMoveType : unsigned char
  16. {
  17. Noop,
  18. Retract,
  19. Unretract,
  20. Tool_change,
  21. Color_change,
  22. Pause_Print,
  23. Custom_GCode,
  24. Travel,
  25. Wipe,
  26. Extrude,
  27. Count
  28. };
  29. enum Axis {
  30. X=0,
  31. Y,
  32. Z,
  33. E,
  34. F,
  35. I,
  36. J,
  37. P,
  38. NUM_AXES,
  39. UNKNOWN_AXIS = NUM_AXES,
  40. };
  41. enum ExtrusionRole : uint8_t {
  42. erNone,
  43. erPerimeter,
  44. erExternalPerimeter,
  45. erOverhangPerimeter,
  46. erInternalInfill,
  47. erSolidInfill,
  48. erTopSolidInfill,
  49. erBottomSurface,
  50. erIroning,
  51. erBridgeInfill,
  52. erGapFill,
  53. erSkirt,
  54. erBrim,
  55. erSupportMaterial,
  56. erSupportMaterialInterface,
  57. erSupportTransition,
  58. erWipeTower,
  59. erCustom,
  60. // Extrusion role for a collection with multiple extrusion roles.
  61. erMixed,
  62. erCount
  63. };
  64. class GCodeChecker {
  65. public:
  66. class GCodeLine {
  67. public:
  68. GCodeLine() {}
  69. const std::string cmd() const {
  70. const char *cmd = GCodeChecker::skip_whitespaces(m_raw.c_str());
  71. return std::string(cmd, GCodeChecker::skip_word(cmd) - cmd);
  72. }
  73. bool has(Axis axis) const { return (m_mask & (1 << int(axis))) != 0; }
  74. double get(Axis axis) const { return m_axis[int(axis)]; }
  75. std::string m_raw;
  76. double m_axis[NUM_AXES] = { 0.0f };
  77. uint32_t m_mask = 0;
  78. };
  79. enum class EPositioningType : unsigned char
  80. {
  81. Absolute,
  82. Relative
  83. };
  84. GCodeChecker() {}
  85. GCodeCheckResult parse_file(const std::string& path);
  86. private:
  87. bool include_chinese(const char* str);
  88. GCodeCheckResult parse_line(const std::string& line);
  89. GCodeCheckResult parse_command(GCodeLine& gcode_line);
  90. GCodeCheckResult parse_axis(GCodeLine& gcode_line);
  91. GCodeCheckResult parse_G0_G1(GCodeLine& gcode_line);
  92. GCodeCheckResult parse_G2_G3(GCodeLine& gcode_line);
  93. GCodeCheckResult parse_G90(const GCodeLine& gcode_line);
  94. GCodeCheckResult parse_G91(const GCodeLine& gcode_line);
  95. GCodeCheckResult parse_G92(GCodeLine& gcode_line);
  96. GCodeCheckResult parse_M82(const GCodeLine& gcode_line);
  97. GCodeCheckResult parse_M83(const GCodeLine& gcode_line);
  98. GCodeCheckResult parse_comment(GCodeLine& gcode_line);
  99. GCodeCheckResult check_line_width(const GCodeLine& gcode_line);
  100. GCodeCheckResult check_G0_G1_width(const GCodeLine& gcode_line);
  101. GCodeCheckResult check_G2_G3_width(const GCodeLine& gcode_line);
  102. double calculate_G1_width(const std::array<double, 3>& source,
  103. const std::array<double, 3>& target,
  104. double e, double height, bool is_bridge) const;
  105. double calculate_G2_G3_width(const std::array<double, 2>& source,
  106. const std::array<double, 2>& target,
  107. const std::array<double, 2>& center,
  108. bool is_ccw, double e, double height, bool is_bridge) const;
  109. public:
  110. static bool is_whitespace(char c) { return c == ' ' || c == '\t'; }
  111. static bool is_end_of_line(char c) { return c == '\r' || c == '\n' || c == 0; }
  112. static bool is_comment_line(char c) { return c == ';'; }
  113. static bool is_end_of_gcode_line(char c) { return is_comment_line(c) || is_end_of_line(c); }
  114. static bool is_end_of_word(char c) { return is_whitespace(c) || is_end_of_gcode_line(c); }
  115. static const char* skip_word(const char *c) {
  116. for (; ! is_end_of_word(*c); ++ c)
  117. ; // silence -Wempty-body
  118. return c;
  119. }
  120. static const char* skip_whitespaces(const char *c) {
  121. for (; is_whitespace(*c); ++ c)
  122. ; // silence -Wempty-body
  123. return c;
  124. }
  125. static bool is_single_gcode_word(const char* c) {
  126. c = skip_word(c);
  127. c = skip_whitespaces(c);
  128. return is_end_of_gcode_line(*c);
  129. }
  130. static bool starts_with(const std::string &comment, const std::string &tag) {
  131. size_t tag_len = tag.size();
  132. return comment.size() >= tag_len && comment.substr(0, tag_len) == tag;
  133. }
  134. static ExtrusionRole string_to_role(const std::string& role);
  135. //BBS: Returns true if the number was parsed correctly into out and the number spanned the whole input string.
  136. static bool parse_double_from_str(const std::string& input, double& out) {
  137. size_t read = 0;
  138. try {
  139. out = std::stod(input, &read);
  140. return input.size() == read;
  141. } catch (...) {
  142. return false;
  143. }
  144. }
  145. private:
  146. EPositioningType m_global_positioning_type = EPositioningType::Absolute;
  147. EPositioningType m_e_local_positioning_type = EPositioningType::Absolute;
  148. std::array<double, 4> m_start_position = { 0.0, 0.0, 0.0, 0.0 };
  149. std::array<double, 4> m_end_position = { 0.0, 0.0, 0.0, 0.0 };
  150. std::array<double, 4> m_origin = { 0.0, 0.0, 0.0, 0.0 };
  151. //BBS: use these value to save information from comment
  152. ExtrusionRole m_role = erNone;
  153. bool m_wiping = false;
  154. int m_layer_num = 0;
  155. double m_height = 0.0;
  156. double m_width = 0.0;
  157. };
  158. }
  159. #endif