void SHAPE_POLY_SET::importTree( PolyTree* tree) { m_polys.clear(); for( PolyNode* n = tree->GetFirst(); n; n = n->GetNext() ) { if( !n->IsHole() ) { POLYGON paths; paths.push_back( convertFromClipper( n->Contour ) ); for( unsigned int i = 0; i < n->Childs.size(); i++ ) paths.push_back( convertFromClipper( n->Childs[i]->Contour ) ); m_polys.push_back(paths); } } }
void triangulate(const Polygon& inputPoly, std::vector<Mesh>& outputMeshes) { // Use Clipper to ensure strictly simple polygons using namespace ClipperLib; Clipper clipper; clipper.StrictlySimple(true); try { clipper.AddPaths(polyToClipperPaths(inputPoly), ptSubject, true); } catch (...) { std::cerr << "Error in Clipper::AddPaths" << std::endl; return; } PolyTree polyTree; clipper.Execute(ctUnion, polyTree, pftNonZero, pftNonZero); // Traverse the PolyTree nodes and triangulate them with only their children holes PolyNode *currentNode = polyTree.GetFirst(); while(currentNode != NULL) { // The holes are only used as the children of the contours if (currentNode->IsHole()) { currentNode = currentNode->GetNext(); continue; } // Convert to poly2tri's format std::vector<p2t::Point> allPoints; std::vector<size_t> linesSizes; // Contour for (const auto& pt : currentNode->Contour) allPoints.emplace_back(static_cast<double>(pt.X), static_cast<double>(pt.Y)); linesSizes.push_back(allPoints.size()); // Holes for(const auto childNode : currentNode->Childs) { // Slightly modify the polygon to guarantee no duplicate points edgeShrink(childNode->Contour); for (const auto& pt : childNode->Contour) allPoints.emplace_back(static_cast<double>(pt.X), static_cast<double>(pt.Y)); linesSizes.push_back(allPoints.size()); } // Poly2Tri uses pointers to points std::vector<p2t::Point*> contourLine; std::vector<std::vector<p2t::Point*>> holes; auto nbLines = linesSizes.size(); size_t start = 0; for (size_t i = 0; i < nbLines; ++i) { size_t end = linesSizes[i]; std::vector<p2t::Point*> line; line.reserve(end - start); for (size_t j = start; j < end; ++j) line.push_back(&allPoints[j]); start = end; if (!i) contourLine = std::move(line); else holes.push_back(std::move(line)); } // Set the contour in poly2tri p2t::CDT cdt(contourLine); // Add the holes for(auto& hole : holes) cdt.AddHole(hole); // Do the actual triangulation cdt.Triangulate(); // Downscale the points and add them to the mesh Mesh mesh; for (const auto pt : allPoints) mesh.addPoint(convert(pt)); // Convert the triangles auto triangles = cdt.GetTriangles(); auto firstPt = allPoints.data(); for (const auto triangle : triangles) { int ptId1 = std::distance(firstPt, triangle->GetPoint(0)); int ptId2 = std::distance(firstPt, triangle->GetPoint(1)); int ptId3 = std::distance(firstPt, triangle->GetPoint(2)); mesh.addTriangle(ptId1, ptId2, ptId3); } outputMeshes.push_back(mesh); currentNode = currentNode->GetNext(); } }