Compare commits

...

2 Commits

Author SHA1 Message Date
yang.yongquan de037ca303 Merge 2022-11-20 16:52:02 +08:00
yang.yongquan 66d652fa30 增加了对于与X轴平行直线的修正 2022-11-20 16:46:17 +08:00
9 changed files with 195 additions and 8 deletions

View File

@ -118,6 +118,7 @@
<ClCompile Include="src\Renderer\Painting\Line.cpp" /> <ClCompile Include="src\Renderer\Painting\Line.cpp" />
<ClCompile Include="src\Renderer\Mesh.cpp" /> <ClCompile Include="src\Renderer\Mesh.cpp" />
<ClCompile Include="src\Renderer\Model.cpp" /> <ClCompile Include="src\Renderer\Model.cpp" />
<ClCompile Include="src\Renderer\Painting\LineTree.cpp" />
<ClCompile Include="src\Renderer\Painting\Painting.cpp" /> <ClCompile Include="src\Renderer\Painting\Painting.cpp" />
<ClCompile Include="src\Renderer\Painting\PaintingHelper.cpp" /> <ClCompile Include="src\Renderer\Painting\PaintingHelper.cpp" />
<ClCompile Include="src\Renderer\PaintingMesh.cpp" /> <ClCompile Include="src\Renderer\PaintingMesh.cpp" />
@ -137,6 +138,8 @@
<ItemGroup> <ItemGroup>
<None Include="darkstyle.qss" /> <None Include="darkstyle.qss" />
<None Include="lightstyle.qss" /> <None Include="lightstyle.qss" />
<None Include="msvc_make.bat" />
<None Include="qt.conf" />
<None Include="Shaders\depth_init.comp" /> <None Include="Shaders\depth_init.comp" />
<None Include="Shaders\depth_mipmap.comp" /> <None Include="Shaders\depth_mipmap.comp" />
<None Include="Shaders\final.frag" /> <None Include="Shaders\final.frag" />
@ -163,6 +166,7 @@
<ClInclude Include="src\Editor\LayerWrapper.h" /> <ClInclude Include="src\Editor\LayerWrapper.h" />
<QtMoc Include="src\Editor\PreviewWindow.h" /> <QtMoc Include="src\Editor\PreviewWindow.h" />
<ClInclude Include="src\Renderer\Painting\Element.h" /> <ClInclude Include="src\Renderer\Painting\Element.h" />
<ClInclude Include="src\Renderer\Painting\LineTree.h" />
<ClInclude Include="src\Renderer\Painting\Painting.h" /> <ClInclude Include="src\Renderer\Painting\Painting.h" />
<ClInclude Include="src\SvgParser.h" /> <ClInclude Include="src\SvgParser.h" />
<QtMoc Include="src\TitleWidget.h" /> <QtMoc Include="src\TitleWidget.h" />

View File

@ -226,6 +226,10 @@
<None Include="lightstyle.qss"> <None Include="lightstyle.qss">
<Filter>Resource Files</Filter> <Filter>Resource Files</Filter>
</None> </None>
<None Include="msvc_make.bat">
<Filter>Source Files</Filter>
</None>
<None Include="qt.conf" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<QtUic Include="EditorWidget.ui"> <QtUic Include="EditorWidget.ui">

View File

@ -86,3 +86,12 @@ bool Line::judgeIntersection(QVector4D bound) {
|| judgeBoundIntersection(bound.x(), bound.y(), bound.w(), false) || judgeBoundIntersection(bound.x(), bound.y(), bound.w(), false)
|| judgeBoundIntersection(bound.z(), 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;
}
}

View File

@ -46,6 +46,8 @@ namespace Renderer
virtual void monotonization(std::vector <LinePtr>& res) = 0; virtual void monotonization(std::vector <LinePtr>& res) = 0;
virtual int judgeBoundIntersection(double xy, double l, double r, bool isY) = 0; virtual int judgeBoundIntersection(double xy, double l, double r, bool isY) = 0;
virtual bool judgeIntersection(QVector4D bound); virtual bool judgeIntersection(QVector4D bound);
virtual double minDistanceToLine(Point uv);
void upwardOffsetForY(bool isStart, double offset);
bool isLineContained(QVector4D bound); bool isLineContained(QVector4D bound);
Point operator[](int index) const; Point operator[](int index) const;
Point getPointByIndex(int index) const; Point getPointByIndex(int index) const;

View File

@ -0,0 +1,117 @@
#include "LineTree.h"
#include <set>
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 <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 LineTree::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 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<PointVector>& inLines, vector<std::shared_ptr<Line>>& outLines) {
bool isOffset = false;
for (PointVector& l : inLines) {
std::shared_ptr<Line> 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);
}
}
}

View File

@ -0,0 +1,51 @@
#pragma once
#include "CubicBezier.h"
#include "StraightLine.h"
#include "BvhTree.h"
#include <queue>
#include <set>
namespace Renderer {
struct LineTreeNode {
int eastGroup;
bool divided;
/*
0
1*/
QVector4D bound;
std::vector<int> lineSet;
LineTreeNode() {
eastGroup = 0;
divided = true;
bound = { 0, 0, 0, 0 };
lineSet.clear();
}
~LineTreeNode() {}
};
class LineTree {
typedef std::vector<Point> PointVector;
typedef std::vector<int> PointIndexVector;
private:
std::vector<LineTreeNode> restOfTreeNodes;
std::vector<std::shared_ptr<Line>> allLine;
int requiredLineMin, numPoint, numLine, lineWidth;
std::map<Point, int> pointMap;
std::vector<int> lineIndexs;
int getPointIndex(Point nowPoint);
void spliteToLineTree();
void simplifyLineVector();
bool handleShortCutNode(LineTreeNode& fa, LineTreeNode& nowTreeNode, double yValue, std::vector<LineTreeNode>& v);
bool isLineEqual(PointIndexVector& a, PointIndexVector& b) const;
static bool IsBorderValueResonable(double value, std::set <double>& valueSet);
static double findBorderValueNotOnLine(double value, std::set <double>& valueSet);
static void monotonization(std::vector<PointVector>& inL, std::vector<std::shared_ptr<Line>>& 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<PointVector>& lineSet);
std::vector<BvhTreeData> getPointLineAndBvhTree(std::vector<float>& pointSet, std::vector<GLuint>& lineSet);
};
}

View File

@ -76,7 +76,7 @@ void ShortCutTree::monotonization(vector<PointVector>& inLines, vector<std::shar
} }
} }
void ShortCutTree::generateShortCutsegmentement(ShortCutNode& nowTreeNode) { void ShortCutTree::generateShortCutSegment(ShortCutNode& nowTreeNode) {
Point p = {0, 0}; Point p = {0, 0};
set<pair<int, int> > pointSet; set<pair<int, int> > pointSet;
for (int & lineIndex : nowTreeNode.lineSet) { for (int & lineIndex : nowTreeNode.lineSet) {
@ -133,7 +133,7 @@ bool ShortCutTree::handleShortCutNode(ShortCutNode& fa, ShortCutNode& nowTreeNod
} }
} }
qDebug() << nowTreeNode.lineSet.size() ; qDebug() << nowTreeNode.lineSet.size() ;
if (nowTreeNode.lineSet.size() <= RequiredLineMin) { if (nowTreeNode.lineSet.size() <= requiredLineMin) {
if (nowTreeNode.lineSet.empty() && nowTreeNode.windingIncrement == 0) if (nowTreeNode.lineSet.empty() && nowTreeNode.windingIncrement == 0)
return false; return false;
restOfTreeNodes.push_back(nowTreeNode); restOfTreeNodes.push_back(nowTreeNode);
@ -160,7 +160,7 @@ void ShortCutTree::simplifyLineVector() {
} }
} }
for (auto& nowTreeNode : restOfTreeNodes) { for (auto& nowTreeNode : restOfTreeNodes) {
generateShortCutsegmentement(nowTreeNode); generateShortCutSegment(nowTreeNode);
} }
} }

View File

@ -9,10 +9,9 @@ namespace Renderer
struct ShortCutNode { struct ShortCutNode {
typedef std::vector<Point> vectorPoint;
int windingIncrement, eastGroup; int windingIncrement, eastGroup;
bool divided; bool divided;
/* type 代表进入广度优先搜索队列的节点种类: /*
0 0
1*/ 1*/
QVector4D bound; QVector4D bound;
@ -33,12 +32,12 @@ namespace Renderer
private: private:
std::vector<ShortCutNode> restOfTreeNodes; std::vector<ShortCutNode> restOfTreeNodes;
std::vector<std::shared_ptr<Line>> allLine; std::vector<std::shared_ptr<Line>> allLine;
int RequiredLineMin, numPoint, numLine; int requiredLineMin, numPoint, numLine;
std::map<Point, int> pointMap; std::map<Point, int> pointMap;
std::vector<int> lineIndexs; std::vector<int> lineIndexs;
int getPointIndex(Point nowPoint); int getPointIndex(Point nowPoint);
void generateShortCutsegmentement(ShortCutNode& nowTreeNode); void generateShortCutSegment(ShortCutNode& nowTreeNode);
bool handleShortCutNode(ShortCutNode& fa, ShortCutNode& nowTreeNode, double yValue, std::vector<ShortCutNode>& v, int& sumIncrement); bool handleShortCutNode(ShortCutNode& fa, ShortCutNode& nowTreeNode, double yValue, std::vector<ShortCutNode>& v, int& sumIncrement);
void spliteToShortCutTree(); void spliteToShortCutTree();
static void monotonization(std::vector<PointVector>& inL, std::vector<std::shared_ptr<Line>>& outL); static void monotonization(std::vector<PointVector>& inL, std::vector<std::shared_ptr<Line>>& outL);
@ -51,7 +50,7 @@ namespace Renderer
void init(); void init();
//lineMin最小线数目即划分终止条件 //lineMin最小线数目即划分终止条件
ShortCutTree(int lineMin = 3) ShortCutTree(int lineMin = 3)
:RequiredLineMin(lineMin), numPoint(0), numLine(0) {} :requiredLineMin(lineMin), numPoint(0), numLine(0) {}
// 传入一个vector<vector<Point> > 作为所有输入的线 // 传入一个vector<vector<Point> > 作为所有输入的线
void buildShortCutTree(std::vector<PointVector>& lineSet); void buildShortCutTree(std::vector<PointVector>& lineSet);
// 获得点集合和线集合 返回输入BvhTree的数据集合 // 获得点集合和线集合 返回输入BvhTree的数据集合

View File

@ -1,3 +1,4 @@
#pragma once
#include "Line.h" #include "Line.h"
namespace Renderer namespace Renderer
{ {