You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

93 lines
2.0 KiB
C++

#include <memory>
#include <vector>
#include "DrawOperator/CurveEx.h"
#include "clipper2/clipper.h"
#include "PolygonUtils.h"
/**
* 重叠检测类
*/
class OverlapDetection
{
public:
OverlapDetection() = default;
~OverlapDetection() = default;
struct Overlap
{
std::unique_ptr<CCurveEx> pArea;
CCurveEx* pFirstCurve;
CCurveEx* pSecondCurve;
};
/**
* 检测哪些曲线有交集
*
* \param curves 参与运算的所有曲线,如果没闭合,会当闭合曲线处理
* \return 返回曲线的交集
*/
std::vector<Overlap> DetectOverlap(const std::vector<CCurveEx*>& curves) const
{
std::vector<Overlap> allOverlaps;
const size_t numCurves = curves.size();
if (numCurves < 2)
{
return allOverlaps;
}
std::vector<Clipper2Lib::PathD> cachedPaths;
cachedPaths.reserve(numCurves);
for (size_t i = 0; i < numCurves; i++)
{
cachedPaths.push_back(PolygonUtils::ConvertCurveToPath(curves[i]));
}
for (size_t i = 0; i < numCurves; i++)
{
for (size_t j = i + 1; j < numCurves; j++)
{
const Clipper2Lib::PathD& path1 = cachedPaths[i];
const Clipper2Lib::PathD& path2 = cachedPaths[j];
if (path1.size() < 3 || path2.size() < 3)
{
continue;
}
Clipper2Lib::PathsD solution = PolygonUtils::Intersect(path1, path2);
auto result = SolutionToOverlap(solution, curves, curves[i], curves[j]);
allOverlaps.insert(allOverlaps.end(),
std::make_move_iterator(result.begin()),
std::make_move_iterator(result.end()));
}
}
return allOverlaps;
}
private:
std::vector<Overlap> SolutionToOverlap(Clipper2Lib::PathsD& solution, const std::vector<CCurveEx*>& curves, CCurveEx* pFirst, CCurveEx* pSecond) const
{
std::vector<Overlap> result;
for (const auto& solutionPath : solution)
{
std::unique_ptr<CCurveEx> pOverlapArea = PolygonUtils::ConvertPathToClosedCurve(solutionPath);
if (pOverlapArea)
{
Overlap overlap;
overlap.pArea = std::move(pOverlapArea);
overlap.pFirstCurve = pFirst;
overlap.pSecondCurve = pSecond;
result.push_back(std::move(overlap));
}
}
return result;
}
};