void Layer::MakeSkirt(double distance, bool single) { clearpolys(skirtPolygons); vector<Poly> all; if (single) { // single skirt all.push_back(hullPolygon); all.insert(all.end(),supportPolygons.begin(),supportPolygons.end()); Poly hull = convexHull2D(all); vector<Poly> skp = Clipping::getOffset(hull, distance, jround); if (skp.size()>0){ skirtPolygons.push_back(skp.front()); skirtPolygons[0].setZ(Z); skirtPolygons[0].cleanup(thickness); } } else { // skirt for each shape skirtPolygons = Clipping::getOffset(*GetOuterShell(), distance, jround); } }
// Convert to GCode void Layer::MakeGcode(GCodeState &state, double offsetZ, const Settings::SlicingSettings &slicing, const Settings::HardwareSettings &hardware) { Vector3d start3 = state.LastPosition(); Vector2d startPoint(start3.x,start3.y); double extrf = hardware.GetExtrudeFactor(thickness); double OPTRATIO = 1.5; double optratio = OPTRATIO; double linewidthratio = hardware.ExtrudedMaterialWidthRatio; double linewidth = thickness/linewidthratio; double minspeed = hardware.MinPrintSpeedXY, maxspeed = hardware.MaxPrintSpeedXY; bool linelengthsort = slicing.LinelengthSort; //vector<Vector3d> lines; vector<printline> lines; //cerr << "gcode layer " << LayerNo << "z="<<Z<<endl; Printlines printlines; lines.clear(); // will contain everything vector<Poly> polys; // intermediate collection // 1. Skins, because they are the lowest lines, below layer Z if (skins>1){ for(uint s=1;s <= skins;s++) { // z offset from bottom to top polys.clear(); double sz = Z - thickness + (s)*thickness/skins; // outlines for(size_t p=0;p<skinPolygons.size();p++) { Poly sp(skinPolygons[p],sz); polys.push_back(sp); } // skin infill polys polys.insert(polys.end(), skinFullInfills[s-1]->infillpolys.begin(), skinFullInfills[s-1]->infillpolys.end()); // add all of this skin layer to lines printlines.clear(); printlines.makeLines(polys, startPoint, (s==1), //displace at first skin minspeed, maxspeed, linewidth, linewidthratio, optratio); printlines.slowdownTo(slicing.MinLayertime); printlines.clipMovements(GetOuterShell()); printlines.getLines(lines); } } polys.clear(); // 2. Skirt skirtPolygon.getLines(lines, startPoint); // 3. Support printlines.clear(); printlines.makeLines(supportInfill->infillpolys, startPoint, minspeed, maxspeed, linewidth, linewidthratio, optratio, linelengthsort); printlines.slowdownTo(slicing.MinLayertime); printlines.clipMovements(GetOuterShell()); printlines.getLines(lines); // 4. all other polygons: // Shells for(size_t p=0;p<shellPolygons.size();p++) // outer to inner, in this order polys.insert(polys.end(), shellPolygons[p].begin(),shellPolygons[p].end()); polys.insert(polys.end(), normalInfill->infillpolys.begin(), normalInfill->infillpolys.end()); polys.insert(polys.end(), fullInfill->infillpolys.begin(), fullInfill->infillpolys.end()); polys.insert(polys.end(), decorInfill->infillpolys.begin(), decorInfill->infillpolys.end()); polys.insert(polys.end(), bridgeInfill->infillpolys.begin(), bridgeInfill->infillpolys.end()); printlines.clear(); printlines.makeLines(polys, startPoint, true, //displace at beginning minspeed, maxspeed, linewidth, linewidthratio, optratio, linelengthsort); printlines.slowdownTo(slicing.MinLayertime); printlines.clipMovements(GetOuterShell(), linewidth/2.); printlines.getLines(lines); // push all lines to gcode state.AddLines(lines, extrf, offsetZ, slicing, hardware); }
void Layer::Draw(const Settings &settings) { #if 0 // test single area expolys vector<ExPoly> expolys = Clipping::getExPolys(polygons); draw_polys(expolys, GL_LINE_LOOP, 1, 3, RED, 1); cerr << expolys.size() << endl; Infill exinf(this, 1.); exinf.setName("infill"); double infilldistance = settings.GetInfillDistance(thickness, settings.Slicing.InfillPercent); exinf.addPolys(Z, expolys, HexInfill, infilldistance, infilldistance, 0.4); draw_polys(exinf.infillpolys, GL_LINE_LOOP, 1, 3, (exinf.cached?BLUEGREEN:GREEN), 1); return; #endif bool randomized = settings.get_boolean("Display","RandomizedLines"); bool filledpolygons = settings.get_boolean("Display","DisplayFilledAreas"); // glEnable(GL_LINE_SMOOTH); // glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); draw_polys(polygons, GL_LINE_LOOP, 1, 3, RED, 1, randomized); draw_polys(polygons, GL_POINTS, 1, 3, RED, 1, randomized); if(settings.get_boolean("Display","DrawCPOutlineNumbers")) for(size_t p=0; p<polygons.size();p++) { ostringstream oss; oss << p; Vector2d center = polygons[p].getCenter(); Render::draw_string(Vector3d(center.x(), center.y(), Z), oss.str()); } draw_poly(hullPolygon, GL_LINE_LOOP, 3, 3, ORANGE, 0.5, randomized); draw_polys(skirtPolygons, GL_LINE_LOOP, 3, 3, YELLOW, 1, randomized); draw_polys(shellPolygons, GL_LINE_LOOP, 1, 3, YELLOW2, 1, randomized); draw_polys(thinPolygons, GL_LINE_LOOP, 2, 3, YELLOW, 1, randomized); glColor4f(0.5,0.9,1,1); glLineWidth(1); double zs = Z; for(size_t s=0;s<skins;s++) { for(size_t p=0; p < skinPolygons.size();p++) { //cerr << s << ": " << p << " _ " << zs << endl; skinPolygons[p].draw(GL_LINE_LOOP, zs, randomized); } zs-=thickness/skins; } draw_polys(fillPolygons, GL_LINE_LOOP, 1, 3, WHITE, 0.6, randomized); if (supportPolygons.size()>0) { if (filledpolygons) draw_polys_surface(supportPolygons, Min, Max, Z, thickness/2., BLUE2, 0.4); draw_polys(supportPolygons, GL_LINE_LOOP, 3, 3, BLUE2, 1, randomized); if(settings.get_boolean("Display","DrawVertexNumbers")) for(size_t p=0; p<supportPolygons.size();p++) supportPolygons[p].drawVertexNumbers(); } // else // draw_polys(toSupportPolygons, GL_LINE_LOOP, 1, 1, BLUE2, 1, randomized); draw_polys(bridgePolygons, GL_LINE_LOOP, 3, 3, RED2, 0.7, randomized); draw_polys(fullFillPolygons, GL_LINE_LOOP, 1, 1, GREY, 0.6, randomized); draw_polys(decorPolygons, GL_LINE_LOOP, 1, 3, WHITE, 1, randomized); draw_polys(skinFullFillPolygons, GL_LINE_LOOP, 1, 3, GREY, 0.6, randomized); if (filledpolygons) { draw_polys_surface(fullFillPolygons, Min, Max, Z, thickness/2., GREEN, 0.5); draw_polys_surface(decorPolygons, Min, Max, Z, thickness/2., GREY, 0.2); } if(settings.get_boolean("Display","DisplayinFill")) { if (filledpolygons) draw_polys_surface(fillPolygons, Min, Max, Z, thickness/2., GREEN2, 0.25); bool DebugInfill = settings.get_boolean("Display","DisplayDebuginFill"); if (normalInfill) draw_polys(normalInfill->infillpolys, GL_LINE_LOOP, 1, 3, (normalInfill->cached?BLUEGREEN:GREEN), 1, randomized); if(DebugInfill && normalInfill->cached) draw_polys(normalInfill->getCachedPattern(Z), GL_LINE_LOOP, 1, 3, ORANGE, 0.5, randomized); if (thinInfill) draw_polys(thinInfill->infillpolys, GL_LINE_LOOP, 1, 3, GREEN, 1, randomized); if (fullInfill) draw_polys(fullInfill->infillpolys, GL_LINE_LOOP, 1, 3, (fullInfill->cached?BLUEGREEN:GREEN), 0.8, randomized); if (skirtInfill) draw_polys(skirtInfill->infillpolys, GL_LINE_LOOP, 1, 3, YELLOW, 0.6, randomized); if(DebugInfill && fullInfill->cached) draw_polys(fullInfill->getCachedPattern(Z), GL_LINE_LOOP, 1, 3, ORANGE, 0.5, randomized); if (decorInfill) draw_polys(decorInfill->infillpolys, GL_LINE_LOOP, 1, 3, (decorInfill->cached?BLUEGREEN:GREEN), 0.8, randomized); if(DebugInfill && decorInfill->cached) draw_polys(decorInfill->getCachedPattern(Z), GL_LINE_LOOP, 1, 3, ORANGE, 0.5, randomized); uint bridgecount = bridgeInfills.size(); if (bridgecount>0) for (uint i = 0; i<bridgecount; i++) draw_polys(bridgeInfills[i]->infillpolys, GL_LINE_LOOP, 2, 3, RED3,0.9, randomized); if (supportInfill) draw_polys(supportInfill->infillpolys, GL_LINE_LOOP, 1, 3, (supportInfill->cached?BLUEGREEN:GREEN), 0.8, randomized); if(DebugInfill && supportInfill->cached) draw_polys(supportInfill->getCachedPattern(Z), GL_LINE_LOOP, 1, 3, ORANGE, 0.5, randomized); for(size_t s=0;s<skinFullInfills.size();s++) draw_polys(skinFullInfills[s]->infillpolys, GL_LINE_LOOP, 1, 3, (skinFullInfills[s]->cached?BLUEGREEN:GREEN), 0.6, randomized); } //draw_polys(GetInnerShell(), GL_LINE_LOOP, 2, 3, WHITE, 1); glLineWidth(1); if(settings.get_boolean("Display","DrawCPVertexNumbers")) // poly vertex numbers for(size_t p=0; p<polygons.size();p++) polygons[p].drawVertexNumbers(); //polygons[p].drawVertexAngles(); if(settings.get_boolean("Display","DrawCPLineNumbers")) // poly line numbers for(size_t p=0; p<polygons.size();p++) polygons[p].drawLineNumbers(); if(settings.get_boolean("Display","DrawVertexNumbers")) { // infill vertex numbers for(size_t p=0; p<fillPolygons.size();p++) fillPolygons[p].drawVertexNumbers(); for(size_t p=0; p<fullFillPolygons.size();p++) fullFillPolygons[p].drawVertexNumbers(); for(size_t p=0; p<decorPolygons.size();p++) decorPolygons[p].drawVertexNumbers(); for(size_t p=0; p<shellPolygons.size();p++) for(size_t q=0; q<shellPolygons[p].size();q++) shellPolygons[p][q].drawVertexNumbers(); } if (settings.get_boolean("Display","ShowLayerOverhang")) { draw_polys(bridgePillars, GL_LINE_LOOP, 3, 3, YELLOW,0.7, randomized); if (previous!=NULL) { vector<Poly> overhangs = getOverhangs(); draw_polys(overhangs, GL_LINE_LOOP, 1, 3, VIOLET, 0.8, randomized); //draw_polys_surface(overhangs, Min, Max, Z, thickness/5, VIOLET , 0.5); Cairo::RefPtr<Cairo::ImageSurface> surface; Cairo::RefPtr<Cairo::Context> context; if (rasterpolys(overhangs, Min, Max, thickness/5, surface, context)) if(surface!=0) { glColor4f(RED[0],RED[1],RED[2], 0.5); glDrawCairoSurface(surface, Min, Max, Z); glColor4f(RED[0],RED[1],RED[2], 0.6); glPointSize(3); glBegin(GL_POINTS); for (double x = Min.x(); x<Max.x(); x+=thickness) for (double y = Min.y(); y<Max.y(); y+=thickness) if (getCairoSurfaceDatapoint(surface, Min, Max, Vector2d(x,y))!=0) glVertex3d(x,y,Z); glEnd(); } } } #if 0 // test point-in-polygons const vector<Poly> *polys = GetOuterShell(); glColor4f(RED[0],RED[1],RED[2], 0.6); glPointSize(3); glBegin(GL_POINTS); for (double x = Min.x(); x<Max.x(); x+=thickness/1) for (double y = Min.y(); y<Max.y(); y+=thickness/1) { bool inpoly = false; for (uint i=0; i<polys->size(); i++) { if ((*polys)[i].vertexInside(Vector2d(x,y))){ inpoly=true; break; } } if (inpoly) glVertex3d(x,y,Z); // else // glColor4f(0.3,0.3,0.3, 0.6); } glEnd(); #endif }
// Convert to Printlines void Layer::MakePrintlines(Vector3d &lastPos, //GCodeState &state, vector<PLine3> &lines3, double offsetZ, Settings &settings) const { const double linewidth = settings.GetExtrudedMaterialWidth(thickness); const double cornerradius = linewidth*settings.get_double("Slicing","CornerRadius"); const bool clipnearest = settings.get_boolean("Slicing","MoveNearest"); const uint supportExtruder = settings.GetSupportExtruder(); const double minshelltime = settings.get_double("Slicing","MinShelltime"); const double maxshellspeed = settings.get_double("Extruder","MaxShellSpeed"); const bool ZliftAlways = settings.get_boolean("Extruder","ZliftAlways"); Vector2d startPoint(lastPos.x(),lastPos.y()); const double extr_per_mm = settings.GetExtrusionPerMM(thickness); //vector<PLine3> lines3; Printlines printlines(this, &settings, offsetZ); vector<PLine2> lines; vector<Poly> polys; // intermediate collection // polys to keep line movements inside //const vector<Poly> * clippolys = &polygons; const vector<Poly> * clippolys = GetOuterShell(); // 1. Skins, all but last, because they are the lowest lines, below layer Z if (skins > 1) { for(uint s = 0; s < skins; s++) { // z offset from bottom to top: double skin_z = Z - thickness + (s+1)*thickness/skins; if ( skin_z < 0 ){ cerr << "Skin Z<0! " << s << " -- " << Z << " -- "<<skin_z <<" -- " << thickness << endl; continue; } // skin infill polys: if (skinFullInfills[s]) polys.insert(polys.end(), skinFullInfills[s]->infillpolys.begin(), skinFullInfills[s]->infillpolys.end()); // add skin infill to lines printlines.addPolys(INFILL, polys, false); polys.clear(); // make polygons at skin_z: for(size_t p = 0; p < skinPolygons.size(); p++) { polys.push_back(Poly(skinPolygons[p], skin_z)); } // add skin to lines printlines.addPolys(SKIN, polys, (s==0), // displace at first skin maxshellspeed * 60, minshelltime); if (s < skins-1) { // not on the last layer, this handle with all other lines // have to get all these separately because z changes printlines.makeLines(startPoint, lines); if (!ZliftAlways) printlines.clipMovements(*clippolys, lines, clipnearest, linewidth); printlines.optimize(linewidth, minshelltime, cornerradius, lines); printlines.getLines(lines, lines3, extr_per_mm); printlines.clear(); lines.clear(); } polys.clear(); } } // last skin layer now still in lines lines.clear(); // 2. Skirt printlines.addPolys(SKIRT, skirtPolygons, false, maxshellspeed * 60, minshelltime); // 3. Support if (supportInfill) { uint extruderbefore = settings.selectedExtruder; settings.SelectExtruder(supportExtruder); printlines.addPolys(SUPPORT, supportInfill->infillpolys, false); settings.SelectExtruder(extruderbefore); } // 4. all other polygons: // Shells for(int p=shellPolygons.size()-1; p>=0; p--) { // inner to outer printlines.addPolys(SHELL, shellPolygons[p], (p==(int)(shellPolygons.size())-1), maxshellspeed * 60, minshelltime); } // Infill if (normalInfill) printlines.addPolys(INFILL, normalInfill->infillpolys, false); if (thinInfill) printlines.addPolys(INFILL, thinInfill->infillpolys, false); if (fullInfill) printlines.addPolys(INFILL, fullInfill->infillpolys, false); if (skirtInfill) printlines.addPolys(INFILL, skirtInfill->infillpolys, false); if (decorInfill) printlines.addPolys(INFILL, decorInfill->infillpolys, false); for (uint b=0; b < bridgeInfills.size(); b++) if (bridgeInfills[b]) printlines.addPolys(INFILL, bridgeInfills[b]->infillpolys, false); double polyspeedfactor = printlines.makeLines(startPoint, lines); // FINISH Command lchange(LAYERCHANGE, LayerNo); lchange.where = Vector3d(0.,0.,Z); lchange.comment += info(); lines3.push_back(PLine3(lchange)); if (!ZliftAlways) printlines.clipMovements(*clippolys, lines, clipnearest, linewidth); printlines.optimize(linewidth, settings.get_double("Slicing","MinLayertime"), cornerradius, lines); if ((guint)LayerNo < (guint)settings.get_integer("Slicing","FirstLayersNum")) printlines.setSpeedFactor(settings.get_double("Slicing","FirstLayersSpeed"), lines); double slowdownfactor = printlines.getSlowdownFactor() * polyspeedfactor; if (settings.get_boolean("Slicing","FanControl")) { int fanspeed = settings.get_integer("Slicing","MinFanSpeed"); if (slowdownfactor < 1 && slowdownfactor > 0) { double fanfactor = 1-slowdownfactor; fanspeed += int(fanfactor * (settings.get_integer("Slicing","MaxFanSpeed")-settings.get_integer("Slicing","MinFanSpeed"))); fanspeed = CLAMP(fanspeed, settings.get_integer("Slicing","MinFanSpeed"), settings.get_integer("Slicing","MaxFanSpeed")); //cerr << slowdownfactor << " - " << fanfactor << " - " << fanspeed << " - " << endl; } Command fancommand(FANON, fanspeed); lines3.push_back(PLine3(fancommand)); } printlines.getLines(lines, lines3, extr_per_mm); if (lines3.size()>0) lastPos = lines3.back().to; }
void Layer::CalcInfill (const Settings &settings) { // inFill distances in real mm: // for full polys/layers: double fullInfillDistance=0; double infillDistance=0; // normal fill double altInfillDistance=0; double altInfillPercent=settings.get_double("Slicing","InfillPercent"); double normalInfilldist=0; bool shellOnly = !settings.get_boolean("Slicing","DoInfill"); fullInfillDistance = settings.GetInfillDistance(thickness, 100); if (settings.get_double("Slicing","InfillPercent") == 0) shellOnly = true; else infillDistance = settings.GetInfillDistance(thickness,altInfillPercent); int altinfill = settings.get_integer("Slicing","AltInfillLayers"); normalInfilldist = infillDistance; if ( altinfill != 0 && LayerNo % altinfill == 0 && altInfillPercent != 0) { altInfillDistance = settings.GetInfillDistance(thickness, settings.get_double("Slicing","AltInfillPercent")); normalInfilldist = altInfillDistance; } // first layers: if (LayerNo < (int)settings.get_integer("Slicing","FirstLayersNum")) { double first_infdist = fullInfillDistance * (1.+settings.get_double("Slicing","FirstLayersInfillDist")); normalInfilldist = max(normalInfilldist, first_infdist); fullInfillDistance = max(fullInfillDistance, first_infdist); } // relative extrusion for skins: double skinfillextrf = settings.get_double("Slicing","FullFillExtrusion")/skins/skins; normalInfill = new Infill(this,settings.get_double("Slicing","NormalFillExtrusion")); normalInfill->setName("normal"); fullInfill = new Infill(this,settings.get_double("Slicing","FullFillExtrusion")); fullInfill->setName("full"); skirtInfill = new Infill(this,settings.get_double("Slicing","FullFillExtrusion")); skirtInfill->setName("skirt"); skinFullInfills.clear(); supportInfill = new Infill(this,settings.get_double("Slicing","SupportExtrusion")); supportInfill->setName("support"); decorInfill = new Infill(this,1.); decorInfill->setName("decor"); thinInfill = new Infill(this, 1.); thinInfill->setName("thin"); double rot = (settings.get_double("Slicing","InfillRotation"), + (double)LayerNo*settings.get_double("Slicing","InfillRotationPrLayer"))/180.0*M_PI; if (!shellOnly) normalInfill->addPolys(Z, fillPolygons, (InfillType)settings.get_integer("Slicing","NormalFilltype"), normalInfilldist, fullInfillDistance, rot); if (settings.get_boolean("Slicing","FillSkirt")) { vector<Poly> skirtFill; Clipping clipp; clipp.addPolys(skirtPolygons, subject); clipp.addPolys(*GetOuterShell(), clip); clipp.addPolys(supportPolygons, clip); skirtFill = clipp.subtract(); skirtFill = Clipping::getOffset(skirtFill, -fullInfillDistance); skirtInfill->addPolys(Z, skirtFill, (InfillType)settings.get_integer("Slicing","FullFilltype"), fullInfillDistance, fullInfillDistance, rot); } fullInfill->addPolys(Z, fullFillPolygons, (InfillType)settings.get_integer("Slicing","FullFilltype"), fullInfillDistance, fullInfillDistance, rot); decorInfill->addPolys(Z, decorPolygons, (InfillType)settings.get_integer("Slicing","DecorFilltype"), settings.get_double("Slicing","DecorInfillDistance"), settings.get_double("Slicing","DecorInfillDistance"), settings.get_double("Slicing","DecorInfillRotation")/180.0*M_PI); assert(bridge_angles.size() >= bridgePolygons.size()); bridgeInfills.resize(bridgePolygons.size()); for (uint b=0; b < bridgePolygons.size(); b++){ bridgeInfills[b] = new Infill(this, settings.get_double("Slicing","BridgeExtrusion")); bridgeInfills[b]->addPoly(Z, bridgePolygons[b], BridgeInfill, fullInfillDistance, fullInfillDistance, bridge_angles[b]+M_PI/2); } if (skins>1) { double skindistance = fullInfillDistance/skins; for (uint s = 0; s<skins; s++){ double drot = rot + settings.get_double("Slicing","InfillRotationPrLayer")/180.0*M_PI*s; double sz = Z-thickness + (s+1)*thickness/skins; Infill *inf = new Infill(this, skinfillextrf); inf->setName("skin"); inf->addPolys(sz, skinFullFillPolygons, (InfillType)settings.get_integer("Slicing","FullFilltype"), skindistance, skindistance, drot); skinFullInfills.push_back(inf); } } supportInfill->addPolys(Z, supportPolygons, (InfillType)settings.get_integer("Slicing","SupportFilltype"), settings.get_double("Slicing","SupportInfillDistance"), settings.get_double("Slicing","SupportInfillDistance"), 0); thinInfill->addPolys(Z, thinPolygons, ThinInfill, fullInfillDistance, fullInfillDistance, 0); }