From ab391ed0ec8235255df2ff6e221b8b24b3fc4947 Mon Sep 17 00:00:00 2001 From: "yang.yongquan" <3395816735@qq.com> Date: Sat, 25 Feb 2023 10:47:27 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=88=86=E5=89=B2=E7=82=B9?= =?UTF-8?q?=E5=9C=A8=E5=8E=9F=E7=BA=BF=E7=9A=84=E6=AF=94=E4=BE=8B=E5=85=B3?= =?UTF-8?q?=E7=B3=BB=E4=B8=8ESvg=E5=A4=84=E7=90=86=E5=8F=98=E6=8D=A2?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/Editor/util/SvgFileLoader.cpp | 148 +++++++++++++++--- .../src/Editor/util/SvgFileLoader.h | 7 +- .../src/Renderer/Painting/CubicBezier.cpp | 28 +++- .../src/Renderer/Painting/CubicBezier.h | 2 + .../src/Renderer/Painting/Line.cpp | 39 +++++ .../src/Renderer/Painting/Line.h | 9 +- .../src/Renderer/Painting/LineTree.cpp | 35 +++-- .../src/Renderer/Painting/StraightLine.cpp | 4 + .../src/Renderer/Painting/StraightLine.h | 1 + UnitTest/ElementRendererTest.cpp | 2 + UnitTest/UnitTest.cpp | 64 ++++++++ svg/test.svg | 6 + 12 files changed, 303 insertions(+), 42 deletions(-) create mode 100644 svg/test.svg diff --git a/ArchitectureColoredPainting/src/Editor/util/SvgFileLoader.cpp b/ArchitectureColoredPainting/src/Editor/util/SvgFileLoader.cpp index 30f0ae6..d4c7d03 100644 --- a/ArchitectureColoredPainting/src/Editor/util/SvgFileLoader.cpp +++ b/ArchitectureColoredPainting/src/Editor/util/SvgFileLoader.cpp @@ -2,9 +2,12 @@ #include #include "../ThirdPartyLib/qquick/qquicksvgparser_p.h" #include +#include using std::map; +using std::vector; +using std::reverse; bool SvgFileLoader::loadSvgFile(const QString& filePath, QPainterPath& painterPath) { QFile file(filePath); @@ -46,12 +49,12 @@ bool SvgFileLoader::loadSvgFile(const QString& filePath, QPainterPath& painterPa } } } - + qDebug() << painterPath; file.close(); return true; } -QMap SvgFileLoader::transformStyle(QString style) { +QMap SvgFileLoader::handleAttrStyle(QString style) { QMap resStyleMap; for (auto& attr : style.split(';')) { if (attr.isEmpty() || attr.trimmed() == "") continue; @@ -62,7 +65,7 @@ QMap SvgFileLoader::transformStyle(QString style) { return resStyleMap; } -QPolygonF SvgFileLoader::transformPoints(QString points) { +QPolygonF SvgFileLoader::handleAttrPoints(QString points) { QPolygonF resPointVector; QPointF point(0, 0); bool isX = true; @@ -80,10 +83,58 @@ QPolygonF SvgFileLoader::transformPoints(QString points) { return resPointVector; } +void SvgFileLoader::handleAttrTransform(QString transformStyle, QPainterPath& painterPath) { + QTransform trans; + QStringList ops = transformStyle.split(')'); + reverse(ops.begin(), ops.end()); + vector 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) { for (auto& attr : xmlReader->attributes()) { if (attr.name().toString() == QLatin1String("style")) { - styleMap = transformStyle(attr.value().toLatin1()); + styleMap = handleAttrStyle(attr.value().toLatin1()); } else { styleMap.insert(attr.name().toLatin1(), attr.value().toLatin1()); @@ -94,22 +145,33 @@ void SvgFileLoader::handleLabelG(QPainterPath& painterPath) { } void SvgFileLoader::handleLabelPath(QPainterPath& painterPath) { + QPainterPath elementPainterPath; + QString transformStyle = ""; QMap labelStyle; for (auto& attr : xmlReader->attributes()) { 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")) { - labelStyle = transformStyle(attr.value().toLatin1()); + labelStyle = handleAttrStyle(attr.value().toLatin1()); } + else if (attr.name().toString() == QLatin1String("transform")) { + transformStyle = attr.value().toLatin1(); + } else { labelStyle.insert(attr.name().toLatin1(), attr.value().toLatin1()); } } + if (!transformStyle.isEmpty()) { + handleAttrTransform(transformStyle, elementPainterPath); + } + painterPath.addPath(elementPainterPath); } void SvgFileLoader::handleLabelRect(QPainterPath& painterPath) { QMap labelStyle; + QPainterPath elementPainterPath; + QString transformStyle = ""; double xBegin = 0, yBegin = 0, width = 0, height = 0;; for (auto& attr : xmlReader->attributes()) { if (attr.name().toString() == QLatin1String("x")) { @@ -122,17 +184,26 @@ void SvgFileLoader::handleLabelRect(QPainterPath& painterPath) { height = attr.value().toDouble(); } 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 { labelStyle.insert(attr.name().toLatin1(), attr.value().toLatin1()); } } 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) { + QPainterPath elementPainterPath; + QString transformStyle = ""; QMap labelStyle; double cx = 0, cy = 0, r = 0; for (auto& attr : xmlReader->attributes()) { @@ -144,18 +215,28 @@ void SvgFileLoader::handleLabelCircle(QPainterPath& painterPath) { r = attr.value().toDouble(); } 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 { labelStyle.insert(attr.name().toLatin1(), attr.value().toLatin1()); } } qDebug() << labelStyle; + elementPainterPath.addEllipse(cx, cy, r, r); + if (!transformStyle.isEmpty()) { + handleAttrTransform(transformStyle, elementPainterPath); + } + painterPath.addPath(elementPainterPath); //addEllipse(cx, cy, r, r, painterPath); - painterPath.addEllipse(cx, cy, r, r); + } void SvgFileLoader::handleLabelEllipse(QPainterPath& painterPath) { + QPainterPath elementPainterPath; + QString transformStyle = ""; QMap labelStyle; double cx = 0, cy = 0, rx = 0, ry = 0; for (auto& attr : xmlReader->attributes()) { @@ -168,7 +249,10 @@ void SvgFileLoader::handleLabelEllipse(QPainterPath& painterPath) { } else if (attr.name().toString() == QLatin1String("ry")) { rx = attr.value().toDouble(); } 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 { labelStyle.insert(attr.name().toLatin1(), attr.value().toLatin1()); @@ -176,49 +260,73 @@ void SvgFileLoader::handleLabelEllipse(QPainterPath& painterPath) { } qDebug() << labelStyle; //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) { + QPainterPath elementPainterPath; + QString transformStyle = ""; QMap labelStyle; for (auto& attr : xmlReader->attributes()) { if (attr.name().toString() == QLatin1String("points")) { - QPolygonF points = transformPoints(attr.value().toLatin1()); - painterPath.addPolygon(points); + QPolygonF points = handleAttrPoints(attr.value().toLatin1()); + elementPainterPath.addPolygon(points); } 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 { labelStyle.insert(attr.name().toLatin1(), attr.value().toLatin1()); } } qDebug() << labelStyle; + if (!transformStyle.isEmpty()) { + handleAttrTransform(transformStyle, elementPainterPath); + } + painterPath.addPath(elementPainterPath); } void SvgFileLoader::handleLabelPolygon(QPainterPath & painterPath) { + QPainterPath elementPainterPath; + QString transformStyle = ""; QMap labelStyle; for (auto& attr : xmlReader->attributes()) { if (attr.name().toString() == QLatin1String("points")) { - QPolygonF points = transformPoints(attr.value().toLatin1()); + QPolygonF points = handleAttrPoints(attr.value().toLatin1()); //points.push_back(*points.begin()); - painterPath.addPolygon(points); - painterPath.closeSubpath(); + elementPainterPath.addPolygon(points); + elementPainterPath.closeSubpath(); } 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 { labelStyle.insert(attr.name().toLatin1(), attr.value().toLatin1()); } } qDebug() << labelStyle; + if (!transformStyle.isEmpty()) { + handleAttrTransform(transformStyle, elementPainterPath); + } + painterPath.addPath(elementPainterPath); } +/* void SvgFileLoader::addEllipse(double x, double y, double w, double h, QPainterPath& painterPath) { double k = w / 0.75; painterPath.moveTo(x, y - h); 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(); -} \ No newline at end of file +} +*/ \ No newline at end of file diff --git a/ArchitectureColoredPainting/src/Editor/util/SvgFileLoader.h b/ArchitectureColoredPainting/src/Editor/util/SvgFileLoader.h index 352b9b0..3bdcd8a 100644 --- a/ArchitectureColoredPainting/src/Editor/util/SvgFileLoader.h +++ b/ArchitectureColoredPainting/src/Editor/util/SvgFileLoader.h @@ -13,9 +13,10 @@ private: bool existFatherLabelG; QMap styleMap; std::shared_ptr xmlReader; - QPolygonF transformPoints(QString points); - QMap transformStyle(QString style); - void addEllipse(double cx, double cy, double h, double w, QPainterPath& painterPath); + QPolygonF handleAttrPoints(QString points); + QMap handleAttrStyle(QString style); + void handleAttrTransform(QString transformStyle, QPainterPath& painterPath); + //void addEllipse(double cx, double cy, double h, double w, QPainterPath& painterPath); void handleLabelG(QPainterPath& painterPath); void handleLabelPath(QPainterPath& painterPath); void handleLabelRect(QPainterPath& painterPath); diff --git a/ArchitectureColoredPainting/src/Renderer/Painting/CubicBezier.cpp b/ArchitectureColoredPainting/src/Renderer/Painting/CubicBezier.cpp index 5c01eb8..442a6d2 100644 --- a/ArchitectureColoredPainting/src/Renderer/Painting/CubicBezier.cpp +++ b/ArchitectureColoredPainting/src/Renderer/Painting/CubicBezier.cpp @@ -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 &p, vector& res) { double a = (-p[0] + 3 * p[1] - 3 * p[2] + p[3]); if (fabs(a) > eps) { @@ -55,20 +61,26 @@ void CubicBezier::transformToCubic() { } void CubicBezier::splitBezierCubic(double t, vector& res) { - LinePtr Lf(new CubicBezier()); - float pt = 1 - t; Point pointE = { getLineValueByT(t, false), getLineValueByT(t, true) }; Point pointF = getPointByT(getPointByIndex(0), getPointByIndex(1), t); Point pointG = getPointByT(getPointByIndex(1), getPointByIndex(2), t); Point pointH = getPointByT(getPointByIndex(2), getPointByIndex(3), t); - Lf->push_back(getPointByIndex(0)); - Lf->push_back(pointF); - Lf->push_back(getPointByT(pointF, pointG, t)); - Lf->push_back(pointE); - res.push_back(Lf); + vector vP; vP.clear(); + vP.push_back(getPointByIndex(0)); + vP.push_back(pointF); + vP.push_back(getPointByT(pointF, pointG, t)); + 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(1, getPointByT(pointG, pointH, t)); setPointByIndex(2, pointH); + updateLeftType(); + setRate({ ratePoint, rate.second }); } void CubicBezier::monotonization(vector & res) { @@ -120,4 +132,4 @@ int CubicBezier::judgeOneSideIntersection(double xy, double l, double r, bool is double CubicBezier::getMinDistanceFromPoint(Point p) { return CubicBezierSignedDistance::cubic_bezier_dis(p, getBegin(), getPointByIndex(1), getPointByIndex(2), getEnd()); -} \ No newline at end of file +} diff --git a/ArchitectureColoredPainting/src/Renderer/Painting/CubicBezier.h b/ArchitectureColoredPainting/src/Renderer/Painting/CubicBezier.h index 81f9d5d..e479f67 100644 --- a/ArchitectureColoredPainting/src/Renderer/Painting/CubicBezier.h +++ b/ArchitectureColoredPainting/src/Renderer/Painting/CubicBezier.h @@ -11,12 +11,14 @@ namespace Renderer static Point calculateControlPoint(Point a, Point b); static void findPointsOfDivison(std::vector& p, std::vector& res); void splitBezierCubic(double t, std::vector& res); + public: virtual double findTByValue(double value, bool isY); virtual void monotonization(std::vector & res); virtual double getLineValueByT(double t, bool isY); virtual int judgeOneSideIntersection(double xy, double l, double r, bool isY); virtual double getMinDistanceFromPoint(Point p); + virtual double ValueOfFunctionS(double t); void transformToCubic(); }; } diff --git a/ArchitectureColoredPainting/src/Renderer/Painting/Line.cpp b/ArchitectureColoredPainting/src/Renderer/Painting/Line.cpp index f26afd7..dbd6c0f 100644 --- a/ArchitectureColoredPainting/src/Renderer/Painting/Line.cpp +++ b/ArchitectureColoredPainting/src/Renderer/Painting/Line.cpp @@ -1,4 +1,5 @@ #include "Line.h" +#include using namespace Renderer; using std::vector; using std::pair; @@ -14,14 +15,29 @@ Line::Line(vector Vp) { vX.push_back(now.x); vY.push_back(now.y); } + updateLeftType(); + rate = { 0, 1 }; +} + +bool Line::updateLeftType() { if (*vY.rbegin() < vY[0]) leftType = 0; else leftType = 1; + return true; } int Line::size() { return siz; } +bool Line::setRate(std::pair inRate) { + rate = inRate; + return true; +} + +uint Line::getRate() { + return glm::packUnorm2x16(glm::vec2(rate.first, rate.second)); +} + vector Line::toPointVector() const { vector vL; for (int i = 0; i < siz; i++) { @@ -151,4 +167,27 @@ bool Line::judgeIntersectionWithWidth(QVector4D bound, double width, int type) { || judgeOneSideIntersectionWithWidth(bound.w(), bound.x(), bound.z(), true, width, type) || judgeOneSideIntersectionWithWidth(bound.x(), 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]; } \ No newline at end of file diff --git a/ArchitectureColoredPainting/src/Renderer/Painting/Line.h b/ArchitectureColoredPainting/src/Renderer/Painting/Line.h index e9accc4..2198f8c 100644 --- a/ArchitectureColoredPainting/src/Renderer/Painting/Line.h +++ b/ArchitectureColoredPainting/src/Renderer/Painting/Line.h @@ -49,21 +49,28 @@ namespace Renderer protected: std::vector vX, vY; int siz, leftType; + std::pair rate; public: typedef std::shared_ptr LinePtr; - Line() :siz(0) {} + Line() : siz(0), leftType(0), rate({0, 1}) {} Line(std::vector Vp); int size(); + bool setRate(std::pair inRate); + uint getRate(); void clear(); Point getBegin(); Point getEnd(); int direction(bool isY); + bool updateLeftType(); 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 & res) = 0; virtual int judgeOneSideIntersection(double xy, double l, double r, bool isY) = 0; virtual double getMinDistanceFromPoint(Point p) = 0; bool judgeOneSideIntersectionWithWidth(double xy, double l, double r, bool isY, double width, int type); virtual double findTByValue(double value, bool isY) = 0; + double getIntegralByT(double t); bool judgeIntersectionWithWidth(QVector4D bound, double width, int type); bool judgeIntersection(QVector4D bound); int getPointSideOfLine(Point p); diff --git a/ArchitectureColoredPainting/src/Renderer/Painting/LineTree.cpp b/ArchitectureColoredPainting/src/Renderer/Painting/LineTree.cpp index 736b55e..2b4cd56 100644 --- a/ArchitectureColoredPainting/src/Renderer/Painting/LineTree.cpp +++ b/ArchitectureColoredPainting/src/Renderer/Painting/LineTree.cpp @@ -108,15 +108,30 @@ void LineTree::monotonization(vector& inLines, vectortoPointVector(); + canPut = false; + index = 0; for (Point& p : pointVector) { int pointIndex = getPointIndex(p); - lineIndexs.push_back(pointIndex); - if (pointVector.size() == 2) - lineIndexs.push_back(pointIndex); + if (pointVector.size() == 2) { + index = (pointIndex << 16) + 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 LineTree::getPointLineAndBvhTree(vector& resPoints, v for (auto& vectorIter : tmpPoints) { resPoints.push_back(vectorIter.second.x); resPoints.push_back(vectorIter.second.y); - vectorIter.second.show(); - std::cout << '\n'; + //vectorIter.second.show(); + //std::cout << '\n'; } // 线集 for (auto& nowLineIndex : lineIndexs) { resLines.push_back(nowLineIndex); - std::cout << nowLineIndex << ' '; + //std::cout << nowLineIndex << ' '; } - std::cout << '\n'; + //std::cout << '\n'; // 返回构造BvhTree数据 vector resBvhTreeData; for (auto& nowTreeNode : restOfTreeNodes) { @@ -253,13 +268,13 @@ vector LineTree::getPointLineAndBvhTree(vector& resPoints, v oneData.leftSon = resLines.size(); oneData.rightSon = 0; oneData.bound = nowTreeNode.bound; - std::cout << nowTreeNode.lineSet.size() << ' '; + //std::cout << nowTreeNode.lineSet.size() << ' '; resLines.push_back(nowTreeNode.lineSet.size()); for (auto& lineIndex : nowTreeNode.lineSet) { resLines.push_back(lineIndex); - std::cout << lineIndex << ' '; + //std::cout << lineIndex << ' '; } - std::cout << '\n'; + //std::cout << '\n'; resBvhTreeData.push_back(oneData); } return resBvhTreeData; diff --git a/ArchitectureColoredPainting/src/Renderer/Painting/StraightLine.cpp b/ArchitectureColoredPainting/src/Renderer/Painting/StraightLine.cpp index 5351c22..101b5f8 100644 --- a/ArchitectureColoredPainting/src/Renderer/Painting/StraightLine.cpp +++ b/ArchitectureColoredPainting/src/Renderer/Painting/StraightLine.cpp @@ -14,6 +14,10 @@ double StraightLine::getLineValueByT(double t, bool isY) { 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) { Point pointBegin = getPointByIndex(0), pointEnd = getPointByIndex(1); if (!isY) { diff --git a/ArchitectureColoredPainting/src/Renderer/Painting/StraightLine.h b/ArchitectureColoredPainting/src/Renderer/Painting/StraightLine.h index f2101d4..73625c0 100644 --- a/ArchitectureColoredPainting/src/Renderer/Painting/StraightLine.h +++ b/ArchitectureColoredPainting/src/Renderer/Painting/StraightLine.h @@ -11,5 +11,6 @@ namespace Renderer virtual double findTByValue(double value, bool isY); virtual int judgeOneSideIntersection(double xy, double l, double r, bool isY); virtual double getMinDistanceFromPoint(Point p); + virtual double ValueOfFunctionS(double t); }; } \ No newline at end of file diff --git a/UnitTest/ElementRendererTest.cpp b/UnitTest/ElementRendererTest.cpp index f9c9538..859f4a3 100644 --- a/UnitTest/ElementRendererTest.cpp +++ b/UnitTest/ElementRendererTest.cpp @@ -3,6 +3,7 @@ #include #include "ElementRendererTest.h" #include "Renderer/Painting/ElementStyle.h" +#include using namespace Microsoft::VisualStudio::CppUnitTestFramework; using namespace Renderer; @@ -195,4 +196,5 @@ namespace UnitTest a.exec(); } }; + } diff --git a/UnitTest/UnitTest.cpp b/UnitTest/UnitTest.cpp index a03f793..d24ce02 100644 --- a/UnitTest/UnitTest.cpp +++ b/UnitTest/UnitTest.cpp @@ -3,12 +3,43 @@ #include #include #include +#include +#include "Renderer/Painting/CubicBezier.h" +#include using namespace Microsoft::VisualStudio::CppUnitTestFramework; 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) { public: @@ -31,4 +62,37 @@ namespace UnitTest 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 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> outLines; + line->monotonization(outLines); + for (auto line : outLines) { + qDebug() << line->getRate(); + } + + } + }; + } diff --git a/svg/test.svg b/svg/test.svg new file mode 100644 index 0000000..1424018 --- /dev/null +++ b/svg/test.svg @@ -0,0 +1,6 @@ + + + + \ No newline at end of file