Flow PrintRegion::flow(FlowRole role, double layer_height, bool bridge, bool first_layer, double width, const PrintObject &object) const { ConfigOptionFloatOrPercent config_width; if (width != -1) { // use the supplied custom width, if any config_width.value = width; config_width.percent = false; } else { // otherwise, get extrusion width from configuration // (might be an absolute value, or a percent value, or zero for auto) if (first_layer && this->_print->config.first_layer_extrusion_width.value > 0) { config_width = this->_print->config.first_layer_extrusion_width; } else if (role == frExternalPerimeter) { config_width = this->config.external_perimeter_extrusion_width; } else if (role == frPerimeter) { config_width = this->config.perimeter_extrusion_width; } else if (role == frInfill) { config_width = this->config.infill_extrusion_width; } else if (role == frSolidInfill) { config_width = this->config.solid_infill_extrusion_width; } else if (role == frTopSolidInfill) { config_width = this->config.top_infill_extrusion_width; } else { CONFESS("Unknown role"); } } if (config_width.value == 0) { config_width = object.config.extrusion_width; } // get the configured nozzle_diameter for the extruder associated // to the flow role requested size_t extruder; // 1-based if (role == frPerimeter || role == frExternalPerimeter) { extruder = this->config.perimeter_extruder; } else if (role == frInfill) { extruder = this->config.infill_extruder; } else if (role == frSolidInfill || role == frTopSolidInfill) { extruder = this->config.solid_infill_extruder; } else { CONFESS("Unknown role $role"); } double nozzle_diameter = this->_print->config.nozzle_diameter.get_at(extruder-1); return Flow::new_from_config_width(role, config_width, nozzle_diameter, layer_height, bridge ? (float)this->config.bridge_flow_ratio : 0.0); }
void Surface::from_SV_check(SV* surface_sv) { if (!sv_isa(surface_sv, perl_class_name(this)) && !sv_isa(surface_sv, perl_class_name_ref(this))) CONFESS("Not a valid %s object", perl_class_name(this)); // a XS Surface was supplied *this = *(Surface *)SvIV((SV*)SvRV( surface_sv )); }
void Polygon::from_SV_check(SV* poly_sv) { if (sv_isobject(poly_sv) && !sv_isa(poly_sv, perl_class_name(this)) && !sv_isa(poly_sv, perl_class_name_ref(this))) CONFESS("Not a valid %s object", perl_class_name(this)); MultiPoint::from_SV_check(poly_sv); }
/* This constructor builds a Flow object from a given centerline spacing. */ Flow Flow::new_from_spacing(float spacing, float nozzle_diameter, float height, bool bridge) { // we need layer height unless it's a bridge if (height <= 0 && !bridge) CONFESS("Invalid flow height supplied to new_from_spacing()"); float w = Flow::_width_from_spacing(spacing, nozzle_diameter, height, bridge); return Flow(w, height, nozzle_diameter, bridge); }
void Line::from_SV_check(SV* line_sv) { if (sv_isobject(line_sv) && (SvTYPE(SvRV(line_sv)) == SVt_PVMG)) { if (!sv_isa(line_sv, perl_class_name(this)) && !sv_isa(line_sv, perl_class_name_ref(this))) CONFESS("Not a valid %s object", perl_class_name(this)); *this = *(Line*)SvIV((SV*)SvRV( line_sv )); } else { this->from_SV(line_sv); } }
BoundingBox3Base<PointClass>::BoundingBox3Base(const std::vector<PointClass> &points) : BoundingBoxBase<PointClass>(points) { if (points.empty()) CONFESS("Empty point set supplied to BoundingBox3Base constructor"); typename std::vector<PointClass>::const_iterator it = points.begin(); this->min.z = this->max.z = it->z; for (++it; it != points.end(); ++it) { this->min.z = std::min(it->z, this->min.z); this->max.z = std::max(it->z, this->max.z); } }
BoundingBoxf3 ModelObject::raw_bounding_box() const { BoundingBoxf3 bb; for (ModelVolumePtrs::const_iterator v = this->volumes.begin(); v != this->volumes.end(); ++v) { if ((*v)->modifier) continue; if (this->instances.empty()) CONFESS("Can't call raw_bounding_box() with no instances"); bb.merge(this->instances.front()->transform_mesh_bounding_box(&(*v)->mesh, true)); } return bb; }
void Line::from_SV_check(SV* line_sv) { if (sv_isobject(line_sv) && (SvTYPE(SvRV(line_sv)) == SVt_PVMG)) { if (!sv_isa(line_sv, "Slic3r::Line") && !sv_isa(line_sv, "Slic3r::Line::Ref")) CONFESS("Not a valid Slic3r::Line object"); *this = *(Line*)SvIV((SV*)SvRV( line_sv )); } else { this->from_SV(line_sv); } }
Polyline* Polygon::split_at(const Point &point) const { // find index of point for (Points::const_iterator it = this->points.begin(); it != this->points.end(); ++it) { if (it->coincides_with(point)) return this->split_at_index(it - this->points.begin()); } CONFESS("Point not found"); return NULL; }
void Point::from_SV_check(SV* point_sv) { if (sv_isobject(point_sv) && (SvTYPE(SvRV(point_sv)) == SVt_PVMG)) { if (!sv_isa(point_sv, perl_class_name(this)) && !sv_isa(point_sv, perl_class_name_ref(this))) CONFESS("Not a valid %s object (got %s)", perl_class_name(this), HvNAME(SvSTASH(SvRV(point_sv)))); *this = *(Point*)SvIV((SV*)SvRV( point_sv )); } else { this->from_SV(point_sv); } }
Point PolylineCollection::leftmost_point() const { if (this->polylines.empty()) CONFESS("leftmost_point() called on empty PolylineCollection"); Point p = this->polylines.front().leftmost_point(); for (Polylines::const_iterator it = this->polylines.begin() + 1; it != this->polylines.end(); ++it) { Point p2 = it->leftmost_point(); if (p2.x < p.x) p = p2; } return p; }
Point PolylineCollection::leftmost_point(const Polylines &polylines) { if (polylines.empty()) CONFESS("leftmost_point() called on empty PolylineCollection"); Polylines::const_iterator it = polylines.begin(); Point p = it->leftmost_point(); for (++ it; it != polylines.end(); ++it) { Point p2 = it->leftmost_point(); if (p2.x < p.x) p = p2; } return p; }
BoundingBoxBase<PointClass>::BoundingBoxBase(const std::vector<PointClass> &points) { if (points.empty()) CONFESS("Empty point set supplied to BoundingBoxBase constructor"); typename std::vector<PointClass>::const_iterator it = points.begin(); this->min.x = this->max.x = it->x; this->min.y = this->max.y = it->y; for (++it; it != points.end(); ++it) { this->min.x = std::min(it->x, this->min.x); this->min.y = std::min(it->y, this->min.y); this->max.x = std::max(it->x, this->max.x); this->max.y = std::max(it->y, this->max.y); } this->defined = true; }
std::string GCode::extrude(const ExtrusionEntity &entity, std::string description, double speed, int partNum) { std::string gcode = ";start extrusion\n"; if (const ExtrusionPath* path = dynamic_cast<const ExtrusionPath*>(&entity)) { gcode += this->extrude(*path, description, speed); } else if (const ExtrusionLoop* loop = dynamic_cast<const ExtrusionLoop*>(&entity)) { gcode += this->extrude(*loop, description, speed); } else { CONFESS("Invalid argument supplied to extrude()"); return ""; } gcode += ";end extrusion\n"; return gcode; }
void ModelObject::raw_bounding_box(BoundingBoxf3* bb) const { for (ModelVolumePtrs::const_iterator v = this->volumes.begin(); v != this->volumes.end(); ++v) { if ((*v)->modifier) continue; TriangleMesh mesh = (*v)->mesh; if (this->instances.empty()) CONFESS("Can't call raw_bounding_box() with no instances"); this->instances.front()->transform_mesh(&mesh, true); BoundingBoxf3 mbb; mesh.bounding_box(&mbb); bb->merge(mbb); } }
TriangleMeshPtrs TriangleMesh::split() const { TriangleMeshPtrs meshes; std::set<int> seen_facets; // we need neighbors if (!this->repaired) CONFESS("split() requires repair()"); // loop while we have remaining facets while (1) { // get the first facet std::queue<int> facet_queue; std::deque<int> facets; for (int facet_idx = 0; facet_idx < this->stl.stats.number_of_facets; facet_idx++) { if (seen_facets.find(facet_idx) == seen_facets.end()) { // if facet was not seen put it into queue and start searching facet_queue.push(facet_idx); break; } } if (facet_queue.empty()) break; while (!facet_queue.empty()) { int facet_idx = facet_queue.front(); facet_queue.pop(); if (seen_facets.find(facet_idx) != seen_facets.end()) continue; facets.push_back(facet_idx); for (int j = 0; j <= 2; j++) { facet_queue.push(this->stl.neighbors_start[facet_idx].neighbor[j]); } seen_facets.insert(facet_idx); } TriangleMesh* mesh = new TriangleMesh; meshes.push_back(mesh); mesh->stl.stats.type = inmemory; mesh->stl.stats.number_of_facets = facets.size(); mesh->stl.stats.original_num_facets = mesh->stl.stats.number_of_facets; stl_allocate(&mesh->stl); for (std::deque<int>::const_iterator facet = facets.begin(); facet != facets.end(); facet++) { mesh->stl.facet_start[facet - facets.begin()] = this->stl.facet_start[*facet]; } } return meshes; }
/* This constructor builds a Flow object from an extrusion width config setting and other context properties. */ Flow Flow::new_from_config_width(FlowRole role, const ConfigOptionFloatOrPercent &width, float nozzle_diameter, float height, float bridge_flow_ratio) { // we need layer height unless it's a bridge if (height <= 0 && bridge_flow_ratio == 0) CONFESS("Invalid flow height supplied to new_from_config_width()"); float w; if (bridge_flow_ratio > 0) { // if bridge flow was requested, calculate bridge width w = Flow::_bridge_width(nozzle_diameter, bridge_flow_ratio); } else if (!width.percent && width.value == 0) { // if user left option to 0, calculate a sane default width w = Flow::_auto_width(role, nozzle_diameter, height); } else { // if user set a manual value, use it w = width.get_abs_value(height); } return Flow(w, height, nozzle_diameter, bridge_flow_ratio > 0); }
void ExtrusionLoop::split_at_vertex(const Point &point) { for (ExtrusionPaths::iterator path = this->paths.begin(); path != this->paths.end(); ++path) { int idx = path->polyline.find_point(point); if (idx != -1) { if (this->paths.size() == 1) { // just change the order of points path->polyline.points.insert(path->polyline.points.end(), path->polyline.points.begin() + 1, path->polyline.points.begin() + idx + 1); path->polyline.points.erase(path->polyline.points.begin(), path->polyline.points.begin() + idx); } else { // if we have multiple paths we assume they have different types, so no need to // check for continuity as we do for the single path case above // new paths list starts with the second half of current path ExtrusionPaths new_paths; { ExtrusionPath p = *path; p.polyline.points.erase(p.polyline.points.begin(), p.polyline.points.begin() + idx); if (p.polyline.is_valid()) new_paths.push_back(p); } // then we add all paths until the end of current path list new_paths.insert(new_paths.end(), this->paths.begin(), path); // not including this path // then we add all paths since the beginning of current list up to the previous one new_paths.insert(new_paths.end(), path+1, this->paths.end()); // not including this path // finally we add the first half of current path { ExtrusionPath p = *path; p.polyline.points.erase(p.polyline.points.begin() + idx + 1, p.polyline.points.end()); if (p.polyline.is_valid()) new_paths.push_back(p); } // we can now override the old path list with the new one and stop looping this->paths = new_paths; } return; } } CONFESS("Point not found"); }
void ConfigBase::apply(const ConfigBase &other, bool ignore_nonexistent) { // get list of option keys to apply t_config_option_keys opt_keys = other.keys(); // loop through options and apply them for (t_config_option_keys::const_iterator it = opt_keys.begin(); it != opt_keys.end(); ++it) { ConfigOption* my_opt = this->option(*it, true); if (my_opt == NULL) { if (ignore_nonexistent == false) throw "Attempt to apply non-existent option"; continue; } // not the most efficient way, but easier than casting pointers to subclasses bool res = my_opt->deserialize( other.option(*it)->serialize() ); if (!res) { std::string error = "Unexpected failure when deserializing serialized value for " + *it; CONFESS(error.c_str()); } } }
/* duplicate the entire model preserving instance relative positions */ void Model::duplicate(size_t copies_num, coordf_t dist, const BoundingBoxf* bb) { Pointfs model_sizes(copies_num-1, this->bounding_box().size()); Pointfs positions; if (! this->_arrange(model_sizes, dist, bb, positions)) CONFESS("Cannot duplicate part as the resulting objects would not fit on the print bed.\n"); // note that this will leave the object count unaltered for (ModelObjectPtrs::const_iterator o = this->objects.begin(); o != this->objects.end(); ++o) { // make a copy of the pointers in order to avoid recursion when appending their copies ModelInstancePtrs instances = (*o)->instances; for (ModelInstancePtrs::const_iterator i = instances.begin(); i != instances.end(); ++i) { for (Pointfs::const_iterator pos = positions.begin(); pos != positions.end(); ++pos) { ModelInstance* instance = (*o)->add_instance(**i); instance->offset.translate(*pos); } } (*o)->invalidate_bounding_box(); } }
static gdouble spectrum_ramp_wait(struct spectrum_iterator* self) { CONFESS("0x%x: wait idx %d", self, self->idx_linear); return (gdouble)(*(self->idx)); }
Polyline as_polyline() const { CONFESS("Calling as_polyline() on a ExtrusionEntityCollection"); return Polyline(); };
Polyline::operator Line() const { if (this->points.size() > 2) CONFESS("Can't convert polyline with more than two points to a line"); return Line(this->points.front(), this->points.back()); }
std::string GCode::_extrude(ExtrusionPath path, std::string description, double speed) { path.simplify(SCALED_RESOLUTION); std::string gcode; // go to first point of extrusion path if (!this->_last_pos_defined || !this->_last_pos.coincides_with(path.first_point())) { gcode += this->travel_to( path.first_point(), path.role, "move to first " + description + " point" ); } // compensate retraction gcode += this->unretract(); // adjust acceleration { double acceleration; if (this->config.first_layer_acceleration.value > 0 && this->first_layer) { acceleration = this->config.first_layer_acceleration.value; } else if (this->config.perimeter_acceleration.value > 0 && path.is_perimeter()) { acceleration = this->config.perimeter_acceleration.value; } else if (this->config.bridge_acceleration.value > 0 && path.is_bridge()) { acceleration = this->config.bridge_acceleration.value; } else if (this->config.infill_acceleration.value > 0 && path.is_infill()) { acceleration = this->config.infill_acceleration.value; } else { acceleration = this->config.default_acceleration.value; } gcode += this->writer.set_acceleration(acceleration); } // calculate extrusion length per distance unit double e_per_mm = this->writer.extruder()->e_per_mm3 * path.mm3_per_mm; if (this->writer.extrusion_axis().empty()) e_per_mm = 0; // set speed if (speed == -1) { if (path.role == erPerimeter) { speed = this->config.get_abs_value("perimeter_speed"); } else if (path.role == erExternalPerimeter) { speed = this->config.get_abs_value("external_perimeter_speed"); } else if (path.role == erOverhangPerimeter || path.role == erBridgeInfill) { speed = this->config.get_abs_value("bridge_speed"); } else if (path.role == erInternalInfill) { speed = this->config.get_abs_value("infill_speed"); } else if (path.role == erSolidInfill) { speed = this->config.get_abs_value("solid_infill_speed"); } else if (path.role == erTopSolidInfill) { speed = this->config.get_abs_value("top_solid_infill_speed"); } else if (path.role == erGapFill) { speed = this->config.get_abs_value("gap_fill_speed"); } else { CONFESS("Invalid speed"); } } if (this->first_layer) { speed = this->config.get_abs_value("first_layer_speed", speed); } if (this->volumetric_speed != 0 && speed == 0) { speed = this->volumetric_speed / path.mm3_per_mm; } if (this->config.max_volumetric_speed.value > 0) { // cap speed with max_volumetric_speed anyway (even if user is not using autospeed) speed = std::min( speed, this->config.max_volumetric_speed.value / path.mm3_per_mm ); } double F = speed * 60; // convert mm/sec to mm/min // extrude arc or line if (path.is_bridge() && this->enable_cooling_markers) gcode += ";_BRIDGE_FAN_START\n"; if (lowerSpeed) { gcode += this->writer.set_speed(600, "", this->enable_cooling_markers ? ";_EXTRUDE_SET_SPEED" : ""); } else { gcode += this->writer.set_speed(F, "", this->enable_cooling_markers ? ";_EXTRUDE_SET_SPEED" : ""); } double path_length = 0; { std::string comment = this->config.gcode_comments ? description : ""; Lines lines = path.polyline.lines(); for (Lines::const_iterator line = lines.begin(); line != lines.end(); ++line) { const double line_length = line->length() * SCALING_FACTOR; path_length += line_length; gcode += this->writer.extrude_to_xy( this->point_to_gcode(line->b), e_per_mm * line_length, comment ); if (path_length > 10 && lowerSpeed) { lowerSpeed = false; gcode += this->writer.set_speed(F, "", this->enable_cooling_markers ? ";_EXTRUDE_SET_SPEED" : ""); } } lowerSpeed = false; } if (this->wipe.enable) { this->wipe.path = path.polyline; this->wipe.path.reverse(); } if (path.is_bridge() && this->enable_cooling_markers) gcode += ";_BRIDGE_FAN_END\n"; this->set_last_pos(path.last_point()); if (this->config.cooling) this->elapsed_time += path_length / F * 60; return gcode; }