mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-30 12:11:15 -06:00 
			
		
		
		
	FDM Print refactoring:
Layer newly remembers bounding boxes of slices, the bounding boxes are used by G-code generator & newly the support generator. Slices are stored as ExPolygons, not ExPolygonCollection.
This commit is contained in:
		
							parent
							
								
									0e325824b1
								
							
						
					
					
						commit
						564eddd99d
					
				
					 12 changed files with 70 additions and 166 deletions
				
			
		|  | @ -13,12 +13,12 @@ typedef std::vector<ExPolygonCollection> ExPolygonCollections; | |||
| 
 | ||||
| class ExPolygonCollection | ||||
| { | ||||
|     public: | ||||
| public: | ||||
|     ExPolygons expolygons; | ||||
|      | ||||
|     ExPolygonCollection() {}; | ||||
|     ExPolygonCollection() {} | ||||
|     ExPolygonCollection(const ExPolygon &expolygon); | ||||
|     ExPolygonCollection(const ExPolygons &expolygons) : expolygons(expolygons) {}; | ||||
|     ExPolygonCollection(const ExPolygons &expolygons) : expolygons(expolygons) {} | ||||
|     operator Points() const; | ||||
|     operator Polygons() const; | ||||
|     operator ExPolygons&(); | ||||
|  |  | |||
|  | @ -117,11 +117,11 @@ 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.expolygons.size() + layer2->slices.expolygons.size()); | ||||
|                     for (const ExPolygon &expoly : layer1->slices.expolygons) | ||||
|                      polys.reserve(layer1->slices.size() + layer2->slices.size()); | ||||
|                     for (const ExPolygon &expoly : layer1->slices) | ||||
|                         //FIXME no holes?
 | ||||
|                         polys.emplace_back(expoly.contour); | ||||
|                     for (const ExPolygon &expoly : layer2->slices.expolygons) | ||||
|                     for (const ExPolygon &expoly : layer2->slices) | ||||
|                         //FIXME no holes?
 | ||||
|                         polys.emplace_back(expoly.contour); | ||||
|                      polygons_per_layer[i] = union_(polys); | ||||
|  | @ -130,8 +130,8 @@ Polygons AvoidCrossingPerimeters::collect_contours_all_layers(const PrintObjectP | |||
|          if (object->layers().size() & 1) { | ||||
|             const Layer *layer = object->layers().back(); | ||||
|             Polygons polys; | ||||
|             polys.reserve(layer->slices.expolygons.size()); | ||||
|             for (const ExPolygon &expoly : layer->slices.expolygons) | ||||
|             polys.reserve(layer->slices.size()); | ||||
|             for (const ExPolygon &expoly : layer->slices) | ||||
|                 //FIXME no holes?
 | ||||
|                 polys.emplace_back(expoly.contour); | ||||
|              polygons_per_layer.back() = union_(polys); | ||||
|  | @ -1802,11 +1802,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.expolygons.size(); | ||||
|             std::vector<BoundingBox> layer_surface_bboxes; | ||||
|             layer_surface_bboxes.reserve(n_slices); | ||||
|             for (const ExPolygon &expoly : layer.slices.expolygons) | ||||
|                 layer_surface_bboxes.push_back(get_extents(expoly.contour)); | ||||
|             size_t n_slices = layer.slices.size(); | ||||
|             const std::vector<BoundingBox> &layer_surface_bboxes = layer.slices_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; | ||||
|  | @ -1822,7 +1819,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.expolygons[i].contour.contains(point); | ||||
|                        layer.slices[i].contour.contains(point); | ||||
|             }; | ||||
| 
 | ||||
|             for (size_t region_id = 0; region_id < print.regions().size(); ++ region_id) { | ||||
|  | @ -2418,7 +2415,7 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou | |||
|             static int iRun = 0; | ||||
|             SVG svg(debug_out_path("GCode_extrude_loop-%d.svg", iRun ++)); | ||||
|             if (m_layer->lower_layer != NULL) | ||||
|                 svg.draw(m_layer->lower_layer->slices.expolygons); | ||||
|                 svg.draw(m_layer->lower_layer->slices); | ||||
|             for (size_t i = 0; i < loop.paths.size(); ++ i) | ||||
|                 svg.draw(loop.paths[i].as_polyline(), "red"); | ||||
|             Polylines polylines; | ||||
|  |  | |||
|  | @ -47,8 +47,8 @@ void Layer::make_slices() | |||
|         slices = union_ex(slices_p); | ||||
|     } | ||||
|      | ||||
|     this->slices.expolygons.clear(); | ||||
|     this->slices.expolygons.reserve(slices.size()); | ||||
|     this->slices.clear(); | ||||
|     this->slices.reserve(slices.size()); | ||||
|      | ||||
|     // prepare ordering points
 | ||||
|     Points ordering_points; | ||||
|  | @ -61,7 +61,7 @@ void Layer::make_slices() | |||
|      | ||||
|     // populate slices vector
 | ||||
|     for (size_t i : order) | ||||
|         this->slices.expolygons.push_back(std::move(slices[i])); | ||||
|         this->slices.push_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.
 | ||||
|  | @ -70,7 +70,7 @@ void Layer::merge_slices() | |||
|     if (m_regions.size() == 1) { | ||||
|         // 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.expolygons, stInternal); | ||||
|         m_regions.front()->slices.set(this->slices, stInternal); | ||||
|     } else { | ||||
|         for (LayerRegion *layerm : m_regions) | ||||
|             // without safety offset, artifacts are generated (GH #2494)
 | ||||
|  |  | |||
|  | @ -110,7 +110,8 @@ public: | |||
|     // 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.
 | ||||
|     ExPolygonCollection slices; | ||||
|     ExPolygons 			slices; | ||||
|     std::vector<BoundingBox> slices_bboxes; | ||||
| 
 | ||||
|     size_t                  region_count() const { return m_regions.size(); } | ||||
|     const LayerRegion*      get_region(int idx) const { return m_regions.at(idx); } | ||||
|  |  | |||
|  | @ -140,7 +140,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.expolygons); | ||||
|             	lower_layer_covered_tmp = to_polygons(lower_layer->slices); | ||||
|             } | ||||
|             if (! lower_layer_covered->empty()) | ||||
|             	voids = diff(voids, *lower_layer_covered); | ||||
|  |  | |||
|  | @ -3,7 +3,6 @@ | |||
| 
 | ||||
| #include "libslic3r.h" | ||||
| #include <vector> | ||||
| #include "ExPolygonCollection.hpp" | ||||
| #include "Flow.hpp" | ||||
| #include "Polygon.hpp" | ||||
| #include "PrintConfig.hpp" | ||||
|  | @ -15,7 +14,7 @@ class PerimeterGenerator { | |||
| public: | ||||
|     // Inputs:
 | ||||
|     const SurfaceCollection     *slices; | ||||
|     const ExPolygonCollection   *lower_slices; | ||||
|     const ExPolygons            *lower_slices; | ||||
|     double                       layer_height; | ||||
|     int                          layer_id; | ||||
|     Flow                         perimeter_flow; | ||||
|  | @ -45,7 +44,7 @@ public: | |||
|         ExtrusionEntityCollection*  gap_fill, | ||||
|         // Infills without the gap fills
 | ||||
|         SurfaceCollection*          fill_surfaces) | ||||
|         : slices(slices), lower_slices(NULL), layer_height(layer_height), | ||||
|         : slices(slices), lower_slices(nullptr), layer_height(layer_height), | ||||
|             layer_id(-1), perimeter_flow(flow), ext_perimeter_flow(flow), | ||||
|             overhang_flow(flow), solid_infill_flow(flow), | ||||
|             config(config), object_config(object_config), print_config(print_config), | ||||
|  |  | |||
|  | @ -328,17 +328,6 @@ unsigned int Print::num_object_instances() const | |||
|     return instances; | ||||
| } | ||||
| 
 | ||||
| void Print::_simplify_slices(double distance) | ||||
| { | ||||
|     for (PrintObject *object : m_objects) { | ||||
|         for (Layer *layer : object->m_layers) { | ||||
|             layer->slices.simplify(distance); | ||||
|             for (LayerRegion *layerm : layer->regions()) | ||||
|                 layerm->slices.simplify(distance); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| double Print::max_allowed_layer_height() const | ||||
| { | ||||
|     double nozzle_diameter_max = 0.; | ||||
|  | @ -1593,7 +1582,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.expolygons) | ||||
|             for (const ExPolygon &expoly : layer->slices) | ||||
|                 // Collect the outer contour points only, ignore holes for the calculation of the convex hull.
 | ||||
|                 append(object_points, expoly.contour.points); | ||||
|         } | ||||
|  | @ -1704,7 +1693,7 @@ void Print::_make_brim() | |||
|     Polygons    islands; | ||||
|     for (PrintObject *object : m_objects) { | ||||
|         Polygons object_islands; | ||||
|         for (ExPolygon &expoly : object->m_layers.front()->slices.expolygons) | ||||
|         for (ExPolygon &expoly : object->m_layers.front()->slices) | ||||
|             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)); | ||||
|  |  | |||
|  | @ -180,7 +180,6 @@ private: | |||
|     void _slice(const std::vector<coordf_t> &layer_height_profile); | ||||
|     std::string _fix_slicing_errors(); | ||||
|     void _simplify_slices(double distance); | ||||
|     void _make_perimeters(); | ||||
|     bool has_support_material() const; | ||||
|     void detect_surfaces_type(); | ||||
|     void process_external_surfaces(); | ||||
|  | @ -383,7 +382,6 @@ private: | |||
|     void                _make_skirt(); | ||||
|     void                _make_brim(); | ||||
|     void                _make_wipe_tower(); | ||||
|     void                _simplify_slices(double distance); | ||||
| 
 | ||||
|     // Declared here to have access to Model / ModelObject / ModelInstance
 | ||||
|     static void         model_volume_list_update_supports(ModelObject &model_object_dst, const ModelObject &model_object_src); | ||||
|  |  | |||
|  | @ -117,6 +117,19 @@ void PrintObject::slice() | |||
|     // Simplify slices if required.
 | ||||
|     if (m_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()), | ||||
|         [this](const tbb::blocked_range<size_t>& range) { | ||||
|             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)); | ||||
|             } | ||||
|         }); | ||||
|     if (m_layers.empty()) | ||||
|         throw std::runtime_error("No layers were detected. You might want to repair your STL file(s) or check their size or thickness and retry.\n");     | ||||
|     this->set_done(posSlice); | ||||
|  | @ -865,7 +878,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.expolygons), voids); | ||||
| 		                surfaces_covered[layer_idx] = diff(to_polygons(this->m_layers[layer_idx]->slices), voids); | ||||
| 	            	} | ||||
| 	        } | ||||
| 	    ); | ||||
|  | @ -975,8 +988,8 @@ void PrintObject::discover_vertical_shells() | |||
|                         polygons_append(cache.holes, offset(offset_ex(layer.slices, 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.expolygons)); | ||||
|                             svg.draw(layer.slices.expolygons, "blue"); | ||||
|                             Slic3r::SVG svg(debug_out_path("discover_vertical_shells-extra-holes-%d.svg", debug_idx), get_extents(layer.slices)); | ||||
|                             svg.draw(layer.slices, "blue"); | ||||
|                             svg.draw(union_ex(cache.holes), "red"); | ||||
|                             svg.draw_outline(union_ex(cache.holes), "black", "blue", scale_(0.05)); | ||||
|                             svg.Close();  | ||||
|  | @ -2141,7 +2154,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.expolygons.empty()) { | ||||
|     while (! m_layers.empty() && m_layers.front()->slices.empty()) { | ||||
|         delete m_layers.front(); | ||||
|         m_layers.erase(m_layers.begin()); | ||||
|         m_layers.front()->lower_layer = nullptr; | ||||
|  | @ -2168,115 +2181,17 @@ void PrintObject::_simplify_slices(double distance) | |||
|                 Layer *layer = m_layers[layer_idx]; | ||||
|                 for (size_t region_idx = 0; region_idx < layer->m_regions.size(); ++ region_idx) | ||||
|                     layer->m_regions[region_idx]->slices.simplify(distance); | ||||
|                 layer->slices.simplify(distance); | ||||
| 				{ | ||||
| 					ExPolygons simplified; | ||||
| 					for (const ExPolygon& expoly : layer->slices) | ||||
| 						expoly.simplify(distance, &simplified); | ||||
| 					layer->slices = std::move(simplified); | ||||
| 				} | ||||
|             } | ||||
|         }); | ||||
|     BOOST_LOG_TRIVIAL(debug) << "Slicing objects - siplifying slices in parallel - end"; | ||||
| } | ||||
| 
 | ||||
| void PrintObject::_make_perimeters() | ||||
| { | ||||
|     if (! this->set_started(posPerimeters)) | ||||
|         return; | ||||
| 
 | ||||
|     BOOST_LOG_TRIVIAL(info) << "Generating perimeters..." << log_memory_info(); | ||||
|      | ||||
|     // merge slices if they were split into types
 | ||||
|     if (this->typed_slices) { | ||||
|         for (Layer *layer : m_layers) | ||||
|             layer->merge_slices(); | ||||
|         this->typed_slices = false; | ||||
|         this->invalidate_step(posPrepareInfill); | ||||
|     } | ||||
|      | ||||
|     // compare each layer to the one below, and mark those slices needing
 | ||||
|     // one additional inner perimeter, like the top of domed objects-
 | ||||
|      | ||||
|     // this algorithm makes sure that at least one perimeter is overlapping
 | ||||
|     // but we don't generate any extra perimeter if fill density is zero, as they would be floating
 | ||||
|     // inside the object - infill_only_where_needed should be the method of choice for printing
 | ||||
|     // hollow objects
 | ||||
|     for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) { | ||||
|         const PrintRegion ®ion = *m_print->regions()[region_id]; | ||||
|         if (! region.config().extra_perimeters || region.config().perimeters == 0 || region.config().fill_density == 0 || this->layer_count() < 2) | ||||
|             continue; | ||||
|          | ||||
|         BOOST_LOG_TRIVIAL(debug) << "Generating extra perimeters for region " << region_id << " in parallel - start"; | ||||
|         tbb::parallel_for( | ||||
|             tbb::blocked_range<size_t>(0, m_layers.size() - 1), | ||||
|             [this, ®ion, region_id](const tbb::blocked_range<size_t>& range) { | ||||
|                 for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx) { | ||||
|                     LayerRegion &layerm                     = *m_layers[layer_idx]->regions()[region_id]; | ||||
|                     const LayerRegion &upper_layerm         = *m_layers[layer_idx+1]->regions()[region_id]; | ||||
|                     const Polygons upper_layerm_polygons    = upper_layerm.slices; | ||||
|                     // Filter upper layer polygons in intersection_ppl by their bounding boxes?
 | ||||
|                     // my $upper_layerm_poly_bboxes= [ map $_->bounding_box, @{$upper_layerm_polygons} ];
 | ||||
|                     const double total_loop_length      = total_length(upper_layerm_polygons); | ||||
|                     const coord_t perimeter_spacing     = layerm.flow(frPerimeter).scaled_spacing(); | ||||
|                     const Flow ext_perimeter_flow       = layerm.flow(frExternalPerimeter); | ||||
|                     const coord_t ext_perimeter_width   = ext_perimeter_flow.scaled_width(); | ||||
|                     const coord_t ext_perimeter_spacing = ext_perimeter_flow.scaled_spacing(); | ||||
| 
 | ||||
|                     for (Surface &slice : layerm.slices.surfaces) { | ||||
|                         for (;;) { | ||||
|                             // compute the total thickness of perimeters
 | ||||
|                             const coord_t perimeters_thickness = ext_perimeter_width/2 + ext_perimeter_spacing/2 | ||||
|                                 + (region.config().perimeters-1 + slice.extra_perimeters) * perimeter_spacing; | ||||
|                             // define a critical area where we don't want the upper slice to fall into
 | ||||
|                             // (it should either lay over our perimeters or outside this area)
 | ||||
|                             const coord_t critical_area_depth = coord_t(perimeter_spacing * 1.5); | ||||
|                             const Polygons critical_area = diff( | ||||
|                                 offset(slice.expolygon, float(- perimeters_thickness)), | ||||
|                                 offset(slice.expolygon, float(- perimeters_thickness - critical_area_depth)) | ||||
|                             ); | ||||
|                             // check whether a portion of the upper slices falls inside the critical area
 | ||||
|                             const Polylines intersection = intersection_pl(to_polylines(upper_layerm_polygons), critical_area); | ||||
|                             // only add an additional loop if at least 30% of the slice loop would benefit from it
 | ||||
|                             if (total_length(intersection) <=  total_loop_length*0.3) | ||||
|                                 break; | ||||
|                             /*
 | ||||
|                             if (0) { | ||||
|                                 require "Slic3r/SVG.pm"; | ||||
|                                 Slic3r::SVG::output( | ||||
|                                     "extra.svg", | ||||
|                                     no_arrows   => 1, | ||||
|                                     expolygons  => union_ex($critical_area), | ||||
|                                     polylines   => [ map $_->split_at_first_point, map $_->p, @{$upper_layerm->slices} ], | ||||
|                                 ); | ||||
|                             } | ||||
|                             */ | ||||
|                             ++ slice.extra_perimeters; | ||||
|                         } | ||||
|                         #ifdef DEBUG | ||||
|                             if (slice.extra_perimeters > 0) | ||||
|                                 printf("  adding %d more perimeter(s) at layer %zu\n", slice.extra_perimeters, layer_idx); | ||||
|                         #endif | ||||
|                     } | ||||
|                 } | ||||
|             }); | ||||
|         BOOST_LOG_TRIVIAL(debug) << "Generating extra perimeters for region " << region_id << " in parallel - end"; | ||||
|     } | ||||
| 
 | ||||
|     BOOST_LOG_TRIVIAL(debug) << "Generating perimeters in parallel - start"; | ||||
|     tbb::parallel_for( | ||||
|         tbb::blocked_range<size_t>(0, m_layers.size()), | ||||
|         [this](const tbb::blocked_range<size_t>& range) { | ||||
|             for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx) | ||||
|                 m_layers[layer_idx]->make_perimeters(); | ||||
|         } | ||||
|     ); | ||||
|     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); | ||||
| } | ||||
| 
 | ||||
| // Only active if config->infill_only_where_needed. This step trims the sparse infill,
 | ||||
| // so it acts as an internal support. It maintains all other infill types intact.
 | ||||
| // Here the internal surfaces and perimeters have to be supported by the sparse infill.
 | ||||
|  | @ -2302,7 +2217,7 @@ void PrintObject::clip_fill_surfaces() | |||
|         // Detect things that we need to support.
 | ||||
|         // Cummulative slices.
 | ||||
|         Polygons slices; | ||||
|         polygons_append(slices, layer->slices.expolygons); | ||||
|         polygons_append(slices, layer->slices); | ||||
|         // Cummulative fill surfaces.
 | ||||
|         Polygons fill_surfaces; | ||||
|         // Solid surfaces to be supported.
 | ||||
|  |  | |||
|  | @ -445,8 +445,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.expolygons.size()); | ||||
|     for (const ExPolygon &expoly : layer.slices.expolygons) | ||||
|     out.reserve(out.size() + layer.slices.size()); | ||||
|     for (const ExPolygon &expoly : layer.slices) | ||||
|         out.emplace_back(expoly.contour); | ||||
|     return out; | ||||
| } | ||||
|  | @ -907,9 +907,13 @@ namespace SupportMaterialInternal { | |||
|                     polyline.extend_start(fw); | ||||
|                     polyline.extend_end(fw); | ||||
|                     // Is the straight perimeter segment supported at both sides?
 | ||||
|                     if (lower_layer.slices.contains(polyline.first_point()) && lower_layer.slices.contains(polyline.last_point())) | ||||
|                         // Offset a polyline into a thick line.
 | ||||
|                         polygons_append(bridges, offset(polyline, 0.5f * w + 10.f)); | ||||
| 					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())) { | ||||
| 							// Offset a polyline into a thick line.
 | ||||
| 							polygons_append(bridges, offset(polyline, 0.5f * w + 10.f)); | ||||
| 							break; | ||||
| 						} | ||||
|                 } | ||||
|             bridges = union_(bridges); | ||||
|         } | ||||
|  | @ -994,7 +998,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.expolygons, scale_(0.01))); | ||||
|             polygons_append(covered, offset(lower_layer.slices, scale_(0.01))); | ||||
|             covered = union_(covered, false); // don't apply the safety offset.
 | ||||
|         } | ||||
|     } | ||||
|  | @ -1023,7 +1027,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.expolygons); | ||||
|                 Polygons lower_layer_polygons = (layer_id == 0) ? Polygons() : to_polygons(object.layers()[layer_id-1]->slices); | ||||
|                 // 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) { | ||||
|  | @ -1162,7 +1166,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.expolygons), - no_interface_offset * 0.5f, slices_margin_offset + no_interface_offset * 0.5f, SUPPORT_SURFACES_OFFSET_PARAMETERS); | ||||
|                                     offset2(to_polygons(lower_layer.slices), - 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]); | ||||
|  | @ -1468,7 +1472,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::bottom_conta | |||
|                         svg.draw(union_ex(top, false), "blue", 0.5f); | ||||
|                         svg.draw(union_ex(projection_raw, true), "red", 0.5f); | ||||
|                         svg.draw_outline(union_ex(projection_raw, true), "red", "blue", scale_(0.1f)); | ||||
|                         svg.draw(layer.slices.expolygons, "green", 0.5f); | ||||
|                         svg.draw(layer.slices, "green", 0.5f); | ||||
|                     } | ||||
|         #endif /* SLIC3R_DEBUG */ | ||||
| 
 | ||||
|  | @ -1568,8 +1572,8 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::bottom_conta | |||
|             Polygons &layer_support_area = layer_support_areas[layer_id]; | ||||
|             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.expolygons), touching, true);
 | ||||
|                 Polygons trimming = offset(layer.slices.expolygons, float(SCALED_EPSILON)); | ||||
|     //            Polygons trimming = union_(to_polygons(layer.slices), touching, true);
 | ||||
|                 Polygons trimming = offset(layer.slices, float(SCALED_EPSILON)); | ||||
|                 projection = diff(projection_raw, trimming, false); | ||||
|     #ifdef SLIC3R_DEBUG | ||||
|                 { | ||||
|  | @ -2101,7 +2105,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.expolygons, gap_xy_scaled, SUPPORT_SURFACES_OFFSET_PARAMETERS)); | ||||
|                     polygons_append(polygons_trimming, offset(object_layer.slices, 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.
 | ||||
|  | @ -2214,7 +2218,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.expolygons, (float)scale_(m_gap_xy), SUPPORT_SURFACES_OFFSET_PARAMETERS)); | ||||
|             offset(m_object->layers().front()->slices, (float)scale_(m_gap_xy), SUPPORT_SURFACES_OFFSET_PARAMETERS)); | ||||
|         if (contacts != nullptr) | ||||
|             columns_base->polygons = diff(columns_base->polygons, interface_polygons); | ||||
|     } | ||||
|  |  | |||
|  | @ -3,6 +3,7 @@ | |||
| %{ | ||||
| #include <xsinit.h> | ||||
| #include "libslic3r/Layer.hpp" | ||||
| #include "libslic3r/ExPolygonCollection.hpp" | ||||
| %} | ||||
| 
 | ||||
| %name{Slic3r::Layer::Region} class LayerRegion { | ||||
|  | @ -59,8 +60,8 @@ | |||
|     Ref<LayerRegion> get_region(int idx); | ||||
|     Ref<LayerRegion> add_region(PrintRegion* print_region); | ||||
| 
 | ||||
|     Ref<ExPolygonCollection> slices() | ||||
|         %code%{ RETVAL = &THIS->slices; %}; | ||||
|     ExPolygonCollection* slices() | ||||
|         %code%{ RETVAL = new ExPolygonCollection(THIS->slices); %}; | ||||
| 
 | ||||
|     int ptr() | ||||
|         %code%{ RETVAL = (int)(intptr_t)THIS; %}; | ||||
|  | @ -108,8 +109,8 @@ | |||
|     Ref<LayerRegion> get_region(int idx); | ||||
|     Ref<LayerRegion> add_region(PrintRegion* print_region); | ||||
| 
 | ||||
|     Ref<ExPolygonCollection> slices() | ||||
|         %code%{ RETVAL = &THIS->slices; %}; | ||||
|     ExPolygonCollection* slices() | ||||
|         %code%{ RETVAL = new ExPolygonCollection(THIS->slices); %}; | ||||
|      | ||||
|     void export_region_slices_to_svg(const char *path); | ||||
|     void export_region_fill_surfaces_to_svg(const char *path); | ||||
|  |  | |||
|  | @ -19,7 +19,7 @@ | |||
|     ~PerimeterGenerator(); | ||||
|      | ||||
|     void set_lower_slices(ExPolygonCollection* lower_slices) | ||||
|         %code{% THIS->lower_slices = lower_slices; %}; | ||||
|         %code{% THIS->lower_slices = &lower_slices->expolygons; %}; | ||||
|     void set_layer_id(int layer_id) | ||||
|         %code{% THIS->layer_id = layer_id; %}; | ||||
|     void set_perimeter_flow(Flow* flow) | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 bubnikv
						bubnikv