Polygon2D halfBanana(std::vector<Line2D>& lines) { int n = (int)lines.size() + 4; int l, r; std::vector<Line2D> deq(n); // infinite square boundary lines.push_back(Line2D(Vector2D(-INF, -INF), Vector2D( 1, 0))); lines.push_back(Line2D(Vector2D( INF, -INF), Vector2D( 0, 1))); lines.push_back(Line2D(Vector2D( INF, INF), Vector2D(-1, 0))); lines.push_back(Line2D(Vector2D(-INF, INF), Vector2D( 0, -1))); // sort std::sort(lines.begin(), lines.end(), cmpBySlope); // find intersection result l = 0; r = -1; #define deqSize (r-l+1) for(int i=0; i<n; ++i) { if(deqSize > 0 && lines[i].parallel(deq[r])) { if(lines[i].side(deq[r].p0) >= 0) continue; if(deqSize == 1) { deq[r] = Line2D(lines[i]); continue; } } while(deqSize > 1 && lines[i].side(deq[r].intersect(deq[r-1])) <= 0) r--; while(deqSize > 1 && lines[i].side(deq[l].intersect(deq[l+1])) <= 0) l++; if(deqSize == 1 && deq[r].ang() + M_PI < lines[i].ang()) return Polygon2D(); deq[++r] = Line2D(lines[i]); } while(deqSize > 1 && deq[l].side(deq[r].intersect(deq[r-1])) <= 0) r--; if(deqSize < 3) return Polygon2D(); // generate polygon Polygon2D ret; for(int i=l; i<r; ++i) ret.push(deq[i].intersect(deq[i+1])); ret.push(deq[l].intersect(deq[r])); return ret; }
/* std::vector<Polygon> DecomposePolygonToConvexhulls(const Polygon& polygon) { using VHACD::IVHACD; TriangleMesh mesh = TriangulatePolygon(polygon); std::vector<float> points; points.reserve(2 * mesh.vertices.size()); for (auto& vertex : mesh.vertices) { points.emplace_back(vertex(0)); points.emplace_back(vertex(1)); } std::vector<int> triangle_indices; triangle_indices.reserve(mesh.faces.size() * 3); for (auto& tr_idx : mesh.faces) { triangle_indices.emplace_back(tr_idx[0]); triangle_indices.emplace_back(tr_idx[1]); triangle_indices.emplace_back(tr_idx[2]); } IVHACD::Parameters params; // // params.m_maxNumVerticesPerCH = 8; params.m_oclAcceleration = false; IVHACD* vhacd_interface = VHACD::CreateVHACD(); bool res = vhacd_interface->Compute(points.data(), 2, mesh.vertices.size(), triangle_indices.data(), 3, mesh.faces.size(), params); std::vector<Polygon> polygons; if (res) { size_t num_hulls = vhacd_interface->GetNConvexHulls(); IVHACD::ConvexHull hull; for (size_t p = 0; p < num_hulls; ++p) { vhacd_interface->GetConvexHull(p, hull); for (size_t v = 0; v < hull.m_nPoints; ++v) { std::cout << p << " "; std::cout << hull.m_points[3 * v + 0] << " "; std::cout << hull.m_points[3 * v + 1] << " "; std::cout << hull.m_points[3 * v + 2] << "\n"; } } } else { std::cerr << "convex hull decomposition not successfull! fall back to " "triangulation!\n"; } vhacd_interface->Clean(); vhacd_interface->Release(); exit(0); return polygons; } */ std::vector<Polygon2D> ResolveIntersections(const Polygon2D& polygon) { // the polygon boundary maybe splitted during this process // auto paths = ResolveIntersectionsClosedPath(polygon.path); // auto holes = ResolveIntersectionsClosedPaths(polygon.holes); ClipperLib::Clipper clipper; ClipperLib::Path scaled_path = UScalePathDiaToClipper(polygon.path); clipper.AddPath(scaled_path, ClipperLib::ptSubject, true); /* for (auto& path : paths) { ClipperLib::Path scaled_path = UScalePathDiaToClipper(path); clipper.AddPath(scaled_path, ClipperLib::ptSubject, true); }*/ for (auto& hole : polygon.holes) { ClipperLib::Path scaled_hole = UScalePathDiaToClipper(hole); clipper.AddPath(scaled_hole, ClipperLib::ptClip, true); } ClipperLib::PolyTree path_tree; clipper.StrictlySimple(true); clipper.Execute(ClipperLib::ctDifference, path_tree, ClipperLib::pftNonZero, ClipperLib::pftNonZero); // iterating into the tree std::vector<Polygon2D> polygons; // only store the pointer to outer polygons std::unordered_map<ClipperLib::PolyNode*, size_t> polynode_map; for (ClipperLib::PolyNode* node_ptr = path_tree.GetFirst(); node_ptr; node_ptr = node_ptr->GetNext()) { ClipperLib::PolyNode* poly_ptr = node_ptr; while (poly_ptr && poly_ptr->IsHole()) { poly_ptr = poly_ptr->Parent; } if (polynode_map.find(poly_ptr) == polynode_map.end()) { polygons.emplace_back(Polygon2D()); polygons.back().path = DScalePathClipperToDia(poly_ptr->Contour); polynode_map[poly_ptr] = polygons.size() - 1; } else { polygons[polynode_map[poly_ptr]].holes.emplace_back( DScalePathClipperToDia(node_ptr->Contour)); } } return polygons; }
/*! */ Polygon2D ConvexHull::toPolygon() const { return Polygon2D( M_vertices ); }