Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Visualization3DTester.hpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file Visualization3DTester.hpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2020 CERN for the benefit of the Acts project
4 //
5 // This Source Code Form is subject to the terms of the Mozilla Public
6 // License, v. 2.0. If a copy of the MPL was not distributed with this
7 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 
9 #pragma once
10 
11 #include <iostream>
12 #include <sstream>
13 #include <string>
14 
15 #include <boost/algorithm/string.hpp>
16 
17 namespace Acts {
18 
19 namespace Test {
20 
39 inline static std::vector<std::string> testObjString(const std::string& tString,
40  bool triMesh = false) {
41  std::vector<std::string> errorStrings;
42  const std::string w = "[ Invalid obj : ";
43 
44  std::vector<std::string> passes = {"#", "usemtl", "mtllib", "o", "g", "s"};
45 
46  auto ss = std::stringstream{tString};
47  for (std::string line; std::getline(ss, line, '\n');) {
48  auto fnbc = line.find_first_not_of(" ", 0);
49  if (fnbc != std::string::npos) {
50  auto snbc = line.find_first_of(" ", fnbc);
51  std::string stag = line.substr(fnbc, snbc - fnbc);
52 
53  // Ignore comment line, usemtl, mtllib
54  bool pass(false);
55  for (const auto& ptag : passes) {
56  if (ptag == stag) {
57  pass = true;
58  break;
59  }
60  }
61  if (pass) {
62  continue;
63  }
64 
65  auto tnbc = line.find_first_not_of(" ", snbc);
66  std::string body = line.substr(tnbc, line.size() - tnbc);
67 
68  // Check if we have triplets
69  if (stag.find("v") != std::string::npos or
70  (stag == std::string("f") and triMesh)) {
71  std::vector<std::string> bodySplit;
72  boost::split(bodySplit, body, boost::is_any_of(" "));
73  if (bodySplit.size() != 3 and stag != std::string("f")) {
74  errorStrings.push_back(w + line + " ] " + stag +
75  " must only have three attributes!");
76  } else if (bodySplit.size() != 3) {
77  errorStrings.push_back("[ not a triangular mesh : " + line + " ]");
78  }
79  continue;
80  }
81  // Check if face and line only have positive integer numbers > 1
82  // or deliminator " ", " /"
83  if (stag == std::string("f") or stag == std::string("l")) {
84  bool onlyDigits =
85  (body.find_first_not_of("0123456789/ ") == std::string::npos);
86  if (!onlyDigits) {
87  errorStrings.push_back(w + line + " ] " + stag +
88  " can only have positive integers!");
89  }
90  std::vector<std::string> bodySplit;
91  boost::split(bodySplit, body, boost::is_any_of(" "));
92  for (auto& bs : bodySplit) {
93  if (bs == "0") {
94  errorStrings.push_back(w + line +
95  " ] vertex with index 0 detected!");
96  }
97  }
98  continue;
99  }
100  errorStrings.push_back(w + line + " ] invalid syntax!");
101  }
102  }
103  return errorStrings;
104 }
105 
107 struct PlyElement {
108  std::string name = "none";
109  size_t copies = 0;
110  int properties = 0; // -1 for list
111 };
112 
123 inline static std::vector<std::string> testPlyString(const std::string& tString,
124  bool triMesh = false) {
125  std::vector<std::string> errorStrings;
126  const std::string w = "[ Invalid ply : ";
127 
128  std::vector<std::string> hPasses = {"format", "comment"};
129 
130  auto ss = std::stringstream{tString};
131  bool inHeader = false;
132 
133  size_t lNumber = 0;
134  size_t cElement = 0;
135  std::vector<PlyElement> elements;
136  PlyElement currentElement;
137 
138  for (std::string line; std::getline(ss, line, '\n'); ++lNumber) {
139  // Check the "ply" statement at the beginning of the file
140  if (lNumber == 0 and line != "ply") {
141  errorStrings.push_back(w + line + " ] first line has to be 'ply");
142  } else if (line == "ply") {
143  inHeader = true;
144  cElement = 0;
145  elements.clear();
146  continue;
147  }
148  // Process the header
149  if (inHeader) {
150  auto fnbc = line.find_first_not_of(" ", 0);
151  if (fnbc != std::string::npos) {
152  auto snbc = line.find_first_of(" ", fnbc);
153  std::string stag = line.substr(fnbc, snbc - fnbc);
154  if (stag == "comment" or stag == "format") {
155  continue;
156  }
157  if (stag == "end_header") {
158  inHeader = false;
159  elements.push_back(currentElement);
160  currentElement = PlyElement();
161  continue;
162  }
163 
164  auto tnbc = line.find_first_not_of(" ", snbc);
165  std::string body = line.substr(tnbc, line.size() - tnbc);
166 
167  auto n0nbc = body.find_first_not_of(" ", 0);
168  auto n1nbc = body.find_first_of(" ", n0nbc);
169  std::string name = body.substr(n0nbc, n1nbc);
170 
171  if (stag == "element") {
172  // new element write the old one
173  if (currentElement.name != "none" and currentElement.copies > 0) {
174  elements.push_back(currentElement);
175  currentElement = PlyElement();
176  }
177  currentElement.name = name;
178  // get the number of copies
179  auto n2nbc = body.find_first_of(" ", n1nbc);
180  std::string copies = body.substr(n1nbc, n2nbc);
181  currentElement.copies = std::stoi(copies);
182  } else if (stag == "property") {
183  if (name == "list") {
184  currentElement.properties = -1;
185  continue;
186  }
187  if (currentElement.properties >= 0) {
188  ++currentElement.properties;
189  }
190  } else {
191  errorStrings.push_back(w + line + " ] Unknown command.");
192  }
193  }
194  } else {
195  if (elements[cElement].copies == 0) {
196  ++cElement;
197  }
198  if (cElement < elements.size()) {
199  elements[cElement].copies -= 1;
200  std::vector<std::string> lineSplit;
201  boost::split(lineSplit, line, boost::is_any_of(" "));
202  if (elements[cElement].properties == -1) {
203  int nprops = std::stoi(lineSplit[0]);
204  if (nprops != (int(lineSplit.size()) - 1)) {
205  errorStrings.push_back(w + line + std::string(" ] List expected ") +
206  std::to_string(nprops) +
207  std::string(" properties, while found ") +
208  std::to_string(lineSplit.size() - 1) +
209  std::string("."));
210  }
211  } else if (lineSplit.size() != size_t(elements[cElement].properties)) {
212  errorStrings.push_back(
213  w + line + std::string(" ] Element expected ") +
214  std::to_string(elements[cElement].properties) +
215  std::string(" properties, while found ") +
216  std::to_string(lineSplit.size()) + std::string("."));
217  }
218  }
219  }
220  }
221 
222  (void)triMesh;
223 
224  return errorStrings;
225 }
226 
227 } // namespace Test
228 
229 } // namespace Acts