mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-31 04:31:15 -06:00 
			
		
		
		
	ENH: speed up the wall generator process by using bounding box
Signed-off-by: qing.zhang <qing.zhang@bambulab.com> Change-Id: Ifccbb33bc6df28136746f98020ef2cad002b5868
This commit is contained in:
		
							parent
							
								
									aba824bbb9
								
							
						
					
					
						commit
						fdd659cefe
					
				
					 3 changed files with 122 additions and 11 deletions
				
			
		|  | @ -57,8 +57,96 @@ err: | |||
| #endif /* CLIPPER_UTILS_DEBUG */ | ||||
| 
 | ||||
| namespace ClipperUtils { | ||||
|     Points EmptyPathsProvider::s_empty_points; | ||||
|     Points SinglePathProvider::s_end; | ||||
| Points EmptyPathsProvider::s_empty_points; | ||||
| Points SinglePathProvider::s_end; | ||||
| 
 | ||||
| // Clip source polygon to be used as a clipping polygon with a bouding box around the source (to be clipped) polygon.
 | ||||
| // Useful as an optimization for expensive ClipperLib operations, for example when clipping source polygons one by one
 | ||||
| // with a set of polygons covering the whole layer below.
 | ||||
| template<typename PointType> inline void clip_clipper_polygon_with_subject_bbox_templ(const std::vector<PointType> &src, const BoundingBox &bbox, std::vector<PointType> &out) | ||||
| { | ||||
|     out.clear(); | ||||
|     const size_t cnt = src.size(); | ||||
|     if (cnt < 3) return; | ||||
| 
 | ||||
|     enum class Side { Left = 1, Right = 2, Top = 4, Bottom = 8 }; | ||||
| 
 | ||||
|     auto sides = [bbox](const PointType &p) { | ||||
|         return int(p.x() < bbox.min.x()) * int(Side::Left) + int(p.x() > bbox.max.x()) * int(Side::Right) + int(p.y() < bbox.min.y()) * int(Side::Bottom) + | ||||
|                int(p.y() > bbox.max.y()) * int(Side::Top); | ||||
|     }; | ||||
| 
 | ||||
|     int          sides_prev = sides(src.back()); | ||||
|     int          sides_this = sides(src.front()); | ||||
|     const size_t last       = cnt - 1; | ||||
|     for (size_t i = 0; i < last; ++i) { | ||||
|         int sides_next = sides(src[i + 1]); | ||||
|         if ( // This point is inside. Take it.
 | ||||
|             sides_this == 0 || | ||||
|             // Either this point is outside and previous or next is inside, or
 | ||||
|             // the edge possibly cuts corner of the bounding box.
 | ||||
|             (sides_prev & sides_this & sides_next) == 0) { | ||||
|             out.emplace_back(src[i]); | ||||
|             sides_prev = sides_this; | ||||
|         } else { | ||||
|             // All the three points (this, prev, next) are outside at the same side.
 | ||||
|             // Ignore this point.
 | ||||
|         } | ||||
|         sides_this = sides_next; | ||||
|     } | ||||
| 
 | ||||
|     // Never produce just a single point output polygon.
 | ||||
|     if (!out.empty()) | ||||
|         if (int sides_next = sides(out.front()); | ||||
|             // The last point is inside. Take it.
 | ||||
|             sides_this == 0 || | ||||
|             // Either this point is outside and previous or next is inside, or
 | ||||
|             // the edge possibly cuts corner of the bounding box.
 | ||||
|             (sides_prev & sides_this & sides_next) == 0) | ||||
|             out.emplace_back(src.back()); | ||||
| } | ||||
| 
 | ||||
|     void clip_clipper_polygon_with_subject_bbox(const Points &src, const BoundingBox &bbox, Points &out) { clip_clipper_polygon_with_subject_bbox_templ(src, bbox, out); } | ||||
| void clip_clipper_polygon_with_subject_bbox(const ZPoints &src, const BoundingBox &bbox, ZPoints &out) { clip_clipper_polygon_with_subject_bbox_templ(src, bbox, out); } | ||||
| 
 | ||||
| template<typename PointType> [[nodiscard]] std::vector<PointType> clip_clipper_polygon_with_subject_bbox_templ(const std::vector<PointType> &src, const BoundingBox &bbox) | ||||
| { | ||||
|     std::vector<PointType> out; | ||||
|     clip_clipper_polygon_with_subject_bbox(src, bbox, out); | ||||
|     return out; | ||||
| } | ||||
| 
 | ||||
| [[nodiscard]] Points  clip_clipper_polygon_with_subject_bbox(const Points &src, const BoundingBox &bbox) { return clip_clipper_polygon_with_subject_bbox_templ(src, bbox); } | ||||
| [[nodiscard]] ZPoints clip_clipper_polygon_with_subject_bbox(const ZPoints &src, const BoundingBox &bbox) { return clip_clipper_polygon_with_subject_bbox_templ(src, bbox); } | ||||
| 
 | ||||
| void clip_clipper_polygon_with_subject_bbox(const Polygon &src, const BoundingBox &bbox, Polygon &out) {  | ||||
|     clip_clipper_polygon_with_subject_bbox(src.points, bbox, out.points); | ||||
| } | ||||
| 
 | ||||
| [[nodiscard]] Polygon clip_clipper_polygon_with_subject_bbox(const Polygon &src, const BoundingBox &bbox) | ||||
| { | ||||
|     Polygon out; | ||||
|     clip_clipper_polygon_with_subject_bbox(src.points, bbox, out.points); | ||||
|     return out; | ||||
| } | ||||
| 
 | ||||
| [[nodiscard]] Polygons clip_clipper_polygons_with_subject_bbox(const Polygons &src, const BoundingBox &bbox) | ||||
| { | ||||
|     Polygons out; | ||||
|     out.reserve(src.size()); | ||||
|     for (const Polygon &p : src) out.emplace_back(clip_clipper_polygon_with_subject_bbox(p, bbox)); | ||||
|     out.erase(std::remove_if(out.begin(), out.end(), [](const Polygon &polygon) { return polygon.empty(); }), out.end()); | ||||
|     return out; | ||||
| } | ||||
| [[nodiscard]] Polygons clip_clipper_polygons_with_subject_bbox(const ExPolygon &src, const BoundingBox &bbox) | ||||
| { | ||||
|     Polygons out; | ||||
|     out.reserve(src.num_contours()); | ||||
|     out.emplace_back(clip_clipper_polygon_with_subject_bbox(src.contour, bbox)); | ||||
|     for (const Polygon &p : src.holes) out.emplace_back(clip_clipper_polygon_with_subject_bbox(p, bbox)); | ||||
|     out.erase(std::remove_if(out.begin(), out.end(), [](const Polygon &polygon) { return polygon.empty(); }), out.end()); | ||||
|     return out; | ||||
| } | ||||
| } | ||||
| 
 | ||||
| static ExPolygons PolyTreeToExPolygons(ClipperLib::PolyTree &&polytree) | ||||
|  |  | |||
|  | @ -296,7 +296,25 @@ namespace ClipperUtils { | |||
|         const SurfacesPtr &m_surfaces; | ||||
|         size_t             m_size; | ||||
|     }; | ||||
| } | ||||
| 
 | ||||
|      | ||||
|     // For ClipperLib with Z coordinates.
 | ||||
|     using ZPoint  = Vec3i32; | ||||
|     using ZPoints = std::vector<Vec3i32>; | ||||
| 
 | ||||
|     // Clip source polygon to be used as a clipping polygon with a bouding box around the source (to be clipped) polygon.
 | ||||
|     // Useful as an optimization for expensive ClipperLib operations, for example when clipping source polygons one by one
 | ||||
|     // with a set of polygons covering the whole layer below.
 | ||||
|     void                   clip_clipper_polygon_with_subject_bbox(const Points &src, const BoundingBox &bbox, Points &out); | ||||
|     void                   clip_clipper_polygon_with_subject_bbox(const ZPoints &src, const BoundingBox &bbox, ZPoints &out); | ||||
|     [[nodiscard]] Points   clip_clipper_polygon_with_subject_bbox(const Points &src, const BoundingBox &bbox); | ||||
|     [[nodiscard]] ZPoints  clip_clipper_polygon_with_subject_bbox(const ZPoints &src, const BoundingBox &bbox); | ||||
|     void                   clip_clipper_polygon_with_subject_bbox(const Polygon &src, const BoundingBox &bbox, Polygon &out); | ||||
|     [[nodiscard]] Polygon  clip_clipper_polygon_with_subject_bbox(const Polygon &src, const BoundingBox &bbox); | ||||
|     [[nodiscard]] Polygons clip_clipper_polygons_with_subject_bbox(const Polygons &src, const BoundingBox &bbox); | ||||
|     [[nodiscard]] Polygons clip_clipper_polygons_with_subject_bbox(const ExPolygon &src, const BoundingBox &bbox); | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
| // Perform union of input polygons using the non-zero rule, convert to ExPolygons.
 | ||||
| ExPolygons ClipperPaths_to_Slic3rExPolygons(const ClipperLib::Paths &input, bool do_union = false); | ||||
|  |  | |||
|  | @ -268,6 +268,10 @@ static ExtrusionEntityCollection traverse_loops(const PerimeterGenerator &perime | |||
|         } | ||||
|         if (perimeter_generator.config->detect_overhang_wall && perimeter_generator.layer_id > perimeter_generator.object_config->raft_layers) { | ||||
|             // get non 100% overhang paths by intersecting this loop with the grown lower slices
 | ||||
|             // prepare grown lower layer slices for overhang detection
 | ||||
|             BoundingBox bbox(polygon.points); | ||||
|             bbox.offset(SCALED_EPSILON); | ||||
| 
 | ||||
|             Polylines remain_polines; | ||||
| 
 | ||||
|             //BBS: don't calculate overhang degree when enable fuzzy skin. It's unmeaning
 | ||||
|  | @ -275,10 +279,10 @@ static ExtrusionEntityCollection traverse_loops(const PerimeterGenerator &perime | |||
|                 for (auto it = lower_polygons_series->begin(); | ||||
|                     it != lower_polygons_series->end(); it++) | ||||
|                 { | ||||
|                     Polygons lower_polygons_series_clipped = ClipperUtils::clip_clipper_polygons_with_subject_bbox(it->second, bbox); | ||||
| 
 | ||||
|                     Polylines inside_polines = (it == lower_polygons_series->begin()) ? | ||||
|                         intersection_pl({ polygon }, it->second) : | ||||
|                         intersection_pl(remain_polines, it->second); | ||||
|                     Polylines inside_polines = (it == lower_polygons_series->begin()) ? intersection_pl({polygon}, lower_polygons_series_clipped) : | ||||
|                                                                                         intersection_pl(remain_polines, lower_polygons_series_clipped); | ||||
|                     extrusion_paths_append( | ||||
|                         paths, | ||||
|                         std::move(inside_polines), | ||||
|  | @ -289,9 +293,8 @@ static ExtrusionEntityCollection traverse_loops(const PerimeterGenerator &perime | |||
|                         extrusion_width, | ||||
|                         (float)perimeter_generator.layer_height); | ||||
| 
 | ||||
|                     remain_polines = (it == lower_polygons_series->begin()) ? | ||||
|                         diff_pl({ polygon }, it->second) : | ||||
|                         diff_pl(remain_polines, it->second); | ||||
|                     remain_polines = (it == lower_polygons_series->begin()) ? diff_pl({polygon}, lower_polygons_series_clipped) : | ||||
|                                                                               diff_pl(remain_polines, lower_polygons_series_clipped); | ||||
| 
 | ||||
|                     if (remain_polines.size() == 0) | ||||
|                         break; | ||||
|  | @ -299,7 +302,9 @@ static ExtrusionEntityCollection traverse_loops(const PerimeterGenerator &perime | |||
|             } else { | ||||
|                 auto it = lower_polygons_series->end(); | ||||
|                 it--; | ||||
|                 Polylines inside_polines = intersection_pl({ polygon }, it->second); | ||||
|                 Polygons lower_polygons_series_clipped = ClipperUtils::clip_clipper_polygons_with_subject_bbox(it->second, bbox); | ||||
| 
 | ||||
|                 Polylines inside_polines = intersection_pl({polygon}, lower_polygons_series_clipped); | ||||
|                 extrusion_paths_append( | ||||
|                     paths, | ||||
|                     std::move(inside_polines), | ||||
|  | @ -310,7 +315,7 @@ static ExtrusionEntityCollection traverse_loops(const PerimeterGenerator &perime | |||
|                     extrusion_width, | ||||
|                     (float)perimeter_generator.layer_height); | ||||
| 
 | ||||
|                 remain_polines = diff_pl({ polygon }, it->second); | ||||
|                 remain_polines = diff_pl({polygon}, lower_polygons_series_clipped); | ||||
|             } | ||||
| 
 | ||||
|             // get 100% overhang paths by checking what parts of this loop fall
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 qing.zhang
						qing.zhang