mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-31 12:41:20 -06:00 
			
		
		
		
	Ported make_perimeters() and infill() to C++/XS, use pure C++ threads, cherry picked from @alexrj 66591bcc556c01572ec7519b1f8cb4ee2d430685
This commit is contained in:
		
							parent
							
								
									3e8cafa857
								
							
						
					
					
						commit
						86c8207d31
					
				
					 5 changed files with 202 additions and 133 deletions
				
			
		|  | @ -41,8 +41,12 @@ sub size { | |||
| sub process { | ||||
|     my ($self) = @_; | ||||
|      | ||||
|     $self->status_cb->(20, "Generating perimeters"); | ||||
|     $_->make_perimeters for @{$self->objects}; | ||||
|      | ||||
|     $self->status_cb->(70, "Infilling layers"); | ||||
|     $_->infill for @{$self->objects}; | ||||
|      | ||||
|     $_->generate_support_material for @{$self->objects}; | ||||
|     $self->make_skirt; | ||||
|     $self->make_brim;  # must come after make_skirt | ||||
|  |  | |||
|  | @ -371,114 +371,11 @@ sub _slice_region { | |||
| # 2) Increases an "extra perimeters" counter at region slices where needed. | ||||
| # 3) Generates perimeters, gap fills and fill regions (fill regions of type stInternal). | ||||
| sub make_perimeters { | ||||
|     my $self = shift; | ||||
|     my ($self) = @_; | ||||
|      | ||||
|     # prerequisites | ||||
|     $self->slice; | ||||
|      | ||||
|     return if $self->step_done(STEP_PERIMETERS); | ||||
|     $self->set_step_started(STEP_PERIMETERS); | ||||
|     $self->print->status_cb->(20, "Generating perimeters"); | ||||
|      | ||||
|     # Merge region slices if they were split into types. | ||||
|     # FIXME this is using a safety offset, so the region slices will be slightly bigger with each iteration. | ||||
|     if ($self->typed_slices) { | ||||
|         $_->merge_slices for @{$self->layers}; | ||||
|         $self->set_typed_slices(0); | ||||
|         $self->invalidate_step(STEP_PREPARE_INFILL); | ||||
|     } | ||||
|      | ||||
|     # 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 my $region_id (0 .. ($self->print->region_count-1)) { | ||||
|         my $region = $self->print->regions->[$region_id]; | ||||
|         my $region_perimeters = $region->config->perimeters; | ||||
|          | ||||
|         next if !$region->config->extra_perimeters; | ||||
|         next if $region_perimeters == 0; | ||||
|         next if $region->config->fill_density == 0; | ||||
|          | ||||
|         for my $i (0 .. ($self->layer_count - 2)) { | ||||
|             my $layerm                  = $self->get_layer($i)->get_region($region_id); | ||||
|             my $upper_layerm            = $self->get_layer($i+1)->get_region($region_id); | ||||
|             my $upper_layerm_polygons   = [ map $_->p, @{$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} ]; | ||||
|             my $total_loop_length       = sum(map $_->length, @$upper_layerm_polygons) // 0; | ||||
|              | ||||
|             my $perimeter_spacing       = $layerm->flow(FLOW_ROLE_PERIMETER)->scaled_spacing; | ||||
|             my $ext_perimeter_flow      = $layerm->flow(FLOW_ROLE_EXTERNAL_PERIMETER); | ||||
|             my $ext_perimeter_width     = $ext_perimeter_flow->scaled_width; | ||||
|             my $ext_perimeter_spacing   = $ext_perimeter_flow->scaled_spacing; | ||||
|              | ||||
|             foreach my $slice (@{$layerm->slices}) { | ||||
|                 while (1) { | ||||
|                     # compute the total thickness of perimeters | ||||
|                     my $perimeters_thickness = $ext_perimeter_width/2 + $ext_perimeter_spacing/2 | ||||
|                         + ($region_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) | ||||
|                     my $critical_area_depth = $perimeter_spacing*1.5; | ||||
|                     my $critical_area = diff( | ||||
|                         offset($slice->expolygon->arrayref, -$perimeters_thickness), | ||||
|                         offset($slice->expolygon->arrayref, -($perimeters_thickness + $critical_area_depth)), | ||||
|                     ); | ||||
|                      | ||||
|                     # check whether a portion of the upper slices falls inside the critical area | ||||
|                     my $intersection = intersection_ppl( | ||||
|                         $upper_layerm_polygons, | ||||
|                         $critical_area, | ||||
|                     ); | ||||
|                      | ||||
|                     # only add an additional loop if at least 30% of the slice loop would benefit from it | ||||
|                     my $total_intersection_length = sum(map $_->length, @$intersection) // 0; | ||||
|                     last unless $total_intersection_length > $total_loop_length*0.3; | ||||
|                      | ||||
|                     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($slice->extra_perimeters + 1); | ||||
|                 } | ||||
|                 Slic3r::debugf "  adding %d more perimeter(s) at layer %d\n", | ||||
|                     $slice->extra_perimeters, $layerm->layer->id | ||||
|                     if $slice->extra_perimeters > 0; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     Slic3r::parallelize( | ||||
|         threads => $self->print->config->threads, | ||||
|         items => sub { 0 .. ($self->layer_count - 1) }, | ||||
|         thread_cb => sub { | ||||
|             my $q = shift; | ||||
|             while (defined (my $i = $q->dequeue)) { | ||||
|                 $self->get_layer($i)->make_perimeters; | ||||
|             } | ||||
|         }, | ||||
|         no_threads_cb => sub { | ||||
|             $_->make_perimeters for @{$self->layers}; | ||||
|         }, | ||||
|     ); | ||||
|      | ||||
|     # 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); | ||||
|      | ||||
|     $self->set_step_done(STEP_PERIMETERS); | ||||
|     $self->_make_perimeters; | ||||
| } | ||||
| 
 | ||||
| sub prepare_infill { | ||||
|  | @ -598,32 +495,7 @@ sub infill { | |||
|      | ||||
|     # prerequisites | ||||
|     $self->prepare_infill; | ||||
|      | ||||
|     return if $self->step_done(STEP_INFILL); | ||||
|     $self->set_step_started(STEP_INFILL); | ||||
|     $self->print->status_cb->(70, "Infilling layers"); | ||||
|      | ||||
|     Slic3r::parallelize( | ||||
|         threads => $self->print->config->threads, | ||||
|         items => sub { 0..$#{$self->layers} }, | ||||
|         thread_cb => sub { | ||||
|             my $q = shift; | ||||
|             while (defined (my $i = $q->dequeue)) { | ||||
|                 $self->get_layer($i)->make_fills; | ||||
|             } | ||||
|         }, | ||||
|         no_threads_cb => sub { | ||||
|             foreach my $layer (@{$self->layers}) { | ||||
|                 $layer->make_fills; | ||||
|             } | ||||
|         }, | ||||
|     ); | ||||
| 
 | ||||
|     ### we could free memory now, but this would make this step not idempotent | ||||
|     ### Vojtech: Cannot release the fill_surfaces, they are used by the support generator. | ||||
|     ### $_->fill_surfaces->clear for map @{$_->regions}, @{$object->layers}; | ||||
|      | ||||
|     $self->set_step_done(STEP_INFILL); | ||||
|     $self->_infill; | ||||
| } | ||||
| 
 | ||||
| sub generate_support_material { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Alessandro Ranellucci
						Alessandro Ranellucci