mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-31 04:31:15 -06:00 
			
		
		
		
	Port PrusaSlicer staggered_inner_seams
				
					
				
			This commit is contained in:
		
							parent
							
								
									b47777e73e
								
							
						
					
					
						commit
						c3c6bbc4e5
					
				
					 7 changed files with 1469 additions and 1255 deletions
				
			
		
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -27,138 +27,136 @@ class Grid; | |||
| 
 | ||||
| namespace SeamPlacerImpl { | ||||
| 
 | ||||
| // ************  FOR BACKPORT COMPATIBILITY ONLY ***************
 | ||||
| // Angle from v1 to v2, returning double atan2(y, x) normalized to <-PI, PI>.
 | ||||
| template<typename Derived, typename Derived2> inline double angle(const Eigen::MatrixBase<Derived> &v1, const Eigen::MatrixBase<Derived2> &v2) | ||||
| { | ||||
|     static_assert(Derived::IsVectorAtCompileTime && int(Derived::SizeAtCompileTime) == 2, "angle(): first parameter is not a 2D vector"); | ||||
|     static_assert(Derived2::IsVectorAtCompileTime && int(Derived2::SizeAtCompileTime) == 2, "angle(): second parameter is not a 2D vector"); | ||||
|     auto v1d = v1.template cast<double>(); | ||||
|     auto v2d = v2.template cast<double>(); | ||||
|     return atan2(cross2(v1d, v2d), v1d.dot(v2d)); | ||||
| } | ||||
| // ***************************
 | ||||
| 
 | ||||
| struct GlobalModelInfo; | ||||
| struct SeamComparator; | ||||
| 
 | ||||
| enum class EnforcedBlockedSeamPoint { | ||||
|     Blocked  = 0, | ||||
|     Neutral  = 1, | ||||
|     Enforced = 2, | ||||
|   Blocked = 0, | ||||
|   Neutral = 1, | ||||
|   Enforced = 2, | ||||
| }; | ||||
| 
 | ||||
| // struct representing single perimeter loop
 | ||||
| struct Perimeter | ||||
| { | ||||
|     size_t start_index{}; | ||||
|     size_t end_index{}; // inclusive!
 | ||||
|     size_t seam_index{}; | ||||
|     float  flow_width{}; | ||||
| struct Perimeter { | ||||
|   size_t start_index{}; | ||||
|   size_t end_index{}; //inclusive!
 | ||||
|   size_t seam_index{}; | ||||
|   float flow_width{}; | ||||
| 
 | ||||
|     // During alignment, a final position may be stored here. In that case, finalized is set to true.
 | ||||
|     // Note that final seam position is not limited to points of the perimeter loop. In theory it can be any position
 | ||||
|     // Random position also uses this flexibility to set final seam point position
 | ||||
|     bool  finalized           = false; | ||||
|     Vec3f final_seam_position = Vec3f::Zero(); | ||||
|   // During alignment, a final position may be stored here. In that case, finalized is set to true.
 | ||||
|   // Note that final seam position is not limited to points of the perimeter loop. In theory it can be any position
 | ||||
|   // Random position also uses this flexibility to set final seam point position
 | ||||
|   bool finalized = false; | ||||
|   Vec3f final_seam_position = Vec3f::Zero(); | ||||
| }; | ||||
| 
 | ||||
| // Struct over which all processing of perimeters is done. For each perimeter point, its respective candidate is created,
 | ||||
| //Struct over which all processing of perimeters is done. For each perimeter point, its respective candidate is created,
 | ||||
| // then all the needed attributes are computed and finally, for each perimeter one point is chosen as seam.
 | ||||
| // This seam position can be then further aligned
 | ||||
| struct SeamCandidate | ||||
| { | ||||
|     SeamCandidate(const Vec3f &pos, Perimeter &perimeter, float local_ccw_angle, EnforcedBlockedSeamPoint type) | ||||
|         : position(pos), perimeter(perimeter), visibility(0.0f), overhang(0.0f), embedded_distance(0.0f), local_ccw_angle(local_ccw_angle), type(type), central_enforcer(false) | ||||
|     {} | ||||
|     const Vec3f position; | ||||
|     // pointer to Perimeter loop of this point. It is shared across all points of the loop
 | ||||
|     Perimeter &perimeter; | ||||
|     float      visibility; | ||||
|     float      overhang; | ||||
|     // distance inside the merged layer regions, for detecting perimeter points which are hidden indside the print (e.g. multimaterial join)
 | ||||
|     // Negative sign means inside the print, comes from EdgeGrid structure
 | ||||
|     float                    embedded_distance; | ||||
|     float                    local_ccw_angle; | ||||
|     EnforcedBlockedSeamPoint type; | ||||
|     bool                     central_enforcer; // marks this candidate as central point of enforced segment on the perimeter - important for alignment
 | ||||
| struct SeamCandidate { | ||||
|   SeamCandidate(const Vec3f &pos, Perimeter &perimeter, | ||||
|                 float local_ccw_angle, | ||||
|                 EnforcedBlockedSeamPoint type) : | ||||
|                                                  position(pos), perimeter(perimeter), visibility(0.0f), overhang(0.0f), embedded_distance(0.0f), local_ccw_angle( | ||||
|                                                                                                                                                      local_ccw_angle), type(type), central_enforcer(false) { | ||||
|   } | ||||
|   const Vec3f position; | ||||
|   // pointer to Perimeter loop of this point. It is shared across all points of the loop
 | ||||
|   Perimeter &perimeter; | ||||
|   float visibility; | ||||
|   float overhang; | ||||
|   // distance inside the merged layer regions, for detecting perimeter points which are hidden indside the print (e.g. multimaterial join)
 | ||||
|   // Negative sign means inside the print, comes from EdgeGrid structure
 | ||||
|   float embedded_distance; | ||||
|   float local_ccw_angle; | ||||
|   EnforcedBlockedSeamPoint type; | ||||
|   bool central_enforcer; //marks this candidate as central point of enforced segment on the perimeter - important for alignment
 | ||||
| }; | ||||
| 
 | ||||
| struct SeamCandidateCoordinateFunctor | ||||
| { | ||||
|     SeamCandidateCoordinateFunctor(const std::vector<SeamCandidate> &seam_candidates) : seam_candidates(seam_candidates) {} | ||||
|     const std::vector<SeamCandidate> &seam_candidates; | ||||
|     float                             operator()(size_t index, size_t dim) const { return seam_candidates[index].position[dim]; } | ||||
| struct SeamCandidateCoordinateFunctor { | ||||
|   SeamCandidateCoordinateFunctor(const std::vector<SeamCandidate> &seam_candidates) : | ||||
|                                                                                       seam_candidates(seam_candidates) { | ||||
|   } | ||||
|   const std::vector<SeamCandidate> &seam_candidates; | ||||
|   float operator()(size_t index, size_t dim) const { | ||||
|     return seam_candidates[index].position[dim]; | ||||
|   } | ||||
| }; | ||||
| } // namespace SeamPlacerImpl
 | ||||
| 
 | ||||
| struct PrintObjectSeamData | ||||
| { | ||||
|     using SeamCandidatesTree = KDTreeIndirect<3, float, SeamPlacerImpl::SeamCandidateCoordinateFunctor>; | ||||
|   using SeamCandidatesTree = KDTreeIndirect<3, float, SeamPlacerImpl::SeamCandidateCoordinateFunctor>; | ||||
| 
 | ||||
|     struct LayerSeams | ||||
|     { | ||||
|         Slic3r::deque<SeamPlacerImpl::Perimeter>   perimeters; | ||||
|         std::vector<SeamPlacerImpl::SeamCandidate> points; | ||||
|         std::unique_ptr<SeamCandidatesTree>        points_tree; | ||||
|     }; | ||||
|     // Map of PrintObjects (PO) -> vector of layers of PO -> vector of perimeter
 | ||||
|     std::vector<LayerSeams> layers; | ||||
|     // Map of PrintObjects (PO) -> vector of layers of PO -> unique_ptr to KD
 | ||||
|     // tree of all points of the given layer
 | ||||
|   struct LayerSeams | ||||
|   { | ||||
|     Slic3r::deque<SeamPlacerImpl::Perimeter> perimeters; | ||||
|     std::vector<SeamPlacerImpl::SeamCandidate> points; | ||||
|     std::unique_ptr<SeamCandidatesTree> points_tree; | ||||
|   }; | ||||
|   // Map of PrintObjects (PO) -> vector of layers of PO -> vector of perimeter
 | ||||
|   std::vector<LayerSeams> layers; | ||||
|   // Map of PrintObjects (PO) -> vector of layers of PO -> unique_ptr to KD
 | ||||
|   // tree of all points of the given layer
 | ||||
| 
 | ||||
|     void clear() { layers.clear(); } | ||||
|   void clear() | ||||
|   { | ||||
|     layers.clear(); | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| class SeamPlacer | ||||
| { | ||||
| class SeamPlacer { | ||||
| public: | ||||
|     // Number of samples generated on the mesh. There are sqr_rays_per_sample_point*sqr_rays_per_sample_point rays casted from each samples
 | ||||
|     static constexpr size_t raycasting_visibility_samples_count = 30000; | ||||
|     // square of number of rays per sample point
 | ||||
|     static constexpr size_t sqr_rays_per_sample_point = 5; | ||||
|   // Number of samples generated on the mesh. There are sqr_rays_per_sample_point*sqr_rays_per_sample_point rays casted from each samples
 | ||||
|   static constexpr size_t raycasting_visibility_samples_count = 30000; | ||||
|   static constexpr size_t fast_decimation_triangle_count_target = 16000; | ||||
|   //square of number of rays per sample point
 | ||||
|   static constexpr size_t sqr_rays_per_sample_point = 5; | ||||
| 
 | ||||
|     // snapping angle - angles larger than this value will be snapped to during seam painting
 | ||||
|     static constexpr float sharp_angle_snapping_threshold = 55.0f * float(PI) / 180.0f; | ||||
|     // overhang angle for seam placement that still yields good results, in degrees, measured from vertical direction
 | ||||
|     //BBS
 | ||||
|     static constexpr float overhang_angle_threshold = 45.0f * float(PI) / 180.0f; | ||||
|   // snapping angle - angles larger than this value will be snapped to during seam painting
 | ||||
|   static constexpr float sharp_angle_snapping_threshold = 55.0f * float(PI) / 180.0f; | ||||
|   // overhang angle for seam placement that still yields good results, in degrees, measured from vertical direction
 | ||||
|   static constexpr float overhang_angle_threshold = 50.0f * float(PI) / 180.0f; | ||||
| 
 | ||||
|     // determines angle importance compared to visibility ( neutral value is 1.0f. )
 | ||||
|     static constexpr float angle_importance_aligned = 0.6f; | ||||
|     static constexpr float angle_importance_nearest = 1.0f; // use much higher angle importance for nearest mode, to combat the visibility info noise
 | ||||
|   // determines angle importance compared to visibility ( neutral value is 1.0f. )
 | ||||
|   static constexpr float angle_importance_aligned = 0.6f; | ||||
|   static constexpr float angle_importance_nearest = 1.0f; // use much higher angle importance for nearest mode, to combat the visibility info noise
 | ||||
| 
 | ||||
|     // For long polygon sides, if they are close to the custom seam drawings, they are oversampled with this step size
 | ||||
|     static constexpr float enforcer_oversampling_distance = 0.2f; | ||||
|   // For long polygon sides, if they are close to the custom seam drawings, they are oversampled with this step size
 | ||||
|   static constexpr float enforcer_oversampling_distance = 0.2f; | ||||
| 
 | ||||
|     // When searching for seam clusters for alignment:
 | ||||
|     // following value describes, how much worse score can point have and still be picked into seam cluster instead of original seam point on the same layer
 | ||||
|     static constexpr float seam_align_score_tolerance = 0.3f; | ||||
|     // seam_align_tolerable_dist_factor - how far to search for seam from current position, final dist is seam_align_tolerable_dist_factor * flow_width
 | ||||
|     static constexpr float seam_align_tolerable_dist_factor = 4.0f; | ||||
|     // minimum number of seams needed in cluster to make alignment happen
 | ||||
|     static constexpr size_t seam_align_minimum_string_seams = 6; | ||||
|     // millimeters covered by spline; determines number of splines for the given string
 | ||||
|     static constexpr size_t seam_align_mm_per_segment = 4.0f; | ||||
|   // When searching for seam clusters for alignment:
 | ||||
|   // following value describes, how much worse score can point have and still be picked into seam cluster instead of original seam point on the same layer
 | ||||
|   static constexpr float seam_align_score_tolerance = 0.3f; | ||||
|   // seam_align_tolerable_dist_factor - how far to search for seam from current position, final dist is seam_align_tolerable_dist_factor * flow_width
 | ||||
|   static constexpr float seam_align_tolerable_dist_factor = 4.0f; | ||||
|   // minimum number of seams needed in cluster to make alignment happen
 | ||||
|   static constexpr size_t seam_align_minimum_string_seams = 6; | ||||
|   // millimeters covered by spline; determines number of splines for the given string
 | ||||
|   static constexpr size_t seam_align_mm_per_segment = 4.0f; | ||||
| 
 | ||||
|     // The following data structures hold all perimeter points for all PrintObject.
 | ||||
|     std::unordered_map<const PrintObject *, PrintObjectSeamData> m_seam_per_object; | ||||
|   //The following data structures hold all perimeter points for all PrintObject.
 | ||||
|   std::unordered_map<const PrintObject*, PrintObjectSeamData> m_seam_per_object; | ||||
| 
 | ||||
|     void init(const Print &print, std::function<void(void)> throw_if_canceled_func); | ||||
|   void init(const Print &print, std::function<void(void)> throw_if_canceled_func); | ||||
| 
 | ||||
|     void place_seam(const Layer *layer, ExtrusionLoop &loop, bool external_first, const Point &last_pos) const; | ||||
|   void place_seam(const Layer *layer, ExtrusionLoop &loop, bool external_first, const Point &last_pos) const; | ||||
| 
 | ||||
| private: | ||||
|     void gather_seam_candidates(const PrintObject *po, const SeamPlacerImpl::GlobalModelInfo &global_model_info, const SeamPosition configured_seam_preference); | ||||
|     void calculate_candidates_visibility(const PrintObject *po, const SeamPlacerImpl::GlobalModelInfo &global_model_info); | ||||
|     void calculate_overhangs_and_layer_embedding(const PrintObject *po); | ||||
|     void align_seam_points(const PrintObject *po, const SeamPlacerImpl::SeamComparator &comparator); | ||||
|     std::vector<std::pair<size_t, size_t>> find_seam_string(const PrintObject *po, std::pair<size_t, size_t> start_seam, const SeamPlacerImpl::SeamComparator &comparator) const; | ||||
|     std::optional<std::pair<size_t, size_t>> find_next_seam_in_layer(const std::vector<PrintObjectSeamData::LayerSeams> &layers, | ||||
|                                                                      const Vec3f &                                       projected_position, | ||||
|                                                                      const size_t                                        layer_idx, | ||||
|                                                                      const float                                         max_distance, | ||||
|                                                                      const SeamPlacerImpl::SeamComparator &              comparator) const; | ||||
|   void gather_seam_candidates(const PrintObject *po, const SeamPlacerImpl::GlobalModelInfo &global_model_info); | ||||
|   void calculate_candidates_visibility(const PrintObject *po, | ||||
|                                        const SeamPlacerImpl::GlobalModelInfo &global_model_info); | ||||
|   void calculate_overhangs_and_layer_embedding(const PrintObject *po); | ||||
|   void align_seam_points(const PrintObject *po, const SeamPlacerImpl::SeamComparator &comparator); | ||||
|   std::vector<std::pair<size_t, size_t>> find_seam_string(const PrintObject *po, | ||||
|                                                           std::pair<size_t, size_t> start_seam, | ||||
|                                                           const SeamPlacerImpl::SeamComparator &comparator) const; | ||||
|   std::optional<std::pair<size_t, size_t>> find_next_seam_in_layer( | ||||
|       const std::vector<PrintObjectSeamData::LayerSeams> &layers, | ||||
|       const Vec3f& projected_position, | ||||
|       const size_t layer_idx, const float max_distance, | ||||
|       const SeamPlacerImpl::SeamComparator &comparator) const; | ||||
| }; | ||||
| 
 | ||||
| } // namespace Slic3r
 | ||||
|  |  | |||
|  | @ -708,7 +708,7 @@ static std::vector<std::string> s_Preset_print_options { | |||
|     "layer_height", "initial_layer_print_height", "wall_loops", "slice_closing_radius", "spiral_mode", "slicing_mode", | ||||
|     "top_shell_layers", "top_shell_thickness", "bottom_shell_layers", "bottom_shell_thickness", | ||||
|     "ensure_vertical_shell_thickness", "reduce_crossing_wall", "detect_thin_wall", "detect_overhang_wall", | ||||
|     "seam_position", "wall_infill_order", "sparse_infill_density", "sparse_infill_pattern", "top_surface_pattern", "bottom_surface_pattern", | ||||
|     "seam_position", "staggered_inner_seams", "wall_infill_order", "sparse_infill_density", "sparse_infill_pattern", "top_surface_pattern", "bottom_surface_pattern", | ||||
|     "infill_direction", | ||||
|     "minimum_sparse_infill_area", "reduce_infill_retraction", | ||||
|     "ironing_type", "ironing_flow", "ironing_speed", "ironing_spacing", | ||||
|  |  | |||
|  | @ -2613,6 +2613,12 @@ void PrintConfigDef::init_fff_params() | |||
|     def->enum_labels.push_back(L("Random")); | ||||
|     def->mode = comSimple; | ||||
|     def->set_default_value(new ConfigOptionEnum<SeamPosition>(spAligned)); | ||||
| 
 | ||||
|     def = this->add("staggered_inner_seams", coBool); | ||||
|     def->label = L("Staggered inner seams"); | ||||
|     def->tooltip = L("This option causes the inner seams to be shifted backwards based on their depth, forming a zigzag pattern."); | ||||
|     def->mode = comAdvanced; | ||||
|     def->set_default_value(new ConfigOptionBool(false)); | ||||
|      | ||||
|     def = this->add("seam_gap", coFloatOrPercent); | ||||
|     def->label = L("Seam gap"); | ||||
|  |  | |||
|  | @ -646,6 +646,7 @@ PRINT_CONFIG_CLASS_DEFINE( | |||
|     ((ConfigOptionFloat,               raft_first_layer_expansion)) | ||||
|     ((ConfigOptionInt,                 raft_layers)) | ||||
|     ((ConfigOptionEnum<SeamPosition>,  seam_position)) | ||||
|     ((ConfigOptionBool,                staggered_inner_seams)) | ||||
|     ((ConfigOptionFloat,               slice_closing_radius)) | ||||
|     ((ConfigOptionEnum<SlicingMode>,   slicing_mode)) | ||||
|     ((ConfigOptionBool,                enable_support)) | ||||
|  |  | |||
|  | @ -540,7 +540,7 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co | |||
|      | ||||
|     bool have_perimeters = config->opt_int("wall_loops") > 0; | ||||
|     for (auto el : { "ensure_vertical_shell_thickness", "detect_thin_wall", "detect_overhang_wall", | ||||
|                     "seam_position", "wall_infill_order", "outer_wall_line_width", | ||||
|                     "seam_position", "staggered_inner_seams", "wall_infill_order", "outer_wall_line_width", | ||||
|                     "inner_wall_speed", "outer_wall_speed", "small_perimeter_speed", "small_perimeter_threshold" }) | ||||
|         toggle_field(el, have_perimeters); | ||||
| 
 | ||||
|  |  | |||
|  | @ -1845,6 +1845,7 @@ void TabPrint::build() | |||
| 
 | ||||
|         optgroup = page->new_optgroup(L("Seam"), L"param_seam"); | ||||
|         optgroup->append_single_option_line("seam_position", "Seam"); | ||||
|         optgroup->append_single_option_line("staggered_inner_seams", "Seam"); | ||||
|         optgroup->append_single_option_line("seam_gap","Seam"); | ||||
|         optgroup->append_single_option_line("role_based_wipe_speed","Seam"); | ||||
|         optgroup->append_single_option_line("wipe_speed", "Seam"); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 SoftFever
						SoftFever