mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-30 20:21:12 -06:00 
			
		
		
		
	Fix of "Don't use bridging perimeters on top of elephant-foot compensation #3011"
If the Elephant foot compensation is applied to the 1st object's layer, the uncompensated 1st object's slice is newly used for calculation of bridges, overhans, skirt, brim, raft and supports. Layer::slices were renamed to Layer::lslices to simplify reading of the code, to differentiate from LayerRegion::slices.
This commit is contained in:
		
							parent
							
								
									a4ad0a0925
								
							
						
					
					
						commit
						3d17543d40
					
				
					 8 changed files with 158 additions and 137 deletions
				
			
		|  | @ -122,21 +122,21 @@ Polygons AvoidCrossingPerimeters::collect_contours_all_layers(const PrintObjectP | |||
|                      const Layer* layer1 = object->layers()[i * 2]; | ||||
|                      const Layer* layer2 = object->layers()[i * 2 + 1]; | ||||
|                      Polygons polys; | ||||
|                      polys.reserve(layer1->slices.size() + layer2->slices.size()); | ||||
|                     for (const ExPolygon &expoly : layer1->slices) | ||||
|                      polys.reserve(layer1->lslices.size() + layer2->lslices.size()); | ||||
|                      for (const ExPolygon &expoly : layer1->lslices) | ||||
|                         //FIXME no holes?
 | ||||
|                         polys.emplace_back(expoly.contour); | ||||
|                     for (const ExPolygon &expoly : layer2->slices) | ||||
|                      for (const ExPolygon &expoly : layer2->lslices) | ||||
|                         //FIXME no holes?
 | ||||
|                         polys.emplace_back(expoly.contour); | ||||
|                      polygons_per_layer[i] = union_(polys); | ||||
|                 } | ||||
|             }); | ||||
|                  } | ||||
|              }); | ||||
|          if (object->layers().size() & 1) { | ||||
|             const Layer *layer = object->layers().back(); | ||||
|             Polygons polys; | ||||
|             polys.reserve(layer->slices.size()); | ||||
|             for (const ExPolygon &expoly : layer->slices) | ||||
|             polys.reserve(layer->lslices.size()); | ||||
|             for (const ExPolygon &expoly : layer->lslices) | ||||
|                 //FIXME no holes?
 | ||||
|                 polys.emplace_back(expoly.contour); | ||||
|              polygons_per_layer.back() = union_(polys); | ||||
|  | @ -2006,8 +2006,8 @@ void GCode::process_layer( | |||
|             // - for each island, we extrude perimeters first, unless user set the infill_first
 | ||||
|             //   option
 | ||||
|             // (Still, we have to keep track of regions because we need to apply their config)
 | ||||
|             size_t n_slices = layer.slices.size(); | ||||
|             const std::vector<BoundingBox> &layer_surface_bboxes = layer.slices_bboxes; | ||||
|             size_t n_slices = layer.lslices.size(); | ||||
|             const std::vector<BoundingBox> &layer_surface_bboxes = layer.lslices_bboxes; | ||||
|             // Traverse the slices in an increasing order of bounding box size, so that the islands inside another islands are tested first,
 | ||||
|             // so we can just test a point inside ExPolygon::contour and we may skip testing the holes.
 | ||||
|             std::vector<size_t> slices_test_order; | ||||
|  | @ -2023,7 +2023,7 @@ void GCode::process_layer( | |||
|                 const BoundingBox &bbox = layer_surface_bboxes[i]; | ||||
|                 return point(0) >= bbox.min(0) && point(0) < bbox.max(0) && | ||||
|                        point(1) >= bbox.min(1) && point(1) < bbox.max(1) && | ||||
|                        layer.slices[i].contour.contains(point); | ||||
|                        layer.lslices[i].contour.contains(point); | ||||
|             }; | ||||
| 
 | ||||
|             for (size_t region_id = 0; region_id < print.regions().size(); ++ region_id) { | ||||
|  | @ -2155,7 +2155,7 @@ void GCode::process_layer( | |||
|                 m_config.apply(instance_to_print.print_object.config(), true); | ||||
|                 m_layer = layers[instance_to_print.layer_id].layer(); | ||||
|                 if (m_config.avoid_crossing_perimeters) | ||||
|                     m_avoid_crossing_perimeters.init_layer_mp(union_ex(m_layer->slices, true)); | ||||
|                     m_avoid_crossing_perimeters.init_layer_mp(union_ex(m_layer->lslices, true)); | ||||
| 
 | ||||
|                 if (this->config().gcode_label_objects) | ||||
|                     gcode += std::string("; printing object ") + instance_to_print.print_object.model_object()->name + " id:" + std::to_string(instance_to_print.layer_id) + " copy " + std::to_string(instance_to_print.instance_id) + "\n"; | ||||
|  | @ -2476,7 +2476,7 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou | |||
|             // Create the distance field for a layer below.
 | ||||
|             const coord_t distance_field_resolution = coord_t(scale_(1.) + 0.5); | ||||
|             *lower_layer_edge_grid = make_unique<EdgeGrid::Grid>(); | ||||
|             (*lower_layer_edge_grid)->create(m_layer->lower_layer->slices, distance_field_resolution); | ||||
|             (*lower_layer_edge_grid)->create(m_layer->lower_layer->lslices, distance_field_resolution); | ||||
|             (*lower_layer_edge_grid)->calculate_sdf(); | ||||
|             #if 0 | ||||
|             { | ||||
|  |  | |||
|  | @ -47,8 +47,8 @@ void Layer::make_slices() | |||
|         slices = union_ex(slices_p); | ||||
|     } | ||||
|      | ||||
|     this->slices.clear(); | ||||
|     this->slices.reserve(slices.size()); | ||||
|     this->lslices.clear(); | ||||
|     this->lslices.reserve(slices.size()); | ||||
|      | ||||
|     // prepare ordering points
 | ||||
|     Points ordering_points; | ||||
|  | @ -61,19 +61,21 @@ void Layer::make_slices() | |||
|      | ||||
|     // populate slices vector
 | ||||
|     for (size_t i : order) | ||||
|         this->slices.push_back(std::move(slices[i])); | ||||
|         this->lslices.emplace_back(std::move(slices[i])); | ||||
| } | ||||
| 
 | ||||
| // Merge typed slices into untyped slices. This method is used to revert the effects of detect_surfaces_type() called for posPrepareInfill.
 | ||||
| void Layer::merge_slices() | ||||
| { | ||||
|     if (m_regions.size() == 1) { | ||||
|     if (m_regions.size() == 1 && (this->id() > 0 || this->object()->config().elefant_foot_compensation.value == 0)) { | ||||
|         // Optimization, also more robust. Don't merge classified pieces of layerm->slices,
 | ||||
|         // but use the non-split islands of a layer. For a single region print, these shall be equal.
 | ||||
|         m_regions.front()->slices.set(this->slices, stInternal); | ||||
|         // Don't use this optimization on 1st layer with Elephant foot compensation applied, as this->lslices are uncompensated,
 | ||||
|         // while regions are compensated.
 | ||||
|         m_regions.front()->slices.set(this->lslices, stInternal); | ||||
|     } else { | ||||
|         for (LayerRegion *layerm : m_regions) | ||||
|             // without safety offset, artifacts are generated (GH #2494)
 | ||||
|             // without safety offset, artifacts are generated (upstream Slic3r GH #2494)
 | ||||
|             layerm->slices.set(union_ex(to_polygons(std::move(layerm->slices.surfaces)), true), stInternal); | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -106,12 +106,16 @@ public: | |||
|     coordf_t            print_z;       // Z used for printing in unscaled coordinates
 | ||||
|     coordf_t            height;        // layer height in unscaled coordinates
 | ||||
| 
 | ||||
|     // collection of expolygons generated by slicing the original geometry;
 | ||||
|     // also known as 'islands' (all regions and surface types are merged here)
 | ||||
|     // The slices are chained by the shortest traverse distance and this traversal
 | ||||
|     // order will be recovered by the G-code generator.
 | ||||
|     ExPolygons 			slices; | ||||
|     std::vector<BoundingBox> slices_bboxes; | ||||
|     // Collection of expolygons generated by slicing the possibly multiple meshes of the source geometry 
 | ||||
|     // (with possibly differing extruder ID and slicing parameters) and merged.
 | ||||
|     // For the first layer, if the ELephant foot compensation is applied, this lslice is uncompensated, therefore
 | ||||
|     // it includes the Elephant foot effect, thus it corresponds to the shape of the printed 1st layer.
 | ||||
|     // These lslices aka islands are chained by the shortest traverse distance and this traversal
 | ||||
|     // order will be applied by the G-code generator to the extrusions fitting into these lslices.
 | ||||
|     // These lslices are also used to detect overhangs and overlaps between successive layers, therefore it is important
 | ||||
|     // that the 1st lslice is not compensated by the Elephant foot compensation algorithm.
 | ||||
|     ExPolygons 				 lslices; | ||||
|     std::vector<BoundingBox> lslices_bboxes; | ||||
| 
 | ||||
|     size_t                  region_count() const { return m_regions.size(); } | ||||
|     const LayerRegion*      get_region(int idx) const { return m_regions.at(idx); } | ||||
|  |  | |||
|  | @ -72,7 +72,7 @@ void LayerRegion::make_perimeters(const SurfaceCollection &slices, SurfaceCollec | |||
|      | ||||
|     if (this->layer()->lower_layer != nullptr) | ||||
|         // Cummulative sum of polygons over all the regions.
 | ||||
|         g.lower_slices = &this->layer()->lower_layer->slices; | ||||
|         g.lower_slices = &this->layer()->lower_layer->lslices; | ||||
|      | ||||
|     g.layer_id              = (int)this->layer()->id(); | ||||
|     g.ext_perimeter_flow    = this->flow(frExternalPerimeter); | ||||
|  | @ -139,7 +139,7 @@ void LayerRegion::process_external_surfaces(const Layer *lower_layer, const Poly | |||
|         	// Remove voids from fill_boundaries, that are not supported by the layer below.
 | ||||
|             if (lower_layer_covered == nullptr) { | ||||
|             	lower_layer_covered = &lower_layer_covered_tmp; | ||||
|             	lower_layer_covered_tmp = to_polygons(lower_layer->slices); | ||||
|             	lower_layer_covered_tmp = to_polygons(lower_layer->lslices); | ||||
|             } | ||||
|             if (! lower_layer_covered->empty()) | ||||
|             	voids = diff(voids, *lower_layer_covered); | ||||
|  | @ -260,7 +260,7 @@ void LayerRegion::process_external_surfaces(const Layer *lower_layer, const Poly | |||
|                 // of very thin (but still working) anchors, the grown expolygon would go beyond them
 | ||||
|                 BridgeDetector bd( | ||||
|                     initial, | ||||
|                     lower_layer->slices, | ||||
|                     lower_layer->lslices, | ||||
|                     this->flow(frInfill, true).scaled_width() | ||||
|                 ); | ||||
|                 #ifdef SLIC3R_DEBUG | ||||
|  |  | |||
|  | @ -1658,7 +1658,7 @@ void Print::_make_skirt() | |||
|         for (const Layer *layer : object->m_layers) { | ||||
|             if (layer->print_z > skirt_height_z) | ||||
|                 break; | ||||
|             for (const ExPolygon &expoly : layer->slices) | ||||
|             for (const ExPolygon &expoly : layer->lslices) | ||||
|                 // Collect the outer contour points only, ignore holes for the calculation of the convex hull.
 | ||||
|                 append(object_points, expoly.contour.points); | ||||
|         } | ||||
|  | @ -1787,7 +1787,7 @@ void Print::_make_brim() | |||
|     Polygons    islands; | ||||
|     for (PrintObject *object : m_objects) { | ||||
|         Polygons object_islands; | ||||
|         for (ExPolygon &expoly : object->m_layers.front()->slices) | ||||
|         for (ExPolygon &expoly : object->m_layers.front()->lslices) | ||||
|             object_islands.push_back(expoly.contour); | ||||
|         if (! object->support_layers().empty()) | ||||
|             object->support_layers().front()->support_fills.polygons_covered_by_spacing(object_islands, float(SCALED_EPSILON)); | ||||
|  |  | |||
|  | @ -182,7 +182,7 @@ private: | |||
| 
 | ||||
|     void _slice(const std::vector<coordf_t> &layer_height_profile); | ||||
|     std::string _fix_slicing_errors(); | ||||
|     void _simplify_slices(double distance); | ||||
|     void simplify_slices(double distance); | ||||
|     bool has_support_material() const; | ||||
|     void detect_surfaces_type(); | ||||
|     void process_external_surfaces(); | ||||
|  |  | |||
|  | @ -117,7 +117,7 @@ void PrintObject::slice() | |||
|         BOOST_LOG_TRIVIAL(info) << warning; | ||||
|     // Simplify slices if required.
 | ||||
|     if (m_print->config().resolution) | ||||
|         this->_simplify_slices(scale_(this->print()->config().resolution)); | ||||
|         this->simplify_slices(scale_(this->print()->config().resolution)); | ||||
|     // Update bounding boxes
 | ||||
|     tbb::parallel_for( | ||||
|         tbb::blocked_range<size_t>(0, m_layers.size()), | ||||
|  | @ -125,10 +125,10 @@ void PrintObject::slice() | |||
|             for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx) { | ||||
|                 m_print->throw_if_canceled(); | ||||
|                 Layer &layer = *m_layers[layer_idx]; | ||||
|                 layer.slices_bboxes.clear(); | ||||
|                 layer.slices_bboxes.reserve(layer.slices.size()); | ||||
|                 for (const ExPolygon &expoly : layer.slices) | ||||
|                 	layer.slices_bboxes.emplace_back(get_extents(expoly)); | ||||
|                 layer.lslices_bboxes.clear(); | ||||
|                 layer.lslices_bboxes.reserve(layer.lslices.size()); | ||||
|                 for (const ExPolygon &expoly : layer.lslices) | ||||
|                 	layer.lslices_bboxes.emplace_back(get_extents(expoly)); | ||||
|             } | ||||
|         }); | ||||
|     if (m_layers.empty()) | ||||
|  | @ -242,13 +242,6 @@ void PrintObject::make_perimeters() | |||
|     m_print->throw_if_canceled(); | ||||
|     BOOST_LOG_TRIVIAL(debug) << "Generating perimeters in parallel - end"; | ||||
| 
 | ||||
|     /*
 | ||||
|         simplify slices (both layer and region slices), | ||||
|         we only need the max resolution for perimeters | ||||
|     ### This makes this method not-idempotent, so we keep it disabled for now. | ||||
|     ###$self->_simplify_slices(&Slic3r::SCALED_RESOLUTION); | ||||
|     */ | ||||
|      | ||||
|     this->set_done(posPerimeters); | ||||
| } | ||||
| 
 | ||||
|  | @ -692,7 +685,7 @@ void PrintObject::detect_surfaces_type() | |||
|                     if (upper_layer) { | ||||
|                         Polygons upper_slices = interface_shells ?  | ||||
|                             to_polygons(upper_layer->get_region(idx_region)->slices.surfaces) :  | ||||
|                             to_polygons(upper_layer->slices); | ||||
|                             to_polygons(upper_layer->lslices); | ||||
|                         surfaces_append(top, | ||||
|                             //FIXME implement offset2_ex working over ExPolygons, that should be a bit more efficient than calling offset_ex twice.
 | ||||
|                             offset_ex(offset_ex(diff_ex(layerm_slices_surfaces, upper_slices, true), -offset), offset), | ||||
|  | @ -721,7 +714,7 @@ void PrintObject::detect_surfaces_type() | |||
|                         surfaces_append( | ||||
|                             bottom, | ||||
|                             offset2_ex( | ||||
|                                 diff(layerm_slices_surfaces, to_polygons(lower_layer->slices), true),  | ||||
|                                 diff(layerm_slices_surfaces, to_polygons(lower_layer->lslices), true),  | ||||
|                                 -offset, offset), | ||||
|                             surface_type_bottom_other); | ||||
|                         // if user requested internal shells, we need to identify surfaces
 | ||||
|  | @ -733,7 +726,7 @@ void PrintObject::detect_surfaces_type() | |||
|                                 bottom, | ||||
|                                 offset2_ex( | ||||
|                                     diff( | ||||
|                                         intersection(layerm_slices_surfaces, to_polygons(lower_layer->slices)), // supported
 | ||||
|                                         intersection(layerm_slices_surfaces, to_polygons(lower_layer->lslices)), // supported
 | ||||
|                                         to_polygons(lower_layer->get_region(idx_region)->slices.surfaces),  | ||||
|                                         true),  | ||||
|                                     -offset, offset), | ||||
|  | @ -879,7 +872,7 @@ void PrintObject::process_external_surfaces() | |||
| 		                			// Shrink the holes, let the layer above expand slightly inside the unsupported areas.
 | ||||
| 		                			polygons_append(voids, offset(surface.expolygon, unsupported_width)); | ||||
| 		                } | ||||
| 		                surfaces_covered[layer_idx] = diff(to_polygons(this->m_layers[layer_idx]->slices), voids); | ||||
| 		                surfaces_covered[layer_idx] = diff(to_polygons(this->m_layers[layer_idx]->lslices), voids); | ||||
| 	            	} | ||||
| 	        } | ||||
| 	    ); | ||||
|  | @ -985,8 +978,8 @@ void PrintObject::discover_vertical_shells() | |||
|                     cache.bottom_surfaces = union_(cache.bottom_surfaces, false); | ||||
|                     // For a multi-material print, simulate perimeter / infill split as if only a single extruder has been used for the whole print.
 | ||||
|                     if (perimeter_offset > 0.) { | ||||
|                         // The layer.slices are forced to merge by expanding them first.
 | ||||
|                         polygons_append(cache.holes, offset(offset_ex(layer.slices, 0.3f * perimeter_min_spacing), - perimeter_offset - 0.3f * perimeter_min_spacing)); | ||||
|                         // The layer.lslices are forced to merge by expanding them first.
 | ||||
|                         polygons_append(cache.holes, offset(offset_ex(layer.lslices, 0.3f * perimeter_min_spacing), - perimeter_offset - 0.3f * perimeter_min_spacing)); | ||||
| #ifdef SLIC3R_DEBUG_SLICE_PROCESSING | ||||
|                         { | ||||
|                             Slic3r::SVG svg(debug_out_path("discover_vertical_shells-extra-holes-%d.svg", debug_idx), get_extents(layer.slices)); | ||||
|  | @ -1762,78 +1755,101 @@ end: | |||
|     ; | ||||
| 
 | ||||
|     BOOST_LOG_TRIVIAL(debug) << "Slicing objects - make_slices in parallel - begin"; | ||||
|     tbb::parallel_for( | ||||
|         tbb::blocked_range<size_t>(0, m_layers.size()), | ||||
| 		[this, upscaled, clipped](const tbb::blocked_range<size_t>& range) { | ||||
|             for (size_t layer_id = range.begin(); layer_id < range.end(); ++ layer_id) { | ||||
|                 m_print->throw_if_canceled(); | ||||
|                 Layer *layer = m_layers[layer_id]; | ||||
|                 // Apply size compensation and perform clipping of multi-part objects.
 | ||||
|                 float delta = float(scale_(m_config.xy_size_compensation.value)); | ||||
|                 //FIXME only apply the compensation if no raft is enabled.
 | ||||
|                 float elephant_foot_compensation = 0.f; | ||||
|                 if (layer_id == 0 && m_config.raft_layers == 0) | ||||
|                 	// Only enable Elephant foot compensation if printing directly on the print bed.
 | ||||
|                     elephant_foot_compensation = float(scale_(m_config.elefant_foot_compensation.value)); | ||||
|                 if (layer->m_regions.size() == 1) { | ||||
|                     // Optimized version for a single region layer.
 | ||||
|                     if (layer_id == 0) { | ||||
|                         if (delta > elephant_foot_compensation) { | ||||
|                             delta -= elephant_foot_compensation; | ||||
|                             elephant_foot_compensation = 0.f; | ||||
|                         } else if (delta > 0) | ||||
|                             elephant_foot_compensation -= delta; | ||||
|                     } | ||||
|                     if (delta != 0.f || elephant_foot_compensation > 0.f) { | ||||
|                         // Single region, growing or shrinking.
 | ||||
|                         LayerRegion *layerm = layer->m_regions.front(); | ||||
|                         // Apply the XY compensation.
 | ||||
|                         ExPolygons expolygons = (delta == 0.f) ? | ||||
|                             to_expolygons(std::move(layerm->slices.surfaces)) : | ||||
|                             offset_ex(to_expolygons(std::move(layerm->slices.surfaces)), delta); | ||||
|                         // Apply the elephant foot compensation.
 | ||||
|                         if (elephant_foot_compensation > 0) | ||||
| 							expolygons = union_ex(Slic3r::elephant_foot_compensation(expolygons, layerm->flow(frExternalPerimeter), unscale<double>(elephant_foot_compensation))); | ||||
|                         layerm->slices.set(std::move(expolygons), stInternal); | ||||
|                     } | ||||
|                 } else { | ||||
|                     bool upscale   = ! upscaled && delta > 0.f; | ||||
|                     bool clip      = ! clipped && m_config.clip_multipart_objects.value; | ||||
|                     if (upscale || clip) { | ||||
|                         // Multiple regions, growing or just clipping one region by the other.
 | ||||
|                         // When clipping the regions, priority is given to the first regions.
 | ||||
|                         Polygons processed; | ||||
|             			for (size_t region_id = 0; region_id < layer->m_regions.size(); ++ region_id) { | ||||
|                             LayerRegion *layerm = layer->m_regions[region_id]; | ||||
|             				ExPolygons slices = to_expolygons(std::move(layerm->slices.surfaces)); | ||||
|             				if (upscale) | ||||
|             					slices = offset_ex(std::move(slices), delta); | ||||
|                             if (region_id > 0 && clip) | ||||
|                                 // Trim by the slices of already processed regions.
 | ||||
|                                 slices = diff_ex(to_polygons(std::move(slices)), processed); | ||||
|                             if (clip && (region_id + 1 < layer->m_regions.size())) | ||||
|                                 // Collect the already processed regions to trim the to be processed regions.
 | ||||
|                                 polygons_append(processed, slices); | ||||
|                             layerm->slices.set(std::move(slices), stInternal); | ||||
|                         } | ||||
|                     } | ||||
|                     if (delta < 0.f || elephant_foot_compensation > 0.f) { | ||||
|                         // Apply the negative XY compensation.
 | ||||
|                         Polygons trimming; | ||||
|                         static const float eps = float(scale_(m_config.slice_closing_radius.value) * 1.5); | ||||
|                         if (elephant_foot_compensation > 0.f) { | ||||
| 							trimming = to_polygons(Slic3r::elephant_foot_compensation(offset_ex(layer->merged(eps), std::min(delta, 0.f) - eps), | ||||
| 								layer->m_regions.front()->flow(frExternalPerimeter), unscale<double>(elephant_foot_compensation))); | ||||
|                         } else | ||||
| 	                        trimming = offset(layer->merged(float(SCALED_EPSILON)), delta - float(SCALED_EPSILON)); | ||||
|                         for (size_t region_id = 0; region_id < layer->m_regions.size(); ++ region_id) | ||||
|                             layer->m_regions[region_id]->trim_surfaces(trimming); | ||||
|                     } | ||||
|                 } | ||||
|                 // Merge all regions' slices to get islands, chain them by a shortest path.
 | ||||
|                 layer->make_slices(); | ||||
|             } | ||||
|         }); | ||||
|     { | ||||
|         // Compensation value, scaled.
 | ||||
|         const float xy_compensation_scaled 	 			= float(scale_(m_config.xy_size_compensation.value)); | ||||
|         const float elephant_foot_compensation_scaled 	= (m_config.raft_layers == 0) ?  | ||||
|         	// Only enable Elephant foot compensation if printing directly on the print bed.
 | ||||
|             float(scale_(m_config.elefant_foot_compensation.value)) : | ||||
|         	0.f; | ||||
|         // Uncompensated slices for the first layer in case the Elephant foot compensation is applied.
 | ||||
| 	    ExPolygons  lslices_1st_layer; | ||||
| 	    tbb::parallel_for( | ||||
| 	        tbb::blocked_range<size_t>(0, m_layers.size()), | ||||
| 			[this, upscaled, clipped, xy_compensation_scaled, elephant_foot_compensation_scaled, &lslices_1st_layer] | ||||
| 				(const tbb::blocked_range<size_t>& range) { | ||||
| 	            for (size_t layer_id = range.begin(); layer_id < range.end(); ++ layer_id) { | ||||
| 	                m_print->throw_if_canceled(); | ||||
| 	                Layer *layer = m_layers[layer_id]; | ||||
| 	                // Apply size compensation and perform clipping of multi-part objects.
 | ||||
| 	                float elfoot = (layer_id == 0) ? elephant_foot_compensation_scaled : 0.f; | ||||
| 	                if (layer->m_regions.size() == 1) { | ||||
| 	                	assert(! upscaled); | ||||
| 	                	assert(! clipped); | ||||
| 	                    // Optimized version for a single region layer.
 | ||||
| 	                    // Single region, growing or shrinking.
 | ||||
| 	                    LayerRegion *layerm = layer->m_regions.front(); | ||||
| 	                    if (elfoot > 0) { | ||||
| 		                    // Apply the elephant foot compensation and store the 1st layer slices without the Elephant foot compensation applied.
 | ||||
| 		                    lslices_1st_layer = to_expolygons(std::move(layerm->slices.surfaces)); | ||||
| 		                    float delta = xy_compensation_scaled; | ||||
| 	                        if (delta > elfoot) { | ||||
| 	                            delta -= elfoot; | ||||
| 	                            elfoot = 0.f; | ||||
| 	                        } else if (delta > 0) | ||||
| 	                            elfoot -= delta; | ||||
| 							layerm->slices.set( | ||||
| 								union_ex( | ||||
| 									Slic3r::elephant_foot_compensation( | ||||
| 										(delta == 0.f) ? lslices_1st_layer : offset_ex(lslices_1st_layer, delta),  | ||||
| 	                            		layerm->flow(frExternalPerimeter), unscale<double>(elfoot))), | ||||
| 								stInternal); | ||||
| 							if (xy_compensation_scaled != 0.f) | ||||
| 								lslices_1st_layer = offset_ex(std::move(lslices_1st_layer), xy_compensation_scaled); | ||||
| 	                    } else if (xy_compensation_scaled != 0.f) { | ||||
| 	                        // Apply the XY compensation.
 | ||||
| 	                        layerm->slices.set( | ||||
|                                 offset_ex(to_expolygons(std::move(layerm->slices.surfaces)), xy_compensation_scaled), | ||||
| 	                            stInternal); | ||||
| 	                    } | ||||
| 	                } else { | ||||
| 	                    bool upscale   = ! upscaled && xy_compensation_scaled > 0.f; | ||||
| 	                    bool clip      = ! clipped && m_config.clip_multipart_objects.value; | ||||
| 	                    if (upscale || clip) { | ||||
| 	                        // Multiple regions, growing or just clipping one region by the other.
 | ||||
| 	                        // When clipping the regions, priority is given to the first regions.
 | ||||
| 	                        Polygons processed; | ||||
| 	            			for (size_t region_id = 0; region_id < layer->m_regions.size(); ++ region_id) { | ||||
| 	                            LayerRegion *layerm = layer->m_regions[region_id]; | ||||
| 	            				ExPolygons slices = to_expolygons(std::move(layerm->slices.surfaces)); | ||||
| 	            				if (upscale) | ||||
| 	            					slices = offset_ex(std::move(slices), xy_compensation_scaled); | ||||
| 	                            if (region_id > 0 && clip) | ||||
| 	                                // Trim by the slices of already processed regions.
 | ||||
| 	                                slices = diff_ex(to_polygons(std::move(slices)), processed); | ||||
| 	                            if (clip && (region_id + 1 < layer->m_regions.size())) | ||||
| 	                                // Collect the already processed regions to trim the to be processed regions.
 | ||||
| 	                                polygons_append(processed, slices); | ||||
| 	                            layerm->slices.set(std::move(slices), stInternal); | ||||
| 	                        } | ||||
| 	                    } | ||||
| 	                    if (xy_compensation_scaled < 0.f || elfoot > 0.f) { | ||||
| 	                        // Apply the negative XY compensation.
 | ||||
| 	                        Polygons trimming; | ||||
| 	                        static const float eps = float(scale_(m_config.slice_closing_radius.value) * 1.5); | ||||
| 	                        if (elfoot > 0.f) { | ||||
| 	                        	lslices_1st_layer = offset_ex(layer->merged(eps), std::min(xy_compensation_scaled, 0.f) - eps); | ||||
| 								trimming = to_polygons(Slic3r::elephant_foot_compensation(lslices_1st_layer, | ||||
| 									layer->m_regions.front()->flow(frExternalPerimeter), unscale<double>(elfoot))); | ||||
| 	                        } else | ||||
| 		                        trimming = offset(layer->merged(float(SCALED_EPSILON)), xy_compensation_scaled - float(SCALED_EPSILON)); | ||||
| 	                        for (size_t region_id = 0; region_id < layer->m_regions.size(); ++ region_id) | ||||
| 	                            layer->m_regions[region_id]->trim_surfaces(trimming); | ||||
| 	                    } | ||||
| 	                } | ||||
| 	                // Merge all regions' slices to get islands, chain them by a shortest path.
 | ||||
| 	                layer->make_slices(); | ||||
| 	            } | ||||
| 	        }); | ||||
| 	    if (elephant_foot_compensation_scaled > 0.f) { | ||||
| 	    	// The Elephant foot has been compensated, therefore the 1st layer's lslices are shrank with the Elephant foot compensation value.
 | ||||
| 	    	// Store the uncompensated value there.
 | ||||
| 	    	assert(! m_layers.empty()); | ||||
| 	    	assert(m_layers.front()->id() == 0); | ||||
| 			m_layers.front()->lslices = std::move(lslices_1st_layer); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
|     m_print->throw_if_canceled(); | ||||
|     BOOST_LOG_TRIVIAL(debug) << "Slicing objects - make_slices in parallel - end"; | ||||
| } | ||||
|  | @ -2131,7 +2147,7 @@ std::string PrintObject::_fix_slicing_errors() | |||
|     BOOST_LOG_TRIVIAL(debug) << "Slicing objects - fixing slicing errors in parallel - end"; | ||||
| 
 | ||||
|     // remove empty layers from bottom
 | ||||
|     while (! m_layers.empty() && m_layers.front()->slices.empty()) { | ||||
|     while (! m_layers.empty() && (m_layers.front()->lslices.empty() || m_layers.front()->empty())) { | ||||
|         delete m_layers.front(); | ||||
|         m_layers.erase(m_layers.begin()); | ||||
|         m_layers.front()->lower_layer = nullptr; | ||||
|  | @ -2147,7 +2163,7 @@ std::string PrintObject::_fix_slicing_errors() | |||
| // Simplify the sliced model, if "resolution" configuration parameter > 0.
 | ||||
| // The simplification is problematic, because it simplifies the slices independent from each other,
 | ||||
| // which makes the simplified discretization visible on the object surface.
 | ||||
| void PrintObject::_simplify_slices(double distance) | ||||
| void PrintObject::simplify_slices(double distance) | ||||
| { | ||||
|     BOOST_LOG_TRIVIAL(debug) << "Slicing objects - siplifying slices in parallel - begin"; | ||||
|     tbb::parallel_for( | ||||
|  | @ -2160,9 +2176,9 @@ void PrintObject::_simplify_slices(double distance) | |||
|                     layer->m_regions[region_idx]->slices.simplify(distance); | ||||
| 				{ | ||||
| 					ExPolygons simplified; | ||||
| 					for (const ExPolygon& expoly : layer->slices) | ||||
| 					for (const ExPolygon &expoly : layer->lslices) | ||||
| 						expoly.simplify(distance, &simplified); | ||||
| 					layer->slices = std::move(simplified); | ||||
| 					layer->lslices = std::move(simplified); | ||||
| 				} | ||||
|             } | ||||
|         }); | ||||
|  | @ -2194,7 +2210,7 @@ void PrintObject::clip_fill_surfaces() | |||
|         // Detect things that we need to support.
 | ||||
|         // Cummulative slices.
 | ||||
|         Polygons slices; | ||||
|         polygons_append(slices, layer->slices); | ||||
|         polygons_append(slices, layer->lslices); | ||||
|         // Cummulative fill surfaces.
 | ||||
|         Polygons fill_surfaces; | ||||
|         // Solid surfaces to be supported.
 | ||||
|  |  | |||
|  | @ -1,6 +1,5 @@ | |||
| #include "ClipperUtils.hpp" | ||||
| #include "ExtrusionEntityCollection.hpp" | ||||
| #include "PerimeterGenerator.hpp" | ||||
| #include "Layer.hpp" | ||||
| #include "Print.hpp" | ||||
| #include "SupportMaterial.hpp" | ||||
|  | @ -445,8 +444,8 @@ Polygons collect_region_slices_by_type(const Layer &layer, SurfaceType surface_t | |||
| Polygons collect_slices_outer(const Layer &layer) | ||||
| { | ||||
|     Polygons out; | ||||
|     out.reserve(out.size() + layer.slices.size()); | ||||
|     for (const ExPolygon &expoly : layer.slices) | ||||
|     out.reserve(out.size() + layer.lslices.size()); | ||||
|     for (const ExPolygon &expoly : layer.lslices) | ||||
|         out.emplace_back(expoly.contour); | ||||
|     return out; | ||||
| } | ||||
|  | @ -907,9 +906,9 @@ namespace SupportMaterialInternal { | |||
|                     polyline.extend_start(fw); | ||||
|                     polyline.extend_end(fw); | ||||
|                     // Is the straight perimeter segment supported at both sides?
 | ||||
| 					for (size_t i = 0; i < lower_layer.slices.size(); ++ i) | ||||
| 						if (lower_layer.slices_bboxes[i].contains(polyline.first_point()) && lower_layer.slices_bboxes[i].contains(polyline.last_point()) &&  | ||||
| 							lower_layer.slices[i].contains(polyline.first_point()) && lower_layer.slices[i].contains(polyline.last_point())) { | ||||
| 					for (size_t i = 0; i < lower_layer.lslices.size(); ++ i) | ||||
| 						if (lower_layer.lslices_bboxes[i].contains(polyline.first_point()) && lower_layer.lslices_bboxes[i].contains(polyline.last_point()) &&  | ||||
| 							lower_layer.lslices[i].contains(polyline.first_point()) && lower_layer.lslices[i].contains(polyline.last_point())) { | ||||
| 							// Offset a polyline into a thick line.
 | ||||
| 							polygons_append(bridges, offset(polyline, 0.5f * w + 10.f)); | ||||
| 							break; | ||||
|  | @ -998,7 +997,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_ | |||
|             // inflate the polygons over and over.
 | ||||
|             Polygons &covered = buildplate_covered[layer_id]; | ||||
|             covered = buildplate_covered[layer_id - 1]; | ||||
|             polygons_append(covered, offset(lower_layer.slices, scale_(0.01))); | ||||
|             polygons_append(covered, offset(lower_layer.lslices, scale_(0.01))); | ||||
|             covered = union_(covered, false); // don't apply the safety offset.
 | ||||
|         } | ||||
|     } | ||||
|  | @ -1027,7 +1026,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_ | |||
|                 Polygons contact_polygons; | ||||
|                 Polygons slices_margin_cached; | ||||
|                 float    slices_margin_cached_offset = -1.; | ||||
|                 Polygons lower_layer_polygons = (layer_id == 0) ? Polygons() : to_polygons(object.layers()[layer_id-1]->slices); | ||||
|                 Polygons lower_layer_polygons = (layer_id == 0) ? Polygons() : to_polygons(object.layers()[layer_id-1]->lslices); | ||||
|                 // Offset of the lower layer, to trim the support polygons with to calculate dense supports.
 | ||||
|                 float    no_interface_offset = 0.f; | ||||
|                 if (layer_id == 0) { | ||||
|  | @ -1166,7 +1165,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_ | |||
|                                 slices_margin_cached_offset = slices_margin_offset; | ||||
|                                 slices_margin_cached = (slices_margin_offset == 0.f) ?  | ||||
|                                     lower_layer_polygons : | ||||
|                                     offset2(to_polygons(lower_layer.slices), - no_interface_offset * 0.5f, slices_margin_offset + no_interface_offset * 0.5f, SUPPORT_SURFACES_OFFSET_PARAMETERS); | ||||
|                                     offset2(to_polygons(lower_layer.lslices), - no_interface_offset * 0.5f, slices_margin_offset + no_interface_offset * 0.5f, SUPPORT_SURFACES_OFFSET_PARAMETERS); | ||||
|                                 if (! buildplate_covered.empty()) { | ||||
|                                     // Trim the inflated contact surfaces by the top surfaces as well.
 | ||||
|                                     polygons_append(slices_margin_cached, buildplate_covered[layer_id]); | ||||
|  | @ -1573,7 +1572,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::bottom_conta | |||
|             task_group.run([this, &projection, &projection_raw, &layer, &layer_support_area, layer_id] { | ||||
|                 // Remove the areas that touched from the projection that will continue on next, lower, top surfaces.
 | ||||
|     //            Polygons trimming = union_(to_polygons(layer.slices), touching, true);
 | ||||
|                 Polygons trimming = offset(layer.slices, float(SCALED_EPSILON)); | ||||
|                 Polygons trimming = offset(layer.lslices, float(SCALED_EPSILON)); | ||||
|                 projection = diff(projection_raw, trimming, false); | ||||
|     #ifdef SLIC3R_DEBUG | ||||
|                 { | ||||
|  | @ -2105,7 +2104,7 @@ void PrintObjectSupportMaterial::trim_support_layers_by_object( | |||
|                     const Layer &object_layer = *object.layers()[i]; | ||||
|                     if (object_layer.print_z - object_layer.height > support_layer.print_z + gap_extra_above - EPSILON) | ||||
|                         break; | ||||
|                     polygons_append(polygons_trimming, offset(object_layer.slices, gap_xy_scaled, SUPPORT_SURFACES_OFFSET_PARAMETERS)); | ||||
|                     polygons_append(polygons_trimming, offset(object_layer.lslices, gap_xy_scaled, SUPPORT_SURFACES_OFFSET_PARAMETERS)); | ||||
|                 } | ||||
|                 if (! m_slicing_params.soluble_interface) { | ||||
|                     // Collect all bottom surfaces, which will be extruded with a bridging flow.
 | ||||
|  | @ -2218,7 +2217,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::generate_raf | |||
|         // Expand the bases of the support columns in the 1st layer.
 | ||||
|         columns_base->polygons = diff( | ||||
|             offset(columns_base->polygons, inflate_factor_1st_layer), | ||||
|             offset(m_object->layers().front()->slices, (float)scale_(m_gap_xy), SUPPORT_SURFACES_OFFSET_PARAMETERS)); | ||||
|             offset(m_object->layers().front()->lslices, (float)scale_(m_gap_xy), SUPPORT_SURFACES_OFFSET_PARAMETERS)); | ||||
|         if (contacts != nullptr) | ||||
|             columns_base->polygons = diff(columns_base->polygons, interface_polygons); | ||||
|     } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 bubnikv
						bubnikv