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

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 {
if (a.size() != b.size())
return false;
@ -31,16 +57,16 @@ bool ShortCutTree::isLineEqual(PointIndexVector& a, PointIndexVector& b) const {
return true;
}
void ShortCutTree::monotonization(vector<PointVector>& inL, vector<LinePtr>& outL) {
for (PointVector&l: inL) {
void ShortCutTree::monotonization(vector<PointVector>& inLines, vector<LinePtr>& outLines) {
for (PointVector&l: inLines) {
LinePtr nowLine;
switch(l.size()) {
case 2: nowLine.reset(new StraightLine(l)); break;
case 3: case 4: nowLine.reset(new CubicBezier(l)); break;
default: break;
}
nowLine->monotonization(outL);
outL.push_back(nowLine);
nowLine->monotonization(outLines);
outLines.push_back(nowLine);
}
}
@ -133,6 +159,15 @@ void ShortCutTree::simplifyLineVector() {
}
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<pair<double, double> > lineBound;
ShortCutNode root;
@ -144,13 +179,15 @@ void ShortCutTree::spliteToShortCutTree() {
root.eastGroup = eastGroupSize;
Q.push(root);
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()) {
// 取出一行的所有可行方格
++nowEastGroup;
auto segment = lineBound.front();
auto segment = lineBound.front(); lineBound.pop();
double yMid = (segment.first + segment.second) / 2;
lineBound.pop();
yMid = findBorderValueNotOnLine(yMid, yLineSet);
while (!Q.empty()) {
auto nowTreeNode = Q.front();
if (nowTreeNode.eastGroup == nowEastGroup) {
@ -161,66 +198,57 @@ void ShortCutTree::spliteToShortCutTree() {
break;
}
}
int sumIncrement = 0;
bool isDivided = false;
generatedTreeNodes.clear();
// Éϲ¿·Ö;
sumUpperIncrement = 0; sumLowerIncrement = 0;
isUpperDivided = false; isLowerDivided = false;
upperTreeNodes.clear(); lowerTreeNodes.clear();
// 处理方格;
for (auto& nowTreeNode : tmpTreeNodes) {
if (!nowTreeNode.divided) {
for (int& lineIndex : nowTreeNode.lineSet) {
// 上半部分
int type = allLine[lineIndex]->judgeBoundIntersection(yMid, nowTreeNode.bound.x(), nowTreeNode.bound.z(), true);
if (type == 2)
sumIncrement++;
sumUpperIncrement++;
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 {
ShortCutNode nwTreeNode, neTreeNode;
ShortCutNode nwTreeNode, neTreeNode, seTreeNode, swTreeNode;
double xMid = (nowTreeNode.bound.x() + nowTreeNode.bound.z()) / 2;
xMid = findBorderValueNotOnLine(xMid, xLineSet);
// 上部分
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());
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;
lineBound.push({yMid, segment.second});
for (auto nowTreeNode : generatedTreeNodes) {
for (auto& nowTreeNode : upperTreeNodes) {
nowTreeNode.eastGroup = eastGroupSize;
Q.push(nowTreeNode);
}
}
// ϲ¿·Ö
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) {
if (isLowerDivided) {
++eastGroupSize;
lineBound.push({ segment.first, yMid });
for (auto nowTreeNode : generatedTreeNodes) {
for (auto& nowTreeNode : lowerTreeNodes) {
nowTreeNode.eastGroup = eastGroupSize;
Q.push(nowTreeNode);
}

View File

@ -46,6 +46,9 @@ private:
static void monotonization(vector<PointVector>& inL, vector<LinePtr> &outL);
bool isLineEqual(PointIndexVector& a, PointIndexVector& b) const;
void simplifyLineVector();
// 需要测试,随机获得合理的边界
static bool IsBorderValueResonable(double value, set <double>& valueSet);
static double findBorderValueNotOnLine(double value, set <double>& valueSet);
public:
void init();
//lineMin最小线数目即划分终止条件