Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:13:03

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
0008 
0009 #pragma once
0010 
0011 #include <iostream>
0012 #include <sstream>
0013 #include <string>
0014 #include <vector>
0015 
0016 #include <boost/algorithm/string.hpp>
0017 
0018 namespace Acts::Test {
0019 
0020 /// This is a test function that tests the validity of an obj stream
0021 /// It tests for special characters that are not allowed to be contained
0022 ///
0023 /// It checks for:
0024 ///
0025 /// * Allowed as tags:
0026 ///    mtllib, usemtl
0027 ///    v, vn, vt, l, f, g, o, s
0028 ///    comment lines (starting with #)
0029 /// * v, vn, vt are checked for 3 entries
0030 /// * f is checked for integer > 0 entries only
0031 /// * f is also check for being a triplet if triMesh is true
0032 /// * l is checked for integer > 0 entries only
0033 ///
0034 /// @param tString is the test string
0035 /// @param triMesh is the test if only triangular surfaces exist
0036 ///
0037 /// @return a vector of failure messages
0038 inline static std::vector<std::string> testObjString(const std::string& tString,
0039                                                      bool triMesh = false) {
0040   std::vector<std::string> errorStrings;
0041   const std::string w = "[ Invalid obj : ";
0042 
0043   std::vector<std::string> passes = {"#", "usemtl", "mtllib", "o", "g", "s"};
0044 
0045   auto ss = std::stringstream{tString};
0046   for (std::string line; std::getline(ss, line, '\n');) {
0047     auto fnbc = line.find_first_not_of(" ", 0);
0048     if (fnbc != std::string::npos) {
0049       auto snbc = line.find_first_of(" ", fnbc);
0050       std::string stag = line.substr(fnbc, snbc - fnbc);
0051 
0052       // Ignore comment line, usemtl, mtllib
0053       bool pass(false);
0054       for (const auto& ptag : passes) {
0055         if (ptag == stag) {
0056           pass = true;
0057           break;
0058         }
0059       }
0060       if (pass) {
0061         continue;
0062       }
0063 
0064       auto tnbc = line.find_first_not_of(" ", snbc);
0065       std::string body = line.substr(tnbc, line.size() - tnbc);
0066 
0067       // Check if we have triplets
0068       if (stag.find("v") != std::string::npos ||
0069           (stag == std::string("f") && triMesh)) {
0070         std::vector<std::string> bodySplit;
0071         boost::split(bodySplit, body, boost::is_any_of(" "));
0072         if (bodySplit.size() != 3 && stag != std::string("f")) {
0073           errorStrings.push_back(w + line + " ] " + stag +
0074                                  " must only have three attributes!");
0075         } else if (bodySplit.size() != 3) {
0076           errorStrings.push_back("[ not a triangular mesh : " + line + " ]");
0077         }
0078         continue;
0079       }
0080       // Check if face and line only have positive integer numbers > 1
0081       // or deliminator " ", " /"
0082       if (stag == std::string("f") || stag == std::string("l")) {
0083         bool onlyDigits =
0084             (body.find_first_not_of("0123456789/ ") == std::string::npos);
0085         if (!onlyDigits) {
0086           errorStrings.push_back(w + line + " ] " + stag +
0087                                  " can only have positive integers!");
0088         }
0089         std::vector<std::string> bodySplit;
0090         boost::split(bodySplit, body, boost::is_any_of(" "));
0091         for (auto& bs : bodySplit) {
0092           if (bs == "0") {
0093             errorStrings.push_back(w + line +
0094                                    " ] vertex with index 0 detected!");
0095           }
0096         }
0097         continue;
0098       }
0099       errorStrings.push_back(w + line + " ] invalid syntax!");
0100     }
0101   }
0102   return errorStrings;
0103 }
0104 
0105 /// Ply element struct
0106 struct PlyElement {
0107   std::string name = "none";
0108   std::size_t copies = 0;
0109   int properties = 0;  // -1 for list
0110 };
0111 
0112 /// This is a test function that tests the validity of an obj stream
0113 /// It tests for special characters that are not allowed to be contained
0114 ///
0115 /// It checks for:
0116 ///
0117 ///
0118 /// @param tString is the test string
0119 /// @param triMesh is the test if only triangular surfaces exist
0120 ///
0121 /// @return a vector of failure messages
0122 inline static std::vector<std::string> testPlyString(const std::string& tString,
0123                                                      bool /*triMesh*/ = false) {
0124   std::vector<std::string> errorStrings;
0125   const std::string w = "[ Invalid ply : ";
0126 
0127   std::vector<std::string> hPasses = {"format", "comment"};
0128 
0129   auto ss = std::stringstream{tString};
0130   bool inHeader = false;
0131 
0132   std::size_t lNumber = 0;
0133   std::size_t cElement = 0;
0134   std::vector<PlyElement> elements;
0135   PlyElement currentElement;
0136 
0137   for (std::string line; std::getline(ss, line, '\n'); ++lNumber) {
0138     // Check the "ply" statement at the beginning of the file
0139     if (lNumber == 0 && line != "ply") {
0140       errorStrings.push_back(w + line + " ] first line has to be 'ply");
0141     } else if (line == "ply") {
0142       inHeader = true;
0143       cElement = 0;
0144       elements.clear();
0145       continue;
0146     }
0147     // Process the header
0148     if (inHeader) {
0149       auto fnbc = line.find_first_not_of(" ", 0);
0150       if (fnbc != std::string::npos) {
0151         auto snbc = line.find_first_of(" ", fnbc);
0152         std::string stag = line.substr(fnbc, snbc - fnbc);
0153         if (stag == "comment" || stag == "format") {
0154           continue;
0155         }
0156         if (stag == "end_header") {
0157           inHeader = false;
0158           elements.push_back(currentElement);
0159           currentElement = PlyElement();
0160           continue;
0161         }
0162 
0163         auto tnbc = line.find_first_not_of(" ", snbc);
0164         std::string body = line.substr(tnbc, line.size() - tnbc);
0165 
0166         auto n0nbc = body.find_first_not_of(" ", 0);
0167         auto n1nbc = body.find_first_of(" ", n0nbc);
0168         std::string name = body.substr(n0nbc, n1nbc);
0169 
0170         if (stag == "element") {
0171           // new element write the old one
0172           if (currentElement.name != "none" && currentElement.copies > 0) {
0173             elements.push_back(currentElement);
0174             currentElement = PlyElement();
0175           }
0176           currentElement.name = name;
0177           // get the number of copies
0178           auto n2nbc = body.find_first_of(" ", n1nbc);
0179           std::string copies = body.substr(n1nbc, n2nbc);
0180           currentElement.copies = std::stoi(copies);
0181         } else if (stag == "property") {
0182           if (name == "list") {
0183             currentElement.properties = -1;
0184             continue;
0185           }
0186           if (currentElement.properties >= 0) {
0187             ++currentElement.properties;
0188           }
0189         } else {
0190           errorStrings.push_back(w + line + " ] Unknown command.");
0191         }
0192       }
0193     } else {
0194       if (elements[cElement].copies == 0) {
0195         ++cElement;
0196       }
0197       if (cElement < elements.size()) {
0198         elements[cElement].copies -= 1;
0199         std::vector<std::string> lineSplit;
0200         boost::split(lineSplit, line, boost::is_any_of(" "));
0201         if (elements[cElement].properties == -1) {
0202           int nprops = std::stoi(lineSplit[0]);
0203           if (nprops != (static_cast<int>(lineSplit.size()) - 1)) {
0204             errorStrings.push_back(w + line + std::string(" ] List expected ") +
0205                                    std::to_string(nprops) +
0206                                    std::string(" properties, while found ") +
0207                                    std::to_string(lineSplit.size() - 1) +
0208                                    std::string("."));
0209           }
0210         } else if (lineSplit.size() !=
0211                    static_cast<std::size_t>(elements[cElement].properties)) {
0212           errorStrings.push_back(
0213               w + line + std::string(" ] Element expected ") +
0214               std::to_string(elements[cElement].properties) +
0215               std::string(" properties, while found ") +
0216               std::to_string(lineSplit.size()) + std::string("."));
0217         }
0218       }
0219     }
0220   }
0221 
0222   return errorStrings;
0223 }
0224 
0225 }  // namespace Acts::Test