void MakePolygonFromInts(int *ints, int size, ClipperLib::Polygon &p) { p.clear(); p.reserve(size / 2); for (int i = 0; i < size; i +=2) p.push_back(IntPoint(ints[i], ints[i+1])); }
void Slic3rPolygon_to_ClipperPolygon(const Slic3r::Polygon &input, ClipperLib::Polygon &output) { output.clear(); for (Slic3r::Points::const_iterator pit = input.points.begin(); pit != input.points.end(); ++pit) { output.push_back(ClipperLib::IntPoint( (*pit).x, (*pit).y )); } }
void ClipperPolygon_to_Slic3rPolygon(const ClipperLib::Polygon &input, Slic3r::Polygon &output) { output.points.clear(); for (ClipperLib::Polygon::const_iterator pit = input.begin(); pit != input.end(); ++pit) { output.points.push_back(Slic3r::Point( (*pit).X, (*pit).Y )); } }
ClipperLib::Polygon Rectangle::toClipperPolygon() const { ClipperLib::Polygon ret; ret.push_back(topleft); ret.push_back(glm::vec2(topleft.x, bottomright.y)); ret.push_back(bottomright); ret.push_back(glm::vec2(bottomright.x, topleft.y)); return ret; }
void polygonFromQxClipper(const QPolygonF& qxPolygon, ClipperLib::Polygon &clipperPolygon) { clipperPolygon.clear(); clipperPolygon.reserve(qxPolygon.size()); foreach(const QPointF &point, qxPolygon) { clipperPolygon.push_back(ClipperLib::IntPoint(point.x()*ConversionFactor, point.y()*ConversionFactor)); }
TPPLPoly TPPLPoly_To_Polygon(const ClipperLib::Polygon& B) { TPPLPoly poly; poly.Init(B.size()); for(unsigned int i=0; i < B.size() ; ++i) { poly[i].x = B[i].X; poly[i].y = B[i].Y; } return poly; }
//-------------------------------------------------------------- ofPolyline ofxClipper::polygon_to_ofPolyline(ClipperLib::Polygon& polygon) { vector<ClipperLib::IntPoint>::iterator iter; ofPolyline polyline; for(iter = polygon.begin(); iter != polygon.end(); iter++) { ofPoint pnt((*iter).X / double(clipperGlobalScale), // bring back to our coords (*iter).Y / double(clipperGlobalScale)); // bring back to our coords polyline.addVertex(pnt); } polyline.close(); // close it return polyline; }
//-------------------------------------------------------------- ClipperLib::Polygon ofxClipper::ofPolyline_to_Polygon(ofPolyline& polyline) { vector<ofPoint> verts = polyline.getVertices(); vector<ofPoint>::iterator iter; ClipperLib::Polygon polygon; for(iter = verts.begin(); iter != verts.end(); iter++) { ClipperLib::IntPoint ip((*iter).x * clipperGlobalScale, (*iter).y * clipperGlobalScale); polygon.push_back(ip); } return polygon; }
void GCodePlanner::addPolygon(ClipperLib::Polygon& polygon, int startIdx, GCodePathConfig* config) { Point p0 = polygon[startIdx]; addTravel(p0); for(unsigned int i=1; i<polygon.size(); i++) { Point p1 = polygon[(startIdx + i) % polygon.size()]; addExtrusionMove(p1, config); p0 = p1; } if (polygon.size() > 2) addExtrusionMove(polygon[startIdx], config); }
void Slice::fillPolygonLayer(){ //for every layer for(int j=0; j<this->pointLayer.size(); j++){ Polygons layer; for(int k=0; k<this->pointLayer.at(j)->size(); k++){ ClipperLib::Polygon p; for(int i=0; i<this->pointLayer.at(j)->at(k)->size(); i++){ p.push_back(ClipperLib::IntPoint((int)(this->pointLayer.at(j)->at(k)->at(i).x()*1000),(int)(this->pointLayer.at(j)->at(k)->at(i).y()*1000))); } layer.push_back(p); } this->polygonLayer.append(layer); } }
int main(int argc, char* argv[]) { if (argc != 3) { cout<<"Usage: offset.exe <input.poly> <output.poly>\n\n Input and output files should be different.\n Only one ring poly files are accepted now without inner rings.\n Default offset is 0.001 degree\n"; return 0; } ifstream f(argv[1], ifstream::in); ofstream outfile(argv[2], ofstream::out); outfile.precision(9); string s; for (int i=0;i<3;i++) { getline(f, s); outfile<<s<<"\n"; } ClipperLib::Polygons polygons; ClipperLib::Polygon polygon; while(!f.eof()) { f>>s; if (s == "END") { break; } double c1 = ::atof(s.c_str()); f>>s; double c2 = ::atof(s.c_str()); ClipperLib::IntPoint point(c1 * MUL, c2 * MUL); polygon.push_back(point); } polygons.push_back(polygon); double distance = 0.001 * MUL; ClipperLib::Polygons res_polygons; ClipperLib::OffsetPolygons (polygons, res_polygons, distance, ClipperLib::jtMiter); if (res_polygons.size() < 1) { cerr<<"Bad output of OffsetPolygons!\n";return 1;} ClipperLib::Polygon result = res_polygons.front(); for (ClipperLib::Polygon::iterator it = result.begin(); it != result.end(); ++it) { ClipperLib::IntPoint point = *it; outfile << " " << (point.X/MUL) << " " << (point.Y/MUL) << " \n"; } outfile<<s; while (!f.eof()) { getline(f, s); outfile<<s<<"\n"; } return 0; }
void TranslatePolygon(ClipperLib::Polygon &p, int dx, int dy) { for (size_t i = 0; i < p.size(); ++i) { p[i].X += dx; p[i].Y += dy; } }
void optimizePolygon(ClipperLib::Polygon& poly) { Point p0 = poly[poly.size()-1]; for(unsigned int i=0;i<poly.size();i++) { Point p1 = poly[i]; if (shorterThen(p0 - p1, 10)) { poly.erase(poly.begin() + i); i --; }else{ Point p2; if (i < poly.size() - 1) p2 = poly[i+1]; else p2 = poly[0]; Point diff0 = normal(p1 - p0, 1000000); Point diff2 = normal(p1 - p2, 1000000); int64_t d = dot(diff0, diff2); if (d < -999999000000LL) { poly.erase(poly.begin() + i); i --; }else{ p0 = p1; } } } }
void MakeRandomPoly(ClipperLib::Polygon &p, int width, int height, int edgeCount) { p.resize(edgeCount); for (int i = 0; i < edgeCount; i++) { p[i].X = (rand()%(width -20) +10)*scale; p[i].Y = (rand()%(height -20) +10)*scale; } }
void SlicerLayer::makePolygons(OptimizedVolume* ov, bool keepNoneClosed, bool extensiveStitching) { for(unsigned int startSegment=0; startSegment < segmentList.size(); startSegment++) { if (segmentList[startSegment].addedToPolygon) continue; ClipperLib::Polygon poly; poly.push_back(segmentList[startSegment].start); unsigned int segmentIndex = startSegment; bool canClose; while(true) { canClose = false; segmentList[segmentIndex].addedToPolygon = true; Point p0 = segmentList[segmentIndex].end; poly.push_back(p0); int nextIndex = -1; OptimizedFace* face = &ov->faces[segmentList[segmentIndex].faceIndex]; for(unsigned int i=0;i<3;i++) { if (face->touching[i] > -1 && faceToSegmentIndex.find(face->touching[i]) != faceToSegmentIndex.end()) { Point p1 = segmentList[faceToSegmentIndex[face->touching[i]]].start; Point diff = p0 - p1; if (shorterThen(diff, 10)) { if (faceToSegmentIndex[face->touching[i]] == (int)startSegment) canClose = true; if (segmentList[faceToSegmentIndex[face->touching[i]]].addedToPolygon) continue; nextIndex = faceToSegmentIndex[face->touching[i]]; } } } if (nextIndex == -1) break; segmentIndex = nextIndex; } if (canClose) polygonList.add(poly); else openPolygonList.add(poly); } //Clear the segmentList to save memory, it is no longer needed after this point. segmentList.clear(); //Connecting polygons that are not closed yet, as models are not always perfect manifold we need to join some stuff up to get proper polygons //First link up polygon ends that are within 2 microns. for(unsigned int i=0;i<openPolygonList.size();i++) { if (openPolygonList[i].size() < 1) continue; for(unsigned int j=0;j<openPolygonList.size();j++) { if (openPolygonList[j].size() < 1) continue; Point diff = openPolygonList[i][openPolygonList[i].size()-1] - openPolygonList[j][0]; int64_t distSquared = vSize2(diff); if (distSquared < 2 * 2) { if (i == j) { polygonList.add(openPolygonList[i]); openPolygonList[i].clear(); break; }else{ for(unsigned int n=0; n<openPolygonList[j].size(); n++) openPolygonList[i].push_back(openPolygonList[j][n]); openPolygonList[j].clear(); } } } } //Next link up all the missing ends, closing up the smallest gaps first. This is an inefficient implementation which can run in O(n*n*n) time. while(1) { int64_t bestScore = 10000 * 10000; unsigned int bestA = -1; unsigned int bestB = -1; bool reversed = false; for(unsigned int i=0;i<openPolygonList.size();i++) { if (openPolygonList[i].size() < 1) continue; for(unsigned int j=0;j<openPolygonList.size();j++) { if (openPolygonList[j].size() < 1) continue; Point diff = openPolygonList[i][openPolygonList[i].size()-1] - openPolygonList[j][0]; int64_t distSquared = vSize2(diff); if (distSquared < bestScore) { bestScore = distSquared; bestA = i; bestB = j; reversed = false; } if (i != j) { Point diff = openPolygonList[i][openPolygonList[i].size()-1] - openPolygonList[j][openPolygonList[j].size()-1]; int64_t distSquared = vSize2(diff); if (distSquared < bestScore) { bestScore = distSquared; bestA = i; bestB = j; reversed = true; } } } } if (bestScore >= 10000 * 10000) break; if (bestA == bestB) { polygonList.add(openPolygonList[bestA]); openPolygonList[bestA].clear(); }else{ if (reversed) { for(unsigned int n=openPolygonList[bestB].size()-1; int(n)>=0; n--) openPolygonList[bestA].push_back(openPolygonList[bestB][n]); }else{ for(unsigned int n=0; n<openPolygonList[bestB].size(); n++) openPolygonList[bestA].push_back(openPolygonList[bestB][n]); } openPolygonList[bestB].clear(); } } if (extensiveStitching) { //For extensive stitching find 2 open polygons that are touching 2 closed polygons. // Then find the sortest path over this polygon that can be used to connect the open polygons, // And generate a path over this shortest bit to link up the 2 open polygons. // (If these 2 open polygons are the same polygon, then the final result is a closed polyon) while(1) { unsigned int bestA = -1; unsigned int bestB = -1; gapCloserResult bestResult; bestResult.len = LLONG_MAX; bestResult.polygonIdx = -1; bestResult.pointIdxA = -1; bestResult.pointIdxB = -1; for(unsigned int i=0; i<openPolygonList.size(); i++) { if (openPolygonList[i].size() < 1) continue; { gapCloserResult res = findPolygonGapCloser(openPolygonList[i][0], openPolygonList[i][openPolygonList[i].size()-1]); if (res.len > 0 && res.len < bestResult.len) { bestA = i; bestB = i; bestResult = res; } } for(unsigned int j=0; j<openPolygonList.size(); j++) { if (openPolygonList[j].size() < 1 || i == j) continue; gapCloserResult res = findPolygonGapCloser(openPolygonList[i][0], openPolygonList[j][openPolygonList[j].size()-1]); if (res.len > 0 && res.len < bestResult.len) { bestA = i; bestB = j; bestResult = res; } } } if (bestResult.len < LLONG_MAX) { if (bestA == bestB) { if (bestResult.pointIdxA == bestResult.pointIdxB) { polygonList.add(openPolygonList[bestA]); openPolygonList[bestA].clear(); } else if (bestResult.AtoB) { unsigned int n = polygonList.size(); polygonList.add(ClipperLib::Polygon()); for(unsigned int j = bestResult.pointIdxA; j != bestResult.pointIdxB; j = (j + 1) % polygonList[bestResult.polygonIdx].size()) polygonList[n].push_back(polygonList[bestResult.polygonIdx][j]); for(unsigned int j = openPolygonList[bestA].size() - 1; int(j) >= 0; j--) polygonList[n].push_back(openPolygonList[bestA][j]); openPolygonList[bestA].clear(); } else { unsigned int n = polygonList.size(); polygonList.add(openPolygonList[bestA]); for(unsigned int j = bestResult.pointIdxB; j != bestResult.pointIdxA; j = (j + 1) % polygonList[bestResult.polygonIdx].size()) polygonList[n].push_back(polygonList[bestResult.polygonIdx][j]); openPolygonList[bestA].clear(); } } else { if (bestResult.pointIdxA == bestResult.pointIdxB) { for(unsigned int n=0; n<openPolygonList[bestA].size(); n++) openPolygonList[bestB].push_back(openPolygonList[bestA][n]); openPolygonList[bestA].clear(); } else if (bestResult.AtoB) { ClipperLib::Polygon poly; for(unsigned int n = bestResult.pointIdxA; n != bestResult.pointIdxB; n = (n + 1) % polygonList[bestResult.polygonIdx].size()) poly.push_back(polygonList[bestResult.polygonIdx][n]); for(unsigned int n=poly.size()-1;int(n) >= 0; n--) openPolygonList[bestB].push_back(poly[n]); for(unsigned int n=0; n<openPolygonList[bestA].size(); n++) openPolygonList[bestB].push_back(openPolygonList[bestA][n]); openPolygonList[bestA].clear(); } else { for(unsigned int n = bestResult.pointIdxB; n != bestResult.pointIdxA; n = (n + 1) % polygonList[bestResult.polygonIdx].size()) openPolygonList[bestB].push_back(polygonList[bestResult.polygonIdx][n]); for(unsigned int n = openPolygonList[bestA].size() - 1; int(n) >= 0; n--) openPolygonList[bestB].push_back(openPolygonList[bestA][n]); openPolygonList[bestA].clear(); } } } else { break; } } } /* int q=0; for(unsigned int i=0;i<openPolygonList.size();i++) { if (openPolygonList[i].size() < 2) continue; if (!q) printf("***\n"); printf("S: %f %f\n", float(openPolygonList[i][0].X), float(openPolygonList[i][0].Y)); printf("E: %f %f\n", float(openPolygonList[i][openPolygonList[i].size()-1].X), float(openPolygonList[i][openPolygonList[i].size()-1].Y)); q = 1; } */ //if (q) exit(1); if (keepNoneClosed) { for(unsigned int n=0; n<openPolygonList.size(); n++) { if (openPolygonList[n].size() > 0) polygonList.add(openPolygonList[n]); } } //Clear the openPolygonList to save memory, the only reason to keep it after this is for debugging. //openPolygonList.clear(); //Remove all the tiny polygons, or polygons that are not closed. As they do not contribute to the actual print. int snapDistance = 1000; for(unsigned int i=0;i<polygonList.size();i++) { int length = 0; for(unsigned int n=1; n<polygonList[i].size(); n++) { length += vSize(polygonList[i][n] - polygonList[i][n-1]); if (length > snapDistance) break; } if (length < snapDistance) { polygonList.remove(i); i--; } } //Finally optimize all the polygons. Every point removed saves time in the long run. optimizePolygons(polygonList); }
void PathOrderOptimizer::optimize() { std::vector<bool> picked; for(unsigned int i=0;i<polygons.size(); i++) { int best = -1; float bestDist = 0xFFFFFFFFFFFFFFFFLL; ClipperLib::Polygon* poly = polygons[i]; for(unsigned int j=0; j<poly->size(); j++) { float dist = vSize2f((*poly)[j] - startPoint); if (dist < bestDist) { best = j; bestDist = dist; } } polyStart.push_back(best); picked.push_back(false); } Point p0 = startPoint; for(unsigned int n=0; n<polygons.size(); n++) { int best = -1; float bestDist = 0xFFFFFFFFFFFFFFFFLL; for(unsigned int i=0;i<polygons.size(); i++) { if (picked[i] || (*polygons[i]).size() < 1) continue; if ((*polygons[i]).size() == 2) { float dist = vSize2f((*polygons[i])[0] - p0); if (dist < bestDist) { best = i; bestDist = dist; polyStart[i] = 0; } dist = vSize2f((*polygons[i])[1] - p0); if (dist < bestDist) { best = i; bestDist = dist; polyStart[i] = 1; } }else{ float dist = vSize2f((*polygons[i])[polyStart[i]] - p0); if (dist < bestDist) { best = i; bestDist = dist; } } } if (best > -1) { if (polygons[best]->size() == 2) { p0 = (*polygons[best])[(polyStart[best] + 1) % 2]; }else{ p0 = (*polygons[best])[polyStart[best]]; } picked[best] = true; polyOrder.push_back(best); } } p0 = startPoint; for(unsigned int n=0; n<polyOrder.size(); n++) { int nr = polyOrder[n]; int best = -1; float bestDist = 0xFFFFFFFFFFFFFFFFLL; for(unsigned int i=0;i<polygons[nr]->size(); i++) { float dist = vSize2f((*polygons[nr])[i] - p0); if (dist < bestDist) { best = i; bestDist = dist; } } polyStart[nr] = best; if ((*polygons[nr]).size() <= 2) { p0 = (*polygons[nr])[(best + 1) % 2]; }else{ p0 = (*polygons[nr])[best]; } } }