#include "SigmaView.h" #include "ItemCurveArc.h" #include "ItemCurveEdit.h" #include "ItemSelect.h" #include "clipper2/clipper.h" enum class BooleanOp { Difference = 0, Intersect = 1, Union = 2, Xor = 3, }; /** * 多边形处理类 */ class PolygonCombiner { public: /** * 差集 * * \param first 第一条闭合曲线 * \param second 第二条闭合曲线 * \return 返回合并后的曲线 */ static std::vector> Difference(const std::vector& first, const std::vector& second) { return Execute(first, second, BooleanOp::Difference); } /** * 交集 * * \param first 第一条闭合曲线 * \param second 第二条闭合曲线 * \return 返回合并后的曲线 */ static std::vector> Intersect(const std::vector& first, const std::vector& second) { return Execute(first, second, BooleanOp::Intersect); } /** * 并集 * * \param first 第一条闭合曲线 * \param second 第二条闭合曲线 * \return 返回合并后的曲线 */ static std::vector> Union(const std::vector& first, const std::vector& second) { return Execute(first, second, BooleanOp::Union); } /** * 异或 * * \param first 第一条闭合曲线 * \param second 第二条闭合曲线 * \return 返回合并后的曲线 */ static std::vector> Xor(const std::vector& first, const std::vector& second) { return Execute(first, second, BooleanOp::Xor); } static Clipper2Lib::PathD CurveToPathD(const CCurveEx* curve) { Clipper2Lib::PathD path; path.reserve(curve->num); for (int i = 0; i < curve->num; i++) { path.push_back({ curve->x[i], curve->y[i] }); } return path; } static Clipper2Lib::PathsD CurvesToPathsD(const std::vector& curves) { Clipper2Lib::PathsD path; path.reserve(curves.size()); for (auto* pCurve : curves) { if (pCurve == nullptr) { continue; } path.emplace_back(CurveToPathD(pCurve)); } return path; } static std::unique_ptr PathDToCurve(const Clipper2Lib::PathD& path) { auto pCurve = std::make_unique(); pCurve->Create(path.size() + 1); size_t i = 0; for (; i < path.size(); i++) { pCurve->x[i] = path[i].x; pCurve->y[i] = path[i].y; } pCurve->x[i] = path[0].x; pCurve->y[i] = path[0].y; return pCurve; } static std::vector> Execute(const std::vector& first, const std::vector& second, BooleanOp op) { auto firstPaths = CurvesToPathsD(first); auto secondPaths = CurvesToPathsD(second); auto solution = Clipper2Lib::PathsD(); switch (op) { case BooleanOp::Difference: solution = Clipper2Lib::Difference(firstPaths, secondPaths, Clipper2Lib::FillRule::NonZero); break; case BooleanOp::Intersect: solution = Clipper2Lib::Intersect(firstPaths, secondPaths, Clipper2Lib::FillRule::NonZero); break; case BooleanOp::Union: solution = Clipper2Lib::Union(firstPaths, secondPaths, Clipper2Lib::FillRule::NonZero); break; case BooleanOp::Xor: solution = Clipper2Lib::Xor(firstPaths, secondPaths, Clipper2Lib::FillRule::NonZero); break; default: break; } if (solution.empty()) { return {}; } std::vector> result; for (auto& path : solution) { result.push_back(PathDToCurve(path)); } return result; } };