增加了对于与X轴平行直线的修正
parent
cbc4c2ebf5
commit
66d652fa30
|
@ -113,6 +113,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" />
|
||||||
|
@ -132,6 +133,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" />
|
||||||
|
@ -153,6 +156,7 @@
|
||||||
<QtMoc Include="src\MainWindow.h" />
|
<QtMoc Include="src\MainWindow.h" />
|
||||||
<ClInclude Include="src\Editor\GraphicElement.h" />
|
<ClInclude Include="src\Editor\GraphicElement.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" />
|
||||||
|
|
|
@ -129,6 +129,9 @@
|
||||||
<ClCompile Include="src\Editor\GraphicElement.cpp">
|
<ClCompile Include="src\Editor\GraphicElement.cpp">
|
||||||
<Filter>Source Files\Editor</Filter>
|
<Filter>Source Files\Editor</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Renderer\Painting\LineTree.cpp">
|
||||||
|
<Filter>Source Files\Renderer\Painting</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<QtMoc Include="src\Renderer\RendererGLWidget.h">
|
<QtMoc Include="src\Renderer\RendererGLWidget.h">
|
||||||
|
@ -211,6 +214,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">
|
||||||
|
@ -272,6 +279,9 @@
|
||||||
<ClInclude Include="src\Editor\GraphicElement.h">
|
<ClInclude Include="src\Editor\GraphicElement.h">
|
||||||
<Filter>Header Files\Editor</Filter>
|
<Filter>Header Files\Editor</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Renderer\Painting\LineTree.h">
|
||||||
|
<Filter>Header Files\Renderer\Painting</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<QtRcc Include="MainWindow.qrc">
|
<QtRcc Include="MainWindow.qrc">
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
};
|
||||||
|
}
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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的数据集合
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#pragma once
|
||||||
#include "Line.h"
|
#include "Line.h"
|
||||||
namespace Renderer
|
namespace Renderer
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue