初步解决了线在方格边界上的特殊情况

dev-VirtualTexture
yang.yongquan 2022-10-18 20:00:58 +08:00
parent 656fa704a7
commit e279007d88
2 changed files with 77 additions and 46 deletions

View File

@ -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);
} }

View File

@ -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最小线数目即划分终止条件