From e279007d884174fea08142a6e6ea979cfed42328 Mon Sep 17 00:00:00 2001 From: "yang.yongquan" <3395816735@qq.com> Date: Tue, 18 Oct 2022 20:00:58 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E6=AD=A5=E8=A7=A3=E5=86=B3=E4=BA=86?= =?UTF-8?q?=E7=BA=BF=E5=9C=A8=E6=96=B9=E6=A0=BC=E8=BE=B9=E7=95=8C=E4=B8=8A?= =?UTF-8?q?=E7=9A=84=E7=89=B9=E6=AE=8A=E6=83=85=E5=86=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ArchitectureColoredPainting/ShortCutTree.cpp | 120 ++++++++++++------- ArchitectureColoredPainting/ShortCutTree.h | 3 + 2 files changed, 77 insertions(+), 46 deletions(-) diff --git a/ArchitectureColoredPainting/ShortCutTree.cpp b/ArchitectureColoredPainting/ShortCutTree.cpp index 94c3ecd..555e7bb 100644 --- a/ArchitectureColoredPainting/ShortCutTree.cpp +++ b/ArchitectureColoredPainting/ShortCutTree.cpp @@ -22,6 +22,32 @@ int ShortCutTree::getPointIndex(Point nowPoint) { } } +bool ShortCutTree::IsBorderValueResonable(double value, set & 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& 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& inL, vector& outL) { - for (PointVector&l: inL) { +void ShortCutTree::monotonization(vector& inLines, vector& 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 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 Q; queue > lineBound; ShortCutNode root; @@ -144,13 +179,15 @@ void ShortCutTree::spliteToShortCutTree() { root.eastGroup = eastGroupSize; Q.push(root); lineBound.push({ -1, 1 }); - vector tmpTreeNodes, generatedTreeNodes; + vector 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) { + lineBound.push({ segment.first, yMid }); + for (auto& nowTreeNode : lowerTreeNodes) { nowTreeNode.eastGroup = eastGroupSize; Q.push(nowTreeNode); } diff --git a/ArchitectureColoredPainting/ShortCutTree.h b/ArchitectureColoredPainting/ShortCutTree.h index 59ee04f..31f0f7a 100644 --- a/ArchitectureColoredPainting/ShortCutTree.h +++ b/ArchitectureColoredPainting/ShortCutTree.h @@ -46,6 +46,9 @@ private: static void monotonization(vector& inL, vector &outL); bool isLineEqual(PointIndexVector& a, PointIndexVector& b) const; void simplifyLineVector(); + // 需要测试,随机获得合理的边界 + static bool IsBorderValueResonable(double value, set & valueSet); + static double findBorderValueNotOnLine(double value, set & valueSet); public: void init(); //lineMin最小线数目,即划分终止条件