增加了对于与X轴平行直线的修正
parent
cbc4c2ebf5
commit
66d652fa30
|
@ -113,6 +113,7 @@
|
|||
<ClCompile Include="src\Renderer\Painting\Line.cpp" />
|
||||
<ClCompile Include="src\Renderer\Mesh.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\PaintingHelper.cpp" />
|
||||
<ClCompile Include="src\Renderer\PaintingMesh.cpp" />
|
||||
|
@ -132,6 +133,8 @@
|
|||
<ItemGroup>
|
||||
<None Include="darkstyle.qss" />
|
||||
<None Include="lightstyle.qss" />
|
||||
<None Include="msvc_make.bat" />
|
||||
<None Include="qt.conf" />
|
||||
<None Include="Shaders\depth_init.comp" />
|
||||
<None Include="Shaders\depth_mipmap.comp" />
|
||||
<None Include="Shaders\final.frag" />
|
||||
|
@ -153,6 +156,7 @@
|
|||
<QtMoc Include="src\MainWindow.h" />
|
||||
<ClInclude Include="src\Editor\GraphicElement.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\SvgParser.h" />
|
||||
<QtMoc Include="src\TitleWidget.h" />
|
||||
|
|
|
@ -129,6 +129,9 @@
|
|||
<ClCompile Include="src\Editor\GraphicElement.cpp">
|
||||
<Filter>Source Files\Editor</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\Renderer\Painting\LineTree.cpp">
|
||||
<Filter>Source Files\Renderer\Painting</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<QtMoc Include="src\Renderer\RendererGLWidget.h">
|
||||
|
@ -211,6 +214,10 @@
|
|||
<None Include="lightstyle.qss">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="msvc_make.bat">
|
||||
<Filter>Source Files</Filter>
|
||||
</None>
|
||||
<None Include="qt.conf" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<QtUic Include="EditorWidget.ui">
|
||||
|
@ -272,6 +279,9 @@
|
|||
<ClInclude Include="src\Editor\GraphicElement.h">
|
||||
<Filter>Header Files\Editor</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\Renderer\Painting\LineTree.h">
|
||||
<Filter>Header Files\Renderer\Painting</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<QtRcc Include="MainWindow.qrc">
|
||||
|
|
|
@ -86,3 +86,12 @@ bool Line::judgeIntersection(QVector4D bound) {
|
|||
|| 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;
|
||||
}
|
||||
}
|
|
@ -46,6 +46,8 @@ namespace Renderer
|
|||
virtual void monotonization(std::vector <LinePtr>& 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;
|
||||
|
|
|
@ -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};
|
||||
set<pair<int, int> > 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,10 +9,9 @@ namespace Renderer
|
|||
|
||||
|
||||
struct ShortCutNode {
|
||||
typedef std::vector<Point> vectorPoint;
|
||||
int windingIncrement, eastGroup;
|
||||
bool divided;
|
||||
/* type 代表进入广度优先搜索队列的节点种类:
|
||||
/*
|
||||
0:不需要拆开的节点
|
||||
1:需要拆分*/
|
||||
QVector4D bound;
|
||||
|
@ -33,12 +32,12 @@ namespace Renderer
|
|||
private:
|
||||
std::vector<ShortCutNode> restOfTreeNodes;
|
||||
std::vector<std::shared_ptr<Line>> allLine;
|
||||
int RequiredLineMin, numPoint, numLine;
|
||||
int requiredLineMin, numPoint, numLine;
|
||||
std::map<Point, int> pointMap;
|
||||
std::vector<int> lineIndexs;
|
||||
|
||||
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);
|
||||
void spliteToShortCutTree();
|
||||
static void monotonization(std::vector<PointVector>& inL, std::vector<std::shared_ptr<Line>>& 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<vector<Point> > 作为所有输入的线
|
||||
void buildShortCutTree(std::vector<PointVector>& lineSet);
|
||||
// 获得点集合和线集合 返回输入BvhTree的数据集合
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#pragma once
|
||||
#include "Line.h"
|
||||
namespace Renderer
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue