#ifndef UTILITIES_H #define UTILITIES_H #include #include #include #include namespace Utilities { inline void parseIntegers(const std::string &str, std::vector &result) { typedef std::regex_iterator re_iterator; typedef re_iterator::value_type re_iterated; std::regex re("(\\d+)"); re_iterator rit(str.begin(), str.end(), re); re_iterator rend; std::transform(rit, rend, std::back_inserter(result), [](const re_iterated &it) { return std::stoi(it[1]); }); } // std::string convertToLowercase(const std::string &s) { // std::string lowercase; // std::transform(s.begin(), s.end(), lowercase.begin(), // [](unsigned char c) { return std::tolower(c); }); // return lowercase; //} // bool hasExtension(const std::string &filename, const std::string &extension) // { // const std::filesystem::path path(filename); // if (!path.has_extension()) { // std::cerr << "Error: No file extension found in " << filename << // std::endl; return false; // } // const std::string detectedExtension = path.extension().string(); // if (convertToLowercase(detectedExtension) != convertToLowercase(extension)) // { // std::cerr << "Error: detected extension is " + detectedExtension + // " and not " + extension // << std::endl; // return false; // } // return true; //} } // namespace Utilities struct NodalForce { size_t index; size_t dof; double magnitude; }; struct Vector6d : public std::array { Vector6d() { for (size_t i = 0; i < 6; i++) { this->operator[](i) = 0; } } Vector6d(const double &d) { for (size_t i = 0; i < 6; i++) { this->operator[](i) = d; } } Vector6d(const std::initializer_list &initList) { std::copy(initList.begin(), initList.end(), this->begin()); } Vector6d operator*(const double &d) const { Vector6d result; for (size_t i = 0; i < 6; i++) { result[i] = this->operator[](i) * d; } return result; } Vector6d operator*(const Vector6d &v) const { Vector6d result; for (size_t i = 0; i < 6; i++) { result[i] = this->operator[](i) * v[i]; } return result; } Vector6d operator/(const double &d) const { Vector6d result; for (size_t i = 0; i < 6; i++) { result[i] = this->operator[](i) / d; } return result; } Vector6d operator+(const Vector6d &v) const { Vector6d result; for (size_t i = 0; i < 6; i++) { result[i] = this->operator[](i) + v[i]; } return result; } Vector6d operator-(const Vector6d &v) const { Vector6d result; for (size_t i = 0; i < 6; i++) { result[i] = this->operator[](i) - v[i]; } return result; } Vector6d inverted() const { Vector6d result; for (size_t i = 0; i < 6; i++) { assert(this->operator[](i) != 0); result[i] = 1 / this->operator[](i); } return result; } bool isZero() const { for (size_t i = 0; i < 6; i++) { if (this->operator[](i) != 0) return false; } return true; } double squaredNorm() const { double squaredNorm = 0; std::for_each(begin(), end(), [&](const double &v) { squaredNorm += pow(v, 2); }); return squaredNorm; } double norm() const { return sqrt(squaredNorm()); } bool isFinite() const { return std::any_of(begin(), end(), [](const double &v) { if (!std::isfinite(v)) { return false; } return true; }); } }; // namespace ConfigurationFile { // inline void getPlyFilename(const std::string jsonFilepath, // std::string &plyFilename) { // std::ifstream inFile(jsonFilepath); // std::string jsonContents((std::istreambuf_iterator(inFile)), // std::istreambuf_iterator()); // nlohmann::json jsonFile(nlohmann::json::parse(jsonContents)); // if (jsonFile.contains("plyFilename")) { // plyFilename = jsonFile["plyFilename"]; // } //} // inline void // getNodalForces(const std::string jsonFilepath, // std::unordered_map &nodalForces) { // std::ifstream inFile(jsonFilepath); // std::string jsonContents((std::istreambuf_iterator(inFile)), // std::istreambuf_iterator()); // nlohmann::json jsonFile(nlohmann::json::parse(jsonContents)); // nodalForces.clear(); // if (jsonFile.contains("forces")) { // std::vector> forces = jsonFile["forces"]; // for (size_t forceIndex = 0; forceIndex < forces.size(); forceIndex++) { // const BeamFormFinder::NodalForce nf{ // static_cast(forces[forceIndex][0]), // static_cast(forces[forceIndex][1]), forces[forceIndex][2]}; // const size_t vertexIndex = forces[forceIndex][0]; // const Eigen::Vector3d forceVector( // forces[forceIndex][1], forces[forceIndex][2], // forces[forceIndex][3]); // assert(forceIndex >= 0 && forceVector.norm() >= 0); // nodalForces[vertexIndex] = forceVector; // } // } //} // inline void getFixedVertices(const std::string jsonFilepath, // std::vector &fixedVertices) { // std::ifstream inFile(jsonFilepath); // std::string jsonContents((std::istreambuf_iterator(inFile)), // std::istreambuf_iterator()); // nlohmann::json jsonFile(nlohmann::json::parse(jsonContents)); // fixedVertices.clear(); // if (jsonFile.contains("fixedVertices")) { // fixedVertices = // static_cast>(jsonFile["fixedVertices"]); // } //} // struct SimulationScenario { // std::string edgeMeshFilename; // std::vector fixedVertices; // std::unordered_map nodalForces; //}; // void to_json(nlohmann::json &json, const SimulationScenario &scenario) { // json["plyFilename"] = scenario.edgeMeshFilename; // if (!scenario.fixedVertices.empty()) { // json["fixedVertices"] = scenario.fixedVertices; // } // if (!scenario.nodalForces.empty()) { // std::vector> forces; // std::transform(scenario.nodalForces.begin(), scenario.nodalForces.end(), // std::back_inserter(forces), // [](const std::pair &f) { // return std::tuple{ // f.first, f.second[0], f.second[1], f.second[2]}; // }); // json["forces"] = forces; // } //} //} // namespace ConfigurationFile #include "polyscope/curve_network.h" #include "polyscope/polyscope.h" inline void initPolyscope() { if (polyscope::state::initialized) { return; } polyscope::init(); polyscope::options::groundPlaneEnabled = false; polyscope::view::upDir = polyscope::view::UpDir::ZUp; } inline void registerWorldAxes() { if (!polyscope::state::initialized) { initPolyscope(); } Eigen::MatrixX3d axesPositions(4, 3); axesPositions.row(0) = Eigen::Vector3d(0, 0, 0); axesPositions.row(1) = Eigen::Vector3d(polyscope::state::lengthScale, 0, 0); axesPositions.row(2) = Eigen::Vector3d(0, polyscope::state::lengthScale, 0); axesPositions.row(3) = Eigen::Vector3d(0, 0, polyscope::state::lengthScale); Eigen::MatrixX2i axesEdges(3, 2); axesEdges.row(0) = Eigen::Vector2i(0, 1); axesEdges.row(1) = Eigen::Vector2i(0, 2); axesEdges.row(2) = Eigen::Vector2i(0, 3); Eigen::MatrixX3d axesColors(3, 3); axesColors.row(0) = Eigen::Vector3d(1, 0, 0); axesColors.row(1) = Eigen::Vector3d(0, 1, 0); axesColors.row(2) = Eigen::Vector3d(0, 0, 1); const std::string worldAxesName = "World Axes"; polyscope::registerCurveNetwork(worldAxesName, axesPositions, axesEdges); polyscope::getCurveNetwork(worldAxesName)->setRadius(0.001); const std::string worldAxesColorName = worldAxesName + " Color"; polyscope::getCurveNetwork(worldAxesName) ->addEdgeColorQuantity(worldAxesColorName, axesColors) ->setEnabled(true); } template void constructInverseMap(const T1 &map, T2 &oppositeMap) { assert(!map.empty()); oppositeMap.clear(); for (const auto &mapIt : map) { oppositeMap[mapIt.second] = mapIt.first; } } #endif // UTILITIES_H