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++
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;
|
|
}
|
|
}; |