|
|
|
|
|
#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;
|
|
|
|
|
|
// }
|
|
|
|
|
|
//}
|