Fill.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. #include <assert.h>
  2. #include <stdio.h>
  3. #include <memory>
  4. #include "../ClipperUtils.hpp"
  5. #include "../Geometry.hpp"
  6. #include "../Layer.hpp"
  7. #include "../Print.hpp"
  8. #include "../PrintConfig.hpp"
  9. #include "../Surface.hpp"
  10. #include "FillBase.hpp"
  11. namespace Slic3r {
  12. struct SurfaceGroupAttrib
  13. {
  14. SurfaceGroupAttrib() : is_solid(false), flow_width(0.f), pattern(-1) {}
  15. bool operator==(const SurfaceGroupAttrib &other) const
  16. { return is_solid == other.is_solid && flow_width == other.flow_width && pattern == other.pattern; }
  17. bool is_solid;
  18. float flow_width;
  19. // pattern is of type InfillPattern, -1 for an unset pattern.
  20. int pattern;
  21. };
  22. // Generate infills for Slic3r::Layer::Region.
  23. // The Slic3r::Layer::Region at this point of time may contain
  24. // surfaces of various types (internal/bridge/top/bottom/solid).
  25. // The infills are generated on the groups of surfaces with a compatible type.
  26. // Returns an array of Slic3r::ExtrusionPath::Collection objects containing the infills generaed now
  27. // and the thin fills generated by generate_perimeters().
  28. void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out)
  29. {
  30. // Slic3r::debugf "Filling layer %d:\n", $layerm->layer->id;
  31. double fill_density = layerm.region()->config().fill_density;
  32. Flow infill_flow = layerm.flow(frInfill);
  33. Flow solid_infill_flow = layerm.flow(frSolidInfill);
  34. Flow top_solid_infill_flow = layerm.flow(frTopSolidInfill);
  35. Surfaces surfaces;
  36. // merge adjacent surfaces
  37. // in case of bridge surfaces, the ones with defined angle will be attached to the ones
  38. // without any angle (shouldn't this logic be moved to process_external_surfaces()?)
  39. {
  40. Polygons polygons_bridged;
  41. polygons_bridged.reserve(layerm.fill_surfaces.surfaces.size());
  42. for (Surfaces::iterator it = layerm.fill_surfaces.surfaces.begin(); it != layerm.fill_surfaces.surfaces.end(); ++ it)
  43. if (it->bridge_angle >= 0)
  44. polygons_append(polygons_bridged, *it);
  45. // group surfaces by distinct properties (equal surface_type, thickness, thickness_layers, bridge_angle)
  46. // group is of type Slic3r::SurfaceCollection
  47. //FIXME: Use some smart heuristics to merge similar surfaces to eliminate tiny regions.
  48. std::vector<SurfacesPtr> groups;
  49. layerm.fill_surfaces.group(&groups);
  50. // merge compatible groups (we can generate continuous infill for them)
  51. {
  52. // cache flow widths and patterns used for all solid groups
  53. // (we'll use them for comparing compatible groups)
  54. std::vector<SurfaceGroupAttrib> group_attrib(groups.size());
  55. for (size_t i = 0; i < groups.size(); ++ i) {
  56. // we can only merge solid non-bridge surfaces, so discard
  57. // non-solid surfaces
  58. const Surface &surface = *groups[i].front();
  59. if (surface.is_solid() && (!surface.is_bridge() || layerm.layer()->id() == 0)) {
  60. group_attrib[i].is_solid = true;
  61. group_attrib[i].flow_width = (surface.surface_type == stTop) ? top_solid_infill_flow.width : solid_infill_flow.width;
  62. group_attrib[i].pattern = surface.is_external() ?
  63. (surface.is_top() ? layerm.region()->config().top_fill_pattern.value : layerm.region()->config().bottom_fill_pattern.value) :
  64. ipRectilinear;
  65. }
  66. }
  67. // Loop through solid groups, find compatible groups and append them to this one.
  68. for (size_t i = 0; i < groups.size(); ++ i) {
  69. if (! group_attrib[i].is_solid)
  70. continue;
  71. for (size_t j = i + 1; j < groups.size();) {
  72. if (group_attrib[i] == group_attrib[j]) {
  73. // groups are compatible, merge them
  74. groups[i].insert(groups[i].end(), groups[j].begin(), groups[j].end());
  75. groups.erase(groups.begin() + j);
  76. group_attrib.erase(group_attrib.begin() + j);
  77. } else
  78. ++ j;
  79. }
  80. }
  81. }
  82. // Give priority to bridges. Process the bridges in the first round, the rest of the surfaces in the 2nd round.
  83. for (size_t round = 0; round < 2; ++ round) {
  84. for (std::vector<SurfacesPtr>::iterator it_group = groups.begin(); it_group != groups.end(); ++ it_group) {
  85. const SurfacesPtr &group = *it_group;
  86. bool is_bridge = group.front()->bridge_angle >= 0;
  87. if (is_bridge != (round == 0))
  88. continue;
  89. // Make a union of polygons defining the infiill regions of a group, use a safety offset.
  90. Polygons union_p = union_(to_polygons(*it_group), true);
  91. // Subtract surfaces having a defined bridge_angle from any other, use a safety offset.
  92. if (! polygons_bridged.empty() && ! is_bridge)
  93. union_p = diff(union_p, polygons_bridged, true);
  94. // subtract any other surface already processed
  95. //FIXME Vojtech: Because the bridge surfaces came first, they are subtracted twice!
  96. // Using group.front() as a template.
  97. surfaces_append(surfaces, diff_ex(union_p, to_polygons(surfaces), true), *group.front());
  98. }
  99. }
  100. }
  101. // we need to detect any narrow surfaces that might collapse
  102. // when adding spacing below
  103. // such narrow surfaces are often generated in sloping walls
  104. // by bridge_over_infill() and combine_infill() as a result of the
  105. // subtraction of the combinable area from the layer infill area,
  106. // which leaves small areas near the perimeters
  107. // we are going to grow such regions by overlapping them with the void (if any)
  108. // TODO: detect and investigate whether there could be narrow regions without
  109. // any void neighbors
  110. {
  111. coord_t distance_between_surfaces = std::max(
  112. std::max(infill_flow.scaled_spacing(), solid_infill_flow.scaled_spacing()),
  113. top_solid_infill_flow.scaled_spacing());
  114. Polygons surfaces_polygons = to_polygons(surfaces);
  115. Polygons collapsed = diff(
  116. surfaces_polygons,
  117. offset2(surfaces_polygons, (float)-distance_between_surfaces/2, (float)+distance_between_surfaces/2),
  118. true);
  119. Polygons to_subtract;
  120. to_subtract.reserve(collapsed.size() + number_polygons(surfaces));
  121. for (Surfaces::const_iterator it_surface = surfaces.begin(); it_surface != surfaces.end(); ++ it_surface)
  122. if (it_surface->surface_type == stInternalVoid)
  123. polygons_append(to_subtract, *it_surface);
  124. polygons_append(to_subtract, collapsed);
  125. surfaces_append(
  126. surfaces,
  127. intersection_ex(
  128. offset(collapsed, (float)distance_between_surfaces),
  129. to_subtract,
  130. true),
  131. stInternalSolid);
  132. }
  133. if (0) {
  134. // require "Slic3r/SVG.pm";
  135. // Slic3r::SVG::output("fill_" . $layerm->print_z . ".svg",
  136. // expolygons => [ map $_->expolygon, grep !$_->is_solid, @surfaces ],
  137. // red_expolygons => [ map $_->expolygon, grep $_->is_solid, @surfaces ],
  138. // );
  139. }
  140. for (const Surface &surface : surfaces) {
  141. if (surface.surface_type == stInternalVoid)
  142. continue;
  143. InfillPattern fill_pattern = layerm.region()->config().fill_pattern.value;
  144. double density = fill_density;
  145. FlowRole role = (surface.surface_type == stTop) ? frTopSolidInfill :
  146. (surface.is_solid() ? frSolidInfill : frInfill);
  147. bool is_bridge = layerm.layer()->id() > 0 && surface.is_bridge();
  148. if (surface.is_solid()) {
  149. density = 100.;
  150. fill_pattern = (surface.is_external() && ! is_bridge) ?
  151. (surface.is_top() ? layerm.region()->config().top_fill_pattern.value : layerm.region()->config().bottom_fill_pattern.value) :
  152. ipRectilinear;
  153. } else if (density <= 0)
  154. continue;
  155. // get filler object
  156. std::unique_ptr<Fill> f = std::unique_ptr<Fill>(Fill::new_from_type(fill_pattern));
  157. f->set_bounding_box(layerm.layer()->object()->bounding_box());
  158. // calculate the actual flow we'll be using for this infill
  159. coordf_t h = (surface.thickness == -1) ? layerm.layer()->height : surface.thickness;
  160. Flow flow = layerm.region()->flow(
  161. role,
  162. h,
  163. is_bridge || f->use_bridge_flow(), // bridge flow?
  164. layerm.layer()->id() == 0, // first layer?
  165. -1, // auto width
  166. *layerm.layer()->object()
  167. );
  168. // calculate flow spacing for infill pattern generation
  169. bool using_internal_flow = false;
  170. if (! surface.is_solid() && ! is_bridge) {
  171. // it's internal infill, so we can calculate a generic flow spacing
  172. // for all layers, for avoiding the ugly effect of
  173. // misaligned infill on first layer because of different extrusion width and
  174. // layer height
  175. Flow internal_flow = layerm.region()->flow(
  176. frInfill,
  177. layerm.layer()->object()->config().layer_height.value, // TODO: handle infill_every_layers?
  178. false, // no bridge
  179. false, // no first layer
  180. -1, // auto width
  181. *layerm.layer()->object()
  182. );
  183. f->spacing = internal_flow.spacing();
  184. using_internal_flow = true;
  185. } else {
  186. f->spacing = flow.spacing();
  187. }
  188. double link_max_length = 0.;
  189. if (! is_bridge) {
  190. #if 0
  191. link_max_length = layerm.region()->config().get_abs_value(surface.is_external() ? "external_fill_link_max_length" : "fill_link_max_length", flow.spacing());
  192. // printf("flow spacing: %f, is_external: %d, link_max_length: %lf\n", flow.spacing(), int(surface.is_external()), link_max_length);
  193. #else
  194. if (density > 80.) // 80%
  195. link_max_length = 3. * f->spacing;
  196. #endif
  197. }
  198. f->layer_id = layerm.layer()->id();
  199. f->z = layerm.layer()->print_z;
  200. f->angle = float(Geometry::deg2rad(layerm.region()->config().fill_angle.value));
  201. // Maximum length of the perimeter segment linking two infill lines.
  202. f->link_max_length = (coord_t)scale_(link_max_length);
  203. // Used by the concentric infill pattern to clip the loops to create extrusion paths.
  204. f->loop_clipping = coord_t(scale_(flow.nozzle_diameter) * LOOP_CLIPPING_LENGTH_OVER_NOZZLE_DIAMETER);
  205. // f->layer_height = h;
  206. // apply half spacing using this flow's own spacing and generate infill
  207. FillParams params;
  208. params.density = float(0.01 * density);
  209. // params.dont_adjust = true;
  210. params.dont_adjust = false;
  211. Polylines polylines = f->fill_surface(&surface, params);
  212. if (polylines.empty())
  213. continue;
  214. // calculate actual flow from spacing (which might have been adjusted by the infill
  215. // pattern generator)
  216. if (using_internal_flow) {
  217. // if we used the internal flow we're not doing a solid infill
  218. // so we can safely ignore the slight variation that might have
  219. // been applied to $f->flow_spacing
  220. } else {
  221. flow = Flow::new_from_spacing(f->spacing, flow.nozzle_diameter, (float)h, is_bridge || f->use_bridge_flow());
  222. }
  223. // Save into layer.
  224. auto *eec = new ExtrusionEntityCollection();
  225. out.entities.push_back(eec);
  226. // Only concentric fills are not sorted.
  227. eec->no_sort = f->no_sort();
  228. extrusion_entities_append_paths(
  229. eec->entities, std::move(polylines),
  230. is_bridge ?
  231. erBridgeInfill :
  232. (surface.is_solid() ?
  233. ((surface.surface_type == stTop) ? erTopSolidInfill : erSolidInfill) :
  234. erInternalInfill),
  235. flow.mm3_per_mm(), flow.width, flow.height);
  236. }
  237. // add thin fill regions
  238. // thin_fills are of C++ Slic3r::ExtrusionEntityCollection, perl type Slic3r::ExtrusionPath::Collection
  239. // Unpacks the collection, creates multiple collections per path.
  240. // The path type could be ExtrusionPath, ExtrusionLoop or ExtrusionEntityCollection.
  241. // Why the paths are unpacked?
  242. for (const ExtrusionEntity *thin_fill : layerm.thin_fills.entities) {
  243. ExtrusionEntityCollection &collection = *(new ExtrusionEntityCollection());
  244. out.entities.push_back(&collection);
  245. collection.entities.push_back(thin_fill->clone());
  246. }
  247. }
  248. } // namespace Slic3r