PrintObject.cpp 188 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389
  1. #include "Print.hpp"
  2. #include "BoundingBox.hpp"
  3. #include "ClipperUtils.hpp"
  4. #include "ElephantFootCompensation.hpp"
  5. #include "Geometry.hpp"
  6. #include "I18N.hpp"
  7. #include "SupportMaterial.hpp"
  8. #include "Surface.hpp"
  9. #include "Slicing.hpp"
  10. #include "Utils.hpp"
  11. #include <utility>
  12. #include <boost/log/trivial.hpp>
  13. #include <float.h>
  14. #include <tbb/parallel_for.h>
  15. #include <tbb/atomic.h>
  16. #include <Shiny/Shiny.h>
  17. //! macro used to mark string used at localization,
  18. //! return same string
  19. #define L(s) Slic3r::I18N::translate(s)
  20. #ifdef SLIC3R_DEBUG_SLICE_PROCESSING
  21. #define SLIC3R_DEBUG
  22. #endif
  23. // #define SLIC3R_DEBUG
  24. // Make assert active if SLIC3R_DEBUG
  25. #ifdef SLIC3R_DEBUG
  26. #undef NDEBUG
  27. #define DEBUG
  28. #define _DEBUG
  29. #include "SVG.hpp"
  30. #undef assert
  31. #include <cassert>
  32. #endif
  33. namespace Slic3r {
  34. // Constructor is called from the main thread, therefore all Model / ModelObject / ModelIntance data are valid.
  35. PrintObject::PrintObject(Print* print, ModelObject* model_object, const Transform3d& trafo, PrintInstances&& instances) :
  36. PrintObjectBaseWithState(print, model_object),
  37. m_trafo(trafo)
  38. {
  39. // Compute centering offet to be applied to our meshes so that we work with smaller coordinates
  40. // requiring less bits to represent Clipper coordinates.
  41. // Snug bounding box of a rotated and scaled object by the 1st instantion, without the instance translation applied.
  42. // All the instances share the transformation matrix with the exception of translation in XY and rotation by Z,
  43. // therefore a bounding box from 1st instance of a ModelObject is good enough for calculating the object center,
  44. // snug height and an approximate bounding box in XY.
  45. BoundingBoxf3 bbox = model_object->raw_bounding_box();
  46. Vec3d bbox_center = bbox.center();
  47. // We may need to rotate the bbox / bbox_center from the original instance to the current instance.
  48. double z_diff = Geometry::rotation_diff_z(model_object->instances.front()->get_rotation(), instances.front().model_instance->get_rotation());
  49. if (std::abs(z_diff) > EPSILON) {
  50. auto z_rot = Eigen::AngleAxisd(z_diff, Vec3d::UnitZ());
  51. bbox = bbox.transformed(Transform3d(z_rot));
  52. bbox_center = (z_rot * bbox_center).eval();
  53. }
  54. // Center of the transformed mesh (without translation).
  55. m_center_offset = Point::new_scale(bbox_center.x(), bbox_center.y());
  56. // Size of the transformed mesh. This bounding may not be snug in XY plane, but it is snug in Z.
  57. m_size = (bbox.size() * (1. / SCALING_FACTOR)).cast<coord_t>();
  58. this->set_instances(std::move(instances));
  59. //create config hierarchy
  60. m_config.parent = &print->config();
  61. }
  62. PrintBase::ApplyStatus PrintObject::set_instances(PrintInstances &&instances)
  63. {
  64. for (PrintInstance &i : instances)
  65. // Add the center offset, which will be subtracted from the mesh when slicing.
  66. i.shift += m_center_offset;
  67. // Invalidate and set copies.
  68. PrintBase::ApplyStatus status = PrintBase::APPLY_STATUS_UNCHANGED;
  69. bool equal_length = instances.size() == m_instances.size();
  70. bool equal = equal_length && std::equal(instances.begin(), instances.end(), m_instances.begin(),
  71. [](const PrintInstance& lhs, const PrintInstance& rhs) { return lhs.model_instance == rhs.model_instance && lhs.shift == rhs.shift; });
  72. if (! equal) {
  73. status = PrintBase::APPLY_STATUS_CHANGED;
  74. if (m_print->invalidate_steps({ psSkirt, psBrim, psGCodeExport }) ||
  75. (! equal_length && m_print->invalidate_step(psWipeTower)))
  76. status = PrintBase::APPLY_STATUS_INVALIDATED;
  77. m_instances = std::move(instances);
  78. for (PrintInstance &i : m_instances)
  79. i.print_object = this;
  80. }
  81. return status;
  82. }
  83. // 1) Decides Z positions of the layers,
  84. // 2) Initializes layers and their regions
  85. // 3) Slices the object meshes
  86. // 4) Slices the modifier meshes and reclassifies the slices of the object meshes by the slices of the modifier meshes
  87. // 5) Applies size compensation (offsets the slices in XY plane)
  88. // 6) Replaces bad slices by the slices reconstructed from the upper/lower layer
  89. // Resulting expolygons of layer regions are marked as Internal.
  90. //
  91. // this should be idempotent
  92. void PrintObject::slice()
  93. {
  94. if (! this->set_started(posSlice))
  95. return;
  96. m_print->set_status(10, L("Processing triangulated mesh"));
  97. std::vector<coordf_t> layer_height_profile;
  98. this->update_layer_height_profile(*this->model_object(), m_slicing_params, layer_height_profile);
  99. m_print->throw_if_canceled();
  100. this->_slice(layer_height_profile);
  101. m_print->throw_if_canceled();
  102. // Fix the model.
  103. //FIXME is this the right place to do? It is done repeateadly at the UI and now here at the backend.
  104. std::string warning = this->_fix_slicing_errors();
  105. m_print->throw_if_canceled();
  106. if (! warning.empty())
  107. BOOST_LOG_TRIVIAL(info) << warning;
  108. // Simplify slices if required.
  109. if (m_print->config().resolution)
  110. this->simplify_slices(scale_(this->print()->config().resolution));
  111. //create polyholes
  112. this->_transform_hole_to_polyholes();
  113. // Update bounding boxes
  114. tbb::parallel_for(
  115. tbb::blocked_range<size_t>(0, m_layers.size()),
  116. [this](const tbb::blocked_range<size_t>& range) {
  117. for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx) {
  118. m_print->throw_if_canceled();
  119. Layer &layer = *m_layers[layer_idx];
  120. layer.lslices_bboxes.clear();
  121. layer.lslices_bboxes.reserve(layer.lslices.size());
  122. for (const ExPolygon &expoly : layer.lslices)
  123. layer.lslices_bboxes.emplace_back(get_extents(expoly));
  124. }
  125. });
  126. if (m_layers.empty())
  127. throw std::runtime_error("No layers were detected. You might want to repair your STL file(s) or check their size or thickness and retry.\n");
  128. this->set_done(posSlice);
  129. }
  130. Polygon create_polyhole(const Point center, const coord_t diameter, const coord_t nozzle_diameter)
  131. {
  132. // n = max(round(2 * d), 3); // for 0.4mm nozzle
  133. size_t nb_polygons = (int)std::max(3, (int)std::round(2.0 * unscaled(diameter) * 0.4 / unscaled(nozzle_diameter)));
  134. // cylinder(h = h, r = (d / 2) / cos (180 / n), $fn = n);
  135. Points pts;
  136. const float rayon = (diameter / 1) / std::cos(PI / nb_polygons);
  137. for (int i = 0; i < nb_polygons; ++i) {
  138. float angle = (PI * 2 * i) / nb_polygons;
  139. pts.emplace_back(center.x() + rayon * cos(angle), center.y() + rayon * sin(angle));
  140. }
  141. return Polygon{ pts };
  142. }
  143. void PrintObject::_transform_hole_to_polyholes()
  144. {
  145. // get all circular holes for each layer
  146. // the id is center-diameter-extruderid
  147. std::vector<std::vector<std::pair<std::tuple<Point,float, int>, Polygon*>>> layerid2center;
  148. for (size_t i = 0; i < this->m_layers.size(); i++) layerid2center.emplace_back();
  149. //tbb::parallel_for(
  150. //tbb::blocked_range<size_t>(0, m_layers.size()),
  151. //[this, layerid2center](const tbb::blocked_range<size_t>& range) {
  152. //for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++layer_idx) {
  153. for (size_t layer_idx = 0; layer_idx < this->m_layers.size(); ++layer_idx) {
  154. m_print->throw_if_canceled();
  155. Layer *layer = m_layers[layer_idx];
  156. for (size_t region_idx = 0; region_idx < layer->m_regions.size(); ++region_idx)
  157. {
  158. if (layer->m_regions[region_idx]->region()->config().hole_to_polyhole) {
  159. for (Surface &surf : layer->m_regions[region_idx]->m_slices.surfaces) {
  160. for (Polygon &hole : surf.expolygon.holes) {
  161. //test if convex (as it's clockwise bc it's a hole, we have to do the opposite)
  162. if (hole.convex_points().empty() && hole.points.size() > 4) {
  163. double center_x = 0, center_y = 0;
  164. for (int i = 0; i < hole.points.size(); ++i) {
  165. center_x += hole.points[i].x();
  166. center_y += hole.points[i].y();
  167. }
  168. Point center{ center_x / hole.points.size(), center_y / hole.points.size() };
  169. double diameter_min = std::numeric_limits<float>::max(), diameter_max = 0;
  170. for (int i = 0; i < hole.points.size(); ++i) {
  171. double dist = hole.points[i].distance_to_square(center);
  172. diameter_min = std::min(diameter_min, dist);
  173. diameter_max = std::max(diameter_max, dist);
  174. }
  175. diameter_min = std::sqrt(diameter_min);
  176. diameter_max = std::sqrt(diameter_max);
  177. if (diameter_max - diameter_min < SCALED_EPSILON) {
  178. layerid2center[layer_idx].emplace_back(
  179. std::tuple<Point, float, int>{center, diameter_max, layer->m_regions[region_idx]->region()->config().perimeter_extruder.value}, &hole);
  180. }
  181. }
  182. }
  183. }
  184. }
  185. }
  186. // for layer->slices, it will be also replaced later.
  187. }
  188. //});
  189. //sort holes per center-diameter
  190. std::map<std::tuple<Point, float, int>,std::vector<std::pair<Polygon*,int>>> id2layerz2hole;
  191. //search & find hole that span at least X layers
  192. const size_t min_nb_layers = 2;
  193. float max_layer_height = config().layer_height * 2;
  194. for (size_t layer_idx = 0; layer_idx < this->m_layers.size(); ++layer_idx) {
  195. for (size_t hole_idx = 0; hole_idx < layerid2center[layer_idx].size(); ++hole_idx) {
  196. //get all other same polygons
  197. std::tuple<Point, float, int> &id = layerid2center[layer_idx][hole_idx].first;
  198. float max_z = layers()[layer_idx]->print_z;
  199. std::vector<std::pair<Polygon*,int>> holes;
  200. holes.emplace_back(layerid2center[layer_idx][hole_idx].second, layer_idx);
  201. for (size_t search_layer_idx = layer_idx + 1; search_layer_idx < this->m_layers.size(); ++search_layer_idx) {
  202. if (layers()[search_layer_idx]->print_z - layers()[search_layer_idx]->height - max_z > EPSILON) break;
  203. //search an other polygon with same id
  204. for (size_t search_hole_idx = 0; search_hole_idx < layerid2center[search_layer_idx].size(); ++search_hole_idx) {
  205. std::tuple<Point, float, int> &search_id = layerid2center[search_layer_idx][search_hole_idx].first;
  206. if (std::get<0>(id).distance_to(std::get<0>(search_id)) < SCALED_EPSILON
  207. && std::abs(std::get<1>(id) - std::get<1>(search_id)) < SCALED_EPSILON
  208. && std::get<2>(id) == std::get<2>(search_id)) {
  209. max_z = layers()[search_layer_idx]->print_z;
  210. holes.emplace_back(layerid2center[search_layer_idx][search_hole_idx].second, search_layer_idx);
  211. layerid2center[search_layer_idx].erase(layerid2center[search_layer_idx].begin() + search_hole_idx);
  212. search_hole_idx--;
  213. break;
  214. }
  215. }
  216. }
  217. if (holes.size() >= min_nb_layers) {
  218. id2layerz2hole.emplace(std::move(id), std::move(holes));
  219. }
  220. }
  221. }
  222. //create a polyhole per id and replace holes points by it.
  223. for (auto entry : id2layerz2hole) {
  224. Polygon polyhole = create_polyhole(std::get<0>(entry.first), std::get<1>(entry.first), scale_(print()->config().nozzle_diameter.get_at(std::get<2>(entry.first) - 1)));
  225. polyhole.make_clockwise();
  226. for (auto &poly_to_replace : entry.second) {
  227. //search the clone in layers->slices
  228. for (ExPolygon &explo_slice : m_layers[poly_to_replace.second]->lslices) {
  229. for (Polygon &poly_slice : explo_slice.holes) {
  230. if (poly_slice.points == poly_to_replace.first->points) {
  231. poly_slice.points = polyhole.points;
  232. }
  233. }
  234. }
  235. // copy
  236. poly_to_replace.first->points = polyhole.points;
  237. }
  238. }
  239. }
  240. // 1) Merges typed region slices into stInternal type.
  241. // 2) Increases an "extra perimeters" counter at region slices where needed.
  242. // 3) Generates perimeters, gap fills and fill regions (fill regions of type stInternal).
  243. void PrintObject::make_perimeters()
  244. {
  245. // prerequisites
  246. this->slice();
  247. if (! this->set_started(posPerimeters))
  248. return;
  249. m_print->set_status(20, L("Generating perimeters"));
  250. BOOST_LOG_TRIVIAL(info) << "Generating perimeters..." << log_memory_info();
  251. // merge slices if they were split into types
  252. if (m_typed_slices) {
  253. for (Layer *layer : m_layers) {
  254. layer->merge_slices();
  255. m_print->throw_if_canceled();
  256. }
  257. m_typed_slices = false;
  258. }
  259. // compare each layer to the one below, and mark those slices needing
  260. // one additional inner perimeter, like the top of domed objects-
  261. // this algorithm makes sure that at least one perimeter is overlapping
  262. // but we don't generate any extra perimeter if fill density is zero, as they would be floating
  263. // inside the object - infill_only_where_needed should be the method of choice for printing
  264. // hollow objects
  265. for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) {
  266. const PrintRegion &region = *m_print->regions()[region_id];
  267. if (! region.config().extra_perimeters || region.config().perimeters == 0 || region.config().fill_density == 0 || this->layer_count() < 2)
  268. continue;
  269. BOOST_LOG_TRIVIAL(debug) << "Generating extra perimeters for region " << region_id << " in parallel - start";
  270. tbb::parallel_for(
  271. tbb::blocked_range<size_t>(0, m_layers.size() - 1),
  272. [this, &region, region_id](const tbb::blocked_range<size_t>& range) {
  273. for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx) {
  274. m_print->throw_if_canceled();
  275. LayerRegion &layerm = *m_layers[layer_idx]->m_regions[region_id];
  276. const LayerRegion &upper_layerm = *m_layers[layer_idx+1]->m_regions[region_id];
  277. const Polygons upper_layerm_polygons = upper_layerm.slices();
  278. // Filter upper layer polygons in intersection_ppl by their bounding boxes?
  279. // my $upper_layerm_poly_bboxes= [ map $_->bounding_box, @{$upper_layerm_polygons} ];
  280. const double total_loop_length = total_length(upper_layerm_polygons);
  281. const coord_t perimeter_spacing = layerm.flow(frPerimeter).scaled_spacing();
  282. const Flow ext_perimeter_flow = layerm.flow(frExternalPerimeter);
  283. const coord_t ext_perimeter_width = ext_perimeter_flow.scaled_width();
  284. const coord_t ext_perimeter_spacing = ext_perimeter_flow.scaled_spacing();
  285. for (Surface &slice : layerm.m_slices.surfaces) {
  286. for (;;) {
  287. // compute the total thickness of perimeters
  288. const coord_t perimeters_thickness = ext_perimeter_width/2 + ext_perimeter_spacing/2
  289. + (region.config().perimeters-1 + slice.extra_perimeters) * perimeter_spacing;
  290. // define a critical area where we don't want the upper slice to fall into
  291. // (it should either lay over our perimeters or outside this area)
  292. const coord_t critical_area_depth = coord_t(perimeter_spacing * 1.5);
  293. const Polygons critical_area = diff(
  294. offset(slice.expolygon, double(- perimeters_thickness)),
  295. offset(slice.expolygon, double(- perimeters_thickness - critical_area_depth))
  296. );
  297. // check whether a portion of the upper slices falls inside the critical area
  298. const Polylines intersection = intersection_pl(to_polylines(upper_layerm_polygons), critical_area);
  299. // only add an additional loop if at least 30% of the slice loop would benefit from it
  300. if (total_length(intersection) <= total_loop_length*0.3)
  301. break;
  302. /*
  303. if (0) {
  304. require "Slic3r/SVG.pm";
  305. Slic3r::SVG::output(
  306. "extra.svg",
  307. no_arrows => 1,
  308. expolygons => union_ex($critical_area),
  309. polylines => [ map $_->split_at_first_point, map $_->p, @{$upper_layerm->slices} ],
  310. );
  311. }
  312. */
  313. ++ slice.extra_perimeters;
  314. }
  315. #ifdef DEBUG
  316. if (slice.extra_perimeters > 0)
  317. printf(" adding %d more perimeter(s) at layer %zu\n", slice.extra_perimeters, layer_idx);
  318. #endif
  319. }
  320. }
  321. });
  322. m_print->throw_if_canceled();
  323. BOOST_LOG_TRIVIAL(debug) << "Generating extra perimeters for region " << region_id << " in parallel - end";
  324. }
  325. BOOST_LOG_TRIVIAL(debug) << "Generating perimeters in parallel - start";
  326. tbb::parallel_for(
  327. tbb::blocked_range<size_t>(0, m_layers.size()),
  328. [this](const tbb::blocked_range<size_t>& range) {
  329. for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++layer_idx) {
  330. m_print->throw_if_canceled();
  331. m_layers[layer_idx]->make_perimeters();
  332. }
  333. }
  334. );
  335. m_print->throw_if_canceled();
  336. BOOST_LOG_TRIVIAL(debug) << "Generating perimeters in parallel - end";
  337. if (print()->config().milling_diameter.size() > 0 ) {
  338. BOOST_LOG_TRIVIAL(debug) << "Generating milling post-process in parallel - start";
  339. tbb::parallel_for(
  340. tbb::blocked_range<size_t>(0, m_layers.size()),
  341. [this](const tbb::blocked_range<size_t>& range) {
  342. for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++layer_idx) {
  343. m_print->throw_if_canceled();
  344. m_layers[layer_idx]->make_milling_post_process();
  345. }
  346. }
  347. );
  348. m_print->throw_if_canceled();
  349. BOOST_LOG_TRIVIAL(debug) << "Generating milling post-process in parallel - end";
  350. }
  351. this->set_done(posPerimeters);
  352. }
  353. void PrintObject::prepare_infill()
  354. {
  355. if (! this->set_started(posPrepareInfill))
  356. return;
  357. m_print->set_status(30, L("Preparing infill"));
  358. // This will assign a type (top/bottom/internal) to $layerm->slices.
  359. // Then the classifcation of $layerm->slices is transfered onto
  360. // the $layerm->fill_surfaces by clipping $layerm->fill_surfaces
  361. // by the cummulative area of the previous $layerm->fill_surfaces.
  362. this->detect_surfaces_type();
  363. m_print->throw_if_canceled();
  364. // Decide what surfaces are to be filled.
  365. // Here the stTop / stBottomBridge / stBottom infill is turned to just stInternal if zero top / bottom infill layers are configured.
  366. // Also tiny stInternal surfaces are turned to stInternalSolid.
  367. BOOST_LOG_TRIVIAL(info) << "Preparing fill surfaces..." << log_memory_info();
  368. for (auto *layer : m_layers)
  369. for (auto *region : layer->m_regions) {
  370. region->prepare_fill_surfaces();
  371. m_print->throw_if_canceled();
  372. }
  373. // this will detect bridges and reverse bridges
  374. // and rearrange top/bottom/internal surfaces
  375. // It produces enlarged overlapping bridging areas.
  376. //
  377. // 1) stBottomBridge / stBottom infill is grown by 3mm and clipped by the total infill area. Bridges are detected. The areas may overlap.
  378. // 2) stTop is grown by 3mm and clipped by the grown bottom areas. The areas may overlap.
  379. // 3) Clip the internal surfaces by the grown top/bottom surfaces.
  380. // 4) Merge surfaces with the same style. This will mostly get rid of the overlaps.
  381. //FIXME This does not likely merge surfaces, which are supported by a material with different colors, but same properties.
  382. this->process_external_surfaces();
  383. m_print->throw_if_canceled();
  384. // Add solid fills to ensure the shell vertical thickness.
  385. this->discover_vertical_shells();
  386. m_print->throw_if_canceled();
  387. // Debugging output.
  388. #ifdef SLIC3R_DEBUG_SLICE_PROCESSING
  389. for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) {
  390. for (const Layer *layer : m_layers) {
  391. LayerRegion *layerm = layer->m_regions[region_id];
  392. layerm->export_region_slices_to_svg_debug("6_discover_vertical_shells-final");
  393. layerm->export_region_fill_surfaces_to_svg_debug("6_discover_vertical_shells-final");
  394. } // for each layer
  395. } // for each region
  396. #endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
  397. // Detect, which fill surfaces are near external layers.
  398. // They will be split in internal and internal-solid surfaces.
  399. // The purpose is to add a configurable number of solid layers to support the TOP surfaces
  400. // and to add a configurable number of solid layers above the BOTTOM / BOTTOMBRIDGE surfaces
  401. // to close these surfaces reliably.
  402. //FIXME Vojtech: Is this a good place to add supporting infills below sloping perimeters?
  403. this->discover_horizontal_shells();
  404. m_print->throw_if_canceled();
  405. #ifdef SLIC3R_DEBUG_SLICE_PROCESSING
  406. for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) {
  407. for (const Layer *layer : m_layers) {
  408. LayerRegion *layerm = layer->m_regions[region_id];
  409. layerm->export_region_slices_to_svg_debug("7_discover_horizontal_shells-final");
  410. layerm->export_region_fill_surfaces_to_svg_debug("7_discover_horizontal_shells-final");
  411. } // for each layer
  412. } // for each region
  413. #endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
  414. // Only active if config->infill_only_where_needed. This step trims the sparse infill,
  415. // so it acts as an internal support. It maintains all other infill types intact.
  416. // Here the internal surfaces and perimeters have to be supported by the sparse infill.
  417. //FIXME The surfaces are supported by a sparse infill, but the sparse infill is only as large as the area to support.
  418. // Likely the sparse infill will not be anchored correctly, so it will not work as intended.
  419. // Also one wishes the perimeters to be supported by a full infill.
  420. this->clip_fill_surfaces();
  421. m_print->throw_if_canceled();
  422. #ifdef SLIC3R_DEBUG_SLICE_PROCESSING
  423. for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) {
  424. for (const Layer *layer : m_layers) {
  425. LayerRegion *layerm = layer->m_regions[region_id];
  426. layerm->export_region_slices_to_svg_debug("8_clip_surfaces-final");
  427. layerm->export_region_fill_surfaces_to_svg_debug("8_clip_surfaces-final");
  428. } // for each layer
  429. } // for each region
  430. #endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
  431. // the following step needs to be done before combination because it may need
  432. // to remove only half of the combined infill
  433. this->bridge_over_infill();
  434. m_print->throw_if_canceled();
  435. this->replaceSurfaceType(stPosInternal | stDensSolid,
  436. stPosInternal | stDensSolid | stModOverBridge,
  437. stPosInternal | stDensSolid | stModBridge);
  438. m_print->throw_if_canceled();
  439. this->replaceSurfaceType(stPosTop | stDensSolid,
  440. stPosTop | stDensSolid | stModOverBridge,
  441. stPosInternal | stDensSolid | stModBridge);
  442. m_print->throw_if_canceled();
  443. this->replaceSurfaceType(stPosInternal | stDensSolid,
  444. stPosInternal | stDensSolid | stModOverBridge,
  445. stPosBottom | stDensSolid | stModBridge);
  446. m_print->throw_if_canceled();
  447. this->replaceSurfaceType(stPosTop | stDensSolid,
  448. stPosTop | stDensSolid | stModOverBridge,
  449. stPosBottom | stDensSolid | stModBridge);
  450. m_print->throw_if_canceled();
  451. // combine fill surfaces to honor the "infill every N layers" option
  452. this->combine_infill();
  453. m_print->throw_if_canceled();
  454. // count the distance from the nearest top surface, to allow to use denser infill
  455. // if needed and if infill_dense_layers is positive.
  456. this->tag_under_bridge();
  457. m_print->throw_if_canceled();
  458. #ifdef SLIC3R_DEBUG_SLICE_PROCESSING
  459. for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) {
  460. for (const Layer *layer : m_layers) {
  461. LayerRegion *layerm = layer->m_regions[region_id];
  462. layerm->export_region_slices_to_svg_debug("9_prepare_infill-final");
  463. layerm->export_region_fill_surfaces_to_svg_debug("9_prepare_infill-final");
  464. } // for each layer
  465. } // for each region
  466. for (const Layer *layer : m_layers) {
  467. layer->export_region_slices_to_svg_debug("9_prepare_infill-final");
  468. layer->export_region_fill_surfaces_to_svg_debug("9_prepare_infill-final");
  469. } // for each layer
  470. #endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
  471. this->set_done(posPrepareInfill);
  472. }
  473. void PrintObject::infill()
  474. {
  475. // prerequisites
  476. this->prepare_infill();
  477. if (this->set_started(posInfill)) {
  478. BOOST_LOG_TRIVIAL(debug) << "Filling layers in parallel - start";
  479. tbb::parallel_for(
  480. tbb::blocked_range<size_t>(0, m_layers.size()),
  481. [this](const tbb::blocked_range<size_t>& range) {
  482. for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx) {
  483. m_print->throw_if_canceled();
  484. m_layers[layer_idx]->make_fills();
  485. }
  486. }
  487. );
  488. //for (size_t layer_idx = 0; layer_idx < m_layers.size(); ++ layer_idx) {
  489. // m_print->throw_if_canceled();
  490. // m_layers[layer_idx]->make_fills();
  491. //}
  492. m_print->throw_if_canceled();
  493. BOOST_LOG_TRIVIAL(debug) << "Filling layers in parallel - end";
  494. /* we could free memory now, but this would make this step not idempotent
  495. ### $_->fill_surfaces->clear for map @{$_->regions}, @{$object->layers};
  496. */
  497. this->set_done(posInfill);
  498. }
  499. }
  500. void PrintObject::generate_support_material()
  501. {
  502. if (this->set_started(posSupportMaterial)) {
  503. this->clear_support_layers();
  504. if ((m_config.support_material || m_config.raft_layers > 0) && m_layers.size() > 1) {
  505. m_print->set_status(85, L("Generating support material"));
  506. this->_generate_support_material();
  507. m_print->throw_if_canceled();
  508. } else {
  509. #if 0
  510. // Printing without supports. Empty layer means some objects or object parts are levitating,
  511. // therefore they cannot be printed without supports.
  512. for (const Layer *layer : m_layers)
  513. if (layer->empty())
  514. throw std::runtime_error("Levitating objects cannot be printed without supports.");
  515. #endif
  516. }
  517. this->set_done(posSupportMaterial);
  518. }
  519. }
  520. void PrintObject::clear_layers()
  521. {
  522. for (Layer *l : m_layers)
  523. delete l;
  524. m_layers.clear();
  525. }
  526. Layer* PrintObject::add_layer(int id, coordf_t height, coordf_t print_z, coordf_t slice_z)
  527. {
  528. m_layers.emplace_back(new Layer(id, this, height, print_z, slice_z));
  529. return m_layers.back();
  530. }
  531. void PrintObject::clear_support_layers()
  532. {
  533. for (Layer *l : m_support_layers)
  534. delete l;
  535. m_support_layers.clear();
  536. }
  537. SupportLayer* PrintObject::add_support_layer(int id, coordf_t height, coordf_t print_z)
  538. {
  539. m_support_layers.emplace_back(new SupportLayer(id, this, height, print_z, -1));
  540. return m_support_layers.back();
  541. }
  542. SupportLayerPtrs::const_iterator PrintObject::insert_support_layer(SupportLayerPtrs::const_iterator pos, size_t id, coordf_t height, coordf_t print_z, coordf_t slice_z)
  543. {
  544. return m_support_layers.insert(pos, new SupportLayer(id, this, height, print_z, slice_z));
  545. }
  546. // Called by Print::apply().
  547. // This method only accepts PrintObjectConfig and PrintRegionConfig option keys.
  548. bool PrintObject::invalidate_state_by_config_options(const std::vector<t_config_option_key> &opt_keys)
  549. {
  550. if (opt_keys.empty())
  551. return false;
  552. std::vector<PrintObjectStep> steps;
  553. bool invalidated = false;
  554. for (const t_config_option_key &opt_key : opt_keys) {
  555. if ( opt_key == "perimeters"
  556. || opt_key == "extra_perimeters"
  557. || opt_key == "extra_perimeters_odd_layers"
  558. || opt_key == "gap_fill"
  559. || opt_key == "gap_fill_speed"
  560. || opt_key == "overhangs"
  561. || opt_key == "overhangs_width"
  562. || opt_key == "overhangs_reverse"
  563. || opt_key == "overhangs_reverse_threshold"
  564. || opt_key == "first_layer_extrusion_width"
  565. || opt_key == "perimeter_extrusion_width"
  566. || opt_key == "infill_overlap"
  567. || opt_key == "thin_perimeters"
  568. || opt_key == "thin_walls"
  569. || opt_key == "thin_walls_min_width"
  570. || opt_key == "thin_walls_overlap"
  571. || opt_key == "external_perimeters_first"
  572. || opt_key == "external_perimeters_vase"
  573. || opt_key == "external_perimeters_nothole"
  574. || opt_key == "external_perimeters_hole"
  575. || opt_key == "perimeter_loop"
  576. || opt_key == "perimeter_loop_seam"
  577. || opt_key == "only_one_perimeter_top"
  578. || opt_key == "no_perimeter_unsupported_algo") {
  579. steps.emplace_back(posPerimeters);
  580. } else if (
  581. opt_key == "layer_height"
  582. || opt_key == "first_layer_height"
  583. || opt_key == "exact_last_layer_height"
  584. || opt_key == "raft_layers"
  585. || opt_key == "slice_closing_radius"
  586. || opt_key == "clip_multipart_objects"
  587. || opt_key == "first_layer_size_compensation"
  588. || opt_key == "elephant_foot_min_width"
  589. || opt_key == "support_material_contact_distance_type"
  590. || opt_key == "support_material_contact_distance_top"
  591. || opt_key == "support_material_contact_distance_bottom"
  592. || opt_key == "xy_size_compensation"
  593. || opt_key == "hole_size_compensation"
  594. || opt_key == "hole_to_polyhole"
  595. || opt_key == "z_step") {
  596. steps.emplace_back(posSlice);
  597. } else if (opt_key == "support_material") {
  598. steps.emplace_back(posSupportMaterial);
  599. if (m_config.support_material_contact_distance_top == 0. || m_config.support_material_contact_distance_bottom == 0.) {
  600. // Enabling / disabling supports while soluble support interface is enabled.
  601. // This changes the bridging logic (bridging enabled without supports, disabled with supports).
  602. // Reset everything.
  603. // See GH #1482 for details.
  604. steps.emplace_back(posSlice);
  605. }
  606. } else if (
  607. opt_key == "support_material_auto"
  608. || opt_key == "support_material_angle"
  609. || opt_key == "support_material_buildplate_only"
  610. || opt_key == "support_material_enforce_layers"
  611. || opt_key == "support_material_extruder"
  612. || opt_key == "support_material_extrusion_width"
  613. || opt_key == "support_material_interface_layers"
  614. || opt_key == "support_material_interface_contact_loops"
  615. || opt_key == "support_material_interface_extruder"
  616. || opt_key == "support_material_interface_spacing"
  617. || opt_key == "support_material_pattern"
  618. || opt_key == "support_material_interface_pattern"
  619. || opt_key == "support_material_xy_spacing"
  620. || opt_key == "support_material_spacing"
  621. || opt_key == "support_material_synchronize_layers"
  622. || opt_key == "support_material_threshold"
  623. || opt_key == "support_material_with_sheath"
  624. || opt_key == "dont_support_bridges"
  625. || opt_key == "first_layer_extrusion_width"
  626. || opt_key == "support_material_solid_first_layer") {
  627. steps.emplace_back(posSupportMaterial);
  628. } else if (
  629. opt_key == "interface_shells"
  630. || opt_key == "infill_only_where_needed"
  631. || opt_key == "infill_every_layers"
  632. || opt_key == "solid_infill_every_layers"
  633. || opt_key == "infill_dense"
  634. || opt_key == "infill_not_connected"
  635. || opt_key == "infill_dense_algo"
  636. || opt_key == "bottom_solid_layers"
  637. || opt_key == "bottom_solid_min_thickness"
  638. || opt_key == "top_solid_layers"
  639. || opt_key == "top_solid_min_thickness"
  640. || opt_key == "solid_infill_below_area"
  641. || opt_key == "infill_extruder"
  642. || opt_key == "solid_infill_extruder"
  643. || opt_key == "infill_extrusion_width"
  644. || opt_key == "ensure_vertical_shell_thickness"
  645. || opt_key == "bridged_infill_margin"
  646. || opt_key == "bridge_angle") {
  647. steps.emplace_back(posPrepareInfill);
  648. } else if (
  649. opt_key == "top_fill_pattern"
  650. || opt_key == "bottom_fill_pattern"
  651. || opt_key == "solid_fill_pattern"
  652. || opt_key == "enforce_full_fill_volume"
  653. || opt_key == "fill_angle"
  654. || opt_key == "fill_angle_increment"
  655. || opt_key == "fill_pattern"
  656. || opt_key == "fill_top_flow_ratio"
  657. || opt_key == "fill_smooth_width"
  658. || opt_key == "fill_smooth_distribution"
  659. || opt_key == "top_infill_extrusion_width"
  660. || opt_key == "first_layer_extrusion_width") {
  661. steps.emplace_back(posInfill);
  662. } else if (
  663. opt_key == "fill_density"
  664. || opt_key == "external_infill_margin"
  665. || opt_key == "solid_infill_extrusion_width") {
  666. steps.emplace_back(posPerimeters);
  667. steps.emplace_back(posPrepareInfill);
  668. } else if (
  669. opt_key == "external_perimeter_extrusion_width"
  670. || opt_key == "perimeter_extruder") {
  671. steps.emplace_back(posPerimeters);
  672. steps.emplace_back(posSupportMaterial);
  673. } else if (opt_key == "bridge_flow_ratio") {
  674. //if (m_config.support_material_contact_distance > 0.) {
  675. // Only invalidate due to bridging if bridging is enabled.
  676. // If later "support_material_contact_distance" is modified, the complete PrintObject is invalidated anyway.
  677. steps.emplace_back(posPerimeters);
  678. steps.emplace_back(posInfill);
  679. steps.emplace_back(posSupportMaterial);
  680. //}
  681. } else if (
  682. opt_key == "seam_position"
  683. || opt_key == "seam_travel"
  684. || opt_key == "seam_preferred_direction"
  685. || opt_key == "seam_preferred_direction_jitter"
  686. || opt_key == "support_material_speed"
  687. || opt_key == "support_material_interface_speed"
  688. || opt_key == "bridge_speed"
  689. || opt_key == "external_perimeter_speed"
  690. || opt_key == "external_perimeters_vase"
  691. || opt_key == "infill_speed"
  692. || opt_key == "perimeter_speed"
  693. || opt_key == "small_perimeter_speed"
  694. || opt_key == "solid_infill_speed"
  695. || opt_key == "top_solid_infill_speed") {
  696. invalidated |= m_print->invalidate_step(psGCodeExport);
  697. } else if (
  698. opt_key == "wipe_into_infill"
  699. || opt_key == "wipe_into_objects") {
  700. invalidated |= m_print->invalidate_step(psWipeTower);
  701. invalidated |= m_print->invalidate_step(psGCodeExport);
  702. } else if (
  703. opt_key == "brim_inside_holes"
  704. || opt_key == "brim_width"
  705. || opt_key == "brim_width_interior"
  706. || opt_key == "brim_offset"
  707. || opt_key == "brim_ears"
  708. || opt_key == "brim_ears_max_angle"
  709. || opt_key == "brim_ears_pattern") {
  710. invalidated |= m_print->invalidate_step(psBrim);
  711. } else {
  712. // for legacy, if we can't handle this option let's invalidate all steps
  713. this->invalidate_all_steps();
  714. invalidated = true;
  715. }
  716. }
  717. sort_remove_duplicates(steps);
  718. for (PrintObjectStep step : steps)
  719. invalidated |= this->invalidate_step(step);
  720. return invalidated;
  721. }
  722. bool PrintObject::invalidate_step(PrintObjectStep step)
  723. {
  724. bool invalidated = Inherited::invalidate_step(step);
  725. // propagate to dependent steps
  726. if (step == posPerimeters) {
  727. invalidated |= this->invalidate_steps({ posPrepareInfill, posInfill });
  728. invalidated |= m_print->invalidate_steps({ psSkirt, psBrim });
  729. } else if (step == posPrepareInfill) {
  730. invalidated |= this->invalidate_step(posInfill);
  731. } else if (step == posInfill) {
  732. invalidated |= m_print->invalidate_steps({ psSkirt, psBrim });
  733. } else if (step == posSlice) {
  734. invalidated |= this->invalidate_steps({ posPerimeters, posPrepareInfill, posInfill, posSupportMaterial });
  735. invalidated |= m_print->invalidate_steps({ psSkirt, psBrim });
  736. this->m_slicing_params.valid = false;
  737. } else if (step == posSupportMaterial) {
  738. invalidated |= m_print->invalidate_steps({ psSkirt, psBrim });
  739. this->m_slicing_params.valid = false;
  740. }
  741. // Wipe tower depends on the ordering of extruders, which in turn depends on everything.
  742. // It also decides about what the wipe_into_infill / wipe_into_object features will do,
  743. // and that too depends on many of the settings.
  744. invalidated |= m_print->invalidate_step(psWipeTower);
  745. // Invalidate G-code export in any case.
  746. invalidated |= m_print->invalidate_step(psGCodeExport);
  747. return invalidated;
  748. }
  749. bool PrintObject::invalidate_all_steps()
  750. {
  751. // First call the "invalidate" functions, which may cancel background processing.
  752. bool result = Inherited::invalidate_all_steps() | m_print->invalidate_all_steps();
  753. // Then reset some of the depending values.
  754. this->m_slicing_params.valid = false;
  755. this->region_volumes.clear();
  756. return result;
  757. }
  758. bool PrintObject::has_support_material() const
  759. {
  760. return m_config.support_material
  761. || m_config.raft_layers > 0
  762. || m_config.support_material_enforce_layers > 0;
  763. }
  764. static const PrintRegion* first_printing_region(const PrintObject &print_object)
  765. {
  766. for (size_t idx_region = 0; idx_region < print_object.region_volumes.size(); ++ idx_region)
  767. if (!print_object.region_volumes.empty())
  768. return print_object.print()->regions()[idx_region];
  769. return nullptr;
  770. }
  771. // Function used by fit_to_size.
  772. // It check if polygon_to_check can be decimated, using only point into allowedPoints and also cover polygon_to_cover
  773. ExPolygon try_fit_to_size(ExPolygon polygon_to_cover, ExPolygon polygon_to_check, const ExPolygons &allowedPoints) {
  774. ExPolygon polygon_reduced = polygon_to_check;
  775. size_t pos_check = 0;
  776. bool has_del = false;
  777. while ( (polygon_reduced.contour.points.begin() + pos_check) != polygon_reduced.contour.points.end()) {
  778. bool ok = false;
  779. for (ExPolygon poly : allowedPoints) {
  780. if (poly.contains_b(*(polygon_reduced.contour.points.begin() + pos_check))) {
  781. ok = true;
  782. has_del = true;
  783. break;
  784. }
  785. }
  786. if (ok) ++pos_check;
  787. else polygon_reduced.contour.points.erase(polygon_reduced.contour.points.begin() + pos_check);
  788. }
  789. if (has_del) polygon_reduced.holes.clear();
  790. return polygon_reduced;
  791. }
  792. // find one of the smallest polygon, growing polygon_to_check, only using point into allowedPoints and covering polygon_to_cover.
  793. ExPolygons fit_to_size(ExPolygon polygon_to_cover, ExPolygon polygon_to_check, const ExPolygons &allowedPoints,
  794. const ExPolygon &growing_area, const coord_t offset, float coverage) {
  795. //grow the polygon_to_check enough to cover polygon_to_cover
  796. float current_coverage = coverage;
  797. coord_t previous_offset = 0;
  798. coord_t current_offset = offset;
  799. ExPolygon polygon_reduced = try_fit_to_size(polygon_to_cover, polygon_to_check, allowedPoints);
  800. while (!diff_ex(polygon_to_cover, polygon_reduced).empty()){
  801. //not enough, use a bigger offset
  802. float percent_coverage = (float)(polygon_reduced.area() / growing_area.area());
  803. float next_coverage = percent_coverage + (percent_coverage - current_coverage) * 4;
  804. previous_offset = current_offset;
  805. current_offset *= 2;
  806. if (next_coverage < 0.1) current_offset *= 2;
  807. //create the bigger polygon and test it
  808. ExPolygons bigger_polygon = offset_ex(polygon_to_check, double(current_offset));
  809. if (bigger_polygon.size() != 1) {
  810. // Error, growing a single polygon result in many/no other => fallback to full coverage
  811. return ExPolygons({ growing_area });
  812. }
  813. bigger_polygon = intersection_ex(bigger_polygon[0], growing_area);
  814. if (bigger_polygon.size() != 1 || bigger_polygon[0].area() > growing_area.area()) {
  815. // Growing too much => we can as well use the full coverage, in this case
  816. return ExPolygons() = { growing_area };
  817. }
  818. polygon_reduced = try_fit_to_size(polygon_to_cover, bigger_polygon[0], allowedPoints);
  819. }
  820. //ok, we have a good one, now try to optimise (unless there are almost no growth)
  821. if (current_offset > offset * 3){
  822. //try to shrink
  823. uint32_t nb_opti_max = 6;
  824. for (uint32_t i = 0; i < nb_opti_max; ++i){
  825. coord_t new_offset = (previous_offset + current_offset) / 2;
  826. ExPolygons bigger_polygon = offset_ex(polygon_to_check, double(new_offset));
  827. if (bigger_polygon.size() != 1) {
  828. //Warn, growing a single polygon result in many/no other, use previous good result
  829. break;
  830. }
  831. bigger_polygon = intersection_ex(bigger_polygon[0], growing_area);
  832. if (bigger_polygon.size() != 1 || bigger_polygon[0].area() > growing_area.area()) {
  833. //growing too much, use previous good result (imo, should not be possible to enter this branch)
  834. break;
  835. }
  836. ExPolygon polygon_test = try_fit_to_size(polygon_to_cover, bigger_polygon[0], allowedPoints);
  837. if (!diff_ex(polygon_to_cover, polygon_test).empty()){
  838. //bad, not enough, use a bigger offset
  839. previous_offset = new_offset;
  840. }
  841. else {
  842. //good, we may now try a smaller offset
  843. current_offset = new_offset;
  844. polygon_reduced = polygon_test;
  845. }
  846. }
  847. }
  848. //return the area which cover the growing_area. Intersect it to retreive the holes.
  849. return intersection_ex(polygon_reduced, growing_area);
  850. }
  851. void PrintObject::tag_under_bridge() {
  852. const float COEFF_SPLIT = 1.5;
  853. for (const PrintRegion *region : this->m_print->regions()) {
  854. LayerRegion *previousOne = NULL;
  855. //count how many surface there are on each one
  856. if (region->config().infill_dense.getBool() && region->config().fill_density < 40) {
  857. for (size_t idx_layer = this->layers().size() - 1; idx_layer < this->layers().size(); --idx_layer) {
  858. LayerRegion *layerm = NULL;
  859. for (LayerRegion * lregion : this->layers()[idx_layer]->regions()) {
  860. if (lregion->region() == region) {
  861. layerm = lregion;
  862. break;
  863. }
  864. }
  865. if (layerm == NULL){
  866. previousOne = NULL;
  867. continue;
  868. }
  869. if (previousOne == NULL) {
  870. previousOne = layerm;
  871. continue;
  872. }
  873. Surfaces surf_to_add;
  874. for (Surface &surf : layerm->fill_surfaces.surfaces) {
  875. surf.maxNbSolidLayersOnTop = -1;
  876. if (!surf.has_fill_solid()){
  877. ExPolygons dense_polys;
  878. ExPolygons sparse_polys = { surf.expolygon };
  879. //find the surface which intersect with the smallest maxNb possible
  880. for (Surface &upp : previousOne->fill_surfaces.surfaces) {
  881. if (upp.has_fill_solid()){
  882. // i'm using intersection_ex because the result different than
  883. // upp.expolygon.overlaps(surf.expolygon) or surf.expolygon.overlaps(upp.expolygon)
  884. //and a little offset2 to remove the almost supported area
  885. ExPolygons intersect =
  886. offset2_ex(
  887. intersection_ex(sparse_polys, { upp.expolygon }, true)
  888. , (float)-layerm->flow(frInfill).scaled_width(), (float)layerm->flow(frInfill).scaled_width());
  889. if (!intersect.empty()) {
  890. if (layerm->region()->config().infill_dense_algo == dfaEnlarged) {
  891. //expand the area a bit
  892. intersect = offset_ex(intersect, double(scale_(layerm->region()->config().external_infill_margin.get_abs_value(
  893. region->config().perimeters == 0 ? 0 : (layerm->flow(frExternalPerimeter).width + layerm->flow(frPerimeter).spacing() * (region->config().perimeters - 1))))));
  894. } else if (layerm->region()->config().infill_dense_algo == dfaAutoNotFull
  895. || layerm->region()->config().infill_dense_algo == dfaAutomatic){
  896. //check if area isn't too big for autonotfull
  897. double area_intersect = 0;
  898. if (layerm->region()->config().infill_dense_algo == dfaAutoNotFull)
  899. for (ExPolygon poly_inter : intersect)
  900. area_intersect += poly_inter.area();
  901. //like intersect.empty() but more resilient
  902. if (layerm->region()->config().infill_dense_algo == dfaAutomatic
  903. || surf.area() > area_intersect * COEFF_SPLIT) {
  904. // it will be a dense infill, split the surface if needed
  905. ExPolygons cover_intersect;
  906. for (ExPolygon &expoly_tocover : intersect) {
  907. ExPolygons temp = (fit_to_size(expoly_tocover, expoly_tocover,
  908. diff_ex(offset_ex(layerm->fill_no_overlap_expolygons, double(layerm->flow(frInfill).scaled_width())),
  909. offset_ex(layerm->fill_no_overlap_expolygons, double(-layerm->flow(frInfill).scaled_width()))),
  910. surf.expolygon,
  911. 4 * layerm->flow(frInfill).scaled_width(), 0.01f));
  912. cover_intersect.insert(cover_intersect.end(), temp.begin(), temp.end());
  913. }
  914. intersect = offset2_ex(cover_intersect,
  915. double(-layerm->flow(frInfill).scaled_width()),
  916. double(layerm->flow(frInfill).scaled_width() * 2));
  917. } else {
  918. intersect.clear();
  919. }
  920. }
  921. if (!intersect.empty()) {
  922. ExPolygons sparse_surfaces = offset2_ex(
  923. diff_ex(sparse_polys, intersect, true),
  924. double(-layerm->flow(frInfill).scaled_width()),
  925. double(layerm->flow(frInfill).scaled_width()));
  926. ExPolygons dense_surfaces = diff_ex(sparse_polys, sparse_surfaces, true);
  927. //assign (copy)
  928. sparse_polys = std::move(sparse_surfaces);
  929. dense_polys.insert(dense_polys.end(), dense_surfaces.begin(), dense_surfaces.end());
  930. }
  931. }
  932. }
  933. //check if we are full-dense
  934. if (sparse_polys.empty()) break;
  935. }
  936. //check if we need to split the surface
  937. if (!dense_polys.empty()) {
  938. double area_dense = 0;
  939. for (ExPolygon poly_inter : dense_polys) area_dense += poly_inter.area();
  940. double area_sparse = 0;
  941. for (ExPolygon poly_inter : sparse_polys) area_sparse += poly_inter.area();
  942. if (area_sparse > area_dense * COEFF_SPLIT) {
  943. //split
  944. dense_polys = union_ex(dense_polys);
  945. for (ExPolygon dense_poly : dense_polys) {
  946. Surface dense_surf(surf, dense_poly);
  947. dense_surf.maxNbSolidLayersOnTop = 1;
  948. surf_to_add.push_back(dense_surf);
  949. }
  950. sparse_polys = union_ex(sparse_polys);
  951. for (ExPolygon sparse_poly : sparse_polys) {
  952. Surface sparse_surf(surf, sparse_poly);
  953. surf_to_add.push_back(sparse_surf);
  954. }
  955. //layerm->fill_surfaces.surfaces.erase(it_surf);
  956. } else {
  957. surf.maxNbSolidLayersOnTop = 1;
  958. surf_to_add.push_back(surf);
  959. }
  960. } else surf_to_add.emplace_back(std::move(surf));
  961. } else surf_to_add.emplace_back(std::move(surf));
  962. }
  963. layerm->fill_surfaces.surfaces = std::move(surf_to_add);
  964. previousOne = layerm;
  965. }
  966. }
  967. }
  968. }
  969. // This function analyzes slices of a region (SurfaceCollection slices).
  970. // Each region slice (instance of Surface) is analyzed, whether it is supported or whether it is the top surface.
  971. // Initially all slices are of type stInternal.
  972. // Slices are compared against the top / bottom slices and regions and classified to the following groups:
  973. // stTop - Part of a region, which is not covered by any upper layer. This surface will be filled with a top solid infill.
  974. // stBottomBridge - Part of a region, which is not fully supported, but it hangs in the air, or it hangs losely on a support or a raft.
  975. // stBottom - Part of a region, which is not supported by the same region, but it is supported either by another region, or by a soluble interface layer.
  976. // stInternal - Part of a region, which is supported by the same region type.
  977. // If a part of a region is of stBottom and stTop, the stBottom wins.
  978. void PrintObject::detect_surfaces_type()
  979. {
  980. BOOST_LOG_TRIVIAL(info) << "Detecting solid surfaces..." << log_memory_info();
  981. // Interface shells: the intersecting parts are treated as self standing objects supporting each other.
  982. // Each of the objects will have a full number of top / bottom layers, even if these top / bottom layers
  983. // are completely hidden inside a collective body of intersecting parts.
  984. // This is useful if one of the parts is to be dissolved, or if it is transparent and the internal shells
  985. // should be visible.
  986. bool spiral_vase = this->print()->config().spiral_vase.value;
  987. bool interface_shells = ! spiral_vase && m_config.interface_shells.value;
  988. size_t num_layers = spiral_vase ? first_printing_region(*this)->config().bottom_solid_layers : m_layers.size();
  989. for (size_t idx_region = 0; idx_region < this->region_volumes.size(); ++ idx_region) {
  990. BOOST_LOG_TRIVIAL(debug) << "Detecting solid surfaces for region " << idx_region << " in parallel - start";
  991. #ifdef SLIC3R_DEBUG_SLICE_PROCESSING
  992. for (Layer *layer : m_layers)
  993. layer->m_regions[idx_region]->export_region_fill_surfaces_to_svg_debug("1_detect_surfaces_type-initial");
  994. #endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
  995. // If interface shells are allowed, the region->surfaces cannot be overwritten as they may be used by other threads.
  996. // Cache the result of the following parallel_loop.
  997. std::vector<Surfaces> surfaces_new;
  998. if (interface_shells)
  999. surfaces_new.assign(num_layers, Surfaces());
  1000. tbb::parallel_for(
  1001. tbb::blocked_range<size_t>(0,
  1002. spiral_vase ?
  1003. // In spiral vase mode, reserve the last layer for the top surface if more than 1 layer is planned for the vase bottom.
  1004. ((num_layers > 1) ? num_layers - 1 : num_layers) :
  1005. // In non-spiral vase mode, go over all layers.
  1006. m_layers.size()),
  1007. [this, idx_region, interface_shells, &surfaces_new](const tbb::blocked_range<size_t>& range) {
  1008. // If we have raft layers, consider bottom layer as a bridge just like any other bottom surface lying on the void.
  1009. SurfaceType surface_type_bottom_1st =
  1010. (m_config.raft_layers.value > 0 && m_config.support_material_contact_distance_type.value != zdNone) ?
  1011. stPosBottom | stDensSolid | stModBridge : stPosBottom | stDensSolid;
  1012. // If we have soluble support material, don't bridge. The overhang will be squished against a soluble layer separating
  1013. // the support from the print.
  1014. SurfaceType surface_type_bottom_other =
  1015. (m_config.support_material.value && m_config.support_material_contact_distance_type.value == zdNone) ?
  1016. stPosBottom | stDensSolid : stPosBottom | stDensSolid | stModBridge;
  1017. for (size_t idx_layer = range.begin(); idx_layer < range.end(); ++ idx_layer) {
  1018. m_print->throw_if_canceled();
  1019. // BOOST_LOG_TRIVIAL(trace) << "Detecting solid surfaces for region " << idx_region << " and layer " << layer->print_z;
  1020. Layer *layer = m_layers[idx_layer];
  1021. LayerRegion *layerm = layer->m_regions[idx_region];
  1022. // comparison happens against the *full* slices (considering all regions)
  1023. // unless internal shells are requested
  1024. Layer *upper_layer = (idx_layer + 1 < this->layer_count()) ? m_layers[idx_layer + 1] : nullptr;
  1025. Layer *lower_layer = (idx_layer > 0) ? m_layers[idx_layer - 1] : nullptr;
  1026. // collapse very narrow parts (using the safety offset in the diff is not enough)
  1027. float offset = layerm->flow(frExternalPerimeter).scaled_width() / 10.f;
  1028. Polygons layerm_slices_surfaces = to_polygons(layerm->slices().surfaces);
  1029. // no_perimeter_full_bridge allow to put bridges where there are nothing, hence adding area to slice, that's why we need to start from the result of PerimeterGenerator.
  1030. if (layerm->region()->config().no_perimeter_unsupported_algo == npuaFilled) {
  1031. layerm_slices_surfaces = union_(layerm_slices_surfaces, to_polygons(layerm->fill_surfaces));
  1032. }
  1033. // find top surfaces (difference between current surfaces
  1034. // of current layer and upper one)
  1035. Surfaces top;
  1036. if (upper_layer) {
  1037. Polygons upper_slices = interface_shells ?
  1038. to_polygons(upper_layer->get_region(idx_region)->slices().surfaces) :
  1039. to_polygons(upper_layer->lslices);
  1040. surfaces_append(top,
  1041. //FIXME implement offset2_ex working over ExPolygons, that should be a bit more efficient than calling offset_ex twice.
  1042. offset_ex(offset_ex(diff_ex(layerm_slices_surfaces, upper_slices, true), -offset), offset),
  1043. stPosTop | stDensSolid);
  1044. } else {
  1045. // if no upper layer, all surfaces of this one are solid
  1046. // we clone surfaces because we're going to clear the slices collection
  1047. top = layerm->m_slices.surfaces;
  1048. for (Surface &surface : top)
  1049. surface.surface_type = stPosTop | stDensSolid;
  1050. }
  1051. // Find bottom surfaces (difference between current surfaces of current layer and lower one).
  1052. Surfaces bottom;
  1053. if (lower_layer) {
  1054. #if 0
  1055. //FIXME Why is this branch failing t\multi.t ?
  1056. Polygons lower_slices = interface_shells ?
  1057. to_polygons(lower_layer->get_region(idx_region)->slices.surfaces) :
  1058. to_polygons(lower_layer->slices);
  1059. surfaces_append(bottom,
  1060. offset2_ex(diff(layerm_slices_surfaces, lower_slices, true), -offset, offset),
  1061. surface_type_bottom_other);
  1062. #else
  1063. ExPolygons lower_slices = lower_layer->lslices;
  1064. //if we added new surfaces, we can use them as support
  1065. /*if (layerm->region()->config().no_perimeter_full_bridge) {
  1066. lower_slices = union_ex(lower_slices, lower_layer->get_region(idx_region)->fill_surfaces);
  1067. }*/
  1068. // Any surface lying on the void is a true bottom bridge (an overhang)
  1069. surfaces_append(
  1070. bottom,
  1071. offset2_ex(
  1072. diff(layerm_slices_surfaces, to_polygons(lower_slices), true),
  1073. -offset, offset),
  1074. surface_type_bottom_other);
  1075. // if user requested internal shells, we need to identify surfaces
  1076. // lying on other slices not belonging to this region
  1077. if (interface_shells) {
  1078. // non-bridging bottom surfaces: any part of this layer lying
  1079. // on something else, excluding those lying on our own region
  1080. surfaces_append(
  1081. bottom,
  1082. offset2_ex(
  1083. diff(
  1084. intersection(layerm_slices_surfaces, to_polygons(lower_slices)), // supported
  1085. to_polygons(lower_layer->get_region(idx_region)->slices().surfaces),
  1086. true),
  1087. -offset, offset),
  1088. stPosBottom | stDensSolid);
  1089. }
  1090. #endif
  1091. } else {
  1092. // if no lower layer, all surfaces of this one are solid
  1093. // we clone surfaces because we're going to clear the slices collection
  1094. bottom = layerm->slices().surfaces;
  1095. for (Surface &surface : bottom)
  1096. surface.surface_type = surface_type_bottom_1st;
  1097. }
  1098. // now, if the object contained a thin membrane, we could have overlapping bottom
  1099. // and top surfaces; let's do an intersection to discover them and consider them
  1100. // as bottom surfaces (to allow for bridge detection)
  1101. if (! top.empty() && ! bottom.empty()) {
  1102. // Polygons overlapping = intersection(to_polygons(top), to_polygons(bottom));
  1103. // Slic3r::debugf " layer %d contains %d membrane(s)\n", $layerm->layer->id, scalar(@$overlapping)
  1104. // if $Slic3r::debug;
  1105. Polygons top_polygons = to_polygons(std::move(top));
  1106. top.clear();
  1107. surfaces_append(top,
  1108. diff_ex(top_polygons, to_polygons(bottom), false),
  1109. stPosTop | stDensSolid);
  1110. }
  1111. #ifdef SLIC3R_DEBUG_SLICE_PROCESSING
  1112. {
  1113. static int iRun = 0;
  1114. std::vector<std::pair<Slic3r::ExPolygons, SVG::ExPolygonAttributes>> expolygons_with_attributes;
  1115. expolygons_with_attributes.emplace_back(std::make_pair(union_ex(top), SVG::ExPolygonAttributes("green")));
  1116. expolygons_with_attributes.emplace_back(std::make_pair(union_ex(bottom), SVG::ExPolygonAttributes("brown")));
  1117. expolygons_with_attributes.emplace_back(std::make_pair(to_expolygons(layerm->slices().surfaces), SVG::ExPolygonAttributes("black")));
  1118. SVG::export_expolygons(debug_out_path("1_detect_surfaces_type_%d_region%d-layer_%f.svg", iRun ++, idx_region, layer->print_z).c_str(), expolygons_with_attributes);
  1119. }
  1120. #endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
  1121. // save surfaces to layer
  1122. Surfaces &surfaces_out = interface_shells ? surfaces_new[idx_layer] : layerm->m_slices.surfaces;
  1123. surfaces_out.clear();
  1124. // find internal surfaces (difference between top/bottom surfaces and others)
  1125. {
  1126. Polygons topbottom = to_polygons(top);
  1127. polygons_append(topbottom, to_polygons(bottom));
  1128. surfaces_append(surfaces_out,
  1129. diff_ex(layerm_slices_surfaces, topbottom, false),
  1130. stPosInternal | stDensSparse);
  1131. }
  1132. surfaces_append(surfaces_out, std::move(top));
  1133. surfaces_append(surfaces_out, std::move(bottom));
  1134. // Slic3r::debugf " layer %d has %d bottom, %d top and %d internal surfaces\n",
  1135. // $layerm->layer->id, scalar(@bottom), scalar(@top), scalar(@internal) if $Slic3r::debug;
  1136. #ifdef SLIC3R_DEBUG_SLICE_PROCESSING
  1137. layerm->export_region_slices_to_svg_debug("detect_surfaces_type-final");
  1138. #endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
  1139. }
  1140. }
  1141. ); // for each layer of a region
  1142. m_print->throw_if_canceled();
  1143. if (interface_shells) {
  1144. // Move surfaces_new to layerm->slices.surfaces
  1145. for (size_t idx_layer = 0; idx_layer < m_layers.size(); ++idx_layer)
  1146. m_layers[idx_layer]->get_region(idx_region)->m_slices.surfaces = std::move(surfaces_new[idx_layer]);
  1147. }
  1148. if (spiral_vase) {
  1149. if (num_layers > 1)
  1150. // Turn the last bottom layer infill to a top infill, so it will be extruded with a proper pattern.
  1151. m_layers[num_layers - 1]->m_regions[idx_region]->m_slices.set_type((stPosTop | stDensSolid));
  1152. for (size_t i = num_layers; i < m_layers.size(); ++ i)
  1153. m_layers[i]->m_regions[idx_region]->m_slices.set_type((stPosInternal | stDensSparse));
  1154. }
  1155. BOOST_LOG_TRIVIAL(debug) << "Detecting solid surfaces for region " << idx_region << " - clipping in parallel - start";
  1156. // Fill in layerm->fill_surfaces by trimming the layerm->slices by the cummulative layerm->fill_surfaces.
  1157. tbb::parallel_for(
  1158. tbb::blocked_range<size_t>(0, m_layers.size()),
  1159. [this, idx_region, interface_shells](const tbb::blocked_range<size_t>& range) {
  1160. for (size_t idx_layer = range.begin(); idx_layer < range.end(); ++ idx_layer) {
  1161. m_print->throw_if_canceled();
  1162. LayerRegion *layerm = m_layers[idx_layer]->get_region(idx_region);
  1163. layerm->slices_to_fill_surfaces_clipped();
  1164. #ifdef SLIC3R_DEBUG_SLICE_PROCESSING
  1165. layerm->export_region_fill_surfaces_to_svg_debug("1_detect_surfaces_type-final");
  1166. #endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
  1167. } // for each layer of a region
  1168. });
  1169. m_print->throw_if_canceled();
  1170. BOOST_LOG_TRIVIAL(debug) << "Detecting solid surfaces for region " << idx_region << " - clipping in parallel - end";
  1171. } // for each this->print->region_count
  1172. // 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.)
  1173. m_typed_slices = true;
  1174. }
  1175. void PrintObject::process_external_surfaces()
  1176. {
  1177. BOOST_LOG_TRIVIAL(info) << "Processing external surfaces..." << log_memory_info();
  1178. // Cached surfaces covered by some extrusion, defining regions, over which the from the surfaces one layer higher are allowed to expand.
  1179. std::vector<Polygons> surfaces_covered;
  1180. // Is there any printing region, that has zero infill? If so, then we don't want the expansion to be performed over the complete voids, but only
  1181. // over voids, which are supported by the layer below.
  1182. bool has_voids = false;
  1183. for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id)
  1184. if (! this->region_volumes.empty() && this->print()->regions()[region_id]->config().fill_density == 0) {
  1185. has_voids = true;
  1186. break;
  1187. }
  1188. if (has_voids && m_layers.size() > 1) {
  1189. // All but stInternal-sparse fill surfaces will get expanded and possibly trimmed.
  1190. std::vector<unsigned char> layer_expansions_and_voids(m_layers.size(), false);
  1191. for (size_t layer_idx = 0; layer_idx < m_layers.size(); ++ layer_idx) {
  1192. const Layer *layer = m_layers[layer_idx];
  1193. bool expansions = false;
  1194. bool voids = false;
  1195. for (const LayerRegion *layerm : layer->regions()) {
  1196. for (const Surface &surface : layerm->fill_surfaces.surfaces) {
  1197. if (surface.surface_type == (stPosInternal | stDensSparse))
  1198. voids = true;
  1199. else
  1200. expansions = true;
  1201. if (voids && expansions) {
  1202. layer_expansions_and_voids[layer_idx] = true;
  1203. goto end;
  1204. }
  1205. }
  1206. }
  1207. end:;
  1208. }
  1209. BOOST_LOG_TRIVIAL(debug) << "Collecting surfaces covered with extrusions in parallel - start";
  1210. surfaces_covered.resize(m_layers.size() - 1, Polygons());
  1211. tbb::parallel_for(
  1212. tbb::blocked_range<size_t>(0, m_layers.size() - 1),
  1213. [this, &surfaces_covered, &layer_expansions_and_voids](const tbb::blocked_range<size_t>& range) {
  1214. for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx)
  1215. if (layer_expansions_and_voids[layer_idx + 1]) {
  1216. m_print->throw_if_canceled();
  1217. Polygons voids;
  1218. for (const LayerRegion *layerm : m_layers[layer_idx]->regions()) {
  1219. /// supermerill: why *0.3 ???
  1220. float unsupported_width = -float(scale_(layerm->region()->config().external_infill_margin.get_abs_value(
  1221. layerm->region()->config().perimeters == 0 ? 0 : (layerm->flow(frExternalPerimeter).width + layerm->flow(frPerimeter).spacing() * (layerm->region()->config().perimeters - 1)))));
  1222. if (layerm->region()->config().fill_density.value == 0.)
  1223. for (const Surface &surface : layerm->fill_surfaces.surfaces)
  1224. // Shrink the holes, let the layer above expand slightly inside the unsupported areas.
  1225. polygons_append(voids, offset(surface.expolygon, unsupported_width));
  1226. }
  1227. surfaces_covered[layer_idx] = diff(to_polygons(this->m_layers[layer_idx]->lslices), voids);
  1228. }
  1229. }
  1230. );
  1231. m_print->throw_if_canceled();
  1232. BOOST_LOG_TRIVIAL(debug) << "Collecting surfaces covered with extrusions in parallel - end";
  1233. }
  1234. for (size_t region_id = 0; region_id < this->region_volumes.size(); ++region_id) {
  1235. BOOST_LOG_TRIVIAL(debug) << "Processing external surfaces for region " << region_id << " in parallel - start";
  1236. tbb::parallel_for(
  1237. tbb::blocked_range<size_t>(0, m_layers.size()),
  1238. [this, &surfaces_covered, region_id](const tbb::blocked_range<size_t>& range) {
  1239. for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx) {
  1240. m_print->throw_if_canceled();
  1241. // BOOST_LOG_TRIVIAL(trace) << "Processing external surface, layer" << m_layers[layer_idx]->print_z;
  1242. m_layers[layer_idx]->get_region((int)region_id)->process_external_surfaces(
  1243. (layer_idx == 0) ? nullptr : m_layers[layer_idx - 1],
  1244. (layer_idx == 0 || surfaces_covered.empty() || surfaces_covered[layer_idx - 1].empty()) ? nullptr : &surfaces_covered[layer_idx - 1]);
  1245. }
  1246. }
  1247. );
  1248. m_print->throw_if_canceled();
  1249. BOOST_LOG_TRIVIAL(debug) << "Processing external surfaces for region " << region_id << " in parallel - end";
  1250. }
  1251. }
  1252. void PrintObject::discover_vertical_shells()
  1253. {
  1254. PROFILE_FUNC();
  1255. BOOST_LOG_TRIVIAL(info) << "Discovering vertical shells..." << log_memory_info();
  1256. struct DiscoverVerticalShellsCacheEntry
  1257. {
  1258. // Collected polygons, offsetted
  1259. Polygons top_surfaces;
  1260. Polygons bottom_surfaces;
  1261. Polygons holes;
  1262. };
  1263. bool spiral_vase = this->print()->config().spiral_vase.value;
  1264. size_t num_layers = spiral_vase ? first_printing_region(*this)->config().bottom_solid_layers : m_layers.size();
  1265. coordf_t min_layer_height = this->slicing_parameters().min_layer_height;
  1266. // Does this region possibly produce more than 1 top or bottom layer?
  1267. auto has_extra_layers_fn = [min_layer_height](const PrintRegionConfig &config) {
  1268. auto num_extra_layers = [min_layer_height](int num_solid_layers, coordf_t min_shell_thickness) {
  1269. if (num_solid_layers == 0)
  1270. return 0;
  1271. int n = num_solid_layers - 1;
  1272. int n2 = int(ceil(min_shell_thickness / min_layer_height));
  1273. return std::max(n, n2 - 1);
  1274. };
  1275. return num_extra_layers(config.top_solid_layers, config.top_solid_min_thickness) +
  1276. num_extra_layers(config.bottom_solid_layers, config.bottom_solid_min_thickness) > 0;
  1277. };
  1278. std::vector<DiscoverVerticalShellsCacheEntry> cache_top_botom_regions(num_layers, DiscoverVerticalShellsCacheEntry());
  1279. bool top_bottom_surfaces_all_regions = this->region_volumes.size() > 1 && ! m_config.interface_shells.value;
  1280. if (top_bottom_surfaces_all_regions) {
  1281. // This is a multi-material print and interface_shells are disabled, meaning that the vertical shell thickness
  1282. // is calculated over all materials.
  1283. // Is the "ensure vertical wall thickness" applicable to any region?
  1284. bool has_extra_layers = false;
  1285. for (size_t idx_region = 0; idx_region < this->region_volumes.size(); ++idx_region) {
  1286. const PrintRegionConfig &config = m_print->get_region(idx_region)->config();
  1287. if (config.ensure_vertical_shell_thickness.value && has_extra_layers_fn(config)) {
  1288. has_extra_layers = true;
  1289. break;
  1290. }
  1291. }
  1292. if (! has_extra_layers)
  1293. // The "ensure vertical wall thickness" feature is not applicable to any of the regions. Quit.
  1294. return;
  1295. BOOST_LOG_TRIVIAL(debug) << "Discovering vertical shells in parallel - start : cache top / bottom";
  1296. //FIXME Improve the heuristics for a grain size.
  1297. size_t grain_size = std::max(num_layers / 16, size_t(1));
  1298. tbb::parallel_for(
  1299. tbb::blocked_range<size_t>(0, num_layers, grain_size),
  1300. [this, &cache_top_botom_regions](const tbb::blocked_range<size_t>& range) {
  1301. const size_t num_regions = this->region_volumes.size();
  1302. for (size_t idx_layer = range.begin(); idx_layer < range.end(); ++ idx_layer) {
  1303. m_print->throw_if_canceled();
  1304. const Layer &layer = *m_layers[idx_layer];
  1305. DiscoverVerticalShellsCacheEntry &cache = cache_top_botom_regions[idx_layer];
  1306. // Simulate single set of perimeters over all merged regions.
  1307. float perimeter_offset = 0.f;
  1308. float perimeter_min_spacing = FLT_MAX;
  1309. #ifdef SLIC3R_DEBUG_SLICE_PROCESSING
  1310. static size_t debug_idx = 0;
  1311. ++ debug_idx;
  1312. #endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
  1313. for (size_t idx_region = 0; idx_region < num_regions; ++ idx_region) {
  1314. LayerRegion &layerm = *layer.m_regions[idx_region];
  1315. float min_perimeter_infill_spacing = float(layerm.flow(frSolidInfill).scaled_spacing()) * 1.05f;
  1316. // Top surfaces.
  1317. append(cache.top_surfaces, offset(to_expolygons(layerm.slices().filter_by_type(stPosTop | stDensSolid)), min_perimeter_infill_spacing));
  1318. append(cache.top_surfaces, offset(to_expolygons(layerm.fill_surfaces.filter_by_type(stPosTop | stDensSolid)), min_perimeter_infill_spacing));
  1319. // Bottom surfaces.
  1320. const SurfaceType surfaces_bottom[2] = { stPosBottom | stDensSolid, stPosBottom | stDensSolid | stModBridge };
  1321. append(cache.bottom_surfaces, offset(to_expolygons(layerm.slices().filter_by_types(surfaces_bottom, 2)), min_perimeter_infill_spacing));
  1322. append(cache.bottom_surfaces, offset(to_expolygons(layerm.fill_surfaces.filter_by_types(surfaces_bottom, 2)), min_perimeter_infill_spacing));
  1323. // Calculate the maximum perimeter offset as if the slice was extruded with a single extruder only.
  1324. // First find the maxium number of perimeters per region slice.
  1325. unsigned int perimeters = 0;
  1326. for (const Surface &s : layerm.slices().surfaces)
  1327. perimeters = std::max<unsigned int>(perimeters, s.extra_perimeters);
  1328. perimeters += layerm.region()->config().perimeters.value;
  1329. // Then calculate the infill offset.
  1330. if (perimeters > 0) {
  1331. Flow extflow = layerm.flow(frExternalPerimeter);
  1332. Flow flow = layerm.flow(frPerimeter);
  1333. perimeter_offset = std::max(perimeter_offset,
  1334. 0.5f * float(extflow.scaled_width() + extflow.scaled_spacing()) + (float(perimeters) - 1.f) * flow.scaled_spacing());
  1335. perimeter_min_spacing = std::min(perimeter_min_spacing, float(std::min(extflow.scaled_spacing(), flow.scaled_spacing())));
  1336. }
  1337. polygons_append(cache.holes, to_polygons(layerm.fill_expolygons));
  1338. }
  1339. // Save some computing time by reducing the number of polygons.
  1340. cache.top_surfaces = union_(cache.top_surfaces, false);
  1341. cache.bottom_surfaces = union_(cache.bottom_surfaces, false);
  1342. // For a multi-material print, simulate perimeter / infill split as if only a single extruder has been used for the whole print.
  1343. if (perimeter_offset > 0.) {
  1344. // The layer.lslices are forced to merge by expanding them first.
  1345. polygons_append(cache.holes, offset(offset_ex(layer.lslices, 0.3f * perimeter_min_spacing), - perimeter_offset - 0.3f * perimeter_min_spacing));
  1346. #ifdef SLIC3R_DEBUG_SLICE_PROCESSING
  1347. {
  1348. Slic3r::SVG svg(debug_out_path("discover_vertical_shells-extra-holes-%d.svg", debug_idx), get_extents(layer.lslices));
  1349. svg.draw(layer.lslices, "blue");
  1350. svg.draw(union_ex(cache.holes), "red");
  1351. svg.draw_outline(union_ex(cache.holes), "black", "blue", scale_(0.05));
  1352. svg.Close();
  1353. }
  1354. #endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
  1355. }
  1356. cache.holes = union_(cache.holes, false);
  1357. }
  1358. });
  1359. m_print->throw_if_canceled();
  1360. BOOST_LOG_TRIVIAL(debug) << "Discovering vertical shells in parallel - end : cache top / bottom";
  1361. }
  1362. for (size_t idx_region = 0; idx_region < this->region_volumes.size(); ++ idx_region) {
  1363. PROFILE_BLOCK(discover_vertical_shells_region);
  1364. const PrintRegion &region = *m_print->get_region(idx_region);
  1365. if (! region.config().ensure_vertical_shell_thickness.value)
  1366. // This region will be handled by discover_horizontal_shells().
  1367. continue;
  1368. if (! has_extra_layers_fn(region.config()))
  1369. // Zero or 1 layer, there is no additional vertical wall thickness enforced.
  1370. continue;
  1371. //FIXME Improve the heuristics for a grain size.
  1372. size_t grain_size = std::max(num_layers / 16, size_t(1));
  1373. if (! top_bottom_surfaces_all_regions) {
  1374. // This is either a single material print, or a multi-material print and interface_shells are enabled, meaning that the vertical shell thickness
  1375. // is calculated over a single material.
  1376. BOOST_LOG_TRIVIAL(debug) << "Discovering vertical shells for region " << idx_region << " in parallel - start : cache top / bottom";
  1377. tbb::parallel_for(
  1378. tbb::blocked_range<size_t>(0, num_layers, grain_size),
  1379. [this, idx_region, &cache_top_botom_regions](const tbb::blocked_range<size_t>& range) {
  1380. for (size_t idx_layer = range.begin(); idx_layer < range.end(); ++ idx_layer) {
  1381. m_print->throw_if_canceled();
  1382. Layer &layer = *m_layers[idx_layer];
  1383. LayerRegion &layerm = *layer.m_regions[idx_region];
  1384. float min_perimeter_infill_spacing = float(layerm.flow(frSolidInfill).scaled_spacing()) * 1.05f;
  1385. // Top surfaces.
  1386. auto &cache = cache_top_botom_regions[idx_layer];
  1387. cache.top_surfaces = offset(to_expolygons(layerm.slices().filter_by_type(stPosTop | stDensSolid)), min_perimeter_infill_spacing);
  1388. append(cache.top_surfaces, offset(to_expolygons(layerm.fill_surfaces.filter_by_type(stPosTop | stDensSolid)), min_perimeter_infill_spacing));
  1389. // Bottom surfaces.
  1390. const SurfaceType surfaces_bottom[2] = { stPosBottom | stDensSolid, stPosBottom | stDensSolid | stModBridge };
  1391. cache.bottom_surfaces = offset(to_expolygons(layerm.slices().filter_by_types(surfaces_bottom, 2)), min_perimeter_infill_spacing);
  1392. append(cache.bottom_surfaces, offset(to_expolygons(layerm.fill_surfaces.filter_by_types(surfaces_bottom, 2)), min_perimeter_infill_spacing));
  1393. // Holes over all regions. Only collect them once, they are valid for all idx_region iterations.
  1394. if (cache.holes.empty()) {
  1395. for (size_t idx_region = 0; idx_region < layer.regions().size(); ++ idx_region)
  1396. polygons_append(cache.holes, to_polygons(layer.regions()[idx_region]->fill_expolygons));
  1397. }
  1398. }
  1399. });
  1400. m_print->throw_if_canceled();
  1401. BOOST_LOG_TRIVIAL(debug) << "Discovering vertical shells for region " << idx_region << " in parallel - end : cache top / bottom";
  1402. }
  1403. BOOST_LOG_TRIVIAL(debug) << "Discovering vertical shells for region " << idx_region << " in parallel - start : ensure vertical wall thickness";
  1404. tbb::parallel_for(
  1405. tbb::blocked_range<size_t>(0, num_layers, grain_size),
  1406. [this, idx_region, &cache_top_botom_regions]
  1407. (const tbb::blocked_range<size_t>& range) {
  1408. // printf("discover_vertical_shells from %d to %d\n", range.begin(), range.end());
  1409. for (size_t idx_layer = range.begin(); idx_layer < range.end(); ++ idx_layer) {
  1410. PROFILE_BLOCK(discover_vertical_shells_region_layer);
  1411. m_print->throw_if_canceled();
  1412. #ifdef SLIC3R_DEBUG_SLICE_PROCESSING
  1413. static size_t debug_idx = 0;
  1414. ++ debug_idx;
  1415. #endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
  1416. Layer *layer = m_layers[idx_layer];
  1417. LayerRegion *layerm = layer->m_regions[idx_region];
  1418. const PrintRegionConfig &region_config = layerm->region()->config();
  1419. #ifdef SLIC3R_DEBUG_SLICE_PROCESSING
  1420. layerm->export_region_slices_to_svg_debug("4_discover_vertical_shells-initial");
  1421. layerm->export_region_fill_surfaces_to_svg_debug("4_discover_vertical_shells-initial");
  1422. #endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
  1423. Flow solid_infill_flow = layerm->flow(frSolidInfill);
  1424. coord_t infill_line_spacing = solid_infill_flow.scaled_spacing();
  1425. // Find a union of perimeters below / above this surface to guarantee a minimum shell thickness.
  1426. Polygons shell;
  1427. Polygons holes;
  1428. #ifdef SLIC3R_DEBUG_SLICE_PROCESSING
  1429. ExPolygons shell_ex;
  1430. #endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
  1431. float min_perimeter_infill_spacing = float(infill_line_spacing) * 1.05f;
  1432. {
  1433. PROFILE_BLOCK(discover_vertical_shells_region_layer_collect);
  1434. #if 0
  1435. // #ifdef SLIC3R_DEBUG_SLICE_PROCESSING
  1436. {
  1437. Slic3r::SVG svg_cummulative(debug_out_path("discover_vertical_shells-perimeters-before-union-run%d.svg", debug_idx), this->bounding_box());
  1438. for (int n = (int)idx_layer - n_extra_bottom_layers; n <= (int)idx_layer + n_extra_top_layers; ++ n) {
  1439. if (n < 0 || n >= (int)m_layers.size())
  1440. continue;
  1441. ExPolygons &expolys = m_layers[n]->perimeter_expolygons;
  1442. for (size_t i = 0; i < expolys.size(); ++ i) {
  1443. Slic3r::SVG svg(debug_out_path("discover_vertical_shells-perimeters-before-union-run%d-layer%d-expoly%d.svg", debug_idx, n, i), get_extents(expolys[i]));
  1444. svg.draw(expolys[i]);
  1445. svg.draw_outline(expolys[i].contour, "black", scale_(0.05));
  1446. svg.draw_outline(expolys[i].holes, "blue", scale_(0.05));
  1447. svg.Close();
  1448. svg_cummulative.draw(expolys[i]);
  1449. svg_cummulative.draw_outline(expolys[i].contour, "black", scale_(0.05));
  1450. svg_cummulative.draw_outline(expolys[i].holes, "blue", scale_(0.05));
  1451. }
  1452. }
  1453. }
  1454. #endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
  1455. polygons_append(holes, cache_top_botom_regions[idx_layer].holes);
  1456. if (int n_top_layers = region_config.top_solid_layers.value; n_top_layers > 0) {
  1457. // Gather top regions projected to this layer.
  1458. coordf_t print_z = layer->print_z;
  1459. for (int i = int(idx_layer) + 1;
  1460. i < int(cache_top_botom_regions.size()) &&
  1461. (i < int(idx_layer) + n_top_layers ||
  1462. m_layers[i]->print_z - print_z < region_config.top_solid_min_thickness - EPSILON);
  1463. ++ i) {
  1464. const DiscoverVerticalShellsCacheEntry &cache = cache_top_botom_regions[i];
  1465. if (! holes.empty())
  1466. holes = intersection(holes, cache.holes);
  1467. if (! cache.top_surfaces.empty()) {
  1468. polygons_append(shell, cache.top_surfaces);
  1469. // Running the union_ using the Clipper library piece by piece is cheaper
  1470. // than running the union_ all at once.
  1471. shell = union_(shell, false);
  1472. }
  1473. }
  1474. }
  1475. if (int n_bottom_layers = region_config.bottom_solid_layers.value; n_bottom_layers > 0) {
  1476. // Gather bottom regions projected to this layer.
  1477. coordf_t bottom_z = layer->bottom_z();
  1478. for (int i = int(idx_layer) - 1;
  1479. i >= 0 &&
  1480. (i > int(idx_layer) - n_bottom_layers ||
  1481. bottom_z - m_layers[i]->bottom_z() < region_config.bottom_solid_min_thickness - EPSILON);
  1482. -- i) {
  1483. const DiscoverVerticalShellsCacheEntry &cache = cache_top_botom_regions[i];
  1484. if (! holes.empty())
  1485. holes = intersection(holes, cache.holes);
  1486. if (! cache.bottom_surfaces.empty()) {
  1487. polygons_append(shell, cache.bottom_surfaces);
  1488. // Running the union_ using the Clipper library piece by piece is cheaper
  1489. // than running the union_ all at once.
  1490. shell = union_(shell, false);
  1491. }
  1492. }
  1493. }
  1494. #ifdef SLIC3R_DEBUG_SLICE_PROCESSING
  1495. {
  1496. Slic3r::SVG svg(debug_out_path("discover_vertical_shells-perimeters-before-union-%d.svg", debug_idx), get_extents(shell));
  1497. svg.draw(shell);
  1498. svg.draw_outline(shell, "black", scale_(0.05));
  1499. svg.Close();
  1500. }
  1501. #endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
  1502. #if 0
  1503. {
  1504. PROFILE_BLOCK(discover_vertical_shells_region_layer_shell_);
  1505. // shell = union_(shell, true);
  1506. shell = union_(shell, false);
  1507. }
  1508. #endif
  1509. #ifdef SLIC3R_DEBUG_SLICE_PROCESSING
  1510. shell_ex = union_ex(shell, true);
  1511. #endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
  1512. }
  1513. //if (shell.empty())
  1514. // continue;
  1515. #ifdef SLIC3R_DEBUG_SLICE_PROCESSING
  1516. {
  1517. Slic3r::SVG svg(debug_out_path("discover_vertical_shells-perimeters-after-union-%d.svg", debug_idx), get_extents(shell));
  1518. svg.draw(shell_ex);
  1519. svg.draw_outline(shell_ex, "black", "blue", scale_(0.05));
  1520. svg.Close();
  1521. }
  1522. #endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
  1523. #ifdef SLIC3R_DEBUG_SLICE_PROCESSING
  1524. {
  1525. Slic3r::SVG svg(debug_out_path("discover_vertical_shells-internal-wshell-%d.svg", debug_idx), get_extents(shell));
  1526. svg.draw(layerm->fill_surfaces.filter_by_type(stInternal), "yellow", 0.5);
  1527. svg.draw_outline(layerm->fill_surfaces.filter_by_type(stInternal), "black", "blue", scale_(0.05));
  1528. svg.draw(shell_ex, "blue", 0.5);
  1529. svg.draw_outline(shell_ex, "black", "blue", scale_(0.05));
  1530. svg.Close();
  1531. }
  1532. {
  1533. Slic3r::SVG svg(debug_out_path("discover_vertical_shells-internalvoid-wshell-%d.svg", debug_idx), get_extents(shell));
  1534. svg.draw(layerm->fill_surfaces.filter_by_type(stInternalVoid), "yellow", 0.5);
  1535. svg.draw_outline(layerm->fill_surfaces.filter_by_type(stInternalVoid), "black", "blue", scale_(0.05));
  1536. svg.draw(shell_ex, "blue", 0.5);
  1537. svg.draw_outline(shell_ex, "black", "blue", scale_(0.05));
  1538. svg.Close();
  1539. }
  1540. {
  1541. Slic3r::SVG svg(debug_out_path("discover_vertical_shells-internalvoid-wshell-%d.svg", debug_idx), get_extents(shell));
  1542. svg.draw(layerm->fill_surfaces.filter_by_type(stInternalVoid), "yellow", 0.5);
  1543. svg.draw_outline(layerm->fill_surfaces.filter_by_type(stInternalVoid), "black", "blue", scale_(0.05));
  1544. svg.draw(shell_ex, "blue", 0.5);
  1545. svg.draw_outline(shell_ex, "black", "blue", scale_(0.05));
  1546. svg.Close();
  1547. }
  1548. #endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
  1549. // Trim the shells region by the internal & internal void surfaces.
  1550. const SurfaceType surfaceTypesInternal[] = { stPosInternal | stDensSparse, stPosInternal | stDensVoid, stPosInternal | stDensSolid };
  1551. const Polygons polygonsInternal = to_polygons(layerm->fill_surfaces.filter_by_types(surfaceTypesInternal, 3));
  1552. shell = intersection(shell, polygonsInternal, true);
  1553. polygons_append(shell, diff(polygonsInternal, holes));
  1554. if (shell.empty())
  1555. continue;
  1556. // Append the internal solids, so they will be merged with the new ones.
  1557. polygons_append(shell, to_polygons(layerm->fill_surfaces.filter_by_type(stPosInternal | stDensSolid)));
  1558. // These regions will be filled by a rectilinear full infill. Currently this type of infill
  1559. // only fills regions, which fit at least a single line. To avoid gaps in the sparse infill,
  1560. // make sure that this region does not contain parts narrower than the infill spacing width.
  1561. #ifdef SLIC3R_DEBUG_SLICE_PROCESSING
  1562. Polygons shell_before = shell;
  1563. #endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
  1564. #if 1
  1565. // Intentionally inflate a bit more than how much the region has been shrunk,
  1566. // so there will be some overlap between this solid infill and the other infill regions (mainly the sparse infill).
  1567. shell = offset(offset_ex(union_ex(shell), - 0.5f * min_perimeter_infill_spacing), 0.8f * min_perimeter_infill_spacing, ClipperLib::jtSquare);
  1568. if (shell.empty())
  1569. continue;
  1570. #else
  1571. // Ensure each region is at least 3x infill line width wide, so it could be filled in.
  1572. // float margin = float(infill_line_spacing) * 3.f;
  1573. float margin = float(infill_line_spacing) * 1.5f;
  1574. // we use a higher miterLimit here to handle areas with acute angles
  1575. // in those cases, the default miterLimit would cut the corner and we'd
  1576. // get a triangle in $too_narrow; if we grow it below then the shell
  1577. // would have a different shape from the external surface and we'd still
  1578. // have the same angle, so the next shell would be grown even more and so on.
  1579. Polygons too_narrow = diff(shell, offset2(shell, -margin, margin, ClipperLib::jtMiter, 5.), true);
  1580. if (! too_narrow.empty()) {
  1581. // grow the collapsing parts and add the extra area to the neighbor layer
  1582. // as well as to our original surfaces so that we support this
  1583. // additional area in the next shell too
  1584. // make sure our grown surfaces don't exceed the fill area
  1585. polygons_append(shell, intersection(offset(too_narrow, margin), polygonsInternal));
  1586. }
  1587. #endif
  1588. ExPolygons new_internal_solid = intersection_ex(polygonsInternal, shell, false);
  1589. #ifdef SLIC3R_DEBUG_SLICE_PROCESSING
  1590. {
  1591. Slic3r::SVG svg(debug_out_path("discover_vertical_shells-regularized-%d.svg", debug_idx), get_extents(shell_before));
  1592. // Source shell.
  1593. svg.draw(union_ex(shell_before, true));
  1594. // Shell trimmed to the internal surfaces.
  1595. svg.draw_outline(union_ex(shell, true), "black", "blue", scale_(0.05));
  1596. // Regularized infill region.
  1597. svg.draw_outline(new_internal_solid, "red", "magenta", scale_(0.05));
  1598. svg.Close();
  1599. }
  1600. #endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
  1601. // Trim the internal & internalvoid by the shell.
  1602. Slic3r::ExPolygons new_internal = diff_ex(
  1603. to_polygons(layerm->fill_surfaces.filter_by_type(stPosInternal | stDensSparse)),
  1604. shell,
  1605. false
  1606. );
  1607. Slic3r::ExPolygons new_internal_void = diff_ex(
  1608. to_polygons(layerm->fill_surfaces.filter_by_type(stPosInternal | stDensVoid)),
  1609. shell,
  1610. false
  1611. );
  1612. #ifdef SLIC3R_DEBUG_SLICE_PROCESSING
  1613. {
  1614. SVG::export_expolygons(debug_out_path("discover_vertical_shells-new_internal-%d.svg", debug_idx), get_extents(shell), new_internal, "black", "blue", scale_(0.05));
  1615. SVG::export_expolygons(debug_out_path("discover_vertical_shells-new_internal_void-%d.svg", debug_idx), get_extents(shell), new_internal_void, "black", "blue", scale_(0.05));
  1616. SVG::export_expolygons(debug_out_path("discover_vertical_shells-new_internal_solid-%d.svg", debug_idx), get_extents(shell), new_internal_solid, "black", "blue", scale_(0.05));
  1617. }
  1618. #endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
  1619. // Assign resulting internal surfaces to layer.
  1620. const SurfaceType surfaceTypesKeep[] = { stPosTop | stDensSolid, stPosBottom | stDensSolid, stPosBottom | stDensSolid | stModBridge };
  1621. layerm->fill_surfaces.keep_types(surfaceTypesKeep, sizeof(surfaceTypesKeep)/sizeof(SurfaceType));
  1622. //layerm->fill_surfaces.keep_types_flag(stPosTop | stPosBottom);
  1623. layerm->fill_surfaces.append(new_internal, stPosInternal | stDensSparse);
  1624. layerm->fill_surfaces.append(new_internal_void, stPosInternal | stDensVoid);
  1625. layerm->fill_surfaces.append(new_internal_solid, stPosInternal | stDensSolid);
  1626. } // for each layer
  1627. });
  1628. m_print->throw_if_canceled();
  1629. BOOST_LOG_TRIVIAL(debug) << "Discovering vertical shells for region " << idx_region << " in parallel - end";
  1630. #ifdef SLIC3R_DEBUG_SLICE_PROCESSING
  1631. for (size_t idx_layer = 0; idx_layer < m_layers.size(); ++idx_layer) {
  1632. LayerRegion *layerm = m_layers[idx_layer]->get_region(idx_region);
  1633. layerm->export_region_slices_to_svg_debug("4_discover_vertical_shells-final");
  1634. layerm->export_region_fill_surfaces_to_svg_debug("4_discover_vertical_shells-final");
  1635. }
  1636. #endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
  1637. } // for each region
  1638. // Write the profiler measurements to file
  1639. // PROFILE_UPDATE();
  1640. // PROFILE_OUTPUT(debug_out_path("discover_vertical_shells-profile.txt").c_str());
  1641. }
  1642. /* This method applies bridge flow to the first internal solid layer above
  1643. sparse infill */
  1644. void PrintObject::bridge_over_infill()
  1645. {
  1646. BOOST_LOG_TRIVIAL(info) << "Bridge over infill..." << log_memory_info();
  1647. for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) {
  1648. const PrintRegion &region = *m_print->regions()[region_id];
  1649. // skip bridging in case there are no voids
  1650. if (region.config().fill_density.value == 100) continue;
  1651. // get bridge flow
  1652. Flow bridge_flow = region.flow(
  1653. frSolidInfill,
  1654. -1, // layer height, not relevant for bridge flow
  1655. true, // bridge
  1656. false, // first layer
  1657. -1, // custom width, not relevant for bridge flow
  1658. *this
  1659. );
  1660. for (LayerPtrs::iterator layer_it = m_layers.begin(); layer_it != m_layers.end(); ++ layer_it) {
  1661. // skip first layer
  1662. if (layer_it == m_layers.begin())
  1663. continue;
  1664. Layer* layer = *layer_it;
  1665. LayerRegion* layerm = layer->m_regions[region_id];
  1666. // extract the stInternalSolid surfaces that might be transformed into bridges
  1667. Polygons internal_solid;
  1668. layerm->fill_surfaces.filter_by_type(stPosInternal | stDensSolid, &internal_solid);
  1669. // check whether the lower area is deep enough for absorbing the extra flow
  1670. // (for obvious physical reasons but also for preventing the bridge extrudates
  1671. // from overflowing in 3D preview)
  1672. ExPolygons to_bridge;
  1673. {
  1674. Polygons to_bridge_pp = internal_solid;
  1675. // iterate through lower layers spanned by bridge_flow
  1676. double bottom_z = layer->print_z - bridge_flow.height;
  1677. for (int i = int(layer_it - m_layers.begin()) - 1; i >= 0; --i) {
  1678. const Layer* lower_layer = m_layers[i];
  1679. // stop iterating if layer is lower than bottom_z
  1680. if (lower_layer->print_z < bottom_z) break;
  1681. // iterate through regions and collect internal surfaces
  1682. Polygons lower_internal;
  1683. for (LayerRegion *lower_layerm : lower_layer->m_regions)
  1684. lower_layerm->fill_surfaces.filter_by_type(stPosInternal | stDensSparse, &lower_internal);
  1685. // intersect such lower internal surfaces with the candidate solid surfaces
  1686. to_bridge_pp = intersection(to_bridge_pp, lower_internal);
  1687. }
  1688. // there's no point in bridging too thin/short regions
  1689. //FIXME Vojtech: The offset2 function is not a geometric offset,
  1690. // therefore it may create 1) gaps, and 2) sharp corners, which are outside the original contour.
  1691. // The gaps will be filled by a separate region, which makes the infill less stable and it takes longer.
  1692. {
  1693. float min_width = float(bridge_flow.scaled_width()) * 3.f;
  1694. to_bridge_pp = offset2(to_bridge_pp, -min_width, +min_width);
  1695. }
  1696. if (to_bridge_pp.empty()) continue;
  1697. // convert into ExPolygons
  1698. to_bridge = union_ex(to_bridge_pp);
  1699. }
  1700. #ifdef SLIC3R_DEBUG
  1701. printf("Bridging " PRINTF_ZU " internal areas at layer " PRINTF_ZU "\n", to_bridge.size(), layer->id());
  1702. #endif
  1703. //add a bit of overlap for the internal bridge, note that this can only be useful in inverted slopes and with extra_perimeters_odd_layers
  1704. coord_t overlap_width = 0;
  1705. // if extra_perimeters_odd_layers, fill the void if possible
  1706. if (region.config().extra_perimeters_odd_layers.value) {
  1707. overlap_width = layerm->flow(frPerimeter).scaled_width();
  1708. }
  1709. else
  1710. {
  1711. //half a perimeter should be enough for most of the cases.
  1712. overlap_width = layerm->flow(frPerimeter).scaled_width() /2;
  1713. }
  1714. if (overlap_width > 0)
  1715. to_bridge = offset_ex(to_bridge, overlap_width);
  1716. // compute the remaning internal solid surfaces as difference
  1717. ExPolygons not_to_bridge = diff_ex(internal_solid, to_polygons(to_bridge), true);
  1718. to_bridge = intersection_ex(to_polygons(to_bridge), internal_solid, true);
  1719. // build the new collection of fill_surfaces
  1720. layerm->fill_surfaces.remove_type(stPosInternal | stDensSolid);
  1721. for (ExPolygon &ex : to_bridge)
  1722. layerm->fill_surfaces.surfaces.push_back(Surface(stPosInternal | stDensSolid | stModBridge, ex));
  1723. for (ExPolygon &ex : not_to_bridge)
  1724. layerm->fill_surfaces.surfaces.push_back(Surface(stPosInternal | stDensSolid, ex));
  1725. /*
  1726. # exclude infill from the layers below if needed
  1727. # see discussion at https://github.com/alexrj/Slic3r/issues/240
  1728. # Update: do not exclude any infill. Sparse infill is able to absorb the excess material.
  1729. if (0) {
  1730. my $excess = $layerm->extruders->{infill}->bridge_flow->width - $layerm->height;
  1731. for (my $i = $layer_id-1; $excess >= $self->get_layer($i)->height; $i--) {
  1732. Slic3r::debugf " skipping infill below those areas at layer %d\n", $i;
  1733. foreach my $lower_layerm (@{$self->get_layer($i)->regions}) {
  1734. my @new_surfaces = ();
  1735. # subtract the area from all types of surfaces
  1736. foreach my $group (@{$lower_layerm->fill_surfaces->group}) {
  1737. push @new_surfaces, map $group->[0]->clone(expolygon => $_),
  1738. @{diff_ex(
  1739. [ map $_->p, @$group ],
  1740. [ map @$_, @$to_bridge ],
  1741. )};
  1742. push @new_surfaces, map Slic3r::Surface->new(
  1743. expolygon => $_,
  1744. surface_type => stInternalVoid,
  1745. ), @{intersection_ex(
  1746. [ map $_->p, @$group ],
  1747. [ map @$_, @$to_bridge ],
  1748. )};
  1749. }
  1750. $lower_layerm->fill_surfaces->clear;
  1751. $lower_layerm->fill_surfaces->append($_) for @new_surfaces;
  1752. }
  1753. $excess -= $self->get_layer($i)->height;
  1754. }
  1755. }
  1756. */
  1757. #ifdef SLIC3R_DEBUG_SLICE_PROCESSING
  1758. layerm->export_region_slices_to_svg_debug("7_bridge_over_infill");
  1759. layerm->export_region_fill_surfaces_to_svg_debug("7_bridge_over_infill");
  1760. #endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
  1761. m_print->throw_if_canceled();
  1762. }
  1763. }
  1764. }
  1765. /* This method applies overextrude flow to the first internal solid layer above
  1766. bridge (which is over sparse infill) note: it's almost complete copy/paste from the method behind,
  1767. i think it should be merged before gitpull that.
  1768. */
  1769. void
  1770. PrintObject::replaceSurfaceType(SurfaceType st_to_replace, SurfaceType st_replacement, SurfaceType st_under_it)
  1771. {
  1772. BOOST_LOG_TRIVIAL(info) << "overextrude over Bridge...";
  1773. for (size_t region_id = 0; region_id < this->region_volumes.size(); ++region_id) {
  1774. const PrintRegion &region = *m_print->regions()[region_id];
  1775. // skip over-bridging in case there are no modification
  1776. if (region.config().over_bridge_flow_ratio.get_abs_value(1) == 1) continue;
  1777. for (LayerPtrs::iterator layer_it = m_layers.begin(); layer_it != m_layers.end(); ++layer_it) {
  1778. // skip first layer
  1779. if (layer_it == this->layers().begin()) continue;
  1780. Layer* layer = *layer_it;
  1781. LayerRegion* layerm = layer->regions()[region_id];
  1782. Polygons poly_to_check;
  1783. // extract the surfaces that might be transformed
  1784. layerm->fill_surfaces.filter_by_type(st_to_replace, &poly_to_check);
  1785. Polygons poly_to_replace = poly_to_check;
  1786. // check the lower layer
  1787. if (int(layer_it - this->layers().begin()) - 1 >= 0) {
  1788. const Layer* lower_layer = this->layers()[int(layer_it - this->layers().begin()) - 1];
  1789. // iterate through regions and collect internal surfaces
  1790. Polygons lower_internal;
  1791. for (LayerRegion *lower_layerm : lower_layer->m_regions) {
  1792. lower_layerm->fill_surfaces.filter_by_type(st_under_it, &lower_internal);
  1793. }
  1794. // intersect such lower internal surfaces with the candidate solid surfaces
  1795. poly_to_replace = intersection(poly_to_replace, lower_internal);
  1796. }
  1797. if (poly_to_replace.empty()) continue;
  1798. // compute the remaning internal solid surfaces as difference
  1799. ExPolygons not_expoly_to_replace = diff_ex(poly_to_check, poly_to_replace, true);
  1800. // build the new collection of fill_surfaces
  1801. {
  1802. Surfaces new_surfaces;
  1803. for (Surfaces::const_iterator surface = layerm->fill_surfaces.surfaces.begin(); surface != layerm->fill_surfaces.surfaces.end(); ++surface) {
  1804. if (surface->surface_type != st_to_replace)
  1805. new_surfaces.push_back(*surface);
  1806. }
  1807. for (ExPolygon &ex : union_ex(poly_to_replace)) {
  1808. new_surfaces.push_back(Surface(st_replacement, ex));
  1809. }
  1810. for (ExPolygon &ex : not_expoly_to_replace){
  1811. new_surfaces.push_back(Surface(st_to_replace, ex));
  1812. }
  1813. layerm->fill_surfaces.surfaces = new_surfaces;
  1814. }
  1815. }
  1816. }
  1817. }
  1818. static void clamp_exturder_to_default(ConfigOptionInt &opt, size_t num_extruders)
  1819. {
  1820. if (opt.value > (int)num_extruders)
  1821. // assign the default extruder
  1822. opt.value = 1;
  1823. }
  1824. PrintObjectConfig PrintObject::object_config_from_model_object(const PrintObjectConfig &default_object_config, const ModelObject &object, size_t num_extruders)
  1825. {
  1826. PrintObjectConfig config = default_object_config;
  1827. normalize_and_apply_config(config, object.config);
  1828. // Clamp invalid extruders to the default extruder (with index 1).
  1829. clamp_exturder_to_default(config.support_material_extruder, num_extruders);
  1830. clamp_exturder_to_default(config.support_material_interface_extruder, num_extruders);
  1831. return config;
  1832. }
  1833. PrintRegionConfig PrintObject::region_config_from_model_volume(const PrintRegionConfig &default_region_config, const DynamicPrintConfig *layer_range_config, const ModelVolume &volume, size_t num_extruders)
  1834. {
  1835. PrintRegionConfig config = default_region_config;
  1836. normalize_and_apply_config(config, volume.get_object()->config);
  1837. if (layer_range_config != nullptr)
  1838. normalize_and_apply_config(config, *layer_range_config);
  1839. normalize_and_apply_config(config, volume.config);
  1840. if (! volume.material_id().empty())
  1841. normalize_and_apply_config(config, volume.material()->config);
  1842. // Clamp invalid extruders to the default extruder (with index 1).
  1843. clamp_exturder_to_default(config.infill_extruder, num_extruders);
  1844. clamp_exturder_to_default(config.perimeter_extruder, num_extruders);
  1845. clamp_exturder_to_default(config.solid_infill_extruder, num_extruders);
  1846. return config;
  1847. }
  1848. void PrintObject::update_slicing_parameters()
  1849. {
  1850. if (! m_slicing_params.valid)
  1851. m_slicing_params = SlicingParameters::create_from_config(
  1852. this->print()->config(), m_config, unscale<double>(this->height()), this->object_extruders());
  1853. }
  1854. SlicingParameters PrintObject::slicing_parameters(const DynamicPrintConfig& full_config, const ModelObject& model_object, float object_max_z)
  1855. {
  1856. PrintConfig print_config;
  1857. PrintObjectConfig object_config;
  1858. PrintRegionConfig default_region_config;
  1859. print_config.apply(full_config, true);
  1860. object_config.apply(full_config, true);
  1861. default_region_config.apply(full_config, true);
  1862. size_t num_extruders = print_config.nozzle_diameter.size();
  1863. object_config = object_config_from_model_object(object_config, model_object, num_extruders);
  1864. std::vector<uint16_t> object_extruders;
  1865. for (const ModelVolume* model_volume : model_object.volumes)
  1866. if (model_volume->is_model_part()) {
  1867. PrintRegion::collect_object_printing_extruders(
  1868. print_config,
  1869. object_config,
  1870. region_config_from_model_volume(default_region_config, nullptr, *model_volume, num_extruders),
  1871. object_extruders);
  1872. for (const std::pair<const t_layer_height_range, DynamicPrintConfig> &range_and_config : model_object.layer_config_ranges)
  1873. if (range_and_config.second.has("perimeter_extruder") ||
  1874. range_and_config.second.has("infill_extruder") ||
  1875. range_and_config.second.has("solid_infill_extruder"))
  1876. PrintRegion::collect_object_printing_extruders(
  1877. print_config,
  1878. object_config,
  1879. region_config_from_model_volume(default_region_config, &range_and_config.second, *model_volume, num_extruders),
  1880. object_extruders);
  1881. }
  1882. sort_remove_duplicates(object_extruders);
  1883. if (object_max_z <= 0.f)
  1884. object_max_z = (float)model_object.raw_bounding_box().size().z();
  1885. return SlicingParameters::create_from_config(print_config, object_config, object_max_z, object_extruders);
  1886. }
  1887. // returns 0-based indices of extruders used to print the object (without brim, support and other helper extrusions)
  1888. std::vector<uint16_t> PrintObject::object_extruders() const
  1889. {
  1890. std::vector<uint16_t> extruders;
  1891. extruders.reserve(this->region_volumes.size() * 3);
  1892. for (size_t idx_region = 0; idx_region < this->region_volumes.size(); ++ idx_region)
  1893. if (! this->region_volumes[idx_region].empty())
  1894. m_print->get_region(idx_region)->collect_object_printing_extruders(extruders);
  1895. sort_remove_duplicates(extruders);
  1896. return extruders;
  1897. }
  1898. bool PrintObject::update_layer_height_profile(const ModelObject &model_object, const SlicingParameters &slicing_parameters, std::vector<coordf_t> &layer_height_profile)
  1899. {
  1900. bool updated = false;
  1901. if (layer_height_profile.empty()) {
  1902. layer_height_profile = model_object.layer_height_profile;
  1903. updated = true;
  1904. }
  1905. // Verify the layer_height_profile.
  1906. if (! layer_height_profile.empty() &&
  1907. // Must not be of even length.
  1908. ((layer_height_profile.size() & 1) != 0 ||
  1909. // Last entry must be at the top of the object.
  1910. std::abs(layer_height_profile[layer_height_profile.size() - 2] - slicing_parameters.object_print_z_height()) > 1e-3))
  1911. layer_height_profile.clear();
  1912. if (layer_height_profile.empty()) {
  1913. layer_height_profile = layer_height_profile_from_ranges(slicing_parameters, model_object.layer_config_ranges);
  1914. updated = true;
  1915. }
  1916. return updated;
  1917. }
  1918. // 1) Decides Z positions of the layers,
  1919. // 2) Initializes layers and their regions
  1920. // 3) Slices the object meshes
  1921. // 4) Slices the modifier meshes and reclassifies the slices of the object meshes by the slices of the modifier meshes
  1922. // 5) Applies size compensation (offsets the slices in XY plane)
  1923. // 6) Replaces bad slices by the slices reconstructed from the upper/lower layer
  1924. // Resulting expolygons of layer regions are marked as Internal.
  1925. //
  1926. // this should be idempotent
  1927. void PrintObject::_slice(const std::vector<coordf_t> &layer_height_profile)
  1928. {
  1929. BOOST_LOG_TRIVIAL(info) << "Slicing objects..." << log_memory_info();
  1930. m_typed_slices = false;
  1931. #ifdef SLIC3R_PROFILE
  1932. // Disable parallelization so the Shiny profiler works
  1933. static tbb::task_scheduler_init *tbb_init = nullptr;
  1934. tbb_init = new tbb::task_scheduler_init(1);
  1935. #endif
  1936. // 1) Initialize layers and their slice heights.
  1937. std::vector<float> slice_zs;
  1938. {
  1939. this->clear_layers();
  1940. // Object layers (pairs of bottom/top Z coordinate), without the raft.
  1941. std::vector<coordf_t> object_layers = generate_object_layers(m_slicing_params, layer_height_profile);
  1942. // Reserve object layers for the raft. Last layer of the raft is the contact layer.
  1943. int id = int(m_slicing_params.raft_layers());
  1944. slice_zs.reserve(object_layers.size());
  1945. Layer *prev = nullptr;
  1946. for (size_t i_layer = 0; i_layer < object_layers.size(); i_layer += 2) {
  1947. coordf_t lo = object_layers[i_layer];
  1948. coordf_t hi = object_layers[i_layer + 1];
  1949. coordf_t slice_z = 0.5 * (lo + hi);
  1950. Layer *layer = this->add_layer(id ++, hi - lo, hi + m_slicing_params.object_print_z_min, slice_z);
  1951. slice_zs.push_back(float(slice_z));
  1952. if (prev != nullptr) {
  1953. prev->upper_layer = layer;
  1954. layer->lower_layer = prev;
  1955. }
  1956. // Make sure all layers contain layer region objects for all regions.
  1957. for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id)
  1958. layer->add_region(this->print()->regions()[region_id]);
  1959. prev = layer;
  1960. }
  1961. }
  1962. // Count model parts and modifier meshes, check whether the model parts are of the same region.
  1963. int all_volumes_single_region = -2; // not set yet
  1964. bool has_z_ranges = false;
  1965. size_t num_volumes = 0;
  1966. size_t num_modifiers = 0;
  1967. for (int region_id = 0; region_id < (int)this->region_volumes.size(); ++ region_id) {
  1968. int last_volume_id = -1;
  1969. for (const std::pair<t_layer_height_range, int> &volume_and_range : this->region_volumes[region_id]) {
  1970. const int volume_id = volume_and_range.second;
  1971. const ModelVolume *model_volume = this->model_object()->volumes[volume_id];
  1972. if (model_volume->is_model_part()) {
  1973. if (last_volume_id == volume_id) {
  1974. has_z_ranges = true;
  1975. } else {
  1976. last_volume_id = volume_id;
  1977. if (all_volumes_single_region == -2)
  1978. // first model volume met
  1979. all_volumes_single_region = region_id;
  1980. else if (all_volumes_single_region != region_id)
  1981. // multiple volumes met and they are not equal
  1982. all_volumes_single_region = -1;
  1983. ++ num_volumes;
  1984. }
  1985. } else if (model_volume->is_modifier())
  1986. ++ num_modifiers;
  1987. }
  1988. }
  1989. assert(num_volumes > 0);
  1990. // Slice all non-modifier volumes.
  1991. bool clipped = false;
  1992. bool upscaled = false;
  1993. auto slicing_mode = this->print()->config().spiral_vase ? SlicingMode::PositiveLargestContour : SlicingMode::Regular;
  1994. if (! has_z_ranges && (! m_config.clip_multipart_objects.value || all_volumes_single_region >= 0)) {
  1995. // Cheap path: Slice regions without mutual clipping.
  1996. // The cheap path is possible if no clipping is allowed or if slicing volumes of just a single region.
  1997. for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) {
  1998. BOOST_LOG_TRIVIAL(debug) << "Slicing objects - region " << region_id;
  1999. // slicing in parallel
  2000. std::vector<ExPolygons> expolygons_by_layer = this->slice_region(region_id, slice_zs, slicing_mode);
  2001. //scale for shrinkage
  2002. double scale = print()->config().filament_shrink.get_abs_value(this->print()->regions()[region_id]->extruder(FlowRole::frPerimeter) - 1, 1);
  2003. if (scale != 1) {
  2004. scale = 1 / scale;
  2005. for (ExPolygons &polys : expolygons_by_layer)
  2006. for (ExPolygon &poly : polys)
  2007. poly.scale(scale);
  2008. }
  2009. m_print->throw_if_canceled();
  2010. BOOST_LOG_TRIVIAL(debug) << "Slicing objects - append slices " << region_id << " start";
  2011. for (size_t layer_id = 0; layer_id < expolygons_by_layer.size(); ++ layer_id)
  2012. m_layers[layer_id]->regions()[region_id]->m_slices.append(std::move(expolygons_by_layer[layer_id]), stPosInternal | stDensSparse);
  2013. m_print->throw_if_canceled();
  2014. BOOST_LOG_TRIVIAL(debug) << "Slicing objects - append slices " << region_id << " end";
  2015. }
  2016. } else {
  2017. // Expensive path: Slice one volume after the other in the order they are presented at the user interface,
  2018. // clip the last volumes with the first.
  2019. // First slice the volumes.
  2020. struct SlicedVolume {
  2021. SlicedVolume(int volume_id, int region_id, std::vector<ExPolygons> &&expolygons_by_layer) :
  2022. volume_id(volume_id), region_id(region_id), expolygons_by_layer(std::move(expolygons_by_layer)) {}
  2023. int volume_id;
  2024. int region_id;
  2025. std::vector<ExPolygons> expolygons_by_layer;
  2026. };
  2027. std::vector<SlicedVolume> sliced_volumes;
  2028. sliced_volumes.reserve(num_volumes);
  2029. for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) {
  2030. const std::vector<std::pair<t_layer_height_range, int>> &volumes_and_ranges = this->region_volumes[region_id];
  2031. for (size_t i = 0; i < volumes_and_ranges.size(); ) {
  2032. int volume_id = volumes_and_ranges[i].second;
  2033. const ModelVolume *model_volume = this->model_object()->volumes[volume_id];
  2034. if (model_volume->is_model_part()) {
  2035. BOOST_LOG_TRIVIAL(debug) << "Slicing objects - volume " << volume_id;
  2036. // Find the ranges of this volume. Ranges in volumes_and_ranges must not overlap for a single volume.
  2037. std::vector<t_layer_height_range> ranges;
  2038. ranges.emplace_back(volumes_and_ranges[i].first);
  2039. size_t j = i + 1;
  2040. for (; j < volumes_and_ranges.size() && volume_id == volumes_and_ranges[j].second; ++ j)
  2041. if (! ranges.empty() && std::abs(ranges.back().second - volumes_and_ranges[j].first.first) < EPSILON)
  2042. ranges.back().second = volumes_and_ranges[j].first.second;
  2043. else
  2044. ranges.emplace_back(volumes_and_ranges[j].first);
  2045. // slicing in parallel
  2046. sliced_volumes.emplace_back(volume_id, (int)region_id, this->slice_volume(slice_zs, ranges, slicing_mode, *model_volume));
  2047. i = j;
  2048. } else
  2049. ++ i;
  2050. }
  2051. }
  2052. //scale for shrinkage
  2053. for (SlicedVolume &sv : sliced_volumes) {
  2054. double scale = print()->config().filament_shrink.get_abs_value(this->print()->regions()[sv.region_id]->extruder(FlowRole::frPerimeter) - 1, 1);
  2055. if (scale != 1) {
  2056. scale = 1 / scale;
  2057. for (ExPolygons &polys : sv.expolygons_by_layer)
  2058. for (ExPolygon &poly : polys)
  2059. poly.scale(scale);
  2060. }
  2061. }
  2062. // Second clip the volumes in the order they are presented at the user interface.
  2063. BOOST_LOG_TRIVIAL(debug) << "Slicing objects - parallel clipping - start";
  2064. tbb::parallel_for(
  2065. tbb::blocked_range<size_t>(0, slice_zs.size()),
  2066. [this, &sliced_volumes, num_modifiers](const tbb::blocked_range<size_t>& range) {
  2067. float delta = float(scale_(m_config.xy_size_compensation.value));
  2068. // Only upscale together with clipping if there are no modifiers, as the modifiers shall be applied before upscaling
  2069. // (upscaling may grow the object outside of the modifier mesh).
  2070. bool upscale = false && delta > 0 && num_modifiers == 0;
  2071. for (size_t layer_id = range.begin(); layer_id < range.end(); ++ layer_id) {
  2072. m_print->throw_if_canceled();
  2073. // Trim volumes in a single layer, one by the other, possibly apply upscaling.
  2074. {
  2075. Polygons processed;
  2076. for (SlicedVolume &sliced_volume : sliced_volumes)
  2077. if (! sliced_volume.expolygons_by_layer.empty()) {
  2078. ExPolygons slices = std::move(sliced_volume.expolygons_by_layer[layer_id]);
  2079. if (upscale)
  2080. slices = offset_ex(std::move(slices), delta);
  2081. if (! processed.empty())
  2082. // Trim by the slices of already processed regions.
  2083. slices = diff_ex(to_polygons(std::move(slices)), processed);
  2084. if (size_t(&sliced_volume - &sliced_volumes.front()) + 1 < sliced_volumes.size())
  2085. // Collect the already processed regions to trim the to be processed regions.
  2086. polygons_append(processed, slices);
  2087. sliced_volume.expolygons_by_layer[layer_id] = std::move(slices);
  2088. }
  2089. }
  2090. // Collect and union volumes of a single region.
  2091. for (int region_id = 0; region_id < (int)this->region_volumes.size(); ++ region_id) {
  2092. ExPolygons expolygons;
  2093. size_t num_volumes = 0;
  2094. for (SlicedVolume &sliced_volume : sliced_volumes)
  2095. if (sliced_volume.region_id == region_id && ! sliced_volume.expolygons_by_layer.empty() && ! sliced_volume.expolygons_by_layer[layer_id].empty()) {
  2096. ++ num_volumes;
  2097. append(expolygons, std::move(sliced_volume.expolygons_by_layer[layer_id]));
  2098. }
  2099. if (num_volumes > 1)
  2100. // Merge the islands using a positive / negative offset.
  2101. expolygons = offset_ex(offset_ex(expolygons, double(scale_(EPSILON))), double( - scale_(EPSILON)));
  2102. m_layers[layer_id]->regions()[region_id]->m_slices.append(std::move(expolygons), stPosInternal | stDensSparse);
  2103. }
  2104. }
  2105. });
  2106. BOOST_LOG_TRIVIAL(debug) << "Slicing objects - parallel clipping - end";
  2107. clipped = true;
  2108. upscaled = false && m_config.xy_size_compensation.value > 0 && num_modifiers == 0;
  2109. }
  2110. // Slice all modifier volumes.
  2111. if (this->region_volumes.size() > 1) {
  2112. for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) {
  2113. BOOST_LOG_TRIVIAL(debug) << "Slicing modifier volumes - region " << region_id;
  2114. // slicing in parallel
  2115. std::vector<ExPolygons> expolygons_by_layer = this->slice_modifiers(region_id, slice_zs);
  2116. m_print->throw_if_canceled();
  2117. if (expolygons_by_layer.empty())
  2118. continue;
  2119. // loop through the other regions and 'steal' the slices belonging to this one
  2120. BOOST_LOG_TRIVIAL(debug) << "Slicing modifier volumes - stealing " << region_id << " start";
  2121. tbb::parallel_for(
  2122. tbb::blocked_range<size_t>(0, m_layers.size()),
  2123. [this, &expolygons_by_layer, region_id](const tbb::blocked_range<size_t>& range) {
  2124. for (size_t layer_id = range.begin(); layer_id < range.end(); ++ layer_id) {
  2125. for (size_t other_region_id = 0; other_region_id < this->region_volumes.size(); ++ other_region_id) {
  2126. if (region_id == other_region_id)
  2127. continue;
  2128. Layer *layer = m_layers[layer_id];
  2129. LayerRegion *layerm = layer->m_regions[region_id];
  2130. LayerRegion *other_layerm = layer->m_regions[other_region_id];
  2131. if (layerm == nullptr || other_layerm == nullptr || other_layerm->slices().empty() || expolygons_by_layer[layer_id].empty())
  2132. continue;
  2133. Polygons other_slices = to_polygons(other_layerm->slices());
  2134. ExPolygons my_parts = intersection_ex(other_slices, to_polygons(expolygons_by_layer[layer_id]));
  2135. if (my_parts.empty())
  2136. continue;
  2137. // Remove such parts from original region.
  2138. other_layerm->m_slices.set(diff_ex(other_slices, to_polygons(my_parts)), stPosInternal | stDensSparse);
  2139. // Append new parts to our region.
  2140. layerm->m_slices.append(std::move(my_parts), stPosInternal | stDensSparse);
  2141. }
  2142. }
  2143. });
  2144. m_print->throw_if_canceled();
  2145. BOOST_LOG_TRIVIAL(debug) << "Slicing modifier volumes - stealing " << region_id << " end";
  2146. }
  2147. }
  2148. BOOST_LOG_TRIVIAL(debug) << "Slicing objects - removing top empty layers";
  2149. while (! m_layers.empty()) {
  2150. const Layer *layer = m_layers.back();
  2151. if (! layer->empty())
  2152. goto end;
  2153. delete layer;
  2154. m_layers.pop_back();
  2155. if (! m_layers.empty())
  2156. m_layers.back()->upper_layer = nullptr;
  2157. }
  2158. m_print->throw_if_canceled();
  2159. end:
  2160. ;
  2161. BOOST_LOG_TRIVIAL(debug) << "Slicing objects - make_slices in parallel - begin";
  2162. {
  2163. // Uncompensated slices for the first layer in case the Elephant foot compensation is applied.
  2164. tbb::parallel_for(
  2165. tbb::blocked_range<size_t>(0, m_layers.size()),
  2166. [this, upscaled, clipped](const tbb::blocked_range<size_t>& range) {
  2167. ExPolygons expolygons_first_layer;
  2168. for (size_t layer_id = range.begin(); layer_id < range.end(); ++ layer_id) {
  2169. m_print->throw_if_canceled();
  2170. Layer *layer = m_layers[layer_id];
  2171. // Apply size compensation and perform clipping of multi-part objects.
  2172. float outter_delta = float(scale_(m_config.xy_size_compensation.value));
  2173. float inner_delta = float(scale_(m_config.xy_inner_size_compensation.value));
  2174. float hole_delta = inner_delta + float(scale_(m_config.hole_size_compensation.value));
  2175. //FIXME only apply the compensation if no raft is enabled.
  2176. float first_layer_compensation = 0.f;
  2177. if (layer_id == 0 && m_config.raft_layers == 0 && m_config.first_layer_size_compensation.value != 0) {
  2178. // Only enable Elephant foot compensation if printing directly on the print bed.
  2179. first_layer_compensation = float(scale_(m_config.first_layer_size_compensation.value));
  2180. if (first_layer_compensation > 0) {
  2181. outter_delta += first_layer_compensation;
  2182. inner_delta += first_layer_compensation;
  2183. hole_delta += first_layer_compensation;
  2184. first_layer_compensation = 0;
  2185. }
  2186. else {
  2187. float min_delta = std::min(outter_delta, std::min(inner_delta, hole_delta));
  2188. if (min_delta > 0) {
  2189. if (-first_layer_compensation < min_delta) {
  2190. outter_delta += first_layer_compensation;
  2191. inner_delta += first_layer_compensation;
  2192. hole_delta += first_layer_compensation;
  2193. first_layer_compensation = 0;
  2194. } else {
  2195. first_layer_compensation += min_delta;
  2196. outter_delta -= min_delta;
  2197. inner_delta -= min_delta;
  2198. hole_delta -= min_delta;
  2199. }
  2200. }
  2201. }
  2202. }
  2203. // Optimized version for a single region layer.
  2204. if (layer->regions().size() == 1) {
  2205. assert(!upscaled);
  2206. assert(!clipped);
  2207. // Single region, growing or shrinking.
  2208. LayerRegion *layerm = layer->regions().front();
  2209. ExPolygons expolygons = to_expolygons(std::move(layerm->m_slices.surfaces));
  2210. // Apply all three main XY compensation.
  2211. if (hole_delta > 0 || inner_delta > 0 || outter_delta > 0) {
  2212. expolygons = _shrink_contour_holes(std::max(0.f, outter_delta), std::max(0.f, inner_delta), std::max(0.f, hole_delta), expolygons);
  2213. if (layer_id == 0 && first_layer_compensation != 0)
  2214. expolygons_first_layer = expolygons;
  2215. }
  2216. // Apply the elephant foot compensation.
  2217. if (layer_id == 0 && first_layer_compensation != 0.f) {
  2218. expolygons = union_ex(Slic3r::elephant_foot_compensation(expolygons, layerm->flow(frExternalPerimeter),
  2219. unscale<double>(-first_layer_compensation)));
  2220. }
  2221. // Apply all three main negative XY compensation.
  2222. if (hole_delta < 0 || inner_delta < 0 || outter_delta < 0) {
  2223. expolygons = _shrink_contour_holes(std::min(0.f, outter_delta), std::min(0.f, inner_delta), std::min(0.f, hole_delta), expolygons);
  2224. if (layer_id == 0 && first_layer_compensation != 0)
  2225. expolygons_first_layer = _shrink_contour_holes(std::min(0.f, outter_delta), std::min(0.f, inner_delta), std::min(0.f, hole_delta), expolygons_first_layer);
  2226. }
  2227. if (layer->regions().front()->region()->config().curve_smoothing_precision > 0.f) {
  2228. //smoothing
  2229. expolygons = _smooth_curves(expolygons, layer->regions().front()->region()->config());
  2230. if (layer_id == 0 && first_layer_compensation != 0)
  2231. expolygons_first_layer = _smooth_curves(expolygons_first_layer, layer->regions().front()->region()->config());
  2232. }
  2233. layerm->m_slices.set(std::move(expolygons), stPosInternal | stDensSparse);
  2234. } else {
  2235. float max_growth = std::max(hole_delta, std::max(inner_delta, outter_delta));
  2236. float min_growth = std::min(hole_delta, std::min(inner_delta, outter_delta));
  2237. bool clip = /*! clipped && ??? */ m_config.clip_multipart_objects.value;
  2238. ExPolygons merged_poly_for_holes_growing;
  2239. if (max_growth > 0) {
  2240. //merge polygons because region can cut "holes".
  2241. //then, cut them to give them again later to their region
  2242. merged_poly_for_holes_growing = layer->merged(float(SCALED_EPSILON));
  2243. merged_poly_for_holes_growing = _shrink_contour_holes(std::max(0.f, outter_delta), std::max(0.f, inner_delta), std::max(0.f, hole_delta), union_ex(merged_poly_for_holes_growing));
  2244. }
  2245. if (clip || max_growth > 0) {
  2246. // Multiple regions, growing or just clipping one region by the other.
  2247. // When clipping the regions, priority is given to the first regions.
  2248. Polygons processed;
  2249. for (size_t region_id = 0; region_id < layer->regions().size(); ++ region_id) {
  2250. LayerRegion *layerm = layer->regions()[region_id];
  2251. ExPolygons slices = to_expolygons(std::move(layerm->slices().surfaces));
  2252. if (max_growth > 0.f) {
  2253. slices = intersection_ex(offset_ex(slices, max_growth), merged_poly_for_holes_growing);
  2254. }
  2255. // Apply the first_layer_compensation if >0.
  2256. if (layer_id == 0 && first_layer_compensation > 0)
  2257. slices = offset_ex(std::move(slices), std::max(first_layer_compensation, 0.f));
  2258. //smoothing
  2259. if (layerm->region()->config().curve_smoothing_precision > 0.f)
  2260. slices = _smooth_curves(slices, layerm->region()->config());
  2261. // Trim by the slices of already processed regions.
  2262. if (region_id > 0 && clip)
  2263. slices = diff_ex(to_polygons(std::move(slices)), processed);
  2264. if (clip && (region_id + 1 < layer->regions().size()))
  2265. // Collect the already processed regions to trim the to be processed regions.
  2266. polygons_append(processed, slices);
  2267. layerm->m_slices.set(std::move(slices), stPosInternal | stDensSparse);
  2268. }
  2269. }
  2270. if (min_growth < 0.f || first_layer_compensation != 0.f) {
  2271. // Apply the negative XY compensation. (the ones that is <0)
  2272. ExPolygons trimming;
  2273. static const float eps = float(scale_(m_config.slice_closing_radius.value) * 1.5);
  2274. if (layer_id == 0 && first_layer_compensation < 0.f) {
  2275. expolygons_first_layer = offset_ex(layer->merged(eps), - eps);
  2276. trimming = Slic3r::elephant_foot_compensation(expolygons_first_layer,
  2277. layer->regions().front()->flow(frExternalPerimeter), unscale<double>(-first_layer_compensation));
  2278. }
  2279. else {
  2280. trimming = layer->merged(float(SCALED_EPSILON));
  2281. }
  2282. if (min_growth < 0)
  2283. trimming = _shrink_contour_holes(std::min(0.f, outter_delta), std::min(0.f, inner_delta), std::min(0.f, hole_delta), trimming);
  2284. //trim surfaces
  2285. for (size_t region_id = 0; region_id < layer->regions().size(); ++region_id) {
  2286. layer->regions()[region_id]->trim_surfaces(to_polygons(trimming));
  2287. }
  2288. }
  2289. }
  2290. // Merge all regions' slices to get islands, chain them by a shortest path.
  2291. layer->make_slices();
  2292. //FIXME: can't make it work in multi-region object, it seems useful to avoid bridge on top of first layer compensation
  2293. //so it's disable, if you want an offset, use the offset field.
  2294. //if (layer->regions().size() == 1 && layer_id == 0 && first_layer_compensation < 0 && m_config.raft_layers == 0) {
  2295. // // The Elephant foot has been compensated, therefore the 1st layer's lslices are shrank with the Elephant foot compensation value.
  2296. // // Store the uncompensated value there.
  2297. // assert(! m_layers.empty());
  2298. // assert(m_layers.front()->id() == 0);
  2299. // m_layers.front()->lslices = offset_ex(std::move(m_layers.front()->lslices), -first_layer_compensation);
  2300. //}
  2301. }
  2302. });
  2303. }
  2304. m_print->throw_if_canceled();
  2305. BOOST_LOG_TRIVIAL(debug) << "Slicing objects - make_slices in parallel - end";
  2306. }
  2307. ExPolygons PrintObject::_shrink_contour_holes(double contour_delta, double default_delta, double convex_delta, const ExPolygons& polys) const {
  2308. ExPolygons new_ex_polys;
  2309. for (const ExPolygon& ex_poly : polys) {
  2310. Polygons contours;
  2311. Polygons holes;
  2312. for (const Polygon& hole : ex_poly.holes) {
  2313. //check if convex to reduce it
  2314. // check whether first point forms a convex angle
  2315. //note: we allow a deviation of 5.7° (0.01rad = 0.57°)
  2316. bool ok = true;
  2317. ok = (hole.points.front().ccw_angle(hole.points.back(), *(hole.points.begin() + 1)) <= PI + 0.1);
  2318. // check whether points 1..(n-1) form convex angles
  2319. if (ok)
  2320. for (Points::const_iterator p = hole.points.begin() + 1; p != hole.points.end() - 1; ++p) {
  2321. ok = (p->ccw_angle(*(p - 1), *(p + 1)) <= PI + 0.1);
  2322. if (!ok) break;
  2323. }
  2324. // check whether last point forms a convex angle
  2325. ok &= (hole.points.back().ccw_angle(*(hole.points.end() - 2), hole.points.front()) <= PI + 0.1);
  2326. if (ok) {
  2327. if (convex_delta != 0) {
  2328. for (Polygon &newHole : offset(hole, -convex_delta)) {
  2329. newHole.make_counter_clockwise();
  2330. holes.emplace_back(std::move(newHole));
  2331. }
  2332. } else {
  2333. holes.push_back(hole);
  2334. holes.back().make_counter_clockwise();
  2335. }
  2336. } else {
  2337. if (default_delta != 0) {
  2338. for (Polygon &newHole : offset(hole, -default_delta)) {
  2339. newHole.make_counter_clockwise();
  2340. holes.emplace_back(std::move(newHole));
  2341. }
  2342. } else {
  2343. holes.push_back(hole);
  2344. holes.back().make_counter_clockwise();
  2345. }
  2346. }
  2347. }
  2348. //modify contour
  2349. if (contour_delta != 0) {
  2350. Polygons new_contours = offset(ex_poly.contour, contour_delta);
  2351. if (new_contours.size() == 0)
  2352. continue;
  2353. contours.insert(contours.end(), std::make_move_iterator(new_contours.begin()), std::make_move_iterator(new_contours.end()));
  2354. } else {
  2355. contours.push_back(ex_poly.contour);
  2356. }
  2357. ExPolygons temp = diff_ex(union_(contours), union_(holes));
  2358. new_ex_polys.insert(new_ex_polys.end(), std::make_move_iterator(temp.begin()), std::make_move_iterator(temp.end()));
  2359. }
  2360. return union_ex(new_ex_polys);
  2361. }
  2362. /// max angle: you ahve to be lwer than that to divide it. PI => all accepted
  2363. /// min angle: don't smooth sharp angles! 0 => all accepted
  2364. /// cutoff_dist: maximum dist between two point to add new points
  2365. /// max dist : maximum distance between two pointsd, where we add new points
  2366. Polygon _smooth_curve(Polygon &p, double max_angle, double min_angle_convex, double min_angle_concave, coord_t cutoff_dist, coord_t max_dist){
  2367. if (p.size() < 4) return p;
  2368. Polygon pout;
  2369. //duplicate points to simplify the loop
  2370. p.points.insert(p.points.end(), p.points.begin(), p.points.begin() + 3);
  2371. for (size_t idx = 1; idx<p.size() - 2; idx++){
  2372. //put first point
  2373. pout.points.push_back(p[idx]);
  2374. //get angles
  2375. double angle1 = p[idx].ccw_angle(p.points[idx - 1], p.points[idx + 1]);
  2376. bool angle1_concave = true;
  2377. if (angle1 > PI) {
  2378. angle1 = 2 * PI - angle1;
  2379. angle1_concave = false;
  2380. }
  2381. double angle2 = p[idx + 1].ccw_angle(p.points[idx], p.points[idx + 2]);
  2382. bool angle2_concave = true;
  2383. if (angle2 > PI) {
  2384. angle2 = 2 * PI - angle2;
  2385. angle2_concave = false;
  2386. }
  2387. //filters
  2388. bool angle1_ok = angle1_concave ? angle1 >= min_angle_concave : angle1 >= min_angle_convex;
  2389. bool angle2_ok = angle2_concave ? angle2 >= min_angle_concave : angle2 >= min_angle_convex;
  2390. if (!angle1_ok && !angle2_ok) continue;
  2391. if (angle1 > max_angle && angle2 > max_angle) continue;
  2392. if (cutoff_dist > 0 && p.points[idx].distance_to(p.points[idx+1]) > cutoff_dist) continue;
  2393. // add points, but how many?
  2394. coordf_t dist = p[idx].distance_to(p[idx + 1]);
  2395. int nb_add = dist / max_dist;
  2396. if (max_angle < PI) {
  2397. int nb_add_per_angle = std::max((PI - angle1) / (PI - max_angle), (PI - angle2) / (PI - max_angle));
  2398. nb_add = std::min(nb_add, nb_add_per_angle);
  2399. }
  2400. if (nb_add == 0) continue;
  2401. //création des points de controles
  2402. Vec2d vec_ab = (p[idx] - p[idx - 1]).cast<double>();
  2403. Vec2d vec_bc = (p[idx + 1] - p[idx]).cast<double>();
  2404. Vec2d vec_cb = (p[idx] - p[idx + 1]).cast<double>();
  2405. Vec2d vec_dc = (p[idx + 1] - p[idx + 2]).cast<double>();
  2406. vec_ab.normalize();
  2407. vec_bc.normalize();
  2408. vec_cb.normalize();
  2409. vec_dc.normalize();
  2410. Vec2d vec_b_tang = vec_ab + vec_bc;
  2411. vec_b_tang.normalize();
  2412. //should be 0.55 / 1.414 = ~0.39 to create a true circle from a square (90°)
  2413. // it's ~0.36 for exagon (120°)
  2414. // it's ~0.34 for octogon (135°)
  2415. vec_b_tang *= dist * (0.31 + 0.12 * (1-(angle1 / PI)));
  2416. Vec2d vec_c_tang = vec_dc + vec_cb;
  2417. vec_c_tang.normalize();
  2418. vec_c_tang *= dist * (0.31 + 0.12 * (1 - (angle2 / PI)));
  2419. Point bp = p[idx] + ((!angle1_ok) ? vec_bc.cast<coord_t>() : vec_b_tang.cast<coord_t>());
  2420. Point cp = p[idx + 1] + ((!angle2_ok) ? vec_cb.cast<coord_t>() : vec_c_tang.cast<coord_t>());
  2421. for (int idx_np = 0; idx_np < nb_add; idx_np++){
  2422. const float percent_np = (idx_np + 1) / (float)(nb_add + 1);
  2423. const float inv_percent_np = 1 - percent_np;
  2424. pout.points.emplace_back();
  2425. Point &new_p = pout.points.back();
  2426. const float coeff0 = inv_percent_np * inv_percent_np * inv_percent_np;
  2427. const float coeff1 = percent_np * inv_percent_np * inv_percent_np;
  2428. const float coeff2 = percent_np * percent_np * inv_percent_np;
  2429. const float coeff3 = percent_np * percent_np * percent_np;
  2430. new_p.x() = (p[idx].x() * coeff0)
  2431. + (3 * bp.x() * coeff1)
  2432. + (3 * cp.x() * coeff2)
  2433. + (p[idx + 1].x() * coeff3);
  2434. new_p.y() = (p[idx].y() * coeff0)
  2435. + (3 * bp.y() * coeff1)
  2436. + (3 * cp.y() * coeff2)
  2437. + (p[idx + 1].y() * coeff3);
  2438. }
  2439. }
  2440. return pout;
  2441. }
  2442. ExPolygons PrintObject::_smooth_curves(const ExPolygons & input, const PrintRegionConfig &conf) const {
  2443. ExPolygons new_polys;
  2444. for (const ExPolygon &ex_poly : input) {
  2445. ExPolygon new_ex_poly(ex_poly);
  2446. new_ex_poly.contour.remove_collinear(SCALED_RESOLUTION);
  2447. new_ex_poly.contour = _smooth_curve(new_ex_poly.contour, PI,
  2448. conf.curve_smoothing_angle_convex.value*PI / 180.0,
  2449. conf.curve_smoothing_angle_concave.value*PI / 180.0,
  2450. scale_(conf.curve_smoothing_cutoff_dist.value),
  2451. scale_(conf.curve_smoothing_precision.value));
  2452. for (Polygon &phole : new_ex_poly.holes){
  2453. phole.reverse(); // make_counter_clockwise();
  2454. phole.remove_collinear(SCALED_RESOLUTION);
  2455. phole = _smooth_curve(phole, PI,
  2456. conf.curve_smoothing_angle_convex.value*PI / 180.0,
  2457. conf.curve_smoothing_angle_concave.value*PI / 180.0,
  2458. scale_(conf.curve_smoothing_cutoff_dist.value),
  2459. scale_(conf.curve_smoothing_precision.value));
  2460. phole.reverse(); // make_clockwise();
  2461. }
  2462. new_polys.push_back(new_ex_poly);
  2463. }
  2464. return new_polys;
  2465. }
  2466. // To be used only if there are no layer span specific configurations applied, which would lead to z ranges being generated for this region.
  2467. std::vector<ExPolygons> PrintObject::slice_region(size_t region_id, const std::vector<float> &z, SlicingMode mode) const
  2468. {
  2469. std::vector<const ModelVolume*> volumes;
  2470. if (region_id < this->region_volumes.size()) {
  2471. for (const std::pair<t_layer_height_range, int> &volume_and_range : this->region_volumes[region_id]) {
  2472. const ModelVolume *volume = this->model_object()->volumes[volume_and_range.second];
  2473. if (volume->is_model_part())
  2474. volumes.emplace_back(volume);
  2475. }
  2476. }
  2477. return this->slice_volumes(z, mode, volumes);
  2478. }
  2479. // Z ranges are not applicable to modifier meshes, therefore a sinle volume will be found in volume_and_range at most once.
  2480. std::vector<ExPolygons> PrintObject::slice_modifiers(size_t region_id, const std::vector<float> &slice_zs) const
  2481. {
  2482. std::vector<ExPolygons> out;
  2483. if (region_id < this->region_volumes.size())
  2484. {
  2485. std::vector<std::vector<t_layer_height_range>> volume_ranges;
  2486. const std::vector<std::pair<t_layer_height_range, int>> &volumes_and_ranges = this->region_volumes[region_id];
  2487. volume_ranges.reserve(volumes_and_ranges.size());
  2488. for (size_t i = 0; i < volumes_and_ranges.size(); ) {
  2489. int volume_id = volumes_and_ranges[i].second;
  2490. const ModelVolume *model_volume = this->model_object()->volumes[volume_id];
  2491. if (model_volume->is_modifier()) {
  2492. std::vector<t_layer_height_range> ranges;
  2493. ranges.emplace_back(volumes_and_ranges[i].first);
  2494. size_t j = i + 1;
  2495. for (; j < volumes_and_ranges.size() && volume_id == volumes_and_ranges[j].second; ++ j) {
  2496. if (! ranges.empty() && std::abs(ranges.back().second - volumes_and_ranges[j].first.first) < EPSILON)
  2497. ranges.back().second = volumes_and_ranges[j].first.second;
  2498. else
  2499. ranges.emplace_back(volumes_and_ranges[j].first);
  2500. }
  2501. volume_ranges.emplace_back(std::move(ranges));
  2502. i = j;
  2503. } else
  2504. ++ i;
  2505. }
  2506. if (! volume_ranges.empty())
  2507. {
  2508. bool equal_ranges = true;
  2509. for (size_t i = 1; i < volume_ranges.size(); ++ i) {
  2510. assert(! volume_ranges[i].empty());
  2511. if (volume_ranges.front() != volume_ranges[i]) {
  2512. equal_ranges = false;
  2513. break;
  2514. }
  2515. }
  2516. if (equal_ranges && volume_ranges.front().size() == 1 && volume_ranges.front().front() == t_layer_height_range(0, DBL_MAX)) {
  2517. // No modifier in this region was split to layer spans.
  2518. std::vector<const ModelVolume*> volumes;
  2519. for (const std::pair<t_layer_height_range, int> &volume_and_range : this->region_volumes[region_id]) {
  2520. const ModelVolume *volume = this->model_object()->volumes[volume_and_range.second];
  2521. if (volume->is_modifier())
  2522. volumes.emplace_back(volume);
  2523. }
  2524. out = this->slice_volumes(slice_zs, SlicingMode::Regular, volumes);
  2525. } else {
  2526. // Some modifier in this region was split to layer spans.
  2527. std::vector<char> merge;
  2528. for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) {
  2529. const std::vector<std::pair<t_layer_height_range, int>> &volumes_and_ranges = this->region_volumes[region_id];
  2530. for (size_t i = 0; i < volumes_and_ranges.size(); ) {
  2531. int volume_id = volumes_and_ranges[i].second;
  2532. const ModelVolume *model_volume = this->model_object()->volumes[volume_id];
  2533. if (model_volume->is_modifier()) {
  2534. BOOST_LOG_TRIVIAL(debug) << "Slicing modifiers - volume " << volume_id;
  2535. // Find the ranges of this volume. Ranges in volumes_and_ranges must not overlap for a single volume.
  2536. std::vector<t_layer_height_range> ranges;
  2537. ranges.emplace_back(volumes_and_ranges[i].first);
  2538. size_t j = i + 1;
  2539. for (; j < volumes_and_ranges.size() && volume_id == volumes_and_ranges[j].second; ++ j)
  2540. ranges.emplace_back(volumes_and_ranges[j].first);
  2541. // slicing in parallel
  2542. std::vector<ExPolygons> this_slices = this->slice_volume(slice_zs, ranges, SlicingMode::Regular, *model_volume);
  2543. if (out.empty()) {
  2544. out = std::move(this_slices);
  2545. merge.assign(out.size(), false);
  2546. } else {
  2547. for (size_t i = 0; i < out.size(); ++ i)
  2548. if (! this_slices[i].empty()) {
  2549. if (! out[i].empty()) {
  2550. append(out[i], this_slices[i]);
  2551. merge[i] = true;
  2552. } else
  2553. out[i] = std::move(this_slices[i]);
  2554. }
  2555. }
  2556. i = j;
  2557. } else
  2558. ++ i;
  2559. }
  2560. }
  2561. for (size_t i = 0; i < merge.size(); ++ i)
  2562. if (merge[i])
  2563. out[i] = union_ex(out[i]);
  2564. }
  2565. }
  2566. }
  2567. return out;
  2568. }
  2569. std::vector<ExPolygons> PrintObject::slice_support_volumes(const ModelVolumeType &model_volume_type) const
  2570. {
  2571. std::vector<const ModelVolume*> volumes;
  2572. for (const ModelVolume *volume : this->model_object()->volumes)
  2573. if (volume->type() == model_volume_type)
  2574. volumes.emplace_back(volume);
  2575. std::vector<float> zs;
  2576. zs.reserve(this->layers().size());
  2577. for (const Layer *l : this->layers())
  2578. zs.emplace_back((float)l->slice_z);
  2579. return this->slice_volumes(zs, SlicingMode::Regular, volumes);
  2580. }
  2581. std::vector<ExPolygons> PrintObject::slice_volumes(const std::vector<float> &z, SlicingMode mode, const std::vector<const ModelVolume*> &volumes) const
  2582. {
  2583. std::vector<ExPolygons> layers;
  2584. if (! volumes.empty()) {
  2585. // Compose mesh.
  2586. //FIXME better to perform slicing over each volume separately and then to use a Boolean operation to merge them.
  2587. TriangleMesh mesh(volumes.front()->mesh());
  2588. mesh.transform(volumes.front()->get_matrix(), true);
  2589. assert(mesh.repaired);
  2590. if (volumes.size() == 1 && mesh.repaired) {
  2591. //FIXME The admesh repair function may break the face connectivity, rather refresh it here as the slicing code relies on it.
  2592. stl_check_facets_exact(&mesh.stl);
  2593. }
  2594. for (size_t idx_volume = 1; idx_volume < volumes.size(); ++ idx_volume) {
  2595. const ModelVolume &model_volume = *volumes[idx_volume];
  2596. TriangleMesh vol_mesh(model_volume.mesh());
  2597. vol_mesh.transform(model_volume.get_matrix(), true);
  2598. mesh.merge(vol_mesh);
  2599. }
  2600. if (mesh.stl.stats.number_of_facets > 0) {
  2601. mesh.transform(m_trafo, true);
  2602. // apply XY shift
  2603. mesh.translate(- unscale<float>(m_center_offset.x()), - unscale<float>(m_center_offset.y()), 0);
  2604. // perform actual slicing
  2605. const Print *print = this->print();
  2606. auto callback = TriangleMeshSlicer::throw_on_cancel_callback_type([print](){print->throw_if_canceled();});
  2607. // TriangleMeshSlicer needs shared vertices, also this calls the repair() function.
  2608. mesh.require_shared_vertices();
  2609. TriangleMeshSlicer mslicer(float(m_config.slice_closing_radius.value), float(m_config.model_precision.value));
  2610. mslicer.init(&mesh, callback);
  2611. mslicer.slice(z, mode, &layers, callback);
  2612. m_print->throw_if_canceled();
  2613. }
  2614. }
  2615. return layers;
  2616. }
  2617. std::vector<ExPolygons> PrintObject::slice_volume(const std::vector<float> &z, SlicingMode mode, const ModelVolume &volume) const
  2618. {
  2619. std::vector<ExPolygons> layers;
  2620. if (! z.empty()) {
  2621. // Compose mesh.
  2622. //FIXME better to split the mesh into separate shells, perform slicing over each shell separately and then to use a Boolean operation to merge them.
  2623. TriangleMesh mesh(volume.mesh());
  2624. mesh.transform(volume.get_matrix(), true);
  2625. if (mesh.repaired) {
  2626. //FIXME The admesh repair function may break the face connectivity, rather refresh it here as the slicing code relies on it.
  2627. stl_check_facets_exact(&mesh.stl);
  2628. }
  2629. if (mesh.stl.stats.number_of_facets > 0) {
  2630. mesh.transform(m_trafo, true);
  2631. // apply XY shift
  2632. mesh.translate(- unscale<float>(m_center_offset.x()), - unscale<float>(m_center_offset.y()), 0);
  2633. // perform actual slicing
  2634. TriangleMeshSlicer mslicer(float(m_config.slice_closing_radius.value), float(m_config.model_precision.value));
  2635. const Print *print = this->print();
  2636. auto callback = TriangleMeshSlicer::throw_on_cancel_callback_type([print](){print->throw_if_canceled();});
  2637. // TriangleMeshSlicer needs the shared vertices.
  2638. mesh.require_shared_vertices();
  2639. mslicer.init(&mesh, callback);
  2640. mslicer.slice(z, mode, &layers, callback);
  2641. m_print->throw_if_canceled();
  2642. }
  2643. }
  2644. return layers;
  2645. }
  2646. // Filter the zs not inside the ranges. The ranges are closed at the botton and open at the top, they are sorted lexicographically and non overlapping.
  2647. std::vector<ExPolygons> PrintObject::slice_volume(const std::vector<float> &z, const std::vector<t_layer_height_range> &ranges, SlicingMode mode, const ModelVolume &volume) const
  2648. {
  2649. std::vector<ExPolygons> out;
  2650. if (! z.empty() && ! ranges.empty()) {
  2651. if (ranges.size() == 1 && z.front() >= ranges.front().first && z.back() < ranges.front().second) {
  2652. // All layers fit into a single range.
  2653. out = this->slice_volume(z, mode, volume);
  2654. } else {
  2655. std::vector<float> z_filtered;
  2656. std::vector<std::pair<size_t, size_t>> n_filtered;
  2657. z_filtered.reserve(z.size());
  2658. n_filtered.reserve(2 * ranges.size());
  2659. size_t i = 0;
  2660. for (const t_layer_height_range &range : ranges) {
  2661. for (; i < z.size() && z[i] < range.first; ++ i) ;
  2662. size_t first = i;
  2663. for (; i < z.size() && z[i] < range.second; ++ i)
  2664. z_filtered.emplace_back(z[i]);
  2665. if (i > first)
  2666. n_filtered.emplace_back(std::make_pair(first, i));
  2667. }
  2668. if (! n_filtered.empty()) {
  2669. std::vector<ExPolygons> layers = this->slice_volume(z_filtered, mode, volume);
  2670. out.assign(z.size(), ExPolygons());
  2671. i = 0;
  2672. for (const std::pair<size_t, size_t> &span : n_filtered)
  2673. for (size_t j = span.first; j < span.second; ++ j)
  2674. out[j] = std::move(layers[i ++]);
  2675. }
  2676. }
  2677. }
  2678. return out;
  2679. }
  2680. std::string PrintObject::_fix_slicing_errors()
  2681. {
  2682. // Collect layers with slicing errors.
  2683. // These layers will be fixed in parallel.
  2684. std::vector<size_t> buggy_layers;
  2685. buggy_layers.reserve(m_layers.size());
  2686. for (size_t idx_layer = 0; idx_layer < m_layers.size(); ++ idx_layer)
  2687. if (m_layers[idx_layer]->slicing_errors)
  2688. buggy_layers.push_back(idx_layer);
  2689. BOOST_LOG_TRIVIAL(debug) << "Slicing objects - fixing slicing errors in parallel - begin";
  2690. tbb::parallel_for(
  2691. tbb::blocked_range<size_t>(0, buggy_layers.size()),
  2692. [this, &buggy_layers](const tbb::blocked_range<size_t>& range) {
  2693. for (size_t buggy_layer_idx = range.begin(); buggy_layer_idx < range.end(); ++ buggy_layer_idx) {
  2694. m_print->throw_if_canceled();
  2695. size_t idx_layer = buggy_layers[buggy_layer_idx];
  2696. Layer *layer = m_layers[idx_layer];
  2697. assert(layer->slicing_errors);
  2698. // Try to repair the layer surfaces by merging all contours and all holes from neighbor layers.
  2699. // BOOST_LOG_TRIVIAL(trace) << "Attempting to repair layer" << idx_layer;
  2700. for (size_t region_id = 0; region_id < layer->m_regions.size(); ++ region_id) {
  2701. LayerRegion *layerm = layer->m_regions[region_id];
  2702. // Find the first valid layer below / above the current layer.
  2703. const Surfaces *upper_surfaces = nullptr;
  2704. const Surfaces *lower_surfaces = nullptr;
  2705. for (size_t j = idx_layer + 1; j < m_layers.size(); ++ j)
  2706. if (! m_layers[j]->slicing_errors) {
  2707. upper_surfaces = &m_layers[j]->regions()[region_id]->slices().surfaces;
  2708. break;
  2709. }
  2710. for (int j = int(idx_layer) - 1; j >= 0; -- j)
  2711. if (! m_layers[j]->slicing_errors) {
  2712. lower_surfaces = &m_layers[j]->regions()[region_id]->slices().surfaces;
  2713. break;
  2714. }
  2715. // Collect outer contours and holes from the valid layers above & below.
  2716. Polygons outer;
  2717. outer.reserve(
  2718. ((upper_surfaces == nullptr) ? 0 : upper_surfaces->size()) +
  2719. ((lower_surfaces == nullptr) ? 0 : lower_surfaces->size()));
  2720. size_t num_holes = 0;
  2721. if (upper_surfaces)
  2722. for (const auto &surface : *upper_surfaces) {
  2723. outer.push_back(surface.expolygon.contour);
  2724. num_holes += surface.expolygon.holes.size();
  2725. }
  2726. if (lower_surfaces)
  2727. for (const auto &surface : *lower_surfaces) {
  2728. outer.push_back(surface.expolygon.contour);
  2729. num_holes += surface.expolygon.holes.size();
  2730. }
  2731. Polygons holes;
  2732. holes.reserve(num_holes);
  2733. if (upper_surfaces)
  2734. for (const auto &surface : *upper_surfaces)
  2735. polygons_append(holes, surface.expolygon.holes);
  2736. if (lower_surfaces)
  2737. for (const auto &surface : *lower_surfaces)
  2738. polygons_append(holes, surface.expolygon.holes);
  2739. layerm->m_slices.set(diff_ex(union_(outer), holes, false), stPosInternal | stDensSparse);
  2740. }
  2741. // Update layer slices after repairing the single regions.
  2742. layer->make_slices();
  2743. }
  2744. });
  2745. m_print->throw_if_canceled();
  2746. BOOST_LOG_TRIVIAL(debug) << "Slicing objects - fixing slicing errors in parallel - end";
  2747. // remove empty layers from bottom
  2748. while (! m_layers.empty() && (m_layers.front()->lslices.empty() || m_layers.front()->empty())) {
  2749. delete m_layers.front();
  2750. m_layers.erase(m_layers.begin());
  2751. m_layers.front()->lower_layer = nullptr;
  2752. for (size_t i = 0; i < m_layers.size(); ++ i)
  2753. m_layers[i]->set_id(m_layers[i]->id() - 1);
  2754. }
  2755. return buggy_layers.empty() ? "" :
  2756. "The model has overlapping or self-intersecting facets. I tried to repair it, "
  2757. "however you might want to check the results or repair the input file and retry.\n";
  2758. }
  2759. // Simplify the sliced model, if "resolution" configuration parameter > 0.
  2760. // The simplification is problematic, because it simplifies the slices independent from each other,
  2761. // which makes the simplified discretization visible on the object surface.
  2762. void PrintObject::simplify_slices(coord_t distance)
  2763. {
  2764. BOOST_LOG_TRIVIAL(debug) << "Slicing objects - siplifying slices in parallel - begin";
  2765. tbb::parallel_for(
  2766. tbb::blocked_range<size_t>(0, m_layers.size()),
  2767. [this, distance](const tbb::blocked_range<size_t>& range) {
  2768. for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx) {
  2769. m_print->throw_if_canceled();
  2770. Layer *layer = m_layers[layer_idx];
  2771. for (size_t region_idx = 0; region_idx < layer->m_regions.size(); ++ region_idx)
  2772. layer->m_regions[region_idx]->m_slices.simplify(distance);
  2773. {
  2774. ExPolygons simplified;
  2775. for (const ExPolygon &expoly : layer->lslices)
  2776. expoly.simplify(distance, &simplified);
  2777. layer->lslices = std::move(simplified);
  2778. }
  2779. }
  2780. });
  2781. BOOST_LOG_TRIVIAL(debug) << "Slicing objects - siplifying slices in parallel - end";
  2782. }
  2783. // Only active if config->infill_only_where_needed. This step trims the sparse infill,
  2784. // so it acts as an internal support. It maintains all other infill types intact.
  2785. // Here the internal surfaces and perimeters have to be supported by the sparse infill.
  2786. //FIXME The surfaces are supported by a sparse infill, but the sparse infill is only as large as the area to support.
  2787. // Likely the sparse infill will not be anchored correctly, so it will not work as intended.
  2788. // Also one wishes the perimeters to be supported by a full infill.
  2789. // Idempotence of this method is guaranteed by the fact that we don't remove things from
  2790. // fill_surfaces but we only turn them into VOID surfaces, thus preserving the boundaries.
  2791. void PrintObject::clip_fill_surfaces()
  2792. {
  2793. if (! m_config.infill_only_where_needed.value ||
  2794. ! std::any_of(this->print()->regions().begin(), this->print()->regions().end(),
  2795. [](const PrintRegion *region) { return region->config().fill_density > 0; }))
  2796. return;
  2797. // We only want infill under ceilings; this is almost like an
  2798. // internal support material.
  2799. // Proceed top-down, skipping the bottom layer.
  2800. Polygons upper_internal;
  2801. for (int layer_id = int(m_layers.size()) - 1; layer_id > 0; -- layer_id) {
  2802. Layer *layer = m_layers[layer_id];
  2803. Layer *lower_layer = m_layers[layer_id - 1];
  2804. // Detect things that we need to support.
  2805. // Cummulative slices.
  2806. Polygons slices;
  2807. polygons_append(slices, layer->lslices);
  2808. // Cummulative fill surfaces.
  2809. Polygons fill_surfaces;
  2810. // Solid surfaces to be supported.
  2811. Polygons overhangs;
  2812. for (const LayerRegion *layerm : layer->m_regions)
  2813. for (const Surface &surface : layerm->fill_surfaces.surfaces) {
  2814. Polygons polygons = to_polygons(surface.expolygon);
  2815. if (surface.has_fill_solid())
  2816. polygons_append(overhangs, polygons);
  2817. polygons_append(fill_surfaces, std::move(polygons));
  2818. }
  2819. Polygons lower_layer_fill_surfaces;
  2820. Polygons lower_layer_internal_surfaces;
  2821. for (const LayerRegion *layerm : lower_layer->m_regions)
  2822. for (const Surface &surface : layerm->fill_surfaces.surfaces) {
  2823. Polygons polygons = to_polygons(surface.expolygon);
  2824. if (surface.has_pos_internal() && (surface.has_fill_sparse() || surface.has_fill_void()) )
  2825. polygons_append(lower_layer_internal_surfaces, polygons);
  2826. polygons_append(lower_layer_fill_surfaces, std::move(polygons));
  2827. }
  2828. // We also need to support perimeters when there's at least one full unsupported loop
  2829. {
  2830. // Get perimeters area as the difference between slices and fill_surfaces
  2831. // Only consider the area that is not supported by lower perimeters
  2832. Polygons perimeters = intersection(diff(slices, fill_surfaces), lower_layer_fill_surfaces);
  2833. // Only consider perimeter areas that are at least one extrusion width thick.
  2834. //FIXME Offset2 eats out from both sides, while the perimeters are create outside in.
  2835. //Should the pw not be half of the current value?
  2836. float pw = FLT_MAX;
  2837. for (const LayerRegion *layerm : layer->m_regions)
  2838. pw = std::min(pw, (float)layerm->flow(frPerimeter).scaled_width());
  2839. // Append such thick perimeters to the areas that need support
  2840. polygons_append(overhangs, offset2(perimeters, -pw, +pw));
  2841. }
  2842. // Find new internal infill.
  2843. polygons_append(overhangs, std::move(upper_internal));
  2844. upper_internal = intersection(overhangs, lower_layer_internal_surfaces);
  2845. // Apply new internal infill to regions.
  2846. for (LayerRegion *layerm : lower_layer->m_regions) {
  2847. if (layerm->region()->config().fill_density.value == 0)
  2848. continue;
  2849. SurfaceType internal_surface_types[] = { stPosInternal | stDensSparse, stPosInternal | stDensVoid };
  2850. Polygons internal;
  2851. for (Surface &surface : layerm->fill_surfaces.surfaces)
  2852. if (surface.has_pos_internal() && (surface.has_fill_sparse() || surface.has_fill_void()))
  2853. polygons_append(internal, std::move(surface.expolygon));
  2854. layerm->fill_surfaces.remove_types(internal_surface_types, 2);
  2855. layerm->fill_surfaces.append(intersection_ex(internal, upper_internal, true), stPosInternal | stDensSparse);
  2856. layerm->fill_surfaces.append(diff_ex (internal, upper_internal, true), stPosInternal | stDensVoid);
  2857. // If there are voids it means that our internal infill is not adjacent to
  2858. // perimeters. In this case it would be nice to add a loop around infill to
  2859. // make it more robust and nicer. TODO.
  2860. #ifdef SLIC3R_DEBUG_SLICE_PROCESSING
  2861. layerm->export_region_fill_surfaces_to_svg_debug("6_clip_fill_surfaces");
  2862. #endif
  2863. }
  2864. m_print->throw_if_canceled();
  2865. }
  2866. }
  2867. void PrintObject::discover_horizontal_shells()
  2868. {
  2869. BOOST_LOG_TRIVIAL(trace) << "discover_horizontal_shells()";
  2870. for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) {
  2871. for (size_t i = 0; i < m_layers.size(); ++ i) {
  2872. m_print->throw_if_canceled();
  2873. Layer *layer = m_layers[i];
  2874. LayerRegion *layerm = layer->regions()[region_id];
  2875. const PrintRegionConfig &region_config = layerm->region()->config();
  2876. if (region_config.solid_infill_every_layers.value > 0 && region_config.fill_density.value > 0 &&
  2877. (i % region_config.solid_infill_every_layers) == 0) {
  2878. // Insert a solid internal layer. Mark stInternal surfaces as stInternalSolid or stInternalBridge.
  2879. SurfaceType type = (region_config.fill_density == 100) ? (stPosInternal | stDensSolid) : (stPosInternal | stDensSolid | stModBridge);
  2880. for (Surface &surface : layerm->fill_surfaces.surfaces)
  2881. if (surface.surface_type == (stPosInternal | stDensSparse))
  2882. surface.surface_type = type;
  2883. }
  2884. // If ensure_vertical_shell_thickness, then the rest has already been performed by discover_vertical_shells().
  2885. if (region_config.ensure_vertical_shell_thickness.value)
  2886. continue;
  2887. coordf_t print_z = layer->print_z;
  2888. coordf_t bottom_z = layer->bottom_z();
  2889. for (size_t idx_surface_type = 0; idx_surface_type < 3; ++ idx_surface_type) {
  2890. m_print->throw_if_canceled();
  2891. SurfaceType type = (idx_surface_type == 0) ? (stPosTop | stDensSolid) :
  2892. ( (idx_surface_type == 1) ? (stPosBottom | stDensSolid) : (stPosBottom | stDensSolid |stModBridge));
  2893. int num_solid_layers = ( (type & stPosTop) == stPosTop) ? region_config.top_solid_layers.value : region_config.bottom_solid_layers.value;
  2894. if (num_solid_layers == 0)
  2895. continue;
  2896. // Find slices of current type for current layer.
  2897. // Use slices instead of fill_surfaces, because they also include the perimeter area,
  2898. // which needs to be propagated in shells; we need to grow slices like we did for
  2899. // fill_surfaces though. Using both ungrown slices and grown fill_surfaces will
  2900. // not work in some situations, as there won't be any grown region in the perimeter
  2901. // area (this was seen in a model where the top layer had one extra perimeter, thus
  2902. // its fill_surfaces were thinner than the lower layer's infill), however it's the best
  2903. // solution so far. Growing the external slices by external_infill_margin will put
  2904. // too much solid infill inside nearly-vertical slopes.
  2905. // Surfaces including the area of perimeters. Everything, that is visible from the top / bottom
  2906. // (not covered by a layer above / below).
  2907. // This does not contain the areas covered by perimeters!
  2908. Polygons solid;
  2909. for (const Surface &surface : layerm->slices().surfaces)
  2910. if (surface.surface_type == type)
  2911. polygons_append(solid, to_polygons(surface.expolygon));
  2912. // Infill areas (slices without the perimeters).
  2913. for (const Surface &surface : layerm->fill_surfaces.surfaces)
  2914. if (surface.surface_type == type)
  2915. polygons_append(solid, to_polygons(surface.expolygon));
  2916. if (solid.empty())
  2917. continue;
  2918. // Slic3r::debugf "Layer %d has %s surfaces\n", $i, (($type & stTop) != 0) ? 'top' : 'bottom';
  2919. // Scatter top / bottom regions to other layers. Scattering process is inherently serial, it is difficult to parallelize without locking.
  2920. for (int n = ((type & stPosTop) == stPosTop) ? int(i) - 1 : int(i) + 1;
  2921. ((type & stPosTop) == stPosTop) ?
  2922. (n >= 0 && (int(i) - n < num_solid_layers ||
  2923. print_z - m_layers[n]->print_z < region_config.top_solid_min_thickness.value - EPSILON)) :
  2924. (n < int(m_layers.size()) && (n - int(i) < num_solid_layers ||
  2925. m_layers[n]->bottom_z() - bottom_z < region_config.bottom_solid_min_thickness.value - EPSILON));
  2926. ((type & stPosTop) == stPosTop) ? -- n : ++ n)
  2927. {
  2928. // Slic3r::debugf " looking for neighbors on layer %d...\n", $n;
  2929. // Reference to the lower layer of a TOP surface, or an upper layer of a BOTTOM surface.
  2930. LayerRegion *neighbor_layerm = m_layers[n]->regions()[region_id];
  2931. // find intersection between neighbor and current layer's surfaces
  2932. // intersections have contours and holes
  2933. // we update $solid so that we limit the next neighbor layer to the areas that were
  2934. // found on this one - in other words, solid shells on one layer (for a given external surface)
  2935. // are always a subset of the shells found on the previous shell layer
  2936. // this approach allows for DWIM in hollow sloping vases, where we want bottom
  2937. // shells to be generated in the base but not in the walls (where there are many
  2938. // narrow bottom surfaces): reassigning $solid will consider the 'shadow' of the
  2939. // upper perimeter as an obstacle and shell will not be propagated to more upper layers
  2940. //FIXME How does it work for stInternalBRIDGE? This is set for sparse infill. Likely this does not work.
  2941. Polygons new_internal_solid;
  2942. {
  2943. Polygons internal;
  2944. for (const Surface &surface : neighbor_layerm->fill_surfaces.surfaces)
  2945. if (surface.has_pos_internal() &&(surface.has_fill_sparse() || surface.has_fill_solid()))
  2946. polygons_append(internal, to_polygons(surface.expolygon));
  2947. new_internal_solid = intersection(solid, internal, true);
  2948. }
  2949. if (new_internal_solid.empty()) {
  2950. // No internal solid needed on this layer. In order to decide whether to continue
  2951. // searching on the next neighbor (thus enforcing the configured number of solid
  2952. // layers, use different strategies according to configured infill density:
  2953. if (region_config.fill_density.value == 0) {
  2954. // If user expects the object to be void (for example a hollow sloping vase),
  2955. // don't continue the search. In this case, we only generate the external solid
  2956. // shell if the object would otherwise show a hole (gap between perimeters of
  2957. // the two layers), and internal solid shells are a subset of the shells found
  2958. // on each previous layer.
  2959. goto EXTERNAL;
  2960. } else {
  2961. // If we have internal infill, we can generate internal solid shells freely.
  2962. continue;
  2963. }
  2964. }
  2965. if (region_config.fill_density.value == 0) {
  2966. // if we're printing a hollow object we discard any solid shell thinner
  2967. // than a perimeter width, since it's probably just crossing a sloping wall
  2968. // and it's not wanted in a hollow print even if it would make sense when
  2969. // obeying the solid shell count option strictly (DWIM!)
  2970. float margin = float(neighbor_layerm->flow(frExternalPerimeter).scaled_width());
  2971. Polygons too_narrow = diff(
  2972. new_internal_solid,
  2973. offset2(new_internal_solid, -margin, +margin, jtMiter, 5),
  2974. true);
  2975. // Trim the regularized region by the original region.
  2976. if (! too_narrow.empty())
  2977. new_internal_solid = solid = diff(new_internal_solid, too_narrow);
  2978. }
  2979. // make sure the new internal solid is wide enough, as it might get collapsed
  2980. // when spacing is added in Fill.pm
  2981. {
  2982. //FIXME Vojtech: Disable this and you will be sorry.
  2983. // https://github.com/prusa3d/PrusaSlicer/issues/26 bottom
  2984. float margin = 3.f * layerm->flow(frSolidInfill).scaled_width(); // require at least this size
  2985. // we use a higher miterLimit here to handle areas with acute angles
  2986. // in those cases, the default miterLimit would cut the corner and we'd
  2987. // get a triangle in $too_narrow; if we grow it below then the shell
  2988. // would have a different shape from the external surface and we'd still
  2989. // have the same angle, so the next shell would be grown even more and so on.
  2990. Polygons too_narrow = diff(
  2991. new_internal_solid,
  2992. offset2(new_internal_solid, -margin, +margin, ClipperLib::jtMiter, 5),
  2993. true);
  2994. if (! too_narrow.empty()) {
  2995. // grow the collapsing parts and add the extra area to the neighbor layer
  2996. // as well as to our original surfaces so that we support this
  2997. // additional area in the next shell too
  2998. // make sure our grown surfaces don't exceed the fill area
  2999. Polygons internal;
  3000. for (const Surface &surface : neighbor_layerm->fill_surfaces.surfaces)
  3001. if (surface.has_pos_internal() && !surface.has_mod_bridge())
  3002. polygons_append(internal, to_polygons(surface.expolygon));
  3003. polygons_append(new_internal_solid,
  3004. intersection(
  3005. offset(too_narrow, +margin),
  3006. // Discard bridges as they are grown for anchoring and we can't
  3007. // remove such anchors. (This may happen when a bridge is being
  3008. // anchored onto a wall where little space remains after the bridge
  3009. // is grown, and that little space is an internal solid shell so
  3010. // it triggers this too_narrow logic.)
  3011. internal));
  3012. // see https://github.com/prusa3d/PrusaSlicer/pull/3426
  3013. // solid = new_internal_solid;
  3014. }
  3015. }
  3016. // internal-solid are the union of the existing internal-solid surfaces
  3017. // and new ones
  3018. SurfaceCollection backup = std::move(neighbor_layerm->fill_surfaces);
  3019. polygons_append(new_internal_solid, to_polygons(backup.filter_by_type(stPosInternal | stDensSolid)));
  3020. ExPolygons internal_solid = union_ex(new_internal_solid, false);
  3021. // assign new internal-solid surfaces to layer
  3022. neighbor_layerm->fill_surfaces.set(internal_solid, stPosInternal | stDensSolid);
  3023. // subtract intersections from layer surfaces to get resulting internal surfaces
  3024. Polygons polygons_internal = to_polygons(std::move(internal_solid));
  3025. ExPolygons internal = diff_ex(
  3026. to_polygons(backup.filter_by_type(stPosInternal | stDensSparse)),
  3027. polygons_internal,
  3028. true);
  3029. // assign resulting internal surfaces to layer
  3030. neighbor_layerm->fill_surfaces.append(internal, stPosInternal | stDensSparse);
  3031. polygons_append(polygons_internal, to_polygons(std::move(internal)));
  3032. // assign top and bottom surfaces to layer
  3033. SurfaceType surface_types_solid[] = { stPosTop | stDensSolid, stPosBottom | stDensSolid, stPosBottom | stDensSolid | stModBridge };
  3034. backup.keep_types(surface_types_solid, 3);
  3035. //backup.keep_types_flag(stPosTop | stPosBottom);
  3036. std::vector<SurfacesPtr> top_bottom_groups;
  3037. backup.group(&top_bottom_groups);
  3038. for (SurfacesPtr &group : top_bottom_groups)
  3039. neighbor_layerm->fill_surfaces.append(
  3040. diff_ex(to_polygons(group), polygons_internal),
  3041. // Use an existing surface as a template, it carries the bridge angle etc.
  3042. *group.front());
  3043. }
  3044. EXTERNAL:;
  3045. } // foreach type (stTop, stBottom, stBottomBridge)
  3046. } // for each layer
  3047. } // for each region
  3048. #ifdef SLIC3R_DEBUG_SLICE_PROCESSING
  3049. for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) {
  3050. for (const Layer *layer : m_layers) {
  3051. const LayerRegion *layerm = layer->m_regions[region_id];
  3052. layerm->export_region_slices_to_svg_debug("5_discover_horizontal_shells");
  3053. layerm->export_region_fill_surfaces_to_svg_debug("5_discover_horizontal_shells");
  3054. } // for each layer
  3055. } // for each region
  3056. #endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
  3057. }
  3058. // combine fill surfaces across layers to honor the "infill every N layers" option
  3059. // Idempotence of this method is guaranteed by the fact that we don't remove things from
  3060. // fill_surfaces but we only turn them into VOID surfaces, thus preserving the boundaries.
  3061. void PrintObject::combine_infill()
  3062. {
  3063. // Work on each region separately.
  3064. for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) {
  3065. const PrintRegion *region = this->print()->regions()[region_id];
  3066. const size_t every = region->config().infill_every_layers.value;
  3067. if (every < 2 || region->config().fill_density == 0.)
  3068. continue;
  3069. // Limit the number of combined layers to the maximum height allowed by this regions' nozzle.
  3070. //FIXME limit the layer height to max_layer_height
  3071. double nozzle_diameter = std::min(
  3072. this->print()->config().nozzle_diameter.get_at(region->config().infill_extruder.value - 1),
  3073. this->print()->config().nozzle_diameter.get_at(region->config().solid_infill_extruder.value - 1));
  3074. // define the combinations
  3075. std::vector<size_t> combine(m_layers.size(), 0);
  3076. {
  3077. double current_height = 0.;
  3078. size_t num_layers = 0;
  3079. for (size_t layer_idx = 0; layer_idx < m_layers.size(); ++ layer_idx) {
  3080. m_print->throw_if_canceled();
  3081. const Layer *layer = m_layers[layer_idx];
  3082. if (layer->id() == 0)
  3083. // Skip first print layer (which may not be first layer in array because of raft).
  3084. continue;
  3085. // Check whether the combination of this layer with the lower layers' buffer
  3086. // would exceed max layer height or max combined layer count.
  3087. if (current_height + layer->height >= nozzle_diameter + EPSILON || num_layers >= every) {
  3088. // Append combination to lower layer.
  3089. combine[layer_idx - 1] = num_layers;
  3090. current_height = 0.;
  3091. num_layers = 0;
  3092. }
  3093. current_height += layer->height;
  3094. ++ num_layers;
  3095. }
  3096. // Append lower layers (if any) to uppermost layer.
  3097. combine[m_layers.size() - 1] = num_layers;
  3098. }
  3099. // loop through layers to which we have assigned layers to combine
  3100. for (size_t layer_idx = 0; layer_idx < m_layers.size(); ++ layer_idx) {
  3101. m_print->throw_if_canceled();
  3102. size_t num_layers = combine[layer_idx];
  3103. if (num_layers <= 1)
  3104. continue;
  3105. // Get all the LayerRegion objects to be combined.
  3106. std::vector<LayerRegion*> layerms;
  3107. layerms.reserve(num_layers);
  3108. for (size_t i = layer_idx + 1 - num_layers; i <= layer_idx; ++ i)
  3109. layerms.emplace_back(m_layers[i]->regions()[region_id]);
  3110. // We need to perform a multi-layer intersection, so let's split it in pairs.
  3111. // Initialize the intersection with the candidates of the lowest layer.
  3112. ExPolygons intersection = to_expolygons(layerms.front()->fill_surfaces.filter_by_type(stPosInternal | stDensSparse));
  3113. // Start looping from the second layer and intersect the current intersection with it.
  3114. for (size_t i = 1; i < layerms.size(); ++ i)
  3115. intersection = intersection_ex(
  3116. to_polygons(intersection),
  3117. to_polygons(layerms[i]->fill_surfaces.filter_by_type(stPosInternal | stDensSparse)),
  3118. false);
  3119. double area_threshold = layerms.front()->infill_area_threshold();
  3120. if (! intersection.empty() && area_threshold > 0.)
  3121. intersection.erase(std::remove_if(intersection.begin(), intersection.end(),
  3122. [area_threshold](const ExPolygon &expoly) { return expoly.area() <= area_threshold; }),
  3123. intersection.end());
  3124. if (intersection.empty())
  3125. continue;
  3126. // Slic3r::debugf " combining %d %s regions from layers %d-%d\n",
  3127. // scalar(@$intersection),
  3128. // ($type == stInternal ? 'internal' : 'internal-solid'),
  3129. // $layer_idx-($every-1), $layer_idx;
  3130. // intersection now contains the regions that can be combined across the full amount of layers,
  3131. // so let's remove those areas from all layers.
  3132. Polygons intersection_with_clearance;
  3133. intersection_with_clearance.reserve(intersection.size());
  3134. //TODO: check if that 'hack' isn't counter-productive : the overlap is done at perimetergenerator (so before this)
  3135. // and the not-overlap area is stored in the LayerRegion object
  3136. float clearance_offset =
  3137. 0.5f * layerms.back()->flow(frPerimeter).scaled_width() +
  3138. // Because fill areas for rectilinear and honeycomb are grown
  3139. // later to overlap perimeters, we need to counteract that too.
  3140. ((region->config().fill_pattern == ipRectilinear ||
  3141. region->config().fill_pattern == ipGrid ||
  3142. region->config().fill_pattern == ipLine ||
  3143. region->config().fill_pattern == ipHoneycomb) ? 1.5f : 0.5f) *
  3144. layerms.back()->flow(frSolidInfill).scaled_width();
  3145. for (ExPolygon &expoly : intersection)
  3146. polygons_append(intersection_with_clearance, offset(expoly, clearance_offset));
  3147. for (LayerRegion *layerm : layerms) {
  3148. Polygons internal = to_polygons(layerm->fill_surfaces.filter_by_type(stPosInternal | stDensSparse));
  3149. layerm->fill_surfaces.remove_type(stPosInternal | stDensSparse);
  3150. layerm->fill_surfaces.append(diff_ex(internal, intersection_with_clearance, false), stPosInternal | stDensSparse);
  3151. if (layerm == layerms.back()) {
  3152. // Apply surfaces back with adjusted depth to the uppermost layer.
  3153. Surface templ(stPosInternal | stDensSparse, ExPolygon());
  3154. templ.thickness = 0.;
  3155. for (LayerRegion *layerm2 : layerms)
  3156. templ.thickness += layerm2->layer()->height;
  3157. templ.thickness_layers = (unsigned short)layerms.size();
  3158. layerm->fill_surfaces.append(intersection, templ);
  3159. } else {
  3160. // Save void surfaces.
  3161. layerm->fill_surfaces.append(
  3162. intersection_ex(internal, intersection_with_clearance, false),
  3163. stPosInternal | stDensVoid);
  3164. }
  3165. }
  3166. }
  3167. }
  3168. }
  3169. void PrintObject::_generate_support_material()
  3170. {
  3171. PrintObjectSupportMaterial support_material(this, m_slicing_params);
  3172. support_material.generate(*this);
  3173. }
  3174. } // namespace Slic3r