Codebase list slic3r-prusa / c435c86
Imported Upstream version 1.31.6 Chow Loong Jin 7 years ago
50 changed file(s) with 622 addition(s) and 467 deletion(s). Raw diff Collapse all Expand all
8181 use constant VIEW_FRONT => [0.0,90.0];
8282 use constant VIEW_REAR => [180.0,90.0];
8383
84 #use constant GIMBALL_LOCK_THETA_MAX => 150;
85 use constant GIMBALL_LOCK_THETA_MAX => 170;
86
8487 # make OpenGL::Array thread-safe
8588 {
8689 no warnings 'redefine';
253256 if (TURNTABLE_MODE) {
254257 $self->_sphi($self->_sphi + ($pos->x - $orig->x) * TRACKBALLSIZE);
255258 $self->_stheta($self->_stheta - ($pos->y - $orig->y) * TRACKBALLSIZE); #-
256 $self->_stheta(150) if $self->_stheta > 150;
259 $self->_stheta(GIMBALL_LOCK_THETA_MAX) if $self->_stheta > GIMBALL_LOCK_THETA_MAX;
257260 $self->_stheta(0) if $self->_stheta < 0;
258261 } else {
259262 my $size = $self->GetClientSize;
358361 $self->_sphi($dirvec->[0]);
359362 $self->_stheta($dirvec->[1]);
360363 # Avoid gimball lock.
361 $self->_stheta(150) if $self->_stheta > 150;
364 $self->_stheta(GIMBALL_LOCK_THETA_MAX) if $self->_stheta > GIMBALL_LOCK_THETA_MAX;
362365 $self->_stheta(0) if $self->_stheta < 0;
363366 # View everything.
364367 $self->zoom_to_bounding_box($bb);
2121
2222 my $self = $class->SUPER::new(undef, -1, $Slic3r::FORK_NAME . ' - ' . $Slic3r::VERSION, wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE);
2323 if ($^O eq 'MSWin32') {
24 $self->SetIcon(Wx::Icon->new($Slic3r::var->("Slic3r.ico"), wxBITMAP_TYPE_ICO));
24 # Load the icon either from the exe, or fron the ico file.
25 my $iconfile = $Slic3r::var->('..\slic3r.exe');
26 $iconfile = $Slic3r::var->("Slic3r.ico") unless -f $iconfile;
27 $self->SetIcon(Wx::Icon->new($iconfile, wxBITMAP_TYPE_ICO));
2528 } else {
2629 $self->SetIcon(Wx::Icon->new($Slic3r::var->("Slic3r_128px.png"), wxBITMAP_TYPE_PNG));
2730 }
2929 keep_upper => 1,
3030 keep_lower => 1,
3131 rotate_lower => 1,
32 preview => 1,
32 # preview => 1,
33 # Disabled live preview by default as it is not stable and/or the calculation takes too long for interactive usage.
34 preview => 0,
3335 };
3436
3537 my $optgroup;
257259 $optgroup->get_field('keep_upper')->toggle(my $have_upper = abs($z - $optgroup->get_option('z')->max) > 0.1);
258260 $optgroup->get_field('keep_lower')->toggle(my $have_lower = $z > 0.1);
259261 $optgroup->get_field('rotate_lower')->toggle($z > 0 && $self->{cut_options}{keep_lower});
260 $optgroup->get_field('preview')->toggle($self->{cut_options}{keep_upper} != $self->{cut_options}{keep_lower});
262 # Disabled live preview by default as it is not stable and/or the calculation takes too long for interactive usage.
263 # $optgroup->get_field('preview')->toggle($self->{cut_options}{keep_upper} != $self->{cut_options}{keep_lower});
261264
262265 # update cut button
263266 if (($self->{cut_options}{keep_upper} && $have_upper)
818818 $new_conf->set("spiral_vase", 0);
819819 $self->load_config($new_conf);
820820 }
821 }
822
823 if ($config->support_material) {
824 # Ask only once.
825 if (! $self->{support_material_overhangs_queried}) {
826 $self->{support_material_overhangs_queried} = 1;
827 if ($config->overhangs != 1) {
828 my $dialog = Wx::MessageDialog->new($self,
829 "Supports work better, if the following feature is enabled:\n"
830 . "- Detect bridging perimeters\n"
831 . "\nShall I adjust those settings for supports?",
832 'Support Generator', wxICON_WARNING | wxYES | wxNO | wxCANCEL);
833 my $answer = $dialog->ShowModal();
834 my $new_conf = Slic3r::Config->new;
835 if ($answer == wxID_YES) {
836 # Enable "detect bridging perimeters".
837 $new_conf->set("overhangs", 1);
838 } elsif ($answer == wxID_NO) {
839 # Do nothing, leave supports on and "detect bridging perimeters" off.
840 } elsif ($answer == wxID_CANCEL) {
841 # Disable supports.
842 $new_conf->set("support_material", 0);
843 $self->{support_material_overhangs_queried} = 0;
844 }
845 $self->load_config($new_conf);
846 }
847 }
848 } else {
849 $self->{support_material_overhangs_queried} = 0;
821850 }
822851
823852 if ($config->fill_density == 100
258258 }
259259 }
260260
261 # merge all regions' slices to get islands
261 # Merge all regions' slices to get islands, chain them by a shortest path.
262262 $layer->make_slices;
263263 }
264264
366366 return $mesh->slice($z);
367367 }
368368
369 # 1) Merges typed region slices into stInternal type.
370 # 2) Increases an "extra perimeters" counter at region slices where needed.
371 # 3) Generates perimeters, gap fills and fill regions (fill regions of type stInternal).
369372 sub make_perimeters {
370373 my $self = shift;
371374
376379 $self->set_step_started(STEP_PERIMETERS);
377380 $self->print->status_cb->(20, "Generating perimeters");
378381
379 # merge slices if they were split into types
382 # Merge region slices if they were split into types.
383 # FIXME this is using a safety offset, so the region slices will be slightly bigger with each iteration.
380384 if ($self->typed_slices) {
381385 $_->merge_slices for @{$self->layers};
382386 $self->set_typed_slices(0);
486490 $self->set_step_started(STEP_PREPARE_INFILL);
487491 $self->print->status_cb->(30, "Preparing infill");
488492
489 # this will assign a type (top/bottom/internal) to $layerm->slices
490 # and transform $layerm->fill_surfaces from expolygon
491 # to typed top/bottom/internal surfaces;
493 # This will assign a type (top/bottom/internal) to $layerm->slices.
494 # Then the classifcation of $layerm->slices is transfered onto
495 # the $layerm->fill_surfaces by clipping $layerm->fill_surfaces
496 # by the cummulative area of the previous $layerm->fill_surfaces.
492497 $self->detect_surfaces_type;
493 # Mark the object to have the slices classified (typed, which also means they are split based on whether they are supported, bridging, top layers etc.)
498 # Mark the object to have the region slices classified (typed, which also means they are split based on whether they are supported, bridging, top layers etc.)
494499 $self->set_typed_slices(1);
495500
496501 # Decide what surfaces are to be filled.
614619 );
615620
616621 ### we could free memory now, but this would make this step not idempotent
622 ### Vojtech: Cannot release the fill_surfaces, they are used by the support generator.
617623 ### $_->fill_surfaces->clear for map @{$_->regions}, @{$object->layers};
618624
619625 $self->set_step_done(STEP_INFILL);
3333 expolygon => $_,
3434 )) for @$expolygons;
3535
36 my ($region_config, $object_config, $print_config, $loops, $gap_fill, $perimeter_surfaces, $fill_surfaces);
36 my ($region_config, $object_config, $print_config, $loops, $gap_fill, $fill_surfaces);
3737 my $g = Slic3r::Layer::PerimeterGenerator->new(
3838 # input:
3939 $slices,
4646 # output:
4747 ($loops = Slic3r::ExtrusionPath::Collection->new),
4848 ($gap_fill = Slic3r::ExtrusionPath::Collection->new),
49 ($perimeter_surfaces = Slic3r::Surface::Collection->new),
5049 ($fill_surfaces = Slic3r::Surface::Collection->new),
5150 );
5251 $g->config->apply_dynamic($config);
Binary diff not shown
2222 # In case windows.h is included, we don't want the min / max macros to be active.
2323 # If <math.h> is included, we want the #defines to be active (M_PI etc.)
2424 push @cflags, qw(-D_WIN32 -DNOMINMAX -D_USE_MATH_DEFINES);
25 }
26 if (! $cpp_guess->is_msvc) {
27 # Don't use the version flag on MS Visual Studio, as it starts to recognize them up to 2015 and it uses different syntax.
28 push @cflags, qw(-std=c++11);
2529 }
2630
2731 my @early_includes = ();
3943 $alienwx_libraries =~ s/-L/-LIBPATH:/g if ($cpp_guess->is_msvc);
4044 push @ldflags, Alien::wxWidgets->link_flags, $alienwx_libraries;
4145 # push @early_includes, qw(slic3r/GUI/wxinit.h);
46 }
47
48 if ($ENV{SLIC3R_PROFILE})
49 {
50 print "Slic3r will be built with a Shiny invasive profiler\n";
51 push @cflags, qw(-DSLIC3R_PROFILE);
4252 }
4353
4454 if ($ENV{SLIC3R_HAS_BROKEN_CROAK})
2727 /*---------------------------------------------------------------------------*/
2828
2929 #include "ShinyMacros.h"
30
31 #ifdef SLIC3R_PROFILE
3032 #include "ShinyManager.h"
33 #endif /* SLIC3R_PROFILE */
3134
3235 #endif /* SHINY_H */
2626
2727
2828 /*---------------------------------------------------------------------------*/
29
30 /* SHINY_IS_COMPILED is the master on or off swith at compile time. Define it to TRUE or FALSE before including header Shiny.h or inside ShinyConfig.h. Default is TRUE.
31 */
32 #if defined(SLIC3R_PROFILE) && defined(WIN32)
33 #define SHINY_IS_COMPILED TRUE
34 #else
35 #define SHINY_IS_COMPILED FALSE
36 #endif
37
38 #define SHINY_STATIC_LINK TRUE
3929
4030 /* if SHINY_LOOKUP_RATE is defined to TRUE then Shiny will record the success of its hash function. This is useful for debugging. Default is FALSE.
4131 */
2424 #ifndef SHINY_MACROS_H
2525 #define SHINY_MACROS_H
2626
27 #ifdef SLIC3R_PROFILE
28
2729 #include "ShinyManager.h"
28
29 #if SHINY_IS_COMPILED == TRUE
3030
3131 /*---------------------------------------------------------------------------*/
3232 /* public preprocessors */
253253
254254 /*---------------------------------------------------------------------------*/
255255
256 #else /* if SHINY_IS_COMPILED == TRUE */
257
258 #ifdef __cplusplus
259 extern "C" {
260 #endif
261 SHINY_INLINE ShinyData GetEmptyData() {
262 ShinyData a = { { 0, 0 }, { 0, 0 }, { 0, 0 } };
263 return a;
264 }
265 #ifdef __cplusplus
266 } /* end of extern "C" */
267 #endif
256 #else /* SLIC3R_PROFILE */
268257
269258 #define PROFILE_UPDATE()
270259 #define PROFILE_SET_DAMPING(x)
284273 #define PROFILE_SHARED_DEFINE(name)
285274 #define PROFILE_SHARED_BEGIN(name)
286275 #define PROFILE_SHARED_BLOCK(name)
287 #define PROFILE_GET_SHARED_DATA(name) ShinyGetEmptyData()
288 #define PROFILE_GET_ROOT_DATA() ShinyGetEmptyData()
289
290 #if SHINY_HAS_ENABLED == TRUE
291276 #define PROFILE_SET_ENABLED(boolean)
292 #endif
293
294 #endif /* SHINY_IS_COMPILED == TRUE */
277
278 #endif /* SLIC3R_PROFILE */
295279
296280 #endif /* SHINY_MACROS_H */
2121 THE SOFTWARE.
2222 */
2323
24 #ifdef SLIC3R_PROFILE
25
2426 #include "ShinyManager.h"
2527
26 // #include <malloc.h>
28 #include <malloc.h>
2729 #include <memory.h>
2830 #include <string.h>
2931 #include <stdio.h>
30
31 #if SHINY_IS_COMPILED == TRUE
32
3332
3433 /*---------------------------------------------------------------------------*/
3534
442441 #endif
443442 }
444443
445 #endif /* if SHINY_IS_COMPILED == TRUE */
444 #endif /* SLIC3R_PROFILE */
3232
3333 #include <stdio.h>
3434
35 #if SHINY_IS_COMPILED == TRUE
36
3735 #ifdef __cplusplus
3836 extern "C" {
3937 #endif
261259 };
262260 #endif
263261
264 #endif /* if SHINY_IS_COMPILED == TRUE */
265
266262 #endif /* SHINY_MANAGER_H */
2121 THE SOFTWARE.
2222 */
2323
24 #ifdef SLIC3R_PROFILE
25
2426 #include "ShinyNode.h"
2527 #include "ShinyZone.h"
2628 #include "ShinyNodeState.h"
2729
2830 #include <memory.h>
29
30
31 #if SHINY_IS_COMPILED == TRUE
3231
3332 /*---------------------------------------------------------------------------*/
3433
126125 if (a_node->nextSibling) ShinyNode_enumerateNodes(a_node->nextSibling, a_func);
127126 }
128127
129 #endif
128 #endif /* SLIC3R_PROFILE */
2626
2727 #include "ShinyData.h"
2828 #include "ShinyTools.h"
29
30 #if SHINY_IS_COMPILED == TRUE
3129
3230 #ifdef __cplusplus
3331 extern "C" {
131129 }
132130 #endif /* __cplusplus */
133131
134 #endif /* if SHINY_IS_COMPILED == TRUE */
135
136132 #endif /* SHINY_NODE_H */
2121 THE SOFTWARE.
2222 */
2323
24 #ifdef SLIC3R_PROFILE
25
2426 #include "ShinyNodePool.h"
2527 #include "ShinyTools.h"
2628
2729 #include <memory.h>
28 // #include <malloc.h>
29
30 #if SHINY_IS_COMPILED == TRUE
31
30 #include <malloc.h>
3231
3332 /*---------------------------------------------------------------------------*/
3433
7473 free(self);
7574 }
7675
77 #endif
76 #endif /* SLIC3R_PROFILE */
2525 #define SHINY_NODE_POOL_H
2626
2727 #include "ShinyNode.h"
28
29 #if SHINY_IS_COMPILED == TRUE
3028
3129 #ifdef __cplusplus
3230 extern "C" {
6563 } /* end of extern "C" */
6664 #endif
6765
68 #endif /* if SHINY_IS_COMPILED == TRUE */
69
70
7166 #endif /* SHINY_NODE_POOL_H */
2121 THE SOFTWARE.
2222 */
2323
24 #ifdef SLIC3R_PROFILE
25
2426 #include "ShinyNodeState.h"
2527 #include "ShinyNode.h"
2628 #include "ShinyZone.h"
2729
28 // #include <malloc.h>
29
30
31 #if SHINY_IS_COMPILED == TRUE
30 #include <malloc.h>
3231
3332 /*---------------------------------------------------------------------------*/
3433
105104 return node->nextSibling;
106105 }
107106
108 #endif
107 #endif /* SLIC3R_PROFILE */
2626
2727 #include "ShinyNode.h"
2828
29 #if SHINY_IS_COMPILED == TRUE
30
3129 #ifdef __cplusplus
3230 extern "C" {
3331 #endif
5452 } /* end of extern "C" */
5553 #endif
5654
57 #endif /* if SHINY_IS_COMPILED == TRUE */
58
5955 #endif /* SHINY_NODE_STATE_H */
2121 THE SOFTWARE.
2222 */
2323
24 #ifdef SLIC3R_PROFILE
25
2426 #include "ShinyOutput.h"
2527
2628 #include <stdio.h>
3436 # define TRAILING 1
3537 #endif
3638
37 #if SHINY_IS_COMPILED == TRUE
38
39
4039 /*---------------------------------------------------------------------------*/
4140
4241 #define OUTPUT_WIDTH_CALL 6
4342 #define OUTPUT_WIDTH_TIME 6
4443 #define OUTPUT_WIDTH_PERC 4
45 #define OUTPUT_WIDTH_SUM 79
44 #define OUTPUT_WIDTH_SUM 120
4645
4746 #define OUTPUT_WIDTH_DATA (1+OUTPUT_WIDTH_CALL + 1 + 2*(OUTPUT_WIDTH_TIME+4+OUTPUT_WIDTH_PERC+1) + 1)
4847 #define OUTPUT_WIDTH_NAME (OUTPUT_WIDTH_SUM - OUTPUT_WIDTH_DATA)
186185 }
187186 }
188187
189 #endif
188 #endif /* SLIC3R_PROFILE */
2626
2727 #include "ShinyNode.h"
2828 #include "ShinyZone.h"
29
30 #if SHINY_IS_COMPILED == TRUE
3129
3230 #ifdef __cplusplus
3331 extern "C" {
6664 }
6765 #endif /* __cplusplus */
6866
69 #endif /* if SHINY_IS_COMPILED == TRUE */
70
7167 #endif /* SHINY_OUTPUT_H */
8585
8686 /*---------------------------------------------------------------------------*/
8787
88 #if SHINY_IS_COMPILED == TRUE
89 struct _ShinyNode;
90 struct _ShinyZone;
88 struct _ShinyNode;
89 struct _ShinyZone;
9190
92 typedef struct _ShinyNode* ShinyNodeCache;
93 typedef struct _ShinyNode* ShinyNodeTable;
94 #endif
95
91 typedef struct _ShinyNode* ShinyNodeCache;
92 typedef struct _ShinyNode* ShinyNodeTable;
9693
9794 /*---------------------------------------------------------------------------*/
9895
99 #ifdef SHINY_STATIC_LINK
100 # define SHINY_API
101 #else
102 # define SHINY_API SHINY_EXPORT
103 #endif
104
96 #define SHINY_API
10597
10698 /*---------------------------------------------------------------------------*/
10799
108100 #if SHINY_COMPILER == SHINY_COMPILER_MSVC
109101 # define SHINY_INLINE __inline
110102 # define SHINY_UNUSED
111 # define SHINY_EXPORT __declspec(dllexport)
112
113103 #elif SHINY_COMPILER == SHINY_COMPILER_GNUC
114104 # define SHINY_INLINE inline
115105 # define SHINY_UNUSED __attribute__((unused))
116 # define SHINY_EXPORT __attribute__((dllexport))
117
118106 #elif SHINY_COMPILER == SHINY_COMPILER_OTHER
119107 # define SHINY_INLINE inline
120108 # define SHINY_UNUSED
121 # define SHINY_EXPORT extern
122109 #endif
123110
124111
2121 THE SOFTWARE.
2222 */
2323
24 #if SHINY_IS_COMPILED == TRUE
24 #ifdef SLIC3R_PROFILE
2525
2626 #include "ShinyTools.h"
2727
109109
110110 #endif
111111
112 #endif /* if SHINY_IS_COMPILED == TRUE */
112 #endif /* SLIC3R_PROFILE */
2121 THE SOFTWARE.
2222 */
2323
24 #ifdef SLIC3R_PROFILE
25
2426 #include "ShinyZone.h"
2527
2628 #include <memory.h>
27
28 #if SHINY_IS_COMPILED == TRUE
2929
3030 /*---------------------------------------------------------------------------*/
3131
197197 if (a_zone->next) ShinyZone_enumerateZones(a_zone->next, a_func);
198198 }
199199
200 #endif
200 #endif /* SLIC3R_PROFILE */
2626
2727 #include "ShinyData.h"
2828 #include <memory.h>
29
30 #if SHINY_IS_COMPILED == TRUE
3129
3230 #ifdef __cplusplus
3331 extern "C" {
8987 }
9088 #endif /* __cplusplus */
9189
92 #endif /* if SHINY_IS_COMPILED == TRUE */
93
9490 #endif /* SHINY_ZONE_H */
105105 }
106106 }
107107 stl_free_edges(stl);
108
109 #if 0
110 printf("Number of faces: %d, number of manifold edges: %d, number of connected edges: %d, number of unconnected edges: %d\r\n",
111 stl->stats.number_of_facets, stl->stats.number_of_facets * 3,
112 stl->stats.connected_edges, stl->stats.number_of_facets * 3 - stl->stats.connected_edges);
113 #endif
108114 }
109115
110116 static void
111117 stl_load_edge_exact(stl_file *stl, stl_hash_edge *edge,
112118 stl_vertex *a, stl_vertex *b) {
113119
114 float diff_x;
115 float diff_y;
116 float diff_z;
117 float max_diff;
118
119 if (stl->error) return;
120
121 diff_x = ABS(a->x - b->x);
122 diff_y = ABS(a->y - b->y);
123 diff_z = ABS(a->z - b->z);
124 max_diff = STL_MAX(diff_x, diff_y);
125 max_diff = STL_MAX(diff_z, max_diff);
126 stl->stats.shortest_edge = STL_MIN(max_diff, stl->stats.shortest_edge);
127
128 if(diff_x == max_diff) {
129 if(a->x > b->x) {
130 memcpy(&edge->key[0], a, sizeof(stl_vertex));
131 memcpy(&edge->key[3], b, sizeof(stl_vertex));
132 } else {
133 memcpy(&edge->key[0], b, sizeof(stl_vertex));
134 memcpy(&edge->key[3], a, sizeof(stl_vertex));
135 edge->which_edge += 3; /* this edge is loaded backwards */
136 }
137 } else if(diff_y == max_diff) {
138 if(a->y > b->y) {
139 memcpy(&edge->key[0], a, sizeof(stl_vertex));
140 memcpy(&edge->key[3], b, sizeof(stl_vertex));
141 } else {
142 memcpy(&edge->key[0], b, sizeof(stl_vertex));
143 memcpy(&edge->key[3], a, sizeof(stl_vertex));
144 edge->which_edge += 3; /* this edge is loaded backwards */
145 }
146 } else {
147 if(a->z > b->z) {
148 memcpy(&edge->key[0], a, sizeof(stl_vertex));
149 memcpy(&edge->key[3], b, sizeof(stl_vertex));
150 } else {
151 memcpy(&edge->key[0], b, sizeof(stl_vertex));
152 memcpy(&edge->key[3], a, sizeof(stl_vertex));
153 edge->which_edge += 3; /* this edge is loaded backwards */
154 }
120 if (stl->error) return;
121
122 {
123 float diff_x = ABS(a->x - b->x);
124 float diff_y = ABS(a->y - b->y);
125 float diff_z = ABS(a->z - b->z);
126 float max_diff = STL_MAX(diff_x, diff_y);
127 max_diff = STL_MAX(diff_z, max_diff);
128 stl->stats.shortest_edge = STL_MIN(max_diff, stl->stats.shortest_edge);
129 }
130
131 // Ensure identical vertex ordering of equal edges.
132 // This method is numerically robust.
133 if ((a->x != b->x) ?
134 (a->x < b->x) :
135 ((a->y != b->y) ?
136 (a->y < b->y) :
137 (a->z < b->z))) {
138 memcpy(&edge->key[0], a, sizeof(stl_vertex));
139 memcpy(&edge->key[3], b, sizeof(stl_vertex));
140 } else {
141 memcpy(&edge->key[0], b, sizeof(stl_vertex));
142 memcpy(&edge->key[3], a, sizeof(stl_vertex));
143 edge->which_edge += 3; /* this edge is loaded backwards */
155144 }
156145 }
157146
308297 static int
309298 stl_load_edge_nearby(stl_file *stl, stl_hash_edge *edge,
310299 stl_vertex *a, stl_vertex *b, float tolerance) {
311 float diff_x;
312 float diff_y;
313 float diff_z;
314 float max_diff;
315 unsigned vertex1[3];
316 unsigned vertex2[3];
317
318
319 diff_x = ABS(a->x - b->x);
320 diff_y = ABS(a->y - b->y);
321 diff_z = ABS(a->z - b->z);
322 max_diff = STL_MAX(diff_x, diff_y);
323 max_diff = STL_MAX(diff_z, max_diff);
324
325 vertex1[0] = (unsigned)((a->x - stl->stats.min.x) / tolerance);
326 vertex1[1] = (unsigned)((a->y - stl->stats.min.y) / tolerance);
327 vertex1[2] = (unsigned)((a->z - stl->stats.min.z) / tolerance);
328 vertex2[0] = (unsigned)((b->x - stl->stats.min.x) / tolerance);
329 vertex2[1] = (unsigned)((b->y - stl->stats.min.y) / tolerance);
330 vertex2[2] = (unsigned)((b->z - stl->stats.min.z) / tolerance);
300 // Index of a grid cell spaced by tolerance.
301 uint32_t vertex1[3] = {
302 (uint32_t)((a->x - stl->stats.min.x) / tolerance),
303 (uint32_t)((a->y - stl->stats.min.y) / tolerance),
304 (uint32_t)((a->z - stl->stats.min.z) / tolerance)
305 };
306 uint32_t vertex2[3] = {
307 (uint32_t)((b->x - stl->stats.min.x) / tolerance),
308 (uint32_t)((b->y - stl->stats.min.y) / tolerance),
309 (uint32_t)((b->z - stl->stats.min.z) / tolerance)
310 };
331311
332312 if( (vertex1[0] == vertex2[0])
333313 && (vertex1[1] == vertex2[1])
336316 return 0;
337317 }
338318
339 if(diff_x == max_diff) {
340 if(a->x > b->x) {
341 memcpy(&edge->key[0], vertex1, sizeof(stl_vertex));
342 memcpy(&edge->key[3], vertex2, sizeof(stl_vertex));
343 } else {
344 memcpy(&edge->key[0], vertex2, sizeof(stl_vertex));
345 memcpy(&edge->key[3], vertex1, sizeof(stl_vertex));
346 edge->which_edge += 3; /* this edge is loaded backwards */
347 }
348 } else if(diff_y == max_diff) {
349 if(a->y > b->y) {
350 memcpy(&edge->key[0], vertex1, sizeof(stl_vertex));
351 memcpy(&edge->key[3], vertex2, sizeof(stl_vertex));
352 } else {
353 memcpy(&edge->key[0], vertex2, sizeof(stl_vertex));
354 memcpy(&edge->key[3], vertex1, sizeof(stl_vertex));
355 edge->which_edge += 3; /* this edge is loaded backwards */
356 }
357 } else {
358 if(a->z > b->z) {
359 memcpy(&edge->key[0], vertex1, sizeof(stl_vertex));
360 memcpy(&edge->key[3], vertex2, sizeof(stl_vertex));
361 } else {
362 memcpy(&edge->key[0], vertex2, sizeof(stl_vertex));
363 memcpy(&edge->key[3], vertex1, sizeof(stl_vertex));
364 edge->which_edge += 3; /* this edge is loaded backwards */
365 }
319 // Ensure identical vertex ordering of edges, which vertices land into equal grid cells.
320 // This method is numerically robust.
321 if ((vertex1[0] != vertex2[0]) ?
322 (vertex1[0] < vertex2[0]) :
323 ((vertex1[1] != vertex2[1]) ?
324 (vertex1[1] < vertex2[1]) :
325 (vertex1[2] < vertex2[2]))) {
326 memcpy(&edge->key[0], vertex1, sizeof(stl_vertex));
327 memcpy(&edge->key[3], vertex2, sizeof(stl_vertex));
328 } else {
329 memcpy(&edge->key[0], vertex2, sizeof(stl_vertex));
330 memcpy(&edge->key[3], vertex1, sizeof(stl_vertex));
331 edge->which_edge += 3; /* this edge is loaded backwards */
366332 }
367333 return 1;
368334 }
563529 next_edge = pivot_vertex;
564530 }
565531 }
532 #if 0
533 if (stl->facet_start[facet_num].vertex[pivot_vertex].x == new_vertex.x &&
534 stl->facet_start[facet_num].vertex[pivot_vertex].y == new_vertex.y &&
535 stl->facet_start[facet_num].vertex[pivot_vertex].z == new_vertex.z)
536 printf("Changing vertex %f,%f,%f: Same !!!\r\n",
537 new_vertex.x, new_vertex.y, new_vertex.z);
538 else {
539 if (stl->facet_start[facet_num].vertex[pivot_vertex].x != new_vertex.x)
540 printf("Changing coordinate x, vertex %e (0x%08x) to %e(0x%08x)\r\n",
541 stl->facet_start[facet_num].vertex[pivot_vertex].x,
542 *reinterpret_cast<const int*>(&stl->facet_start[facet_num].vertex[pivot_vertex].x),
543 new_vertex.x,
544 *reinterpret_cast<const int*>(&new_vertex.x));
545 if (stl->facet_start[facet_num].vertex[pivot_vertex].y != new_vertex.y)
546 printf("Changing coordinate x, vertex %e (0x%08x) to %e(0x%08x)\r\n",
547 stl->facet_start[facet_num].vertex[pivot_vertex].y,
548 *reinterpret_cast<const int*>(&stl->facet_start[facet_num].vertex[pivot_vertex].y),
549 new_vertex.y,
550 *reinterpret_cast<const int*>(&new_vertex.y));
551 if (stl->facet_start[facet_num].vertex[pivot_vertex].z != new_vertex.z)
552 printf("Changing coordinate x, vertex %e (0x%08x) to %e(0x%08x)\r\n",
553 stl->facet_start[facet_num].vertex[pivot_vertex].z,
554 *reinterpret_cast<const int*>(&stl->facet_start[facet_num].vertex[pivot_vertex].z),
555 new_vertex.z,
556 *reinterpret_cast<const int*>(&new_vertex.z));
557 }
558 #endif
566559 stl->facet_start[facet_num].vertex[pivot_vertex] = new_vertex;
567560 vnot = stl->neighbors_start[facet_num].which_vertex_not[next_edge];
568561 facet_num = stl->neighbors_start[facet_num].neighbor[next_edge];
2323 #define __admesh_stl__
2424
2525 #include <stdio.h>
26 #include <stdint.h>
27 #include <stddef.h>
28 #include <boost/predef/detail/endian_compat.h>
29
30 #ifndef BOOST_LITTLE_ENDIAN
31 #error "admesh works correctly on little endian machines only!"
32 #endif
2633
2734 #ifdef __cplusplus
2835 extern "C" {
3239 #define STL_MIN(A,B) ((A)<(B)? (A):(B))
3340 #define ABS(X) ((X) < 0 ? -(X) : (X))
3441
42 // Size of the binary STL header, free form.
3543 #define LABEL_SIZE 80
44 // Binary STL, length of the "number of faces" counter.
3645 #define NUM_FACET_SIZE 4
46 // Binary STL, sizeof header + number of faces.
3747 #define HEADER_SIZE 84
3848 #define STL_MIN_FILE_SIZE 284
3949 #define ASCII_LINES_PER_FACET 7
50 // Comparing an edge by memcmp, 2x3x4 bytes = 24
4051 #define SIZEOF_EDGE_SORT 24
4152
4253 typedef struct {
4556 float z;
4657 } stl_vertex;
4758
59 static_assert(sizeof(stl_vertex) == 12, "size of stl_vertex incorrect");
60
4861 typedef struct {
4962 float x;
5063 float y;
5164 float z;
5265 } stl_normal;
66
67 static_assert(sizeof(stl_normal) == 12, "size of stl_normal incorrect");
5368
5469 typedef char stl_extra[2];
5570
6075 } stl_facet;
6176 #define SIZEOF_STL_FACET 50
6277
78 static_assert(offsetof(stl_facet, normal) == 0, "stl_facet.normal has correct offset");
79 static_assert(offsetof(stl_facet, vertex) == 12, "stl_facet.vertex has correct offset");
80 static_assert(offsetof(stl_facet, extra ) == 48, "stl_facet.extra has correct offset");
81 static_assert(sizeof(stl_facet) >= SIZEOF_STL_FACET, "size of stl_facet incorrect");
82
6383 typedef enum {binary, ascii, inmemory} stl_type;
6484
6585 typedef struct {
6989 } stl_edge;
7090
7191 typedef struct stl_hash_edge {
72 unsigned key[6];
92 // Key of a hash edge: 2x binary copy of a floating point vertex.
93 uint32_t key[6];
94 // Index of a facet owning this edge.
7395 int facet_number;
96 // Index of this edge inside the facet with an index of facet_number.
97 // If this edge is stored backwards, which_edge is increased by 3.
7498 int which_edge;
7599 struct stl_hash_edge *next;
76100 } stl_hash_edge;
77101
78 typedef struct {
102 static_assert(offsetof(stl_hash_edge, facet_number) == SIZEOF_EDGE_SORT, "size of stl_hash_edge.key incorrect");
103
104 typedef struct {
105 // Index of a neighbor facet.
79106 int neighbor[3];
107 // Index of an opposite vertex at the neighbor face.
80108 char which_vertex_not[3];
81109 } stl_neighbors;
82110
203203 }
204204
205205 void
206 stl_put_little_int(FILE *fp, int value_in) {
207 int new_value;
208 union {
209 int int_value;
210 char char_value[4];
211 } value;
212
213 value.int_value = value_in;
214
215 new_value = value.char_value[0] & 0xFF;
216 new_value |= (value.char_value[1] & 0xFF) << 0x08;
217 new_value |= (value.char_value[2] & 0xFF) << 0x10;
218 new_value |= (value.char_value[3] & 0xFF) << 0x18;
219 fwrite(&new_value, sizeof(int), 1, fp);
220 }
221
222 void
223 stl_put_little_float(FILE *fp, float value_in) {
224 int new_value;
225 union {
226 float float_value;
227 char char_value[4];
228 } value;
229
230 value.float_value = value_in;
231
232 new_value = value.char_value[0] & 0xFF;
233 new_value |= (value.char_value[1] & 0xFF) << 0x08;
234 new_value |= (value.char_value[2] & 0xFF) << 0x10;
235 new_value |= (value.char_value[3] & 0xFF) << 0x18;
236 fwrite(&new_value, sizeof(int), 1, fp);
237 }
238
239 void
240 stl_write_binary_block(stl_file *stl, FILE *fp)
241 {
242 int i;
243 for(i = 0; i < stl->stats.number_of_facets; i++)
244 {
245 stl_put_little_float(fp, stl->facet_start[i].normal.x);
246 stl_put_little_float(fp, stl->facet_start[i].normal.y);
247 stl_put_little_float(fp, stl->facet_start[i].normal.z);
248 stl_put_little_float(fp, stl->facet_start[i].vertex[0].x);
249 stl_put_little_float(fp, stl->facet_start[i].vertex[0].y);
250 stl_put_little_float(fp, stl->facet_start[i].vertex[0].z);
251 stl_put_little_float(fp, stl->facet_start[i].vertex[1].x);
252 stl_put_little_float(fp, stl->facet_start[i].vertex[1].y);
253 stl_put_little_float(fp, stl->facet_start[i].vertex[1].z);
254 stl_put_little_float(fp, stl->facet_start[i].vertex[2].x);
255 stl_put_little_float(fp, stl->facet_start[i].vertex[2].y);
256 stl_put_little_float(fp, stl->facet_start[i].vertex[2].z);
257 fputc(stl->facet_start[i].extra[0], fp);
258 fputc(stl->facet_start[i].extra[1], fp);
259 }
260 }
261
262 void
263206 stl_write_binary(stl_file *stl, const char *file, const char *label) {
264207 FILE *fp;
265208 int i;
284227 for(i = strlen(label); i < LABEL_SIZE; i++) putc(0, fp);
285228
286229 fseek(fp, LABEL_SIZE, SEEK_SET);
287
288 stl_put_little_int(fp, stl->stats.number_of_facets);
289
290 stl_write_binary_block(stl, fp);
291
230 fwrite(&stl->stats.number_of_facets, 4, 1, fp);
231 for(i = 0; i < stl->stats.number_of_facets; i++)
232 fwrite(stl->facet_start + i, SIZEOF_STL_FACET, 1, fp);
292233 fclose(fp);
293234 }
294235
2626
2727 #include "stl.h"
2828
29 #if !defined(SEEK_SET)
30 #define SEEK_SET 0
31 #define SEEK_CUR 1
32 #define SEEK_END 2
29 #ifndef SEEK_SET
30 #error "SEEK_SET not defined"
3331 #endif
3432
3533 void
276274 /* Read a single facet from a binary .STL file */
277275 {
278276 /* we assume little-endian architecture! */
279 if (fread(&facet.normal, sizeof(stl_normal), 1, stl->fp) \
280 + fread(&facet.vertex, sizeof(stl_vertex), 3, stl->fp) \
281 + fread(&facet.extra, sizeof(char), 2, stl->fp) != 6) {
282 perror("Cannot read facet");
277 if (fread(&facet, 1, SIZEOF_STL_FACET, stl->fp) != SIZEOF_STL_FACET) {
283278 stl->error = 1;
284279 return;
285280 }
303298 return;
304299 }
305300 }
301
302 #if 0
303 // Report close to zero vertex coordinates. Due to the nature of the floating point numbers,
304 // close to zero values may be represented with singificantly higher precision than the rest of the vertices.
305 // It may be worth to round these numbers to zero during loading to reduce the number of errors reported
306 // during the STL import.
307 for (size_t j = 0; j < 3; ++ j) {
308 if (facet.vertex[j].x > -1e-12f && facet.vertex[j].x < 1e-12f)
309 printf("stl_read: facet %d.x = %e\r\n", j, facet.vertex[j].x);
310 if (facet.vertex[j].y > -1e-12f && facet.vertex[j].y < 1e-12f)
311 printf("stl_read: facet %d.y = %e\r\n", j, facet.vertex[j].y);
312 if (facet.vertex[j].z > -1e-12f && facet.vertex[j].z < 1e-12f)
313 printf("stl_read: facet %d.z = %e\r\n", j, facet.vertex[j].z);
314 }
315 #endif
316
317 #if 1
318 {
319 // Positive and negative zeros are possible in the floats, which are considered equal by the FP unit.
320 // When using a memcmp on raw floats, those numbers report to be different.
321 // Unify all +0 and -0 to +0 to make the floats equal under memcmp.
322 uint32_t *f = (uint32_t*)&facet;
323 for (int j = 0; j < 12; ++ j, ++ f) // 3x vertex + normal: 4x3 = 12 floats
324 if (*f == 0x80000000)
325 // Negative zero, switch to positive zero.
326 *f = 0;
327 }
328 #else
329 {
330 // Due to the nature of the floating point numbers, close to zero values may be represented with singificantly higher precision
331 // than the rest of the vertices. Round them to zero.
332 float *f = (float*)&facet;
333 for (int j = 0; j < 12; ++ j, ++ f) // 3x vertex + normal: 4x3 = 12 floats
334 if (*f > -1e-12f && *f < 1e-12f)
335 // Negative zero, switch to positive zero.
336 *f = 0;
337 }
338 #endif
306339 /* Write the facet into memory. */
307 stl->facet_start[i] = facet;
308
340 memcpy(stl->facet_start+i, &facet, SIZEOF_STL_FACET);
309341 stl_facet_stats(stl, facet, first);
310342 first = 0;
311343 }
2626
2727 #include "stl.h"
2828
29 static void stl_rotate(float *x, float *y, float angle);
29 static void stl_rotate(float *x, float *y, const double c, const double s);
3030 static float get_area(stl_facet *facet);
3131 static float get_volume(stl_file *stl);
3232
188188 stl_rotate_x(stl_file *stl, float angle) {
189189 int i;
190190 int j;
191 double radian_angle = (angle / 180.0) * M_PI;
192 double c = cos(radian_angle);
193 double s = sin(radian_angle);
191194
192195 if (stl->error) return;
193196
194197 for(i = 0; i < stl->stats.number_of_facets; i++) {
195198 for(j = 0; j < 3; j++) {
196199 stl_rotate(&stl->facet_start[i].vertex[j].y,
197 &stl->facet_start[i].vertex[j].z, angle);
200 &stl->facet_start[i].vertex[j].z, c, s);
198201 }
199202 }
200203 stl_get_size(stl);
205208 stl_rotate_y(stl_file *stl, float angle) {
206209 int i;
207210 int j;
211 double radian_angle = (angle / 180.0) * M_PI;
212 double c = cos(radian_angle);
213 double s = sin(radian_angle);
208214
209215 if (stl->error) return;
210216
211217 for(i = 0; i < stl->stats.number_of_facets; i++) {
212218 for(j = 0; j < 3; j++) {
213219 stl_rotate(&stl->facet_start[i].vertex[j].z,
214 &stl->facet_start[i].vertex[j].x, angle);
220 &stl->facet_start[i].vertex[j].x, c, s);
215221 }
216222 }
217223 stl_get_size(stl);
222228 stl_rotate_z(stl_file *stl, float angle) {
223229 int i;
224230 int j;
231 double radian_angle = (angle / 180.0) * M_PI;
232 double c = cos(radian_angle);
233 double s = sin(radian_angle);
225234
226235 if (stl->error) return;
227236
228237 for(i = 0; i < stl->stats.number_of_facets; i++) {
229238 for(j = 0; j < 3; j++) {
230239 stl_rotate(&stl->facet_start[i].vertex[j].x,
231 &stl->facet_start[i].vertex[j].y, angle);
240 &stl->facet_start[i].vertex[j].y, c, s);
232241 }
233242 }
234243 stl_get_size(stl);
238247
239248
240249 static void
241 stl_rotate(float *x, float *y, float angle) {
242 double r;
243 double theta;
244 double radian_angle;
245
246 radian_angle = (angle / 180.0) * M_PI;
247
248 r = sqrt((*x **x) + (*y **y));
249 theta = atan2(*y, *x);
250 *x = r * cos(theta + radian_angle);
251 *y = r * sin(theta + radian_angle);
250 stl_rotate(float *x, float *y, const double c, const double s) {
251 double xold = *x;
252 double yold = *y;
253 *x = float(c * xold - s * yold);
254 *y = float(s * xold + c * yold);
252255 }
253256
254257 extern void
55 #ifdef CLIPPER_UTILS_DEBUG
66 #include "SVG.hpp"
77 #endif /* CLIPPER_UTILS_DEBUG */
8
9 #include <Shiny/Shiny.h>
810
911 namespace Slic3r {
1012
2729
2830 void PolyTreeToExPolygons(ClipperLib::PolyTree& polytree, Slic3r::ExPolygons* expolygons)
2931 {
30 expolygons->clear();
31 for (int i = 0; i < polytree.ChildCount(); ++i)
32 AddOuterPolyNodeToExPolygons(*polytree.Childs[i], expolygons);
32 PROFILE_FUNC();
33 expolygons->clear();
34 for (int i = 0; i < polytree.ChildCount(); ++i)
35 AddOuterPolyNodeToExPolygons(*polytree.Childs[i], expolygons);
3336 }
3437 //-----------------------------------------------------------
3538
3740 void
3841 ClipperPath_to_Slic3rMultiPoint(const ClipperLib::Path &input, T* output)
3942 {
43 PROFILE_FUNC();
4044 output->points.clear();
4145 output->points.reserve(input.size());
4246 for (ClipperLib::Path::const_iterator pit = input.begin(); pit != input.end(); ++pit)
4852 void
4953 ClipperPaths_to_Slic3rMultiPoints(const ClipperLib::Paths &input, T* output)
5054 {
55 PROFILE_FUNC();
5156 output->clear();
5257 output->reserve(input.size());
5358 for (ClipperLib::Paths::const_iterator it = input.begin(); it != input.end(); ++it) {
6065 void
6166 ClipperPaths_to_Slic3rExPolygons(const ClipperLib::Paths &input, Slic3r::ExPolygons* output)
6267 {
68 PROFILE_FUNC();
69
6370 // init Clipper
6471 ClipperLib::Clipper clipper;
6572 clipper.Clear();
7784 void
7885 Slic3rMultiPoint_to_ClipperPath(const Slic3r::MultiPoint &input, ClipperLib::Path* output)
7986 {
87 PROFILE_FUNC();
88
8089 output->clear();
8190 output->reserve(input.points.size());
8291 for (Slic3r::Points::const_iterator pit = input.points.begin(); pit != input.points.end(); ++pit)
8695 void
8796 Slic3rMultiPoint_to_ClipperPath_reversed(const Slic3r::MultiPoint &input, ClipperLib::Path* output)
8897 {
98 PROFILE_FUNC();
99
89100 output->clear();
90101 output->reserve(input.points.size());
91102 for (Slic3r::Points::const_reverse_iterator pit = input.points.rbegin(); pit != input.points.rend(); ++pit)
96107 void
97108 Slic3rMultiPoints_to_ClipperPaths(const T &input, ClipperLib::Paths* output)
98109 {
110 PROFILE_FUNC();
111
99112 output->clear();
100113 output->reserve(input.size());
101114 for (typename T::const_iterator it = input.begin(); it != input.end(); ++it) {
109122 void
110123 scaleClipperPolygon(ClipperLib::Path &polygon, const double scale)
111124 {
125 PROFILE_FUNC();
126
112127 for (ClipperLib::Path::iterator pit = polygon.begin(); pit != polygon.end(); ++pit) {
113128 //FIXME multiplication of int64_t by double!
114129 // Replace by bit shifts?
120135 void
121136 scaleClipperPolygons(ClipperLib::Paths &polygons, const double scale)
122137 {
138 PROFILE_FUNC();
139
123140 for (ClipperLib::Paths::iterator it = polygons.begin(); it != polygons.end(); ++it) {
124141 for (ClipperLib::Path::iterator pit = (*it).begin(); pit != (*it).end(); ++pit) {
125142 //FIXME multiplication of int64_t by double!
134151 offset(const Slic3r::Polygons &polygons, ClipperLib::Paths* retval, const float delta,
135152 double scale, ClipperLib::JoinType joinType, double miterLimit)
136153 {
154 PROFILE_FUNC();
137155 // read input
138156 ClipperLib::Paths input;
139157 Slic3rMultiPoints_to_ClipperPaths(polygons, &input);
148166 } else {
149167 co.MiterLimit = miterLimit;
150168 }
151 co.AddPaths(input, joinType, ClipperLib::etClosedPolygon);
152 co.Execute(*retval, (delta*scale));
169 {
170 PROFILE_BLOCK(offset_AddPaths);
171 co.AddPaths(input, joinType, ClipperLib::etClosedPolygon);
172 }
173 {
174 PROFILE_BLOCK(offset_Execute);
175 co.Execute(*retval, (delta*scale));
176 }
153177
154178 // unscale output
155179 scaleClipperPolygons(*retval, 1/scale);
433457 offset2(const Slic3r::Polygons &polygons, ClipperLib::Paths* retval, const float delta1,
434458 const float delta2, const double scale, const ClipperLib::JoinType joinType, const double miterLimit)
435459 {
460 if (delta1 * delta2 >= 0) {
461 // Both deltas are the same signum
462 offset(polygons, retval, delta1 + delta2, scale, joinType, miterLimit);
463 return;
464 }
436465 #ifdef CLIPPER_UTILS_DEBUG
437466 BoundingBox bbox = get_extents(polygons);
438467 coordf_t stroke_width = scale_(0.005);
525554 void _clipper_do(const ClipperLib::ClipType clipType, const Slic3r::Polygons &subject,
526555 const Slic3r::Polygons &clip, T* retval, const ClipperLib::PolyFillType fillType, const bool safety_offset_)
527556 {
557 PROFILE_BLOCK(_clipper_do_polygons);
558
528559 // read input
529560 ClipperLib::Paths input_subject, input_clip;
530561 Slic3rMultiPoints_to_ClipperPaths(subject, &input_subject);
544575 clipper.Clear();
545576
546577 // add polygons
547 clipper.AddPaths(input_subject, ClipperLib::ptSubject, true);
548 clipper.AddPaths(input_clip, ClipperLib::ptClip, true);
578 {
579 PROFILE_BLOCK(_clipper_do_polygons_AddPaths);
580 clipper.AddPaths(input_subject, ClipperLib::ptSubject, true);
581 clipper.AddPaths(input_clip, ClipperLib::ptClip, true);
582 }
549583
550584 // perform operation
551 clipper.Execute(clipType, *retval, fillType, fillType);
585 {
586 PROFILE_BLOCK(_clipper_do_polygons_Execute);
587 clipper.Execute(clipType, *retval, fillType, fillType);
588 }
552589 }
553590
554591 void _clipper_do(const ClipperLib::ClipType clipType, const Slic3r::Polylines &subject,
555592 const Slic3r::Polygons &clip, ClipperLib::PolyTree* retval, const ClipperLib::PolyFillType fillType,
556593 const bool safety_offset_)
557594 {
595 PROFILE_BLOCK(_clipper_do_polylines);
596
558597 // read input
559598 ClipperLib::Paths input_subject, input_clip;
560599 Slic3rMultiPoints_to_ClipperPaths(subject, &input_subject);
568607 clipper.Clear();
569608
570609 // add polygons
571 clipper.AddPaths(input_subject, ClipperLib::ptSubject, false);
572 clipper.AddPaths(input_clip, ClipperLib::ptClip, true);
610 {
611 PROFILE_BLOCK(_clipper_do_polylines_AddPaths);
612 clipper.AddPaths(input_subject, ClipperLib::ptSubject, false);
613 clipper.AddPaths(input_clip, ClipperLib::ptClip, true);
614 }
573615
574616 // perform operation
575 clipper.Execute(clipType, *retval, fillType, fillType);
617 {
618 PROFILE_BLOCK(_clipper_do_polylines_Execute);
619 clipper.Execute(clipType, *retval, fillType, fillType);
620 }
576621 }
577622
578623 void _clipper(ClipperLib::ClipType clipType, const Slic3r::Polygons &subject,
579624 const Slic3r::Polygons &clip, Slic3r::Polygons* retval, bool safety_offset_)
580625 {
626 PROFILE_FUNC();
581627 // perform operation
582628 ClipperLib::Paths output;
583629 _clipper_do<ClipperLib::Paths>(clipType, subject, clip, &output, ClipperLib::pftNonZero, safety_offset_);
589635 void _clipper(ClipperLib::ClipType clipType, const Slic3r::Polygons &subject,
590636 const Slic3r::Polygons &clip, Slic3r::ExPolygons* retval, bool safety_offset_)
591637 {
638 PROFILE_FUNC();
592639 // perform operation
593640 ClipperLib::PolyTree polytree;
594641 _clipper_do<ClipperLib::PolyTree>(clipType, subject, clip, &polytree, ClipperLib::pftNonZero, safety_offset_);
600647 void _clipper(ClipperLib::ClipType clipType, const Slic3r::Polylines &subject,
601648 const Slic3r::Polygons &clip, Slic3r::Polylines* retval, bool safety_offset_)
602649 {
650 PROFILE_FUNC();
603651 // perform operation
604652 ClipperLib::PolyTree polytree;
605653 _clipper_do(clipType, subject, clip, &polytree, ClipperLib::pftNonZero, safety_offset_);
885933
886934 void simplify_polygons(const Slic3r::Polygons &subject, Slic3r::Polygons* retval, bool preserve_collinear)
887935 {
936 PROFILE_FUNC();
937
888938 // convert into Clipper polygons
889939 ClipperLib::Paths input_subject, output;
890940 Slic3rMultiPoints_to_ClipperPaths(subject, &input_subject);
905955
906956 void simplify_polygons(const Slic3r::Polygons &subject, Slic3r::ExPolygons* retval, bool preserve_collinear)
907957 {
958 PROFILE_FUNC();
959
908960 if (!preserve_collinear) {
909961 Polygons polygons;
910962 simplify_polygons(subject, &polygons, preserve_collinear);
930982
931983 void safety_offset(ClipperLib::Paths* paths)
932984 {
985 PROFILE_FUNC();
986
933987 // scale input
934988 scaleClipperPolygons(*paths, CLIPPER_OFFSET_SCALE);
935989
936990 // perform offset (delta = scale 1e-05)
937991 ClipperLib::ClipperOffset co;
938992 co.MiterLimit = 2;
939 co.AddPaths(*paths, ClipperLib::jtMiter, ClipperLib::etClosedPolygon);
940 co.Execute(*paths, 10.0 * CLIPPER_OFFSET_SCALE);
993 {
994 PROFILE_BLOCK(safety_offset_AddPaths);
995 co.AddPaths(*paths, ClipperLib::jtMiter, ClipperLib::etClosedPolygon);
996 }
997 {
998 PROFILE_BLOCK(safety_offset_Execute);
999 co.Execute(*paths, 10.0 * CLIPPER_OFFSET_SCALE);
1000 }
9411001
9421002 // unscale output
9431003 scaleClipperPolygons(*paths, 1.0/CLIPPER_OFFSET_SCALE);
5757
5858 void ExtrusionPath::polygons_covered_by_width(Polygons &out, const float scaled_epsilon) const
5959 {
60 offset(this->polyline, &out, scale_(this->width/2) + scaled_epsilon);
60 Polygons tmp;
61 offset(this->polyline, &tmp, scale_(this->width/2) + scaled_epsilon);
62 polygons_append(out, STDMOVE(tmp));
6163 }
6264
6365 void ExtrusionPath::polygons_covered_by_spacing(Polygons &out, const float scaled_epsilon) const
6567 // Instantiating the Flow class to get the line spacing.
6668 // Don't know the nozzle diameter, setting to zero. It shall not matter it shall be optimized out by the compiler.
6769 Flow flow(this->width, this->height, 0.f, this->is_bridge());
68 offset(this->polyline, &out, 0.5f * flow.scaled_spacing() + scaled_epsilon);
70 Polygons tmp;
71 offset(this->polyline, &tmp, 0.5f * flow.scaled_spacing() + scaled_epsilon);
72 polygons_append(out, STDMOVE(tmp));
6973 }
7074
7175 bool
263263 if (rate < 40.f) {
264264 printf("Extremely low flow rate: %f. Line %d, Length: %f, extrusion: %f Old position: (%f, %f, %f), new position: (%f, %f, %f)\n",
265265 rate,
266 line_idx,
266 int(line_idx),
267267 sqrt(len2), sqrt((diff[3]*diff[3])/len2),
268268 m_current_pos[0], m_current_pos[1], m_current_pos[2],
269269 new_pos[0], new_pos[1], new_pos[2]);
503503 }
504504 cellsorder.insert(cellsorder.begin() + low, ArrangeItemIndex(index, c));
505505 }
506 ENDSORT: true;
506 ENDSORT: ;
507507 }
508508 }
509509
102102 } else {
103103 Polygons slices_p;
104104 FOREACH_LAYERREGION(this, layerm) {
105 Polygons region_slices_p = (*layerm)->slices;
106 slices_p.insert(slices_p.end(), region_slices_p.begin(), region_slices_p.end());
105 polygons_append(slices_p, to_polygons((*layerm)->slices));
107106 }
108107 union_(slices_p, &slices);
109108 }
122121 Slic3r::Geometry::chained_path(ordering_points, order);
123122
124123 // populate slices vector
125 for (std::vector<Points::size_type>::const_iterator it = order.begin(); it != order.end(); ++it) {
126 this->slices.expolygons.push_back(slices[*it]);
127 }
124 for (std::vector<Points::size_type>::const_iterator it = order.begin(); it != order.end(); ++it)
125 this->slices.expolygons.push_back(STDMOVE(slices[*it]));
128126 }
129127
130128 void
131129 Layer::merge_slices()
132130 {
133 FOREACH_LAYERREGION(this, layerm) {
134 (*layerm)->merge_slices();
131 if (this->regions.size() == 1) {
132 // Optimization, also more robust. Don't merge classified pieces of layerm->slices,
133 // but use the non-split islands of a layer. For a single region print, these shall be equal.
134 this->regions.front()->slices.surfaces.clear();
135 surfaces_append(this->regions.front()->slices.surfaces, this->slices.expolygons, stInternal);
136 } else {
137 FOREACH_LAYERREGION(this, layerm) {
138 ExPolygons expp;
139 // without safety offset, artifacts are generated (GH #2494)
140 union_(to_polygons(STDMOVE((*layerm)->slices.surfaces)), &expp, true);
141 (*layerm)->slices.surfaces.clear();
142 surfaces_append((*layerm)->slices.surfaces, expp, stInternal);
143 }
135144 }
136145 }
137146
199208
200209 if (layerms.size() == 1) { // optimization
201210 (*layerm)->fill_surfaces.surfaces.clear();
202 (*layerm)->perimeter_surfaces.surfaces.clear();
203 (*layerm)->make_perimeters((*layerm)->slices, &(*layerm)->perimeter_surfaces, &(*layerm)->fill_surfaces);
204 this->perimeter_expolygons.expolygons.clear();
205 for (Surfaces::const_iterator it = (*layerm)->perimeter_surfaces.surfaces.begin(); it != (*layerm)->perimeter_surfaces.surfaces.end(); ++ it)
206 this->perimeter_expolygons.expolygons.push_back(it->expolygon);
211 (*layerm)->make_perimeters((*layerm)->slices, &(*layerm)->fill_surfaces);
212 (*layerm)->fill_expolygons = to_expolygons((*layerm)->fill_surfaces.surfaces);
207213 } else {
208 // group slices (surfaces) according to number of extra perimeters
209 std::map<unsigned short,Surfaces> slices; // extra_perimeters => [ surface, surface... ]
210 for (LayerRegionPtrs::iterator l = layerms.begin(); l != layerms.end(); ++l) {
211 for (Surfaces::iterator s = (*l)->slices.surfaces.begin(); s != (*l)->slices.surfaces.end(); ++s) {
212 slices[s->extra_perimeters].push_back(*s);
214 SurfaceCollection new_slices;
215 {
216 // group slices (surfaces) according to number of extra perimeters
217 std::map<unsigned short,Surfaces> slices; // extra_perimeters => [ surface, surface... ]
218 for (LayerRegionPtrs::iterator l = layerms.begin(); l != layerms.end(); ++l) {
219 for (Surfaces::iterator s = (*l)->slices.surfaces.begin(); s != (*l)->slices.surfaces.end(); ++s) {
220 slices[s->extra_perimeters].push_back(*s);
221 }
213222 }
214 }
215
216 // merge the surfaces assigned to each group
217 SurfaceCollection new_slices;
218 for (std::map<unsigned short,Surfaces>::const_iterator it = slices.begin(); it != slices.end(); ++it) {
219 ExPolygons expp = union_ex(it->second, true);
220 for (ExPolygons::iterator ex = expp.begin(); ex != expp.end(); ++ex) {
221 Surface s = it->second.front(); // clone type and extra_perimeters
222 s.expolygon = *ex;
223 new_slices.surfaces.push_back(s);
224 }
223 // merge the surfaces assigned to each group
224 for (std::map<unsigned short,Surfaces>::const_iterator it = slices.begin(); it != slices.end(); ++it)
225 surfaces_append(new_slices.surfaces, union_ex(it->second, true), it->second.front());
225226 }
226227
227228 // make perimeters
228 SurfaceCollection perimeter_surfaces;
229229 SurfaceCollection fill_surfaces;
230 (*layerm)->make_perimeters(new_slices, &perimeter_surfaces, &fill_surfaces);
231 // Copy the perimeter surfaces to the layer's surfaces before splitting them into the regions.
232 this->perimeter_expolygons.expolygons.clear();
233 for (Surfaces::const_iterator it = perimeter_surfaces.surfaces.begin(); it != perimeter_surfaces.surfaces.end(); ++ it)
234 this->perimeter_expolygons.expolygons.push_back(it->expolygon);
230 (*layerm)->make_perimeters(new_slices, &fill_surfaces);
235231
236232 // assign fill_surfaces to each layer
237233 if (!fill_surfaces.surfaces.empty()) {
238234 for (LayerRegionPtrs::iterator l = layerms.begin(); l != layerms.end(); ++l) {
239235 // Separate the fill surfaces.
240 ExPolygons expp = intersection_ex(
241 fill_surfaces,
242 (*l)->slices
243 );
236 ExPolygons expp = intersection_ex(to_polygons(fill_surfaces), (*l)->slices);
237 (*l)->fill_expolygons = expp;
244238 (*l)->fill_surfaces.surfaces.clear();
245
246 for (ExPolygons::iterator ex = expp.begin(); ex != expp.end(); ++ex) {
247 Surface s = fill_surfaces.surfaces.front(); // clone type and extra_perimeters
248 s.expolygon = *ex;
249 (*l)->fill_surfaces.surfaces.push_back(s);
250 }
251
252 // Separate the perimeter surfaces.
253 expp = intersection_ex(
254 perimeter_surfaces,
255 (*l)->slices
256 );
257 (*l)->perimeter_surfaces.surfaces.clear();
258
259 for (ExPolygons::iterator ex = expp.begin(); ex != expp.end(); ++ex) {
260 Surface s = fill_surfaces.surfaces.front(); // clone type and extra_perimeters
261 s.expolygon = *ex;
262 (*l)->perimeter_surfaces.surfaces.push_back(s);
263 }
239 surfaces_append((*l)->fill_surfaces.surfaces, STDMOVE(expp), fill_surfaces.surfaces.front());
264240 }
265241 }
266242 }
3535 // collection of extrusion paths/loops filling gaps
3636 ExtrusionEntityCollection thin_fills;
3737
38 // Unspecified fill polygons, used for overhang detection ("ensure vertical wall thickness feature")
39 // and for re-starting of infills.
40 ExPolygons fill_expolygons;
3841 // collection of surfaces for infill generation
39 SurfaceCollection fill_surfaces;
42 SurfaceCollection fill_surfaces;
4043
4144 // Collection of perimeter surfaces. This is a cached result of diff(slices, fill_surfaces).
4245 // While not necessary, the memory consumption is meager and it speeds up calculation.
5962 ExtrusionEntityCollection fills;
6063
6164 Flow flow(FlowRole role, bool bridge = false, double width = -1) const;
62 void merge_slices();
6365 void slices_to_fill_surfaces_clipped();
6466 void prepare_fill_surfaces();
65 void make_perimeters(const SurfaceCollection &slices, SurfaceCollection* perimeter_surfaces, SurfaceCollection* fill_surfaces);
67 void make_perimeters(const SurfaceCollection &slices, SurfaceCollection* fill_surfaces);
6668 void process_external_surfaces(const Layer* lower_layer);
6769 double infill_area_threshold() const;
6870
102104
103105 // collection of expolygons generated by slicing the original geometry;
104106 // also known as 'islands' (all regions and surface types are merged here)
107 // The slices are chained by the shortest traverse distance and this traversal
108 // order will be recovered by the G-code generator.
105109 ExPolygonCollection slices;
106 // Surfaces of the perimeters including their gap fill.
107 ExPolygonCollection perimeter_expolygons;
108
109110
110111 size_t region_count() const;
111112 const LayerRegion* get_region(int idx) const { return this->regions.at(idx); }
4040 );
4141 }
4242
43 void
44 LayerRegion::merge_slices()
45 {
46 ExPolygons expp;
47 // without safety offset, artifacts are generated (GH #2494)
48 union_(to_polygons(STDMOVE(this->slices.surfaces)), &expp, true);
49 this->slices.surfaces.clear();
50 surfaces_append(this->slices.surfaces, expp, stInternal);
51 }
52
5343 // Fill in layerm->fill_surfaces by trimming the layerm->slices by the cummulative layerm->fill_surfaces.
5444 void LayerRegion::slices_to_fill_surfaces_clipped()
5545 {
5747 // in place. However we're now only using its boundaries (which are invariant)
5848 // so we're safe. This guarantees idempotence of prepare_infill() also in case
5949 // that combine_infill() turns some fill_surface into VOID surfaces.
60 Polygons fill_boundaries = to_polygons(STDMOVE(this->fill_surfaces));
50 // Polygons fill_boundaries = to_polygons(STDMOVE(this->fill_surfaces));
51 Polygons fill_boundaries = to_polygons(this->fill_expolygons);
6152 this->fill_surfaces.surfaces.clear();
6253 for (Surfaces::const_iterator surface = this->slices.surfaces.begin(); surface != this->slices.surfaces.end(); ++ surface)
6354 surfaces_append(
6758 }
6859
6960 void
70 LayerRegion::make_perimeters(const SurfaceCollection &slices, SurfaceCollection* perimeter_surfaces, SurfaceCollection* fill_surfaces)
61 LayerRegion::make_perimeters(const SurfaceCollection &slices, SurfaceCollection* fill_surfaces)
7162 {
7263 this->perimeters.clear();
7364 this->thin_fills.clear();
8475 // output:
8576 &this->perimeters,
8677 &this->thin_fills,
87 perimeter_surfaces,
8878 fill_surfaces
8979 );
9080
125115 // Internal surfaces, not grown.
126116 Surfaces internal;
127117 // Areas, where an infill of various types (top, bottom, bottom bride, sparse, void) could be placed.
118 //FIXME if non zero infill, then fill_boundaries could be cheaply initialized from layerm->fill_expolygons.
128119 Polygons fill_boundaries;
129120
130121 // Collect top surfaces and internal surfaces.
366357
367358 // if no solid layers are requested, turn top/bottom surfaces to internal
368359 if (this->region()->config.top_solid_layers == 0) {
369 for (Surfaces::iterator surface = this->fill_surfaces.surfaces.begin(); surface != this->fill_surfaces.surfaces.end(); ++surface) {
370 if (surface->surface_type == stTop) {
371 if (this->layer()->object()->config.infill_only_where_needed) {
372 surface->surface_type = stInternalVoid;
373 } else {
374 surface->surface_type = stInternal;
375 }
376 }
377 }
360 for (Surfaces::iterator surface = this->fill_surfaces.surfaces.begin(); surface != this->fill_surfaces.surfaces.end(); ++surface)
361 if (surface->surface_type == stTop)
362 surface->surface_type = (this->layer()->object()->config.infill_only_where_needed) ?
363 stInternalVoid : stInternal;
378364 }
379365 if (this->region()->config.bottom_solid_layers == 0) {
380366 for (Surfaces::iterator surface = this->fill_surfaces.surfaces.begin(); surface != this->fill_surfaces.surfaces.end(); ++surface) {
472472 void
473473 ModelObject::update_bounding_box()
474474 {
475 this->_bounding_box = this->mesh().bounding_box();
475 // this->_bounding_box = this->mesh().bounding_box();
476 BoundingBoxf3 raw_bbox;
477 for (ModelVolumePtrs::const_iterator v = this->volumes.begin(); v != this->volumes.end(); ++v) {
478 if ((*v)->modifier) continue;
479 raw_bbox.merge((*v)->mesh.bounding_box());
480 }
481 BoundingBoxf3 bb;
482 for (ModelInstancePtrs::const_iterator i = this->instances.begin(); i != this->instances.end(); ++i)
483 bb.merge((*i)->transform_bounding_box(raw_bbox));
484 this->_bounding_box = bb;
476485 this->_bounding_box_valid = true;
477486 }
478487
508517 BoundingBoxf3 bb;
509518 for (ModelVolumePtrs::const_iterator v = this->volumes.begin(); v != this->volumes.end(); ++v) {
510519 if ((*v)->modifier) continue;
511 TriangleMesh mesh = (*v)->mesh;
512
513520 if (this->instances.empty()) CONFESS("Can't call raw_bounding_box() with no instances");
514 this->instances.front()->transform_mesh(&mesh, true);
515
516 bb.merge(mesh.bounding_box());
521 bb.merge(this->instances.front()->transform_mesh_bounding_box(&(*v)->mesh, true));
517522 }
518523 return bb;
519524 }
522527 BoundingBoxf3
523528 ModelObject::instance_bounding_box(size_t instance_idx) const
524529 {
525 TriangleMesh mesh = this->raw_mesh();
526 this->instances[instance_idx]->transform_mesh(&mesh);
527 return mesh.bounding_box();
530 BoundingBoxf3 bb;
531 for (ModelVolumePtrs::const_iterator v = this->volumes.begin(); v != this->volumes.end(); ++v) {
532 if ((*v)->modifier) continue;
533 bb.merge(this->instances[instance_idx]->transform_mesh_bounding_box(&(*v)->mesh, true));
534 }
535 return bb;
528536 }
529537
530538 void
532540 {
533541 // calculate the displacements needed to
534542 // center this object around the origin
535 BoundingBoxf3 bb = this->raw_mesh().bounding_box();
543 BoundingBoxf3 bb;
544 for (ModelVolumePtrs::const_iterator v = this->volumes.begin(); v != this->volumes.end(); ++v)
545 if (! (*v)->modifier)
546 bb.merge((*v)->mesh.bounding_box());
536547
537548 // first align to origin on XYZ
538549 Vectorf3 vector(-bb.min.x, -bb.min.y, -bb.min.z);
774785 mesh->translate(this->offset.x, this->offset.y, 0);
775786 }
776787
788 BoundingBoxf3 ModelInstance::transform_mesh_bounding_box(const TriangleMesh* mesh, bool dont_translate) const
789 {
790 // rotate around mesh origin
791 double c = cos(this->rotation);
792 double s = sin(this->rotation);
793 BoundingBoxf3 bbox;
794 for (int i = 0; i < mesh->stl.stats.number_of_facets; ++ i) {
795 const stl_facet &facet = mesh->stl.facet_start[i];
796 for (int j = 0; j < 3; ++ j) {
797 stl_vertex v = facet.vertex[j];
798 double xold = v.x;
799 double yold = v.y;
800 v.x = float(c * xold - s * yold);
801 v.y = float(s * xold + c * yold);
802 v.x *= float(this->scaling_factor);
803 v.y *= float(this->scaling_factor);
804 v.z *= float(this->scaling_factor);
805 if (!dont_translate) {
806 v.x += this->offset.x;
807 v.y += this->offset.y;
808 }
809 bbox.merge(Pointf3(v.x, v.y, v.z));
810 }
811 }
812 return bbox;
813 }
814
815 BoundingBoxf3 ModelInstance::transform_bounding_box(const BoundingBoxf3 &bbox, bool dont_translate) const
816 {
817 // rotate around mesh origin
818 double c = cos(this->rotation);
819 double s = sin(this->rotation);
820 Pointf3 pts[4] = {
821 bbox.min,
822 bbox.max,
823 Pointf3(bbox.min.x, bbox.max.y, bbox.min.z),
824 Pointf3(bbox.max.x, bbox.min.y, bbox.max.z)
825 };
826 BoundingBoxf3 out;
827 for (int i = 0; i < 4; ++ i) {
828 Pointf3 &v = pts[i];
829 double xold = v.x;
830 double yold = v.y;
831 v.x = float(c * xold - s * yold);
832 v.y = float(s * xold + c * yold);
833 v.x *= this->scaling_factor;
834 v.y *= this->scaling_factor;
835 v.z *= this->scaling_factor;
836 if (!dont_translate) {
837 v.x += this->offset.x;
838 v.y += this->offset.y;
839 }
840 out.merge(v);
841 }
842 return out;
843 }
844
777845 void
778846 ModelInstance::transform_polygon(Polygon* polygon) const
779847 {
214214
215215 // To be called on an external mesh
216216 void transform_mesh(TriangleMesh* mesh, bool dont_translate = false) const;
217 // Calculate a bounding box of a transformed mesh. To be called on an external mesh.
218 BoundingBoxf3 transform_mesh_bounding_box(const TriangleMesh* mesh, bool dont_translate = false) const;
219 // Transform an external bounding box.
220 BoundingBoxf3 transform_bounding_box(const BoundingBoxf3 &bbox, bool dont_translate = false) const;
217221 // To be called on an external polygon. It does not translate the polygon, only rotates and scales.
218222 void transform_polygon(Polygon* polygon) const;
219223
119119 // from the line width of the infill?
120120 coord_t distance = (i == 1) ? ext_pspacing2 : pspacing;
121121
122
123 //FIXME Vojtech: Why there is a special case for the thin walls?
124 // Gap fill is active all the time anyway and this is not the outer perimeter.
125 // if (this->config->thin_walls) {
126 if (false) {
122 if (this->config->thin_walls) {
123 // This path will ensure, that the perimeters do not overfill, as in
124 // prusa3d/Slic3r GH #32, but with the cost of rounding the perimeters
125 // excessively, creating gaps, which then need to be filled in by the not very
126 // reliable gap fill algorithm.
127 // Also the offset2(perimeter, -x, x) may sometimes lead to a perimeter, which is larger than
128 // the original.
127129 offsets = offset2(
128130 last,
129131 -(distance + min_spacing/2 - 1),
130132 +(min_spacing/2 - 1)
131133 );
132134 } else {
135 // If "detect thin walls" is not enabled, this paths will be entered, which
136 // leads to overflows, as in prusa3d/Slic3r GH #32
133137 offsets = offset(
134138 last,
135139 -distance
241245 if (!entities.empty())
242246 this->loops->append(entities);
243247 } // for each loop of an island
244
245 {
246 //FIXME how about the gaps?
247 // Calculate the region of surface->expolygon covered by the perimeters and their gap fills.
248 // The perimeters will later be used to calculate the object skin.
249 ExPolygons expp = diff_ex((Polygons)surface->expolygon, last, true);
250 for (ExPolygons::const_iterator ex = expp.begin(); ex != expp.end(); ++ex)
251 this->perimeter_surfaces->surfaces.push_back(Surface(stPerimeter, *ex));
252 }
253248
254249 // fill gaps
255250 if (!gaps.empty()) {
317312
318313 // collapse too narrow infill areas
319314 coord_t min_perimeter_infill_spacing = ispacing * (1 - INSET_OVERLAP_TOLERANCE);
320 expp = offset2_ex(
321 pp,
322 -inset -min_perimeter_infill_spacing/2,
323 +min_perimeter_infill_spacing/2
324 );
325315
326316 // append infill areas to fill_surfaces
327 for (ExPolygons::const_iterator ex = expp.begin(); ex != expp.end(); ++ex)
328 this->fill_surfaces->surfaces.push_back(Surface(stInternal, *ex)); // use a bogus surface type
317 surfaces_append(
318 this->fill_surfaces->surfaces,
319 offset2_ex(
320 pp,
321 -inset -min_perimeter_infill_spacing/2,
322 +min_perimeter_infill_spacing/2),
323 stInternal);
329324 }
330325 } // for each island
331326 }
5151 // Outputs:
5252 ExtrusionEntityCollection* loops;
5353 ExtrusionEntityCollection* gap_fill;
54 SurfaceCollection* perimeter_surfaces;
5554 SurfaceCollection* fill_surfaces;
5655
5756 PerimeterGenerator(
6766 ExtrusionEntityCollection* loops,
6867 // Gaps without the thin walls
6968 ExtrusionEntityCollection* gap_fill,
70 // Perimeters including their gap fills
71 SurfaceCollection* perimeter_surfaces,
7269 // Infills without the gap fills
7370 SurfaceCollection* fill_surfaces)
7471 : slices(slices), lower_slices(NULL), layer_height(layer_height),
7572 layer_id(-1), perimeter_flow(flow), ext_perimeter_flow(flow),
7673 overhang_flow(flow), solid_infill_flow(flow),
7774 config(config), object_config(object_config), print_config(print_config),
78 loops(loops), gap_fill(gap_fill), perimeter_surfaces(perimeter_surfaces), fill_surfaces(fill_surfaces),
75 loops(loops), gap_fill(gap_fill), fill_surfaces(fill_surfaces),
7976 _ext_mm3_per_mm(-1), _mm3_per_mm(-1), _mm3_per_mm_overhang(-1)
8077 {};
8178 void process();
22 #include "ClipperUtils.hpp"
33 #include "Geometry.hpp"
44 #include "SVG.hpp"
5
6 #include <Shiny/Shiny.h>
57
68 namespace Slic3r {
79
310312 }
311313
312314 // This function analyzes slices of a region (SurfaceCollection slices).
313 // Each slice (instance of Surface) is analyzed, whether it is supported or whether it is the top surface.
315 // Each region slice (instance of Surface) is analyzed, whether it is supported or whether it is the top surface.
314316 // Initially all slices are of type S_TYPE_INTERNAL.
315317 // Slices are compared against the top / bottom slices and regions and classified to the following groups:
316318 // S_TYPE_TOP - Part of a region, which is not covered by any upper layer. This surface will be filled with a top solid infill.
322324 {
323325 // Slic3r::debugf "Detecting solid surfaces...\n";
324326 for (int idx_region = 0; idx_region < this->_print->regions.size(); ++ idx_region) {
325 // Fill in layerm->fill_surfaces by trimming the layerm->slices by the cummulative layerm->fill_surfaces.
327 #ifdef SLIC3R_DEBUG_SLICE_PROCESSING
326328 for (int idx_layer = 0; idx_layer < int(this->layer_count()); ++ idx_layer) {
327329 LayerRegion *layerm = this->layers[idx_layer]->get_region(idx_region);
328 layerm->slices_to_fill_surfaces_clipped();
329 #ifdef SLIC3R_DEBUG_SLICE_PROCESSING
330330 layerm->export_region_fill_surfaces_to_svg_debug("1_detect_surfaces_type-initial");
331 #endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
332331 }
332 #endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
333333
334334 for (int idx_layer = 0; idx_layer < int(this->layer_count()); ++ idx_layer) {
335335 Layer *layer = this->layers[idx_layer];
481481 }
482482 }
483483
484 struct DiscoverVerticalShellsCacheEntry
485 {
486 DiscoverVerticalShellsCacheEntry() : valid(false) {}
487 // Collected polygons, offsetted
488 Polygons slices;
489 Polygons fill_surfaces;
490 // Is this cache entry valid?
491 bool valid;
492 };
493
484494 void
485495 PrintObject::discover_vertical_shells()
486496 {
497 PROFILE_FUNC();
498
499 const SurfaceType surfaces_bottom[2] = { stBottom, stBottomBridge };
500
487501 for (size_t idx_region = 0; idx_region < this->_print->regions.size(); ++ idx_region) {
488 if (! this->_print->regions[idx_region]->config.ensure_vertical_shell_thickness.value)
502 PROFILE_BLOCK(discover_vertical_shells_region);
503
504 const PrintRegion &region = *this->_print->get_region(idx_region);
505 if (! region.config.ensure_vertical_shell_thickness.value)
506 // This region will be handled by discover_horizontal_shells().
489507 continue;
490 for (size_t idx_layer = 0; idx_layer < this->layers.size(); ++ idx_layer) {
508 int n_extra_top_layers = std::max(0, region.config.top_solid_layers.value - 1);
509 int n_extra_bottom_layers = std::max(0, region.config.bottom_solid_layers.value - 1);
510 if (n_extra_top_layers + n_extra_bottom_layers == 0)
511 // Zero or 1 layer, there is no additional vertical wall thickness enforced.
512 continue;
513 // Cyclic buffers of pre-calculated offsetted top/bottom surfaces.
514 std::vector<DiscoverVerticalShellsCacheEntry> cache_top_regions(n_extra_top_layers, DiscoverVerticalShellsCacheEntry());
515 std::vector<DiscoverVerticalShellsCacheEntry> cache_bottom_regions(n_extra_bottom_layers, DiscoverVerticalShellsCacheEntry());
516 for (size_t idx_layer = 0; idx_layer < this->layers.size(); ++ idx_layer)
517 {
518 PROFILE_BLOCK(discover_vertical_shells_region_layer);
519
491520 Layer *layer = this->layers[idx_layer];
492521 LayerRegion *layerm = layer->get_region(idx_region);
493522 Flow solid_infill_flow = layerm->flow(frSolidInfill);
494523 coord_t infill_line_spacing = solid_infill_flow.scaled_spacing();
495524 // Find a union of perimeters below / above this surface to guarantee a minimum shell thickness.
496525 Polygons shell;
526 Polygons holes;
497527 #ifdef SLIC3R_DEBUG_SLICE_PROCESSING
498528 ExPolygons shell_ex;
499529 #endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
500530 float min_perimeter_infill_spacing = float(infill_line_spacing) * 1.05f;
501531 if (1)
502532 {
533 PROFILE_BLOCK(discover_vertical_shells_region_layer_collect);
503534 #ifdef SLIC3R_DEBUG_SLICE_PROCESSING
504535 {
505536 static size_t idx = 0;
506537 SVG svg_cummulative(debug_out_path("discover_vertical_shells-perimeters-before-union-run%d.svg", idx), this->bounding_box());
507 for (int n = (int)idx_layer - layerm->region()->config.bottom_solid_layers + 1; n < (int)idx_layer + layerm->region()->config.top_solid_layers; ++ n) {
538 for (int n = (int)idx_layer - n_extra_bottom_layers; n <= (int)idx_layer + n_extra_top_layers; ++ n) {
508539 if (n < 0 || n >= (int)this->layers.size())
509540 continue;
510541 ExPolygons &expolys = this->layers[n]->perimeter_expolygons;
523554 ++ idx;
524555 }
525556 #endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
526 SurfaceType surfaces_bottom[2] = { stBottom, stBottomBridge };
527 for (int n = (int)idx_layer - layerm->region()->config.bottom_solid_layers + 1; n < (int)idx_layer + layerm->region()->config.top_solid_layers; ++ n)
557 // Reset the top / bottom inflated regions caches of entries, which are out of the moving window.
558 if (n_extra_top_layers > 0)
559 cache_top_regions[idx_layer % n_extra_top_layers].valid = false;
560 if (n_extra_bottom_layers > 0 && idx_layer > 0)
561 cache_bottom_regions[(idx_layer - 1) % n_extra_bottom_layers].valid = false;
562 bool hole_first = true;
563 for (int n = (int)idx_layer - n_extra_bottom_layers; n <= (int)idx_layer + n_extra_top_layers; ++ n)
528564 if (n >= 0 && n < (int)this->layers.size()) {
529565 Layer &neighbor_layer = *this->layers[n];
530566 LayerRegion &neighbor_region = *neighbor_layer.get_region(int(idx_region));
531 polygons_append(shell, neighbor_layer.perimeter_expolygons.expolygons);
567 Polygons newholes;
568 for (size_t idx_region = 0; idx_region < this->_print->regions.size(); ++ idx_region)
569 polygons_append(newholes, to_polygons(neighbor_layer.get_region(idx_region)->fill_expolygons));
570 if (hole_first) {
571 hole_first = false;
572 polygons_append(holes, STDMOVE(newholes));
573 }
574 else if (! holes.empty()) {
575 holes = intersection(holes, newholes);
576 }
577 size_t n_shell_old = shell.size();
532578 if (n > int(idx_layer)) {
533579 // Collect top surfaces.
534 polygons_append(shell, offset(to_expolygons(neighbor_region.slices.filter_by_type(stTop)), min_perimeter_infill_spacing));
535 polygons_append(shell, offset(to_expolygons(neighbor_region.fill_surfaces.filter_by_type(stTop)), min_perimeter_infill_spacing));
580 DiscoverVerticalShellsCacheEntry &cache = cache_top_regions[n % n_extra_top_layers];
581 if (! cache.valid) {
582 cache.valid = true;
583 // neighbor_region.slices contain the source top regions,
584 // so one would think that they encompass the top fill_surfaces. But the fill_surfaces could have been
585 // expanded before, therefore they may protrude out of neighbor_region.slices's top surfaces.
586 //FIXME one should probably use the cummulative top surfaces over all regions here.
587 cache.slices = offset(to_expolygons(neighbor_region.slices.filter_by_type(stTop)), min_perimeter_infill_spacing);
588 cache.fill_surfaces = offset(to_expolygons(neighbor_region.fill_surfaces.filter_by_type(stTop)), min_perimeter_infill_spacing);
589 }
590 polygons_append(shell, cache.slices);
591 polygons_append(shell, cache.fill_surfaces);
536592 }
537593 else if (n < int(idx_layer)) {
538594 // Collect bottom and bottom bridge surfaces.
539 polygons_append(shell, offset(to_expolygons(neighbor_region.slices.filter_by_types(surfaces_bottom, 2)), min_perimeter_infill_spacing));
540 polygons_append(shell, offset(to_expolygons(neighbor_region.fill_surfaces.filter_by_types(surfaces_bottom, 2)), min_perimeter_infill_spacing));
595 DiscoverVerticalShellsCacheEntry &cache = cache_bottom_regions[n % n_extra_bottom_layers];
596 if (! cache.valid) {
597 cache.valid = true;
598 //FIXME one should probably use the cummulative top surfaces over all regions here.
599 cache.slices = offset(to_expolygons(neighbor_region.slices.filter_by_types(surfaces_bottom, 2)), min_perimeter_infill_spacing);
600 cache.fill_surfaces = offset(to_expolygons(neighbor_region.fill_surfaces.filter_by_types(surfaces_bottom, 2)), min_perimeter_infill_spacing);
601 }
602 polygons_append(shell, cache.slices);
603 polygons_append(shell, cache.fill_surfaces);
541604 }
605 // Running the union_ using the Clipper library piece by piece is cheaper
606 // than running the union_ all at once.
607 if (n_shell_old < shell.size())
608 shell = union_(shell, false);
542609 }
543610 #ifdef SLIC3R_DEBUG_SLICE_PROCESSING
544611 {
549616 svg.Close();
550617 }
551618 #endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
552 shell = union_(shell, true);
619 #if 0
620 {
621 PROFILE_BLOCK(discover_vertical_shells_region_layer_shell_);
622 // shell = union_(shell, true);
623 shell = union_(shell, false);
624 }
625 #endif
553626 #ifdef SLIC3R_DEBUG_SLICE_PROCESSING
554627 shell_ex = union_ex(shell, true);
555628 #endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
556629 }
557630
558 if (shell.empty())
559 continue;
631 //if (shell.empty())
632 // continue;
560633
561634 #ifdef SLIC3R_DEBUG_SLICE_PROCESSING
562635 {
602675 const SurfaceType surfaceTypesInternal[] = { stInternal, stInternalVoid, stInternalSolid };
603676 const Polygons polygonsInternal = to_polygons(layerm->fill_surfaces.filter_by_types(surfaceTypesInternal, 2));
604677 shell = intersection(shell, polygonsInternal, true);
678 polygons_append(shell, diff(polygonsInternal, holes));
605679 if (shell.empty())
606680 continue;
607681
689763 #endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
690764 } // for each layer
691765 } // for each region
766
767 // Write the profiler measurements to file
768 PROFILE_UPDATE();
769 PROFILE_OUTPUT(debug_out_path("discover_vertical_shells-profile.txt").c_str());
692770 }
693771
694772 /* This method applies bridge flow to the first internal solid layer above
9696 return polygons;
9797 }
9898
99 inline ExPolygons to_expolygons(const Surfaces &src)
100 {
101 ExPolygons expolygons;
102 expolygons.reserve(src.size());
103 for (Surfaces::const_iterator it = src.begin(); it != src.end(); ++it)
104 expolygons.push_back(it->expolygon);
105 return expolygons;
106 }
107
99108 inline ExPolygons to_expolygons(const SurfacesPtr &src)
100109 {
101110 ExPolygons expolygons;
5757 void
5858 TriangleMesh::swap(TriangleMesh &other)
5959 {
60 std::swap(this->stl, other.stl);
61 std::swap(this->repaired, other.repaired);
62 std::swap(this->stl.facet_start, other.stl.facet_start);
63 std::swap(this->stl.neighbors_start, other.stl.neighbors_start);
64 std::swap(this->stl.v_indices, other.stl.v_indices);
65 std::swap(this->stl.v_shared, other.stl.v_shared);
60 std::swap(this->stl, other.stl);
61 std::swap(this->repaired, other.repaired);
6662 }
6763
6864 TriangleMesh::~TriangleMesh() {
99 #include <stdarg.h>
1010
1111 #define SLIC3R_FORK_NAME "Slic3r Prusa Edition"
12 #define SLIC3R_VERSION "1.3.0-dev"
12 #define SLIC3R_VERSION "1.31.6"
1313
1414 //FIXME This epsilon value is used for many non-related purposes:
1515 // For a threshold of a squared Euclidean distance,
3939 #include "ppport.h"
4040 #undef do_open
4141 #undef do_close
42 #undef bind
43 #undef seed
4244 #ifdef _MSC_VER
4345 // Undef some of the macros set by Perl <xsinit.h>, which cause compilation errors on Win32
4446 #undef send
4547 #undef connect
46 #undef bind
4748 #endif /* _MSC_VER */
4849 }
4950 #endif
2828 long x_max() %code{% RETVAL = THIS->max.x; %};
2929 long y_min() %code{% RETVAL = THIS->min.y; %};
3030 long y_max() %code{% RETVAL = THIS->max.y; %};
31 std::string serialize() %code{% char buf[2048]; sprintf(buf, "%d,%d;%d,%d", THIS->min.x, THIS->min.y, THIS->max.x, THIS->max.y); RETVAL = buf; %};
31 std::string serialize() %code{% char buf[2048]; sprintf(buf, "%ld,%ld;%ld,%ld", THIS->min.x, THIS->min.y, THIS->max.x, THIS->max.y); RETVAL = buf; %};
3232
3333 %{
3434
2929
3030 Clone<Flow> flow(FlowRole role, bool bridge = false, double width = -1)
3131 %code%{ RETVAL = THIS->flow(role, bridge, width); %};
32 void merge_slices();
3332 void prepare_fill_surfaces();
34 void make_perimeters(SurfaceCollection* slices, SurfaceCollection* perimeter_surfaces, SurfaceCollection* fill_surfaces)
35 %code%{ THIS->make_perimeters(*slices, perimeter_surfaces, fill_surfaces); %};
33 void make_perimeters(SurfaceCollection* slices, SurfaceCollection* fill_surfaces)
34 %code%{ THIS->make_perimeters(*slices, fill_surfaces); %};
3635 double infill_area_threshold();
3736
3837 void export_region_slices_to_svg(const char *path);
7978 Ref<ExPolygonCollection> slices()
8079 %code%{ RETVAL = &THIS->slices; %};
8180
82 Ref<ExPolygonCollection> perimeter_expolygons()
83 %code%{ RETVAL = &THIS->perimeter_expolygons; %};
84
8581 int ptr()
8682 %code%{ RETVAL = (int)(intptr_t)THIS; %};
8783
99 StaticPrintConfig* region_config, StaticPrintConfig* object_config,
1010 StaticPrintConfig* print_config, ExtrusionEntityCollection* loops,
1111 ExtrusionEntityCollection* gap_fill,
12 SurfaceCollection* perimeter_surfaces, SurfaceCollection* fill_surfaces)
12 SurfaceCollection* fill_surfaces)
1313 %code{% RETVAL = new PerimeterGenerator(slices, layer_height, *flow,
1414 dynamic_cast<PrintRegionConfig*>(region_config),
1515 dynamic_cast<PrintObjectConfig*>(object_config),
1616 dynamic_cast<PrintConfig*>(print_config),
17 loops, gap_fill, perimeter_surfaces, fill_surfaces); %};
17 loops, gap_fill, fill_surfaces); %};
1818 ~PerimeterGenerator();
1919
2020 void set_lower_slices(ExPolygonCollection* lower_slices)
4848 %code{% RETVAL = new Point(THIS->negative()); %};
4949 bool coincides_with_epsilon(Point* point)
5050 %code{% RETVAL = THIS->coincides_with_epsilon(*point); %};
51 std::string serialize() %code{% char buf[2048]; sprintf(buf, "%d,%d", THIS->x, THIS->y); RETVAL = buf; %};
51 std::string serialize() %code{% char buf[2048]; sprintf(buf, "%ld,%ld", THIS->x, THIS->y); RETVAL = buf; %};
5252
5353 %{
5454
8686 %code{% RETVAL = THIS->y; %};
8787 long z()
8888 %code{% RETVAL = THIS->z; %};
89 std::string serialize() %code{% char buf[2048]; sprintf(buf, "%d,%d,%d", THIS->x, THIS->y, THIS->z); RETVAL = buf; %};
89 std::string serialize() %code{% char buf[2048]; sprintf(buf, "%ld,%ld,%ld", THIS->x, THIS->y, THIS->z); RETVAL = buf; %};
9090 };
9191
9292 %name{Slic3r::Pointf} class Pointf {