修改了精度问题,待解决单调化
parent
4f9611c385
commit
f4900b8df2
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
};
|
Loading…
Reference in New Issue