|
|
|
|
|
#include "StdAfx.h"
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
|
|
#include "keyholing.h"
|
|
|
|
|
|
#include "clipper2/clipper.core.h"
|
|
|
|
|
|
|
|
|
|
|
|
using namespace Clipper2Lib;
|
|
|
|
|
|
|
|
|
|
|
|
inline size_t GetLowestPtIdx(const Path64& path)
|
|
|
|
|
|
{
|
|
|
|
|
|
size_t result = 0;
|
|
|
|
|
|
Point64 resPt = path[0];
|
|
|
|
|
|
for (size_t i = 1; i < path.size(); ++i)
|
|
|
|
|
|
if (path[i].y < resPt.y) continue;
|
|
|
|
|
|
else if (path[i].y > resPt.y || path[i].x < resPt.x)
|
|
|
|
|
|
{
|
|
|
|
|
|
result = i;
|
|
|
|
|
|
resPt = path[i];
|
|
|
|
|
|
}
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//inline size_t GetNearestPtIdx(const Path64& path, const Point64& pt)
|
|
|
|
|
|
//{
|
|
|
|
|
|
// size_t result = 0;
|
|
|
|
|
|
// double distSqr = DistanceSqr(path[0], pt);
|
|
|
|
|
|
// for (size_t i = 1; i < path.size(); ++i)
|
|
|
|
|
|
// {
|
|
|
|
|
|
// double ds = DistanceSqr(path[i], pt);
|
|
|
|
|
|
// if (ds >= distSqr) continue;
|
|
|
|
|
|
// distSqr = ds;
|
|
|
|
|
|
// result = i;
|
|
|
|
|
|
// }
|
|
|
|
|
|
// return result;
|
|
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
|
|
static Point64 GetClosestPtOnSegment(const Point64& seg1, const Point64& seg2, const Point64& pt)
|
|
|
|
|
|
{
|
|
|
|
|
|
double dx = (seg2.x - seg1.x);
|
|
|
|
|
|
double dy = (seg2.y - seg1.y);
|
|
|
|
|
|
if (dx == 0.0 && dy == 0.0) return seg1;
|
|
|
|
|
|
double q = (dx * (pt.x - seg1.x) + dy * (pt.y - seg1.y)) / (Sqr(dx) + Sqr(dy));
|
|
|
|
|
|
// and restrict the point to the segment ...
|
|
|
|
|
|
q = std::fmax(0, std::fmin(1, q));
|
|
|
|
|
|
return Point64((1 - q) * seg1.x + q * seg2.x, (1 - q) * seg1.y + q * seg2.y);
|
|
|
|
|
|
}
|
|
|
|
|
|
// <20><>ת<EFBFBD><D7AA> (x, y) <20><>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>ת<EFBFBD>Ƕ<EFBFBD> theta (ʹ<><CAB9>Ԥ<EFBFBD>ȼ<EFBFBD><C8BC><EFBFBD><EFBFBD><EFBFBD> cosTheta <20><> sinTheta)
|
|
|
|
|
|
inline Point64 rotatePoint(const Point64& p, double cosTheta, double sinTheta) {
|
|
|
|
|
|
return { p.x * cosTheta + p.y * sinTheta, -p.x * sinTheta + p.y * cosTheta };
|
|
|
|
|
|
}
|
|
|
|
|
|
//// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD><CFB5>ת<EFBFBD><D7AA>ʹ<EFBFBD>߶<EFBFBD>ˮƽ
|
|
|
|
|
|
//inline Point64 rotatePointToHorizontal(const Point64& p, const Point64& origin, double cosTheta, double sinTheta) {
|
|
|
|
|
|
// // ƽ<>Ƶ㵽ԭ<E3B5BD>㣬Ȼ<E3A3AC><C8BB>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD>ת
|
|
|
|
|
|
// double translatedX = p.x - origin.x;
|
|
|
|
|
|
// double translatedY = p.y - origin.y;
|
|
|
|
|
|
// return {
|
|
|
|
|
|
// translatedX * cosTheta + translatedY * sinTheta, // X<>᷽<EFBFBD><E1B7BD>
|
|
|
|
|
|
// -translatedX * sinTheta + translatedY * cosTheta // Y<>᷽<EFBFBD><E1B7BD>
|
|
|
|
|
|
// };
|
|
|
|
|
|
//}
|
|
|
|
|
|
//// <20><><EFBFBD><EFBFBD>X<EFBFBD><58>ƽ<EFBFBD>е<EFBFBD><D0B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
//static Point64 GetClosestPtOnSegmentX(const Point64& seg1, const Point64& seg2, const Point64& pt)
|
|
|
|
|
|
//{
|
|
|
|
|
|
// int64_t dx = (seg2.x - seg1.x);
|
|
|
|
|
|
// int64_t dy = (seg2.y - seg1.y);
|
|
|
|
|
|
// if (dx == 0.0 && dy == 0.0) return seg1;
|
|
|
|
|
|
//
|
|
|
|
|
|
// int64_t segMinX = std::fmin(seg1.x, seg2.x);
|
|
|
|
|
|
//
|
|
|
|
|
|
// //if(pt.x<std::fmin(seg1.x, seg2.x))
|
|
|
|
|
|
// double q = (dx * (pt.x - seg1.x) + dy * (pt.y - seg1.y)) / (Sqr(dx) + Sqr(dy));
|
|
|
|
|
|
// // and restrict the point to the segment ...
|
|
|
|
|
|
// q = std::fmax(0, std::fmin(1, q));
|
|
|
|
|
|
// return Point64((1 - q) * seg1.x + q * seg2.x, (1 - q) * seg1.y + q * seg2.y);
|
|
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
|
|
inline Point64 GetYIntersectPt(const Point64& ln1, const Point64& ln2, int64_t Y)
|
|
|
|
|
|
{
|
|
|
|
|
|
double dx = static_cast<double>(ln2.x - ln1.x);
|
|
|
|
|
|
if (dx == 0.0) return Point64(ln1.x, Y);
|
|
|
|
|
|
double dy = static_cast<double>(ln2.y - ln1.y);
|
|
|
|
|
|
// y = dy/dx * x + b
|
|
|
|
|
|
// b = y1 - dy/dx * x1;
|
|
|
|
|
|
double b = ln1.y - dy / dx * ln1.x;
|
|
|
|
|
|
// x = (Y - b) * dx/dy
|
|
|
|
|
|
return Point64(static_cast<int64_t>(round((Y - b) * dx / dy)), Y);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void JoinAtClosestPtBelowHole(Path64& outer, Path64 hole)
|
|
|
|
|
|
{
|
|
|
|
|
|
// precondition: hole[0] is the hole's lowest vertex
|
|
|
|
|
|
// find the closest point on the outer path (cpOuter) to hole[0],
|
|
|
|
|
|
// while ensuring cpOuter is **below** holePt. (Joining with an
|
|
|
|
|
|
// 'outer' segment that's above holePt (ie y < holePt.y) risks the
|
|
|
|
|
|
// new join passing through a hole that hasn't yet been keyholed.)
|
|
|
|
|
|
|
|
|
|
|
|
int highI = static_cast<int>(outer.size()) - 1;
|
|
|
|
|
|
Point64 holePt = hole[0];
|
|
|
|
|
|
Point64 cpOuter;
|
|
|
|
|
|
int cpOuterIdx = -1;
|
|
|
|
|
|
double distSqrd = MAX_DBL;
|
|
|
|
|
|
for (size_t i = 0; i < highI; ++i)
|
|
|
|
|
|
{
|
|
|
|
|
|
Point64 nextPt = (i == highI) ? outer[0] : outer[i + 1];
|
|
|
|
|
|
// Since cpOuter.y must be below holePt.y ...
|
|
|
|
|
|
if (outer[i].y <= holePt.y && nextPt.y <= holePt.y) continue;
|
|
|
|
|
|
|
|
|
|
|
|
// 'outer' may have overlapping collinear segments due to previous
|
|
|
|
|
|
// hole joins. Therefore it's imperative when the closest segment
|
|
|
|
|
|
// happens to be one of these overlapping collinear segments, that
|
|
|
|
|
|
// the new join is with the correct one. For example, when a hole
|
|
|
|
|
|
// is on the left of an outer segment, that outer segment **must**
|
|
|
|
|
|
// be descending. Likewise, when a hole is on the right of an
|
|
|
|
|
|
// outer segment, then that outer segment must be descending.
|
|
|
|
|
|
if (CrossProduct(holePt, outer[i], nextPt) < 0) continue;
|
|
|
|
|
|
|
|
|
|
|
|
// Again make sure cpOuter.y is below holePt.y ...
|
|
|
|
|
|
Point64 cp;
|
|
|
|
|
|
if (outer[i].y <= holePt.y)
|
|
|
|
|
|
{
|
|
|
|
|
|
Point64 pt = GetYIntersectPt(outer[i], nextPt, holePt.y + 1);
|
|
|
|
|
|
cp = GetClosestPtOnSegment(pt, nextPt, holePt);
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (nextPt.y <= holePt.y)
|
|
|
|
|
|
{
|
|
|
|
|
|
Point64 pt = GetYIntersectPt(outer[i], nextPt, holePt.y + 1);
|
|
|
|
|
|
cp = GetClosestPtOnSegment(outer[i], pt, holePt);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
cp = GetClosestPtOnSegment(outer[i], nextPt, holePt);
|
|
|
|
|
|
|
|
|
|
|
|
double ds = DistanceSqr(cp, holePt);
|
|
|
|
|
|
if (cpOuterIdx >= 0 && ds >= distSqrd) continue;
|
|
|
|
|
|
|
|
|
|
|
|
cpOuter = cp;
|
|
|
|
|
|
distSqrd = ds;
|
|
|
|
|
|
cpOuterIdx = (cp == nextPt) ? i + 1 : i;
|
|
|
|
|
|
if (ds == 0) break;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// insert duplicate points into both outer and hole paths
|
|
|
|
|
|
if (cpOuter != outer[cpOuterIdx])
|
|
|
|
|
|
{
|
|
|
|
|
|
++cpOuterIdx;
|
|
|
|
|
|
if (cpOuterIdx > highI) cpOuterIdx = 0;
|
|
|
|
|
|
outer.insert(outer.begin() + cpOuterIdx, cpOuter);
|
|
|
|
|
|
}
|
|
|
|
|
|
outer.insert(outer.begin() + cpOuterIdx, cpOuter);
|
|
|
|
|
|
++cpOuterIdx;
|
|
|
|
|
|
if (cpOuterIdx >= outer.size()) cpOuterIdx = 0;
|
|
|
|
|
|
|
|
|
|
|
|
hole.insert(hole.begin(), holePt);
|
|
|
|
|
|
|
|
|
|
|
|
// finally join the hole with its outer path
|
|
|
|
|
|
outer.reserve(outer.size() + hole.size());
|
|
|
|
|
|
outer.insert(outer.begin() + cpOuterIdx, hole.begin(), hole.begin() + 1);
|
|
|
|
|
|
outer.insert(outer.begin() + cpOuterIdx, hole.begin() + 1, hole.end());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
struct PolySorter {
|
|
|
|
|
|
inline bool operator()(const Path64& path1, const Path64& path2)
|
|
|
|
|
|
{
|
|
|
|
|
|
return path2[0].y < path1[0].y;
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static bool KeyHoleOuter(const PolyPath64* outer, Paths64& paths)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!outer->Count())
|
|
|
|
|
|
{
|
|
|
|
|
|
paths.push_back(outer->Polygon());
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
Paths64 tmp;
|
|
|
|
|
|
tmp.reserve(outer->Count());
|
|
|
|
|
|
for (const auto& hole : *outer)
|
|
|
|
|
|
{
|
|
|
|
|
|
Path64 p = hole->Polygon();
|
|
|
|
|
|
// rearrange p so the lower vertex is first
|
|
|
|
|
|
size_t i = GetLowestPtIdx(p);
|
|
|
|
|
|
for (size_t j = 0; j < i; ++j)
|
|
|
|
|
|
{
|
|
|
|
|
|
Path64::iterator it = p.begin();
|
|
|
|
|
|
std::rotate(it, it + 1, p.end());
|
|
|
|
|
|
}
|
|
|
|
|
|
tmp.push_back(p);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// sort holes so the lowest ones are first
|
|
|
|
|
|
std::sort(tmp.begin(), tmp.end(), PolySorter());
|
|
|
|
|
|
|
|
|
|
|
|
Path64 merged = outer->Polygon();
|
|
|
|
|
|
// merge all holes into the outer path
|
|
|
|
|
|
for (Paths64::iterator it = tmp.begin(); it != tmp.end(); ++it)
|
|
|
|
|
|
{
|
|
|
|
|
|
JoinAtClosestPtBelowHole(merged, *it);
|
|
|
|
|
|
//std::cout << merged;
|
|
|
|
|
|
}
|
|
|
|
|
|
paths.push_back(merged);
|
|
|
|
|
|
|
|
|
|
|
|
// finally do any nested outer polygons
|
|
|
|
|
|
for (const auto& hole : *outer)
|
|
|
|
|
|
{
|
|
|
|
|
|
for (const auto& nested_outer : *hole)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!KeyHoleOuter(nested_outer.get(), paths))
|
|
|
|
|
|
{
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool KeyHole(const PolyTree64& polytree, Paths64& solution)
|
|
|
|
|
|
{
|
|
|
|
|
|
for (const auto& outer : polytree)
|
|
|
|
|
|
if (!KeyHoleOuter(outer.get(), solution)) return false;
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
|
|
struct BoundingBox64 {
|
|
|
|
|
|
int64_t minX, minY, maxX, maxY;
|
|
|
|
|
|
BoundingBox64() {}
|
|
|
|
|
|
BoundingBox64(int64_t minX, int64_t minY, int64_t maxX, int64_t maxY)
|
|
|
|
|
|
: minX(minX), minY(minY), maxX(maxX), maxY(maxY) {}
|
|
|
|
|
|
// <20>ж<EFBFBD><D0B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Χ<EFBFBD><CEA7><EFBFBD>Ƿ<EFBFBD><C7B7>н<EFBFBD><D0BD><EFBFBD>
|
|
|
|
|
|
bool Intersects(const BoundingBox64& other) const {
|
|
|
|
|
|
return !(other.maxX < this->minX || other.minX > this->maxX ||
|
|
|
|
|
|
other.maxY < this->minY || other.minY > this->maxY);
|
|
|
|
|
|
}
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Χ<EFBFBD><CEA7>֮<EFBFBD><D6AE><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><D0A1><EFBFBD>루<EFBFBD><EBA3A8><EFBFBD>Թ<EFBFBD><D4B9>㣩
|
|
|
|
|
|
double DistanceTo(const BoundingBox64& other) const {
|
|
|
|
|
|
// if (Intersects(other)) return 0;
|
|
|
|
|
|
int64_t dx = max(int64_t(0), max(minX - other.maxX, other.minX - maxX));
|
|
|
|
|
|
int64_t dy = max(int64_t(0), max(minY - other.maxY, other.minY - maxY));
|
|
|
|
|
|
return sqrt(dx * dx + dy * dy);
|
|
|
|
|
|
// return min(dx, dy, )
|
|
|
|
|
|
}
|
|
|
|
|
|
void CreateBoundary(const Path64 path) {
|
|
|
|
|
|
minX = INT64_MAX;
|
|
|
|
|
|
maxX = INT64_MIN;
|
|
|
|
|
|
minY = INT64_MAX;
|
|
|
|
|
|
maxY = INT64_MIN;
|
|
|
|
|
|
for (const auto& p : path) {
|
|
|
|
|
|
minX = min(minX, p.x);
|
|
|
|
|
|
minY = min(minY, p.y);
|
|
|
|
|
|
maxX = max(maxX, p.x);
|
|
|
|
|
|
maxY = max(maxY, p.y);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֮<EFBFBD><D6AE><EFBFBD>ľ<EFBFBD><C4BE><EFBFBD>
|
|
|
|
|
|
inline double distance(const Point64& p1, const Point64& p2) {
|
|
|
|
|
|
return sqrt((p2.x - p1.x) * (p2.x - p1.x) + (p2.y - p1.y) * (p2.y - p1.y));
|
|
|
|
|
|
}
|
|
|
|
|
|
double Clipper64Factor = 10000;
|
|
|
|
|
|
Point64 toPoint64(double x, double y) {
|
|
|
|
|
|
int64_t nX = static_cast<int64_t>(x * Clipper64Factor);
|
|
|
|
|
|
int64_t nY = static_cast<int64_t>(y* Clipper64Factor);
|
|
|
|
|
|
return Point64(nX, nY);
|
|
|
|
|
|
}
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת<EFBFBD><D7AA>Ϊ Clipper ʹ<>õ<EFBFBD> IntPoint <20><>ʽ
|
|
|
|
|
|
Path64 toPolygon64(const PathD& poly) {
|
|
|
|
|
|
Path64 clipperPoly;
|
|
|
|
|
|
for (const PointD& p : poly) {
|
|
|
|
|
|
clipperPoly.push_back(Point64(static_cast<int64_t>(p.x * Clipper64Factor), static_cast<int64_t>(p.y * Clipper64Factor)));
|
|
|
|
|
|
}
|
|
|
|
|
|
return clipperPoly;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// <20><> Clipper <20><> IntPoint <20><><EFBFBD><EFBFBD>ת<EFBFBD><D7AA><EFBFBD><EFBFBD>ԭʼ Polygon <20><>ʽ
|
|
|
|
|
|
PathD fromPolygon64(const Path64& clipperPoly) {
|
|
|
|
|
|
vector<PointD> vertices;
|
|
|
|
|
|
for (const Point64& ip : clipperPoly) {
|
|
|
|
|
|
vertices.emplace_back(ip.x / Clipper64Factor, ip.y/ Clipper64Factor);
|
|
|
|
|
|
}
|
|
|
|
|
|
return PathD(vertices);
|
|
|
|
|
|
}
|
|
|
|
|
|
// <20>ҳ<EFBFBD><D2B3><EFBFBD>ת<EFBFBD><D7AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߶<EFBFBD><DFB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD>
|
|
|
|
|
|
tuple<Point64, Point64, int, int, double> findClosestPointWithRotation(const Path64& poly1, const Path64& poly2, double& minDist) {
|
|
|
|
|
|
Point64 closest1, closest2;
|
|
|
|
|
|
//double minDist = distInit;
|
|
|
|
|
|
int index1 = -1, index2 = -1;
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ε<EFBFBD>ÿһ<C3BF><D2BB><EFBFBD><EFBFBD>
|
|
|
|
|
|
for (int i = 0; i < poly1.size(); i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
Point64 p1 = poly1[i];
|
|
|
|
|
|
Point64 p2 = poly1[(i + 1) % poly1.size()];
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD>߶<EFBFBD> a-b <20><> X <20><><EFBFBD>ļн<C4BC>
|
|
|
|
|
|
double dx = p2.x - p1.x;
|
|
|
|
|
|
double dy = p2.y - p1.y;
|
|
|
|
|
|
double theta = atan2(dy, dx); // <20><><EFBFBD><EFBFBD>Ҫ<EFBFBD>ر<EFBFBD><D8B1><EFBFBD><EFBFBD><EFBFBD> dx == 0<><30>atan2 <20>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
// Ԥ<>ȼ<EFBFBD><C8BC><EFBFBD> cos <20><> sin<69><6E><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>תʱ<D7AA><CAB1><EFBFBD>μ<EFBFBD><CEBC><EFBFBD>
|
|
|
|
|
|
double cosTheta = cos(theta);
|
|
|
|
|
|
double sinTheta = sin(theta);
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת<EFBFBD><D7AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
Point64 rotatedA = rotatePoint(p1, cosTheta, sinTheta);
|
|
|
|
|
|
Point64 rotatedB = rotatePoint(p2, cosTheta, sinTheta);
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD>ڶ<EFBFBD><DAB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ε<EFBFBD>ÿ<EFBFBD><C3BF><EFBFBD><EFBFBD><EFBFBD>㣬<EFBFBD><E3A3AC><EFBFBD>㵽ÿ<E3B5BD><C3BF><EFBFBD>ߵľ<DFB5><C4BE><EFBFBD>
|
|
|
|
|
|
for (int j = 0; j < poly2.size(); j++)
|
|
|
|
|
|
{
|
|
|
|
|
|
Point64 point = poly2[j];
|
|
|
|
|
|
Point64 rotatedP = rotatePoint(point, cosTheta, sinTheta);
|
|
|
|
|
|
double distY = fabs(rotatedP.y - rotatedA.y);
|
|
|
|
|
|
if (distY > minDist)
|
|
|
|
|
|
{
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת<EFBFBD><D7AA><EFBFBD>ĵ<EFBFBD><C4B5><EFBFBD> x <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߶εķ<CEB5>Χ<EFBFBD>ڣ<EFBFBD><DAA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>㴹ֱ<E3B4B9><D6B1><EFBFBD><EFBFBD>
|
|
|
|
|
|
if (rotatedP.x >= rotatedA.x && rotatedP.x <= rotatedB.x) {
|
|
|
|
|
|
//double dist = fabs(rotatedP.y - rotatedA.y); // <20><>ֱ<EFBFBD><D6B1><EFBFBD><EFBFBD>Ϊ y <20><><EFBFBD><EFBFBD>֮<EFBFBD><D6AE>
|
|
|
|
|
|
minDist = distY;
|
|
|
|
|
|
//closestPoint = point; // <20><><EFBFBD><EFBFBD>ԭ<EFBFBD><D4AD><EFBFBD><EFBFBD>ϵ<EFBFBD>еĵ<D0B5>
|
|
|
|
|
|
|
|
|
|
|
|
index1 = i;
|
|
|
|
|
|
index2 = j;
|
|
|
|
|
|
|
|
|
|
|
|
closest1 = Point64{ rotatedP.x , rotatedA.y };
|
|
|
|
|
|
closest1 = rotatePoint(closest1, cosTheta, -sinTheta); // <20><>ת<EFBFBD><D7AA>ԭ<EFBFBD><D4AD><EFBFBD><EFBFBD>ϵ
|
|
|
|
|
|
closest2 = point;
|
|
|
|
|
|
}
|
|
|
|
|
|
else {
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڷ<EFBFBD>Χ<EFBFBD>ڣ<EFBFBD><DAA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>㵽<EFBFBD>߶ζ˵<CEB6><CBB5>ľ<EFBFBD><C4BE><EFBFBD>
|
|
|
|
|
|
size_t dSpaceXA = abs(rotatedP.x - rotatedA.x);
|
|
|
|
|
|
size_t dSpaceXB = abs(rotatedP.x - rotatedB.x);
|
|
|
|
|
|
size_t dSpaceXMin = min(dSpaceXA, dSpaceXB);
|
|
|
|
|
|
if (dSpaceXA > minDist && dSpaceXB > minDist)
|
|
|
|
|
|
{
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (dSpaceXA < dSpaceXB) {
|
|
|
|
|
|
double dDist = distance(rotatedA, rotatedP);
|
|
|
|
|
|
if (dDist < minDist)
|
|
|
|
|
|
{
|
|
|
|
|
|
minDist = dDist;
|
|
|
|
|
|
index1 = i;
|
|
|
|
|
|
index2 = j;
|
|
|
|
|
|
|
|
|
|
|
|
//closest1 = Point64{ rotatedA.x , rotatedA.y };
|
|
|
|
|
|
//closest1 = rotatePoint(closest1, cosTheta, -sinTheta); // <20><>ת<EFBFBD><D7AA>ԭ<EFBFBD><D4AD><EFBFBD><EFBFBD>
|
|
|
|
|
|
closest1 = p1;
|
|
|
|
|
|
closest2 = point;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else {
|
|
|
|
|
|
double dDist = distance(rotatedB, rotatedP);
|
|
|
|
|
|
if (dDist < minDist)
|
|
|
|
|
|
{
|
|
|
|
|
|
minDist = dDist;
|
|
|
|
|
|
index1 = i;
|
|
|
|
|
|
index2 = j;
|
|
|
|
|
|
|
|
|
|
|
|
//closest1 = Point64{ rotatedB.x , rotatedB.y };
|
|
|
|
|
|
//closest1 = rotatePoint(closest1, cosTheta, -sinTheta); // <20><>ת<EFBFBD><D7AA>ԭ<EFBFBD><D4AD><EFBFBD><EFBFBD>
|
|
|
|
|
|
closest1 = p2;
|
|
|
|
|
|
closest2 = point;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD>ڶ<EFBFBD><DAB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ε<EFBFBD>ÿһ<C3BF><D2BB><EFBFBD><EFBFBD>
|
|
|
|
|
|
for (int i = 0; i < poly2.size(); i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
Point64 p1 = poly2[i];
|
|
|
|
|
|
Point64 p2 = poly2[(i + 1) % poly2.size()];
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD>߶<EFBFBD> a-b <20><> X <20><><EFBFBD>ļн<C4BC>
|
|
|
|
|
|
double dx = p2.x - p1.x;
|
|
|
|
|
|
double dy = p2.y - p1.y;
|
|
|
|
|
|
double theta = atan2(dy, dx); // <20><><EFBFBD><EFBFBD>Ҫ<EFBFBD>ر<EFBFBD><D8B1><EFBFBD><EFBFBD><EFBFBD> dx == 0<><30>atan2 <20>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
// Ԥ<>ȼ<EFBFBD><C8BC><EFBFBD> cos <20><> sin<69><6E><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>תʱ<D7AA><CAB1><EFBFBD>μ<EFBFBD><CEBC><EFBFBD>
|
|
|
|
|
|
double cosTheta = cos(theta);
|
|
|
|
|
|
double sinTheta = sin(theta);
|
|
|
|
|
|
// <20><><EFBFBD>߶ζ˵<CEB6><CBB5><EFBFBD>ת<EFBFBD><D7AA><EFBFBD><EFBFBD> X <20><>ƽ<EFBFBD>е<EFBFBD><D0B5><EFBFBD><EFBFBD><EFBFBD>ϵ
|
|
|
|
|
|
Point64 rotatedA = rotatePoint(p1, cosTheta, sinTheta);
|
|
|
|
|
|
Point64 rotatedB = rotatePoint(p2, cosTheta, sinTheta);
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ε<EFBFBD>ÿ<EFBFBD><C3BF><EFBFBD><EFBFBD><EFBFBD>㣬<EFBFBD><E3A3AC><EFBFBD>㵽ÿ<E3B5BD><C3BF><EFBFBD>ߵľ<DFB5><C4BE><EFBFBD>
|
|
|
|
|
|
for (int j = 0; j < poly1.size(); j++)
|
|
|
|
|
|
{
|
|
|
|
|
|
Point64 point = poly1[j];
|
|
|
|
|
|
Point64 rotatedP = rotatePoint(point, cosTheta, sinTheta);
|
|
|
|
|
|
double distY = fabs(rotatedP.y - rotatedA.y);
|
|
|
|
|
|
if (distY > minDist)
|
|
|
|
|
|
{
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת<EFBFBD><D7AA><EFBFBD>ĵ<EFBFBD><C4B5><EFBFBD> x <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߶εķ<CEB5>Χ<EFBFBD>ڣ<EFBFBD><DAA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>㴹ֱ<E3B4B9><D6B1><EFBFBD><EFBFBD>
|
|
|
|
|
|
if (rotatedP.x >= rotatedA.x && rotatedP.x <= rotatedB.x) {
|
|
|
|
|
|
//double dist = fabs(rotatedP.y - rotatedA.y); // <20><>ֱ<EFBFBD><D6B1><EFBFBD><EFBFBD>Ϊ y <20><><EFBFBD><EFBFBD>֮<EFBFBD><D6AE>
|
|
|
|
|
|
minDist = distY;
|
|
|
|
|
|
//closestPoint = point; // <20><><EFBFBD><EFBFBD>ԭ<EFBFBD><D4AD><EFBFBD><EFBFBD>ϵ<EFBFBD>еĵ<D0B5>
|
|
|
|
|
|
index2 = i;
|
|
|
|
|
|
index1 = j;
|
|
|
|
|
|
|
|
|
|
|
|
closest2 = Point64{ rotatedP.x , rotatedA.y };
|
|
|
|
|
|
closest2 = rotatePoint(closest2, cosTheta, -sinTheta); // <20><>ת<EFBFBD><D7AA>ԭ<EFBFBD><D4AD><EFBFBD><EFBFBD>
|
|
|
|
|
|
closest1 = point;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڷ<EFBFBD>Χ<EFBFBD>ڣ<EFBFBD><DAA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>㵽<EFBFBD>߶ζ˵<CEB6><CBB5>ľ<EFBFBD><C4BE><EFBFBD>
|
|
|
|
|
|
size_t dSpaceXA = abs(rotatedP.x - rotatedA.x);
|
|
|
|
|
|
size_t dSpaceXB = abs(rotatedP.x - rotatedB.x);
|
|
|
|
|
|
size_t dSpaceXMin = min(dSpaceXA, dSpaceXB);
|
|
|
|
|
|
if (dSpaceXA > minDist && dSpaceXB > minDist)
|
|
|
|
|
|
{
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (dSpaceXA < dSpaceXB) {
|
|
|
|
|
|
double dDist = distance(rotatedA, rotatedP);
|
|
|
|
|
|
if (dDist < minDist)
|
|
|
|
|
|
{
|
|
|
|
|
|
minDist = dDist;
|
|
|
|
|
|
index2 = i;
|
|
|
|
|
|
index1 = j;
|
|
|
|
|
|
closest2 = p1;
|
|
|
|
|
|
closest1 = point;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else {
|
|
|
|
|
|
double dDist = distance(rotatedB, rotatedP);
|
|
|
|
|
|
if (dDist < minDist)
|
|
|
|
|
|
{
|
|
|
|
|
|
minDist = dDist;
|
|
|
|
|
|
index2 = i;
|
|
|
|
|
|
index1 = j;
|
|
|
|
|
|
closest2 = p2;
|
|
|
|
|
|
closest1 = point;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return { closest1, closest2, index1, index2, minDist };
|
|
|
|
|
|
}
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ε<EFBFBD><CEB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
tuple<Point64, Point64, int, int, double> findClosestPoints(const Path64& poly1, const Path64& poly2) {
|
|
|
|
|
|
Point64 closest1, closest2;
|
|
|
|
|
|
double minDist = 1e30;
|
|
|
|
|
|
int index1 = -1, index2 = -1;
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ε<EFBFBD>ÿһ<C3BF><D2BB><EFBFBD><EFBFBD>
|
|
|
|
|
|
for (int i = 0; i < poly1.size(); i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
Point64 p1 = poly1[i];
|
|
|
|
|
|
Point64 p2 = poly1[(i + 1) % poly1.size()];
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD>ڶ<EFBFBD><DAB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ε<EFBFBD>ÿ<EFBFBD><C3BF><EFBFBD><EFBFBD><EFBFBD>㣬<EFBFBD><E3A3AC><EFBFBD>㵽ÿ<E3B5BD><C3BF><EFBFBD>ߵľ<DFB5><C4BE><EFBFBD>
|
|
|
|
|
|
for (int j = 0; j < poly2.size(); j++)
|
|
|
|
|
|
{
|
|
|
|
|
|
Point64 point = poly2[j];
|
|
|
|
|
|
Point64 ptConn = GetClosestPtOnSegment(p1, p2, point);
|
|
|
|
|
|
double dDisConn = distance(ptConn, point);
|
|
|
|
|
|
if (dDisConn < minDist) {
|
|
|
|
|
|
minDist = dDisConn;
|
|
|
|
|
|
|
|
|
|
|
|
index1 = i;
|
|
|
|
|
|
index2 = j;
|
|
|
|
|
|
|
|
|
|
|
|
closest1 = ptConn;
|
|
|
|
|
|
closest2 = point;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD>ڶ<EFBFBD><DAB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ε<EFBFBD>ÿһ<C3BF><D2BB><EFBFBD><EFBFBD>
|
|
|
|
|
|
for (int i = 0; i < poly2.size(); i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
Point64 p1 = poly2[i];
|
|
|
|
|
|
Point64 p2 = poly2[(i + 1) % poly2.size()];
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ε<EFBFBD>ÿ<EFBFBD><C3BF><EFBFBD><EFBFBD><EFBFBD>㣬<EFBFBD><E3A3AC><EFBFBD>㵽ÿ<E3B5BD><C3BF><EFBFBD>ߵľ<DFB5><C4BE><EFBFBD>
|
|
|
|
|
|
for(int j=0;j<poly1.size();j++)
|
|
|
|
|
|
{
|
|
|
|
|
|
Point64 point = poly1[j];
|
|
|
|
|
|
Point64 ptConn = GetClosestPtOnSegment(p1, p2, point);
|
|
|
|
|
|
|
|
|
|
|
|
double dDisConn = distance(ptConn, point);
|
|
|
|
|
|
if (dDisConn < minDist)
|
|
|
|
|
|
{
|
|
|
|
|
|
minDist = dDisConn;
|
|
|
|
|
|
index2 = i;
|
|
|
|
|
|
index1 = j;
|
|
|
|
|
|
|
|
|
|
|
|
closest2 = ptConn;
|
|
|
|
|
|
closest1 = point;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//for (int i = 0; i < poly1.size();i++) {
|
|
|
|
|
|
// Point64 p1 = poly1[i];
|
|
|
|
|
|
// for (int j = 0; j < poly2.size();j++) {
|
|
|
|
|
|
// Point64 p2 = poly2[j];
|
|
|
|
|
|
// double dist = distance(p1, p2);
|
|
|
|
|
|
// if (dist < minDist) {
|
|
|
|
|
|
// minDist = dist;
|
|
|
|
|
|
// closest1 = p1;
|
|
|
|
|
|
// closest2 = p2;
|
|
|
|
|
|
|
|
|
|
|
|
// index1 = i;
|
|
|
|
|
|
// index2 = j;
|
|
|
|
|
|
// }
|
|
|
|
|
|
// }
|
|
|
|
|
|
//}
|
|
|
|
|
|
return { closest1, closest2, index1, index2, minDist };
|
|
|
|
|
|
}
|
|
|
|
|
|
tuple<int, Point64, Point64, int, int, double> findClosestPath(const Path64& path, const Paths64& source, const std::vector< BoundingBox64> boundings)
|
|
|
|
|
|
{
|
|
|
|
|
|
vector<int> vecSearchIndexs;
|
|
|
|
|
|
BoundingBox64 bounding;
|
|
|
|
|
|
bounding.CreateBoundary(path);
|
|
|
|
|
|
double dDistMin = INT64_MAX;
|
|
|
|
|
|
int nSearchNeareast = -1;
|
|
|
|
|
|
for (int i = 0; i < boundings.size(); i++) {
|
|
|
|
|
|
BoundingBox64* pBdCur = (BoundingBox64*)(&boundings[i]);
|
|
|
|
|
|
if (pBdCur->Intersects(bounding)) {
|
|
|
|
|
|
vecSearchIndexs.emplace_back(i);
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
double dDist = bounding.DistanceTo(*pBdCur);
|
|
|
|
|
|
if (dDist < dDistMin) {
|
|
|
|
|
|
nSearchNeareast = i;
|
|
|
|
|
|
dDistMin = dDist;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if (nSearchNeareast > -1) {
|
|
|
|
|
|
vecSearchIndexs.emplace_back(nSearchNeareast);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Point64 closest1, closest2;
|
|
|
|
|
|
int idxFind = -1;
|
|
|
|
|
|
int idxEdge1 = -1, idxEdge2 = -1;
|
|
|
|
|
|
dDistMin = INT64_MAX;
|
|
|
|
|
|
for (const auto& index : vecSearchIndexs)
|
|
|
|
|
|
{
|
|
|
|
|
|
Path64 item = source[index];
|
|
|
|
|
|
//auto[p1, p2, index1, index2, distance] = findClosestPoints(path, item);
|
|
|
|
|
|
double dDistOld = dDistMin;
|
|
|
|
|
|
auto[p1, p2, index1, index2, distance] = findClosestPointWithRotation(path, item, dDistMin);
|
|
|
|
|
|
if (dDistMin <= 1E-6) {
|
|
|
|
|
|
idxFind = index;
|
|
|
|
|
|
dDistMin = distance;
|
|
|
|
|
|
closest1 = p1;
|
|
|
|
|
|
closest2 = p2;
|
|
|
|
|
|
idxEdge1 = index1;
|
|
|
|
|
|
idxEdge2 = index2;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (distance < dDistOld) {
|
|
|
|
|
|
idxFind = index;
|
|
|
|
|
|
dDistMin = distance;
|
|
|
|
|
|
closest1 = p1;
|
|
|
|
|
|
closest2 = p2;
|
|
|
|
|
|
idxEdge1 = index1;
|
|
|
|
|
|
idxEdge2 = index2;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
//for (int i = 0; i < source.size();i++) {
|
|
|
|
|
|
// Path64 item = source[i];
|
|
|
|
|
|
// auto[p1, p2, index1, index2, distance] = findClosestPoints(path, item);
|
|
|
|
|
|
// if (distance < minDist) {
|
|
|
|
|
|
// idxFind = i;
|
|
|
|
|
|
// minDist = distance;
|
|
|
|
|
|
// closest1 = p1;
|
|
|
|
|
|
// closest2 = p2;
|
|
|
|
|
|
// idxEdge1 = index1;
|
|
|
|
|
|
// idxEdge2 = index2;
|
|
|
|
|
|
// }
|
|
|
|
|
|
//}
|
|
|
|
|
|
return { idxFind, closest1, closest2, idxEdge1, idxEdge2, dDistMin };
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ
|
|
|
|
|
|
Path64 ConnectPolygons(const Paths64& polygons) {
|
|
|
|
|
|
if (polygons.size() == 0) {
|
|
|
|
|
|
return Path64();
|
|
|
|
|
|
}
|
|
|
|
|
|
Paths64 lstSource;
|
|
|
|
|
|
std::vector< BoundingBox64> boundings;
|
|
|
|
|
|
for (const auto& polygon : polygons) {
|
|
|
|
|
|
lstSource.emplace_back(polygon);
|
|
|
|
|
|
BoundingBox64 bounding;
|
|
|
|
|
|
bounding.CreateBoundary(polygon);
|
|
|
|
|
|
boundings.emplace_back(bounding);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Path64 pathResult = lstSource[0];
|
|
|
|
|
|
lstSource.erase(lstSource.begin());
|
|
|
|
|
|
boundings.erase(boundings.begin());
|
|
|
|
|
|
while (lstSource.size() > 0) {
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ķ<EFBFBD><C4B6><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
auto[findIndex, p1, p2, index1, index2, findDist] = findClosestPath(pathResult, lstSource, boundings);
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><CDA8>
|
|
|
|
|
|
pathResult.insert(pathResult.begin() + index1+1, p1);
|
|
|
|
|
|
|
|
|
|
|
|
pathResult.insert(pathResult.begin() + index1+2, p2);
|
|
|
|
|
|
|
|
|
|
|
|
// <20>ϲ<EFBFBD><CFB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ķ<EFBFBD><C4B6><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
Path64 pathFind = lstSource[findIndex];
|
|
|
|
|
|
std::rotate(pathFind.begin(), pathFind.begin() + index2+1, pathFind.end());
|
|
|
|
|
|
pathResult.insert(pathResult.begin() + index1+3, pathFind.begin(), pathFind.end());
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><CDA8>
|
|
|
|
|
|
pathResult.insert(pathResult.begin() + index1 + 3 + pathFind.size(), p2);
|
|
|
|
|
|
pathResult.insert(pathResult.begin() + index1+3 + pathFind.size()+1, p1);
|
|
|
|
|
|
lstSource.erase(lstSource.begin() + findIndex);
|
|
|
|
|
|
|
|
|
|
|
|
boundings.erase(boundings.begin() + findIndex);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return pathResult;
|
|
|
|
|
|
}
|