增加了QPainterPath的单调化

dev-VirtualTexture
yang.yongquan 2023-02-14 18:10:08 +08:00
parent ef88c4a39e
commit 315083cd52
8 changed files with 29 additions and 109 deletions

View File

@ -127,7 +127,6 @@
<ClCompile Include="src\Renderer\Camera.cpp" /> <ClCompile Include="src\Renderer\Camera.cpp" />
<ClCompile Include="src\Renderer\Painting\CubicBezier.cpp" /> <ClCompile Include="src\Renderer\Painting\CubicBezier.cpp" />
<ClCompile Include="src\Renderer\Painting\CubicBezierSignedDistance.cpp" /> <ClCompile Include="src\Renderer\Painting\CubicBezierSignedDistance.cpp" />
<ClCompile Include="src\Renderer\Painting\CubicMonotonization.cpp" />
<ClCompile Include="src\Renderer\Light.cpp" /> <ClCompile Include="src\Renderer\Light.cpp" />
<ClCompile Include="src\Renderer\Painting\Element.cpp" /> <ClCompile Include="src\Renderer\Painting\Element.cpp" />
<ClCompile Include="src\Renderer\Painting\ElementStyle.cpp" /> <ClCompile Include="src\Renderer\Painting\ElementStyle.cpp" />
@ -215,7 +214,6 @@
<ClInclude Include="src\Renderer\Painting\BvhTree.h" /> <ClInclude Include="src\Renderer\Painting\BvhTree.h" />
<ClInclude Include="src\Renderer\Camera.h" /> <ClInclude Include="src\Renderer\Camera.h" />
<ClInclude Include="src\Renderer\Painting\CubicBezier.h" /> <ClInclude Include="src\Renderer\Painting\CubicBezier.h" />
<ClInclude Include="src\Renderer\Painting\CubicMonotonization.h" />
<ClInclude Include="src\Renderer\Drawable.h" /> <ClInclude Include="src\Renderer\Drawable.h" />
<ClInclude Include="src\Renderer\Light.h" /> <ClInclude Include="src\Renderer\Light.h" />
<ClInclude Include="src\Renderer\Painting\Line.h" /> <ClInclude Include="src\Renderer\Painting\Line.h" />

View File

@ -129,9 +129,6 @@
<ClCompile Include="src\Renderer\Painting\CubicBezier.cpp"> <ClCompile Include="src\Renderer\Painting\CubicBezier.cpp">
<Filter>Source Files\Renderer\Painting</Filter> <Filter>Source Files\Renderer\Painting</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="src\Renderer\Painting\CubicMonotonization.cpp">
<Filter>Source Files\Renderer\Painting</Filter>
</ClCompile>
<ClCompile Include="src\Renderer\Painting\PaintingHelper.cpp"> <ClCompile Include="src\Renderer\Painting\PaintingHelper.cpp">
<Filter>Source Files\Renderer\Painting</Filter> <Filter>Source Files\Renderer\Painting</Filter>
</ClCompile> </ClCompile>
@ -360,9 +357,6 @@
<ClInclude Include="src\Renderer\Painting\CubicBezier.h"> <ClInclude Include="src\Renderer\Painting\CubicBezier.h">
<Filter>Header Files\Renderer\Painting</Filter> <Filter>Header Files\Renderer\Painting</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="src\Renderer\Painting\CubicMonotonization.h">
<Filter>Header Files\Renderer\Painting</Filter>
</ClInclude>
<ClInclude Include="src\Renderer\Painting\Line.h"> <ClInclude Include="src\Renderer\Painting\Line.h">
<Filter>Header Files\Renderer\Painting</Filter> <Filter>Header Files\Renderer\Painting</Filter>
</ClInclude> </ClInclude>

View File

@ -1,8 +1,11 @@
#include "PainterPathUtil.h" #include "PainterPathUtil.h"
#include <QDebug> #include <QDebug>
#include "../../Renderer/Painting/LineTree.h"
using Renderer::Point; using Renderer::Point;
using Renderer::Line;
using std::vector; using std::vector;
using std::shared_ptr;
vector<vector<Point> > PainterPathUtil::transformToLines(QPainterPath& painterPath) { vector<vector<Point> > PainterPathUtil::transformToLines(QPainterPath& painterPath) {
vector<Point> line; line.clear(); vector<Point> line; line.clear();
@ -39,3 +42,22 @@ vector<vector<Point> > PainterPathUtil::transformToLines(QPainterPath& painterP
line.clear(); line.clear();
return lines; return lines;
} }
QPainterPath PainterPathUtil::monotonization(QPainterPath& painterPath) {
QPainterPath resPath;
vector<vector<Point> > lines = transformToLines(painterPath);
vector<shared_ptr<Line>> linePtrVector;
Renderer::LineTree::monotonization(lines, linePtrVector);
for (auto linePtr : linePtrVector) {
vector<Point> line = linePtr->toPointVector();
if (line.size() == 2) {
resPath.moveTo(line[0]);
resPath.lineTo(line[1]);
}
if (line.size() == 4) {
resPath.moveTo(line[0]);
resPath.cubicTo(line[1], line[2], line[3]);
}
}
return resPath;
}

View File

@ -9,5 +9,6 @@ class PainterPathUtil
{ {
public: public:
static std::vector<std::vector<Point> > transformToLines(QPainterPath& painterPath); static std::vector<std::vector<Point> > transformToLines(QPainterPath& painterPath);
static QPainterPath monotonization(QPainterPath& painterPath);
}; };

View File

@ -1,77 +0,0 @@
#include "CubicMonotonization.h"
using namespace Renderer;
using std::vector;
using std::min;
using std::max;
using std::sort;
const double CubicMonotonization::eps = 1e-6;
CubicMonotonization::point CubicMonotonization::getPointByT(point a, point b, double t) const {
return { a.first * (1 - t) + b.first, a.second * (1 - t) + b.second };
}
void CubicMonotonization::findPointsOfDivison(vector<double> p, vector<double>& res) {
double a = -p[0] + 7 * p[1] - 9 * p[2] + 3 * p[3];
double b = 6 * p[0] - 12 * p[1] + 6 * p[2];
double c = -3 * p[0] + 3*p[1];
double deta = b * b - 4*a*c;
if (fabs(deta) < eps) return;
double t = 0;
if (fabs(a) <= eps) {
deta = sqrt(deta);
t = -b + deta;
if (0 < t && t < 1) {
res.push_back(t);
}
if (fabs(deta) <= eps) return ;
t = -b - deta;
if (0 < t && t < 1) {
res.push_back(t);
}
}
}
double CubicMonotonization::getBezierPoint(vector<double> &p, double t) const{
double pt = 1 - t;
return pt * pt * pt * p[0] + 3 * t * pt * pt * p[1] + 3 * t * t * pt * p[2] + t * t * t * p[3];
}
void CubicMonotonization::splitBezierCubic(Line& p, point mid, double t, vector <Line>& res) {
Line Lf; Lf.clear();
double pt = 1 - t;
Lf.push_back(p[0]);
point pointF = getPointByT(p[0], p[1], t);
point pointG = getPointByT(p[1], p[2], t);
point pointH = getPointByT(p[2], p[3], t);
Lf.push_back(pointF);
Lf.push_back(getPointByT(pointF, pointG, t));
Lf.push_back(mid);
res.push_back(Lf);
p[0] = mid;
p[1] = getPointByT(pointG, pointH, t);
p[2] = pointH;
}
void CubicMonotonization::getPointsOfDivision(Line p, vector <Line>& res) {
vector<double> vX, vY, re;
vX.clear();
vY.clear();
re.clear();
for (point now : p) {
vX.push_back(now.first);
vY.push_back(now.second);
}
findPointsOfDivison(vX, re);
findPointsOfDivison(vY, re);
sort(re.begin(), re.end());
double lt = 0, x = 0, y = 0;
for (double &t : re) {
if (fabs(t - lt) <= eps) continue;
x = getBezierPoint(vX, t);
y = getBezierPoint(vY, t);
splitBezierCubic(p, { x, y }, t, res);
lt = t;
}
}

View File

@ -1,23 +0,0 @@
#pragma once
#include <utility>
#include <vector>
#include <algorithm>
namespace Renderer
{
class CubicMonotonization
{
typedef std::pair<double, double> point;
typedef std::vector<point> Line;
private:
static const double eps;
point getPointByT(point a, point b, double t) const;
void findPointsOfDivison(std::vector<double> p, std::vector<double>& res);
double getBezierPoint(std::vector<double>& p, double t) const;
void splitBezierCubic(Line& p, point mid, double t, std::vector <Line>& res);
public:
// p 为端点、控制点、控制点、端点, res 为所有导数为0的点
void getPointsOfDivision(Line p, std::vector <Line>& res);
};
}

View File

@ -33,6 +33,11 @@ namespace Renderer
operator glm::dvec2() { operator glm::dvec2() {
return glm::dvec2(x, y); return glm::dvec2(x, y);
} }
operator QPointF() {
return QPointF(x, y);
}
void show() { void show() {
std::cout << '(' << x << ',' << y << ')' << ' '; std::cout << '(' << x << ',' << y << ')' << ' ';
} }

View File

@ -41,13 +41,13 @@ namespace Renderer {
bool isLineEqual(PointIndexVector& a, PointIndexVector& b) const; bool isLineEqual(PointIndexVector& a, PointIndexVector& b) const;
static bool IsBorderValueResonable(double value, std::set <double>& valueSet); static bool IsBorderValueResonable(double value, std::set <double>& valueSet);
static double findBorderValueNotOnLine(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: public:
void init(); void init();
void setLineWidth(double width); void setLineWidth(double width);
LineTree(int lineMin = 3) LineTree(int lineMin = 3)
: requiredLineMin(lineMin), numLine(0), numPoint(0) {} : requiredLineMin(lineMin), numLine(0), numPoint(0) {}
void buildLineTree(std::vector<PointVector>& lineSet, double width, int type = 0); void buildLineTree(std::vector<PointVector>& lineSet, double width, int type = 0);
static void monotonization(std::vector<PointVector>& inL, std::vector<std::shared_ptr<Line>>& outL);
std::vector<BvhTreeData> getPointLineAndBvhTree(std::vector<float>& pointSet, std::vector<GLuint>& lineSet); std::vector<BvhTreeData> getPointLineAndBvhTree(std::vector<float>& pointSet, std::vector<GLuint>& lineSet);
}; };
} }