增加分割点在原线的比例关系与Svg处理变换问题

TaoZhang-Branch
yang.yongquan 2023-02-25 10:47:27 +08:00
parent ff848b1443
commit ab391ed0ec
12 changed files with 303 additions and 42 deletions

View File

@ -2,9 +2,12 @@
#include <QFile> #include <QFile>
#include "../ThirdPartyLib/qquick/qquicksvgparser_p.h" #include "../ThirdPartyLib/qquick/qquicksvgparser_p.h"
#include <QPolygonF> #include <QPolygonF>
#include <iostream>
using std::map; using std::map;
using std::vector;
using std::reverse;
bool SvgFileLoader::loadSvgFile(const QString& filePath, QPainterPath& painterPath) { bool SvgFileLoader::loadSvgFile(const QString& filePath, QPainterPath& painterPath) {
QFile file(filePath); QFile file(filePath);
@ -46,12 +49,12 @@ bool SvgFileLoader::loadSvgFile(const QString& filePath, QPainterPath& painterPa
} }
} }
} }
qDebug() << painterPath;
file.close(); file.close();
return true; return true;
} }
QMap<QString, QString> SvgFileLoader::transformStyle(QString style) { QMap<QString, QString> SvgFileLoader::handleAttrStyle(QString style) {
QMap<QString, QString> resStyleMap; QMap<QString, QString> resStyleMap;
for (auto& attr : style.split(';')) { for (auto& attr : style.split(';')) {
if (attr.isEmpty() || attr.trimmed() == "") continue; if (attr.isEmpty() || attr.trimmed() == "") continue;
@ -62,7 +65,7 @@ QMap<QString, QString> SvgFileLoader::transformStyle(QString style) {
return resStyleMap; return resStyleMap;
} }
QPolygonF SvgFileLoader::transformPoints(QString points) { QPolygonF SvgFileLoader::handleAttrPoints(QString points) {
QPolygonF resPointVector; QPolygonF resPointVector;
QPointF point(0, 0); QPointF point(0, 0);
bool isX = true; bool isX = true;
@ -80,10 +83,58 @@ QPolygonF SvgFileLoader::transformPoints(QString points) {
return resPointVector; return resPointVector;
} }
void SvgFileLoader::handleAttrTransform(QString transformStyle, QPainterPath& painterPath) {
QTransform trans;
QStringList ops = transformStyle.split(')');
reverse(ops.begin(), ops.end());
vector<double> numbers;
for (auto op : ops) {
op = op.simplified();
if (op.isEmpty()) continue;
QString type = (*op.split('(').begin()).trimmed();
QString numStr = (*op.split('(').rbegin()).trimmed() + ',';
QString tmpNum = "";
for (auto c : numStr) {
if (isdigit(c.toLatin1())) {
tmpNum += c;
}
else {
if (c == ',' && tmpNum.size() == 0) {
numbers.push_back(0);
}
else if (tmpNum.size() > 0) {
numbers.push_back(tmpNum.toDouble());
}
tmpNum.clear();
}
}
qDebug() << type << "///:" << numbers;
if (type == "translate") {
trans.translate(numbers[0], numbers[1]);
}
if (type == "scale") {
trans.scale(numbers[0], numbers[1]);
}
if (type == "rotate") {
trans.translate(numbers[1], numbers[2]);
trans.rotate(numbers[0]);
trans.translate(-numbers[1], -numbers[2]);
}
if (type == "skewX") {
trans.shear(numbers[0], 0);
}
if (type == "skewY") {
trans.shear(0, numbers[1]);
}
}
painterPath = trans.map(painterPath);
qDebug() << painterPath;
}
void SvgFileLoader::handleLabelG(QPainterPath& painterPath) { void SvgFileLoader::handleLabelG(QPainterPath& painterPath) {
for (auto& attr : xmlReader->attributes()) { for (auto& attr : xmlReader->attributes()) {
if (attr.name().toString() == QLatin1String("style")) { if (attr.name().toString() == QLatin1String("style")) {
styleMap = transformStyle(attr.value().toLatin1()); styleMap = handleAttrStyle(attr.value().toLatin1());
} }
else { else {
styleMap.insert(attr.name().toLatin1(), attr.value().toLatin1()); styleMap.insert(attr.name().toLatin1(), attr.value().toLatin1());
@ -94,22 +145,33 @@ void SvgFileLoader::handleLabelG(QPainterPath& painterPath) {
} }
void SvgFileLoader::handleLabelPath(QPainterPath& painterPath) { void SvgFileLoader::handleLabelPath(QPainterPath& painterPath) {
QPainterPath elementPainterPath;
QString transformStyle = "";
QMap<QString, QString> labelStyle; QMap<QString, QString> labelStyle;
for (auto& attr : xmlReader->attributes()) { for (auto& attr : xmlReader->attributes()) {
if (attr.name().toString() == QLatin1String("d")) { if (attr.name().toString() == QLatin1String("d")) {
QQuickSvgParser::parsePathDataFast(attr.value().toLatin1(), painterPath); QQuickSvgParser::parsePathDataFast(attr.value().toLatin1(), elementPainterPath);
} }
else if (attr.name().toString() == QLatin1String("style")) { else if (attr.name().toString() == QLatin1String("style")) {
labelStyle = transformStyle(attr.value().toLatin1()); labelStyle = handleAttrStyle(attr.value().toLatin1());
}
else if (attr.name().toString() == QLatin1String("transform")) {
transformStyle = attr.value().toLatin1();
} }
else { else {
labelStyle.insert(attr.name().toLatin1(), attr.value().toLatin1()); labelStyle.insert(attr.name().toLatin1(), attr.value().toLatin1());
} }
} }
if (!transformStyle.isEmpty()) {
handleAttrTransform(transformStyle, elementPainterPath);
}
painterPath.addPath(elementPainterPath);
} }
void SvgFileLoader::handleLabelRect(QPainterPath& painterPath) { void SvgFileLoader::handleLabelRect(QPainterPath& painterPath) {
QMap<QString, QString> labelStyle; QMap<QString, QString> labelStyle;
QPainterPath elementPainterPath;
QString transformStyle = "";
double xBegin = 0, yBegin = 0, width = 0, height = 0;; double xBegin = 0, yBegin = 0, width = 0, height = 0;;
for (auto& attr : xmlReader->attributes()) { for (auto& attr : xmlReader->attributes()) {
if (attr.name().toString() == QLatin1String("x")) { if (attr.name().toString() == QLatin1String("x")) {
@ -122,17 +184,26 @@ void SvgFileLoader::handleLabelRect(QPainterPath& painterPath) {
height = attr.value().toDouble(); height = attr.value().toDouble();
} }
else if (attr.name().toString() == QLatin1String("style")) { else if (attr.name().toString() == QLatin1String("style")) {
labelStyle = transformStyle(attr.value().toLatin1()); labelStyle = handleAttrStyle(attr.value().toLatin1());
}
else if (attr.name().toString() == QLatin1String("transform")) {
transformStyle = attr.value().toLatin1();
} }
else { else {
labelStyle.insert(attr.name().toLatin1(), attr.value().toLatin1()); labelStyle.insert(attr.name().toLatin1(), attr.value().toLatin1());
} }
} }
qDebug() << labelStyle; qDebug() << labelStyle;
painterPath.addRect(xBegin, yBegin, xBegin + width, yBegin + height); elementPainterPath.addRect(xBegin, yBegin, xBegin + width, yBegin + height);
if (!transformStyle.isEmpty()) {
handleAttrTransform(transformStyle, elementPainterPath);
}
painterPath.addPath(elementPainterPath);
} }
void SvgFileLoader::handleLabelCircle(QPainterPath& painterPath) { void SvgFileLoader::handleLabelCircle(QPainterPath& painterPath) {
QPainterPath elementPainterPath;
QString transformStyle = "";
QMap<QString, QString> labelStyle; QMap<QString, QString> labelStyle;
double cx = 0, cy = 0, r = 0; double cx = 0, cy = 0, r = 0;
for (auto& attr : xmlReader->attributes()) { for (auto& attr : xmlReader->attributes()) {
@ -144,18 +215,28 @@ void SvgFileLoader::handleLabelCircle(QPainterPath& painterPath) {
r = attr.value().toDouble(); r = attr.value().toDouble();
} }
else if (attr.name().toString() == QLatin1String("style")) { else if (attr.name().toString() == QLatin1String("style")) {
labelStyle = transformStyle(attr.value().toLatin1()); labelStyle = handleAttrStyle(attr.value().toLatin1());
}
else if (attr.name().toString() == QLatin1String("transform")) {
transformStyle = attr.value().toLatin1();
} }
else { else {
labelStyle.insert(attr.name().toLatin1(), attr.value().toLatin1()); labelStyle.insert(attr.name().toLatin1(), attr.value().toLatin1());
} }
} }
qDebug() << labelStyle; qDebug() << labelStyle;
elementPainterPath.addEllipse(cx, cy, r, r);
if (!transformStyle.isEmpty()) {
handleAttrTransform(transformStyle, elementPainterPath);
}
painterPath.addPath(elementPainterPath);
//addEllipse(cx, cy, r, r, painterPath); //addEllipse(cx, cy, r, r, painterPath);
painterPath.addEllipse(cx, cy, r, r);
} }
void SvgFileLoader::handleLabelEllipse(QPainterPath& painterPath) { void SvgFileLoader::handleLabelEllipse(QPainterPath& painterPath) {
QPainterPath elementPainterPath;
QString transformStyle = "";
QMap<QString, QString> labelStyle; QMap<QString, QString> labelStyle;
double cx = 0, cy = 0, rx = 0, ry = 0; double cx = 0, cy = 0, rx = 0, ry = 0;
for (auto& attr : xmlReader->attributes()) { for (auto& attr : xmlReader->attributes()) {
@ -168,7 +249,10 @@ void SvgFileLoader::handleLabelEllipse(QPainterPath& painterPath) {
} else if (attr.name().toString() == QLatin1String("ry")) { } else if (attr.name().toString() == QLatin1String("ry")) {
rx = attr.value().toDouble(); rx = attr.value().toDouble();
} else if (attr.name().toString() == QLatin1String("style")) { } else if (attr.name().toString() == QLatin1String("style")) {
labelStyle = transformStyle(attr.value().toLatin1()); labelStyle = handleAttrStyle(attr.value().toLatin1());
}
else if (attr.name().toString() == QLatin1String("transform")) {
transformStyle = attr.value().toLatin1();
} }
else { else {
labelStyle.insert(attr.name().toLatin1(), attr.value().toLatin1()); labelStyle.insert(attr.name().toLatin1(), attr.value().toLatin1());
@ -176,45 +260,68 @@ void SvgFileLoader::handleLabelEllipse(QPainterPath& painterPath) {
} }
qDebug() << labelStyle; qDebug() << labelStyle;
//addEllipse(cx, cy, rx, ry, painterPath); //addEllipse(cx, cy, rx, ry, painterPath);
painterPath.addEllipse(cx, cy, rx, ry); elementPainterPath.addEllipse(cx, cy, rx, ry);
if (!transformStyle.isEmpty()) {
handleAttrTransform(transformStyle, elementPainterPath);
}
painterPath.addPath(elementPainterPath);
} }
void SvgFileLoader::handleLabelPolyline(QPainterPath& painterPath) { void SvgFileLoader::handleLabelPolyline(QPainterPath& painterPath) {
QPainterPath elementPainterPath;
QString transformStyle = "";
QMap<QString, QString> labelStyle; QMap<QString, QString> labelStyle;
for (auto& attr : xmlReader->attributes()) { for (auto& attr : xmlReader->attributes()) {
if (attr.name().toString() == QLatin1String("points")) { if (attr.name().toString() == QLatin1String("points")) {
QPolygonF points = transformPoints(attr.value().toLatin1()); QPolygonF points = handleAttrPoints(attr.value().toLatin1());
painterPath.addPolygon(points); elementPainterPath.addPolygon(points);
} }
else if (attr.name().toString() == QLatin1String("style")) { else if (attr.name().toString() == QLatin1String("style")) {
labelStyle = transformStyle(attr.value().toLatin1()); labelStyle = handleAttrStyle(attr.value().toLatin1());
}
else if (attr.name().toString() == QLatin1String("transform")) {
transformStyle = attr.value().toLatin1();
} }
else { else {
labelStyle.insert(attr.name().toLatin1(), attr.value().toLatin1()); labelStyle.insert(attr.name().toLatin1(), attr.value().toLatin1());
} }
} }
qDebug() << labelStyle; qDebug() << labelStyle;
if (!transformStyle.isEmpty()) {
handleAttrTransform(transformStyle, elementPainterPath);
}
painterPath.addPath(elementPainterPath);
} }
void SvgFileLoader::handleLabelPolygon(QPainterPath & painterPath) { void SvgFileLoader::handleLabelPolygon(QPainterPath & painterPath) {
QPainterPath elementPainterPath;
QString transformStyle = "";
QMap<QString, QString> labelStyle; QMap<QString, QString> labelStyle;
for (auto& attr : xmlReader->attributes()) { for (auto& attr : xmlReader->attributes()) {
if (attr.name().toString() == QLatin1String("points")) { if (attr.name().toString() == QLatin1String("points")) {
QPolygonF points = transformPoints(attr.value().toLatin1()); QPolygonF points = handleAttrPoints(attr.value().toLatin1());
//points.push_back(*points.begin()); //points.push_back(*points.begin());
painterPath.addPolygon(points); elementPainterPath.addPolygon(points);
painterPath.closeSubpath(); elementPainterPath.closeSubpath();
} }
else if (attr.name().toString() == QLatin1String("style")) { else if (attr.name().toString() == QLatin1String("style")) {
labelStyle = transformStyle(attr.value().toLatin1()); labelStyle = handleAttrStyle(attr.value().toLatin1());
}
else if (attr.name().toString() == "transform") {
transformStyle = attr.value().toLatin1();
} }
else { else {
labelStyle.insert(attr.name().toLatin1(), attr.value().toLatin1()); labelStyle.insert(attr.name().toLatin1(), attr.value().toLatin1());
} }
} }
qDebug() << labelStyle; qDebug() << labelStyle;
if (!transformStyle.isEmpty()) {
handleAttrTransform(transformStyle, elementPainterPath);
}
painterPath.addPath(elementPainterPath);
} }
/*
void SvgFileLoader::addEllipse(double x, double y, double w, double h, QPainterPath& painterPath) { void SvgFileLoader::addEllipse(double x, double y, double w, double h, QPainterPath& painterPath) {
double k = w / 0.75; double k = w / 0.75;
painterPath.moveTo(x, y - h); painterPath.moveTo(x, y - h);
@ -222,3 +329,4 @@ void SvgFileLoader::addEllipse(double x, double y, double w, double h, QPainterP
painterPath.cubicTo(QPointF(x - k, y + h), QPointF(x - k, y - h), QPointF(x, y - h)); painterPath.cubicTo(QPointF(x - k, y + h), QPointF(x - k, y - h), QPointF(x, y - h));
painterPath.closeSubpath(); painterPath.closeSubpath();
} }
*/

View File

@ -13,9 +13,10 @@ private:
bool existFatherLabelG; bool existFatherLabelG;
QMap<QString, QString> styleMap; QMap<QString, QString> styleMap;
std::shared_ptr<QXmlStreamReader> xmlReader; std::shared_ptr<QXmlStreamReader> xmlReader;
QPolygonF transformPoints(QString points); QPolygonF handleAttrPoints(QString points);
QMap<QString, QString> transformStyle(QString style); QMap<QString, QString> handleAttrStyle(QString style);
void addEllipse(double cx, double cy, double h, double w, QPainterPath& painterPath); void handleAttrTransform(QString transformStyle, QPainterPath& painterPath);
//void addEllipse(double cx, double cy, double h, double w, QPainterPath& painterPath);
void handleLabelG(QPainterPath& painterPath); void handleLabelG(QPainterPath& painterPath);
void handleLabelPath(QPainterPath& painterPath); void handleLabelPath(QPainterPath& painterPath);
void handleLabelRect(QPainterPath& painterPath); void handleLabelRect(QPainterPath& painterPath);

View File

@ -22,6 +22,12 @@ Point CubicBezier::calculateControlPoint(Point a, Point b) {
}; };
} }
double CubicBezier::ValueOfFunctionS(double t) {
double dxt = -3 * vX[0] * (1 - t) * (1 - t) + 3 * vX[1] * (1 - t) * (1 - 3 * t) + 3 * vX[2] * t * (2 - 3 * t) + 3 * vX[3] * t * t;
double dyt = -3 * vY[0] * (1 - t) * (1 - t) + 3 * vY[1] * (1 - t) * (1 - 3 * t) + 3 * vY[2] * t * (2 - 3 * t) + 3 * vY[3] * t * t;
return sqrt(dxt * dxt + dyt * dyt);
}
void CubicBezier::findPointsOfDivison(vector<double> &p, vector<double>& res) { void CubicBezier::findPointsOfDivison(vector<double> &p, vector<double>& res) {
double a = (-p[0] + 3 * p[1] - 3 * p[2] + p[3]); double a = (-p[0] + 3 * p[1] - 3 * p[2] + p[3]);
if (fabs(a) > eps) { if (fabs(a) > eps) {
@ -55,20 +61,26 @@ void CubicBezier::transformToCubic() {
} }
void CubicBezier::splitBezierCubic(double 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) }; Point pointE = { getLineValueByT(t, false), getLineValueByT(t, true) };
Point pointF = getPointByT(getPointByIndex(0), getPointByIndex(1), t); Point pointF = getPointByT(getPointByIndex(0), getPointByIndex(1), t);
Point pointG = getPointByT(getPointByIndex(1), getPointByIndex(2), t); Point pointG = getPointByT(getPointByIndex(1), getPointByIndex(2), t);
Point pointH = getPointByT(getPointByIndex(2), getPointByIndex(3), t); Point pointH = getPointByT(getPointByIndex(2), getPointByIndex(3), t);
Lf->push_back(getPointByIndex(0)); vector<Point> vP; vP.clear();
Lf->push_back(pointF); vP.push_back(getPointByIndex(0));
Lf->push_back(getPointByT(pointF, pointG, t)); vP.push_back(pointF);
Lf->push_back(pointE); vP.push_back(getPointByT(pointF, pointG, t));
res.push_back(Lf); vP.push_back(pointE);
LinePtr lf(new CubicBezier(vP));
double totalLen = getIntegralByT(1), len = getIntegralByT(t);
if (totalLen <= eps) return;
double ratePoint = (1 - len / totalLen) * rate.first + len / totalLen * rate.second;
lf->setRate({ rate.first, ratePoint });
res.push_back(lf);
setPointByIndex(0, pointE); setPointByIndex(0, pointE);
setPointByIndex(1, getPointByT(pointG, pointH, t)); setPointByIndex(1, getPointByT(pointG, pointH, t));
setPointByIndex(2, pointH); setPointByIndex(2, pointH);
updateLeftType();
setRate({ ratePoint, rate.second });
} }
void CubicBezier::monotonization(vector <LinePtr>& res) { void CubicBezier::monotonization(vector <LinePtr>& res) {

View File

@ -11,12 +11,14 @@ namespace Renderer
static Point calculateControlPoint(Point a, Point b); static Point calculateControlPoint(Point a, Point b);
static void findPointsOfDivison(std::vector<double>& p, std::vector<double>& res); static void findPointsOfDivison(std::vector<double>& p, std::vector<double>& res);
void splitBezierCubic(double t, std::vector<LinePtr>& res); void splitBezierCubic(double t, std::vector<LinePtr>& res);
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 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);
virtual double ValueOfFunctionS(double t);
void transformToCubic(); void transformToCubic();
}; };
} }

View File

@ -1,4 +1,5 @@
#include "Line.h" #include "Line.h"
#include <glm/detail/func_packing.hpp>
using namespace Renderer; using namespace Renderer;
using std::vector; using std::vector;
using std::pair; using std::pair;
@ -14,14 +15,29 @@ Line::Line(vector<Point> Vp) {
vX.push_back(now.x); vX.push_back(now.x);
vY.push_back(now.y); vY.push_back(now.y);
} }
updateLeftType();
rate = { 0, 1 };
}
bool Line::updateLeftType() {
if (*vY.rbegin() < vY[0]) leftType = 0; if (*vY.rbegin() < vY[0]) leftType = 0;
else leftType = 1; else leftType = 1;
return true;
} }
int Line::size() { int Line::size() {
return siz; return siz;
} }
bool Line::setRate(std::pair<double, double> inRate) {
rate = inRate;
return true;
}
uint Line::getRate() {
return glm::packUnorm2x16(glm::vec2(rate.first, rate.second));
}
vector<Point> Line::toPointVector() const { vector<Point> Line::toPointVector() const {
vector<Point> vL; vector<Point> vL;
for (int i = 0; i < siz; i++) { for (int i = 0; i < siz; i++) {
@ -152,3 +168,26 @@ bool Line::judgeIntersectionWithWidth(QVector4D bound, double width, int type) {
|| judgeOneSideIntersectionWithWidth(bound.x(), bound.y(), bound.w(), false, width, type) || judgeOneSideIntersectionWithWidth(bound.x(), bound.y(), bound.w(), false, width, type)
|| judgeOneSideIntersectionWithWidth(bound.z(), bound.y(), bound.w(), false, width, type); || judgeOneSideIntersectionWithWidth(bound.z(), bound.y(), bound.w(), false, width, type);
} }
double Line::getIntegralByT(double t) {
double T[12][12], err = 1, S = 0, tmpPow4 = 1;
T[1][1] = t * (ValueOfFunctionS(t) + ValueOfFunctionS(0)) / 2;
int n = 1, k = 0;
while (err > eps) {
++k; S = 0;
for (int i = 1; i <= n; i++) {
double x = t * (2 * i - 1) / 2;
S = S + ValueOfFunctionS(x);
}
tmpPow4 = 1;
T[k + 1][1] = (T[k][1] + t * S) / 2;
for (int m = 1; m <= k; m++) {
tmpPow4 *= 4;
T[k + 1][m + 1] = (tmpPow4 * T[k + 1][m] - T[k][m]) / (tmpPow4 - 1);
}
err = fabs(T[k + 1][k + 1] - T[k + 1][k]);
n <<= 1; t = t / 2;
if (k >= 8) break;
}
return T[k + 1][k + 1];
}

View File

@ -49,21 +49,28 @@ namespace Renderer
protected: protected:
std::vector<double> vX, vY; std::vector<double> vX, vY;
int siz, leftType; int siz, leftType;
std::pair<double, double> rate;
public: public:
typedef std::shared_ptr<Line> LinePtr; typedef std::shared_ptr<Line> LinePtr;
Line() :siz(0) {} Line() : siz(0), leftType(0), rate({0, 1}) {}
Line(std::vector<Point> Vp); Line(std::vector<Point> Vp);
int size(); int size();
bool setRate(std::pair<double, double> inRate);
uint getRate();
void clear(); void clear();
Point getBegin(); Point getBegin();
Point getEnd(); Point getEnd();
int direction(bool isY); int direction(bool isY);
bool updateLeftType();
virtual double getLineValueByT(double t, bool isY) = 0; virtual double getLineValueByT(double t, bool isY) = 0;
// s = sqrt(x^2+y^2);
virtual double ValueOfFunctionS(double t) = 0;
virtual void monotonization(std::vector <LinePtr>& res) = 0; virtual void monotonization(std::vector <LinePtr>& res) = 0;
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 findTByValue(double value, bool isY) = 0; virtual double findTByValue(double value, bool isY) = 0;
double getIntegralByT(double t);
bool judgeIntersectionWithWidth(QVector4D bound, double width, int type); bool judgeIntersectionWithWidth(QVector4D bound, double width, int type);
bool judgeIntersection(QVector4D bound); bool judgeIntersection(QVector4D bound);
int getPointSideOfLine(Point p); int getPointSideOfLine(Point p);

View File

@ -108,15 +108,30 @@ void LineTree::monotonization(vector<PointVector>& inLines, vector<std::shared_p
} }
void LineTree::simplifyLineVector() { void LineTree::simplifyLineVector() {
bool canPut = false;
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;
index = 0;
for (Point& p : pointVector) { for (Point& p : pointVector) {
int pointIndex = getPointIndex(p); int pointIndex = getPointIndex(p);
lineIndexs.push_back(pointIndex); if (pointVector.size() == 2) {
if (pointVector.size() == 2) index = (pointIndex << 16) + pointIndex;
lineIndexs.push_back(pointIndex); lineIndexs.push_back(index);
} }
else {
index <<= 16;
index += pointIndex;
if (canPut) {
lineIndexs.push_back(index);
index = 0;
}
canPut = !canPut;
}
}
lineIndexs.push_back(nowLine->getRate());
} }
} }
@ -237,15 +252,15 @@ vector<BvhTreeData> LineTree::getPointLineAndBvhTree(vector<float>& resPoints, v
for (auto& vectorIter : tmpPoints) { for (auto& vectorIter : tmpPoints) {
resPoints.push_back(vectorIter.second.x); resPoints.push_back(vectorIter.second.x);
resPoints.push_back(vectorIter.second.y); resPoints.push_back(vectorIter.second.y);
vectorIter.second.show(); //vectorIter.second.show();
std::cout << '\n'; //std::cout << '\n';
} }
// Ïß¼¯ // Ïß¼¯
for (auto& nowLineIndex : lineIndexs) { for (auto& nowLineIndex : lineIndexs) {
resLines.push_back(nowLineIndex); resLines.push_back(nowLineIndex);
std::cout << nowLineIndex << ' '; //std::cout << nowLineIndex << ' ';
} }
std::cout << '\n'; //std::cout << '\n';
// ·µ»Ø¹¹ÔìBvhTreeÊý¾Ý // ·µ»Ø¹¹ÔìBvhTreeÊý¾Ý
vector<BvhTreeData> resBvhTreeData; vector<BvhTreeData> resBvhTreeData;
for (auto& nowTreeNode : restOfTreeNodes) { for (auto& nowTreeNode : restOfTreeNodes) {
@ -253,13 +268,13 @@ vector<BvhTreeData> LineTree::getPointLineAndBvhTree(vector<float>& resPoints, v
oneData.leftSon = resLines.size(); oneData.leftSon = resLines.size();
oneData.rightSon = 0; oneData.rightSon = 0;
oneData.bound = nowTreeNode.bound; oneData.bound = nowTreeNode.bound;
std::cout << nowTreeNode.lineSet.size() << ' '; //std::cout << nowTreeNode.lineSet.size() << ' ';
resLines.push_back(nowTreeNode.lineSet.size()); resLines.push_back(nowTreeNode.lineSet.size());
for (auto& lineIndex : nowTreeNode.lineSet) { for (auto& lineIndex : nowTreeNode.lineSet) {
resLines.push_back(lineIndex); resLines.push_back(lineIndex);
std::cout << lineIndex << ' '; //std::cout << lineIndex << ' ';
} }
std::cout << '\n'; //std::cout << '\n';
resBvhTreeData.push_back(oneData); resBvhTreeData.push_back(oneData);
} }
return resBvhTreeData; return resBvhTreeData;

View File

@ -14,6 +14,10 @@ double StraightLine::getLineValueByT(double t, bool isY) {
return t * (valueEnd - valueBegin) + valueBegin; return t * (valueEnd - valueBegin) + valueBegin;
} }
double StraightLine::ValueOfFunctionS(double t) {
return sqrt((vX[1] - vX[0]) * (vX[1] - vX[0]) + (vY[1] - vY[0]) * (vY[1] - vY[0]));
}
double StraightLine::findTByValue(double value, bool isY) { double StraightLine::findTByValue(double value, bool isY) {
Point pointBegin = getPointByIndex(0), pointEnd = getPointByIndex(1); Point pointBegin = getPointByIndex(0), pointEnd = getPointByIndex(1);
if (!isY) { if (!isY) {

View File

@ -11,5 +11,6 @@ namespace Renderer
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 getMinDistanceFromPoint(Point p); virtual double getMinDistanceFromPoint(Point p);
virtual double ValueOfFunctionS(double t);
}; };
} }

View File

@ -3,6 +3,7 @@
#include <QtWidgets/QApplication> #include <QtWidgets/QApplication>
#include "ElementRendererTest.h" #include "ElementRendererTest.h"
#include "Renderer/Painting/ElementStyle.h" #include "Renderer/Painting/ElementStyle.h"
#include <util/SvgFileLoader.h>
using namespace Microsoft::VisualStudio::CppUnitTestFramework; using namespace Microsoft::VisualStudio::CppUnitTestFramework;
using namespace Renderer; using namespace Renderer;
@ -195,4 +196,5 @@ namespace UnitTest
a.exec(); a.exec();
} }
}; };
} }

View File

@ -3,12 +3,43 @@
#include <QGuiApplication> #include <QGuiApplication>
#include <QtWidgets/QApplication> #include <QtWidgets/QApplication>
#include <FramelessHelper/Core/private/framelessconfig_p.h> #include <FramelessHelper/Core/private/framelessconfig_p.h>
#include <util/SvgFileLoader.h>
#include "Renderer/Painting/CubicBezier.h"
#include <Renderer/Painting/StraightLine.h>
using namespace Microsoft::VisualStudio::CppUnitTestFramework; using namespace Microsoft::VisualStudio::CppUnitTestFramework;
namespace UnitTest namespace UnitTest
{ {
void messageHandler(QtMsgType type, const QMessageLogContext& context, const QString& msg)
{
switch (type)
{
case QtInfoMsg:
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY);
break;
case QtDebugMsg:
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
break;
case QtWarningMsg:
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN);
break;
case QtCriticalMsg:
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_BLUE);
break;
case QtFatalMsg:
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED);
break;
}
Logger::WriteMessage(std::format("{}({},{}) {}\n",
QString(context.file).splitRef("\\").back().toLocal8Bit().data(),
context.line,
QString(context.function).splitRef("(").first().split(" ").back().split(":").back().toLocal8Bit().data(),
msg.toStdString()).c_str());
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
}
TEST_CLASS(UnitTest) TEST_CLASS(UnitTest)
{ {
public: public:
@ -31,4 +62,37 @@ namespace UnitTest
a.exec(); a.exec();
} }
}; };
TEST_CLASS(SvgLoaderTest)
{
public:
TEST_METHOD(LoadSvg)
{
qInstallMessageHandler(messageHandler);
QPainterPath painterPath;
SvgFileLoader svgloader;
svgloader.loadSvgFile("D:\\BigC\\Project\\ArchitectureColoredPainting\\svg\\test.svg", painterPath);
}
};
TEST_CLASS(CubicBezierTest)
{
public:
TEST_METHOD(CubicIntegral)
{
qInstallMessageHandler(messageHandler);
std::shared_ptr<Renderer::Line> line(new Renderer::CubicBezier());
line->push_back({ -1, -1 });
line->push_back({ -1, 1 });
line->push_back({ 1, 1 });
line->push_back({ 1, -1 });
vector<std::shared_ptr<Renderer::Line>> outLines;
line->monotonization(outLines);
for (auto line : outLines) {
qDebug() << line->getRate();
}
}
};
} }

6
svg/test.svg Normal file
View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<rect width="300" height="100"
style="fill:rgb(0,0,255);stroke-width:1;stroke:rgb(0,0,0)"
transform="translate(50 20)"/>
</svg>

After

Width:  |  Height:  |  Size: 191 B