修改了精度问题,待解决单调化
parent
4f9611c385
commit
f4900b8df2
|
@ -1,14 +1,14 @@
|
||||||
#include "CubicBezier.h"
|
#include "CubicBezier.h"
|
||||||
|
|
||||||
float CubicBezier::getLineValueByT(float t, bool isY) {
|
double CubicBezier::getLineValueByT(double t, bool isY) {
|
||||||
vector<float> p;
|
vector<double> p;
|
||||||
if (isY) p = vY;
|
if (isY) p = vY;
|
||||||
else p = vX;
|
else p = vX;
|
||||||
float pt = 1 - t;
|
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];
|
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 };
|
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) {
|
void CubicBezier::findPointsOfDivison(vector<double> &p, vector<double>& res) {
|
||||||
float a = -3 * p[0] + 9 * p[1] - 9 * p[2] + 3 * p[3];
|
double a = -3 * p[0] + 9 * p[1] - 9 * p[2] + 3 * p[3];
|
||||||
float b = 6 * p[0] - 12 * p[1] + 6 * p[2];
|
double b = 6 * p[0] - 12 * p[1] + 6 * p[2];
|
||||||
float c = -3 * p[0] + 3 * p[1];
|
double c = -3 * p[0] + 3 * p[1];
|
||||||
float deta = b * b - 4 * a * c, t = 0;
|
double deta = b * b - 4 * a * c, t = 0;
|
||||||
if (fabs(a) > eps) {
|
if (fabs(a) > eps) {
|
||||||
if (deta < eps) return;
|
if (deta < eps) return;
|
||||||
deta = sqrt(deta);
|
deta = sqrt(deta);
|
||||||
|
@ -58,7 +58,7 @@ void CubicBezier::transformToCubic() {
|
||||||
siz = 4;
|
siz = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CubicBezier::splitBezierCubic(float t, vector<LinePtr>& res) {
|
void CubicBezier::splitBezierCubic(double t, vector<LinePtr>& res) {
|
||||||
LinePtr Lf(new CubicBezier());
|
LinePtr Lf(new CubicBezier());
|
||||||
float pt = 1 - t;
|
float pt = 1 - t;
|
||||||
Point pointE = { getLineValueByT(t, false), getLineValueByT(t, true) };
|
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) {
|
void CubicBezier::monotonization(vector <LinePtr>& res) {
|
||||||
transformToCubic();
|
transformToCubic();
|
||||||
vector<float> re;
|
vector<double> re;
|
||||||
re.clear();
|
re.clear();
|
||||||
findPointsOfDivison(vX, re);
|
findPointsOfDivison(vX, re);
|
||||||
findPointsOfDivison(vY, re);
|
findPointsOfDivison(vY, re);
|
||||||
sort(re.begin(), re.end());
|
sort(re.begin(), re.end());
|
||||||
float lt = -1, x = 0, y = 0;
|
double lt = -1, x = 0, y = 0;
|
||||||
for (float &t : re) {
|
for (double&t : re) {
|
||||||
if (fabs(t - lt) <= eps) continue;
|
if (fabs(t - lt) <= eps) continue;
|
||||||
splitBezierCubic(t, res);
|
splitBezierCubic(t, res);
|
||||||
lt = t;
|
lt = t;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float CubicBezier::findTByValue(float value, bool isY) {
|
double CubicBezier::findTByValue(double value, bool isY) {
|
||||||
float l = 0, r = 1, be = 0;
|
double l = 0, r = 1, be = 0;
|
||||||
if (isY) be = vY[0];
|
if (isY) be = vY[0];
|
||||||
else be = vX[0];
|
else be = vX[0];
|
||||||
while (fabs(r-l) > eps) {
|
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)) {
|
if (fabs(midValue - be) > fabs(value - be)) {
|
||||||
r = mid;
|
r = mid;
|
||||||
}
|
}
|
||||||
|
@ -106,15 +106,15 @@ float CubicBezier::findTByValue(float value, bool isY) {
|
||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CubicBezier::judgeBoundIntersection(float xy, float l, float r, bool isY) {
|
int CubicBezier::judgeBoundIntersection(double xy, double l, double r, bool isY) {
|
||||||
float be = *vX.begin(), en = *vX.rbegin();
|
double be = *vX.begin(), en = *vX.rbegin();
|
||||||
if (isY) {
|
if (isY) {
|
||||||
be = *vY.begin();
|
be = *vY.begin();
|
||||||
en = *vY.rbegin();
|
en = *vY.rbegin();
|
||||||
}
|
}
|
||||||
if ((be - xy) * (en - xy) > eps) return 0;
|
if ((be - xy) * (en - xy) > eps) return 0;
|
||||||
float t = findTByValue(xy, isY);
|
double t = findTByValue(xy, isY);
|
||||||
float value = getLineValueByT(t, !isY);
|
double value = getLineValueByT(t, !isY);
|
||||||
if (l <= value && value <= r && fabs(t) > eps && fabs(1 - t) > eps) {
|
if (l <= value && value <= r && fabs(t) > eps && fabs(1 - t) > eps) {
|
||||||
return 1 + direction(isY);
|
return 1 + direction(isY);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,15 +6,15 @@ class CubicBezier : public Line
|
||||||
{
|
{
|
||||||
using Line::Line;
|
using Line::Line;
|
||||||
private:
|
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 Point calculateControlPoint(Point a, Point b);
|
||||||
static void findPointsOfDivison(vector<float> &p, vector<float>& res);
|
static void findPointsOfDivison(vector<double> &p, vector<double>& res);
|
||||||
void splitBezierCubic(float t, vector<LinePtr>& res);
|
void splitBezierCubic(double t, vector<LinePtr>& res);
|
||||||
public:
|
public:
|
||||||
virtual float findTByValue(float value, bool isY);
|
virtual double findTByValue(double value, bool isY);
|
||||||
virtual void monotonization(vector <LinePtr>& res);
|
virtual void monotonization(vector <LinePtr>& res);
|
||||||
virtual float getLineValueByT(float t, bool isY);
|
virtual double getLineValueByT(double t, bool isY);
|
||||||
virtual int judgeBoundIntersection(float xy, float l, float r, bool isY);
|
virtual int judgeBoundIntersection(double xy, double l, double r, bool isY);
|
||||||
void transformToCubic();
|
void transformToCubic();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -45,8 +45,8 @@ void Line::push_back(Point now) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Line::isLineContained(QVector4D bound) {
|
bool Line::isLineContained(QVector4D bound) {
|
||||||
float xMi = min(*vX.begin(), *vX.rbegin()), xMx = max(*vX.begin(), *vX.rbegin());
|
double 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 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())
|
if (bound.x() <= xMi && xMx <= bound.z() && bound.y() <= yMi && yMx <= bound.w())
|
||||||
return true;
|
return true;
|
||||||
else return false;
|
else return false;
|
||||||
|
|
|
@ -16,12 +16,12 @@ using std::shared_ptr;
|
||||||
using std::make_shared;
|
using std::make_shared;
|
||||||
using std::swap;
|
using std::swap;
|
||||||
|
|
||||||
const float eps = 1e-6;
|
const double eps = 1e-5;
|
||||||
|
|
||||||
struct Point {
|
struct Point {
|
||||||
float x, y;
|
double x, y;
|
||||||
Point operator - (const Point a) { return { x - a.x, y - a.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 {
|
bool operator== (const Point& a) const {
|
||||||
return fabs(x - a.x) <= eps && fabs(y - a.y) <= eps;
|
return fabs(x - a.x) <= eps && fabs(y - a.y) <= eps;
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ struct Point {
|
||||||
class Line
|
class Line
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
vector<float> vX, vY;
|
vector<double> vX, vY;
|
||||||
int siz;
|
int siz;
|
||||||
public:
|
public:
|
||||||
typedef shared_ptr<Line> LinePtr;
|
typedef shared_ptr<Line> LinePtr;
|
||||||
|
@ -47,9 +47,9 @@ public:
|
||||||
Point getBegin();
|
Point getBegin();
|
||||||
Point getEnd();
|
Point getEnd();
|
||||||
int direction(bool isY);
|
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 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);
|
virtual bool judgeIntersection(QVector4D bound);
|
||||||
bool isLineContained(QVector4D bound);
|
bool isLineContained(QVector4D bound);
|
||||||
Point operator[](int index) const;
|
Point operator[](int index) const;
|
||||||
|
|
|
@ -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;
|
nowTreeNode.windingIncrement = sumIncrement;
|
||||||
for (int & lineIndex : fa.lineSet) {
|
for (int & lineIndex : fa.lineSet) {
|
||||||
int type = allLine[lineIndex]->judgeBoundIntersection(yValue, nowTreeNode.bound.x(), nowTreeNode.bound.z(), true);
|
int type = allLine[lineIndex]->judgeBoundIntersection(yValue, nowTreeNode.bound.x(), nowTreeNode.bound.z(), true);
|
||||||
|
|
|
@ -38,7 +38,7 @@ private:
|
||||||
|
|
||||||
int getPointIndex(Point nowPoint);
|
int getPointIndex(Point nowPoint);
|
||||||
void generateShortCutsegmentement(ShortCutNode& nowTreeNode);
|
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();
|
void spliteToShortCutTree();
|
||||||
static void monotonization(vector<PointVector>& inL, vector<LinePtr> &outL);
|
static void monotonization(vector<PointVector>& inL, vector<LinePtr> &outL);
|
||||||
bool isLineEqual(PointIndexVector& a, PointIndexVector& b) const;
|
bool isLineEqual(PointIndexVector& a, PointIndexVector& b) const;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#include "StraightLine.h"
|
#include "StraightLine.h"
|
||||||
|
|
||||||
float StraightLine::getLineValueByT(float t, bool isY) {
|
double StraightLine::getLineValueByT(double t, bool isY) {
|
||||||
float pBe, pEn;
|
float pBe, pEn;
|
||||||
if (isY) {
|
if (isY) {
|
||||||
pBe = *vY.begin();
|
pBe = *vY.begin();
|
||||||
|
@ -13,7 +13,7 @@ float StraightLine::getLineValueByT(float t, bool isY) {
|
||||||
return t * (pEn - pBe) + pBe;
|
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);
|
Point be = getPointByIndex(0), en = getPointByIndex(1);
|
||||||
if (!isY) {
|
if (!isY) {
|
||||||
if(fabs(be.x - en.x) <= eps) return 0;
|
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();
|
Point be = getBegin(), en = getEnd();
|
||||||
if (isY) {
|
if (isY) {
|
||||||
swap(be.x, be.y);
|
swap(be.x, be.y);
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
class StraightLine : public Line
|
class StraightLine : public Line
|
||||||
{
|
{
|
||||||
using Line::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 void monotonization(vector <LinePtr>& res) {};
|
||||||
virtual float findTByValue(float value, bool isY);
|
virtual double findTByValue(double value, bool isY);
|
||||||
virtual int judgeBoundIntersection(float xy, float l, float r, bool isY);
|
virtual int judgeBoundIntersection(double xy, double l, double r, bool isY);
|
||||||
};
|
};
|
Loading…
Reference in New Issue