初步解决了线在方格边界上的特殊情况
parent
656fa704a7
commit
e279007d88
|
@ -22,6 +22,32 @@ int ShortCutTree::getPointIndex(Point nowPoint) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ShortCutTree::IsBorderValueResonable(double value, set <double>& valueSet) {
|
||||||
|
bool isResonable = true;
|
||||||
|
auto iter = valueSet.lower_bound(value);
|
||||||
|
if (iter != valueSet.end() && fabs(*iter-value) <= eps) {
|
||||||
|
isResonable = false;
|
||||||
|
}
|
||||||
|
if (iter != valueSet.begin()) {
|
||||||
|
iter--;
|
||||||
|
if (fabs(*iter - value) <= eps) {
|
||||||
|
isResonable = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return isResonable;
|
||||||
|
}
|
||||||
|
|
||||||
|
double ShortCutTree::findBorderValueNotOnLine(double value, set<double>& valueSet) {
|
||||||
|
if (IsBorderValueResonable(value, valueSet)) return value;
|
||||||
|
for (int i = 1; i <= 200; i++) {
|
||||||
|
double changedValue = value + rand() % 50 * 1e-5 + 1e-5;
|
||||||
|
if (IsBorderValueResonable(changedValue, valueSet)) {
|
||||||
|
return changedValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
bool ShortCutTree::isLineEqual(PointIndexVector& a, PointIndexVector& b) const {
|
bool ShortCutTree::isLineEqual(PointIndexVector& a, PointIndexVector& b) const {
|
||||||
if (a.size() != b.size())
|
if (a.size() != b.size())
|
||||||
return false;
|
return false;
|
||||||
|
@ -31,16 +57,16 @@ bool ShortCutTree::isLineEqual(PointIndexVector& a, PointIndexVector& b) const {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShortCutTree::monotonization(vector<PointVector>& inL, vector<LinePtr>& outL) {
|
void ShortCutTree::monotonization(vector<PointVector>& inLines, vector<LinePtr>& outLines) {
|
||||||
for (PointVector&l: inL) {
|
for (PointVector&l: inLines) {
|
||||||
LinePtr nowLine;
|
LinePtr nowLine;
|
||||||
switch(l.size()) {
|
switch(l.size()) {
|
||||||
case 2: nowLine.reset(new StraightLine(l)); break;
|
case 2: nowLine.reset(new StraightLine(l)); break;
|
||||||
case 3: case 4: nowLine.reset(new CubicBezier(l)); break;
|
case 3: case 4: nowLine.reset(new CubicBezier(l)); break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
nowLine->monotonization(outL);
|
nowLine->monotonization(outLines);
|
||||||
outL.push_back(nowLine);
|
outLines.push_back(nowLine);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,6 +159,15 @@ void ShortCutTree::simplifyLineVector() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShortCutTree::spliteToShortCutTree() {
|
void ShortCutTree::spliteToShortCutTree() {
|
||||||
|
// 防止直线的点落在边界上
|
||||||
|
set<double> xLineSet, yLineSet;
|
||||||
|
for (int i = 0; i < allLine.size(); i++) {
|
||||||
|
xLineSet.insert(allLine[i]->getBegin().x);
|
||||||
|
xLineSet.insert(allLine[i]->getEnd().x);
|
||||||
|
yLineSet.insert(allLine[i]->getBegin().y);
|
||||||
|
yLineSet.insert(allLine[i]->getEnd().y);
|
||||||
|
}
|
||||||
|
// 生成方格
|
||||||
queue<ShortCutNode> Q;
|
queue<ShortCutNode> Q;
|
||||||
queue<pair<double, double> > lineBound;
|
queue<pair<double, double> > lineBound;
|
||||||
ShortCutNode root;
|
ShortCutNode root;
|
||||||
|
@ -144,13 +179,15 @@ void ShortCutTree::spliteToShortCutTree() {
|
||||||
root.eastGroup = eastGroupSize;
|
root.eastGroup = eastGroupSize;
|
||||||
Q.push(root);
|
Q.push(root);
|
||||||
lineBound.push({ -1, 1 });
|
lineBound.push({ -1, 1 });
|
||||||
vector<ShortCutNode> tmpTreeNodes, generatedTreeNodes;
|
vector<ShortCutNode> tmpTreeNodes, upperTreeNodes, lowerTreeNodes;
|
||||||
|
int sumUpperIncrement = 0, sumLowerIncrement = 0;
|
||||||
|
bool isUpperDivided = false, isLowerDivided = false;
|
||||||
while (!lineBound.empty()) {
|
while (!lineBound.empty()) {
|
||||||
// 取出一行的所有可行方格
|
// 取出一行的所有可行方格
|
||||||
++nowEastGroup;
|
++nowEastGroup;
|
||||||
auto segment = lineBound.front();
|
auto segment = lineBound.front(); lineBound.pop();
|
||||||
double yMid = (segment.first + segment.second) / 2;
|
double yMid = (segment.first + segment.second) / 2;
|
||||||
lineBound.pop();
|
yMid = findBorderValueNotOnLine(yMid, yLineSet);
|
||||||
while (!Q.empty()) {
|
while (!Q.empty()) {
|
||||||
auto nowTreeNode = Q.front();
|
auto nowTreeNode = Q.front();
|
||||||
if (nowTreeNode.eastGroup == nowEastGroup) {
|
if (nowTreeNode.eastGroup == nowEastGroup) {
|
||||||
|
@ -161,66 +198,57 @@ void ShortCutTree::spliteToShortCutTree() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int sumIncrement = 0;
|
sumUpperIncrement = 0; sumLowerIncrement = 0;
|
||||||
bool isDivided = false;
|
isUpperDivided = false; isLowerDivided = false;
|
||||||
generatedTreeNodes.clear();
|
upperTreeNodes.clear(); lowerTreeNodes.clear();
|
||||||
// Éϲ¿·Ö;
|
// 处理方格;
|
||||||
for (auto& nowTreeNode : tmpTreeNodes) {
|
for (auto& nowTreeNode : tmpTreeNodes) {
|
||||||
if (!nowTreeNode.divided) {
|
if (!nowTreeNode.divided) {
|
||||||
for (int& lineIndex : nowTreeNode.lineSet) {
|
for (int& lineIndex : nowTreeNode.lineSet) {
|
||||||
|
// 上半部分
|
||||||
int type = allLine[lineIndex]->judgeBoundIntersection(yMid, nowTreeNode.bound.x(), nowTreeNode.bound.z(), true);
|
int type = allLine[lineIndex]->judgeBoundIntersection(yMid, nowTreeNode.bound.x(), nowTreeNode.bound.z(), true);
|
||||||
if (type == 2)
|
if (type == 2)
|
||||||
sumIncrement++;
|
sumUpperIncrement++;
|
||||||
if (type == 3)
|
if (type == 3)
|
||||||
sumIncrement--;
|
sumUpperIncrement--;
|
||||||
|
// 下半部分
|
||||||
|
type = allLine[lineIndex]->judgeBoundIntersection(segment.first, nowTreeNode.bound.x(), nowTreeNode.bound.z(), true);
|
||||||
|
if (type == 2)
|
||||||
|
sumLowerIncrement++;
|
||||||
|
if (type == 3)
|
||||||
|
sumLowerIncrement--;
|
||||||
}
|
}
|
||||||
generatedTreeNodes.push_back(nowTreeNode);
|
upperTreeNodes.push_back(nowTreeNode);
|
||||||
|
lowerTreeNodes.push_back(nowTreeNode);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ShortCutNode nwTreeNode, neTreeNode;
|
ShortCutNode nwTreeNode, neTreeNode, seTreeNode, swTreeNode;
|
||||||
double xMid = (nowTreeNode.bound.x() + nowTreeNode.bound.z()) / 2;
|
double xMid = (nowTreeNode.bound.x() + nowTreeNode.bound.z()) / 2;
|
||||||
|
xMid = findBorderValueNotOnLine(xMid, xLineSet);
|
||||||
|
// 上部分
|
||||||
neTreeNode.bound = QVector4D(xMid, yMid, nowTreeNode.bound.z(), nowTreeNode.bound.w());
|
neTreeNode.bound = QVector4D(xMid, yMid, nowTreeNode.bound.z(), nowTreeNode.bound.w());
|
||||||
isDivided |= handleShortCutNode(nowTreeNode, neTreeNode, yMid, generatedTreeNodes, sumIncrement);
|
isUpperDivided |= handleShortCutNode(nowTreeNode, neTreeNode, yMid, upperTreeNodes, sumUpperIncrement);
|
||||||
nwTreeNode.bound = QVector4D(nowTreeNode.bound.x(), yMid, xMid, nowTreeNode.bound.w());
|
nwTreeNode.bound = QVector4D(nowTreeNode.bound.x(), yMid, xMid, nowTreeNode.bound.w());
|
||||||
isDivided |= handleShortCutNode(nowTreeNode, nwTreeNode, yMid, generatedTreeNodes, sumIncrement);
|
isUpperDivided |= handleShortCutNode(nowTreeNode, nwTreeNode, yMid, upperTreeNodes, sumUpperIncrement);
|
||||||
|
// 下部分
|
||||||
|
seTreeNode.bound = QVector4D(xMid, nowTreeNode.bound.y(), nowTreeNode.bound.z(), yMid);
|
||||||
|
isLowerDivided |= handleShortCutNode(nowTreeNode, seTreeNode, segment.first, lowerTreeNodes, sumLowerIncrement);
|
||||||
|
swTreeNode.bound = QVector4D(nowTreeNode.bound.x(), nowTreeNode.bound.y(), xMid, yMid);
|
||||||
|
isLowerDivided |= handleShortCutNode(nowTreeNode, swTreeNode, segment.first, lowerTreeNodes, sumLowerIncrement);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (isDivided) {
|
if (isUpperDivided) {
|
||||||
++eastGroupSize;
|
++eastGroupSize;
|
||||||
lineBound.push({yMid, segment.second});
|
lineBound.push({yMid, segment.second});
|
||||||
for (auto nowTreeNode : generatedTreeNodes) {
|
for (auto& nowTreeNode : upperTreeNodes) {
|
||||||
nowTreeNode.eastGroup = eastGroupSize;
|
nowTreeNode.eastGroup = eastGroupSize;
|
||||||
Q.push(nowTreeNode);
|
Q.push(nowTreeNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ϲ¿·Ö
|
if (isLowerDivided) {
|
||||||
generatedTreeNodes.clear();
|
|
||||||
sumIncrement = 0;
|
|
||||||
isDivided = false;
|
|
||||||
for (auto& nowTreeNode : tmpTreeNodes) {
|
|
||||||
if (!nowTreeNode.divided) {
|
|
||||||
for (int& lineIndex : nowTreeNode.lineSet) {
|
|
||||||
int type = allLine[lineIndex]->judgeBoundIntersection(segment.first, nowTreeNode.bound.x(), nowTreeNode.bound.z(), true);
|
|
||||||
if (type == 2)
|
|
||||||
sumIncrement++;
|
|
||||||
if (type == 3)
|
|
||||||
sumIncrement--;
|
|
||||||
}
|
|
||||||
generatedTreeNodes.push_back(nowTreeNode);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ShortCutNode seTreeNode, swTreeNode;
|
|
||||||
float xMid = (nowTreeNode.bound.x() + nowTreeNode.bound.z()) / 2+1e-5;
|
|
||||||
seTreeNode.bound = QVector4D(xMid, nowTreeNode.bound.y(), nowTreeNode.bound.z(), yMid);
|
|
||||||
isDivided |= handleShortCutNode(nowTreeNode, seTreeNode, segment.first, generatedTreeNodes, sumIncrement);
|
|
||||||
swTreeNode.bound = QVector4D(nowTreeNode.bound.x(), nowTreeNode.bound.y(), xMid, yMid);
|
|
||||||
isDivided |= handleShortCutNode(nowTreeNode, swTreeNode, segment.first, generatedTreeNodes, sumIncrement);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (isDivided) {
|
|
||||||
++eastGroupSize;
|
++eastGroupSize;
|
||||||
lineBound.push({segment.first, yMid});
|
lineBound.push({ segment.first, yMid });
|
||||||
for (auto nowTreeNode : generatedTreeNodes) {
|
for (auto& nowTreeNode : lowerTreeNodes) {
|
||||||
nowTreeNode.eastGroup = eastGroupSize;
|
nowTreeNode.eastGroup = eastGroupSize;
|
||||||
Q.push(nowTreeNode);
|
Q.push(nowTreeNode);
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,9 @@ private:
|
||||||
static void monotonization(vector<PointVector>& inL, vector<LinePtr> &outL);
|
static void monotonization(vector<PointVector>& inL, vector<LinePtr> &outL);
|
||||||
bool isLineEqual(PointIndexVector& a, PointIndexVector& b) const;
|
bool isLineEqual(PointIndexVector& a, PointIndexVector& b) const;
|
||||||
void simplifyLineVector();
|
void simplifyLineVector();
|
||||||
|
// 需要测试,随机获得合理的边界
|
||||||
|
static bool IsBorderValueResonable(double value, set <double>& valueSet);
|
||||||
|
static double findBorderValueNotOnLine(double value, set <double>& valueSet);
|
||||||
public:
|
public:
|
||||||
void init();
|
void init();
|
||||||
//lineMin最小线数目,即划分终止条件
|
//lineMin最小线数目,即划分终止条件
|
||||||
|
|
Loading…
Reference in New Issue