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++
227 lines
5.1 KiB
C++
#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;
|
|
|
|
// 最小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 <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();
|
|
// 生成线段列表
|
|
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<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]));
|
|
// }
|
|
//}
|
|
// 按起始坐标排序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;
|
|
// }
|
|
//}
|