修改了精度问题,待解决单调化

dev-VirtualTexture
yang.yongquan 2022-10-07 10:20:16 +08:00
parent 4f9611c385
commit f4900b8df2
8 changed files with 41 additions and 41 deletions

View File

@ -1,14 +1,14 @@
#include "CubicBezier.h"
float CubicBezier::getLineValueByT(float t, bool isY) {
vector<float> p;
double CubicBezier::getLineValueByT(double t, bool isY) {
vector<double> p;
if (isY) p = vY;
else p = vX;
float 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];
}
Point CubicBezier::getPointByT(Point a, Point b, float t) {
Point CubicBezier::getPointByT(Point a, Point b, double t) {
return { a.x * (1 - t) + b.x * t, a.y * (1 - t) + b.y * t };
}
@ -19,11 +19,11 @@ Point CubicBezier::calculateControlPoint(Point a, Point b) {
};
}
void CubicBezier::findPointsOfDivison(vector<float> &p, vector<float>& res) {
float a = -3 * p[0] + 9 * p[1] - 9 * p[2] + 3 * p[3];
float b = 6 * p[0] - 12 * p[1] + 6 * p[2];
float c = -3 * p[0] + 3 * p[1];
float deta = b * b - 4 * a * c, t = 0;
void CubicBezier::findPointsOfDivison(vector<double> &p, vector<double>& res) {
double a = -3 * p[0] + 9 * 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, t = 0;
if (fabs(a) > eps) {
if (deta < eps) return;
deta = sqrt(deta);
@ -58,7 +58,7 @@ void CubicBezier::transformToCubic() {
siz = 4;
}
void CubicBezier::splitBezierCubic(float t, vector<LinePtr>& res) {
void CubicBezier::splitBezierCubic(double t, vector<LinePtr>& res) {
LinePtr Lf(new CubicBezier());
float pt = 1 - t;
Point pointE = { getLineValueByT(t, false), getLineValueByT(t, true) };
@ -77,25 +77,25 @@ void CubicBezier::splitBezierCubic(float t, vector<LinePtr>& res) {
void CubicBezier::monotonization(vector <LinePtr>& res) {
transformToCubic();
vector<float> re;
vector<double> re;
re.clear();
findPointsOfDivison(vX, re);
findPointsOfDivison(vY, re);
sort(re.begin(), re.end());
float lt = -1, x = 0, y = 0;
for (float &t : re) {
double lt = -1, x = 0, y = 0;
for (double&t : re) {
if (fabs(t - lt) <= eps) continue;
splitBezierCubic(t, res);
lt = t;
}
}
float CubicBezier::findTByValue(float value, bool isY) {
float l = 0, r = 1, be = 0;
double CubicBezier::findTByValue(double value, bool isY) {
double l = 0, r = 1, be = 0;
if (isY) be = vY[0];
else be = vX[0];
while (fabs(r-l) > eps) {
float mid = (l + r) / 2, midValue = getLineValueByT(mid, isY);
double mid = (l + r) / 2, midValue = getLineValueByT(mid, isY);
if (fabs(midValue - be) > fabs(value - be)) {
r = mid;
}
@ -106,15 +106,15 @@ float CubicBezier::findTByValue(float value, bool isY) {
return l;
}
int CubicBezier::judgeBoundIntersection(float xy, float l, float r, bool isY) {
float be = *vX.begin(), en = *vX.rbegin();
int CubicBezier::judgeBoundIntersection(double xy, double l, double r, bool isY) {
double be = *vX.begin(), en = *vX.rbegin();
if (isY) {
be = *vY.begin();
en = *vY.rbegin();
}
if ((be - xy) * (en - xy) > eps) return 0;
float t = findTByValue(xy, isY);
float value = getLineValueByT(t, !isY);
double t = findTByValue(xy, isY);
double value = getLineValueByT(t, !isY);
if (l <= value && value <= r && fabs(t) > eps && fabs(1 - t) > eps) {
return 1 + direction(isY);
}

View File

@ -6,15 +6,15 @@ class CubicBezier : public Line
{
using Line::Line;
private:
static Point getPointByT(Point a, Point b, float t);
static Point getPointByT(Point a, Point b, double t);
static Point calculateControlPoint(Point a, Point b);
static void findPointsOfDivison(vector<float> &p, vector<float>& res);
void splitBezierCubic(float t, vector<LinePtr>& res);
static void findPointsOfDivison(vector<double> &p, vector<double>& res);
void splitBezierCubic(double t, vector<LinePtr>& res);
public:
virtual float findTByValue(float value, bool isY);
virtual double findTByValue(double value, bool isY);
virtual void monotonization(vector <LinePtr>& res);
virtual float getLineValueByT(float t, bool isY);
virtual int judgeBoundIntersection(float xy, float l, float r, bool isY);
virtual double getLineValueByT(double t, bool isY);
virtual int judgeBoundIntersection(double xy, double l, double r, bool isY);
void transformToCubic();
};

View File

@ -45,8 +45,8 @@ void Line::push_back(Point now) {
}
bool Line::isLineContained(QVector4D bound) {
float xMi = min(*vX.begin(), *vX.rbegin()), xMx = max(*vX.begin(), *vX.rbegin());
float yMi = min(*vY.begin(), *vY.rbegin()), yMx = max(*vY.begin(), *vY.rbegin());
double xMi = min(*vX.begin(), *vX.rbegin()), xMx = max(*vX.begin(), *vX.rbegin());
double yMi = min(*vY.begin(), *vY.rbegin()), yMx = max(*vY.begin(), *vY.rbegin());
if (bound.x() <= xMi && xMx <= bound.z() && bound.y() <= yMi && yMx <= bound.w())
return true;
else return false;

View File

@ -16,12 +16,12 @@ using std::shared_ptr;
using std::make_shared;
using std::swap;
const float eps = 1e-6;
const double eps = 1e-5;
struct Point {
float x, y;
double x, y;
Point operator - (const Point a) { return { x - a.x, y - a.y }; }
float operator * (const Point a) { return x * a.y - y * a.x; }
double operator * (const Point a) { return x * a.y - y * a.x; }
bool operator== (const Point& a) const {
return fabs(x - a.x) <= eps && fabs(y - a.y) <= eps;
}
@ -36,7 +36,7 @@ struct Point {
class Line
{
protected:
vector<float> vX, vY;
vector<double> vX, vY;
int siz;
public:
typedef shared_ptr<Line> LinePtr;
@ -47,9 +47,9 @@ public:
Point getBegin();
Point getEnd();
int direction(bool isY);
virtual float getLineValueByT(float t, bool isY) = 0;
virtual double getLineValueByT(double t, bool isY) = 0;
virtual void monotonization(vector <LinePtr>& res) = 0;
virtual int judgeBoundIntersection(float xy, float l, float r, bool isY) = 0;
virtual int judgeBoundIntersection(double xy, double l, double r, bool isY) = 0;
virtual bool judgeIntersection(QVector4D bound);
bool isLineContained(QVector4D bound);
Point operator[](int index) const;

View File

@ -80,7 +80,7 @@ void ShortCutTree::generateShortCutsegmentement(ShortCutNode& nowTreeNode) {
}
}
bool ShortCutTree::handleShortCutNode(ShortCutNode& fa, ShortCutNode& nowTreeNode, float yValue, vector<ShortCutNode>& v, int& sumIncrement) {
bool ShortCutTree::handleShortCutNode(ShortCutNode& fa, ShortCutNode& nowTreeNode, double yValue, vector<ShortCutNode>& v, int& sumIncrement) {
nowTreeNode.windingIncrement = sumIncrement;
for (int & lineIndex : fa.lineSet) {
int type = allLine[lineIndex]->judgeBoundIntersection(yValue, nowTreeNode.bound.x(), nowTreeNode.bound.z(), true);

View File

@ -38,7 +38,7 @@ private:
int getPointIndex(Point nowPoint);
void generateShortCutsegmentement(ShortCutNode& nowTreeNode);
bool handleShortCutNode(ShortCutNode& fa, ShortCutNode& nowTreeNode, float yValue, vector<ShortCutNode>& v, int& sumIncrement);
bool handleShortCutNode(ShortCutNode& fa, ShortCutNode& nowTreeNode, double yValue, vector<ShortCutNode>& v, int& sumIncrement);
void spliteToShortCutTree();
static void monotonization(vector<PointVector>& inL, vector<LinePtr> &outL);
bool isLineEqual(PointIndexVector& a, PointIndexVector& b) const;

View File

@ -1,6 +1,6 @@
#include "StraightLine.h"
float StraightLine::getLineValueByT(float t, bool isY) {
double StraightLine::getLineValueByT(double t, bool isY) {
float pBe, pEn;
if (isY) {
pBe = *vY.begin();
@ -13,7 +13,7 @@ float StraightLine::getLineValueByT(float t, bool isY) {
return t * (pEn - pBe) + pBe;
}
float StraightLine::findTByValue(float value, bool isY) {
double StraightLine::findTByValue(double value, bool isY) {
Point be = getPointByIndex(0), en = getPointByIndex(1);
if (!isY) {
if(fabs(be.x - en.x) <= eps) return 0;
@ -25,7 +25,7 @@ float StraightLine::findTByValue(float value, bool isY) {
}
}
int StraightLine::judgeBoundIntersection(float xy, float l, float r, bool isY) {
int StraightLine::judgeBoundIntersection(double xy, double l, double r, bool isY) {
Point be = getBegin(), en = getEnd();
if (isY) {
swap(be.x, be.y);

View File

@ -3,8 +3,8 @@
class StraightLine : public Line
{
using Line::Line;
virtual float getLineValueByT(float t, bool isY);
virtual double getLineValueByT(double t, bool isY);
virtual void monotonization(vector <LinePtr>& res) {};
virtual float findTByValue(float value, bool isY);
virtual int judgeBoundIntersection(float xy, float l, float r, bool isY);
virtual double findTByValue(double value, bool isY);
virtual int judgeBoundIntersection(double xy, double l, double r, bool isY);
};