void Model::MakeSkirt() { if (!settings.get_boolean("Slicing","Skirt")) return; double skirtdistance = settings.get_double("Slicing","SkirtDistance"); Clipping clipp; guint count = layers.size(); guint endindex = 0; // find maximum of all calculated skirts clipp.clear(); double skirtheight = settings.get_double("Slicing","SkirtHeight"); bool singleskirt = settings.get_boolean("Slicing","SingleSkirt"); bool support = settings.get_boolean("Slicing","Support"); for (guint i=0; i < count; i++) { if (layers[i]->getZ() > skirtheight) break; layers[i]->MakeSkirt(skirtdistance, singleskirt && !support); vector<Poly> sp = layers[i]->GetSkirtPolygons(); clipp.addPolys(sp,subject); endindex = i; } vector<Poly> skirts = clipp.unite(CL::pftPositive,CL::pftPositive); // set this skirt for all skirted layers if (skirts.size()>0) for (guint i=0; i<=endindex; i++) { layers[i]->setSkirtPolygons(skirts); } }
vector<Poly> Clipping::getPolys(const ExPoly &expoly) { Clipping clipp; clipp.addPoly(expoly.outer, subject); clipp.addPolys(expoly.holes, clip); vector<Poly> polys = clipp.subtract(); return polys; }
vector<Poly> Layer::getOverhangs() const { vector<Poly> overhangs; if (previous!=NULL) { Clipping clipp; clipp.addPolys(polygons, subject); vector<Poly> prevoffset = Clipping::getOffset(previous->polygons, thickness/2); clipp.addPolys(prevoffset, clip); clipp.setZ(Z); overhangs = clipp.subtract();//CL::pftNonZero,CL::pftNonZero); } return overhangs; }
void Viewport::transformAndClipObj(Object* obj){ auto t = m_window.getT(); obj->transformNormalized(t); if(!m_clipping.clip(obj)) obj->getNCoords().clear(); }
void Model::MakeSupportPolygons(Layer * layer, // lower -> will change const Layer * layerabove, // upper double widen) { const double distance = settings.GetExtrudedMaterialWidth(layer->thickness); // vector<Poly> tosupport = Clipping::getOffset(layerabove->GetToSupportPolygons(), // distance/2.); //vector<Poly> tosupport = Clipping::getMerged(layerabove->GetToSupportPolygons(), // distance); vector<Poly> tosupport = layerabove->GetToSupportPolygons(); Clipping clipp; clipp.addPolys(layerabove->GetSupportPolygons(), subject); clipp.addPolys(tosupport, subject); clipp.addPolys(layer->GetPolygons(), clip); clipp.setZ(layer->getZ()); vector<Poly> spolys = clipp.subtract(CL::pftNonZero,CL::pftEvenOdd); if (widen != 0) // widen from layer to layer spolys = clipp.getOffset(spolys, widen * layer->thickness); spolys = clipp.getMerged(spolys,distance); layer->setSupportPolygons(spolys); }
// add bridge polys and substract them from normal and full fill polys void Layer::addBridgePolygons(const vector<Poly> newpolys) { if (newpolys.size()==0) return; bridgePolygons.clear(); Clipping clipp; clipp.clear(); clipp.addPolys(fillPolygons,subject); clipp.addPolys(newpolys,clip); vector<Poly> inter = clipp.intersect(); bridgePolygons= inter;//.insert(bridgePolygons.end(),inter.begin(),inter.end()); clipp.clear(); clipp.addPolys(fillPolygons,subject); clipp.addPolys(inter,clip); setNormalFillPolygons(clipp.substract()); mergeFullPolygons(true); }
void Layer::calcBridgeAngles(const Layer *layerbelow) { bridge_angles.resize(bridgePolygons.size()); Clipping clipp; vector<Poly> polysbelow = *(layerbelow->GetInnerShell());//clipp.getOffset(polygons,3*thickness); bridgePillars.resize(bridgePolygons.size()); for (uint i=0; i<bridgePolygons.size(); i++) { // intersect bridge poly with polygons below (=pillars of bridge) clipp.clear(); clipp.addPolys(polysbelow,subject); clipp.addPolys(clipp.getOffset(bridgePolygons[i].outer,thickness),clip); bridgePillars[i] = clipp.intersect(); // TODO detect circular bridges -> rotating infill? // get average direction of the mutual connections of all the intersections Vector2d dir(0,0); for (uint p=0; p<bridgePillars[i].size(); p++){ for (uint q=p+1; q<bridgePillars[i].size(); q++){ // Vector2d p1,p2; // bridgePillars[i][q].shortestConnectionSq(bridgePillars[i][p], p1,p2); // dir += (p2-p1); dir += bridgePillars[i][q].center - bridgePillars[i][p].center; } } //cerr << pillars.size() << " - " << dir << endl; bridge_angles[i] = atan2(dir.y(),dir.x()); if (bridge_angles[i]<0) bridge_angles[i]+=M_PI; } }
// add bridge polys and subtract them from normal and full fill polys // each given ExPoly is a single bridge with its holes void Layer::addBridgePolygons(const vector<ExPoly> &newexpolys) { // clip against normal fill and make these areas into bridges: Clipping clipp; uint num_bridges = newexpolys.size(); if (num_bridges==0) return; clipp.clear(); bridgePolygons.clear(); for (uint i=0; i < num_bridges; i++){ vector<Poly> newpolys = Clipping::getPolys(newexpolys[i]); clipp.clear(); clipp.addPolys(fillPolygons,subject); clipp.addPolys(newpolys, clip); vector<ExPoly> exbridges = clipp.ext_intersect(); bridgePolygons.insert(bridgePolygons.end(),exbridges.begin(),exbridges.end()); } // subtract from normal fill clipp.clear(); clipp.addPolys(fillPolygons,subject); clipp.addPolys(newexpolys, clip); setNormalFillPolygons(clipp.subtract()); }
void Viewport::transformAndClipObj(Object* obj){ auto t = m_window.getT(); obj->transformNormalized(t); if(m_window.getD() != 0) obj->applyPerspective(m_window.getD()); obj->transformNormalized(Transformation::newScaling(1.0/m_window.getWidth(), 1.0/m_window.getHeight(), 2.0/(m_window.getWidth() + m_window.getHeight())),false); //2.0/(m_window.getWidth() + m_window.getHeight()) if(!m_clipping.clip(obj)) obj->getNCoords().clear(); }
void Viewport::transformAndClipObj(Object* obj){ auto t = m_window.getT(); bool shouldDraw = true; obj->transformNormalized(t); switch(obj->getType()){ case ObjType::OBJECT: shouldDraw = false; break; case ObjType::POINT: shouldDraw = m_clipping.clipPoint((Point*)obj); break; case ObjType::LINE: shouldDraw = m_clipping.clipLine((Line*)obj); break; case ObjType::POLYGON: shouldDraw = m_clipping.clipPolygon((Polygon*)obj); break; } if(!shouldDraw) obj->getNCoords().clear(); }
void Layer::FindThinpolys(const vector<Poly> &polys, double extrwidth, vector<Poly> &thickpolys, vector<Poly> &thinpolys) { #define THINPOLYS 1 #if THINPOLYS // go in thickpolys = Clipping::getOffset(polys, -0.5*extrwidth); // go out again, now thin polys are gone thickpolys = Clipping::getOffset(thickpolys, 0.55*extrwidth); // (need overlap to really clip) // use bigger (longer) polys for clip to avoid overlap of thin and thick extrusion lines vector <Poly> bigthick = Clipping::getOffset(thickpolys, extrwidth); // difference to original are thin polys Clipping clipp; clipp.addPolys(polys, subject); clipp.addPolys(bigthick, clip); thinpolys = clipp.subtract(); // remove overlap thickpolys = Clipping::getOffset(thickpolys, -0.05*extrwidth); #else thickpolys = polys; #endif }
// add full fill and substract them from normal fill polys void Layer::addFullPolygons(const vector<Poly> newpolys, bool decor) { if (newpolys.size()==0) return; Clipping clipp; clipp.clear(); // full fill only where already normal fill clipp.addPolys(fillPolygons,subject); clipp.addPolys(newpolys,clip); vector<Poly> inter = clipp.intersect(); if (decor) decorPolygons.insert(decorPolygons.end(),inter.begin(),inter.end()); else fullFillPolygons.insert(fullFillPolygons.end(),inter.begin(),inter.end()); //substract from normal fills clipp.clear(); clipp.addPolys(fillPolygons,subject); clipp.addPolys(inter,clip); setNormalFillPolygons(clipp.substract()); mergeFullPolygons(false); }
// find polys in subjlayer that are not covered by shell of cliplayer vector<Poly> Model::GetUncoveredPolygons(const Layer * subjlayer, const Layer * cliplayer) { Clipping clipp; clipp.clear(); clipp.addPolys(subjlayer->GetFillPolygons(), subject); clipp.addPolys(subjlayer->GetFullFillPolygons(), subject); clipp.addPolys(subjlayer->GetBridgePolygons(), subject); clipp.addPolys(subjlayer->GetDecorPolygons(), subject); //clipp.addPolys(cliplayer->GetOuterShell(), clip); // have some overlap clipp.addPolys(cliplayer->GetInnerShell(), clip); // have some more overlap vector<Poly> uncovered = clipp.subtractMerged(); return uncovered; }
void Layer::calcBridgeAngles(const Layer *layerbelow) { bridge_angles.resize(bridgePolygons.size()); Clipping clipp; vector<Poly> polysbelow = layerbelow->polygons;//clipp.getOffset(polygons,3*thickness); for (uint i=0; i<bridgePolygons.size(); i++) { // intersect bridge poly with polygons below (=pillars of bridge) clipp.clear(); clipp.addPolys(polysbelow,subject); clipp.addPolys(clipp.getOffset(bridgePolygons[i],2*thickness),clip); vector<Poly> pillars = clipp.intersect(); // get average direction of the connection lines of all the intersections Vector2d dir(0,0); for (uint p=0; p<pillars.size(); p++){ for (uint q=p+1; q<pillars.size(); q++){ dir+=pillars[q].center-pillars[p].center; } } //cerr << pillars.size() << " - " << dir << endl; bridge_angles[i] = atan2(dir.y,dir.x); } }
// these are used for the bridge polys of the layer above vector <double> Layer::getBridgeRotations(const vector<Poly> polys) const{ vector<double> angles; angles.resize(polys.size()); Clipping clipp; vector<Poly> offset = polygons;//clipp.getOffset(polygons,3*thickness); for (uint i=0; i<polys.size(); i++) { // intersect bridge poly with polygons below (=pillars of bridge) clipp.clear(); clipp.addPolys(offset,subject); clipp.addPolys(clipp.getOffset(polys[i],2*thickness),clip); vector<Poly> pillars = clipp.intersect(); // get average direction of the connection lines of all the intersections Vector2d dir(0,0); for (uint p=0; p<pillars.size(); p++){ for (uint q=p+1; q<pillars.size(); q++){ dir+=pillars[q].center-pillars[p].center; } } //cerr << pillars.size() << " - " << dir << endl; angles[i] = atan2(dir.y,dir.x); } return angles; }
void Layer::mergeFullPolygons(bool bridge) { // if (bridge) { // // setBridgePolygons(Clipping::getMerged(bridgePolygons, thickness)); // // clipp.addPolys(bridgePolygons,clip); // } else { //subtract decor from full Clipping clipp; // clipp.addPolys(fullFillPolygons,subject); // clipp.addPolys(decorPolygons,clip); // setFullFillPolygons(clipp.subtract()); setFullFillPolygons(Clipping::getMerged(fullFillPolygons, thickness)); cleanup(fullFillPolygons, thickness/CLEANFACTOR); //subtract from normal fills clipp.clear(); cleanup(fillPolygons, thickness/CLEANFACTOR); clipp.addPolys(fillPolygons,subject); clipp.addPolys(fullFillPolygons,clip); clipp.addPolys(decorPolygons,clip); vector<Poly> normals = clipp.subtractMerged(); setNormalFillPolygons(normals); // } }
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); }
// add full fill and subtract them from normal fill polys void Layer::addFullPolygons(const vector<Poly> &newpolys, bool decor) { if (newpolys.size()==0) return; Clipping clipp; clipp.clear(); // full fill only where already normal fill clipp.addPolys(fillPolygons,subject); if (decor) clipp.addPolys(fullFillPolygons,subject); clipp.addPolys(newpolys,clip); clipp.setZ(Z); vector<Poly> inter = clipp.intersect(); vector<Poly> normals = clipp.subtractMerged(thickness/2.); if (decor) {// && LayerNo != 0) // no decor on base layers decorPolygons.insert(decorPolygons.end(), inter.begin(), inter.end()); Clipping clipp; clipp.addPolys(fullFillPolygons,subject); clipp.addPolys(inter,clip); clipp.setZ(Z); setFullFillPolygons(clipp.subtract()); } else { fullFillPolygons.insert(fullFillPolygons.end(),inter.begin(),inter.end()); } setNormalFillPolygons(normals); // mergeFullPolygons(false); // done separately }