#pragma once #include "real.h" #include "tinynurbs/util/array2.h" #include <QFile> #include <QList> #include <QRegularExpression> #include <QString> #include <array> #include <glm/glm.hpp> #include <iostream> #include <qcontainerfwd.h> #include <tinynurbs/tinynurbs.h> using namespace std; using namespace tinynurbs; class Reader { public: static std::array<tinynurbs::RationalSurface<real>, 2> readSurfaces(const string &surfacesPath) { tinynurbs::RationalSurface<real> s; tinynurbs::RationalSurface<real> f; ifstream fin; fin.open(surfacesPath); string str; string tmp; while (fin.good()) { getline(fin, tmp); str += tmp + "\n"; } // cout << str << endl; auto infos = QString(str.c_str()).split(";"); auto wData = infos[0]; auto srf1Data = infos[1]; auto srf2Data = infos[2]; auto points1 = getPtsFromStr(srf1Data); auto points2 = getPtsFromStr(srf2Data); wData = wData.remove(0, wData.indexOf("Matrix") + 6).trimmed(); wData.remove(0, 3); wData.remove(wData.size() - 3, 3); auto wInfos = wData.split(QRegularExpression("\\]( )*,( )*\\[")); array2<real> weights; vector<real> wArray(points1.cols() * points1.rows()); for (int i = 0; i < points1.cols(); i++) { auto wsInV = wInfos[i].split(QRegularExpression("( )*,( )*")); for (int j = 0; j < points1.rows(); j++) { wArray[i * points1.rows() + j] = real(wsInV[j].toDouble()); } } weights = {points1.cols(), points2.rows(), wArray}; // knot std::vector<real> knot_u(2 * points1.cols(), 1.); for (int i = 0; i < knot_u.size() / 2; i++) knot_u[i] = 0; std::vector<real> knot_v(2 * points1.rows(), 1.); for (int i = 0; i < knot_v.size() / 2; i++) knot_v[i] = 0; s.degree_u = knot_u.size() / 2 - 1; s.degree_v = knot_v.size() / 2 - 1; s.knots_u = knot_u; s.knots_v = knot_v; s.control_points = points1; s.weights = weights; f.degree_u = knot_u.size() / 2 - 1; f.degree_v = knot_v.size() / 2 - 1; f.knots_u = knot_u; f.knots_v = knot_v; f.control_points = points2; f.weights = weights; fin.close(); printCtrPtsAsQuadruples(f); return {s, f}; } static void printCtrPtsAsQuadruples(const Surface<real> &s) { cout << endl; for (int i = 0; i < s.control_points.rows(); i++) { for (int j = 0; j < s.control_points.cols(); j++) { auto pt = s.control_points(i, j); cout << pt.x << ", " << pt.y << ", " << pt.z << ", " << endl; } } cout << s.control_points.rows() * s.control_points.cols() * 4 << endl; } static tinynurbs::RationalSurface<real> readSurface(const QString &path) { QFile file(path); file.open(QIODevice::ReadOnly | QIODevice::Text); QByteArray byteArray = file.readAll(); auto infos = QString(byteArray).split("\n"); auto degreeInfos = infos[0].split(QRegularExpression("( )+")); auto degreeU = degreeInfos[0].toInt(), degreeV = degreeInfos[1].toInt(); auto dimInfos = infos[1].split(QRegularExpression("( )+")); auto dimU = dimInfos[0].toInt(), dimV = dimInfos[1].toInt(); auto knotInfos1 = infos[2].split(QRegularExpression("( )+")); auto knotInfos2 = infos[3].split(QRegularExpression("( )+")); auto knotU = std::vector<float>(knotInfos1.size()); auto knotV = std::vector<float>(knotInfos2.size()); for (int i = 0; i < knotInfos1.size(); i++) { knotU[i] = knotInfos1[i].toFloat(); } for (int i = 0; i < knotInfos2.size(); i++) { knotV[i] = knotInfos2[i].toFloat(); } array2<glm::vec3> points(dimU, dimV); auto pts = infos[4].split(QRegularExpression("( )+")); for (int i = 0; i < dimU; i++) { for (int j = 0; j < dimV; j++) { auto pt_coords = pts[i * dimV + j].split(QRegularExpression(",( )*")); for (int k = 0; k < 3; k++) { points(i, j)[k] = pt_coords[k].toFloat(); } } } tinynurbs::RationalSurface<real> s; s.degree_u = degreeU; s.degree_v = degreeV; s.knots_u = knotU; s.knots_v = knotV; s.control_points = points; s.weights = array2<real>(dimU, dimV, 1.0); file.close(); return s; } private: static array2<glm::vec3> getPtsFromStr(QString srfData) { srfData = srfData.remove(0, srfData.indexOf("Matrix") + 6).trimmed(); // 去掉首尾的括号 srfData.remove(0, 1); srfData.remove(srfData.size() - 1, 1); auto srfInfos = srfData.split("{"); auto srfDimInfos = srfInfos[0].split(QRegularExpression(",( )*")); auto dimU = srfDimInfos[0].toInt(); auto dimV = srfDimInfos[1].toInt(); auto srfPtInfo = srfInfos[1].remove(srfInfos[1].indexOf("}"), 1); auto srfPtsInfos = srfPtInfo.split(QRegularExpression(",( )*\\(")); std::vector<glm::vec3> points(dimU * dimV, glm::vec3()); for (int i = 0; i < srfPtsInfos.size(); i++) { auto pt = srfPtsInfos[i].split("=")[1].trimmed(); // 去掉首尾的方括号 pt.remove(0, 1); pt.remove(pt.size() - 1, 1); // int iu = i / dimU; // int iv = i % dimU; auto coords = pt.split(QRegularExpression(",( )*")); for (int k = 0; k < 3; k++) { real num; if (coords[k].contains("/")) { auto nums = coords[k].split("/"); num = real(nums[0].trimmed().toDouble() / nums[1].trimmed().toDouble()); } else { num = real(coords[k].toDouble()); } if (k == 0) points[i].x = num; else if (k == 1) points[i].y = num; else points[i].z = num; } } array2<glm::vec3> res = {(size_t)dimU, (size_t)dimV, points}; return res; } };