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.
kev/Drawer/GVision/WellCalibrate/IntersectionUtil.cpp

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