修复了一个线宽比例计算的bug

main
yang.yongquan 2023-03-29 18:54:56 +08:00
parent f9e316c547
commit 4360fad504
7 changed files with 54 additions and 46 deletions

View File

@ -83,6 +83,10 @@ void CubicBezier::splitBezierCubic(double t, vector<LinePtr>& res) {
setRate({ ratePoint, rate.second }); setRate({ ratePoint, rate.second });
} }
double CubicBezier::getLength() {
return getIntegralByT(1);
}
void CubicBezier::monotonization(vector <LinePtr>& res) { void CubicBezier::monotonization(vector <LinePtr>& res) {
transformToCubic(); transformToCubic();
vector<double> breakPointsT; vector<double> breakPointsT;

View File

@ -15,6 +15,7 @@ namespace Renderer
public: public:
virtual double findTByValue(double value, bool isY); virtual double findTByValue(double value, bool isY);
virtual void monotonization(std::vector <LinePtr>& res); virtual void monotonization(std::vector <LinePtr>& res);
virtual double getLength();
virtual double getLineValueByT(double t, bool isY); virtual double getLineValueByT(double t, bool isY);
virtual int judgeOneSideIntersection(double xy, double l, double r, bool isY); virtual int judgeOneSideIntersection(double xy, double l, double r, bool isY);
virtual double getMinDistanceFromPoint(Point p); virtual double getMinDistanceFromPoint(Point p);

View File

@ -69,6 +69,7 @@ namespace Renderer
virtual int judgeOneSideIntersection(double xy, double l, double r, bool isY) = 0; virtual int judgeOneSideIntersection(double xy, double l, double r, bool isY) = 0;
virtual double getMinDistanceFromPoint(Point p) = 0; virtual double getMinDistanceFromPoint(Point p) = 0;
bool judgeOneSideIntersectionWithWidth(double xy, double l, double r, bool isY, double width, int type); bool judgeOneSideIntersectionWithWidth(double xy, double l, double r, bool isY, double width, int type);
virtual double getLength() = 0;
virtual double findTByValue(double value, bool isY) = 0; virtual double findTByValue(double value, bool isY) = 0;
double getIntegralByT(double t); double getIntegralByT(double t);
bool judgeIntersectionWithWidth(QVector4D bound, double width, int type); bool judgeIntersectionWithWidth(QVector4D bound, double width, int type);

View File

@ -72,55 +72,32 @@ bool LineTree::isLineEqual(PointIndexVector& a, PointIndexVector& b) const {
void LineTree::monotonization(vector<PointVector>& inLines, vector<std::shared_ptr<Line>>& outLines) { void LineTree::monotonization(vector<PointVector>& inLines, vector<std::shared_ptr<Line>>& outLines) {
bool isOffset = false; bool isOffset = false;
vector<std::shared_ptr<Line> > tmpLines; for (PointVector& l : inLines) {
tmpLines.clear(); std::shared_ptr<Line> nowLine;
for (int i = 0; i < inLines.size(); i++) { switch (l.size()) {
int endIndex = i; case 2: {
double totalLength = 0; nowLine = make_shared<StraightLine>(l);
while (endIndex < inLines.size() && *inLines[endIndex].rbegin() == *inLines[endIndex + 1].begin()) { break;
endIndex++;
} }
// 计算总长度 case 4: nowLine = make_shared<CubicBezier>(l); break;
for (int j = i; j <= endIndex; j++) { default: break;
PointVector& l = inLines[j];
std::shared_ptr<Line> nowLine;
switch (l.size()) {
case 2: {
nowLine = make_shared<StraightLine>(l);
break;
}
case 4: nowLine = make_shared<CubicBezier>(l); break;
default: break;
}
totalLength += nowLine->getIntegralByT(1);
tmpLines.push_back(nowLine);
} }
//单调化并求比例 // 防止在同一直线与 X 轴平行上
double prefixLength = 0; if (isOffset) {
for (auto nowLine : tmpLines) { nowLine->upwardOffsetForY(true, 1e-5);
// 防止在同一直线与 X 轴平行上
double nowLineLength = nowLine->getIntegralByT(1);
nowLine->setRate({ prefixLength / totalLength, (prefixLength + nowLineLength) / totalLength });
prefixLength += nowLineLength;
if (isOffset) {
nowLine->upwardOffsetForY(true, 1e-5);
}
isOffset = false;
if (nowLine->direction(true) == 0) {
nowLine->upwardOffsetForY(false, 1e-5);
isOffset = true;
}
nowLine->monotonization(outLines);
outLines.push_back(nowLine);
} }
tmpLines.clear(); isOffset = false;
i = endIndex; if (nowLine->direction(true) == 0) {
nowLine->upwardOffsetForY(false, 1e-5);
isOffset = true;
}
nowLine->monotonization(outLines);
outLines.push_back(nowLine);
} }
// 防止在首尾直线在与 X 轴平行上 // 防止在首尾直线在与 X 轴平行上
int siz = outLines.size(); int siz = outLines.size();
if (!(outLines[0]->getBegin() == outLines[siz - 1]->getEnd())) if (!(outLines[0]->getBegin() == outLines[siz - 1]->getEnd()))
return; return;
if (isOffset) { if (isOffset) {
outLines[0]->upwardOffsetForY(true, 1e-5); outLines[0]->upwardOffsetForY(true, 1e-5);
@ -131,13 +108,31 @@ void LineTree::monotonization(vector<PointVector>& inLines, vector<std::shared_p
} }
} }
void LineTree::countLinesRate(std::vector<std::shared_ptr<Line> >& lines) {
// 计算线的正确比例
for (int i = 0; i < lines.size(); i++) {
int endIndex = i;
double totalLength = lines[i]->getLength();
while (endIndex + 1 < lines.size() && lines[endIndex]->getEnd() == lines[endIndex + 1]->getBegin()) {
totalLength += lines[++endIndex]->getLength();
}
double prefixLength = 0;
for (int j = i; j <= endIndex; j++) {
double nowLineLength = lines[j]->getLength();
lines[j]->setRate({ prefixLength / totalLength, (prefixLength + nowLineLength) / totalLength });
prefixLength += nowLineLength;
}
i = endIndex;
}
}
void LineTree::simplifyLineVector() { void LineTree::simplifyLineVector() {
bool canPut = false; bool canPut = false;
GLuint index = 0; GLuint index = 0;
numLine = allLines.size(); numLine = allLines.size();
for (auto& nowLine : allLines) { for (auto& nowLine : allLines) {
PointVector pointVector = nowLine->toPointVector(); PointVector pointVector = nowLine->toPointVector();
canPut = false; canPut = false;
index = 0; index = 0;
for (Point& p : pointVector) { for (Point& p : pointVector) {
int pointIndex = getPointIndex(p); int pointIndex = getPointIndex(p);
@ -165,8 +160,8 @@ bool LineTree::handleShortCutNode(LineTreeNode& fa, LineTreeNode& nowTreeNode, d
nowTreeNode.lineSet.push_back(lineIndex); nowTreeNode.lineSet.push_back(lineIndex);
} }
} }
if (nowTreeNode.lineSet.size() <= requiredLineMin if (nowTreeNode.lineSet.size() <= requiredLineMin
|| (nowTreeNode.bound.z()-nowTreeNode.bound.x())*sqrt(2) <= lineWidth) { || (nowTreeNode.bound.z() - nowTreeNode.bound.x()) * sqrt(2) <= lineWidth) {
if (nowTreeNode.lineSet.empty()) if (nowTreeNode.lineSet.empty())
return false; return false;
restOfTreeNodes.push_back(nowTreeNode); restOfTreeNodes.push_back(nowTreeNode);
@ -263,6 +258,7 @@ void LineTree::buildLineTree(std::vector<PointVector>& lineSet, double width, in
lineWidth = width; lineWidth = width;
lineType = type; lineType = type;
monotonization(lineSet, allLines); monotonization(lineSet, allLines);
countLinesRate(allLines);
spliteToLineTree(); spliteToLineTree();
simplifyLineVector(); simplifyLineVector();
} }

View File

@ -48,6 +48,7 @@ namespace Renderer {
: 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); static void monotonization(std::vector<PointVector>& inL, std::vector<std::shared_ptr<Line>>& outL);
static void countLinesRate(std::vector<std::shared_ptr<Line> >& lines);
std::vector<BvhTreeData> getPointLineAndBvhTree(std::vector<float>& pointSet, std::vector<GLuint>& lineSet); std::vector<BvhTreeData> getPointLineAndBvhTree(std::vector<float>& pointSet, std::vector<GLuint>& lineSet);
}; };
} }

View File

@ -52,6 +52,10 @@ int StraightLine::judgeOneSideIntersection(double xy, double l, double r, bool i
return 0; return 0;
} }
double StraightLine::getLength() {
return sqrt((vX[1] - vX[0]) * (vX[1] - vX[0]) + (vY[1] - vY[0]) * (vY[1] - vY[0]));
}
double StraightLine::getMinDistanceFromPoint(Point p) { double StraightLine::getMinDistanceFromPoint(Point p) {
Point se = { vX[1] - vX[0], vY[1] - vY[0] }; Point se = { vX[1] - vX[0], vY[1] - vY[0] };
Point dd = { p.x - vX[0], p.y - vY[0] }; Point dd = { p.x - vX[0], p.y - vY[0] };

View File

@ -10,6 +10,7 @@ namespace Renderer
virtual void monotonization(std::vector <LinePtr>& res) {}; virtual void monotonization(std::vector <LinePtr>& res) {};
virtual double findTByValue(double value, bool isY); virtual double findTByValue(double value, bool isY);
virtual int judgeOneSideIntersection(double xy, double l, double r, bool isY); virtual int judgeOneSideIntersection(double xy, double l, double r, bool isY);
virtual double getLength();
virtual double getMinDistanceFromPoint(Point p); virtual double getMinDistanceFromPoint(Point p);
virtual double ValueOfFunctionS(double t); virtual double ValueOfFunctionS(double t);
}; };