增加了分割的贝塞尔曲线的控制点
parent
081e9a7ffb
commit
79883302ac
|
@ -87,6 +87,7 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="BvhTree.cpp" />
|
<ClCompile Include="BvhTree.cpp" />
|
||||||
<ClCompile Include="Camera.cpp" />
|
<ClCompile Include="Camera.cpp" />
|
||||||
|
<ClCompile Include="CubicMonotonization.cpp" />
|
||||||
<ClCompile Include="Light.cpp" />
|
<ClCompile Include="Light.cpp" />
|
||||||
<ClCompile Include="Mesh.cpp" />
|
<ClCompile Include="Mesh.cpp" />
|
||||||
<ClCompile Include="Model.cpp" />
|
<ClCompile Include="Model.cpp" />
|
||||||
|
@ -123,6 +124,7 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="BvhTree.h" />
|
<ClInclude Include="BvhTree.h" />
|
||||||
<ClInclude Include="Camera.h" />
|
<ClInclude Include="Camera.h" />
|
||||||
|
<ClInclude Include="CubicMonotonization.h" />
|
||||||
<ClInclude Include="Drawable.h" />
|
<ClInclude Include="Drawable.h" />
|
||||||
<ClInclude Include="Light.h" />
|
<ClInclude Include="Light.h" />
|
||||||
<ClInclude Include="Mesh.h" />
|
<ClInclude Include="Mesh.h" />
|
||||||
|
|
|
@ -67,6 +67,9 @@
|
||||||
<ClCompile Include="Light.cpp">
|
<ClCompile Include="Light.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="CubicMonotonization.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<QtMoc Include="RendererWidget.h">
|
<QtMoc Include="RendererWidget.h">
|
||||||
|
@ -148,5 +151,8 @@
|
||||||
<ClInclude Include="Light.h">
|
<ClInclude Include="Light.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="CubicMonotonization.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
|
@ -0,0 +1,73 @@
|
||||||
|
#include "CubicMonotonization.h"
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
#include <algorithm>
|
||||||
|
#pragma once
|
||||||
|
using std::pair;
|
||||||
|
using std::vector;
|
||||||
|
using std::min;
|
||||||
|
using std::max;
|
||||||
|
using std::sort;
|
||||||
|
class CubicMonotonization
|
||||||
|
{
|
||||||
|
typedef pair<double, double> point;
|
||||||
|
typedef vector<point> Line;
|
||||||
|
private:
|
||||||
|
static const double eps;
|
||||||
|
point getPointByT(point a, point b, double t) const;
|
||||||
|
void findPointsOfDivison(vector<double> p, vector<double> &res);
|
||||||
|
double getBezierPoint(vector<double> &p, double t) const;
|
||||||
|
void splitBezierCubic(Line& p, point mid, double t, vector <Line> &res);
|
||||||
|
public:
|
||||||
|
// p 为端点、控制点、控制点、端点, res 为所有导数为0的点
|
||||||
|
void getPointsOfDivision(Line p, vector <Line> &res);
|
||||||
|
};
|
||||||
|
|
Loading…
Reference in New Issue