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.

227 lines
5.1 KiB
C++

1 month ago
#include "pch.h"
#include "IntersectionUtil.h"
#include <ppl.h>
#include <array>
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;
// <20><>СX<D0A1><58><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD>߶<EFBFBD>
//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;
}
}
// <20><><EFBFBD>Ҷ˵<D2B6><CBB5>ٴβ<D9B4><CEB2><EFBFBD>
vector <LineSegment> 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();
// <20><><EFBFBD><EFBFBD><EFBFBD>߶<EFBFBD><DFB6>б<EFBFBD>
for (const auto& path : *m_pSourceLines) { // ʹ<>÷<EFBFBD>Χѭ<CEA7><D1AD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ñ<EFBFBD><C3B1><EFBFBD><E2BFBD>
const size_t pointCount = path.size();
for (size_t j = 1; j < pointCount; ++j) { // ʹ<><CAB9>size_t<5F><74>ֹ<EFBFBD><D6B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
const Point64 rawStart = path[j - 1];
const Point64 rawEnd = path[j];
// ȷ<><C8B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>յ<EFBFBD>
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); // ֱ<><D6B1>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//m_Segments.emplace_back(
// const_cast<Point64&>(sortedStart),
// const_cast<Point64&>(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]));
// }
//}
// <20><><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>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;
// }
//}