From 66d652fa30b728feac1aea15e7bf9327771657a1 Mon Sep 17 00:00:00 2001 From: "yang.yongquan" <3395816735@qq.com> Date: Sun, 20 Nov 2022 16:46:17 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=BA=86=E5=AF=B9=E4=BA=8E?= =?UTF-8?q?=E4=B8=8EX=E8=BD=B4=E5=B9=B3=E8=A1=8C=E7=9B=B4=E7=BA=BF?= =?UTF-8?q?=E7=9A=84=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ArchitectureColoredPainting.vcxproj | 4 + ...rchitectureColoredPainting.vcxproj.filters | 10 ++ .../src/Renderer/Painting/Line.cpp | 9 ++ .../src/Renderer/Painting/Line.h | 2 + .../src/Renderer/Painting/LineTree.cpp | 117 ++++++++++++++++++ .../src/Renderer/Painting/LineTree.h | 51 ++++++++ .../src/Renderer/Painting/ShortCutTree.cpp | 6 +- .../src/Renderer/Painting/ShortCutTree.h | 9 +- .../src/Renderer/Painting/StraightLine.h | 1 + 9 files changed, 201 insertions(+), 8 deletions(-) create mode 100644 ArchitectureColoredPainting/src/Renderer/Painting/LineTree.cpp create mode 100644 ArchitectureColoredPainting/src/Renderer/Painting/LineTree.h diff --git a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj index 1c52dfd..148dec9 100644 --- a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj +++ b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj @@ -113,6 +113,7 @@ + @@ -132,6 +133,8 @@ + + @@ -153,6 +156,7 @@ + diff --git a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj.filters b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj.filters index b73c477..8c848f9 100644 --- a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj.filters +++ b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj.filters @@ -129,6 +129,9 @@ Source Files\Editor + + Source Files\Renderer\Painting + @@ -211,6 +214,10 @@ Resource Files + + Source Files + + @@ -272,6 +279,9 @@ Header Files\Editor + + Header Files\Renderer\Painting + diff --git a/ArchitectureColoredPainting/src/Renderer/Painting/Line.cpp b/ArchitectureColoredPainting/src/Renderer/Painting/Line.cpp index b5ed91a..439abd9 100644 --- a/ArchitectureColoredPainting/src/Renderer/Painting/Line.cpp +++ b/ArchitectureColoredPainting/src/Renderer/Painting/Line.cpp @@ -85,4 +85,13 @@ bool Line::judgeIntersection(QVector4D bound) { || judgeBoundIntersection(bound.w(), bound.x(), bound.z(), true) || judgeBoundIntersection(bound.x(), bound.y(), bound.w(), false) || judgeBoundIntersection(bound.z(), bound.y(), bound.w(), false); +} + +void Line::upwardOffsetForY(bool isStart, double offset) { + if (isStart) { + vY[0] = vY[0] + offset; + } + else { + vY[siz - 1] = vY[siz - 1] + offset; + } } \ No newline at end of file diff --git a/ArchitectureColoredPainting/src/Renderer/Painting/Line.h b/ArchitectureColoredPainting/src/Renderer/Painting/Line.h index 6b0e57e..c0677cb 100644 --- a/ArchitectureColoredPainting/src/Renderer/Painting/Line.h +++ b/ArchitectureColoredPainting/src/Renderer/Painting/Line.h @@ -46,6 +46,8 @@ namespace Renderer virtual void monotonization(std::vector & res) = 0; virtual int judgeBoundIntersection(double xy, double l, double r, bool isY) = 0; virtual bool judgeIntersection(QVector4D bound); + virtual double minDistanceToLine(Point uv); + void upwardOffsetForY(bool isStart, double offset); bool isLineContained(QVector4D bound); Point operator[](int index) const; Point getPointByIndex(int index) const; diff --git a/ArchitectureColoredPainting/src/Renderer/Painting/LineTree.cpp b/ArchitectureColoredPainting/src/Renderer/Painting/LineTree.cpp new file mode 100644 index 0000000..93af7c2 --- /dev/null +++ b/ArchitectureColoredPainting/src/Renderer/Painting/LineTree.cpp @@ -0,0 +1,117 @@ +#include "LineTree.h" +#include + +using namespace Renderer; +using std::set; +using std::vector; + +void LineTree::init() { + restOfTreeNodes.clear(); + allLine.clear(); + pointMap.clear(); + lineIndexs.clear(); + numLine = numPoint = 0; +} + +void LineTree::setLineWidth(int width) { + lineWidth = width; +} + +int LineTree::getPointIndex(Point nowPoint) { + auto iter = pointMap.find(nowPoint); + if (iter != pointMap.end()) { + return iter->second; + } + else { + int res = numPoint; + pointMap.insert({ nowPoint, numPoint }); + ++numPoint; + return res; + } +} + +bool LineTree::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 LineTree::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 LineTree::isLineEqual(PointIndexVector& a, PointIndexVector& b) const { + if (a.size() != b.size()) + return false; + for (int i = 0; i < a.size(); i++) + if (a[i] != b[i]) + return false; + return true; +} + +void LineTree::monotonization(vector& inLines, vector>& outLines) { + bool isOffset = false; + for (PointVector& l : inLines) { + std::shared_ptr nowLine; + switch (l.size()) { + case 2: { + nowLine.reset(new StraightLine(l)); + break; + } + case 3: case 4: nowLine.reset(new CubicBezier(l)); break; + default: break; + } + + // 防止在同一直线与 X 轴平行上 + if (isOffset) { + nowLine->upwardOffsetForY(true, 1e-5); + } + isOffset = false; + if (nowLine->direction(true) == 0) { + nowLine->upwardOffsetForY(false, 1e-5); + isOffset = true; + } + nowLine->monotonization(outLines); + outLines.push_back(nowLine); + } + // 防止在首尾直线在与 X 轴平行上 + int siz = outLines.size(); + if (!(outLines[0]->getBegin() == outLines[siz - 1]->getEnd())) + return; + if (isOffset) { + outLines[0]->upwardOffsetForY(true, 1e-5); + } + if (outLines[0]->direction(true) == 0) { + outLines[0]->upwardOffsetForY(true, 2e-5); + outLines[outLines.size() - 1]->upwardOffsetForY(false, 2e-5); + } +} + +void LineTree::simplifyLineVector() { + numLine = allLine.size(); + for (auto& nowLine : allLine) { + PointVector pointVector = nowLine->toPointVector(); + for (Point& p : pointVector) { + int pointIndex = getPointIndex(p); + lineIndexs.push_back(pointIndex); + if (pointVector.size() == 2) + lineIndexs.push_back(pointIndex); + } + } +} \ No newline at end of file diff --git a/ArchitectureColoredPainting/src/Renderer/Painting/LineTree.h b/ArchitectureColoredPainting/src/Renderer/Painting/LineTree.h new file mode 100644 index 0000000..bf839ec --- /dev/null +++ b/ArchitectureColoredPainting/src/Renderer/Painting/LineTree.h @@ -0,0 +1,51 @@ +#pragma once +#include "CubicBezier.h" +#include "StraightLine.h" +#include "BvhTree.h" +#include +#include + +namespace Renderer { + struct LineTreeNode { + int eastGroup; + bool divided; + /* + 0:不需要拆开的节点 + 1:需要拆分*/ + QVector4D bound; + std::vector lineSet; + LineTreeNode() { + eastGroup = 0; + divided = true; + bound = { 0, 0, 0, 0 }; + lineSet.clear(); + } + ~LineTreeNode() {} + }; + class LineTree { + typedef std::vector PointVector; + typedef std::vector PointIndexVector; + private: + std::vector restOfTreeNodes; + std::vector> allLine; + int requiredLineMin, numPoint, numLine, lineWidth; + std::map pointMap; + std::vector lineIndexs; + + int getPointIndex(Point nowPoint); + void spliteToLineTree(); + void simplifyLineVector(); + bool handleShortCutNode(LineTreeNode& fa, LineTreeNode& nowTreeNode, double yValue, std::vector& v); + bool isLineEqual(PointIndexVector& a, PointIndexVector& b) const; + static bool IsBorderValueResonable(double value, std::set & valueSet); + static double findBorderValueNotOnLine(double value, std::set & valueSet); + static void monotonization(std::vector& inL, std::vector>& outL); + public: + void init(); + void setLineWidth(int width); + LineTree(int lineMin = 3, int width = 0.3) + : requiredLineMin(lineMin), lineWidth(width), numLine(0), numPoint(0) {} + void buildLineTree(std::vector& lineSet); + std::vector getPointLineAndBvhTree(std::vector& pointSet, std::vector& lineSet); + }; +} \ No newline at end of file diff --git a/ArchitectureColoredPainting/src/Renderer/Painting/ShortCutTree.cpp b/ArchitectureColoredPainting/src/Renderer/Painting/ShortCutTree.cpp index 8a1069b..60f4b64 100644 --- a/ArchitectureColoredPainting/src/Renderer/Painting/ShortCutTree.cpp +++ b/ArchitectureColoredPainting/src/Renderer/Painting/ShortCutTree.cpp @@ -76,7 +76,7 @@ void ShortCutTree::monotonization(vector& inLines, vector > pointSet; for (int & lineIndex : nowTreeNode.lineSet) { @@ -133,7 +133,7 @@ bool ShortCutTree::handleShortCutNode(ShortCutNode& fa, ShortCutNode& nowTreeNod } } qDebug() << nowTreeNode.lineSet.size() ; - if (nowTreeNode.lineSet.size() <= RequiredLineMin) { + if (nowTreeNode.lineSet.size() <= requiredLineMin) { if (nowTreeNode.lineSet.empty() && nowTreeNode.windingIncrement == 0) return false; restOfTreeNodes.push_back(nowTreeNode); @@ -160,7 +160,7 @@ void ShortCutTree::simplifyLineVector() { } } for (auto& nowTreeNode : restOfTreeNodes) { - generateShortCutsegmentement(nowTreeNode); + generateShortCutSegment(nowTreeNode); } } diff --git a/ArchitectureColoredPainting/src/Renderer/Painting/ShortCutTree.h b/ArchitectureColoredPainting/src/Renderer/Painting/ShortCutTree.h index cf58e99..527a4c3 100644 --- a/ArchitectureColoredPainting/src/Renderer/Painting/ShortCutTree.h +++ b/ArchitectureColoredPainting/src/Renderer/Painting/ShortCutTree.h @@ -9,10 +9,9 @@ namespace Renderer struct ShortCutNode { - typedef std::vector vectorPoint; int windingIncrement, eastGroup; bool divided; - /* type 代表进入广度优先搜索队列的节点种类: + /* 0:不需要拆开的节点 1:需要拆分*/ QVector4D bound; @@ -33,12 +32,12 @@ namespace Renderer private: std::vector restOfTreeNodes; std::vector> allLine; - int RequiredLineMin, numPoint, numLine; + int requiredLineMin, numPoint, numLine; std::map pointMap; std::vector lineIndexs; int getPointIndex(Point nowPoint); - void generateShortCutsegmentement(ShortCutNode& nowTreeNode); + void generateShortCutSegment(ShortCutNode& nowTreeNode); bool handleShortCutNode(ShortCutNode& fa, ShortCutNode& nowTreeNode, double yValue, std::vector& v, int& sumIncrement); void spliteToShortCutTree(); static void monotonization(std::vector& inL, std::vector>& outL); @@ -51,7 +50,7 @@ namespace Renderer void init(); //lineMin最小线数目,即划分终止条件 ShortCutTree(int lineMin = 3) - :RequiredLineMin(lineMin), numPoint(0), numLine(0) {} + :requiredLineMin(lineMin), numPoint(0), numLine(0) {} // 传入一个vector > 作为所有输入的线 void buildShortCutTree(std::vector& lineSet); // 获得点集合和线集合 返回输入BvhTree的数据集合 diff --git a/ArchitectureColoredPainting/src/Renderer/Painting/StraightLine.h b/ArchitectureColoredPainting/src/Renderer/Painting/StraightLine.h index 38f6b2c..c5ebeda 100644 --- a/ArchitectureColoredPainting/src/Renderer/Painting/StraightLine.h +++ b/ArchitectureColoredPainting/src/Renderer/Painting/StraightLine.h @@ -1,3 +1,4 @@ +#pragma once #include "Line.h" namespace Renderer {