#include "pch.h" #include "IntersectionUtil.h" #include #include using namespace concurrency; CIntersectionUtil::CIntersectionUtil(void) { //m_Segments; } CIntersectionUtil::~CIntersectionUtil(void) { } void CIntersectionUtil::SetSourceLines(const Paths64 * subjects) { this->m_pSourceLines = subjects; this->PrepareData(); } bool CIntersectionUtil::Intersects(LineSegment& clip) { size_t nSegCount = m_Segments.size(); if (nSegCount == 0) { return false; } //Point64 ptStart = clip.ptStart; //Point64 ptEnd = clip.ptEnd; Envelope clipRange = clip.Range; LineSegment lineClip(); int nLeft = 0; int nRight = nSegCount - 1; // 最小X符合要求的线段 //int nFindIndex = 0; //if (m_Segments.at(0).Range.MinX > clip.Range.MaxX) //{ // return false; //} int nMid = 0; while (nLeft <= nRight) { //nMid = (nLeft + nRight) / 2; nMid = 0.618*nRight + 0.382*nLeft; if (nMid == nSegCount -1) { //nFindIndex = nMid; break; } if (m_Segments[nMid].Range.MinX <= clipRange.MaxX && m_Segments[nMid + 1].Range.MinX >= clipRange.MaxX) { //nFindIndex = nMid; break; } else if (m_Segments[nMid].Range.MinX > clipRange.MaxX) { nRight = nMid - 1; } else { nLeft = nMid + 1; } } // 按右端点再次查找 vector segmentsR(m_Segments.begin(), m_Segments.begin()+ nMid+1); std::sort(segmentsR.begin(), segmentsR.end(), SegmentSortR); nSegCount = segmentsR.size(); nLeft = 0; nRight = nSegCount - 1; //nFindIndex = 0; nMid = 0; while (nLeft <= nRight) { //nMid = (nLeft + nRight) / 2; nMid = 0.618*nRight + 0.382*nLeft; if (nMid == 0) { //nFindIndex = nMid; break; } if (segmentsR[nMid].Range.MaxX >= clipRange.MinX&& segmentsR[nMid - 1].Range.MaxX <= clipRange.MinX) { //nFindIndex = nMid; break; } else if (segmentsR[nMid].Range.MaxX < clipRange.MinX) { nLeft = nMid + 1; } else { nRight = nMid - 1; } } for (int i = nMid; i < nSegCount; i++) { if (clipRange.Intersects(segmentsR[i].Range)) { if (SegmentsIntersect(segmentsR[i].ptStart, segmentsR[i].ptEnd, clip.ptStart, clip.ptEnd, true)) { return true; } } } return false; } void CIntersectionUtil::PrepareData() { m_Segments.clear(); // 生成线段列表 for (const auto& path : *m_pSourceLines) { // 使用范围循环和引用避免拷贝 const size_t pointCount = path.size(); for (size_t j = 1; j < pointCount; ++j) { // 使用size_t防止负数索引 const Point64 rawStart = path[j - 1]; const Point64 rawEnd = path[j]; // 确定有序的起点和终点 bool needSwap = (rawStart.x > rawEnd.x) || ((rawStart.x == rawEnd.x) && (rawStart.y > rawEnd.y)); const Point64 sortedStart = needSwap ? rawEnd : rawStart; const Point64 sortedEnd = needSwap ? rawStart : rawEnd; Point64 startCopy = sortedStart; Point64 endCopy = sortedEnd; m_Segments.emplace_back(startCopy, endCopy); // 直接使用有序点 //m_Segments.emplace_back( // const_cast(sortedStart), // const_cast(sortedEnd) //); } } //for (int i = 0; i < this->m_pSourceLines->size(); i++) { // Path64 line = this->m_pSourceLines->at(i); // int nLineCount = line.size(); // for (int j = 1; j < nLineCount;j++) { // Point64 ptStart = line[j - 1]; // Point64 ptEnd = line[j]; // if (ptStart.x > ptEnd.x) // { // ptStart = line[j]; // ptEnd = line[j - 1]; // } // else { // if (ptStart.y > ptEnd.y) { // ptStart = line[j]; // ptEnd = line[j - 1]; // } // } // m_Segments.push_back(LineSegment(line[j-1], line[j])); // } //} // 按起始坐标排序parallel_sort std::sort(m_Segments.begin(), m_Segments.end(), CIntersectionUtil::SegmentSort); //m_SegmentsR.clear(); //m_SegmentsR. //for (int i = 0; i < m_Segments.size(); i++) //{ // int nMin = m_Segments.at(i).Range.MinX; // TRACE("%d\r\n" , nMin); //} } bool CIntersectionUtil::SegmentSort(LineSegment& seg1, LineSegment& seg2) { return seg1.ptStart.x < seg2.ptStart.x; //|| (seg1.ptStart.x == seg2.ptStart.x // &&( seg1.ptStart.y < seg2.ptStart.y && seg1.ptEnd.x < seg2.ptEnd.x && seg1.ptEnd.y < seg2.ptEnd.y)); } bool CIntersectionUtil::SegmentSortR(LineSegment& seg1, LineSegment& seg2) { return seg1.ptEnd.x < seg2.ptEnd.x; //|| (seg1.ptStart.x == seg2.ptStart.x // && (seg1.ptStart.y < seg2.ptStart.y && seg1.ptEnd.x < seg2.ptEnd.x && seg1.ptEnd.y < seg2.ptEnd.y)); //|| (seg1.ptEnd.x == seg2.ptEnd.x && seg1.ptStart.y < seg2.ptStart.y); //if (seg1.ptEnd.x == seg2.ptEnd.x) // return true; //else // return seg1.ptEnd.x < seg2.ptEnd.x; } Envelope::Envelope() { } Envelope::Envelope(int64_t x1, int64_t x2, int64_t y1, int64_t y2) { Init(x1, x2, y1, y2); } Envelope::Envelope(Point64& p1, Point64& p2) { } void Envelope::Init(Point64& p1, Point64& p2) { Init(p1.x, p2.x, p1.y, p2.y); } void Envelope::Init(int64_t x1, int64_t x2, int64_t y1, int64_t y2) { if (x1 < x2) { MinX = x1; MaxX = x2; } else { MinX = x2; MaxX = x1; } if (y1 < y2) { MinY = y1; MaxY = y2; } else { MinY = y2; MaxY = y1; } } bool Envelope::Intersects(Envelope& other) { return !(other.MinX > MaxX || other.MaxX < MinX || other.MinY > MaxY || other.MaxY < MinY); } //public bool IsNull //{ // get // { // return _maxX < _minX; // } //}