OrcaSlicer latest
OrcaSlicer
Loading...
Searching...
No Matches
Slic3r::LoopInterfaceProcessor Struct Reference
Collaboration diagram for Slic3r::LoopInterfaceProcessor:

Public Member Functions

 LoopInterfaceProcessor (coordf_t circle_r)
void generate (SupportGeneratorLayerExtruded &top_contact_layer, const Flow &interface_flow_src) const

Public Attributes

int n_contact_loops
coordf_t circle_radius
coordf_t circle_distance
Polygon circle

Detailed Description

Constructor & Destructor Documentation

◆ LoopInterfaceProcessor()

Slic3r::LoopInterfaceProcessor::LoopInterfaceProcessor ( coordf_t circle_r)
inline
973 :
975 circle_radius(circle_r),
976 circle_distance(circle_r * 3.)
977 {
978 // Shape of the top contact area.
979 circle.points.reserve(6);
980 for (size_t i = 0; i < 6; ++ i) {
981 double angle = double(i) * M_PI / 3.;
982 circle.points.push_back(Point(circle_radius * cos(angle), circle_radius * sin(angle)));
983 }
984 }
#define M_PI
Definition ExtrusionSimulator.cpp:31
Kernel::Point_3 Point
Definition MeshRepair.cpp:81
double angle(const Eigen::MatrixBase< Derived > &v1, const Eigen::MatrixBase< Derived2 > &v2)
Definition Point.hpp:138
coordf_t circle_distance
Definition SupportCommon.cpp:992
coordf_t circle_radius
Definition SupportCommon.cpp:991
Polygon circle
Definition SupportCommon.cpp:993
int n_contact_loops
Definition SupportCommon.cpp:990

References Slic3r::angle(), circle, circle_distance, circle_radius, M_PI, and n_contact_loops.

Here is the call graph for this function:

Member Function Documentation

◆ generate()

void Slic3r::LoopInterfaceProcessor::generate ( SupportGeneratorLayerExtruded & top_contact_layer,
const Flow & interface_flow_src ) const
997{
998 if (n_contact_loops == 0 || top_contact_layer.empty())
999 return;
1000
1001 Flow flow = interface_flow_src.with_height(top_contact_layer.layer->height);
1002
1003 Polygons overhang_polygons;
1004 if (top_contact_layer.layer->overhang_polygons != nullptr)
1005 overhang_polygons = std::move(*top_contact_layer.layer->overhang_polygons);
1006
1007 // Generate the outermost loop.
1008 // Find centerline of the external loop (or any other kind of extrusions should the loop be skipped)
1009 ExPolygons top_contact_expolygons = offset_ex(union_ex(top_contact_layer.layer->polygons), - 0.5f * flow.scaled_width());
1010
1011 // Grid size and bit shifts for quick and exact to/from grid coordinates manipulation.
1012 coord_t circle_grid_resolution = 1;
1013 coord_t circle_grid_powerof2 = 0;
1014 {
1015 // epsilon to account for rounding errors
1016 coord_t circle_grid_resolution_non_powerof2 = coord_t(2. * circle_distance + 3.);
1017 while (circle_grid_resolution < circle_grid_resolution_non_powerof2) {
1018 circle_grid_resolution <<= 1;
1019 ++ circle_grid_powerof2;
1020 }
1021 }
1022
1023 struct PointAccessor {
1024 const Point* operator()(const Point &pt) const { return &pt; }
1025 };
1026 typedef ClosestPointInRadiusLookup<Point, PointAccessor> ClosestPointLookupType;
1027
1028 Polygons loops0;
1029 {
1030 // find centerline of the external loop of the contours
1031 // Only consider the loops facing the overhang.
1032 Polygons external_loops;
1033 // Holes in the external loops.
1034 Polygons circles;
1035 Polygons overhang_with_margin = offset(union_ex(overhang_polygons), 0.5f * flow.scaled_width());
1036 for (ExPolygons::iterator it_contact_expoly = top_contact_expolygons.begin(); it_contact_expoly != top_contact_expolygons.end(); ++ it_contact_expoly) {
1037 // Store the circle centers placed for an expolygon into a regular grid, hashed by the circle centers.
1038 ClosestPointLookupType circle_centers_lookup(coord_t(circle_distance - SCALED_EPSILON));
1039 Points circle_centers;
1040 Point center_last;
1041 // For each contour of the expolygon, start with the outer contour, continue with the holes.
1042 for (size_t i_contour = 0; i_contour <= it_contact_expoly->holes.size(); ++ i_contour) {
1043 Polygon &contour = (i_contour == 0) ? it_contact_expoly->contour : it_contact_expoly->holes[i_contour - 1];
1044 const Point *seg_current_pt = nullptr;
1045 coordf_t seg_current_t = 0.;
1046 if (! intersection_pl(contour.split_at_first_point(), overhang_with_margin).empty()) {
1047 // The contour is below the overhang at least to some extent.
1048 //FIXME ideally one would place the circles below the overhang only.
1049 // Walk around the contour and place circles so their centers are not closer than circle_distance from each other.
1050 if (circle_centers.empty()) {
1051 // Place the first circle.
1052 seg_current_pt = &contour.points.front();
1053 seg_current_t = 0.;
1054 center_last = *seg_current_pt;
1055 circle_centers_lookup.insert(center_last);
1056 circle_centers.push_back(center_last);
1057 }
1058 for (Points::const_iterator it = contour.points.begin() + 1; it != contour.points.end(); ++it) {
1059 // Is it possible to place a circle on this segment? Is it not too close to any of the circles already placed on this contour?
1060 const Point &p1 = *(it-1);
1061 const Point &p2 = *it;
1062 // Intersection of a ray (p1, p2) with a circle placed at center_last, with radius of circle_distance.
1063 const Vec2d v_seg(coordf_t(p2(0)) - coordf_t(p1(0)), coordf_t(p2(1)) - coordf_t(p1(1)));
1064 const Vec2d v_cntr(coordf_t(p1(0) - center_last(0)), coordf_t(p1(1) - center_last(1)));
1065 coordf_t a = v_seg.squaredNorm();
1066 coordf_t b = 2. * v_seg.dot(v_cntr);
1067 coordf_t c = v_cntr.squaredNorm() - circle_distance * circle_distance;
1068 coordf_t disc = b * b - 4. * a * c;
1069 if (disc > 0.) {
1070 // The circle intersects a ray. Avoid the parts of the segment inside the circle.
1071 coordf_t t1 = (-b - sqrt(disc)) / (2. * a);
1072 coordf_t t2 = (-b + sqrt(disc)) / (2. * a);
1073 coordf_t t0 = (seg_current_pt == &p1) ? seg_current_t : 0.;
1074 // Take the lowest t in <t0, 1.>, excluding <t1, t2>.
1075 coordf_t t;
1076 if (t0 <= t1)
1077 t = t0;
1078 else if (t2 <= 1.)
1079 t = t2;
1080 else {
1081 // Try the following segment.
1082 seg_current_pt = nullptr;
1083 continue;
1084 }
1085 seg_current_pt = &p1;
1086 seg_current_t = t;
1087 center_last = Point(p1(0) + coord_t(v_seg(0) * t), p1(1) + coord_t(v_seg(1) * t));
1088 // It has been verified that the new point is far enough from center_last.
1089 // Ensure, that it is far enough from all the centers.
1090 std::pair<const Point*, coordf_t> circle_closest = circle_centers_lookup.find(center_last);
1091 if (circle_closest.first != nullptr) {
1092 -- it;
1093 continue;
1094 }
1095 } else {
1096 // All of the segment is outside the circle. Take the first point.
1097 seg_current_pt = &p1;
1098 seg_current_t = 0.;
1099 center_last = p1;
1100 }
1101 // Place the first circle.
1102 circle_centers_lookup.insert(center_last);
1103 circle_centers.push_back(center_last);
1104 }
1105 external_loops.push_back(std::move(contour));
1106 for (const Point &center : circle_centers) {
1107 circles.push_back(circle);
1108 circles.back().translate(center);
1109 }
1110 }
1111 }
1112 }
1113 // Apply a pattern to the external loops.
1114 loops0 = diff(external_loops, circles);
1115 }
1116
1117 Polylines loop_lines;
1118 {
1119 // make more loops
1120 Polygons loop_polygons = loops0;
1121 for (int i = 1; i < n_contact_loops; ++ i)
1122 polygons_append(loop_polygons,
1123 opening(
1124 loops0,
1125 i * flow.scaled_spacing() + 0.5f * flow.scaled_spacing(),
1126 0.5f * flow.scaled_spacing()));
1127 // Clip such loops to the side oriented towards the object.
1128 // Collect split points, so they will be recognized after the clipping.
1129 // At the split points the clipped pieces will be stitched back together.
1130 loop_lines.reserve(loop_polygons.size());
1131 std::unordered_map<Point, int, PointHash> map_split_points;
1132 for (Polygons::const_iterator it = loop_polygons.begin(); it != loop_polygons.end(); ++ it) {
1133 assert(map_split_points.find(it->first_point()) == map_split_points.end());
1134 map_split_points[it->first_point()] = -1;
1135 loop_lines.push_back(it->split_at_first_point());
1136 }
1137 loop_lines = intersection_pl(loop_lines, expand(overhang_polygons, scale_(SUPPORT_MATERIAL_MARGIN)));
1138 // Because a closed loop has been split to a line, loop_lines may contain continuous segments split to 2 pieces.
1139 // Try to connect them.
1140 for (int i_line = 0; i_line < int(loop_lines.size()); ++ i_line) {
1141 Polyline &polyline = loop_lines[i_line];
1142 auto it = map_split_points.find(polyline.first_point());
1143 if (it != map_split_points.end()) {
1144 // This is a stitching point.
1145 // If this assert triggers, multiple source polygons likely intersected at this point.
1146 assert(it->second != -2);
1147 if (it->second < 0) {
1148 // First occurence.
1149 it->second = i_line;
1150 } else {
1151 // Second occurence. Join the lines.
1152 Polyline &polyline_1st = loop_lines[it->second];
1153 assert(polyline_1st.first_point() == it->first || polyline_1st.last_point() == it->first);
1154 if (polyline_1st.first_point() == it->first)
1155 polyline_1st.reverse();
1156 polyline_1st.append(std::move(polyline));
1157 it->second = -2;
1158 }
1159 continue;
1160 }
1161 it = map_split_points.find(polyline.last_point());
1162 if (it != map_split_points.end()) {
1163 // This is a stitching point.
1164 // If this assert triggers, multiple source polygons likely intersected at this point.
1165 assert(it->second != -2);
1166 if (it->second < 0) {
1167 // First occurence.
1168 it->second = i_line;
1169 } else {
1170 // Second occurence. Join the lines.
1171 Polyline &polyline_1st = loop_lines[it->second];
1172 assert(polyline_1st.first_point() == it->first || polyline_1st.last_point() == it->first);
1173 if (polyline_1st.first_point() == it->first)
1174 polyline_1st.reverse();
1175 polyline.reverse();
1176 polyline_1st.append(std::move(polyline));
1177 it->second = -2;
1178 }
1179 }
1180 }
1181 // Remove empty lines.
1182 remove_degenerate(loop_lines);
1183 }
1184
1185 // add the contact infill area to the interface area
1186 // note that growing loops by $circle_radius ensures no tiny
1187 // extrusions are left inside the circles; however it creates
1188 // a very large gap between loops and contact_infill_polygons, so maybe another
1189 // solution should be found to achieve both goals
1190 // Store the trimmed polygons into a separate polygon set, so the original infill area remains intact for
1191 // "modulate by layer thickness".
1192 top_contact_layer.set_polygons_to_extrude(diff(top_contact_layer.layer->polygons, offset(loop_lines, float(circle_radius * 1.1))));
1193
1194 // Transform loops into ExtrusionPath objects.
1196 top_contact_layer.extrusions,
1197 std::move(loop_lines),
1198 ExtrusionRole::erSupportMaterialInterface, flow.mm3_per_mm(), flow.width(), flow.height());
1199}
#define SUPPORT_MATERIAL_MARGIN
Definition PrintObject.cpp:5149
Points points
Definition MultiPoint.hpp:22
Polyline split_at_first_point() const
Definition Polygon.hpp:60
#define SCALED_EPSILON
Definition libslic3r.h:109
#define scale_(val)
Definition libslic3r.h:106
int64_t coord_t
Definition libslic3r.h:48
double coordf_t
Definition GUI_ObjectList.hpp:46
std::vector< ExPolygon > ExPolygons
Definition ExPolygon.hpp:20
Slic3r::Polygons expand(const Slic3r::Polygon &polygon, const float delta, JoinType joinType=DefaultJoinType, double miterLimit=DefaultMiterLimit)
Definition ClipperUtils.hpp:397
void extrusion_entities_append_paths(ExtrusionEntitiesPtr &dst, Polylines &polylines, ExtrusionRole role, double mm3_per_mm, float width, float height, bool can_reverse=true)
Definition ExtrusionEntity.hpp:608
std::vector< Polyline > Polylines
Definition Polyline.hpp:22
void center(ExPolygonsWithIds &e)
Definition Emboss.cpp:1382
@ erSupportMaterialInterface
Definition ExtrusionEntity.hpp:42
std::vector< Polygon, PointsAllocator< Polygon > > Polygons
Definition Polygon.hpp:22
Slic3r::Polygons offset(const Slic3r::Polygon &polygon, const float delta, JoinType joinType, double miterLimit)
Definition ClipperUtils.cpp:582
bool remove_degenerate(Polygons &polys)
Definition Polygon.cpp:610
Slic3r::ExPolygons offset_ex(const Slic3r::Polygons &polygons, const float delta, JoinType joinType, double miterLimit)
Definition ClipperUtils.cpp:605
Slic3r::Polygons opening(const Slic3r::Polygons &polygons, const float delta1, const float delta2, JoinType joinType, double miterLimit)
Definition ClipperUtils.cpp:696
std::vector< Point, PointsAllocator< Point > > Points
Definition Point.hpp:73
void polygons_append(Polygons &dst, const ExPolygon &src)
Definition ExPolygon.hpp:411
Slic3r::ExPolygons union_ex(const Slic3r::Polygons &subject, PolyFillType fill_type)
Definition ClipperUtils.cpp:1011
Slic3r::Polylines intersection_pl(const Slic3r::Polylines &subject, const Slic3r::Polygon &clip)
Definition ClipperUtils.cpp:1111
Eigen::Matrix< double, 2, 1, Eigen::DontAlign > Vec2d
Definition Point.hpp:67
Slic3r::Polygons diff(const Slic3r::Polygon &subject, const Slic3r::Polygon &clip, ApplySafetyOffset do_safety_offset)
Definition ClipperUtils.cpp:731
const Polygon & contour(const ExPolygon &p)
Definition AGGRaster.hpp:30
const Polygons & holes(const ExPolygon &p)
Definition AGGRaster.hpp:31
Slic3r::Polygon Polygon
Definition Emboss.cpp:101

References Slic3r::Polyline::append(), Slic3r::center(), circle, circle_distance, circle_radius, Slic3r::contour(), Slic3r::diff(), Slic3r::SupportGeneratorLayerExtruded::empty(), Slic3r::erSupportMaterialInterface, Slic3r::expand(), Slic3r::extrusion_entities_append_paths(), Slic3r::SupportGeneratorLayerExtruded::extrusions, Slic3r::MultiPoint::first_point(), generate(), Slic3r::Flow::height(), Slic3r::SupportGeneratorLayer::height, Slic3r::intersection_pl(), Slic3r::Polyline::last_point(), Slic3r::SupportGeneratorLayerExtruded::layer, Slic3r::Flow::mm3_per_mm(), n_contact_loops, Slic3r::offset(), Slic3r::offset_ex(), Slic3r::opening(), Slic3r::SupportGeneratorLayer::overhang_polygons, Slic3r::SupportGeneratorLayer::polygons, Slic3r::polygons_append(), Slic3r::remove_degenerate(), Slic3r::Polyline::reverse(), scale_, SCALED_EPSILON, Slic3r::Flow::scaled_spacing(), Slic3r::Flow::scaled_width(), Slic3r::SupportGeneratorLayerExtruded::set_polygons_to_extrude(), SUPPORT_MATERIAL_MARGIN, Slic3r::union_ex(), Slic3r::Flow::width(), and Slic3r::Flow::with_height().

Referenced by generate().

Here is the call graph for this function:
Here is the caller graph for this function:

Member Data Documentation

◆ circle

Polygon Slic3r::LoopInterfaceProcessor::circle

Referenced by LoopInterfaceProcessor(), and generate().

◆ circle_distance

coordf_t Slic3r::LoopInterfaceProcessor::circle_distance

Referenced by LoopInterfaceProcessor(), and generate().

◆ circle_radius

coordf_t Slic3r::LoopInterfaceProcessor::circle_radius

Referenced by LoopInterfaceProcessor(), and generate().

◆ n_contact_loops

int Slic3r::LoopInterfaceProcessor::n_contact_loops

The documentation for this struct was generated from the following file: